r4720 - in dists/trunk: . linux-2.6-git/debian linux-2.6-git/debian/patches-debian linux-2.6-git/debian/patches-debian/series
Frederik Schüler
fschueler-guest at costa.debian.org
Thu Nov 3 17:54:59 UTC 2005
Author: fschueler-guest
Date: 2005-11-03 17:51:59 +0000 (Thu, 03 Nov 2005)
New Revision: 4720
Added:
dists/trunk/linux-2.6-git/
dists/trunk/linux-2.6-git/debian/patches-debian/patch-2.6.14-git5
dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-git-20051103
Removed:
dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-1
dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-2
dists/trunk/linux-2.6/
Modified:
dists/trunk/linux-2.6-git/debian/changelog
Log:
Rename trunk/linux-2.6 to trunk/linux-2.6-git.
Add 2.6.14-git5 patch, without the pruned-drivers bits.
Copied: dists/trunk/linux-2.6-git (from rev 4717, dists/trunk/linux-2.6)
Modified: dists/trunk/linux-2.6-git/debian/changelog
===================================================================
--- dists/trunk/linux-2.6/debian/changelog 2005-11-03 11:39:35 UTC (rev 4717)
+++ dists/trunk/linux-2.6-git/debian/changelog 2005-11-03 17:51:59 UTC (rev 4720)
@@ -1,3 +1,10 @@
+linux-2.6 (2.6.14-git-20051103) UNRELEASED; urgency=low
+
+ [ Frederik Schüler ]
+ * Upgrade to 2.6.14-git5.
+
+ -- Frederik Schüler <fschueler at gmx.net> Thu, 3 Nov 2005 18:25:06 +0100
+
linux-2.6 (2.6.14-3) UNRELEASED; urgency=low
[ Norbert Tretkowski ]
Added: dists/trunk/linux-2.6-git/debian/patches-debian/patch-2.6.14-git5
===================================================================
--- dists/trunk/linux-2.6/debian/patches-debian/patch-2.6.14-git5 2005-11-03 11:39:35 UTC (rev 4717)
+++ dists/trunk/linux-2.6-git/debian/patches-debian/patch-2.6.14-git5 2005-11-03 17:51:59 UTC (rev 4720)
@@ -0,0 +1,536744 @@
+diff --git a/CREDITS b/CREDITS
+--- a/CREDITS
++++ b/CREDITS
+@@ -2247,6 +2247,12 @@ S: 249 Nichols Avenue
+ S: Syracuse, New York 13206
+ S: USA
+
++N: Kyle McMartin
++E: kyle at parisc-linux.org
++D: Linux/PARISC hacker
++D: AD1889 sound driver
++S: Ottawa, Canada
++
+ N: Dirk Melchers
+ E: dirk at merlin.nbg.sub.org
+ D: 8 bit XT hard disk driver for OMTI5520
+diff --git a/Documentation/Changes b/Documentation/Changes
+--- a/Documentation/Changes
++++ b/Documentation/Changes
+@@ -65,7 +65,7 @@ o isdn4k-utils 3.1pre1
+ 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
+--- a/Documentation/DocBook/kernel-api.tmpl
++++ b/Documentation/DocBook/kernel-api.tmpl
+@@ -286,7 +286,9 @@ X!Edrivers/pci/search.c
+ -->
+ !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
+--- a/Documentation/DocBook/libata.tmpl
++++ b/Documentation/DocBook/libata.tmpl
+@@ -415,6 +415,362 @@ and other resources, etc.
+ </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 & 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 & 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 @@ and other resources, etc.
+ !Idrivers/scsi/libata-scsi.c
+ </chapter>
+
++ <chapter id="ataExceptions">
++ <title>ATA errors & 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 && DRDY && !DRQ while trying
++ to issue a command.
++ </para>
++ </listitem>
++
++ <listitem>
++ <para>
++ !BSY && !DRQ during PIO data transfer.
++ </para>
++ </listitem>
++
++ <listitem>
++ <para>
++ DRQ on command completion.
++ </para>
++ </listitem>
++
++ <listitem>
++ <para>
++ !BSY && ERR after CDB tranfer starts but before the
++ last byte of CDB is transferred. ATA/ATAPI standard states
++ that "The device shall not terminate the PACKET command
++ with an error before the last byte of the command packet has
++ been written" 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
++ && ERR during command execution and on completion.
++ </para>
++
++ <para>For ATAPI commands,</para>
++
++ <itemizedlist>
++
++ <listitem>
++ <para>
++ !BSY && ERR && ABRT right after issuing PACKET
++ indicates that PACKET command is not supported and falls in
++ this category.
++ </para>
++ </listitem>
++
++ <listitem>
++ <para>
++ !BSY && ERR(==CHK) && !ABRT after the last
++ byte of CDB is transferred indicates CHECK CONDITION and
++ doesn't fall in this category.
++ </para>
++ </listitem>
++
++ <listitem>
++ <para>
++ !BSY && ERR(==CHK) && 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>
++ <<TODO: fill here>>
++ </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
++ "na" in the output descriptions but upto ATA/ATAPI-7
++ no definition of "na" can be found. However,
++ ATA/ATAPI-8 draft revision 1f describes "N/A" 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 "na" 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
++ && 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>
++ <<TODO: fill here>>
++ </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
+--- 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
+--- a/Documentation/DocBook/writing_usb_driver.tmpl
++++ b/Documentation/DocBook/writing_usb_driver.tmpl
+@@ -345,8 +345,7 @@ if (!retval) {
+ <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
+--- /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/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
+--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
++++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
+@@ -81,7 +81,8 @@ Adding New Machines
+
+ Any large scale modifications, or new drivers should be discussed
+ on the ARM kernel mailing list (linux-arm-kernel) before being
+- attempted.
++ attempted. See http://www.arm.linux.org.uk/mailinglists/ for the
++ mailing list information.
+
+
+ NAND
+@@ -120,6 +121,43 @@ Clock Management
+ various clock units
+
+
++Platform Data
++-------------
++
++ Whenever a device has platform specific data that is specified
++ on a per-machine basis, care should be taken to ensure the
++ following:
++
++ 1) that default data is not left in the device to confuse the
++ driver if a machine does not set it at startup
++
++ 2) the data should (if possible) be marked as __initdata,
++ to ensure that the data is thrown away if the machine is
++ not the one currently in use.
++
++ The best way of doing this is to make a function that
++ kmalloc()s an area of memory, and copies the __initdata
++ and then sets the relevant device's platform data. Making
++ the function `__init` takes care of ensuring it is discarded
++ with the rest of the initialisation code
++
++ static __init void s3c24xx_xxx_set_platdata(struct xxx_data *pd)
++ {
++ struct s3c2410_xxx_mach_info *npd;
++
++ npd = kmalloc(sizeof(struct s3c2410_xxx_mach_info), GFP_KERNEL);
++ if (npd) {
++ memcpy(npd, pd, sizeof(struct s3c2410_xxx_mach_info));
++ s3c_device_xxx.dev.platform_data = npd;
++ } else {
++ printk(KERN_ERR "no memory for xxx platform data\n");
++ }
++ }
++
++ Note, since the code is marked as __init, it should not be
++ exported outside arch/arm/mach-s3c2410/, or exported to
++ modules via EXPORT_SYMBOL() and related functions.
++
+ Port Contributors
+ -----------------
+
+@@ -149,6 +187,7 @@ Document Changes
+ 06 Mar 2005 - BJD - Added Christer Weinigel
+ 08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
+ 08 Mar 2005 - BJD - Added section on adding machines
++ 09 Sep 2005 - BJD - Added section on platform data
+
+ Document Author
+ ---------------
+diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
+--- a/Documentation/block/biodoc.txt
++++ b/Documentation/block/biodoc.txt
+@@ -906,9 +906,20 @@ Aside:
+
+
+ 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 @@ keeping work.
+ 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_may_queue_fn returns true if t
+
+ 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 @@ request in sort order to prevent binary
+ 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 @@ multiple I/O streams are being performed
+ 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 @@ Aside:
+ 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
+--- a/Documentation/cachetlb.txt
++++ b/Documentation/cachetlb.txt
+@@ -49,9 +49,6 @@ changes occur:
+ 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 @@ changes occur:
+ 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 @@ changes occur:
+
+ 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
+--- a/Documentation/cpusets.txt
++++ b/Documentation/cpusets.txt
+@@ -94,7 +94,7 @@ the available CPU and Memory resources a
+ 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
+--- a/Documentation/driver-model/driver.txt
++++ b/Documentation/driver-model/driver.txt
+@@ -14,8 +14,8 @@ struct device_driver {
+ 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 @@ device; i.e. anything in the device's dr
+ 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_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.
+-
+-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.
++suspend is called to put the device in a low power state.
++
++ int (*resume) (struct device * dev);
++
++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
+--- a/Documentation/driver-model/porting.txt
++++ b/Documentation/driver-model/porting.txt
+@@ -350,7 +350,7 @@ When a driver is registered, the bus's l
+ 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/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
+--- a/Documentation/filesystems/ntfs.txt
++++ b/Documentation/filesystems/ntfs.txt
+@@ -50,9 +50,14 @@ userspace utilities, etc.
+ Features
+ ========
+
+-- This is a complete rewrite of the NTFS driver that used to be in the kernel.
+- This new driver implements NTFS read support and is functionally equivalent
+- to the old ntfs driver.
++- This is a complete rewrite of the NTFS driver that used to be in the 2.4 and
++ earlier kernels. This new driver implements NTFS read support and is
++ functionally equivalent to the old ntfs driver and it also implements limited
++ write support. The biggest limitation at present is that files/directories
++ cannot be created or deleted. See below for the list of write features that
++ are so far supported. Another limitation is that writing to compressed files
++ is not implemented at all. Also, neither read nor write access to encrypted
++ files is so far implemented.
+ - The new driver has full support for sparse files on NTFS 3.x volumes which
+ the old driver isn't happy with.
+ - The new driver supports execution of binaries due to mmap() now being
+@@ -78,7 +83,20 @@ Features
+ - The new driver supports fsync(2), fdatasync(2), and msync(2).
+ - The new driver supports readv(2) and writev(2).
+ - The new driver supports access time updates (including mtime and ctime).
+-
++- The new driver supports truncate(2) and open(2) with O_TRUNC. But at present
++ only very limited support for highly fragmented files, i.e. ones which have
++ their data attribute split across multiple extents, is included. Another
++ limitation is that at present truncate(2) will never create sparse files,
++ since to mark a file sparse we need to modify the directory entry for the
++ file and we do not implement directory modifications yet.
++- The new driver supports write(2) which can both overwrite existing data and
++ extend the file size so that you can write beyond the existing data. Also,
++ writing into sparse regions is supported and the holes are filled in with
++ clusters. But at present only limited support for highly fragmented files,
++ i.e. ones which have their data attribute split across multiple extents, is
++ included. Another limitation is that write(2) will never create sparse
++ files, since to mark a file sparse we need to modify the directory entry for
++ the file and we do not implement directory modifications yet.
+
+ Supported mount options
+ =======================
+@@ -439,6 +457,22 @@ ChangeLog
+
+ Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
+
++2.1.25:
++ - Write support is now extended with write(2) being able to both
++ overwrite existing file data and to extend files. Also, if a write
++ to a sparse region occurs, write(2) will fill in the hole. Note,
++ mmap(2) based writes still do not support writing into holes or
++ writing beyond the initialized size.
++ - Write support has a new feature and that is that truncate(2) and
++ open(2) with O_TRUNC are now implemented thus files can be both made
++ smaller and larger.
++ - Note: Both write(2) and truncate(2)/open(2) with O_TRUNC still have
++ limitations in that they
++ - only provide limited support for highly fragmented files.
++ - only work on regular, i.e. uncompressed and unencrypted files.
++ - never create sparse files although this will change once directory
++ operations are implemented.
++ - Lots of bug fixes and enhancements across the board.
+ 2.1.24:
+ - Support journals ($LogFile) which have been modified by chkdsk. This
+ means users can boot into Windows after we marked the volume dirty.
+diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
+--- 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
+--- 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
+--- a/Documentation/hwmon/it87
++++ b/Documentation/hwmon/it87
+@@ -4,18 +4,18 @@ Kernel driver it87
+ 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 at 0-in.com>
+diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
+--- a/Documentation/hwmon/lm90
++++ b/Documentation/hwmon/lm90
+@@ -24,14 +24,14 @@ Supported chips:
+ 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 @@ increased resolution of the remote tempe
+
+ 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 @@ ADM1032:
+ * 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 @@ The lm90 driver will not update its valu
+ 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
+--- a/Documentation/hwmon/smsc47b397
++++ b/Documentation/hwmon/smsc47b397
+@@ -3,6 +3,7 @@ Kernel driver smsc47b397
+
+ 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 @@ Authors: Mark M. Hoffman <mhoffman at light
+
+ 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 at 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 @@ OUT DX,AL
+ 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
+--- a/Documentation/hwmon/smsc47m1
++++ b/Documentation/hwmon/smsc47m1
+@@ -12,6 +12,10 @@ Supported chips:
+ 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 at yahoo.com>,
+@@ -30,6 +34,9 @@ The 47M15x and 47M192 chips contain a fu
+ 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
+--- a/Documentation/hwmon/sysfs-interface
++++ b/Documentation/hwmon/sysfs-interface
+@@ -272,3 +272,6 @@ beep_mask Bitmask for beep.
+
+ 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
+--- a/Documentation/hwmon/via686a
++++ b/Documentation/hwmon/via686a
+@@ -18,8 +18,9 @@ Authors:
+ 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 @@ miss once-only alarms.
+
+ 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
+--- a/Documentation/i2c/busses/i2c-i810
++++ b/Documentation/i2c/busses/i2c-i810
+@@ -2,6 +2,7 @@ Kernel driver i2c-i810
+
+ Supported adapters:
+ * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
++ * Intel 82845G (GMCH)
+
+ Authors:
+ Frodo Looijaard <frodol at dds.nl>,
+diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro
+--- a/Documentation/i2c/busses/i2c-viapro
++++ b/Documentation/i2c/busses/i2c-viapro
+@@ -4,17 +4,18 @@ Supported adapters:
+ * 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 at dds.nl>,
+- Philip Edelbrock <phil at netroedge.com>,
+- Kyösti Mälkki <kmalkki at cc.hut.fi>,
+- Mark D. Studebaker <mdsxyz123 at yahoo.com>
++ Frodo Looijaard <frodol at dds.nl>,
++ Philip Edelbrock <phil at netroedge.com>,
++ Kyösti Mälkki <kmalkki at cc.hut.fi>,
++ Mark D. Studebaker <mdsxyz123 at yahoo.com>,
++ Jean Delvare <khali at linux-fr.org>
+
+ Module Parameters
+ -----------------
+@@ -28,20 +29,22 @@ Description
+ -----------
+
+ 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
+--- /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 at tampabay.rr.com>,
++ Alessandro Zummo <a.zummo at 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
+--- a/Documentation/i2c/functionality
++++ b/Documentation/i2c/functionality
+@@ -17,9 +17,10 @@ For the most up-to-date list of function
+ 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
+--- a/Documentation/i2c/porting-clients
++++ b/Documentation/i2c/porting-clients
+@@ -82,7 +82,7 @@ Technical changes:
+ 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
+--- a/Documentation/i2c/writing-clients
++++ b/Documentation/i2c/writing-clients
+@@ -33,8 +33,8 @@ static struct i2c_driver foo_driver = {
+ .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 @@ This is almost always what you want.
+ 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 @@ be very useful.
+ 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 @@ For now, you can ignore the `flags' para
+ 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 @@ For now, you can ignore the `flags' para
+ 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 @@ much simpler than the attachment code, f
+ 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 @@ SMBus communication
+ 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
+--- a/Documentation/input/yealink.txt
++++ b/Documentation/input/yealink.txt
+@@ -2,7 +2,6 @@ Driver documentation for yealink usb-p1k
+
+ 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 @@ For vendor documentation see http://www.
+
+ 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 @@ the Makefile is pointing to the location
+ 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
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -1460,8 +1460,6 @@ running once the system is up.
+ 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 @@ running once the system is up.
+ 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
+--- a/Documentation/keys.txt
++++ b/Documentation/keys.txt
+@@ -196,7 +196,7 @@ KEY ACCESS PERMISSIONS
+
+ 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 @@ five of each set of eight bits are defin
+ 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 @@ about the status of the key service:
+ 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
+--- a/Documentation/m68k/kernel-options.txt
++++ b/Documentation/m68k/kernel-options.txt
+@@ -626,7 +626,7 @@ ignored (others aren't affected).
+ 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 @@ correctly.
+ 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
+--- /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 at amd.com>
++
++Happy hacking!
++Enrico Walther <enrico.walther at amd.com>
+diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
+--- a/Documentation/networking/bonding.txt
++++ b/Documentation/networking/bonding.txt
+@@ -777,7 +777,7 @@ doing so is the same as described in the
+ 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 @@ the above does not work, and the second
+ 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
+--- a/Documentation/networking/ip-sysctl.txt
++++ b/Documentation/networking/ip-sysctl.txt
+@@ -309,7 +309,7 @@ tcp_tso_win_divisor - INTEGER
+ 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/Documentation/serial/driver b/Documentation/serial/driver
+--- a/Documentation/serial/driver
++++ b/Documentation/serial/driver
+@@ -116,12 +116,15 @@ hardware.
+ line becoming inactive or the tty layer indicating we want
+ to stop transmission due to an XOFF character.
+
++ The driver should stop transmitting characters as soon as
++ possible.
++
+ Locking: port->lock taken.
+ Interrupts: locally disabled.
+ This call must not sleep
+
+ start_tx(port)
+- start transmitting characters.
++ Start transmitting characters.
+
+ Locking: port->lock taken.
+ Interrupts: locally disabled.
+@@ -281,26 +284,31 @@ hardware.
+ Other functions
+ ---------------
+
+-uart_update_timeout(port,cflag,quot)
++uart_update_timeout(port,cflag,baud)
+ Update the FIFO drain timeout, port->timeout, according to the
+- number of bits, parity, stop bits and quotient.
++ number of bits, parity, stop bits and baud rate.
+
+ Locking: caller is expected to take port->lock
+ Interrupts: n/a
+
+-uart_get_baud_rate(port,termios)
++uart_get_baud_rate(port,termios,old,min,max)
+ Return the numeric baud rate for the specified termios, taking
+ account of the special 38400 baud "kludge". The B0 baud rate
+ is mapped to 9600 baud.
+
++ If the baud rate is not within min..max, then if old is non-NULL,
++ the original baud rate will be tried. If that exceeds the
++ min..max constraint, 9600 baud will be returned. termios will
++ be updated to the baud rate in use.
++
++ Note: min..max must always allow 9600 baud to be selected.
++
+ Locking: caller dependent.
+ Interrupts: n/a
+
+-uart_get_divisor(port,termios,oldtermios)
+- Return the divsor (baud_base / baud) for the selected baud rate
+- specified by termios. If the baud rate is out of range, try
+- the original baud rate specified by oldtermios (if non-NULL).
+- If that fails, try 9600 baud.
++uart_get_divisor(port,baud)
++ Return the divsor (baud_base / baud) for the specified baud
++ rate, appropriately rounded.
+
+ If 38400 baud and custom divisor is selected, return the
+ custom divisor instead.
+@@ -308,6 +316,46 @@ uart_get_divisor(port,termios,oldtermios
+ Locking: caller dependent.
+ Interrupts: n/a
+
++uart_match_port(port1,port2)
++ This utility function can be used to determine whether two
++ uart_port structures describe the same port.
++
++ Locking: n/a
++ Interrupts: n/a
++
++uart_write_wakeup(port)
++ A driver is expected to call this function when the number of
++ characters in the transmit buffer have dropped below a threshold.
++
++ Locking: port->lock should be held.
++ Interrupts: n/a
++
++uart_register_driver(drv)
++ Register a uart driver with the core driver. We in turn register
++ with the tty layer, and initialise the core driver per-port state.
++
++ drv->port should be NULL, and the per-port structures should be
++ registered using uart_add_one_port after this call has succeeded.
++
++ Locking: none
++ Interrupts: enabled
++
++uart_unregister_driver()
++ Remove all references to a driver from the core driver. The low
++ level driver must have removed all its ports via the
++ uart_remove_one_port() if it registered them with uart_add_one_port().
++
++ Locking: none
++ Interrupts: enabled
++
++uart_suspend_port()
++
++uart_resume_port()
++
++uart_add_one_port()
++
++uart_remove_one_port()
++
+ Other notes
+ -----------
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -116,12 +116,6 @@ M: ajk at iehk.rwth-aachen.de
+ L: linux-hams at vger.kernel.org
+ S: Maintained
+
+-YEALINK PHONE DRIVER
+-P: Henk Vergonet
+-M: Henk.Vergonet at gmail.com
+-L: usbb2k-api-dev at nongnu.org
+-S: Maintained
+-
+ 8139CP 10/100 FAST ETHERNET DRIVER
+ P: Jeff Garzik
+ M: jgarzik at pobox.com
+@@ -197,6 +191,15 @@ M: Thorsten Knabe <linux at thorsten-knabe.
+ W: http://linux.thorsten-knabe.de
+ S: Maintained
+
++AD1889 SOUND DRIVER
++P: Kyle McMartin
++M: kyle at parisc-linux.org
++P: Thibaut Varene
++M: T-Bone at parisc-linux.org
++W: http://wiki.parisc-linux.org/AD1889
++L: parisc-linux at lists.parisc-linux.org
++S: Maintained
++
+ ADM1025 HARDWARE MONITOR DRIVER
+ P: Jean Delvare
+ M: khali at linux-fr.org
+@@ -1640,7 +1643,7 @@ S: Maintained
+ MIPS
+ P: Ralf Baechle
+ M: ralf at linux-mips.org
+-W: http://oss.sgi.com/mips/mips-howto.html
++W: http://www.linux-mips.org/
+ L: linux-mips at linux-mips.org
+ S: Maintained
+
+@@ -1942,6 +1945,14 @@ M: george at mvista.com
+ L: netdev at vger.kernel.org
+ S: Supported
+
++POWERPC 4xx EMAC DRIVER
++P: Eugene Surovegin
++M: ebs at ebshome.net
++W: http://kernel.ebshome.net/emac/
++L: linuxppc-embedded at ozlabs.org
++L: netdev at vger.kernel.org
++S: Maintained
++
+ PNP SUPPORT
+ P: Adam Belay
+ M: ambx1 at neo.rr.com
+@@ -2275,6 +2286,11 @@ W: http://tpmdd.sourceforge.net
+ L: tpmdd-devel at lists.sourceforge.net
+ S: Maintained
+
++Telecom Clock Driver for MCPL0010
++P: Mark Gross
++M: mark.gross at intel.com
++S: Supported
++
+ TENSILICA XTENSA PORT (xtensa):
+ P: Chris Zankel
+ M: chris at zankel.net
+@@ -2486,14 +2502,6 @@ L: linux-kernel at vger.kernel.org
+ L: linux-usb-devel at lists.sourceforge.net
+ S: Supported
+
+-USB BLUETOOTH TTY CONVERTER DRIVER
+-P: Greg Kroah-Hartman
+-M: greg at kroah.com
+-L: linux-usb-users at lists.sourceforge.net
+-L: linux-usb-devel at lists.sourceforge.net
+-S: Maintained
+-W: http://www.kroah.com/linux-usb/
+-
+ USB CDC ETHERNET DRIVER
+ P: Greg Kroah-Hartman
+ M: greg at kroah.com
+@@ -2727,6 +2735,12 @@ P: Roger Luethi
+ M: rl at hellgate.ch
+ S: Maintained
+
++VIAPRO SMBUS DRIVER
++P: Jean Delvare
++M: khali at linux-fr.org
++L: lm-sensors at lm-sensors.org
++S: Maintained
++
+ UCLINUX (AND M68KNOMMU)
+ P: Greg Ungerer
+ M: gerg at uclinux.org
+@@ -2848,6 +2862,12 @@ M: jpr at f6fbb.org
+ L: linux-hams at vger.kernel.org
+ S: Maintained
+
++YEALINK PHONE DRIVER
++P: Henk Vergonet
++M: Henk.Vergonet at gmail.com
++L: usbb2k-api-dev at nongnu.org
++S: Maintained
++
+ YMFPCI YAMAHA PCI SOUND (Use ALSA instead)
+ P: Pete Zaitcev
+ M: zaitcev at yahoo.com
+diff --git a/Makefile b/Makefile
+--- a/Makefile
++++ b/Makefile
+@@ -334,7 +334,7 @@ KALLSYMS = scripts/kallsyms
+ 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 @@ export MODVERDIR := $(if $(KBUILD_EXTMOD
+
+ # 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
+--- a/README
++++ b/README
+@@ -54,6 +54,10 @@ INSTALLING the kernel:
+
+ 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
+--- a/arch/alpha/kernel/pci-noop.c
++++ b/arch/alpha/kernel/pci-noop.c
+@@ -154,7 +154,7 @@ pci_dma_supported(struct pci_dev *hwdev,
+
+ 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
+--- a/arch/alpha/kernel/pci_iommu.c
++++ b/arch/alpha/kernel/pci_iommu.c
+@@ -397,7 +397,7 @@ pci_alloc_consistent(struct pci_dev *pde
+ {
+ 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
+--- 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
+--- a/arch/alpha/mm/numa.c
++++ b/arch/alpha/mm/numa.c
+@@ -371,6 +371,8 @@ show_mem(void)
+ 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 @@ show_mem(void)
+ 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
+--- 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 @@ remap_area_pte(pte_t * pte, unsigned lon
+ } 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 @@ remap_area_pmd(pmd_t * pmd, unsigned lon
+ 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 @@ __alpha_remap_area_pages(unsigned long a
+ 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 @@ __alpha_remap_area_pages(unsigned long a
+ 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
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -194,6 +194,13 @@ config ARCH_VERSATILE
+ help
+ This enables support for ARM Ltd Versatile board.
+
++config ARCH_REALVIEW
++ bool "RealView"
++ select ARM_AMBA
++ select ICST307
++ help
++ This enables support for ARM Ltd RealView boards.
++
+ config ARCH_IMX
+ bool "IMX"
+
+@@ -204,6 +211,7 @@ config ARCH_H720X
+
+ config ARCH_AAEC2000
+ bool "Agilent AAEC-2000 based"
++ select ARM_AMBA
+ help
+ This enables support for systems based on the Agilent AAEC-2000
+
+@@ -243,6 +251,8 @@ source "arch/arm/mach-versatile/Kconfig"
+
+ source "arch/arm/mach-aaec2000/Kconfig"
+
++source "arch/arm/mach-realview/Kconfig"
++
+ # Definitions to make life easier
+ config ARCH_ACORN
+ bool
+@@ -687,7 +697,8 @@ source "drivers/acorn/block/Kconfig"
+
+ 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
+--- 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
+@@ -99,6 +99,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0x
+ machine-$(CONFIG_ARCH_IMX) := imx
+ machine-$(CONFIG_ARCH_H720X) := h720x
+ machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
++ machine-$(CONFIG_ARCH_REALVIEW) := realview
+
+ ifeq ($(CONFIG_ARCH_EBSA110),y)
+ # This is what happens if you forget the IOCS16 line.
+@@ -108,27 +109,19 @@ export CFLAGS_3c589_cs.o
+ 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
+--- 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
+--- a/arch/arm/boot/compressed/misc.c
++++ b/arch/arm/boot/compressed/misc.c
+@@ -30,7 +30,7 @@ unsigned int __machine_arch_type;
+ #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
+--- 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
+--- 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 @@ struct safe_buffer {
+ 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 @@ static void print_alloc_stats(struct dma
+ 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 @@ find_dmabounce_dev(struct device *dev)
+ /* 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 @@ alloc_safe_buffer(struct dmabounce_devic
+ 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);
+-
+- 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);
++ buf->ptr = ptr;
++ buf->size = size;
++ buf->direction = dir;
++ buf->pool = pool;
+
+- 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 @@ free_safe_buffer(struct dmabounce_device
+ 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 @@ free_safe_buffer(struct dmabounce_device
+ /* ************************************************** */
+
+ #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 @@ map_single(struct device *dev, void *ptr
+ __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 @@ unmap_single(struct device *dev, dma_add
+ /*
+ * 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 @@ dma_sync_sg_for_device(struct device *de
+ 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 @@ dmabounce_register_dev(struct device *de
+ 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 @@ dmabounce_register_dev(struct device *de
+ 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 @@ dmabounce_unregister_dev(struct device *
+ 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
+--- a/arch/arm/common/locomo.c
++++ b/arch/arm/common/locomo.c
+@@ -22,7 +22,7 @@
+ #include <linux/delay.h>
+ #include <linux/errno.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+
+@@ -550,15 +550,12 @@ struct locomo_save_data {
+ 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 @@ static int locomo_suspend(struct device
+ 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
+--- a/arch/arm/common/sa1111.c
++++ b/arch/arm/common/sa1111.c
+@@ -22,7 +22,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/errno.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/dma-mapping.h>
+@@ -801,7 +801,7 @@ struct sa1111_save_data {
+
+ #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 @@ static int sa1111_suspend(struct device
+ 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 @@ static int sa1111_suspend(struct device
+ /*
+ * 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
+--- a/arch/arm/common/scoop.c
++++ b/arch/arm/common/scoop.c
+@@ -12,6 +12,8 @@
+ */
+
+ #include <linux/device.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
+ #include <asm/io.h>
+ #include <asm/hardware/scoop.h>
+
+@@ -102,26 +104,24 @@ static void check_scoop_reg(struct scoop
+ }
+
+ #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
+--- a/arch/arm/configs/ixdp2400_defconfig
++++ b/arch/arm/configs/ixdp2400_defconfig
+@@ -559,7 +559,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ #
+ 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
+--- a/arch/arm/configs/ixdp2800_defconfig
++++ b/arch/arm/configs/ixdp2800_defconfig
+@@ -559,7 +559,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ #
+ 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/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
+--- a/arch/arm/configs/ixp4xx_defconfig
++++ b/arch/arm/configs/ixp4xx_defconfig
+@@ -104,7 +104,7 @@ CONFIG_ARCH_IXCDP1100=y
+ CONFIG_ARCH_PRPMC1100=y
+ CONFIG_ARCH_IXDP4XX=y
+ CONFIG_CPU_IXP46X=y
+-CONFIG_MACH_GTWX5715=y
++# CONFIG_MACH_GTWX5715 is not set
+
+ #
+ # IXP4xx Options
+diff --git a/arch/arm/configs/mp1000_defconfig b/arch/arm/configs/mp1000_defconfig
+new file mode 100644
+--- /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
+--- 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
+--- 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
+--- a/arch/arm/kernel/asm-offsets.c
++++ b/arch/arm/kernel/asm-offsets.c
+@@ -94,7 +94,6 @@ int main(void)
+ 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
+--- 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 @@ __pabt_svc:
+
+ #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
+--- 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
+-#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
++#ifdef CONFIG_XIP_KERNEL
++#define TEXTADDR XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
++#else
++#define TEXTADDR KERNEL_RAM_ADDR
+ #endif
+
+ /*
+@@ -279,7 +256,7 @@ __turn_mmu_on:
+ .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 @@ __create_page_tables:
+ /*
+ * 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
+--- 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
+--- a/arch/arm/kernel/ptrace.c
++++ b/arch/arm/kernel/ptrace.c
+@@ -782,7 +782,7 @@ static int do_ptrace(int request, struct
+ 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
+--- a/arch/arm/kernel/signal.c
++++ b/arch/arm/kernel/signal.c
+@@ -139,93 +139,33 @@ struct iwmmxt_sigframe {
+ 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
+--- 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
+--- a/arch/arm/kernel/traps.c
++++ b/arch/arm/kernel/traps.c
+@@ -198,25 +198,16 @@ void show_stack(struct task_struct *tsk,
+ 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 @@ NORET_TYPE void die(const char *str, str
+ 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 @@ static int bad_syscall(int n, struct pt_
+ 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 @@ asmlinkage int arm_syscall(int no, struc
+ 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
+--- 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 @@ SECTIONS
+
+ #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
+--- a/arch/arm/lib/Makefile
++++ b/arch/arm/lib/Makefile
+@@ -7,13 +7,27 @@
+ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
+ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
+ copy_page.o delay.o findbit.o memchr.o memcpy.o \
+- memset.o memzero.o setbit.o strncpy_from_user.o \
+- 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 \
++ memmove.o memset.o memzero.o setbit.o \
++ strncpy_from_user.o strnlen_user.o \
++ strchr.o strrchr.o \
++ testchangebit.o testclearbit.o testsetbit.o \
++ getuser.o putuser.o clear_user.o \
++ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
++ ucmpdi2.o lib1funcs.o div64.o sha1.o \
+ io-readsb.o io-writesb.o io-readsl.o io-writesl.o
+
++# the code in uaccess.S is not preemption safe and
++# probably faster on ARMv3 only
++ifeq ($CONFIG_PREEMPT,y)
++ lib-y += copy_from_user.o copy_to_user.o
++else
++ifneq ($(CONFIG_CPU_32v3),y)
++ lib-y += copy_from_user.o copy_to_user.o
++else
++ lib-y += uaccess.o
++endif
++endif
++
+ ifeq ($(CONFIG_CPU_32v3),y)
+ lib-y += io-readsw-armv3.o io-writesw-armv3.o
+ else
+diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S
+new file mode 100644
+--- /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
+--- 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
+--- /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
+--- 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/clear_user.S b/arch/arm/lib/clear_user.S
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/lib/clear_user.S
+@@ -0,0 +1,52 @@
++/*
++ * linux/arch/arm/lib/clear_user.S
++ *
++ * Copyright (C) 1995, 1996,1997,1998 Russell King
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++
++ .text
++
++/* Prototype: int __arch_clear_user(void *addr, size_t sz)
++ * Purpose : clear some user memory
++ * Params : addr - user memory address to clear
++ * : sz - number of bytes to clear
++ * Returns : number of bytes NOT cleared
++ */
++ENTRY(__arch_clear_user)
++ stmfd sp!, {r1, lr}
++ mov r2, #0
++ cmp r1, #4
++ blt 2f
++ ands ip, r0, #3
++ beq 1f
++ cmp ip, #2
++USER( strbt r2, [r0], #1)
++USER( strlebt r2, [r0], #1)
++USER( strltbt r2, [r0], #1)
++ rsb ip, ip, #4
++ sub r1, r1, ip @ 7 6 5 4 3 2 1
++1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
++USER( strplt r2, [r0], #4)
++USER( strplt r2, [r0], #4)
++ bpl 1b
++ adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
++USER( strplt r2, [r0], #4)
++2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
++USER( strnebt r2, [r0], #1)
++USER( strnebt r2, [r0], #1)
++ tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
++USER( strnebt r2, [r0], #1)
++ mov r0, #0
++ LOADREGS(fd,sp!, {r1, pc})
++
++ .section .fixup,"ax"
++ .align 0
++9001: LOADREGS(fd,sp!, {r0, pc})
++ .previous
++
+diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/lib/copy_from_user.S
+@@ -0,0 +1,101 @@
++/*
++ * linux/arch/arm/lib/copy_from_user.S
++ *
++ * Author: Nicolas Pitre
++ * Created: Sep 29, 2005
++ * Copyright: MontaVista Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++
++/*
++ * Prototype:
++ *
++ * size_t __arch_copy_from_user(void *to, const void *from, size_t n)
++ *
++ * Purpose:
++ *
++ * copy a block to kernel memory from user memory
++ *
++ * Params:
++ *
++ * to = kernel memory
++ * from = user memory
++ * n = number of bytes to copy
++ *
++ * Return value:
++ *
++ * Number of bytes NOT copied.
++ */
++
++ .macro ldr1w ptr reg abort
++100: ldrt \reg, [\ptr], #4
++ .section __ex_table, "a"
++ .long 100b, \abort
++ .previous
++ .endm
++
++ .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
++ ldr1w \ptr, \reg1, \abort
++ ldr1w \ptr, \reg2, \abort
++ ldr1w \ptr, \reg3, \abort
++ ldr1w \ptr, \reg4, \abort
++ .endm
++
++ .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ ldr4w \ptr, \reg1, \reg2, \reg3, \reg4, \abort
++ ldr4w \ptr, \reg5, \reg6, \reg7, \reg8, \abort
++ .endm
++
++ .macro ldr1b ptr reg cond=al abort
++100: ldr\cond\()bt \reg, [\ptr], #1
++ .section __ex_table, "a"
++ .long 100b, \abort
++ .previous
++ .endm
++
++ .macro str1w ptr reg abort
++ str \reg, [\ptr], #4
++ .endm
++
++ .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
++ .endm
++
++ .macro str1b ptr reg cond=al abort
++ str\cond\()b \reg, [\ptr], #1
++ .endm
++
++ .macro enter reg1 reg2
++ mov r3, #0
++ stmdb sp!, {r0, r2, r3, \reg1, \reg2}
++ .endm
++
++ .macro exit reg1 reg2
++ add sp, sp, #8
++ ldmfd sp!, {r0, \reg1, \reg2}
++ .endm
++
++ .text
++
++ENTRY(__arch_copy_from_user)
++
++#include "copy_template.S"
++
++ .section .fixup,"ax"
++ .align 0
++ copy_abort_preamble
++ ldmfd sp!, {r1, r2}
++ sub r3, r0, r1
++ rsb r1, r3, r2
++ str r1, [sp]
++ bl __memzero
++ ldr r0, [sp], #4
++ copy_abort_end
++ .previous
++
+diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/lib/copy_template.S
+@@ -0,0 +1,255 @@
++/*
++ * linux/arch/arm/lib/copy_template.s
++ *
++ * Code template for optimized memory copy functions
++ *
++ * Author: Nicolas Pitre
++ * Created: Sep 28, 2005
++ * Copyright: MontaVista Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/*
++ * This can be used to enable code to cacheline align the source pointer.
++ * Experiments on tested architectures (StrongARM and XScale) didn't show
++ * this a worthwhile thing to do. That might be different in the future.
++ */
++//#define CALGN(code...) code
++#define CALGN(code...)
++
++/*
++ * Theory of operation
++ * -------------------
++ *
++ * This file provides the core code for a forward memory copy used in
++ * the implementation of memcopy(), copy_to_user() and copy_from_user().
++ *
++ * The including file must define the following accessor macros
++ * according to the need of the given function:
++ *
++ * ldr1w ptr reg abort
++ *
++ * This loads one word from 'ptr', stores it in 'reg' and increments
++ * 'ptr' to the next word. The 'abort' argument is used for fixup tables.
++ *
++ * ldr4w ptr reg1 reg2 reg3 reg4 abort
++ * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ *
++ * This loads four or eight words starting from 'ptr', stores them
++ * in provided registers and increments 'ptr' past those words.
++ * The'abort' argument is used for fixup tables.
++ *
++ * ldr1b ptr reg cond abort
++ *
++ * Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
++ * It also must apply the condition code if provided, otherwise the
++ * "al" condition is assumed by default.
++ *
++ * str1w ptr reg abort
++ * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ * str1b ptr reg cond abort
++ *
++ * Same as their ldr* counterparts, but data is stored to 'ptr' location
++ * rather than being loaded.
++ *
++ * enter reg1 reg2
++ *
++ * Preserve the provided registers on the stack plus any additional
++ * data as needed by the implementation including this code. Called
++ * upon code entry.
++ *
++ * exit reg1 reg2
++ *
++ * Restore registers with the values previously saved with the
++ * 'preserv' macro. Called upon code termination.
++ */
++
++
++ enter r4, lr
++
++ subs r2, r2, #4
++ blt 8f
++ ands ip, r0, #3
++ PLD( pld [r1, #0] )
++ bne 9f
++ ands ip, r1, #3
++ bne 10f
++
++1: subs r2, r2, #(28)
++ stmfd sp!, {r5 - r8}
++ blt 5f
++
++ CALGN( ands ip, r1, #31 )
++ CALGN( rsb r3, ip, #32 )
++ CALGN( sbcnes r4, r3, r2 ) @ C is always set here
++ CALGN( bcs 2f )
++ CALGN( adr r4, 6f )
++ CALGN( subs r2, r2, r3 ) @ C gets set
++ CALGN( add pc, r4, ip )
++
++ PLD( pld [r1, #0] )
++2: PLD( subs r2, r2, #96 )
++ PLD( pld [r1, #28] )
++ PLD( blt 4f )
++ PLD( pld [r1, #60] )
++ PLD( pld [r1, #92] )
++
++3: PLD( pld [r1, #124] )
++4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
++ subs r2, r2, #32
++ str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
++ bge 3b
++ PLD( cmn r2, #96 )
++ PLD( bge 4b )
++
++5: ands ip, r2, #28
++ rsb ip, ip, #32
++ addne pc, pc, ip @ C is always clear here
++ b 7f
++6: nop
++ ldr1w r1, r3, abort=20f
++ ldr1w r1, r4, abort=20f
++ ldr1w r1, r5, abort=20f
++ ldr1w r1, r6, abort=20f
++ ldr1w r1, r7, abort=20f
++ ldr1w r1, r8, abort=20f
++ ldr1w r1, lr, abort=20f
++
++ add pc, pc, ip
++ nop
++ nop
++ str1w r0, r3, abort=20f
++ str1w r0, r4, abort=20f
++ str1w r0, r5, abort=20f
++ str1w r0, r6, abort=20f
++ str1w r0, r7, abort=20f
++ str1w r0, r8, abort=20f
++ str1w r0, lr, abort=20f
++
++ CALGN( bcs 2b )
++
++7: ldmfd sp!, {r5 - r8}
++
++8: movs r2, r2, lsl #31
++ ldr1b r1, r3, ne, abort=21f
++ ldr1b r1, r4, cs, abort=21f
++ ldr1b r1, ip, cs, abort=21f
++ str1b r0, r3, ne, abort=21f
++ str1b r0, r4, cs, abort=21f
++ str1b r0, ip, cs, abort=21f
++
++ exit r4, pc
++
++9: rsb ip, ip, #4
++ cmp ip, #2
++ ldr1b r1, r3, gt, abort=21f
++ ldr1b r1, r4, ge, abort=21f
++ ldr1b r1, lr, abort=21f
++ str1b r0, r3, gt, abort=21f
++ str1b r0, r4, ge, abort=21f
++ subs r2, r2, ip
++ str1b r0, lr, abort=21f
++ blt 8b
++ ands ip, r1, #3
++ beq 1b
++
++10: bic r1, r1, #3
++ cmp ip, #2
++ ldr1w r1, lr, abort=21f
++ beq 17f
++ bgt 18f
++
++
++ .macro forward_copy_shift pull push
++
++ subs r2, r2, #28
++ blt 14f
++
++ CALGN( ands ip, r1, #31 )
++ CALGN( rsb ip, ip, #32 )
++ CALGN( sbcnes r4, ip, r2 ) @ C is always set here
++ CALGN( subcc r2, r2, ip )
++ CALGN( bcc 15f )
++
++11: stmfd sp!, {r5 - r9}
++
++ PLD( pld [r1, #0] )
++ PLD( subs r2, r2, #96 )
++ PLD( pld [r1, #28] )
++ PLD( blt 13f )
++ PLD( pld [r1, #60] )
++ PLD( pld [r1, #92] )
++
++12: PLD( pld [r1, #124] )
++13: ldr4w r1, r4, r5, r6, r7, abort=19f
++ mov r3, lr, pull #\pull
++ subs r2, r2, #32
++ ldr4w r1, r8, r9, ip, lr, abort=19f
++ orr r3, r3, r4, push #\push
++ mov r4, r4, pull #\pull
++ orr r4, r4, r5, push #\push
++ mov r5, r5, pull #\pull
++ orr r5, r5, r6, push #\push
++ mov r6, r6, pull #\pull
++ orr r6, r6, r7, push #\push
++ mov r7, r7, pull #\pull
++ orr r7, r7, r8, push #\push
++ mov r8, r8, pull #\pull
++ orr r8, r8, r9, push #\push
++ mov r9, r9, pull #\pull
++ orr r9, r9, ip, push #\push
++ mov ip, ip, pull #\pull
++ orr ip, ip, lr, push #\push
++ str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
++ bge 12b
++ PLD( cmn r2, #96 )
++ PLD( bge 13b )
++
++ ldmfd sp!, {r5 - r9}
++
++14: ands ip, r2, #28
++ beq 16f
++
++15: mov r3, lr, pull #\pull
++ ldr1w r1, lr, abort=21f
++ subs ip, ip, #4
++ orr r3, r3, lr, push #\push
++ str1w r0, r3, abort=21f
++ bgt 15b
++ CALGN( cmp r2, #0 )
++ CALGN( bge 11b )
++
++16: sub r1, r1, #(\push / 8)
++ b 8b
++
++ .endm
++
++
++ forward_copy_shift pull=8 push=24
++
++17: forward_copy_shift pull=16 push=16
++
++18: forward_copy_shift pull=24 push=8
++
++
++/*
++ * Abort preanble and completion macros.
++ * If a fixup handler is required then those macros must surround it.
++ * It is assumed that the fixup code will handle the private part of
++ * the exit macro.
++ */
++
++ .macro copy_abort_preamble
++19: ldmfd sp!, {r5 - r9}
++ b 21f
++20: ldmfd sp!, {r5 - r8}
++21:
++ .endm
++
++ .macro copy_abort_end
++ ldmfd sp!, {r4, pc}
++ .endm
++
+diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/lib/copy_to_user.S
+@@ -0,0 +1,101 @@
++/*
++ * linux/arch/arm/lib/copy_to_user.S
++ *
++ * Author: Nicolas Pitre
++ * Created: Sep 29, 2005
++ * Copyright: MontaVista Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++
++/*
++ * Prototype:
++ *
++ * size_t __arch_copy_to_user(void *to, const void *from, size_t n)
++ *
++ * Purpose:
++ *
++ * copy a block to user memory from kernel memory
++ *
++ * Params:
++ *
++ * to = user memory
++ * from = kernel memory
++ * n = number of bytes to copy
++ *
++ * Return value:
++ *
++ * Number of bytes NOT copied.
++ */
++
++ .macro ldr1w ptr reg abort
++ ldr \reg, [\ptr], #4
++ .endm
++
++ .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
++ ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
++ .endm
++
++ .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
++ .endm
++
++ .macro ldr1b ptr reg cond=al abort
++ ldr\cond\()b \reg, [\ptr], #1
++ .endm
++
++ .macro str1w ptr reg abort
++100: strt \reg, [\ptr], #4
++ .section __ex_table, "a"
++ .long 100b, \abort
++ .previous
++ .endm
++
++ .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ str1w \ptr, \reg1, \abort
++ str1w \ptr, \reg2, \abort
++ str1w \ptr, \reg3, \abort
++ str1w \ptr, \reg4, \abort
++ str1w \ptr, \reg5, \abort
++ str1w \ptr, \reg6, \abort
++ str1w \ptr, \reg7, \abort
++ str1w \ptr, \reg8, \abort
++ .endm
++
++ .macro str1b ptr reg cond=al abort
++100: str\cond\()bt \reg, [\ptr], #1
++ .section __ex_table, "a"
++ .long 100b, \abort
++ .previous
++ .endm
++
++ .macro enter reg1 reg2
++ mov r3, #0
++ stmdb sp!, {r0, r2, r3, \reg1, \reg2}
++ .endm
++
++ .macro exit reg1 reg2
++ add sp, sp, #8
++ ldmfd sp!, {r0, \reg1, \reg2}
++ .endm
++
++ .text
++
++ENTRY(__arch_copy_to_user)
++
++#include "copy_template.S"
++
++ .section .fixup,"ax"
++ .align 0
++ copy_abort_preamble
++ ldmfd sp!, {r1, r2, r3}
++ sub r0, r0, r1
++ rsb r0, r0, r2
++ copy_abort_end
++ .previous
++
+diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h
+deleted file mode 100644
+--- 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
+--- /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
+--- 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/memcpy.S b/arch/arm/lib/memcpy.S
+--- a/arch/arm/lib/memcpy.S
++++ b/arch/arm/lib/memcpy.S
+@@ -1,393 +1,59 @@
+ /*
+ * linux/arch/arm/lib/memcpy.S
+ *
+- * Copyright (C) 1995-1999 Russell King
++ * Author: Nicolas Pitre
++ * Created: Sep 28, 2005
++ * Copyright: MontaVista Software, Inc.
+ *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * ASM optimised string functions
++ * 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>
+ #include <asm/assembler.h>
+
+- .text
++ .macro ldr1w ptr reg abort
++ ldr \reg, [\ptr], #4
++ .endm
+
+-#define ENTER \
+- mov ip,sp ;\
+- stmfd sp!,{r0,r4-r9,fp,ip,lr,pc} ;\
+- sub fp,ip,#4
++ .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
++ ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
++ .endm
+
+-#define EXIT \
+- LOADREGS(ea, fp, {r0, r4 - r9, fp, sp, pc})
++ .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
++ .endm
+
+-#define EXITEQ \
+- LOADREGS(eqea, fp, {r0, r4 - r9, fp, sp, pc})
++ .macro ldr1b ptr reg cond=al abort
++ ldr\cond\()b \reg, [\ptr], #1
++ .endm
++
++ .macro str1w ptr reg abort
++ str \reg, [\ptr], #4
++ .endm
++
++ .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
++ stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
++ .endm
++
++ .macro str1b ptr reg cond=al abort
++ str\cond\()b \reg, [\ptr], #1
++ .endm
++
++ .macro enter reg1 reg2
++ stmdb sp!, {r0, \reg1, \reg2}
++ .endm
++
++ .macro exit reg1 reg2
++ ldmfd sp!, {r0, \reg1, \reg2}
++ .endm
++
++ .text
++
++/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
+
+-/*
+- * Prototype: void memcpy(void *to,const void *from,unsigned long n);
+- */
+ ENTRY(memcpy)
+-ENTRY(memmove)
+- ENTER
+- cmp r1, r0
+- bcc 23f
+- subs r2, r2, #4
+- blt 6f
+- PLD( pld [r1, #0] )
+- ands ip, r0, #3
+- bne 7f
+- ands ip, r1, #3
+- bne 8f
+-
+-1: subs r2, r2, #8
+- blt 5f
+- subs r2, r2, #20
+- blt 4f
+- PLD( pld [r1, #28] )
+- PLD( subs r2, r2, #64 )
+- PLD( blt 3f )
+-2: PLD( pld [r1, #60] )
+- PLD( pld [r1, #92] )
+- ldmia r1!, {r3 - r9, ip}
+- subs r2, r2, #32
+- stmgeia r0!, {r3 - r9, ip}
+- ldmgeia r1!, {r3 - r9, ip}
+- subges r2, r2, #32
+- stmia r0!, {r3 - r9, ip}
+- bge 2b
+-3: PLD( ldmia r1!, {r3 - r9, ip} )
+- PLD( adds r2, r2, #32 )
+- PLD( stmgeia r0!, {r3 - r9, ip} )
+- PLD( ldmgeia r1!, {r3 - r9, ip} )
+- PLD( subges r2, r2, #32 )
+- PLD( stmia r0!, {r3 - r9, ip} )
+-4: cmn r2, #16
+- ldmgeia r1!, {r3 - r6}
+- subge r2, r2, #16
+- stmgeia r0!, {r3 - r6}
+- adds r2, r2, #20
+- ldmgeia r1!, {r3 - r5}
+- subge r2, r2, #12
+- stmgeia r0!, {r3 - r5}
+-5: adds r2, r2, #8
+- blt 6f
+- subs r2, r2, #4
+- ldrlt r3, [r1], #4
+- ldmgeia r1!, {r4, r5}
+- subge r2, r2, #4
+- strlt r3, [r0], #4
+- stmgeia r0!, {r4, r5}
+-
+-6: adds r2, r2, #4
+- EXITEQ
+- cmp r2, #2
+- ldrb r3, [r1], #1
+- ldrgeb r4, [r1], #1
+- ldrgtb r5, [r1], #1
+- strb r3, [r0], #1
+- strgeb r4, [r0], #1
+- strgtb r5, [r0], #1
+- EXIT
+-
+-7: rsb ip, ip, #4
+- cmp ip, #2
+- ldrb r3, [r1], #1
+- ldrgeb r4, [r1], #1
+- ldrgtb r5, [r1], #1
+- strb r3, [r0], #1
+- strgeb r4, [r0], #1
+- strgtb r5, [r0], #1
+- subs r2, r2, ip
+- blt 6b
+- ands ip, r1, #3
+- beq 1b
+-
+-8: bic r1, r1, #3
+- ldr r7, [r1], #4
+- cmp ip, #2
+- bgt 18f
+- beq 13f
+- cmp r2, #12
+- blt 11f
+- PLD( pld [r1, #12] )
+- sub r2, r2, #12
+- PLD( subs r2, r2, #32 )
+- PLD( blt 10f )
+- PLD( pld [r1, #28] )
+-9: PLD( pld [r1, #44] )
+-10: mov r3, r7, pull #8
+- ldmia r1!, {r4 - r7}
+- subs r2, r2, #16
+- orr r3, r3, r4, push #24
+- mov r4, r4, pull #8
+- orr r4, r4, r5, push #24
+- mov r5, r5, pull #8
+- orr r5, r5, r6, push #24
+- mov r6, r6, pull #8
+- orr r6, r6, r7, push #24
+- stmia r0!, {r3 - r6}
+- bge 9b
+- PLD( cmn r2, #32 )
+- PLD( bge 10b )
+- PLD( add r2, r2, #32 )
+- adds r2, r2, #12
+- blt 12f
+-11: mov r3, r7, pull #8
+- ldr r7, [r1], #4
+- subs r2, r2, #4
+- orr r3, r3, r7, push #24
+- str r3, [r0], #4
+- bge 11b
+-12: sub r1, r1, #3
+- b 6b
+-
+-13: cmp r2, #12
+- blt 16f
+- PLD( pld [r1, #12] )
+- sub r2, r2, #12
+- PLD( subs r2, r2, #32 )
+- PLD( blt 15f )
+- PLD( pld [r1, #28] )
+-14: PLD( pld [r1, #44] )
+-15: mov r3, r7, pull #16
+- ldmia r1!, {r4 - r7}
+- subs r2, r2, #16
+- orr r3, r3, r4, push #16
+- mov r4, r4, pull #16
+- orr r4, r4, r5, push #16
+- mov r5, r5, pull #16
+- orr r5, r5, r6, push #16
+- mov r6, r6, pull #16
+- orr r6, r6, r7, push #16
+- stmia r0!, {r3 - r6}
+- bge 14b
+- PLD( cmn r2, #32 )
+- PLD( bge 15b )
+- PLD( add r2, r2, #32 )
+- adds r2, r2, #12
+- blt 17f
+-16: mov r3, r7, pull #16
+- ldr r7, [r1], #4
+- subs r2, r2, #4
+- orr r3, r3, r7, push #16
+- str r3, [r0], #4
+- bge 16b
+-17: sub r1, r1, #2
+- b 6b
+-
+-18: cmp r2, #12
+- blt 21f
+- PLD( pld [r1, #12] )
+- sub r2, r2, #12
+- PLD( subs r2, r2, #32 )
+- PLD( blt 20f )
+- PLD( pld [r1, #28] )
+-19: PLD( pld [r1, #44] )
+-20: mov r3, r7, pull #24
+- ldmia r1!, {r4 - r7}
+- subs r2, r2, #16
+- orr r3, r3, r4, push #8
+- mov r4, r4, pull #24
+- orr r4, r4, r5, push #8
+- mov r5, r5, pull #24
+- orr r5, r5, r6, push #8
+- mov r6, r6, pull #24
+- orr r6, r6, r7, push #8
+- stmia r0!, {r3 - r6}
+- bge 19b
+- PLD( cmn r2, #32 )
+- PLD( bge 20b )
+- PLD( add r2, r2, #32 )
+- adds r2, r2, #12
+- blt 22f
+-21: mov r3, r7, pull #24
+- ldr r7, [r1], #4
+- subs r2, r2, #4
+- orr r3, r3, r7, push #8
+- str r3, [r0], #4
+- bge 21b
+-22: sub r1, r1, #1
+- b 6b
+-
+-
+-23: add r1, r1, r2
+- add r0, r0, r2
+- subs r2, r2, #4
+- blt 29f
+- PLD( pld [r1, #-4] )
+- ands ip, r0, #3
+- bne 30f
+- ands ip, r1, #3
+- bne 31f
+-
+-24: subs r2, r2, #8
+- blt 28f
+- subs r2, r2, #20
+- blt 27f
+- PLD( pld [r1, #-32] )
+- PLD( subs r2, r2, #64 )
+- PLD( blt 26f )
+-25: PLD( pld [r1, #-64] )
+- PLD( pld [r1, #-96] )
+- ldmdb r1!, {r3 - r9, ip}
+- subs r2, r2, #32
+- stmgedb r0!, {r3 - r9, ip}
+- ldmgedb r1!, {r3 - r9, ip}
+- subges r2, r2, #32
+- stmdb r0!, {r3 - r9, ip}
+- bge 25b
+-26: PLD( ldmdb r1!, {r3 - r9, ip} )
+- PLD( adds r2, r2, #32 )
+- PLD( stmgedb r0!, {r3 - r9, ip} )
+- PLD( ldmgedb r1!, {r3 - r9, ip} )
+- PLD( subges r2, r2, #32 )
+- PLD( stmdb r0!, {r3 - r9, ip} )
+-27: cmn r2, #16
+- ldmgedb r1!, {r3 - r6}
+- subge r2, r2, #16
+- stmgedb r0!, {r3 - r6}
+- adds r2, r2, #20
+- ldmgedb r1!, {r3 - r5}
+- subge r2, r2, #12
+- stmgedb r0!, {r3 - r5}
+-28: adds r2, r2, #8
+- blt 29f
+- subs r2, r2, #4
+- ldrlt r3, [r1, #-4]!
+- ldmgedb r1!, {r4, r5}
+- subge r2, r2, #4
+- strlt r3, [r0, #-4]!
+- stmgedb r0!, {r4, r5}
+-
+-29: adds r2, r2, #4
+- EXITEQ
+- cmp r2, #2
+- ldrb r3, [r1, #-1]!
+- ldrgeb r4, [r1, #-1]!
+- ldrgtb r5, [r1, #-1]!
+- strb r3, [r0, #-1]!
+- strgeb r4, [r0, #-1]!
+- strgtb r5, [r0, #-1]!
+- EXIT
+-
+-30: cmp ip, #2
+- ldrb r3, [r1, #-1]!
+- ldrgeb r4, [r1, #-1]!
+- ldrgtb r5, [r1, #-1]!
+- strb r3, [r0, #-1]!
+- strgeb r4, [r0, #-1]!
+- strgtb r5, [r0, #-1]!
+- subs r2, r2, ip
+- blt 29b
+- ands ip, r1, #3
+- beq 24b
+-
+-31: bic r1, r1, #3
+- ldr r3, [r1], #0
+- cmp ip, #2
+- blt 41f
+- beq 36f
+- cmp r2, #12
+- blt 34f
+- PLD( pld [r1, #-16] )
+- sub r2, r2, #12
+- PLD( subs r2, r2, #32 )
+- PLD( blt 33f )
+- PLD( pld [r1, #-32] )
+-32: PLD( pld [r1, #-48] )
+-33: mov r7, r3, push #8
+- ldmdb r1!, {r3, r4, r5, r6}
+- subs r2, r2, #16
+- orr r7, r7, r6, pull #24
+- mov r6, r6, push #8
+- orr r6, r6, r5, pull #24
+- mov r5, r5, push #8
+- orr r5, r5, r4, pull #24
+- mov r4, r4, push #8
+- orr r4, r4, r3, pull #24
+- stmdb r0!, {r4, r5, r6, r7}
+- bge 32b
+- PLD( cmn r2, #32 )
+- PLD( bge 33b )
+- PLD( add r2, r2, #32 )
+- adds r2, r2, #12
+- blt 35f
+-34: mov ip, r3, push #8
+- ldr r3, [r1, #-4]!
+- subs r2, r2, #4
+- orr ip, ip, r3, pull #24
+- str ip, [r0, #-4]!
+- bge 34b
+-35: add r1, r1, #3
+- b 29b
+-
+-36: cmp r2, #12
+- blt 39f
+- PLD( pld [r1, #-16] )
+- sub r2, r2, #12
+- PLD( subs r2, r2, #32 )
+- PLD( blt 38f )
+- PLD( pld [r1, #-32] )
+-37: PLD( pld [r1, #-48] )
+-38: mov r7, r3, push #16
+- ldmdb r1!, {r3, r4, r5, r6}
+- subs r2, r2, #16
+- orr r7, r7, r6, pull #16
+- mov r6, r6, push #16
+- orr r6, r6, r5, pull #16
+- mov r5, r5, push #16
+- orr r5, r5, r4, pull #16
+- mov r4, r4, push #16
+- orr r4, r4, r3, pull #16
+- stmdb r0!, {r4, r5, r6, r7}
+- bge 37b
+- PLD( cmn r2, #32 )
+- PLD( bge 38b )
+- PLD( add r2, r2, #32 )
+- adds r2, r2, #12
+- blt 40f
+-39: mov ip, r3, push #16
+- ldr r3, [r1, #-4]!
+- subs r2, r2, #4
+- orr ip, ip, r3, pull #16
+- str ip, [r0, #-4]!
+- bge 39b
+-40: add r1, r1, #2
+- b 29b
+-
+-41: cmp r2, #12
+- blt 44f
+- PLD( pld [r1, #-16] )
+- sub r2, r2, #12
+- PLD( subs r2, r2, #32 )
+- PLD( blt 43f )
+- PLD( pld [r1, #-32] )
+-42: PLD( pld [r1, #-48] )
+-43: mov r7, r3, push #24
+- ldmdb r1!, {r3, r4, r5, r6}
+- subs r2, r2, #16
+- orr r7, r7, r6, pull #8
+- mov r6, r6, push #24
+- orr r6, r6, r5, pull #8
+- mov r5, r5, push #24
+- orr r5, r5, r4, pull #8
+- mov r4, r4, push #24
+- orr r4, r4, r3, pull #8
+- stmdb r0!, {r4, r5, r6, r7}
+- bge 42b
+- PLD( cmn r2, #32 )
+- PLD( bge 43b )
+- PLD( add r2, r2, #32 )
+- adds r2, r2, #12
+- blt 45f
+-44: mov ip, r3, push #24
+- ldr r3, [r1, #-4]!
+- subs r2, r2, #4
+- orr ip, ip, r3, pull #8
+- str ip, [r0, #-4]!
+- bge 44b
+-45: add r1, r1, #1
+- b 29b
++
++#include "copy_template.S"
+
+diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/lib/memmove.S
+@@ -0,0 +1,206 @@
++/*
++ * linux/arch/arm/lib/memmove.S
++ *
++ * Author: Nicolas Pitre
++ * Created: Sep 28, 2005
++ * Copyright: (C) MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++
++/*
++ * This can be used to enable code to cacheline align the source pointer.
++ * Experiments on tested architectures (StrongARM and XScale) didn't show
++ * this a worthwhile thing to do. That might be different in the future.
++ */
++//#define CALGN(code...) code
++#define CALGN(code...)
++
++ .text
++
++/*
++ * Prototype: void *memmove(void *dest, const void *src, size_t n);
++ *
++ * Note:
++ *
++ * If the memory regions don't overlap, we simply branch to memcpy which is
++ * normally a bit faster. Otherwise the copy is done going downwards. This
++ * is a transposition of the code from copy_template.S but with the copy
++ * occurring in the opposite direction.
++ */
++
++ENTRY(memmove)
++
++ subs ip, r0, r1
++ cmphi r2, ip
++ bls memcpy
++
++ stmfd sp!, {r0, r4, lr}
++ add r1, r1, r2
++ add r0, r0, r2
++ subs r2, r2, #4
++ blt 8f
++ ands ip, r0, #3
++ PLD( pld [r1, #-4] )
++ bne 9f
++ ands ip, r1, #3
++ bne 10f
++
++1: subs r2, r2, #(28)
++ stmfd sp!, {r5 - r8}
++ blt 5f
++
++ CALGN( ands ip, r1, #31 )
++ CALGN( sbcnes r4, ip, r2 ) @ C is always set here
++ CALGN( bcs 2f )
++ CALGN( adr r4, 6f )
++ CALGN( subs r2, r2, ip ) @ C is set here
++ CALGN( add pc, r4, ip )
++
++ PLD( pld [r1, #-4] )
++2: PLD( subs r2, r2, #96 )
++ PLD( pld [r1, #-32] )
++ PLD( blt 4f )
++ PLD( pld [r1, #-64] )
++ PLD( pld [r1, #-96] )
++
++3: PLD( pld [r1, #-128] )
++4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
++ subs r2, r2, #32
++ stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
++ bge 3b
++ PLD( cmn r2, #96 )
++ PLD( bge 4b )
++
++5: ands ip, r2, #28
++ rsb ip, ip, #32
++ addne pc, pc, ip @ C is always clear here
++ b 7f
++6: nop
++ ldr r3, [r1, #-4]!
++ ldr r4, [r1, #-4]!
++ ldr r5, [r1, #-4]!
++ ldr r6, [r1, #-4]!
++ ldr r7, [r1, #-4]!
++ ldr r8, [r1, #-4]!
++ ldr lr, [r1, #-4]!
++
++ add pc, pc, ip
++ nop
++ nop
++ str r3, [r0, #-4]!
++ str r4, [r0, #-4]!
++ str r5, [r0, #-4]!
++ str r6, [r0, #-4]!
++ str r7, [r0, #-4]!
++ str r8, [r0, #-4]!
++ str lr, [r0, #-4]!
++
++ CALGN( bcs 2b )
++
++7: ldmfd sp!, {r5 - r8}
++
++8: movs r2, r2, lsl #31
++ ldrneb r3, [r1, #-1]!
++ ldrcsb r4, [r1, #-1]!
++ ldrcsb ip, [r1, #-1]
++ strneb r3, [r0, #-1]!
++ strcsb r4, [r0, #-1]!
++ strcsb ip, [r0, #-1]
++ ldmfd sp!, {r0, r4, pc}
++
++9: cmp ip, #2
++ ldrgtb r3, [r1, #-1]!
++ ldrgeb r4, [r1, #-1]!
++ ldrb lr, [r1, #-1]!
++ strgtb r3, [r0, #-1]!
++ strgeb r4, [r0, #-1]!
++ subs r2, r2, ip
++ strb lr, [r0, #-1]!
++ blt 8b
++ ands ip, r1, #3
++ beq 1b
++
++10: bic r1, r1, #3
++ cmp ip, #2
++ ldr r3, [r1, #0]
++ beq 17f
++ blt 18f
++
++
++ .macro backward_copy_shift push pull
++
++ subs r2, r2, #28
++ blt 14f
++
++ CALGN( ands ip, r1, #31 )
++ CALGN( rsb ip, ip, #32 )
++ CALGN( sbcnes r4, ip, r2 ) @ C is always set here
++ CALGN( subcc r2, r2, ip )
++ CALGN( bcc 15f )
++
++11: stmfd sp!, {r5 - r9}
++
++ PLD( pld [r1, #-4] )
++ PLD( subs r2, r2, #96 )
++ PLD( pld [r1, #-32] )
++ PLD( blt 13f )
++ PLD( pld [r1, #-64] )
++ PLD( pld [r1, #-96] )
++
++12: PLD( pld [r1, #-128] )
++13: ldmdb r1!, {r7, r8, r9, ip}
++ mov lr, r3, push #\push
++ subs r2, r2, #32
++ ldmdb r1!, {r3, r4, r5, r6}
++ orr lr, lr, ip, pull #\pull
++ mov ip, ip, push #\push
++ orr ip, ip, r9, pull #\pull
++ mov r9, r9, push #\push
++ orr r9, r9, r8, pull #\pull
++ mov r8, r8, push #\push
++ orr r8, r8, r7, pull #\pull
++ mov r7, r7, push #\push
++ orr r7, r7, r6, pull #\pull
++ mov r6, r6, push #\push
++ orr r6, r6, r5, pull #\pull
++ mov r5, r5, push #\push
++ orr r5, r5, r4, pull #\pull
++ mov r4, r4, push #\push
++ orr r4, r4, r3, pull #\pull
++ stmdb r0!, {r4 - r9, ip, lr}
++ bge 12b
++ PLD( cmn r2, #96 )
++ PLD( bge 13b )
++
++ ldmfd sp!, {r5 - r9}
++
++14: ands ip, r2, #28
++ beq 16f
++
++15: mov lr, r3, push #\push
++ ldr r3, [r1, #-4]!
++ subs ip, ip, #4
++ orr lr, lr, r3, pull #\pull
++ str lr, [r0, #-4]!
++ bgt 15b
++ CALGN( cmp r2, #0 )
++ CALGN( bge 11b )
++
++16: add r1, r1, #(\pull / 8)
++ b 8b
++
++ .endm
++
++
++ backward_copy_shift push=8 pull=24
++
++17: backward_copy_shift push=16 pull=16
++
++18: backward_copy_shift push=24 pull=8
++
+diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S
+new file mode 100644
+--- /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
+--- 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
+--- /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 at 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/uaccess.S b/arch/arm/lib/uaccess.S
+--- a/arch/arm/lib/uaccess.S
++++ b/arch/arm/lib/uaccess.S
+@@ -657,41 +657,3 @@ USER( ldrgtbt r3, [r1], #1) @ May fau
+ LOADREGS(fd,sp!, {r4 - r7, pc})
+ .previous
+
+-/* Prototype: int __arch_clear_user(void *addr, size_t sz)
+- * Purpose : clear some user memory
+- * Params : addr - user memory address to clear
+- * : sz - number of bytes to clear
+- * Returns : number of bytes NOT cleared
+- */
+-ENTRY(__arch_clear_user)
+- stmfd sp!, {r1, lr}
+- mov r2, #0
+- cmp r1, #4
+- blt 2f
+- ands ip, r0, #3
+- beq 1f
+- cmp ip, #2
+-USER( strbt r2, [r0], #1)
+-USER( strlebt r2, [r0], #1)
+-USER( strltbt r2, [r0], #1)
+- rsb ip, ip, #4
+- sub r1, r1, ip @ 7 6 5 4 3 2 1
+-1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
+-USER( strplt r2, [r0], #4)
+-USER( strplt r2, [r0], #4)
+- bpl 1b
+- adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
+-USER( strplt r2, [r0], #4)
+-2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
+-USER( strnebt r2, [r0], #1)
+-USER( strnebt r2, [r0], #1)
+- tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
+-USER( strnebt r2, [r0], #1)
+- mov r0, #0
+- LOADREGS(fd,sp!, {r1, pc})
+-
+- .section .fixup,"ax"
+- .align 0
+-9001: LOADREGS(fd,sp!, {r0, pc})
+- .previous
+-
+diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S
+new file mode 100644
+--- /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
+--- 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
+--- 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
+--- 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 @@ MACHINE_START(AAED2000, "Agilent AAED-20
+ .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
+--- /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
+--- /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
+--- 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/platform_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 @@ struct sys_timer aaec2000_timer = {
+ .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
+--- 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
+--- a/arch/arm/mach-clps711x/Kconfig
++++ b/arch/arm/mach-clps711x/Kconfig
+@@ -69,6 +69,17 @@ config EP72XX_ROM_BOOT
+
+ 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
+--- a/arch/arm/mach-clps711x/Makefile
++++ b/arch/arm/mach-clps711x/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_CDB89712) += cdb89712.
+ 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
+--- 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
+--- 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
+--- 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
+--- a/arch/arm/mach-clps711x/edb7211-mm.c
++++ b/arch/arm/mach-clps711x/edb7211-mm.c
+@@ -51,15 +51,27 @@ extern void clps711x_map_io(void);
+ * 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
+--- 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
+--- /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
+--- /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
+--- /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
+--- 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
+--- a/arch/arm/mach-clps7500/core.c
++++ b/arch/arm/mach-clps7500/core.c
+@@ -259,10 +259,27 @@ static void __init clps7500_init_irq(voi
+ }
+
+ 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
+--- a/arch/arm/mach-ebsa110/core.c
++++ b/arch/arm/mach-ebsa110/core.c
+@@ -76,16 +76,42 @@ static struct map_desc ebsa110_io_desc[]
+ /*
+ * 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)
+@@ -225,9 +251,33 @@ static struct platform_device serial_dev
+ },
+ };
+
++static struct resource am79c961_resources[] = {
++ {
++ .start = 0x220,
++ .end = 0x238,
++ .flags = IORESOURCE_IO,
++ }, {
++ .start = IRQ_EBSA110_ETHERNET,
++ .end = IRQ_EBSA110_ETHERNET,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device am79c961_device = {
++ .name = "am79c961",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(am79c961_resources),
++ .resource = am79c961_resources,
++};
++
++static struct platform_device *ebsa110_devices[] = {
++ &serial_device,
++ &am79c961_device,
++};
++
+ static int __init ebsa110_init(void)
+ {
+- return platform_device_register(&serial_device);
++ return platform_add_devices(ebsa110_devices, ARRAY_SIZE(ebsa110_devices));
+ }
+
+ arch_initcall(ebsa110_init);
+diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c
+--- 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
+--- 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
+--- a/arch/arm/mach-footbridge/common.c
++++ b/arch/arm/mach-footbridge/common.c
+@@ -130,8 +130,17 @@ void __init footbridge_init_irq(void)
+ * 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 fb_common_io_desc
+ */
+ 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 ebsa285_host_io_d
+ */
+ 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
+--- a/arch/arm/mach-h720x/common.c
++++ b/arch/arm/mach-h720x/common.c
+@@ -237,7 +237,12 @@ void __init h720x_init_irq (void)
+ }
+
+ 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-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
+--- a/arch/arm/mach-h720x/h7202-eval.c
++++ b/arch/arm/mach-h720x/h7202-eval.c
+@@ -18,7 +18,7 @@
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/setup.h>
+ #include <asm/types.h>
+diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
+--- a/arch/arm/mach-imx/generic.c
++++ b/arch/arm/mach-imx/generic.c
+@@ -22,10 +22,12 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #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 platform_device *devices[]
+ };
+
+ 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
+--- a/arch/arm/mach-imx/mx1ads.c
++++ b/arch/arm/mach-imx/mx1ads.c
+@@ -14,6 +14,7 @@
+
+ #include <linux/device.h>
+ #include <linux/init.h>
++#include <linux/platform_device.h>
+ #include <asm/system.h>
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+@@ -61,13 +62,37 @@ mx1ads_init(void)
+ }
+
+ 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
+--- 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
+--- a/arch/arm/mach-integrator/integrator_ap.c
++++ b/arch/arm/mach-integrator/integrator_ap.c
+@@ -21,7 +21,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/list.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/sysdev.h>
+@@ -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
+--- a/arch/arm/mach-integrator/integrator_cp.c
++++ b/arch/arm/mach-integrator/integrator_cp.c
+@@ -11,7 +11,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/list.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+@@ -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
+--- 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
+--- a/arch/arm/mach-iop3xx/iop321-setup.c
++++ b/arch/arm/mach-iop3xx/iop321-setup.c
+@@ -16,7 +16,7 @@
+ #include <linux/init.h>
+ #include <linux/major.h>
+ #include <linux/fs.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+ #include <linux/serial_core.h>
+@@ -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
+--- a/arch/arm/mach-iop3xx/iop331-setup.c
++++ b/arch/arm/mach-iop3xx/iop331-setup.c
+@@ -15,7 +15,7 @@
+ #include <linux/init.h>
+ #include <linux/major.h>
+ #include <linux/fs.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+ #include <linux/serial_core.h>
+@@ -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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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/Makefile b/arch/arm/mach-ixp2000/Makefile
+--- a/arch/arm/mach-ixp2000/Makefile
++++ b/arch/arm/mach-ixp2000/Makefile
+@@ -1,7 +1,7 @@
+ #
+ # Makefile for the linux kernel.
+ #
+-obj-y := core.o pci.o
++obj-y := core.o pci.o uengine.o
+ obj-m :=
+ obj-n :=
+ obj- :=
+diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
+--- a/arch/arm/mach-ixp2000/core.c
++++ b/arch/arm/mach-ixp2000/core.c
+@@ -1,5 +1,5 @@
+ /*
+- * arch/arm/mach-ixp2000/common.c
++ * arch/arm/mach-ixp2000/core.c
+ *
+ * Common routines used by all IXP2400/2800 based platforms.
+ *
+@@ -49,7 +49,6 @@ static unsigned long ixp2000_slowport_ir
+ *************************************************************************/
+ void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg)
+ {
+-
+ spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags);
+
+ old_cfg->CCR = *IXP2000_SLOWPORT_CCR;
+@@ -62,7 +61,7 @@ void ixp2000_acquire_slowport(struct slo
+ ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC);
+ ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC);
+ ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR);
+- ixp2000_reg_write(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
++ ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
+ }
+
+ void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
+@@ -71,7 +70,7 @@ void ixp2000_release_slowport(struct slo
+ ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC);
+ ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC);
+ ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR);
+- ixp2000_reg_write(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
++ ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
+
+ spin_unlock_irqrestore(&ixp2000_slowport_lock,
+ ixp2000_slowport_irq_flags);
+@@ -83,42 +82,42 @@ void ixp2000_release_slowport(struct slo
+ 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
+ }
+@@ -145,7 +144,7 @@ void __init ixp2000_map_io(void)
+ iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
+
+ /* Set slowport to 8-bit mode. */
+- ixp2000_reg_write(IXP2000_SLOWPORT_FRM, 1);
++ ixp2000_reg_wrb(IXP2000_SLOWPORT_FRM, 1);
+ }
+
+
+@@ -209,7 +208,7 @@ static int ixp2000_timer_interrupt(int i
+ write_seqlock(&xtime_lock);
+
+ /* clear timer 1 */
+- ixp2000_reg_write(IXP2000_T1_CLR, 1);
++ ixp2000_reg_wrb(IXP2000_T1_CLR, 1);
+
+ while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
+ timer_tick(regs);
+@@ -252,12 +251,12 @@ void __init ixp2000_init_time(unsigned l
+
+ ixp2000_reg_write(IXP2000_T4_CLR, 0);
+ ixp2000_reg_write(IXP2000_T4_CLD, -1);
+- ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
++ ixp2000_reg_wrb(IXP2000_T4_CTL, (1 << 7));
+ missing_jiffy_timer_csr = IXP2000_T4_CSR;
+ } else {
+ ixp2000_reg_write(IXP2000_T2_CLR, 0);
+ ixp2000_reg_write(IXP2000_T2_CLD, -1);
+- ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
++ ixp2000_reg_wrb(IXP2000_T2_CTL, (1 << 7));
+ missing_jiffy_timer_csr = IXP2000_T2_CSR;
+ }
+ next_jiffy_time = 0xffffffff;
+@@ -279,7 +278,7 @@ static void update_gpio_int_csrs(void)
+ ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
+ ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
+ ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
+- ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
++ ixp2000_reg_wrb(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
+ }
+
+ void gpio_line_config(int line, int direction)
+@@ -297,9 +296,9 @@ void gpio_line_config(int line, int dire
+ GPIO_IRQ_level_high &= ~(1 << line);
+ update_gpio_int_csrs();
+
+- ixp2000_reg_write(IXP2000_GPIO_PDSR, 1 << line);
++ ixp2000_reg_wrb(IXP2000_GPIO_PDSR, 1 << line);
+ } else if (direction == GPIO_IN) {
+- ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
++ ixp2000_reg_wrb(IXP2000_GPIO_PDCR, 1 << line);
+ }
+ local_irq_restore(flags);
+ }
+@@ -365,12 +364,12 @@ static void ixp2000_GPIO_irq_mask_ack(un
+
+ ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+ ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+- ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
++ ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
+ }
+
+ static void ixp2000_GPIO_irq_mask(unsigned int irq)
+ {
+- ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
++ ixp2000_reg_wrb(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+ }
+
+ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
+@@ -389,9 +388,9 @@ static void ixp2000_pci_irq_mask(unsigne
+ {
+ unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
+ if (irq == IRQ_IXP2000_PCIA)
+- ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
++ ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
+ else if (irq == IRQ_IXP2000_PCIB)
+- ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
++ ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
+ }
+
+ static void ixp2000_pci_irq_unmask(unsigned int irq)
+@@ -411,7 +410,7 @@ static struct irqchip ixp2000_pci_irq_ch
+
+ static void ixp2000_irq_mask(unsigned int irq)
+ {
+- ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
++ ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
+ }
+
+ static void ixp2000_irq_unmask(unsigned int irq)
+@@ -443,7 +442,7 @@ void __init ixp2000_init_irq(void)
+ ixp2000_reg_write(IXP2000_GPIO_INCR, -1);
+
+ /* clear PCI interrupt sources */
+- ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
++ ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
+
+ /*
+ * Certain bits in the IRQ status register of the
+diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
+--- a/arch/arm/mach-ixp2000/enp2611.c
++++ b/arch/arm/mach-ixp2000/enp2611.c
+@@ -32,7 +32,7 @@
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+ #include <linux/serial_core.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -64,6 +64,35 @@ static struct sys_timer enp2611_timer =
+
+
+ /*************************************************************************
++ * ENP-2611 I/O
++ *************************************************************************/
++static struct map_desc enp2611_io_desc[] __initdata = {
++ {
++ .virtual = ENP2611_CALEB_VIRT_BASE,
++ .physical = ENP2611_CALEB_PHYS_BASE,
++ .length = ENP2611_CALEB_SIZE,
++ .type = MT_IXP2000_DEVICE
++ }, {
++ .virtual = ENP2611_PM3386_0_VIRT_BASE,
++ .physical = ENP2611_PM3386_0_PHYS_BASE,
++ .length = ENP2611_PM3386_0_SIZE,
++ .type = MT_IXP2000_DEVICE
++ }, {
++ .virtual = ENP2611_PM3386_1_VIRT_BASE,
++ .physical = ENP2611_PM3386_1_PHYS_BASE,
++ .length = ENP2611_PM3386_1_SIZE,
++ .type = MT_IXP2000_DEVICE
++ }
++};
++
++void __init enp2611_map_io(void)
++{
++ ixp2000_map_io();
++ iotable_init(enp2611_io_desc, ARRAY_SIZE(enp2611_io_desc));
++}
++
++
++/*************************************************************************
+ * ENP-2611 PCI
+ *************************************************************************/
+ static int enp2611_pci_setup(int nr, struct pci_sys_data *sys)
+@@ -229,7 +258,7 @@ MACHINE_START(ENP2611, "Radisys ENP-2611
+ .phys_io = IXP2000_UART_PHYS_BASE,
+ .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+- .map_io = ixp2000_map_io,
++ .map_io = enp2611_map_io,
+ .init_irq = ixp2000_init_irq,
+ .timer = &enp2611_timer,
+ .init_machine = enp2611_init_machine,
+diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
+--- a/arch/arm/mach-ixp2000/ixdp2x00.c
++++ b/arch/arm/mach-ixp2000/ixdp2x00.c
+@@ -20,7 +20,7 @@
+ #include <linux/mm.h>
+ #include <linux/sched.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/bitops.h>
+ #include <linux/pci.h>
+ #include <linux/ioport.h>
+@@ -81,7 +81,7 @@ static void ixdp2x00_irq_mask(unsigned i
+
+ dummy = *board_irq_mask;
+ dummy |= IXP2000_BOARD_IRQ_MASK(irq);
+- ixp2000_reg_write(board_irq_mask, dummy);
++ ixp2000_reg_wrb(board_irq_mask, dummy);
+
+ #ifdef CONFIG_ARCH_IXDP2400
+ if (machine_is_ixdp2400())
+@@ -101,7 +101,7 @@ static void ixdp2x00_irq_unmask(unsigned
+
+ dummy = *board_irq_mask;
+ dummy &= ~IXP2000_BOARD_IRQ_MASK(irq);
+- ixp2000_reg_write(board_irq_mask, dummy);
++ ixp2000_reg_wrb(board_irq_mask, dummy);
+
+ if (machine_is_ixdp2400())
+ ixp2000_release_slowport(&old_cfg);
+@@ -176,7 +176,7 @@ void ixdp2x00_init_irq(volatile unsigned
+ *************************************************************************/
+ 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
+--- a/arch/arm/mach-ixp2000/ixdp2x01.c
++++ b/arch/arm/mach-ixp2000/ixdp2x01.c
+@@ -29,7 +29,7 @@
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+ #include <linux/serial_core.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -51,7 +51,7 @@
+ *************************************************************************/
+ static void ixdp2x01_irq_mask(unsigned int irq)
+ {
+- ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG,
++ ixp2000_reg_wrb(IXDP2X01_INT_MASK_SET_REG,
+ IXP2000_BOARD_IRQ_MASK(irq));
+ }
+
+@@ -114,7 +114,7 @@ void __init ixdp2x01_init_irq(void)
+
+ /* Mask all interrupts from CPLD, disable simulation */
+ ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, 0xffffffff);
+- ixp2000_reg_write(IXDP2X01_INT_SIM_REG, 0);
++ ixp2000_reg_wrb(IXDP2X01_INT_SIM_REG, 0);
+
+ for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
+ if (irq & valid_irq_mask) {
+@@ -136,7 +136,7 @@ void __init ixdp2x01_init_irq(void)
+ *************************************************************************/
+ 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
+ };
+@@ -299,7 +299,6 @@ struct hw_pci ixdp2x01_pci __initdata =
+
+ int __init ixdp2x01_pci_init(void)
+ {
+-
+ pci_common_init(&ixdp2x01_pci);
+ return 0;
+ }
+@@ -316,7 +315,7 @@ static struct flash_platform_data ixdp2x
+
+ static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs)
+ {
+- ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
++ ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG,
+ ((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN));
+ return (ofs & IXDP2X01_FLASH_WINDOW_MASK);
+ }
+@@ -363,7 +362,7 @@ static struct platform_device *ixdp2x01_
+
+ static void __init ixdp2x01_init_machine(void)
+ {
+- ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
++ ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG,
+ (IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN));
+
+ ixdp2x01_flash_data.nr_banks =
+diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
+--- a/arch/arm/mach-ixp2000/pci.c
++++ b/arch/arm/mach-ixp2000/pci.c
+@@ -148,7 +148,7 @@ int ixp2000_pci_abort_handler(unsigned l
+ local_irq_save(flags);
+ temp = *(IXP2000_PCI_CONTROL);
+ if (temp & ((1 << 8) | (1 << 5))) {
+- ixp2000_reg_write(IXP2000_PCI_CONTROL, temp);
++ ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
+ }
+
+ temp = *(IXP2000_PCI_CMDSTAT);
+@@ -178,8 +178,8 @@ clear_master_aborts(void)
+
+ local_irq_save(flags);
+ temp = *(IXP2000_PCI_CONTROL);
+- if (temp & ((1 << 8) | (1 << 5))) {
+- ixp2000_reg_write(IXP2000_PCI_CONTROL, temp);
++ if (temp & ((1 << 8) | (1 << 5))) {
++ ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
+ }
+
+ temp = *(IXP2000_PCI_CMDSTAT);
+diff --git a/arch/arm/mach-ixp2000/uengine.c b/arch/arm/mach-ixp2000/uengine.c
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-ixp2000/uengine.c
+@@ -0,0 +1,474 @@
++/*
++ * Generic library functions for the microengines found on the Intel
++ * IXP2000 series of network processors.
++ *
++ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh at wantstofly.org>
++ * Dedicated to Marija Kulikova.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of the
++ * License, or (at your option) any later version.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <asm/hardware.h>
++#include <asm/arch/ixp2000-regs.h>
++#include <asm/arch/uengine.h>
++#include <asm/io.h>
++
++#define USTORE_ADDRESS 0x000
++#define USTORE_DATA_LOWER 0x004
++#define USTORE_DATA_UPPER 0x008
++#define CTX_ENABLES 0x018
++#define CC_ENABLE 0x01c
++#define CSR_CTX_POINTER 0x020
++#define INDIRECT_CTX_STS 0x040
++#define ACTIVE_CTX_STS 0x044
++#define INDIRECT_CTX_SIG_EVENTS 0x048
++#define INDIRECT_CTX_WAKEUP_EVENTS 0x050
++#define NN_PUT 0x080
++#define NN_GET 0x084
++#define TIMESTAMP_LOW 0x0c0
++#define TIMESTAMP_HIGH 0x0c4
++#define T_INDEX_BYTE_INDEX 0x0f4
++#define LOCAL_CSR_STATUS 0x180
++
++u32 ixp2000_uengine_mask;
++
++static void *ixp2000_uengine_csr_area(int uengine)
++{
++ return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
++}
++
++/*
++ * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR
++ * space means that the microengine we tried to access was also trying
++ * to access its own CSR space on the same clock cycle as we did. When
++ * this happens, we lose the arbitration process by default, and the
++ * read or write we tried to do was not actually performed, so we try
++ * again until it succeeds.
++ */
++u32 ixp2000_uengine_csr_read(int uengine, int offset)
++{
++ void *uebase;
++ u32 *local_csr_status;
++ u32 *reg;
++ u32 value;
++
++ uebase = ixp2000_uengine_csr_area(uengine);
++
++ local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
++ reg = (u32 *)(uebase + offset);
++ do {
++ value = ixp2000_reg_read(reg);
++ } while (ixp2000_reg_read(local_csr_status) & 1);
++
++ return value;
++}
++EXPORT_SYMBOL(ixp2000_uengine_csr_read);
++
++void ixp2000_uengine_csr_write(int uengine, int offset, u32 value)
++{
++ void *uebase;
++ u32 *local_csr_status;
++ u32 *reg;
++
++ uebase = ixp2000_uengine_csr_area(uengine);
++
++ local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
++ reg = (u32 *)(uebase + offset);
++ do {
++ ixp2000_reg_write(reg, value);
++ } while (ixp2000_reg_read(local_csr_status) & 1);
++}
++EXPORT_SYMBOL(ixp2000_uengine_csr_write);
++
++void ixp2000_uengine_reset(u32 uengine_mask)
++{
++ ixp2000_reg_write(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask);
++ ixp2000_reg_write(IXP2000_RESET1, 0);
++}
++EXPORT_SYMBOL(ixp2000_uengine_reset);
++
++void ixp2000_uengine_set_mode(int uengine, u32 mode)
++{
++ /*
++ * CTL_STR_PAR_EN: unconditionally enable parity checking on
++ * control store.
++ */
++ mode |= 0x10000000;
++ ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode);
++
++ /*
++ * Enable updating of condition codes.
++ */
++ ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000);
++
++ /*
++ * Initialise other per-microengine registers.
++ */
++ ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00);
++ ixp2000_uengine_csr_write(uengine, NN_GET, 0x00);
++ ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0);
++}
++EXPORT_SYMBOL(ixp2000_uengine_set_mode);
++
++static int make_even_parity(u32 x)
++{
++ return hweight32(x) & 1;
++}
++
++static void ustore_write(int uengine, u64 insn)
++{
++ /*
++ * Generate even parity for top and bottom 20 bits.
++ */
++ insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41;
++ insn |= (u64)make_even_parity(insn & 0x000fffff) << 40;
++
++ /*
++ * Write to microstore. The second write auto-increments
++ * the USTORE_ADDRESS index register.
++ */
++ ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn);
++ ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32));
++}
++
++void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns)
++{
++ int i;
++
++ /*
++ * Start writing to microstore at address 0.
++ */
++ ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000);
++ for (i = 0; i < insns; i++) {
++ u64 insn;
++
++ insn = (((u64)ucode[0]) << 32) |
++ (((u64)ucode[1]) << 24) |
++ (((u64)ucode[2]) << 16) |
++ (((u64)ucode[3]) << 8) |
++ ((u64)ucode[4]);
++ ucode += 5;
++
++ ustore_write(uengine, insn);
++ }
++
++ /*
++ * Pad with a few NOPs at the end (to avoid the microengine
++ * aborting as it prefetches beyond the last instruction), unless
++ * we run off the end of the instruction store first, at which
++ * point the address register will wrap back to zero.
++ */
++ for (i = 0; i < 4; i++) {
++ u32 addr;
++
++ addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS);
++ if (addr == 0x80000000)
++ break;
++ ustore_write(uengine, 0xf0000c0300ULL);
++ }
++
++ /*
++ * End programming.
++ */
++ ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000);
++}
++EXPORT_SYMBOL(ixp2000_uengine_load_microcode);
++
++void ixp2000_uengine_init_context(int uengine, int context, int pc)
++{
++ /*
++ * Select the right context for indirect access.
++ */
++ ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context);
++
++ /*
++ * Initialise signal masks to immediately go to Ready state.
++ */
++ ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1);
++ ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1);
++
++ /*
++ * Set program counter.
++ */
++ ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc);
++}
++EXPORT_SYMBOL(ixp2000_uengine_init_context);
++
++void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask)
++{
++ u32 mask;
++
++ /*
++ * Enable the specified context to go to Executing state.
++ */
++ mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
++ mask |= ctx_mask << 8;
++ ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
++}
++EXPORT_SYMBOL(ixp2000_uengine_start_contexts);
++
++void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask)
++{
++ u32 mask;
++
++ /*
++ * Disable the Ready->Executing transition. Note that this
++ * does not stop the context until it voluntarily yields.
++ */
++ mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
++ mask &= ~(ctx_mask << 8);
++ ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
++}
++EXPORT_SYMBOL(ixp2000_uengine_stop_contexts);
++
++static int check_ixp_type(struct ixp2000_uengine_code *c)
++{
++ u32 product_id;
++ u32 rev;
++
++ product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID);
++ if (((product_id >> 16) & 0x1f) != 0)
++ return 0;
++
++ switch ((product_id >> 8) & 0xff) {
++ case 0: /* IXP2800 */
++ if (!(c->cpu_model_bitmask & 4))
++ return 0;
++ break;
++
++ case 1: /* IXP2850 */
++ if (!(c->cpu_model_bitmask & 8))
++ return 0;
++ break;
++
++ case 2: /* IXP2400 */
++ if (!(c->cpu_model_bitmask & 2))
++ return 0;
++ break;
++
++ default:
++ return 0;
++ }
++
++ rev = product_id & 0xff;
++ if (rev < c->cpu_min_revision || rev > c->cpu_max_revision)
++ return 0;
++
++ return 1;
++}
++
++static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b)
++{
++ int offset;
++ int i;
++
++ offset = 0;
++
++ for (i = 0; i < 128; i++) {
++ u8 b3;
++ u8 b2;
++ u8 b1;
++ u8 b0;
++
++ b3 = (gpr_a[i] >> 24) & 0xff;
++ b2 = (gpr_a[i] >> 16) & 0xff;
++ b1 = (gpr_a[i] >> 8) & 0xff;
++ b0 = gpr_a[i] & 0xff;
++
++ // immed[@ai, (b1 << 8) | b0]
++ // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII
++ ucode[offset++] = 0xf0;
++ ucode[offset++] = (b1 >> 4);
++ ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6);
++ ucode[offset++] = (b0 << 2);
++ ucode[offset++] = 0x80 | i;
++
++ // immed_w1[@ai, (b3 << 8) | b2]
++ // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII
++ ucode[offset++] = 0xf4;
++ ucode[offset++] = 0x40 | (b3 >> 4);
++ ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6);
++ ucode[offset++] = (b2 << 2);
++ ucode[offset++] = 0x80 | i;
++ }
++
++ for (i = 0; i < 128; i++) {
++ u8 b3;
++ u8 b2;
++ u8 b1;
++ u8 b0;
++
++ b3 = (gpr_b[i] >> 24) & 0xff;
++ b2 = (gpr_b[i] >> 16) & 0xff;
++ b1 = (gpr_b[i] >> 8) & 0xff;
++ b0 = gpr_b[i] & 0xff;
++
++ // immed[@bi, (b1 << 8) | b0]
++ // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV
++ ucode[offset++] = 0xf0;
++ ucode[offset++] = (b1 >> 4);
++ ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6);
++ ucode[offset++] = (i << 2) | 0x03;
++ ucode[offset++] = b0;
++
++ // immed_w1[@bi, (b3 << 8) | b2]
++ // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV
++ ucode[offset++] = 0xf4;
++ ucode[offset++] = 0x40 | (b3 >> 4);
++ ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6);
++ ucode[offset++] = (i << 2) | 0x03;
++ ucode[offset++] = b2;
++ }
++
++ // ctx_arb[kill]
++ ucode[offset++] = 0xe0;
++ ucode[offset++] = 0x00;
++ ucode[offset++] = 0x01;
++ ucode[offset++] = 0x00;
++ ucode[offset++] = 0x00;
++}
++
++static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c)
++{
++ int per_ctx_regs;
++ u32 *gpr_a;
++ u32 *gpr_b;
++ u8 *ucode;
++ int i;
++
++ gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL);
++ gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL);
++ ucode = kmalloc(513 * 5, GFP_KERNEL);
++ if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) {
++ kfree(ucode);
++ kfree(gpr_b);
++ kfree(gpr_a);
++ return 1;
++ }
++
++ per_ctx_regs = 16;
++ if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS)
++ per_ctx_regs = 32;
++
++ memset(gpr_a, 0, sizeof(gpr_a));
++ memset(gpr_b, 0, sizeof(gpr_b));
++ for (i = 0; i < 256; i++) {
++ struct ixp2000_reg_value *r = c->initial_reg_values + i;
++ u32 *bank;
++ int inc;
++ int j;
++
++ if (r->reg == -1)
++ break;
++
++ bank = (r->reg & 0x400) ? gpr_b : gpr_a;
++ inc = (r->reg & 0x80) ? 128 : per_ctx_regs;
++
++ j = r->reg & 0x7f;
++ while (j < 128) {
++ bank[j] = r->value;
++ j += inc;
++ }
++ }
++
++ generate_ucode(ucode, gpr_a, gpr_b);
++ ixp2000_uengine_load_microcode(uengine, ucode, 513);
++ ixp2000_uengine_init_context(uengine, 0, 0);
++ ixp2000_uengine_start_contexts(uengine, 0x01);
++ for (i = 0; i < 100; i++) {
++ u32 status;
++
++ status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS);
++ if (!(status & 0x80000000))
++ break;
++ }
++ ixp2000_uengine_stop_contexts(uengine, 0x01);
++
++ kfree(ucode);
++ kfree(gpr_b);
++ kfree(gpr_a);
++
++ return !!(i == 100);
++}
++
++int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c)
++{
++ int ctx;
++
++ if (!check_ixp_type(c))
++ return 1;
++
++ if (!(ixp2000_uengine_mask & (1 << uengine)))
++ return 1;
++
++ ixp2000_uengine_reset(1 << uengine);
++ ixp2000_uengine_set_mode(uengine, c->uengine_parameters);
++ if (set_initial_registers(uengine, c))
++ return 1;
++ ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns);
++
++ for (ctx = 0; ctx < 8; ctx++)
++ ixp2000_uengine_init_context(uengine, ctx, 0);
++
++ return 0;
++}
++EXPORT_SYMBOL(ixp2000_uengine_load);
++
++
++static int __init ixp2000_uengine_init(void)
++{
++ int uengine;
++ u32 value;
++
++ /*
++ * Determine number of microengines present.
++ */
++ switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) {
++ case 0: /* IXP2800 */
++ case 1: /* IXP2850 */
++ ixp2000_uengine_mask = 0x00ff00ff;
++ break;
++
++ case 2: /* IXP2400 */
++ ixp2000_uengine_mask = 0x000f000f;
++ break;
++
++ default:
++ printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
++ (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID));
++ ixp2000_uengine_mask = 0x00000000;
++ break;
++ }
++
++ /*
++ * Reset microengines.
++ */
++ ixp2000_reg_write(IXP2000_RESET1, ixp2000_uengine_mask);
++ ixp2000_reg_write(IXP2000_RESET1, 0);
++
++ /*
++ * Synchronise timestamp counters across all microengines.
++ */
++ value = ixp2000_reg_read(IXP2000_MISC_CONTROL);
++ ixp2000_reg_write(IXP2000_MISC_CONTROL, value & ~0x80);
++ for (uengine = 0; uengine < 32; uengine++) {
++ if (ixp2000_uengine_mask & (1 << uengine)) {
++ ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
++ ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
++ }
++ }
++ ixp2000_reg_write(IXP2000_MISC_CONTROL, value | 0x80);
++
++ return 0;
++}
++
++subsys_initcall(ixp2000_uengine_init);
+diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
+--- a/arch/arm/mach-ixp4xx/common.c
++++ b/arch/arm/mach-ixp4xx/common.c
+@@ -20,6 +20,7 @@
+ #include <linux/serial.h>
+ #include <linux/sched.h>
+ #include <linux/tty.h>
++#include <linux/platform_device.h>
+ #include <linux/serial_core.h>
+ #include <linux/bootmem.h>
+ #include <linux/interrupt.h>
+@@ -44,24 +45,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
+--- 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
+--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
++++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+@@ -10,7 +10,7 @@
+
+ #include <linux/tty.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+
+ #include <asm/hardware.h>
+@@ -227,23 +227,79 @@ void __init lh7a40x_init_board_irq (void
+ }
+
+ 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-h2.c b/arch/arm/mach-omap1/board-h2.c
+--- a/arch/arm/mach-omap1/board-h2.c
++++ b/arch/arm/mach-omap1/board-h2.c
+@@ -21,7 +21,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/delay.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
+--- a/arch/arm/mach-omap1/board-h3.c
++++ b/arch/arm/mach-omap1/board-h3.c
+@@ -19,7 +19,7 @@
+ #include <linux/init.h>
+ #include <linux/major.h>
+ #include <linux/kernel.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/errno.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
+--- a/arch/arm/mach-omap1/board-innovator.c
++++ b/arch/arm/mach-omap1/board-innovator.c
+@@ -18,7 +18,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/delay.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+@@ -103,8 +103,12 @@ static struct platform_device innovator_
+
+ /* 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-netstar.c b/arch/arm/mach-omap1/board-netstar.c
+--- a/arch/arm/mach-omap1/board-netstar.c
++++ b/arch/arm/mach-omap1/board-netstar.c
+@@ -11,7 +11,7 @@
+ */
+
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
+--- a/arch/arm/mach-omap1/board-osk.c
++++ b/arch/arm/mach-omap1/board-osk.c
+@@ -28,7 +28,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+
+ #include <linux/mtd/mtd.h>
+diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
+--- a/arch/arm/mach-omap1/board-perseus2.c
++++ b/arch/arm/mach-omap1/board-perseus2.c
+@@ -13,7 +13,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/delay.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+@@ -134,8 +134,12 @@ void omap_perseus2_init_irq(void)
+
+ /* 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/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
+--- a/arch/arm/mach-omap1/board-voiceblue.c
++++ b/arch/arm/mach-omap1/board-voiceblue.c
+@@ -13,7 +13,7 @@
+ */
+
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
+--- a/arch/arm/mach-omap1/devices.c
++++ b/arch/arm/mach-omap1/devices.c
+@@ -13,7 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
+--- a/arch/arm/mach-omap1/io.c
++++ b/arch/arm/mach-omap1/io.c
+@@ -26,27 +26,59 @@ extern void omap_sram_init(void);
+ * 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
+--- a/arch/arm/mach-pxa/corgi.c
++++ b/arch/arm/mach-pxa/corgi.c
+@@ -14,7 +14,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/major.h>
+ #include <linux/fs.h>
+ #include <linux/interrupt.h>
+@@ -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 @@ static struct pxamci_platform_data corgi
+ };
+
+
++/*
++ * 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 @@ static void __init corgi_init(void)
+
+ 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_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
+--- a/arch/arm/mach-pxa/corgi_lcd.c
++++ b/arch/arm/mach-pxa/corgi_lcd.c
+@@ -17,7 +17,7 @@
+
+ #include <linux/delay.h>
+ #include <linux/kernel.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <asm/arch/akita.h>
+ #include <asm/arch/corgi.h>
+diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
+--- a/arch/arm/mach-pxa/corgi_ssp.c
++++ b/arch/arm/mach-pxa/corgi_ssp.c
+@@ -15,7 +15,7 @@
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+
+@@ -222,24 +222,22 @@ static int corgi_ssp_remove(struct devic
+ 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
+--- a/arch/arm/mach-pxa/generic.c
++++ b/arch/arm/mach-pxa/generic.c
+@@ -20,9 +20,10 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_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 @@ EXPORT_SYMBOL(pxa_set_cken);
+ * 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 @@ static struct platform_device stuart_dev
+ .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 resource i2s_resources[] =
+ 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 @@ static struct platform_device *devices[]
+ &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
+--- a/arch/arm/mach-pxa/idp.c
++++ b/arch/arm/mach-pxa/idp.c
+@@ -18,7 +18,7 @@
+
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/fb.h>
+
+ #include <asm/setup.h>
+@@ -152,16 +152,17 @@ static void __init idp_init_irq(void)
+ }
+
+ 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
+--- a/arch/arm/mach-pxa/lubbock.c
++++ b/arch/arm/mach-pxa/lubbock.c
+@@ -14,7 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/sysdev.h>
+ #include <linux/major.h>
+ #include <linux/fb.h>
+@@ -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>
+
+@@ -174,7 +175,7 @@ static struct platform_device sa1111_dev
+ static struct resource smc91x_resources[] = {
+ [0] = {
+ .name = "smc91x-regs",
+- .start = 0x0c000000,
++ .start = 0x0c000c00,
+ .end = 0x0c0fffff,
+ .flags = IORESOURCE_MEM,
+ },
+@@ -223,18 +224,93 @@ static struct pxafb_mach_info sharp_lm8v
+ .lccr3 = LCCR3_PCP | LCCR3_Acb(255),
+ };
+
+-static int lubbock_mci_init(struct device *dev, irqreturn_t (*lubbock_detect_int)(int, void *, struct pt_regs *), void *data)
++#define MMC_POLL_RATE msecs_to_jiffies(1000)
++
++static void lubbock_mmc_poll(unsigned long);
++static irqreturn_t (*mmc_detect_int)(int, void *, struct pt_regs *);
++
++static struct timer_list mmc_timer = {
++ .function = lubbock_mmc_poll,
++};
++
++static void lubbock_mmc_poll(unsigned long data)
++{
++ unsigned long flags;
++
++ /* clear any previous irq state, then ... */
++ local_irq_save(flags);
++ LUB_IRQ_SET_CLR &= ~(1 << 0);
++ local_irq_restore(flags);
++
++ /* poll until mmc/sd card is removed */
++ if (LUB_IRQ_SET_CLR & (1 << 0))
++ mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE);
++ else {
++ (void) mmc_detect_int(LUBBOCK_SD_IRQ, (void *)data, NULL);
++ enable_irq(LUBBOCK_SD_IRQ);
++ }
++}
++
++static irqreturn_t lubbock_detect_int(int irq, void *data, struct pt_regs *regs)
++{
++ /* IRQ is level triggered; disable, and poll for removal */
++ disable_irq(irq);
++ mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE);
++
++ return mmc_detect_int(irq, data, regs);
++}
++
++static int lubbock_mci_init(struct device *dev,
++ irqreturn_t (*detect_int)(int, void *, struct pt_regs *),
++ void *data)
+ {
+ /* setup GPIO for PXA25x MMC controller */
+ pxa_gpio_mode(GPIO6_MMCCLK_MD);
+ pxa_gpio_mode(GPIO8_MMCCS0_MD);
+
+- return 0;
++ /* detect card insert/eject */
++ mmc_detect_int = detect_int;
++ init_timer(&mmc_timer);
++ mmc_timer.data = (unsigned long) data;
++ return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int,
++ SA_SAMPLE_RANDOM, "lubbock-sd-detect", data);
++}
++
++static int lubbock_mci_get_ro(struct device *dev)
++{
++ return (LUB_MISC_RD & (1 << 2)) != 0;
++}
++
++static void lubbock_mci_exit(struct device *dev, void *data)
++{
++ free_irq(LUBBOCK_SD_IRQ, data);
++ del_timer_sync(&mmc_timer);
+ }
+
+ static struct pxamci_platform_data lubbock_mci_platform_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
++ .detect_delay = 1,
+ .init = lubbock_mci_init,
++ .get_ro = lubbock_mci_get_ro,
++ .exit = lubbock_mci_exit,
++};
++
++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)
+@@ -242,11 +318,17 @@ 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
+--- a/arch/arm/mach-pxa/mainstone.c
++++ b/arch/arm/mach-pxa/mainstone.c
+@@ -14,7 +14,7 @@
+ */
+
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/sysdev.h>
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+@@ -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 @@ static struct pxamci_platform_data mains
+ .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 @@ static void __init mainstone_init(void)
+ 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
+--- a/arch/arm/mach-pxa/poodle.c
++++ b/arch/arm/mach-pxa/poodle.c
+@@ -16,7 +16,7 @@
+ */
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/fb.h>
+
+ #include <asm/hardware.h>
+@@ -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 @@ static struct pxamci_platform_data poodl
+
+
+ /*
++ * 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 @@ static void __init poodle_init(void)
+
+ 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
+--- a/arch/arm/mach-pxa/pxa25x.c
++++ b/arch/arm/mach-pxa/pxa25x.c
+@@ -129,7 +129,7 @@ void pxa_cpu_pm_enter(suspend_state_t st
+ 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
+--- a/arch/arm/mach-pxa/pxa27x.c
++++ b/arch/arm/mach-pxa/pxa27x.c
+@@ -16,7 +16,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/pm.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+@@ -157,7 +157,7 @@ void pxa_cpu_pm_enter(suspend_state_t st
+ 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
+--- 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 @@ ENTRY(pxa_cpu_suspend)
+ 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 @@ ENTRY(pxa_cpu_suspend)
+ @ (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
+--- a/arch/arm/mach-pxa/spitz.c
++++ b/arch/arm/mach-pxa/spitz.c
+@@ -14,7 +14,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/delay.h>
+ #include <linux/major.h>
+ #include <linux/fs.h>
+@@ -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 @@ static struct pxamci_platform_data spitz
+
+
+ /*
++ * 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 @@ static void __init common_init(void)
+
+ 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
+--- 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-realview/Kconfig b/arch/arm/mach-realview/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/Kconfig
+@@ -0,0 +1,11 @@
++menu "RealView platform type"
++ depends on ARCH_REALVIEW
++
++config MACH_REALVIEW_EB
++ bool "Support RealView/EB platform"
++ default n
++ select ARM_GIC
++ help
++ Include support for the ARM(R) RealView Emulation Baseboard platform.
++
++endmenu
+diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/Makefile
+@@ -0,0 +1,6 @@
++#
++# Makefile for the linux kernel.
++#
++
++obj-y := core.o clock.o
++obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
+diff --git a/arch/arm/mach-realview/Makefile.boot b/arch/arm/mach-realview/Makefile.boot
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/Makefile.boot
+@@ -0,0 +1,4 @@
++ zreladdr-y := 0x00008000
++params_phys-y := 0x00000100
++initrd_phys-y := 0x00800000
++
+diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/clock.c
+@@ -0,0 +1,145 @@
++/*
++ * linux/arch/arm/mach-realview/clock.c
++ *
++ * Copyright (C) 2004 ARM Limited.
++ * Written by Deep Blue Solutions Limited.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#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 <asm/hardware/icst307.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)
++{
++ int ret = -EIO;
++
++ if (clk->setvco) {
++ struct icst307_vco vco;
++
++ vco = icst307_khz_to_vco(clk->params, rate / 1000);
++ clk->rate = icst307_khz(clk->params, vco) * 1000;
++
++ printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
++ clk->name, vco.s, vco.r, vco.v);
++
++ clk->setvco(clk, vco);
++ ret = 0;
++ }
++ return ret;
++}
++EXPORT_SYMBOL(clk_set_rate);
++
++/*
++ * These are fixed clocks.
++ */
++static struct clk kmi_clk = {
++ .name = "KMIREFCLK",
++ .rate = 24000000,
++};
++
++static struct clk uart_clk = {
++ .name = "UARTCLK",
++ .rate = 24000000,
++};
++
++static struct clk mmci_clk = {
++ .name = "MCLK",
++ .rate = 33000000,
++};
++
++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)
++{
++ clk_register(&kmi_clk);
++ clk_register(&uart_clk);
++ clk_register(&mmci_clk);
++ return 0;
++}
++arch_initcall(clk_init);
+diff --git a/arch/arm/mach-realview/clock.h b/arch/arm/mach-realview/clock.h
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/clock.h
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/arm/mach-realview/clock.h
++ *
++ * Copyright (C) 2004 ARM Limited.
++ * Written by Deep Blue Solutions Limited.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++struct module;
++struct icst307_params;
++
++struct clk {
++ struct list_head node;
++ unsigned long rate;
++ struct module *owner;
++ const char *name;
++ const struct icst307_params *params;
++ void *data;
++ void (*setvco)(struct clk *, struct icst307_vco vco);
++};
++
++int clk_register(struct clk *clk);
++void clk_unregister(struct clk *clk);
+diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/core.c
+@@ -0,0 +1,605 @@
++/*
++ * linux/arch/arm/mach-realview/core.c
++ *
++ * Copyright (C) 1999 - 2003 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * 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/init.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/sysdev.h>
++#include <linux/interrupt.h>
++
++#include <asm/system.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/leds.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/amba.h>
++#include <asm/hardware/amba_clcd.h>
++#include <asm/hardware/arm_timer.h>
++#include <asm/hardware/icst307.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++#include <asm/mach/map.h>
++#include <asm/mach/mmc.h>
++
++#include <asm/hardware/gic.h>
++
++#include "core.h"
++#include "clock.h"
++
++#define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
++
++/*
++ * This is the RealView sched_clock implementation. This has
++ * a resolution of 41.7ns, and a maximum value of about 179s.
++ */
++unsigned long long sched_clock(void)
++{
++ unsigned long long v;
++
++ v = (unsigned long long)readl(REALVIEW_REFCOUNTER) * 125;
++ do_div(v, 3);
++
++ return v;
++}
++
++
++#define REALVIEW_FLASHCTRL (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_FLASH_OFFSET)
++
++static int realview_flash_init(void)
++{
++ u32 val;
++
++ val = __raw_readl(REALVIEW_FLASHCTRL);
++ val &= ~REALVIEW_FLASHPROG_FLVPPEN;
++ __raw_writel(val, REALVIEW_FLASHCTRL);
++
++ return 0;
++}
++
++static void realview_flash_exit(void)
++{
++ u32 val;
++
++ val = __raw_readl(REALVIEW_FLASHCTRL);
++ val &= ~REALVIEW_FLASHPROG_FLVPPEN;
++ __raw_writel(val, REALVIEW_FLASHCTRL);
++}
++
++static void realview_flash_set_vpp(int on)
++{
++ u32 val;
++
++ val = __raw_readl(REALVIEW_FLASHCTRL);
++ if (on)
++ val |= REALVIEW_FLASHPROG_FLVPPEN;
++ else
++ val &= ~REALVIEW_FLASHPROG_FLVPPEN;
++ __raw_writel(val, REALVIEW_FLASHCTRL);
++}
++
++static struct flash_platform_data realview_flash_data = {
++ .map_name = "cfi_probe",
++ .width = 4,
++ .init = realview_flash_init,
++ .exit = realview_flash_exit,
++ .set_vpp = realview_flash_set_vpp,
++};
++
++static struct resource realview_flash_resource = {
++ .start = REALVIEW_FLASH_BASE,
++ .end = REALVIEW_FLASH_BASE + REALVIEW_FLASH_SIZE,
++ .flags = IORESOURCE_MEM,
++};
++
++struct platform_device realview_flash_device = {
++ .name = "armflash",
++ .id = 0,
++ .dev = {
++ .platform_data = &realview_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &realview_flash_resource,
++};
++
++static struct resource realview_smc91x_resources[] = {
++ [0] = {
++ .start = REALVIEW_ETH_BASE,
++ .end = REALVIEW_ETH_BASE + SZ_64K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_ETH,
++ .end = IRQ_ETH,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device realview_smc91x_device = {
++ .name = "smc91x",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(realview_smc91x_resources),
++ .resource = realview_smc91x_resources,
++};
++
++#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
++
++static unsigned int realview_mmc_status(struct device *dev)
++{
++ struct amba_device *adev = container_of(dev, struct amba_device, dev);
++ u32 mask;
++
++ if (adev->res.start == REALVIEW_MMCI0_BASE)
++ mask = 1;
++ else
++ mask = 2;
++
++ return readl(REALVIEW_SYSMCI) & mask;
++}
++
++struct mmc_platform_data realview_mmc0_plat_data = {
++ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
++ .status = realview_mmc_status,
++};
++
++struct mmc_platform_data realview_mmc1_plat_data = {
++ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
++ .status = realview_mmc_status,
++};
++
++/*
++ * Clock handling
++ */
++static const struct icst307_params realview_oscvco_params = {
++ .ref = 24000,
++ .vco_max = 200000,
++ .vd_min = 4 + 8,
++ .vd_max = 511 + 8,
++ .rd_min = 1 + 2,
++ .rd_max = 127 + 2,
++};
++
++static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco)
++{
++ void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET;
++ void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC1_OFFSET;
++ u32 val;
++
++ val = readl(sys_osc) & ~0x7ffff;
++ val |= vco.v | (vco.r << 9) | (vco.s << 16);
++
++ writel(0xa05f, sys_lock);
++ writel(val, sys_osc);
++ writel(0, sys_lock);
++}
++
++struct clk realview_clcd_clk = {
++ .name = "CLCDCLK",
++ .params = &realview_oscvco_params,
++ .setvco = realview_oscvco_set,
++};
++
++/*
++ * CLCD support.
++ */
++#define SYS_CLCD_MODE_MASK (3 << 0)
++#define SYS_CLCD_MODE_888 (0 << 0)
++#define SYS_CLCD_MODE_5551 (1 << 0)
++#define SYS_CLCD_MODE_565_RLSB (2 << 0)
++#define SYS_CLCD_MODE_565_BLSB (3 << 0)
++#define SYS_CLCD_NLCDIOON (1 << 2)
++#define SYS_CLCD_VDDPOSSWITCH (1 << 3)
++#define SYS_CLCD_PWR3V5SWITCH (1 << 4)
++#define SYS_CLCD_ID_MASK (0x1f << 8)
++#define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8)
++#define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8)
++#define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8)
++#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)
++#define SYS_CLCD_ID_VGA (0x1f << 8)
++
++static struct clcd_panel vga = {
++ .mode = {
++ .name = "VGA",
++ .refresh = 60,
++ .xres = 640,
++ .yres = 480,
++ .pixclock = 39721,
++ .left_margin = 40,
++ .right_margin = 24,
++ .upper_margin = 32,
++ .lower_margin = 11,
++ .hsync_len = 96,
++ .vsync_len = 2,
++ .sync = 0,
++ .vmode = FB_VMODE_NONINTERLACED,
++ },
++ .width = -1,
++ .height = -1,
++ .tim2 = TIM2_BCD | TIM2_IPC,
++ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
++ .bpp = 16,
++};
++
++static struct clcd_panel sanyo_3_8_in = {
++ .mode = {
++ .name = "Sanyo QVGA",
++ .refresh = 116,
++ .xres = 320,
++ .yres = 240,
++ .pixclock = 100000,
++ .left_margin = 6,
++ .right_margin = 6,
++ .upper_margin = 5,
++ .lower_margin = 5,
++ .hsync_len = 6,
++ .vsync_len = 6,
++ .sync = 0,
++ .vmode = FB_VMODE_NONINTERLACED,
++ },
++ .width = -1,
++ .height = -1,
++ .tim2 = TIM2_BCD,
++ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
++ .bpp = 16,
++};
++
++static struct clcd_panel sanyo_2_5_in = {
++ .mode = {
++ .name = "Sanyo QVGA Portrait",
++ .refresh = 116,
++ .xres = 240,
++ .yres = 320,
++ .pixclock = 100000,
++ .left_margin = 20,
++ .right_margin = 10,
++ .upper_margin = 2,
++ .lower_margin = 2,
++ .hsync_len = 10,
++ .vsync_len = 2,
++ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .vmode = FB_VMODE_NONINTERLACED,
++ },
++ .width = -1,
++ .height = -1,
++ .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC,
++ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
++ .bpp = 16,
++};
++
++static struct clcd_panel epson_2_2_in = {
++ .mode = {
++ .name = "Epson QCIF",
++ .refresh = 390,
++ .xres = 176,
++ .yres = 220,
++ .pixclock = 62500,
++ .left_margin = 3,
++ .right_margin = 2,
++ .upper_margin = 1,
++ .lower_margin = 0,
++ .hsync_len = 3,
++ .vsync_len = 2,
++ .sync = 0,
++ .vmode = FB_VMODE_NONINTERLACED,
++ },
++ .width = -1,
++ .height = -1,
++ .tim2 = TIM2_BCD | TIM2_IPC,
++ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
++ .bpp = 16,
++};
++
++/*
++ * Detect which LCD panel is connected, and return the appropriate
++ * clcd_panel structure. Note: we do not have any information on
++ * the required timings for the 8.4in panel, so we presently assume
++ * VGA timings.
++ */
++static struct clcd_panel *realview_clcd_panel(void)
++{
++ void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
++ struct clcd_panel *panel = &vga;
++ u32 val;
++
++ val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
++ if (val == SYS_CLCD_ID_SANYO_3_8)
++ panel = &sanyo_3_8_in;
++ else if (val == SYS_CLCD_ID_SANYO_2_5)
++ panel = &sanyo_2_5_in;
++ else if (val == SYS_CLCD_ID_EPSON_2_2)
++ panel = &epson_2_2_in;
++ else if (val == SYS_CLCD_ID_VGA)
++ panel = &vga;
++ else {
++ printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
++ val);
++ panel = &vga;
++ }
++
++ return panel;
++}
++
++/*
++ * Disable all display connectors on the interface module.
++ */
++static void realview_clcd_disable(struct clcd_fb *fb)
++{
++ void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
++ u32 val;
++
++ val = readl(sys_clcd);
++ val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
++ writel(val, sys_clcd);
++}
++
++/*
++ * Enable the relevant connector on the interface module.
++ */
++static void realview_clcd_enable(struct clcd_fb *fb)
++{
++ void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
++ u32 val;
++
++ val = readl(sys_clcd);
++ val &= ~SYS_CLCD_MODE_MASK;
++
++ switch (fb->fb.var.green.length) {
++ case 5:
++ val |= SYS_CLCD_MODE_5551;
++ break;
++ case 6:
++ val |= SYS_CLCD_MODE_565_RLSB;
++ break;
++ case 8:
++ val |= SYS_CLCD_MODE_888;
++ break;
++ }
++
++ /*
++ * Set the MUX
++ */
++ writel(val, sys_clcd);
++
++ /*
++ * And now enable the PSUs
++ */
++ val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
++ writel(val, sys_clcd);
++}
++
++static unsigned long framesize = SZ_1M;
++
++static int realview_clcd_setup(struct clcd_fb *fb)
++{
++ dma_addr_t dma;
++
++ fb->panel = realview_clcd_panel();
++
++ fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
++ &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 = framesize;
++
++ return 0;
++}
++
++static int realview_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 realview_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);
++}
++
++struct clcd_board clcd_plat_data = {
++ .name = "RealView",
++ .check = clcdfb_check,
++ .decode = clcdfb_decode,
++ .disable = realview_clcd_disable,
++ .enable = realview_clcd_enable,
++ .setup = realview_clcd_setup,
++ .mmap = realview_clcd_mmap,
++ .remove = realview_clcd_remove,
++};
++
++#ifdef CONFIG_LEDS
++#define VA_LEDS_BASE (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET)
++
++void realview_leds_event(led_event_t ledevt)
++{
++ unsigned long flags;
++ u32 val;
++
++ local_irq_save(flags);
++ val = readl(VA_LEDS_BASE);
++
++ switch (ledevt) {
++ case led_idle_start:
++ val = val & ~REALVIEW_SYS_LED0;
++ break;
++
++ case led_idle_end:
++ val = val | REALVIEW_SYS_LED0;
++ break;
++
++ case led_timer:
++ val = val ^ REALVIEW_SYS_LED1;
++ break;
++
++ case led_halted:
++ val = 0;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(val, VA_LEDS_BASE);
++ local_irq_restore(flags);
++}
++#endif /* CONFIG_LEDS */
++
++/*
++ * Where is the timer (VA)?
++ */
++#define TIMER0_VA_BASE __io_address(REALVIEW_TIMER0_1_BASE)
++#define TIMER1_VA_BASE (__io_address(REALVIEW_TIMER0_1_BASE) + 0x20)
++#define TIMER2_VA_BASE __io_address(REALVIEW_TIMER2_3_BASE)
++#define TIMER3_VA_BASE (__io_address(REALVIEW_TIMER2_3_BASE) + 0x20)
++
++/*
++ * How long is the timer interval?
++ */
++#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
++#if TIMER_INTERVAL >= 0x100000
++#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
++#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
++#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
++#elif TIMER_INTERVAL >= 0x10000
++#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */
++#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
++#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
++#else
++#define TIMER_RELOAD (TIMER_INTERVAL)
++#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
++#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
++#endif
++
++/*
++ * Returns number of ms since last clock interrupt. Note that interrupts
++ * will have been disabled by do_gettimeoffset()
++ */
++static unsigned long realview_gettimeoffset(void)
++{
++ unsigned long ticks1, ticks2, status;
++
++ /*
++ * Get the current number of ticks. Note that there is a race
++ * condition between us reading the timer and checking for
++ * an interrupt. We get around this by ensuring that the
++ * counter has not reloaded between our two reads.
++ */
++ ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
++ do {
++ ticks1 = ticks2;
++ status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
++ + ((IRQ_TIMERINT0_1 >> 5) << 2));
++ ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
++ } while (ticks2 > ticks1);
++
++ /*
++ * Number of ticks since last interrupt.
++ */
++ ticks1 = TIMER_RELOAD - ticks2;
++
++ /*
++ * Interrupt pending? If so, we've reloaded once already.
++ *
++ * FIXME: Need to check this is effectively timer 0 that expires
++ */
++ if (status & IRQMASK_TIMERINT0_1)
++ ticks1 += TIMER_RELOAD;
++
++ /*
++ * Convert the ticks to usecs
++ */
++ return TICKS2USECS(ticks1);
++}
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ write_seqlock(&xtime_lock);
++
++ // ...clear the interrupt
++ writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
++
++ timer_tick(regs);
++
++ write_sequnlock(&xtime_lock);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction realview_timer_irq = {
++ .name = "RealView Timer Tick",
++ .flags = SA_INTERRUPT | SA_TIMER,
++ .handler = realview_timer_interrupt,
++};
++
++/*
++ * Set up timer interrupt, and return the current time in seconds.
++ */
++static void __init realview_timer_init(void)
++{
++ u32 val;
++
++ /*
++ * set clock frequency:
++ * REALVIEW_REFCLK is 32KHz
++ * REALVIEW_TIMCLK is 1MHz
++ */
++ val = readl(__io_address(REALVIEW_SCTL_BASE));
++ writel((REALVIEW_TIMCLK << REALVIEW_TIMER1_EnSel) |
++ (REALVIEW_TIMCLK << REALVIEW_TIMER2_EnSel) |
++ (REALVIEW_TIMCLK << REALVIEW_TIMER3_EnSel) |
++ (REALVIEW_TIMCLK << REALVIEW_TIMER4_EnSel) | val,
++ __io_address(REALVIEW_SCTL_BASE));
++
++ /*
++ * Initialise to a known state (all timers off)
++ */
++ writel(0, TIMER0_VA_BASE + TIMER_CTRL);
++ writel(0, TIMER1_VA_BASE + TIMER_CTRL);
++ writel(0, TIMER2_VA_BASE + TIMER_CTRL);
++ writel(0, TIMER3_VA_BASE + TIMER_CTRL);
++
++ writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
++ writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
++ writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
++ TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
++
++ /*
++ * Make irqs happen for the system timer
++ */
++ setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
++}
++
++struct sys_timer realview_timer = {
++ .init = realview_timer_init,
++ .offset = realview_gettimeoffset,
++};
+diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/core.h
+@@ -0,0 +1,118 @@
++/*
++ * linux/arch/arm/mach-realview/core.h
++ *
++ * Copyright (C) 2004 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * 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_ARCH_REALVIEW_H
++#define __ASM_ARCH_REALVIEW_H
++
++#include <asm/hardware/amba.h>
++#include <asm/io.h>
++
++#define __io_address(n) __io(IO_ADDRESS(n))
++
++extern struct sys_timer realview_timer;
++
++#define AMBA_DEVICE(name,busid,base,plat) \
++static struct amba_device name##_device = { \
++ .dev = { \
++ .coherent_dma_mask = ~0, \
++ .bus_id = busid, \
++ .platform_data = plat, \
++ }, \
++ .res = { \
++ .start = REALVIEW_##base##_BASE, \
++ .end = (REALVIEW_##base##_BASE) + SZ_4K - 1,\
++ .flags = IORESOURCE_MEM, \
++ }, \
++ .dma_mask = ~0, \
++ .irq = base##_IRQ, \
++ /* .dma = base##_DMA,*/ \
++}
++
++/*
++ * These devices are connected via the core APB bridge
++ */
++#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ }
++#define GPIO2_DMA { 0, 0 }
++#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ }
++#define GPIO3_DMA { 0, 0 }
++
++#define AACI_IRQ { IRQ_AACI, NO_IRQ }
++#define AACI_DMA { 0x80, 0x81 }
++#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_MMCI0B }
++#define MMCI0_DMA { 0x84, 0 }
++#define KMI0_IRQ { IRQ_KMI0, NO_IRQ }
++#define KMI0_DMA { 0, 0 }
++#define KMI1_IRQ { IRQ_KMI1, NO_IRQ }
++#define KMI1_DMA { 0, 0 }
++
++/*
++ * These devices are connected directly to the multi-layer AHB switch
++ */
++#define SMC_IRQ { NO_IRQ, NO_IRQ }
++#define SMC_DMA { 0, 0 }
++#define MPMC_IRQ { NO_IRQ, NO_IRQ }
++#define MPMC_DMA { 0, 0 }
++#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }
++#define CLCD_DMA { 0, 0 }
++#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }
++#define DMAC_DMA { 0, 0 }
++
++/*
++ * These devices are connected via the core APB bridge
++ */
++#define SCTL_IRQ { NO_IRQ, NO_IRQ }
++#define SCTL_DMA { 0, 0 }
++#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }
++#define WATCHDOG_DMA { 0, 0 }
++#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }
++#define GPIO0_DMA { 0, 0 }
++#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }
++#define GPIO1_DMA { 0, 0 }
++#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }
++#define RTC_DMA { 0, 0 }
++
++/*
++ * These devices are connected via the DMA APB bridge
++ */
++#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }
++#define SCI_DMA { 7, 6 }
++#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }
++#define UART0_DMA { 15, 14 }
++#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }
++#define UART1_DMA { 13, 12 }
++#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }
++#define UART2_DMA { 11, 10 }
++#define UART3_IRQ { IRQ_UART3, NO_IRQ }
++#define UART3_DMA { 0x86, 0x87 }
++#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }
++#define SSP_DMA { 9, 8 }
++
++
++extern struct platform_device realview_flash_device;
++extern struct platform_device realview_smc91x_device;
++extern struct mmc_platform_data realview_mmc0_plat_data;
++extern struct mmc_platform_data realview_mmc1_plat_data;
++extern struct clk realview_clcd_clk;
++extern struct clcd_board clcd_plat_data;
++
++extern void realview_leds_event(led_event_t ledevt);
++
++#endif
+diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
+new file mode 100644
+--- /dev/null
++++ b/arch/arm/mach-realview/realview_eb.c
+@@ -0,0 +1,142 @@
++/*
++ * linux/arch/arm/mach-realview/realview_eb.c
++ *
++ * Copyright (C) 2004 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * 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/init.h>
++#include <linux/platform_device.h>
++#include <linux/sysdev.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/leds.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/gic.h>
++#include <asm/hardware/amba.h>
++#include <asm/hardware/icst307.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/mmc.h>
++
++#include <asm/arch/irqs.h>
++
++#include "core.h"
++#include "clock.h"
++
++static struct map_desc realview_eb_io_desc[] __initdata = {
++ { IO_ADDRESS(REALVIEW_SYS_BASE), REALVIEW_SYS_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(REALVIEW_GIC_CPU_BASE), REALVIEW_GIC_CPU_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(REALVIEW_GIC_DIST_BASE), REALVIEW_GIC_DIST_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(REALVIEW_SCTL_BASE), REALVIEW_SCTL_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(REALVIEW_TIMER0_1_BASE), REALVIEW_TIMER0_1_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(REALVIEW_TIMER2_3_BASE), REALVIEW_TIMER2_3_BASE, SZ_4K, MT_DEVICE },
++#ifdef CONFIG_DEBUG_LL
++ { IO_ADDRESS(REALVIEW_UART0_BASE), REALVIEW_UART0_BASE, SZ_4K, MT_DEVICE },
++#endif
++};
++
++static void __init realview_eb_map_io(void)
++{
++ iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc));
++}
++
++/* FPGA Primecells */
++AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
++AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
++AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL);
++AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL);
++AMBA_DEVICE(uart3, "fpga:09", UART3, NULL);
++
++/* DevChip Primecells */
++AMBA_DEVICE(smc, "dev:00", SMC, NULL);
++AMBA_DEVICE(clcd, "dev:20", CLCD, &clcd_plat_data);
++AMBA_DEVICE(dmac, "dev:30", DMAC, NULL);
++AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL);
++AMBA_DEVICE(wdog, "dev:e1", WATCHDOG, NULL);
++AMBA_DEVICE(gpio0, "dev:e4", GPIO0, NULL);
++AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL);
++AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL);
++AMBA_DEVICE(rtc, "dev:e8", RTC, NULL);
++AMBA_DEVICE(sci0, "dev:f0", SCI, NULL);
++AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
++AMBA_DEVICE(uart1, "dev:f2", UART1, NULL);
++AMBA_DEVICE(uart2, "dev:f3", UART2, NULL);
++AMBA_DEVICE(ssp0, "dev:f4", SSP, NULL);
++
++static struct amba_device *amba_devs[] __initdata = {
++ &dmac_device,
++ &uart0_device,
++ &uart1_device,
++ &uart2_device,
++ &uart3_device,
++ &smc_device,
++ &clcd_device,
++ &sctl_device,
++ &wdog_device,
++ &gpio0_device,
++ &gpio1_device,
++ &gpio2_device,
++ &rtc_device,
++ &sci0_device,
++ &ssp0_device,
++ &aaci_device,
++ &mmc0_device,
++ &kmi0_device,
++ &kmi1_device,
++};
++
++static void __init gic_init_irq(void)
++{
++ gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
++ gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
++}
++
++static void __init realview_eb_init(void)
++{
++ int i;
++
++ clk_register(&realview_clcd_clk);
++
++ platform_device_register(&realview_flash_device);
++ platform_device_register(&realview_smc91x_device);
++
++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
++ struct amba_device *d = amba_devs[i];
++ amba_device_register(d, &iomem_resource);
++ }
++
++#ifdef CONFIG_LEDS
++ leds_event = realview_leds_event;
++#endif
++}
++
++MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
++ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
++ .phys_ram = 0x00000000,
++ .phys_io = REALVIEW_UART0_BASE,
++ .io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc,
++ .boot_params = 0x00000100,
++ .map_io = realview_eb_map_io,
++ .init_irq = gic_init_irq,
++ .timer = &realview_timer,
++ .init_machine = realview_eb_init,
++MACHINE_END
+diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
+--- a/arch/arm/mach-rpc/riscpc.c
++++ b/arch/arm/mach-rpc/riscpc.c
+@@ -61,9 +61,22 @@ static int __init parse_tag_acorn(const
+ __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/clock.c b/arch/arm/mach-s3c2410/clock.c
+--- a/arch/arm/mach-s3c2410/clock.c
++++ b/arch/arm/mach-s3c2410/clock.c
+@@ -32,7 +32,7 @@
+ #include <linux/list.h>
+ #include <linux/errno.h>
+ #include <linux/err.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/sysdev.h>
+
+ #include <linux/interrupt.h>
+diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
+--- a/arch/arm/mach-s3c2410/cpu.c
++++ b/arch/arm/mach-s3c2410/cpu.c
+@@ -26,7 +26,7 @@
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
+--- 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
+--- a/arch/arm/mach-s3c2410/devs.c
++++ b/arch/arm/mach-s3c2410/devs.c
+@@ -24,7 +24,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -47,7 +47,7 @@ struct platform_device *s3c24xx_uart_dev
+ 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 @@ EXPORT_SYMBOL(s3c_device_usb);
+ 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 @@ struct platform_device s3c_device_lcd =
+
+ 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 @@ EXPORT_SYMBOL(s3c_device_nand);
+ 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 @@ EXPORT_SYMBOL(s3c_device_usbgadget);
+ 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 @@ EXPORT_SYMBOL(s3c_device_wdt);
+ 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 @@ EXPORT_SYMBOL(s3c_device_i2c);
+ 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 @@ EXPORT_SYMBOL(s3c_device_rtc);
+ 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 @@ struct platform_device s3c_device_adc =
+ 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 @@ EXPORT_SYMBOL(s3c_device_timer3);
+ 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/devs.h b/arch/arm/mach-s3c2410/devs.h
+--- a/arch/arm/mach-s3c2410/devs.h
++++ b/arch/arm/mach-s3c2410/devs.h
+@@ -15,6 +15,7 @@
+ * 10-Feb-2005 BJD Added camera from guillaume.gourat at nexvision.tv
+ */
+ #include <linux/config.h>
++#include <linux/platform_device.h>
+
+ extern struct platform_device *s3c24xx_uart_devs[];
+
+diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
+--- 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 @@ void s3c2410_gpio_cfgpin(unsigned int pi
+ 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-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
+--- a/arch/arm/mach-s3c2410/mach-anubis.c
++++ b/arch/arm/mach-s3c2410/mach-anubis.c
+@@ -21,7 +21,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
+--- 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>
+@@ -40,7 +41,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dm9000.h>
+
+ #include <asm/mach/arch.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 @@ static struct s3c2410_platform_i2c bast_
+ .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 @@ static void __init bast_map_io(void)
+ 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 at simtec.co.uk> */
+@@ -463,5 +502,6 @@ MACHINE_START(BAST, "Simtec-BAST")
+ .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
+--- 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>
+@@ -33,6 +34,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
++#include <linux/platform_device.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -164,7 +166,7 @@ static void __init h1940_init_irq(void)
+
+ 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-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
+--- a/arch/arm/mach-s3c2410/mach-n30.c
++++ b/arch/arm/mach-s3c2410/mach-n30.c
+@@ -20,7 +20,7 @@
+ #include <linux/timer.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/kthread.h>
+
+ #include <asm/mach/arch.h>
+diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
+--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
++++ b/arch/arm/mach-s3c2410/mach-nexcoder.c
+@@ -19,7 +19,7 @@
+ #include <linux/timer.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <linux/mtd/map.h>
+
+diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
+--- a/arch/arm/mach-s3c2410/mach-otom.c
++++ b/arch/arm/mach-s3c2410/mach-otom.c
+@@ -15,7 +15,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
+--- a/arch/arm/mach-s3c2410/mach-rx3715.c
++++ b/arch/arm/mach-s3c2410/mach-rx3715.c
+@@ -17,6 +17,7 @@
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ * 14-Mar-2005 BJD Fixed __iomem warnings
+ * 20-Sep-2005 BJD Added static to non-exported items
++ * 31-Oct-2005 BJD Added LCD setup for framebuffer
+ */
+
+ #include <linux/kernel.h>
+@@ -27,6 +28,7 @@
+ #include <linux/init.h>
+ #include <linux/tty.h>
+ #include <linux/console.h>
++#include <linux/platform_device.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial.h>
+
+@@ -42,6 +44,9 @@
+
+ #include <asm/arch/regs-serial.h>
+ #include <asm/arch/regs-gpio.h>
++#include <asm/arch/regs-lcd.h>
++
++#include <asm/arch/fb.h>
+
+ #include "clock.h"
+ #include "devs.h"
+@@ -96,6 +101,66 @@ static struct s3c2410_uartcfg rx3715_uar
+ }
+ };
+
++/* framebuffer lcd controller information */
++
++static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
++ .regs = {
++ .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \
++ S3C2410_LCDCON1_TFT | \
++ S3C2410_LCDCON1_CLKVAL(0x0C),
++
++ .lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \
++ S3C2410_LCDCON2_LINEVAL(319) | \
++ S3C2410_LCDCON2_VFPD(6) | \
++ S3C2410_LCDCON2_VSPW(2),
++
++ .lcdcon3 = S3C2410_LCDCON3_HBPD(35) | \
++ S3C2410_LCDCON3_HOZVAL(239) | \
++ S3C2410_LCDCON3_HFPD(35),
++
++ .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | \
++ S3C2410_LCDCON4_HSPW(7),
++
++ .lcdcon5 = S3C2410_LCDCON5_INVVLINE |
++ S3C2410_LCDCON5_FRM565 |
++ S3C2410_LCDCON5_HWSWP,
++ },
++
++ .lpcsel = 0xf82,
++
++ .gpccon = 0xaa955699,
++ .gpccon_mask = 0xffc003cc,
++ .gpcup = 0x0000ffff,
++ .gpcup_mask = 0xffffffff,
++
++ .gpdcon = 0xaa95aaa1,
++ .gpdcon_mask = 0xffc0fff0,
++ .gpdup = 0x0000faff,
++ .gpdup_mask = 0xffffffff,
++
++ .fixed_syncs = 1,
++ .width = 240,
++ .height = 320,
++
++ .xres = {
++ .min = 240,
++ .max = 240,
++ .defval = 240,
++ },
++
++ .yres = {
++ .max = 320,
++ .min = 320,
++ .defval = 320,
++ },
++
++ .bpp = {
++ .min = 16,
++ .max = 16,
++ .defval = 16,
++ },
++};
++
+ static struct platform_device *rx3715_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_lcd,
+@@ -122,14 +187,12 @@ static void __init rx3715_init_irq(void)
+ s3c24xx_init_irq();
+ }
+
+-#ifdef CONFIG_PM
+ static void __init rx3715_init_machine(void)
+ {
+ s3c2410_pm_init();
++ s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
+ }
+-#else
+-#define rx3715_init_machine NULL
+-#endif
++
+
+ MACHINE_START(RX3715, "IPAQ-RX3715")
+ /* Maintainer: Ben Dooks <ben at fluff.org> */
+diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
+--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
++++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
+@@ -38,6 +38,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
++#include <linux/platform_device.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
+--- 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>
+@@ -27,6 +28,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
++#include <linux/platform_device.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -41,7 +43,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 +91,70 @@ static struct s3c2410_uartcfg smdk2440_u
+ }
+ };
+
++/* 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 +190,8 @@ static void __init smdk2440_machine_init
+ 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-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
+--- a/arch/arm/mach-s3c2410/s3c2410.c
++++ b/arch/arm/mach-s3c2410/s3c2410.c
+@@ -27,7 +27,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
+--- a/arch/arm/mach-s3c2410/s3c2440.c
++++ b/arch/arm/mach-s3c2410/s3c2440.c
+@@ -26,7 +26,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/sysdev.h>
+
+ #include <asm/mach/arch.h>
+diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
+--- a/arch/arm/mach-sa1100/assabet.c
++++ b/arch/arm/mach-sa1100/assabet.c
+@@ -388,9 +388,17 @@ static struct sa1100_port_fns assabet_po
+ };
+
+ 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
+--- a/arch/arm/mach-sa1100/badge4.c
++++ b/arch/arm/mach-sa1100/badge4.c
+@@ -16,7 +16,7 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/delay.h>
+ #include <linux/tty.h>
+ #include <linux/mtd/mtd.h>
+@@ -254,10 +254,22 @@ EXPORT_SYMBOL(badge4_set_5V);
+
+
+ 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
+--- a/arch/arm/mach-sa1100/cerf.c
++++ b/arch/arm/mach-sa1100/cerf.c
+@@ -14,7 +14,7 @@
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/tty.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+
+@@ -100,8 +100,12 @@ static void __init cerf_init_irq(void)
+ }
+
+ 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
+--- a/arch/arm/mach-sa1100/collie.c
++++ b/arch/arm/mach-sa1100/collie.c
+@@ -21,7 +21,7 @@
+ #include <linux/kernel.h>
+ #include <linux/tty.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/timer.h>
+@@ -171,9 +171,17 @@ static void __init collie_init(void)
+ }
+
+ 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
+--- a/arch/arm/mach-sa1100/generic.c
++++ b/arch/arm/mach-sa1100/generic.c
+@@ -17,12 +17,15 @@
+ #include <linux/pm.h>
+ #include <linux/cpufreq.h>
+ #include <linux/ioport.h>
++#include <linux/sched.h> /* just for sched_clock() - funny that */
++#include <linux/platform_device.h>
+
+ #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 +286,7 @@ static struct platform_device sa11x0mtd_
+ 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 +373,27 @@ EXPORT_SYMBOL(sa1100fb_lcd_power);
+ */
+
+ 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
+--- a/arch/arm/mach-sa1100/h3600.c
++++ b/arch/arm/mach-sa1100/h3600.c
+@@ -223,10 +223,22 @@ static void h3xxx_lcd_power(int enable)
+ }
+
+ 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
+--- a/arch/arm/mach-sa1100/hackkit.c
++++ b/arch/arm/mach-sa1100/hackkit.c
+@@ -57,8 +57,12 @@ static void hackkit_uart_pm(struct uart_
+ */
+
+ 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
+--- a/arch/arm/mach-sa1100/jornada720.c
++++ b/arch/arm/mach-sa1100/jornada720.c
+@@ -6,8 +6,10 @@
+ #include <linux/kernel.h>
+ #include <linux/tty.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_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 @@ static int __init jornada720_init(void)
+ 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 @@ static void __init jornada720_map_io(voi
+ 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 at gernoth.net> */
+ .phys_ram = 0xc0000000,
+@@ -105,4 +180,5 @@ MACHINE_START(JORNADA720, "HP Jornada 72
+ .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
+--- a/arch/arm/mach-sa1100/lart.c
++++ b/arch/arm/mach-sa1100/lart.c
+@@ -31,9 +31,17 @@ static void __init lart_init(void)
+ }
+
+ 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
+--- a/arch/arm/mach-sa1100/neponset.c
++++ b/arch/arm/mach-sa1100/neponset.c
+@@ -8,7 +8,7 @@
+ #include <linux/tty.h>
+ #include <linux/ioport.h>
+ #include <linux/serial_core.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/slab.h>
+
+ #include <asm/hardware.h>
+@@ -178,33 +178,27 @@ static int neponset_probe(struct device
+ /*
+ * 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 @@ static int __init neponset_init(void)
+ 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/pleb.c b/arch/arm/mach-sa1100/pleb.c
+--- a/arch/arm/mach-sa1100/pleb.c
++++ b/arch/arm/mach-sa1100/pleb.c
+@@ -6,7 +6,7 @@
+ #include <linux/kernel.h>
+ #include <linux/tty.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <linux/mtd/partitions.h>
+
+diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
+--- a/arch/arm/mach-sa1100/simpad.c
++++ b/arch/arm/mach-sa1100/simpad.c
+@@ -10,7 +10,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/pm.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+
+@@ -60,11 +60,17 @@ EXPORT_SYMBOL(set_cs3_bit);
+ 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
+--- a/arch/arm/mach-shark/core.c
++++ b/arch/arm/mach-shark/core.c
+@@ -62,7 +62,12 @@ arch_initcall(shark_init);
+ 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
+--- 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
+--- a/arch/arm/mach-versatile/core.c
++++ b/arch/arm/mach-versatile/core.c
+@@ -22,6 +22,7 @@
+ #include <linux/init.h>
+ #include <linux/device.h>
+ #include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
+ #include <linux/sysdev.h>
+ #include <linux/interrupt.h>
+
+@@ -186,25 +187,82 @@ void __init versatile_init_irq(void)
+ }
+
+ 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/Kconfig b/arch/arm/mm/Kconfig
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -120,8 +120,8 @@ config CPU_ARM925T
+
+ # ARM926T
+ config CPU_ARM926T
+- bool "Support ARM926T processor" if ARCH_INTEGRATOR
+- depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX
++ bool "Support ARM926T processor"
++ depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB
+ default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX
+ select CPU_32v5
+ select CPU_ABRT_EV5TJ
+@@ -242,7 +242,7 @@ config CPU_XSCALE
+ # ARMv6
+ config CPU_V6
+ bool "Support ARM V6 processor"
+- depends on ARCH_INTEGRATOR
++ depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB
+ select CPU_32v6
+ select CPU_ABRT_EV6
+ select CPU_CACHE_V6
+diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
+--- a/arch/arm/mm/consistent.c
++++ b/arch/arm/mm/consistent.c
+@@ -75,7 +75,7 @@ static struct vm_region consistent_head
+ };
+
+ 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 @@ static struct vm_region *vm_region_find(
+ #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 @@ __dma_alloc(struct device *dev, size_t s
+ * 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 @@ EXPORT_SYMBOL(dma_alloc_coherent);
+ * 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 @@ static int __init consistent_init(void)
+ 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 @@ static int __init consistent_init(void)
+ }
+ 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 @@ static int __init consistent_init(void)
+ 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
+--- 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 @@ static DEFINE_SPINLOCK(v6_lock);
+ * 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 @@ void v6_copy_user_page_nonaliasing(void
+ * 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 @@ void v6_clear_user_page_nonaliasing(void
+ /*
+ * 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 @@ void v6_copy_user_page_aliasing(void *kt
+ */
+ 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 @@ void v6_copy_user_page_aliasing(void *kt
+ * 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 @@ void v6_clear_user_page_aliasing(void *k
+ */
+ 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
+--- a/arch/arm/mm/fault-armv.c
++++ b/arch/arm/mm/fault-armv.c
+@@ -26,6 +26,11 @@ static unsigned long shared_pte_mask = L
+ /*
+ * 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 @@ void __flush_dcache_page(struct address_
+ * 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
+--- 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 @@ void show_mem(void)
+ 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);
++}
++
++static inline pmd_t *pmd_off_k(unsigned long virt)
++{
++ return pmd_off(pgd_offset_k(virt), virt);
++}
+
+-#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+-#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
++#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 @@ find_bootmap_pfn(int node, struct meminf
+ {
+ 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 @@ find_bootmap_pfn(int node, struct meminf
+ 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 @@ static int __init check_initrd(struct me
+ /*
+ * 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 @@ static __init void reserve_node_zero(uns
+ 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,183 +232,284 @@ static __init void reserve_node_zero(uns
+ 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);
+-}
++ start_pfn = -1UL;
++ end_pfn = 0;
+
+-/*
+- * 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;
++ /*
++ * Calculate the pfn range, and map the memory banks for this node.
++ */
++ for_each_nodebank(i, mi, node) {
++ unsigned long start, end;
++ struct map_desc map;
+
+- bootmap_pages = find_memend_and_nodes(mi, np);
+- bootmap_pfn = find_bootmap_pfn(0, mi, bootmap_pages);
+- initrd_node = check_initrd(mi);
++ start = mi->bank[i].start >> PAGE_SHIFT;
++ end = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT;
++
++ if (start_pfn > start)
++ start_pfn = start;
++ if (end_pfn < end)
++ end_pfn = end;
+
+- map_pg = bootmap_pfn;
++ 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);
++ }
+
+ /*
+- * 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).
++ * If there is no memory in this node, ignore it.
+ */
+- 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;
+- }
++ if (end_pfn == 0)
++ return end_pfn;
+
+- /*
+- * 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;
++ /*
++ * Allocate the bootmem bitmap page.
++ */
++ boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
++ boot_pfn = find_bootmap_pfn(node, mi, boot_pages);
+
+- /*
+- * 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);
+- }
++ /*
++ * 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;
+ }
+
+-/*
+- * paging_init() sets up the page tables, initialises the zone memory
+- * maps, and sets up the zero page, bad page and bad page tables.
+- */
+-void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
++static void __init bootmem_init(struct meminfo *mi)
+ {
+- void *zero_page;
+- int node;
++ unsigned long addr, memend_pfn = 0;
++ int node, initrd_node, i;
+
+- bootmem_init(mi);
++ /*
++ * 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));
+
+ /*
+- * allocate the zero page. Note that we count on this going ok.
++ * Clear out all the mappings below the kernel image.
+ */
+- zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
++ 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));
+
+ /*
+- * initialise the page tables.
++ * Clear out all the kernel space mappings, except for the first
++ * memory bank, up to the end of the vmalloc region.
+ */
+- memtable_init(mi);
+- if (mdesc->map_io)
+- mdesc->map_io();
+- local_flush_tlb_all();
++ 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));
+
+ /*
+- * initialise the zones within each node
++ * Locate which node contains the ramdisk image, if any.
+ */
+- 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;
++ initrd_node = check_initrd(mi);
+
+- /*
+- * Initialise the zone size information.
+- */
+- for (i = 0; i < MAX_NR_ZONES; i++) {
+- zone_size[i] = 0;
+- zhole_size[i] = 0;
+- }
++ /*
++ * Run through each node initialising the bootmem allocator.
++ */
++ for_each_node(node) {
++ unsigned long end_pfn;
+
+- pgdat = NODE_DATA(node);
+- bdata = pgdat->bdata;
++ end_pfn = bootmem_init_node(node, initrd_node, mi);
+
+ /*
+- * 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.
++ * Remember the highest memory PFN.
+ */
+- zone_size[0] = bdata->node_low_pfn -
+- (bdata->node_boot_start >> PAGE_SHIFT);
++ if (end_pfn > memend_pfn)
++ memend_pfn = end_pfn;
++ }
+
+- /*
+- * If this zone has zero size, skip it.
+- */
+- if (!zone_size[0])
+- continue;
++ high_memory = __va(memend_pfn << PAGE_SHIFT);
+
+- /*
+- * 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;
++ /*
++ * 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;
++}
+
+- zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT;
+- }
++/*
++ * 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;
+
+- /*
+- * Adjust the sizes according to any special
+- * requirements for this machine type.
+- */
+- arch_adjust_zones(node, zone_size, zhole_size);
++ for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
++ pmd_clear(pmd_off_k(addr));
+
+- free_area_init_node(node, pgdat, zone_size,
+- bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
++ /*
++ * 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);
+ }
+
+ /*
+- * finish off the bad pages once
+- * the mem_map is initialised
++ * 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();
++}
++
++/*
++ * paging_init() sets up the page tables, initialises the zone memory
++ * maps, and sets up the zero page, bad page and bad page tables.
++ */
++void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
++{
++ void *zero_page;
++
++ build_mem_type_table();
++ bootmem_init(mi);
++ devicemaps_init(mdesc);
++
++ 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);
+ memzero(zero_page, PAGE_SIZE);
+ empty_zero_page = virt_to_page(zero_page);
+ flush_dcache_page(empty_zero_page);
+@@ -562,10 +571,7 @@ static void __init free_unused_memmap_no
+ * 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
+--- 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 @@ remap_area_pmd(pmd_t * pmd, unsigned lon
+
+ 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 @@ remap_area_pages(unsigned long start, un
+ 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 @@ remap_area_pages(unsigned long start, un
+ 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
+--- 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 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
+
+ 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 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
+ 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 @@ void free_pgd_slow(pgd_t *pgd)
+ 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 @@ alloc_init_page(unsigned long virt, unsi
+ 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 @@ static struct mem_types mem_types[] __in
+ /*
+ * 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 @@ static void __init build_mem_type_table(
+ * 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 @@ static void __init create_mapping(struct
+ 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 @@ static void __init create_mapping(struct
+ * 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);
+-
+- virt += (PGDIR_SIZE / 2);
+- length -= (PGDIR_SIZE / 2);
++ /*
++ * 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);
++ }
+ }
+
+ while (length >= SUPERSECTION_SIZE) {
+@@ -601,100 +612,6 @@ void setup_mm_for_reboot(char mode)
+ }
+ }
+
+-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
+--- a/arch/arm/oprofile/Makefile
++++ b/arch/arm/oprofile/Makefile
+@@ -6,6 +6,6 @@ DRIVER_OBJS = $(addprefix ../../../drive
+ 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
+--- a/arch/arm/oprofile/backtrace.c
++++ b/arch/arm/oprofile/backtrace.c
+@@ -49,42 +49,22 @@ static struct frame_tail* kernel_backtra
+
+ 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 @@ static int valid_kernel_stack(struct fra
+ 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 @@ void arm_backtrace(struct pt_regs * cons
+ 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
+--- 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 int pmu_start(void);
+-static int pmu_setup(void);
+-static void pmu_stop(void);
+-static int pmu_create_files(struct super_block *, struct dentry *);
++static struct op_arm_model_spec *op_arm_model;
++static int op_arm_enabled;
++static struct semaphore op_arm_sem;
++
++struct op_counter_config counter_config[OP_MAX_COUNTER];
++
++static int op_arm_create_files(struct super_block *sb, struct dentry *root)
++{
++ 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 op_arm_setup(void)
++{
++ 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 pmu_suspend(struct sys_device *dev, pm_message_t state)
++static int op_arm_suspend(struct sys_device *dev, pm_message_t state)
+ {
+- if (pmu_enabled)
+- pmu_stop();
++ down(&op_arm_sem);
++ if (op_arm_enabled)
++ op_arm_model->stop();
++ up(&op_arm_sem);
+ return 0;
+ }
+
+-static int pmu_resume(struct sys_device *dev)
++static int op_arm_resume(struct sys_device *dev)
+ {
+- if (pmu_enabled)
+- pmu_start();
++ 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 @@ static void exit_driverfs(void)
+ #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];
+-
+- 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);
++#ifdef CONFIG_CPU_XSCALE
++ spec = &op_xscale_spec;
++#endif
++
++ 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)
+-{
+- 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)
++void oprofile_arch_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
+--- 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
+--- a/arch/arm/oprofile/op_arm_model.h
++++ b/arch/arm/oprofile/op_arm_model.h
+@@ -26,6 +26,6 @@ extern struct op_arm_model_spec op_xscal
+
+ 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
+--- 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
+--- a/arch/arm/plat-omap/sram.c
++++ b/arch/arm/plat-omap/sram.c
+@@ -59,7 +59,11 @@ void __init omap_detect_sram(void)
+ }
+
+ 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/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
+--- a/arch/arm/plat-omap/usb.c
++++ b/arch/arm/plat-omap/usb.c
+@@ -26,7 +26,7 @@
+ #include <linux/types.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/usb_otg.h>
+
+ #include <asm/io.h>
+diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
+--- a/arch/arm26/kernel/ptrace.c
++++ b/arch/arm26/kernel/ptrace.c
+@@ -665,7 +665,7 @@ static int do_ptrace(int request, struct
+ 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
+--- 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
+--- a/arch/arm26/mm/memc.c
++++ b/arch/arm26/mm/memc.c
+@@ -79,12 +79,6 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
+ 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 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
+ 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 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
+ 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 @@ pgd_t *get_pgd_slow(struct mm_struct *mm
+ 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
+--- 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
+--- 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
+--- a/arch/cris/arch-v32/mm/tlb.c
++++ b/arch/cris/arch-v32/mm/tlb.c
+@@ -175,6 +175,8 @@ init_new_context(struct task_struct *tsk
+ 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 @@ switch_mm(struct mm_struct *prev, struct
+ 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
+--- 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
+--- a/arch/cris/mm/ioremap.c
++++ b/arch/cris/mm/ioremap.c
+@@ -52,7 +52,7 @@ static inline int remap_area_pmd(pmd_t *
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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
+--- a/arch/frv/kernel/ptrace.c
++++ b/arch/frv/kernel/ptrace.c
+@@ -106,7 +106,7 @@ void ptrace_enable(struct task_struct *c
+ 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
+--- 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 @@ int do_settimeofday(struct timespec *tv)
+ 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
+--- a/arch/frv/mb93090-mb00/pci-dma-nommu.c
++++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c
+@@ -33,7 +33,7 @@ struct dma_alloc_record {
+ 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
+--- 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
+--- a/arch/frv/mm/dma-alloc.c
++++ b/arch/frv/mm/dma-alloc.c
+@@ -55,21 +55,18 @@ static int map_page(unsigned long va, un
+ 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 @@ static int map_page(unsigned long va, un
+ * 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
+--- a/arch/frv/mm/pgalloc.c
++++ b/arch/frv/mm/pgalloc.c
+@@ -87,14 +87,14 @@ static inline void pgd_list_add(pgd_t *p
+ 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
+--- a/arch/h8300/kernel/ptrace.c
++++ b/arch/h8300/kernel/ptrace.c
+@@ -57,7 +57,7 @@ void ptrace_disable(struct task_struct *
+ 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
+--- 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
+--- 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 @@ config SEMAPHORE_SLEEPERS
+ bool
+ default y
+
++config X86
++ bool
++ default y
++
+ config MMU
+ bool
+ default y
+@@ -151,304 +155,7 @@ config ES7000_CLUSTERED_APIC
+ 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 @@ config X86_VISWS_APIC
+ 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
+@@ -1340,8 +1042,3 @@ config X86_TRAMPOLINE
+ bool
+ depends on X86_SMP || (X86_VOYAGER && SMP)
+ default y
+-
+-config PC
+- bool
+- depends on X86 && !EMBEDDED
+- default y
+diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
+new file mode 100644
+--- /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
+--- a/arch/i386/Makefile
++++ b/arch/i386/Makefile
+@@ -34,35 +34,8 @@ CFLAGS += -pipe -msoft-float
+ # 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
+--- /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
+--- a/arch/i386/kernel/apic.c
++++ b/arch/i386/kernel/apic.c
+@@ -1046,10 +1046,11 @@ static unsigned int calibration_result;
+
+ 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 +1058,7 @@ void __init setup_boot_APIC_clock(void)
+ */
+ setup_APIC_timer(calibration_result);
+
+- local_irq_enable();
++ local_irq_restore(flags);
+ }
+
+ void __devinit setup_secondary_APIC_clock(void)
+diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
+--- a/arch/i386/kernel/apm.c
++++ b/arch/i386/kernel/apm.c
+@@ -597,12 +597,14 @@ static u8 apm_bios_call(u32 func, u32 eb
+ 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 @@ static u8 apm_bios_call(u32 func, u32 eb
+ 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 @@ static u8 apm_bios_call_simple(u32 func,
+ 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 @@ static u8 apm_bios_call_simple(u32 func,
+ 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 @@ static int __init apm_init(void)
+ 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
+--- a/arch/i386/kernel/cpu/common.c
++++ b/arch/i386/kernel/cpu/common.c
+@@ -573,6 +573,7 @@ void __devinit cpu_init(void)
+ int cpu = smp_processor_id();
+ struct tss_struct * t = &per_cpu(init_tss, cpu);
+ struct thread_struct *thread = ¤t->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 @@ void __devinit cpu_init(void)
+ * 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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 at 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 @@ struct _cache_table
+ };
+
+ /* 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 @@ struct _cpuid4_info {
+ 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 @@ static int __init find_num_cache_leaves(
+ {
+ 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 @@ unsigned int __devinit init_intel_cachei
+ 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 @@ static struct _cpuid4_info *cpuid4_info[
+ #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 @@ static void free_cache_attributes(unsign
+ 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 @@ static void cpuid4_cache_sysfs_exit(unsi
+ 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 @@ err_out:
+ }
+
+ /* 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 @@ static int __devinit cache_add_dev(struc
+ 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 @@ static int __devexit cache_remove_dev(st
+ kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+ kobject_unregister(cache_kobject[cpu]);
+ cpuid4_cache_sysfs_exit(cpu);
+- return 0;
++ return;
++}
++
++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 sysdev_driver cache_sysdev_driver = {
+- .add = cache_add_dev,
+- .remove = __devexit_p(cache_remove_dev),
++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
+--- a/arch/i386/kernel/cpu/mcheck/p6.c
++++ b/arch/i386/kernel/cpu/mcheck/p6.c
+@@ -102,11 +102,16 @@ void __devinit intel_p6_mcheck_init(stru
+ 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
+--- a/arch/i386/kernel/cpu/mtrr/if.c
++++ b/arch/i386/kernel/cpu/mtrr/if.c
+@@ -149,60 +149,89 @@ mtrr_write(struct file *file, const char
+ 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 @@ mtrr_ioctl(struct inode *inode, struct f
+ 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;
++ break;
++ }
++
++ if (err)
++ return err;
+
++ switch(cmd) {
++ case MTRRIOC_GET_ENTRY:
++ case MTRRIOC_GET_PAGE_ENTRY:
+ if (copy_to_user(arg, &gentry, sizeof gentry))
+- return -EFAULT;
++ 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;
+ }
+- return 0;
++#endif
++ }
++ return err;
+ }
+
+ static int
+@@ -310,7 +338,8 @@ static struct file_operations mtrr_fops
+ .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
+--- a/arch/i386/kernel/cpu/proc.c
++++ b/arch/i386/kernel/cpu/proc.c
+@@ -44,7 +44,7 @@ static int show_cpuinfo(struct seq_file
+ 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
+--- a/arch/i386/kernel/cpuid.c
++++ b/arch/i386/kernel/cpuid.c
+@@ -163,7 +163,7 @@ static int cpuid_class_device_create(int
+ 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
+--- 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 @@ static int crash_nmi_callback(struct pt_
+ 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 @@ static void nmi_shootdown_cpus(void)
+ }
+
+ /* Leave the nmi callback set */
+- disable_local_APIC();
+ }
+ #else
+ static void nmi_shootdown_cpus(void)
+@@ -213,9 +210,5 @@ void machine_crash_shutdown(struct pt_re
+ /* 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/io_apic.c b/arch/i386/kernel/io_apic.c
+--- 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 @@ static int find_irq_entry(int apic, int
+ /*
+ * 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 @@ static int find_isa_irq_pin(int irq, int
+ 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 @@ static void __init setup_IO_APIC_irqs(vo
+ /*
+ * 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 @@ static void __init setup_ExtINT_IRQ0_pin
+ * 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 @@ void /*__init*/ print_PIC(void)
+ 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 @@ static void __init enable_IO_APIC(void)
+ /*
+ * 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 @@ static void __init enable_IO_APIC(void)
+ */
+ void disable_IO_APIC(void)
+ {
+- int pin;
+ /*
+ * Clear the IO-APIC before rebooting:
+ */
+@@ -1638,8 +1709,7 @@ void disable_IO_APIC(void)
+ * 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 @@ void disable_IO_APIC(void)
+ 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 @@ void disable_IO_APIC(void)
+ * 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 void setup_nmi (void)
+ */
+ 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 @@ static inline void unlock_ExtINT_logic(v
+ 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 @@ static inline void unlock_ExtINT_logic(v
+
+ 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 unlock_ExtINT_logic(v
+ */
+ static inline void check_timer(void)
+ {
+- int pin1, pin2;
++ int apic1, pin1, apic2, pin2;
+ int vector;
+
+ /*
+@@ -2196,10 +2269,13 @@ static inline void check_timer(void)
+ 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 @@ static inline void check_timer(void)
+ 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 @@ static inline void check_timer(void)
+ /*
+ * 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 @@ static inline void check_timer(void)
+ /*
+ * Cleanup, just in case ...
+ */
+- clear_IO_APIC_pin(0, pin2);
++ clear_IO_APIC_pin(apic2, pin2);
+ }
+ printk(" failed.\n");
+
+diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
+--- a/arch/i386/kernel/irq.c
++++ b/arch/i386/kernel/irq.c
+@@ -218,7 +218,7 @@ int show_interrupts(struct seq_file *p,
+
+ 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 @@ int show_interrupts(struct seq_file *p,
+ #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 @@ skip:
+ 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
+--- a/arch/i386/kernel/mpparse.c
++++ b/arch/i386/kernel/mpparse.c
+@@ -69,7 +69,7 @@ unsigned int def_to_bigsmp = 0;
+ /* 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 @@ static int MP_valid_apicid(int apicid, i
+ }
+ #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 @@ static void __init MP_processor_info (st
+ 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 @@ static void __init MP_processor_info (st
+ 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 @@ static void __init MP_processor_info (st
+ 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_address (
+ }
+
+
+-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
+--- a/arch/i386/kernel/msr.c
++++ b/arch/i386/kernel/msr.c
+@@ -246,7 +246,7 @@ static int msr_class_device_create(int i
+ 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
+--- a/arch/i386/kernel/nmi.c
++++ b/arch/i386/kernel/nmi.c
+@@ -100,16 +100,44 @@ int nmi_active;
+ (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 @@ static int __init check_nmi_watchdog(voi
+ 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 @@ static int __init check_nmi_watchdog(voi
+ 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
+--- a/arch/i386/kernel/ptrace.c
++++ b/arch/i386/kernel/ptrace.c
+@@ -354,7 +354,7 @@ ptrace_set_thread_area(struct task_struc
+ 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
+--- a/arch/i386/kernel/reboot_fixups.c
++++ b/arch/i386/kernel/reboot_fixups.c
+@@ -44,7 +44,7 @@ void mach_reboot_fixups(void)
+
+ 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
+--- a/arch/i386/kernel/setup.c
++++ b/arch/i386/kernel/setup.c
+@@ -389,14 +389,24 @@ static void __init limit_regions(unsigne
+ }
+ }
+ 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
+--- a/arch/i386/kernel/smpboot.c
++++ b/arch/i386/kernel/smpboot.c
+@@ -87,7 +87,11 @@ EXPORT_SYMBOL(cpu_online_map);
+ 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;
+
+diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
+--- a/arch/i386/kernel/srat.c
++++ b/arch/i386/kernel/srat.c
+@@ -327,7 +327,12 @@ int __init get_memcfg_from_srat(void)
+ 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
+--- a/arch/i386/kernel/time.c
++++ b/arch/i386/kernel/time.c
+@@ -74,10 +74,6 @@ int pit_latch_buggy; /* ext
+
+ #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);
+
+diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
+--- a/arch/i386/kernel/time_hpet.c
++++ b/arch/i386/kernel/time_hpet.c
+@@ -275,6 +275,7 @@ static unsigned long PIE_freq = DEFAULT_
+ 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 @@ int hpet_rtc_timer_init(void)
+ 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 @@ static void hpet_rtc_timer_reinit(void)
+ {
+ 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 @@ static void hpet_rtc_timer_reinit(void)
+ 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
+--- a/arch/i386/kernel/timers/timer_hpet.c
++++ b/arch/i386/kernel/timers/timer_hpet.c
+@@ -30,23 +30,28 @@ static seqlock_t monotonic_lock = SEQLOC
+ * 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 at 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 at polymtl.ca)
++ *
+ * -johnstul at 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 @@ static int __init init_hpet(char* overri
+ 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
+--- a/arch/i386/kernel/timers/timer_tsc.c
++++ b/arch/i386/kernel/timers/timer_tsc.c
+@@ -49,23 +49,28 @@ static seqlock_t monotonic_lock = SEQLOC
+ * 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 at 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 at polymtl.ca)
++ *
+ * -johnstul at 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 @@ time_cpufreq_notifier(struct notifier_bl
+ 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 @@ static int __init init_tsc(char* overrid
+ 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
+--- a/arch/i386/kernel/traps.c
++++ b/arch/i386/kernel/traps.c
+@@ -488,6 +488,7 @@ fastcall void __kprobes do_general_prote
+ 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
+--- a/arch/i386/kernel/vm86.c
++++ b/arch/i386/kernel/vm86.c
+@@ -134,17 +134,16 @@ struct pt_regs * fastcall save_v86_state
+ 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 @@ static void mark_screen_rdonly(struct ta
+ 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 @@ static void do_sys_vm86(struct kernel_vm
+
+ 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
+--- 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 @@ struct mip_reg {
+
+ 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
+--- a/arch/i386/mach-es7000/es7000plat.c
++++ b/arch/i386/mach-es7000/es7000plat.c
+@@ -62,6 +62,9 @@ static unsigned int base;
+ 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 @@ es7000_rename_gsi(int ioapic, int gsi)
+ #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 @@ setup_unisys ()
+ *
+ */
+ 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 @@ parse_unisys_oem (char *oemptr)
+ }
+
+ 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
+--- a/arch/i386/mm/discontig.c
++++ b/arch/i386/mm/discontig.c
+@@ -98,7 +98,7 @@ unsigned long node_memmap_size_bytes(int
+
+ 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 @@ void __init set_highmem_pages_init(int b
+ 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
+--- a/arch/i386/mm/fault.c
++++ b/arch/i386/mm/fault.c
+@@ -108,7 +108,7 @@ static inline unsigned long get_segment_
+ 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
+--- 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 @@ static void __init permanent_kmaps_init(
+ 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 @@ static void __init set_highmem_pages_ini
+ {
+ 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 @@ void __init mem_init(void)
+ #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
+--- a/arch/i386/mm/ioremap.c
++++ b/arch/i386/mm/ioremap.c
+@@ -28,7 +28,7 @@ static int ioremap_pte_range(pmd_t *pmd,
+ 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 @@ static int ioremap_page_range(unsigned l
+ 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
+--- a/arch/i386/mm/pgtable.c
++++ b/arch/i386/mm/pgtable.c
+@@ -31,11 +31,13 @@ void show_mem(void)
+ 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 @@ void show_mem(void)
+ 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 @@ static inline void pgd_list_add(pgd_t *p
+ 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
+--- 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 @@ struct frame_head {
+ static struct frame_head *
+ dump_backtrace(struct frame_head * head)
+ {
+- oprofile_add_trace(head->ret);
++ struct frame_head bufhead[2];
+
+- /* frame pointers should strictly progress back up the stack
+- * (towards higher addresses) */
+- if (head >= head->ebp)
++ /* 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;
+
+- 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;
++ oprofile_add_trace(bufhead[0].ret);
+
+- /* FIXME: only necessary once per page */
+- if (!check_user_page_readable(mm, (unsigned long)head))
+- return 0;
++ /* frame pointers should strictly progress back up the stack
++ * (towards higher addresses) */
++ if (head >= bufhead[0].ebp)
++ return NULL;
+
+- return check_user_page_readable(mm, (unsigned long)(head + 1));
++ return bufhead[0].ebp;
+ }
+
+ /*
+@@ -97,15 +94,6 @@ x86_backtrace(struct pt_regs * const reg
+ return;
+ }
+
+-#ifdef CONFIG_SMP
+- if (!spin_trylock(¤t->mm->page_table_lock))
+- return;
+-#endif
+-
+- while (depth-- && head && pages_present(head))
++ while (depth-- && head)
+ head = dump_backtrace(head);
+-
+-#ifdef CONFIG_SMP
+- spin_unlock(¤t->mm->page_table_lock);
+-#endif
+ }
+diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
+--- 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 @@ static void __devinit pci_fixup_video(st
+ }
+ }
+ 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 __devinitdata 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
+--- a/arch/i386/pci/irq.c
++++ b/arch/i386/pci/irq.c
+@@ -547,31 +547,48 @@ static __init int intel_router_probe(str
+ 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
+--- a/arch/i386/power/cpu.c
++++ b/arch/i386/power/cpu.c
+@@ -51,16 +51,14 @@ void save_processor_state(void)
+ __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
+--- a/arch/ia64/Kconfig
++++ b/arch/ia64/Kconfig
+@@ -63,8 +63,6 @@ config IA64_GENERIC
+ 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 @@ config IA64_L1_CACHE_SHIFT
+ 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 @@ config IA64_SGI_SN_XP
+ 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 @@ config SMP
+ 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 @@ config PREEMPT
+
+ 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
+--- 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_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 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_ITANIUM=y
+ # 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_IA64_PALINFO=y
+ #
+ 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 @@ CONFIG_BINFMT_MISC=m
+ # 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=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
+
+ #
+ # PCI Hotplug Support
+@@ -135,8 +166,70 @@ CONFIG_PCI_NAMES=y
+ # 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_PREVENT_FIRMWARE_BUILD=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
+@@ -163,7 +261,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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_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
+@@ -211,7 +317,8 @@ CONFIG_BLK_DEV_IDEFLOPPY=m
+ #
+ # 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_IDEDMA_PCI_AUTO=y
+ # 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 @@ CONFIG_IDEDMA_AUTO=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -261,6 +370,7 @@ CONFIG_BLK_DEV_SD=y
+ # 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_LOGGING=y
+ #
+ 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_SCSI_SPI_ATTRS=m
+ # 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_QLA2XXX=y
+ # 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_CRYPT=m
+ 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_DM_ZERO=m
+ # 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_DUMMY=y
+ # 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_NET_PCI=y
+ # 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_EEPRO100=y
+ # 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_EEPRO100=y
+ # 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_EVDEV=y
+ # 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_MOUSE_PS2=y
+ # 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_NR_UARTS=4
+ 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_8250_SHARE_IRQ=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,14 +665,22 @@ CONFIG_EFI_RTC=y
+ #
+ 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_ALGOBIT=y
+ # 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,16 +721,43 @@ CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_PCA_ISA is not set
+
+ #
+-# Hardware Sensors Chip support
++# Miscellaneous I2C Chip support
+ #
+-# CONFIG_I2C_SENSOR is not set
++# 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
+@@ -671,33 +768,26 @@ CONFIG_I2C_ALGOBIT=y
+ # 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
+
+ #
+-# Other I2C Chip support
+-#
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_SENSORS_RTC8564 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
++# Misc devices
+ #
+-# CONFIG_W1 is not set
+
+ #
+-# Misc devices
++# Multimedia Capabilities Port drivers
+ #
+
+ #
+@@ -752,11 +842,12 @@ CONFIG_SND_OPL3_LIB=m
+ # 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_AC97_CODEC=m
+ # 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_CS4281=m
+ # 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_CS4281=m
+ # 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 @@ CONFIG_SND_CS4281=m
+ #
+ # 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_DEVICEFS=y
+ # 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_HIDDEV=y
+ # 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_HIDDEV=y
+ # 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_HIDDEV=y
+ #
+ # 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_HIDDEV=y
+ # 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_HIDDEV=y
+ # 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_FS_MBCACHE=y
+ # 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_RAMFS=y
+ #
+ 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=m
+ 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 @@ 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
+
+ #
+ # Profiling support
+@@ -1115,14 +1245,20 @@ CONFIG_OPROFILE=y
+ #
+ # 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_MD5=y
+ # 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_DES=y
+ # 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
+--- /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
+--- 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 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ CONFIG_POSIX_MQUEUE=y
+@@ -27,6 +28,7 @@ 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
+@@ -103,6 +105,7 @@ CONFIG_FLATMEM_MANUAL=y
+ # 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_IA64_PALINFO=y
+ #
+ 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 @@ CONFIG_BINFMT_MISC=m
+ # 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=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
+
+ #
+@@ -188,14 +198,19 @@ CONFIG_SYN_COOKIES=y
+ # 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 @@ CONFIG_TCP_CONG_BIC=y
+ # 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_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
+@@ -247,7 +269,13 @@ CONFIG_FW_LOADER=m
+ #
+ # 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=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+ CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+ # CONFIG_CDROM_PKTCDVD is not set
+
+ #
+@@ -299,7 +326,8 @@ CONFIG_BLK_DEV_IDESCSI=m
+ #
+ # 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 @@ CONFIG_IDEDMA_AUTO=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -366,6 +395,7 @@ CONFIG_CHR_DEV_SG=m
+ 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_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
+@@ -461,6 +492,11 @@ CONFIG_DUMMY=m
+ # 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_TULIP=m
+ # 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_E1000=y
+ # 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 @@ CONFIG_TIGON3=y
+ #
+ # Ethernet (10000 Mbit)
+ #
++# CONFIG_CHELSIO_T1 is not set
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+
+@@ -618,6 +657,7 @@ 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
+@@ -675,6 +715,7 @@ 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
+@@ -691,7 +732,6 @@ CONFIG_MAX_RAW_DEVS=256
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+-# CONFIG_I2C_SENSOR is not set
+
+ #
+ # Dallas's 1-wire bus
+@@ -702,6 +742,7 @@ CONFIG_MAX_RAW_DEVS=256
+ # Hardware Monitoring support
+ #
+ CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
+ # CONFIG_HWMON_DEBUG_CHIP is not set
+
+ #
+@@ -709,6 +750,10 @@ CONFIG_HWMON=y
+ #
+
+ #
++# Multimedia Capabilities Port drivers
++#
++
++#
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+@@ -800,9 +845,11 @@ CONFIG_USB_HIDINPUT=y
+ # 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_POSIX_ACL=y
+ 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_INOTIFY=y
+ 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_NTFS_FS=m
+ 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_CIFS=m
+ # 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 @@ 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
+
+ #
+ # Profiling support
+@@ -1089,6 +1134,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
+ 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
+--- 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 @@ 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
+@@ -29,6 +30,7 @@ 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
+@@ -103,6 +105,7 @@ CONFIG_FLATMEM_MANUAL=y
+ # 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_IA64_PALINFO=y
+ #
+ 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 @@ CONFIG_BINFMT_MISC=y
+ # 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_IP_FIB_HASH=y
+ # 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 @@ CONFIG_NETFILTER=y
+ # 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_ARPTABLES=y
+ # 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 @@ CONFIG_IP_NF_ARPTABLES=y
+ # 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_PREVENT_FIRMWARE_BUILD=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
+@@ -263,7 +284,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+ CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+ # CONFIG_CDROM_PKTCDVD is not set
+
+ #
+@@ -315,7 +341,8 @@ CONFIG_BLK_DEV_IDECD=y
+ #
+ # 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 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -381,6 +409,7 @@ CONFIG_SCSI_LOGGING=y
+ 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_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
+@@ -464,6 +494,11 @@ CONFIG_DUMMY=y
+ # 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_TULIP_NAPI_HW_MITIGATION=y
+ # 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_E1000=y
+ # 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 @@ CONFIG_TIGON3=y
+ #
+ # 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=y
+ 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_ALGOPCF=y
+ # 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_ALGOPCF=y
+ # 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 @@ CONFIG_I2C_ALGOPCF=y
+ # 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_RADEON_DEBUG=y
+ # 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_OPL3_LIB=y
+ # 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_AC97_CODEC=y
+ # 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 @@ CONFIG_USB_UHCI_HCD=y
+ #
+ # 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=y
+ # 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_HIDDEV=y
+ # 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_FS_MBCACHE=y
+ # 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_FS_MBCACHE=y
+ 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_RPCSEC_GSS_KRB5=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -1246,10 +1287,12 @@ CONFIG_NLS_UTF8=y
+ # 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_GENERIC_IRQ_PROBE=y
+ 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
+--- 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 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ CONFIG_POSIX_MQUEUE=y
+@@ -27,6 +28,7 @@ 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
+@@ -80,6 +82,10 @@ CONFIG_MCKINLEY=y
+ # 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_HOLES_IN_ZONE=y
+ 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_IA64_PALINFO=y
+ #
+ 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 @@ CONFIG_BINFMT_MISC=m
+ # 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=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
+@@ -154,6 +177,73 @@ CONFIG_HOTPLUG_PCI_ACPI=m
+ # 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_HOTPLUG_PCI_ACPI=m
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+ CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+ # CONFIG_CDROM_PKTCDVD is not set
+
+ #
+@@ -230,7 +330,8 @@ CONFIG_BLK_DEV_IDESCSI=m
+ #
+ # 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_CMD64X=y
+ # 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 @@ CONFIG_IDEDMA_AUTO=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -297,6 +400,7 @@ CONFIG_CHR_DEV_SG=m
+ 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=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
+@@ -335,7 +440,6 @@ 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_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_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
+@@ -390,74 +495,14 @@ CONFIG_FUSION_MAX_SGE=128
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
+-
++# Network device support
+ #
+-# 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_DUMMY=m
+ # 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_TULIP=m
+ # 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_E1000=y
+ # 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 @@ CONFIG_TIGON3=y
+ #
+ # Ethernet (10000 Mbit)
+ #
++# CONFIG_CHELSIO_T1 is not set
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+
+@@ -549,6 +602,10 @@ CONFIG_TIGON3=y
+ # 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=m
+ # CONFIG_GAMEPORT_NS558 is not set
+ # CONFIG_GAMEPORT_L4 is not set
+ # CONFIG_GAMEPORT_EMU10K1 is not set
+-# CONFIG_GAMEPORT_VORTEX is not set
+ # CONFIG_GAMEPORT_FM801 is not set
+-# CONFIG_GAMEPORT_CS461X is not set
+
+ #
+ # Character devices
+@@ -620,6 +675,7 @@ 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
+@@ -641,7 +697,6 @@ 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_MULTIPORT is not set
+ # CONFIG_SERIAL_8250_RSA is not set
+
+ #
+@@ -650,8 +705,8 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
+ 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_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
+@@ -708,10 +765,21 @@ CONFIG_MMTIMER=y
+ # 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_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
+@@ -764,11 +833,12 @@ 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_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_EMU10K1=m
+ # 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_DEVICEFS=y
+ 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 @@ CONFIG_USB_UHCI_HCD=m
+ #
+ # 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_HIDINPUT=y
+ # 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_HIDINPUT=y
+ # 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_MON=m
+ # 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 @@ CONFIG_USB_MON=m
+ # 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=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
+@@ -996,22 +1076,20 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
+ 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_NTFS_FS=m
+ 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_RAMFS=y
+ #
+ 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_CIFS=m
+ # 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 @@ 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
+@@ -1187,6 +1268,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
+ 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_LOG_BUF_SHIFT=20
+ # 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=y
+ # 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
+--- 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 @@ void
+ 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
+--- a/arch/ia64/hp/common/sba_iommu.c
++++ b/arch/ia64/hp/common/sba_iommu.c
+@@ -1076,7 +1076,7 @@ void sba_unmap_single(struct device *dev
+ * 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,9 +2028,40 @@ static struct acpi_driver acpi_sba_ioc_d
+ static int __init
+ sba_init(void)
+ {
++ if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
++ return 0;
++
+ acpi_bus_register_driver(&acpi_sba_ioc_driver);
+- if (!ioc_list)
++ 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
+ {
+@@ -2048,18 +2079,6 @@ sba_init(void)
+
+ 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
+--- a/arch/ia64/hp/sim/simscsi.c
++++ b/arch/ia64/hp/sim/simscsi.c
+@@ -205,10 +205,11 @@ simscsi_get_disk_size (int fd)
+ 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 @@ simscsi_readwrite10 (struct scsi_cmnd *s
+ {
+ 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
+--- 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
+--- a/arch/ia64/kernel/acpi.c
++++ b/arch/ia64/kernel/acpi.c
+@@ -838,7 +838,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
+ #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 @@ acpi_map_iosapic(acpi_handle handle, u32
+ 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
+--- 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
+--- a/arch/ia64/kernel/efi.c
++++ b/arch/ia64/kernel/efi.c
+@@ -239,57 +239,30 @@ is_available_memory (efi_memory_desc_t *
+ 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;
+-
+- if (md->phys_addr >= start_addr || !md->num_pages)
+- return;
++typedef struct kern_memdesc {
++ u64 attribute;
++ u64 start;
++ u64 num_pages;
++} kern_memdesc_t;
+
+- 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;
+-
+- md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+-
+- if (md_end_addr <= end_addr || !md->num_pages)
+- return;
++ kern_memdesc_t *k;
++ u64 start, end, voff;
+
+- 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 @@ trim_top (efi_memory_desc_t *md, u64 end
+ 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 @@ efi_uart_console_only(void)
+ 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
+--- a/arch/ia64/kernel/irq.c
++++ b/arch/ia64/kernel/irq.c
+@@ -57,9 +57,9 @@ int show_interrupts(struct seq_file *p,
+
+ 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 @@ int show_interrupts(struct seq_file *p,
+ #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
+--- a/arch/ia64/kernel/mca.c
++++ b/arch/ia64/kernel/mca.c
+@@ -508,9 +508,7 @@ ia64_mca_wakeup_all(void)
+ 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
+--- a/arch/ia64/kernel/module.c
++++ b/arch/ia64/kernel/module.c
+@@ -947,8 +947,8 @@ void
+ 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
+--- a/arch/ia64/kernel/patch.c
++++ b/arch/ia64/kernel/patch.c
+@@ -64,22 +64,30 @@ ia64_patch (u64 insn_addr, u64 mask, u64
+ 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
+--- a/arch/ia64/kernel/perfmon.c
++++ b/arch/ia64/kernel/perfmon.c
+@@ -2352,7 +2352,8 @@ pfm_smpl_buffer_alloc(struct task_struct
+ 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
+--- a/arch/ia64/kernel/ptrace.c
++++ b/arch/ia64/kernel/ptrace.c
+@@ -587,8 +587,9 @@ thread_matches (struct task_struct *thre
+ 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 @@ find_thread_for_addr (struct task_struct
+ 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, ¤t->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
+--- a/arch/ia64/kernel/setup.c
++++ b/arch/ia64/kernel/setup.c
+@@ -78,6 +78,19 @@ struct screen_info screen_info;
+ 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 @@ sort_regions (struct rsvd_region *rsvd_r
+ }
+ }
+
++/*
++ * 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 @@ reserve_memory (void)
+ }
+ #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 @@ find_initrd (void)
+ 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 @@ show_cpuinfo (struct seq_file *m, void *
+ 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
+--- a/arch/ia64/kernel/smp.c
++++ b/arch/ia64/kernel/smp.c
+@@ -185,8 +185,8 @@ send_IPI_allbutself (int op)
+ {
+ 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 @@ send_IPI_all (int op)
+ {
+ 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
+--- a/arch/ia64/kernel/smpboot.c
++++ b/arch/ia64/kernel/smpboot.c
+@@ -694,9 +694,9 @@ smp_cpus_done (unsigned int dummy)
+ * 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
+--- 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
+--- a/arch/ia64/kernel/uncached.c
++++ b/arch/ia64/kernel/uncached.c
+@@ -205,23 +205,18 @@ EXPORT_SYMBOL(uncached_free_page);
+ 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
+--- 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 (void)
+ 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 @@ sync_single(struct device *hwdev, char *
+
+ 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
+--- a/arch/ia64/mm/Makefile
++++ b/arch/ia64/mm/Makefile
+@@ -7,6 +7,5 @@ obj-y := init.o fault.o tlb.o extable.o
+ 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
+--- a/arch/ia64/mm/contig.c
++++ b/arch/ia64/mm/contig.c
+@@ -269,7 +269,7 @@ paging_init (void)
+ 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 @@ paging_init (void)
+ 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
+--- a/arch/ia64/mm/discontig.c
++++ b/arch/ia64/mm/discontig.c
+@@ -421,6 +421,37 @@ static void __init memory_less_nodes(voi
+ 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 @@ void show_mem(void)
+ 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 @@ void show_mem(void)
+ 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 @@ void __init paging_init(void)
+
+ 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 @@ void __init paging_init(void)
+
+ 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
+--- 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 @@ ia64_do_page_fault (unsigned long addres
+ 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
+--- a/arch/ia64/mm/init.c
++++ b/arch/ia64/mm/init.c
+@@ -158,7 +158,7 @@ ia64_init_addr_space (void)
+ 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(¤t->mm->mmap_sem);
+ if (insert_vm_struct(current->mm, vma)) {
+ up_write(¤t->mm->mmap_sem);
+@@ -275,26 +275,21 @@ put_kernel_page (struct page *page, unsi
+
+ 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 @@ mem_init (void)
+ 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
+--- a/arch/ia64/mm/numa.c
++++ b/arch/ia64/mm/numa.c
+@@ -47,3 +47,27 @@ paddr_to_nid(unsigned long paddr)
+
+ 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
+--- a/arch/ia64/mm/tlb.c
++++ b/arch/ia64/mm/tlb.c
+@@ -77,19 +77,25 @@ wrap_mmu_context (struct mm_struct *mm)
+ /* 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 @@ flush_tlb_range (struct vm_area_struct *
+ 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 @@ flush_tlb_range (struct vm_area_struct *
+ 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
+--- a/arch/ia64/pci/pci.c
++++ b/arch/ia64/pci/pci.c
+@@ -120,29 +120,6 @@ struct pci_ops pci_root_ops = {
+ .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 @@ add_io_space (struct acpi_resource_addre
+ 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 @@ count_window (struct acpi_resource *reso
+ 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 @@ static __devinit acpi_status add_window(
+ 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
+--- a/arch/ia64/sn/kernel/bte.c
++++ b/arch/ia64/sn/kernel/bte.c
+@@ -87,7 +87,7 @@ bte_result_t bte_copy(u64 src, u64 dest,
+ 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
+--- 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 @@ static void sn_fixup_ionodes(void)
+ * 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
+--- a/arch/ia64/sn/kernel/setup.c
++++ b/arch/ia64/sn/kernel/setup.c
+@@ -59,8 +59,6 @@ DEFINE_PER_CPU(struct pda_s, pda_percpu)
+
+ #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 @@ u8 sn_region_size;
+ 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 @@ char drive_info[4 * 16];
+ #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 @@ void __init early_sn_setup(void)
+ }
+
+ extern int platform_intr_list[];
+-extern nasid_t master_nasid;
+ static int __initdata shub_1_1_found = 0;
+
+ /*
+@@ -269,7 +253,6 @@ static void __init sn_check_for_wars(voi
+ 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 @@ void __init sn_setup(char **cmdline_p)
+
+ 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 @@ void __init sn_setup(char **cmdline_p)
+
+ 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 @@ static void __init sn_init_pdas(char **c
+ {
+ 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 @@ static void __init sn_init_pdas(char **c
+ /*
+ * 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 @@ static void __init sn_init_pdas(char **c
+ /*
+ * 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 @@ static void __init sn_init_pdas(char **c
+ * 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 @@ void __init sn_cpu_init(void)
+ }
+
+ /*
+- * 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 inline int __init board_needs_cnode(int type)
++{
++ return (type == KLTYPE_SNIA || type == KLTYPE_TIO);
++}
+
+-static void __init scan_for_ionodes(void)
++void __init build_cnode_tables(void)
+ {
+- int nasid = 0;
++ int nasid;
++ int node;
+ lboard_t *brd;
+
+- /* 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;
+- }
++ memset(physical_node_map, -1, sizeof(physical_node_map));
++ memset(sn_cnodeid_to_nasid, -1,
++ sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
+
+- brd = find_lboard_any(brd, KLTYPE_SNIA);
++ /*
++ * 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;
++ }
+
+- 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;
++ /*
++ * 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();
+
+- brd = find_lboard_any(brd, KLTYPE_SNIA);
+- }
+- }
++ /* fakeprom does not support klgraph */
++ if (IS_RUNNING_ON_FAKE_PROM())
++ return;
+
+- /* 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);
++ /* 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_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
+--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
++++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
+@@ -177,6 +177,7 @@ void sn_tlb_migrate_finish(struct mm_str
+
+ /**
+ * 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 @@ void sn_tlb_migrate_finish(struct mm_str
+ * - 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 @@ sn2_global_tlb_purge(unsigned long start
+ 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 @@ sn2_global_tlb_purge(unsigned long start
+ 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 @@ sn2_global_tlb_purge(unsigned long start
+ 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 @@ sn2_global_tlb_purge(unsigned long start
+ (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 @@ sn2_global_tlb_purge(unsigned long start
+ 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
+--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
++++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+@@ -476,8 +476,8 @@ static int sn_topology_show(struct seq_f
+ 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
+--- a/arch/ia64/sn/kernel/tiocx.c
++++ b/arch/ia64/sn/kernel/tiocx.c
+@@ -183,11 +183,12 @@ int cx_driver_unregister(struct cx_drv *
+ * @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_device_register(nasid_t nasid, int pa
+ 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 @@ static int cx_device_reload(struct cx_de
+ {
+ 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 @@ static void tio_corelet_reset(nasid_t na
+ 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 @@ static int tiocx_reload(struct cx_dev *c
+
+ 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 @@ static ssize_t show_cxdev_control(struct
+ {
+ 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 @@ static int __init tiocx_init(void)
+
+ 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 @@ static int __init tiocx_init(void)
+
+ 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
+--- 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 @@ struct xpc_vars {
+ 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 @@ struct xpc_vars_part {
+ #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 @@ struct xpc_channel {
+ 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 @@ struct xpc_channel {
+ 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 @@ struct xpc_channel {
+
+ #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 @@ struct xpc_partition {
+
+ /* 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 @@ struct xpc_partition {
+ 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 @@ struct xpc_partition {
+
+ 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 @@ struct xpc_partition {
+ #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 @@ struct xpc_partition {
+ #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 @@ struct xpc_partition {
+ 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 struct xpc_rsvd_page *xpc_rsvd_pa
+ 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_connected_callout(struct
+ 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 @@ xpc_part_ref(struct xpc_partition *part)
+
+
+ /*
++ * 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 @@ xpc_IPI_send(AMO_t *amo, u64 flag, int n
+ * 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_IPI_send_reactivate(struct xpc_parti
+ 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 @@ xpc_notify_IRQ_send_local(struct xpc_cha
+
+ /* 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 @@ xpc_IPI_send_local_msgrequest(struct xpc
+ * 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 @@ xpc_map_bte_errors(bte_result_t error)
+
+
+ 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
+--- a/arch/ia64/sn/kernel/xpc_channel.c
++++ b/arch/ia64/sn/kernel/xpc_channel.c
+@@ -57,6 +57,7 @@ xpc_initialize_channels(struct xpc_parti
+
+ 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_setup_infrastructure(struct xpc_part
+ 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 @@ xpc_allocate_msgqueues(struct xpc_channe
+ 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 @@ xpc_process_connect(struct xpc_channel *
+
+
+ /*
++ * 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(¬ify->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 @@ xpc_free_msgqueues(struct xpc_channel *c
+ 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 @@ static void
+ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
+ {
+ struct xpc_partition *part = &xpc_partitions[ch->partid];
+- u32 ch_flags = ch->flags;
++ u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
+
+
+ DBUG_ON(!spin_is_locked(&ch->lock));
+@@ -701,12 +747,13 @@ xpc_process_disconnect(struct xpc_channe
+ }
+ DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+
+- /* it's now safe to free the channel's message queues */
+-
+- xpc_free_msgqueues(ch);
+- DBUG_ON(ch->flags & XPC_C_SETUP);
++ if (part->act_state == XPC_P_DEACTIVATING) {
++ /* can't proceed until the other side disengages from us */
++ if (xpc_partition_engaged(1UL << ch->partid)) {
++ return;
++ }
+
+- if (part->act_state != XPC_P_DEACTIVATING) {
++ } else {
+
+ /* as long as the other side is up do the full protocol */
+
+@@ -724,16 +771,42 @@ xpc_process_disconnect(struct xpc_channe
+ }
+ }
+
++ /* 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 @@ xpc_process_openclose_IPI(struct xpc_par
+
+ 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 @@ xpc_process_openclose_IPI(struct xpc_par
+ /*
+ * 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 @@ xpc_process_openclose_IPI(struct xpc_par
+
+ /* 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_process_openclose_IPI(struct xpc_par
+ }
+
+ 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 @@ xpc_process_openclose_IPI(struct xpc_par
+ }
+
+ 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 @@ xpc_process_openclose_IPI(struct xpc_par
+ "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 @@ xpc_process_openclose_IPI(struct xpc_par
+ * 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 @@ xpc_process_openclose_IPI(struct xpc_par
+ 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 @@ xpc_connect_channel(struct xpc_channel *
+ struct xpc_registration *registration = &xpc_registrations[ch->number];
+
+
+- if (down_interruptible(®istration->sema) != 0) {
+- return xpcInterrupted;
++ if (down_trylock(®istration->sema) != 0) {
++ return xpcRetry;
+ }
+
+ if (!XPC_CHANNEL_REGISTERED(ch->number)) {
+@@ -1040,55 +1166,6 @@ xpc_connect_channel(struct xpc_channel *
+
+
+ /*
+- * 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(¬ify->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 @@ xpc_process_channel_activity(struct xpc_
+ 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_channel_activity(struct xpc_
+ 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 @@ xpc_process_channel_activity(struct xpc_
+ 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_process_channel_activity(struct xpc_
+
+
+ /*
+- * 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 @@ xpc_process_channel_activity(struct xpc_
+ * 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 @@ xpc_partition_down(struct xpc_partition
+ }
+
+
+- /* 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 @@ xpc_teardown_infrastructure(struct xpc_p
+ * 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 @@ xpc_initiate_connect(int ch_number)
+ 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 @@ xpc_initiate_connect(int ch_number)
+ 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 @@ xpc_connected_callout(struct xpc_channel
+ 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 @@ xpc_initiate_disconnect(int ch_number)
+
+ 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 @@ xpc_initiate_disconnect(int ch_number)
+ /*
+ * To disconnect a channel, and reflect it back to all who may be waiting.
+ *
+- * >>> An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
+- * >>> xpc_free_msgqueues().
++ * 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 @@ void
+ 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,61 +1616,53 @@ xpc_disconnect_channel(const int line, s
+
+ 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;
+ }
+
++ spin_unlock_irqrestore(&ch->lock, *irq_flags);
++
++ /* wake all idle kthreads so they can exit */
+ if (atomic_read(&ch->kthreads_idle) > 0) {
+- /* wake all idle kthreads so they can exit */
+ wake_up_all(&ch->idle_wq);
+ }
+
+- spin_unlock_irqrestore(&ch->lock, *irq_flags);
+-
+-
+ /* wake those waiting to allocate an entry from the local msg queue */
+-
+ if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+ wake_up(&ch->msg_allocate_wq);
+ }
+
+- /* wake those waiting for notify completion */
+-
+- if (atomic_read(&ch->n_to_notify) > 0) {
+- xpc_notify_senders(ch, reason, ch->w_local_GP.put);
+- }
+-
+ spin_lock_irqsave(&ch->lock, *irq_flags);
+ }
+
+
+ void
+-xpc_disconnected_callout(struct xpc_channel *ch)
++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_send_msg(struct xpc_channel *ch, str
+ 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
+--- 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 @@ struct device *xpc_chan = &xpc_chan_dbg_
+
+ /* systune related variables for /proc/sys directories */
+
+-static int xpc_hb_min = 1;
+-static int xpc_hb_max = 10;
+-
+-static int xpc_hb_check_min = 10;
+-static int xpc_hb_check_max = 120;
++static 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_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 @@ static ctl_table xpc_sys_xpc_hb_dir[] =
+ &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 @@ static ctl_table xpc_sys_xpc_hb_dir[] =
+ &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 @@ static ctl_table xpc_sys_xpc_dir[] = {
+ 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 DECLARE_WAIT_QUEUE_HEAD(xpc_act_I
+
+ 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 struct timer_list xpc_hb_timer;
+ 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 @@ xpc_hb_checker(void *ignore)
+
+ 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 @@ xpc_hb_checker(void *ignore)
+ }
+
+
++ /* 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_checker(void *ignore)
+ 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 @@ xpc_initiate_discovery(void *ignore)
+
+ 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 @@ xpc_make_first_contact(struct xpc_partit
+ "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 @@ static void
+ 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 @@ xpc_channel_mgr(struct xpc_partition *pa
+ (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 @@ xpc_activating(void *__partid)
+ return 0;
+ }
+
+- XPC_ALLOW_HB(partid, xpc_vars);
++ xpc_allow_hb(partid, xpc_vars);
+ xpc_IPI_send_activated(part);
+
+
+@@ -492,6 +541,7 @@ xpc_activating(void *__partid)
+ */
+ (void) xpc_partition_up(part);
+
++ xpc_disallow_hb(partid, xpc_vars);
+ xpc_mark_partition_inactive(part);
+
+ if (part->reason == xpcReactivating) {
+@@ -670,6 +720,7 @@ xpc_daemonize_kthread(void *args)
+ 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 @@ xpc_daemonize_kthread(void *args)
+ 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 @@ xpc_daemonize_kthread(void *args)
+ !(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 @@ xpc_create_kthreads(struct xpc_channel *
+ 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 @@ xpc_create_kthreads(struct xpc_channel *
+ 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 @@ xpc_create_kthreads(struct xpc_channel *
+ 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];
++ if (!xpc_part_ref(part)) {
++ continue;
++ }
+
+-// >>> 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);
+- }
++ 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;
+-
+- /*
+- * 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);
++ /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
++ DBUG_ON(xpc_exiting == 1);
+
+ /*
+- * 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 @@ xpc_do_exit(void)
+ }
+
+
++/*
++ * 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_init(void)
+
+ /*
+ * 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 @@ xpc_init(void)
+ 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 @@ xpc_init(void)
+ }
+
+
++ /* 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 @@ xpc_init(void)
+ /* 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 @@ xpc_init(void)
+ /* 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 @@ module_init(xpc_init);
+ void __exit
+ xpc_exit(void)
+ {
+- xpc_do_exit();
++ xpc_do_exit(xpcUnloading);
+ }
+ module_exit(xpc_exit);
+
+@@ -1060,3 +1238,7 @@ module_param(xpc_hb_check_interval, int,
+ 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
+--- a/arch/ia64/sn/kernel/xpc_partition.c
++++ b/arch/ia64/sn/kernel/xpc_partition.c
+@@ -44,16 +44,19 @@ static u64 xpc_sh2_IPI_access3;
+
+
+ /* 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 @@ struct xpc_partition xpc_partitions[XP_M
+
+
+ /*
+- * 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 @@ int xpc_hb_check_interval = XPC_HB_CHECK
+ * 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 @@ xpc_get_rsvd_page_pa(int nasid, u64 buf,
+ 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 @@ xpc_get_rsvd_page_pa(int nasid, u64 buf,
+ }
+ }
+
++ if (buf_base != NULL) {
++ kfree(buf_base);
++ }
++
+ if (status != SALRET_OK) {
+ rp_pa = 0;
+ }
+@@ -141,15 +156,15 @@ xpc_rsvd_page_init(void)
+ {
+ 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 @@ xpc_rsvd_page_init(void)
+
+ 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 @@ xpc_rsvd_page_init(void)
+ 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 @@ xpc_check_remote_hb(void)
+ 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 @@ xpc_check_remote_hb(void)
+ /* 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 @@ xpc_check_remote_hb(void)
+
+ 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 @@ xpc_check_remote_hb(void)
+
+
+ /*
+- * 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 @@ xpc_get_remote_rp(int nasid, u64 *discov
+
+
+ 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 @@ xpc_get_remote_rp(int nasid, u64 *discov
+
+
+ /*
+- * 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 @@ xpc_get_remote_vars(u64 remote_vars_pa,
+ /* 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 @@ xpc_get_remote_vars(u64 remote_vars_pa,
+
+
+ /*
+- * 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 @@ xpc_identify_act_IRQ_req(int nasid)
+ {
+ struct xpc_rsvd_page *remote_rp;
+ struct xpc_vars *remote_vars;
+- u64 remote_rsvd_page_pa;
++ u64 remote_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 @@ xpc_identify_act_IRQ_req(int nasid)
+
+ 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 @@ xpc_identify_act_IRQ_req(int nasid)
+ }
+
+ 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 @@ xpc_identify_act_IRQ_req(int nasid)
+ "%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);
++
++ 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);
++ }
+
+- 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);
++ xpc_activate_partition(part);
++ return;
++ }
+
+- part->last_heartbeat = remote_vars->heartbeat;
+- dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",
+- part->last_heartbeat);
++ DBUG_ON(part->remote_rp_version == 0);
++ DBUG_ON(part->remote_vars_version == 0);
+
+- 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_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;
++ }
++ }
+
+- xpc_activate_partition(part);
++ /*
++ * 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;
++ }
+
+- } else if (part->remote_amos_page_pa != remote_vars->amos_page_pa ||
+- !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
++ 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 @@ xpc_identify_act_IRQ_sender(void)
+ 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 @@ xpc_identify_act_IRQ_sender(void)
+ * 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 @@ xpc_identify_act_IRQ_sender(void)
+
+
+ /*
++ * 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 @@ xpc_deactivate_partition(const int line,
+ 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 @@ xpc_deactivate_partition(const int line,
+
+ 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);
++
++ /* 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);
++ }
+
+- dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n", partid,
+- reason);
++ dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
++ XPC_PARTID(part), reason);
+
+- xpc_partition_down(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 @@ xpc_discovery(void)
+ void *remote_rp_base;
+ struct xpc_rsvd_page *remote_rp;
+ struct xpc_vars *remote_vars;
+- u64 remote_rsvd_page_pa;
++ u64 remote_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 @@ xpc_discovery(void)
+ 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 @@ xpc_discovery(void)
+ 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 @@ xpc_discovery(void)
+ * 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 @@ xpc_discovery(void)
+
+ 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 @@ xpc_discovery(void)
+ 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 @@ xpc_discovery(void)
+ /* 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 @@ xpc_discovery(void)
+ 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 @@ xpc_initiate_partid_to_nasids(partid_t p
+ 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
+--- a/arch/ia64/sn/pci/pci_dma.c
++++ b/arch/ia64/sn/pci/pci_dma.c
+@@ -75,7 +75,7 @@ EXPORT_SYMBOL(sn_dma_set_mask);
+ * 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 @@ int sn_pci_legacy_read(struct pci_bus *b
+ {
+ 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 sn_pci_legacy_write(struct pci_bus *
+ 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
+--- 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 @@ void pcireg_control_bit_clr(struct pcibu
+ 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 @@ void pcireg_control_bit_set(struct pcibu
+ 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 @@ uint64_t pcireg_tflush_get(struct pcibus
+ 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 @@ uint64_t pcireg_intr_status_get(struct p
+ 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 @@ void pcireg_intr_enable_bit_clr(struct p
+ 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 @@ void pcireg_intr_enable_bit_set(struct p
+ 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 @@ void pcireg_intr_addr_addr_set(struct pc
+ 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 @@ void pcireg_force_intr_set(struct pcibus
+ 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 @@ uint64_t pcireg_wrb_flush_get(struct pci
+ 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 @@ void pcireg_int_ate_set(struct pcibus_in
+ 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 @@ uint64_t *pcireg_int_ate_addr(struct pci
+ 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
+--- 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 @@ tioca_gart_init(struct tioca_kernel *tio
+ 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 @@ tioca_gart_init(struct tioca_kernel *tio
+ * 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 @@ void
+ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
+ {
+ int cap_ptr;
+- uint64_t ca_control1;
+ uint32_t reg;
+ struct tioca *tioca_base;
+ struct pci_dev *pdev;
+@@ -256,9 +258,7 @@ tioca_fastwrite_enable(struct tioca_kern
+ */
+
+ 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 @@ tioca_dma_d48(struct pci_dev *pdev, uint
+ 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
+--- 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 @@ tioce_alloc_map(struct tioce_kernel *ce_
+
+ 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 @@ tioce_dma_d32(struct pci_dev *pdev, uint
+ 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 @@ tioce_dma_unmap(struct pci_dev *pdev, dm
+ 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_kern_init(struct tioce_common *tio
+ */
+
+ 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 @@ tioce_force_interrupt(struct sn_irq_info
+ 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 @@ tioce_target_interrupt(struct sn_irq_inf
+ 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 @@ tioce_target_interrupt(struct sn_irq_inf
+
+ 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
+--- a/arch/m32r/kernel/entry.S
++++ b/arch/m32r/kernel/entry.S
+@@ -653,8 +653,6 @@ ENTRY(rie_handler)
+ 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
+--- a/arch/m32r/kernel/io_m32700ut.c
++++ b/arch/m32r/kernel/io_m32700ut.c
+@@ -64,11 +64,11 @@ static inline void *__port2addr_ata(unsi
+ * 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
+--- a/arch/m32r/kernel/io_mappi.c
++++ b/arch/m32r/kernel/io_mappi.c
+@@ -31,7 +31,7 @@ extern void pcc_iowrite(int, unsigned lo
+
+ 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
+--- a/arch/m32r/kernel/io_mappi2.c
++++ b/arch/m32r/kernel/io_mappi2.c
+@@ -33,12 +33,9 @@ extern void pcc_iowrite_word(int, unsign
+
+ 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 @@ static inline void *__port2addr_ata(unsi
+ }
+ #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
+--- a/arch/m32r/kernel/io_mappi3.c
++++ b/arch/m32r/kernel/io_mappi3.c
+@@ -36,9 +36,6 @@ static inline void *_port2addr(unsigned
+ 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 @@ static inline void *__port2addr_ata(unsi
+ }
+ #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
+--- 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
+--- a/arch/m32r/kernel/io_opsput.c
++++ b/arch/m32r/kernel/io_opsput.c
+@@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsign
+
+ static inline void *_port2addr(unsigned long port)
+ {
+- return (void *)(port + NONCACHE_OFFSET);
++ return (void *)(port | (NONCACHE_OFFSET));
+ }
+
+ /*
+@@ -44,11 +44,11 @@ static inline void *_port2addr(unsigned
+ * 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
+--- a/arch/m32r/kernel/io_usrv.c
++++ b/arch/m32r/kernel/io_usrv.c
+@@ -47,7 +47,7 @@ static inline void *_port2addr(unsigned
+ 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
+--- a/arch/m32r/kernel/ptrace.c
++++ b/arch/m32r/kernel/ptrace.c
+@@ -756,7 +756,7 @@ do_ptrace(long request, struct task_stru
+ 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
+--- a/arch/m32r/kernel/setup.c
++++ b/arch/m32r/kernel/setup.c
+@@ -305,19 +305,19 @@ static int show_cpuinfo(struct seq_file
+
+ 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 @@ static int show_cpuinfo(struct seq_file
+ 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/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c
+--- a/arch/m32r/kernel/setup_m32700ut.c
++++ b/arch/m32r/kernel/setup_m32700ut.c
+@@ -15,7 +15,7 @@
+ #include <linux/irq.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/m32r.h>
+diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
+--- a/arch/m32r/kernel/setup_mappi.c
++++ b/arch/m32r/kernel/setup_mappi.c
+@@ -11,7 +11,7 @@
+ #include <linux/irq.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/m32r.h>
+diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c
+--- a/arch/m32r/kernel/setup_mappi2.c
++++ b/arch/m32r/kernel/setup_mappi2.c
+@@ -11,7 +11,7 @@
+ #include <linux/irq.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/m32r.h>
+diff --git a/arch/m32r/kernel/setup_mappi3.c b/arch/m32r/kernel/setup_mappi3.c
+--- a/arch/m32r/kernel/setup_mappi3.c
++++ b/arch/m32r/kernel/setup_mappi3.c
+@@ -11,7 +11,7 @@
+ #include <linux/irq.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/m32r.h>
+diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
+--- a/arch/m32r/kernel/setup_opsput.c
++++ b/arch/m32r/kernel/setup_opsput.c
+@@ -16,7 +16,7 @@
+ #include <linux/irq.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/m32r.h>
+diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
+--- a/arch/m32r/kernel/time.c
++++ b/arch/m32r/kernel/time.c
+@@ -39,10 +39,6 @@ extern void send_IPI_allbutself(int, int
+ 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
+--- 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
+--- a/arch/m32r/mm/init.c
++++ b/arch/m32r/mm/init.c
+@@ -48,6 +48,8 @@ void show_mem(void)
+ 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 @@ void show_mem(void)
+ 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 __init reservedpages_count(void)
+ 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
+--- a/arch/m32r/mm/ioremap.c
++++ b/arch/m32r/mm/ioremap.c
+@@ -67,7 +67,7 @@ remap_area_pmd(pmd_t * pmd, unsigned lon
+ 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 @@ remap_area_pages(unsigned long address,
+ 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 @@ remap_area_pages(unsigned long address,
+ 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
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -388,33 +388,11 @@ config AMIGA_PCMCIA
+ 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
+--- 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 @@ typedef struct stram_block {
+ } 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 @@ static BLOCK *alloc_list;
+ #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_init(void)
+ */
+ 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 @@ void atari_stram_mem_init_hook (void)
+
+ /*
+ * 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 @@ void atari_stram_mem_init_hook (void)
+ * 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 @@ void *atari_stram_alloc(long size, const
+
+ 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 @@ void *atari_stram_alloc(long size, const
+ /* 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 @@ void atari_stram_free( void *addr )
+ 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 @@ void atari_stram_free( void *addr )
+ "(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, ®ion_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 get_stram_list( char *buf )
+ {
+ 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 @@ int get_stram_list( char *buf )
+ 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
+--- a/arch/m68k/kernel/ptrace.c
++++ b/arch/m68k/kernel/ptrace.c
+@@ -121,7 +121,7 @@ void ptrace_disable(struct task_struct *
+ 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
+--- 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
+--- a/arch/m68k/mm/kmap.c
++++ b/arch/m68k/mm/kmap.c
+@@ -201,7 +201,7 @@ void *__ioremap(unsigned long physaddr,
+ 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
+--- a/arch/m68k/sun3x/dvma.c
++++ b/arch/m68k/sun3x/dvma.c
+@@ -116,7 +116,7 @@ inline int dvma_map_cpu(unsigned long ka
+ 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/defconfig b/arch/m68knommu/defconfig
+--- a/arch/m68knommu/defconfig
++++ b/arch/m68knommu/defconfig
+@@ -99,7 +99,7 @@ CONFIG_M5272C3=y
+ # CONFIG_NETtel is not set
+ # CONFIG_CPU16B is not set
+ # CONFIG_MOD5272 is not set
+-CONFIG_MOTOROLA=y
++CONFIG_FREESCALE=y
+ # CONFIG_LARGE_ALLOCS is not set
+ CONFIG_4KSTACKS=y
+ CONFIG_RAMAUTO=y
+@@ -554,7 +554,6 @@ CONFIG_EXT2_FS=y
+ # CONFIG_XFS_FS is not set
+ # CONFIG_MINIX_FS is not set
+ CONFIG_ROMFS_FS=y
+-CONFIG_MAGIC_ROM_PTR=y
+ # CONFIG_INOTIFY is not set
+ # CONFIG_QUOTA is not set
+ # CONFIG_DNOTIFY is not set
+diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
+--- a/arch/m68knommu/kernel/ptrace.c
++++ b/arch/m68knommu/kernel/ptrace.c
+@@ -101,7 +101,7 @@ void ptrace_disable(struct task_struct *
+ 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
+--- 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
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -4,216 +4,147 @@ config MIPS
+ # 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"
+
+-config SYS_SUPPORTS_32BIT_KERNEL
+- bool
+-config SYS_SUPPORTS_64BIT_KERNEL
+- bool
+-config CPU_SUPPORTS_32BIT_KERNEL
+- bool
+-config CPU_SUPPORTS_64BIT_KERNEL
+- bool
+-
+-menu "Kernel type"
+-
+-choice
+-
+- prompt "Kernel code model"
+- help
+- You should only select this option if you have a workload that
+- actually benefits from 64-bit processing or if your machine has
+- large memory. You will only be presented a single option in this
+- menu if your system does not support both 32-bit and 64-bit kernels.
+-
+-config 32BIT
+- bool "32-bit kernel"
+- depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL
+- 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
+- help
+- Select this option if you want to build a 64-bit kernel.
+-
+-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.
++choice
++ prompt "System type"
++ default SGI_IP22
+
+-config ACER_PICA_61
+- bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)"
+- depends on MACH_JAZZ && EXPERIMENTAL
++config MIPS_MTX1
++ bool "Support for 4G Systems MTX-1 board"
+ 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/>.
++ select HW_HAS_PCI
++ select SOC_AU1500
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+-config MIPS_MAGNUM_4000
+- bool "Support for MIPS Magnum 4000"
+- depends on MACH_JAZZ
++config MIPS_BOSPORUS
++ bool "AMD Alchemy Bosporus board"
++ select SOC_AU1500
+ 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/>.
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+-config OLIVETTI_M700
+- bool "Support for Olivetti M700-10"
+- depends on MACH_JAZZ
++config MIPS_PB1000
++ bool "AMD Alchemy PB1000 board"
++ select SOC_AU1000
+ 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
++ select HW_HAS_PCI
++ select SWAP_IO_SPACE
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+-config NEC_CMBVR4133
+- bool "Support for NEC CMB-VR4133"
+- depends on MACH_VR41XX
+- select CPU_VR41XX
++config MIPS_PB1100
++ bool "AMD Alchemy PB1100 board"
++ select SOC_AU1100
+ select DMA_NONCOHERENT
+- select IRQ_CPU
+ select HW_HAS_PCI
++ select SWAP_IO_SPACE
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+-config ROCKHOPPER
+- bool "Support for Rockhopper baseboard"
+- depends on NEC_CMBVR4133
+- select I8259
+- select HAVE_STD_PC_SERIAL_PORT
++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 CASIO_E55
+- bool "Support for CASIO CASSIOPEIA E-10/15/55/65"
+- depends on MACH_VR41XX
+- select CPU_LITTLE_ENDIAN
++config MIPS_PB1550
++ bool "AMD Alchemy PB1550 board"
++ select SOC_AU1550
+ select DMA_NONCOHERENT
+- select IRQ_CPU
+- select ISA
++ select HW_HAS_PCI
++ select MIPS_DISABLE_OBSOLETE_IDE
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+-config IBM_WORKPAD
+- bool "Support for IBM WorkPad z50"
+- depends on MACH_VR41XX
+- select CPU_LITTLE_ENDIAN
++config MIPS_PB1200
++ bool "AMD Alchemy PB1200 board"
++ select SOC_AU1200
+ select DMA_NONCOHERENT
+- select IRQ_CPU
+- select ISA
++ select MIPS_DISABLE_OBSOLETE_IDE
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+-config TANBAC_TB022X
+- bool "Support for TANBAC VR4131 multichip module and TANBAC VR4131DIMM"
+- depends on MACH_VR41XX
+- select CPU_LITTLE_ENDIAN
++config MIPS_DB1000
++ bool "AMD Alchemy DB1000 board"
++ select SOC_AU1000
+ 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 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 IRQ_CPU
+- select HW_HAS_PCI
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+-config ZAO_CAPCELLA
+- bool "Support for ZAO Networks Capcella"
+- depends on MACH_VR41XX
+- select CPU_LITTLE_ENDIAN
++config MIPS_DB1500
++ bool "AMD Alchemy DB1500 board"
++ select SOC_AU1500
+ select DMA_NONCOHERENT
+- select IRQ_CPU
+ 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 PCI_VR41XX
+- bool "Add PCI control unit support of NEC VR4100 series"
+- depends on MACH_VR41XX && HW_HAS_PCI
+- default y
+- select PCI
++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 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 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 TOSHIBA_JMR3927
+- bool "Support for Toshiba JMR-TX3927 board"
++config MIPS_MIRAGE
++ bool "AMD Alchemy Mirage board"
+ select DMA_NONCOHERENT
+- select HW_HAS_PCI
+- select SWAP_IO_SPACE
+- select SYS_SUPPORTS_32BIT_KERNEL
++ select SOC_AU1500
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+ config MIPS_COBALT
+ bool "Support for Cobalt Server"
+- depends on EXPERIMENTAL
+ 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
+- ---help---
++ 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/>.
+@@ -234,8 +165,10 @@ config MIPS_EV64120
+ 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
+@@ -243,10 +176,6 @@ config MIPS_EV64120
+ <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
+@@ -256,8 +185,11 @@ config MIPS_EV96100
+ 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
++ 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
+@@ -268,8 +200,11 @@ 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
+@@ -277,37 +212,16 @@ config MIPS_IVR
+ 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 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
+@@ -315,42 +229,86 @@ config MIPS_ITE8172
+ 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
++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
+- 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>.
++ 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 QED R5231-based MIPS Atlas evaluation
++ 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 VR5000-based MIPS Malta evaluation
++ This enables support for the MIPS Technologies Malta evaluation
+ board.
+
+ config MIPS_SEAD
+@@ -358,50 +316,64 @@ config MIPS_SEAD
+ 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
++ 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 MOMENCO_OCELOT
+- bool "Support for Momentum Ocelot board"
++config MIPS_SIM
++ bool 'Support for MIPS simulator (MIPSsim)'
+ 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_MIPS32_R1
++ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_32BIT_KERNEL
+- select SYS_SUPPORTS_64BIT_KERNEL
++ select SYS_SUPPORTS_BIG_ENDIAN
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+ help
+- The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+- Momentum Computer <http://www.momenco.com/>.
++ This option enables support for MIPS Technologies MIPSsim software
++ emulator.
+
+-config MOMENCO_OCELOT_G
+- bool "Support for Momentum Ocelot-G board"
++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 Ocelot is a MIPS-based Single Board Computer (SBC) made by
++ The Jaguar ATX 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"
++config MOMENCO_OCELOT
++ bool "Support for Momentum Ocelot board"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+- select IRQ_MV64340
+- select PCI_MARVELL
++ 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/>.
+@@ -417,80 +389,95 @@ config MOMENCO_OCELOT_3
+ 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_JAGUAR_ATX
+- bool "Support for Momentum Jaguar board"
+- select BOOT_ELF32
++config MOMENCO_OCELOT_C
++ bool "Support for Momentum Ocelot-C board"
+ 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_RM7000
+ 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
++ The Ocelot 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
++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 IRQ_CPU_RM9K
++ 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
+- Yosemite is an evaluation board for the RM9000x2 processor
+- manufactured by PMC-Sierra
++ The Ocelot is a MIPS-based Single Board Computer (SBC) made by
++ Momentum Computer <http://www.momenco.com/>.
+
+-config HYPERTRANSPORT
+- bool "Hypertransport Support for PMC-Sierra Yosemite"
+- depends on PMC_YOSEMITE
++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
++ 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.
+@@ -501,12 +488,15 @@ config DDB5476
+
+ 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.
+@@ -514,10 +504,28 @@ config DDB5477
+ 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 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"
+@@ -527,15 +535,16 @@ config QEMU
+ 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.
++ 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)"
+@@ -543,11 +552,15 @@ config SGI_IP22
+ 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
+@@ -557,70 +570,18 @@ 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_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
+@@ -633,353 +594,152 @@ config SGI_IP32
+ 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 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
++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_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.
++ select SYS_HAS_CPU_SB1
++ select SYS_SUPPORTS_BIG_ENDIAN
++ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+ config SIBYTE_SWARM
+- bool "BCM91250A-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 "BCM91250E-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 "BCM91125E-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 "BCM91120x-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 "BCM91250PT-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 "BCM91250C2-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 "BCM91120C-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 "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"
++ bool "Support for Sibyte BCM91125C-CRhone"
++ depends on EXPERIMENTAL
++ select BOOT_ELF32
++ select DMA_COHERENT
+ 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
++ 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
+@@ -988,15 +748,51 @@ config TOSHIBA_RBTX4927
+ 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_64BIT_KERNEL
++ select SYS_SUPPORTS_LITTLE_ENDIAN
++ select SYS_SUPPORTS_BIG_ENDIAN
++ select TOSHIBA_BOARDS
+ help
+- This Toshiba board is based on the TX4927 processor. Say Y here to
++ This Toshiba board is based on the TX4938 processor. Say Y here to
+ support this machine type
+
+-config TOSHIBA_FPCIB0
+- bool "FPCIB0 Backplane Support"
+- depends on TOSHIBA_RBTX4927
++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
+@@ -1014,8 +810,9 @@ config GENERIC_CALIBRATE_DELAY
+ #
+ 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 ARCH_MAY_HAVE_PC_FDC
++ bool
+
+ config DMA_COHERENT
+ bool
+@@ -1034,51 +831,65 @@ config DMA_NONCOHERENT
+ config DMA_NEED_PCI_MAP_STATE
+ bool
+
++config OWN_DMA
++ 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
++ select SYS_SUPPORTS_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
++#
++# 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. Say Y if your
+- machine is little endian, N if it's a big endian machine.
++ 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
+@@ -1086,42 +897,69 @@ config IRQ_CPU
+ config IRQ_CPU_RM7K
+ bool
+
++config IRQ_CPU_RM9K
++ 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 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
+@@ -1148,6 +986,9 @@ config SYSCLK_100
+
+ endchoice
+
++config ARC32
++ bool
++
+ config AU1X00_USB_DEVICE
+ bool
+ depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
+@@ -1155,11 +996,7 @@ config AU1X00_USB_DEVICE
+
+ 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/>.
++ select MIPS_GT64120
+
+ config IT8172_CIR
+ bool
+@@ -1173,8 +1010,6 @@ config IT8712
+
+ 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
+@@ -1182,11 +1017,6 @@ config MIPS_L1_CACHE_SHIFT
+ 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
+
+@@ -1206,30 +1036,12 @@ config ARC_PROMLIB
+
+ 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"
+
+@@ -1237,18 +1049,69 @@ choice
+ prompt "CPU type"
+ default CPU_R4X00
+
+-config CPU_MIPS32
+- bool "MIPS32"
++config CPU_MIPS32_R1
++ bool "MIPS32 Release 1"
++ depends on SYS_HAS_CPU_MIPS32_R1
++ select CPU_HAS_PREFETCH
+ select CPU_SUPPORTS_32BIT_KERNEL
+-
+-config CPU_MIPS64
+- bool "MIPS64"
++ 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
+@@ -1259,20 +1122,23 @@ config CPU_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 VR41xx series of processors.
++ 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
+@@ -1280,6 +1146,7 @@ config CPU_R4300
+
+ config CPU_R4X00
+ bool "R4x00"
++ depends on SYS_HAS_CPU_R4X00
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
+ help
+@@ -1288,11 +1155,13 @@ config CPU_R4X00
+
+ 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
+@@ -1300,10 +1169,14 @@ config CPU_R5000
+
+ 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
+@@ -1311,6 +1184,7 @@ config CPU_R6000
+
+ config CPU_NEVADA
+ bool "RM52xx"
++ depends on SYS_HAS_CPU_NEVADA
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
+ help
+@@ -1319,6 +1193,8 @@ config CPU_NEVADA
+ 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
+@@ -1326,25 +1202,151 @@ config CPU_R8000
+
+ 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
++ bool
++config CPU_SUPPORTS_32BIT_KERNEL
++ bool
++config CPU_SUPPORTS_64BIT_KERNEL
++ bool
++
++menu "Kernel type"
++
++choice
++
++ prompt "Kernel code model"
++ help
++ You should only select this option if you have a workload that
++ actually benefits from 64-bit processing or if your machine has
++ large memory. You will only be presented a single option in this
++ menu if your system does not support both 32-bit and 64-bit kernels.
++
++config 32BIT
++ bool "32-bit kernel"
++ depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL
++ 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
++ help
++ Select this option if you want to build a 64-bit kernel.
+
+ endchoice
+
+@@ -1416,12 +1418,43 @@ config SIBYTE_DMA_PAGEOPS
+ 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 MIPS_MT
++ bool "Enable MIPS MT"
+
+-config VTAG_ICACHE
+- bool "Support for Virtual Tagged I-cache" if CPU_MIPS64 || CPU_MIPS32
+- default y if CPU_SB1
++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 SB1_PASS_2_1_WORKAROUNDS
+
+ 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_LLSC
+
+ 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 @@ config CPU_HAS_WB
+ 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 @@ config CPU_HAS_SYNC
+ # 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 @@ source "mm/Kconfig"
+
+ 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 @@ config NR_CPUS
+ 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 @@ config MIPS_INSANE_LARGE
+ 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 ISA
+
+ 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 @@ config MMU
+ bool
+ default y
+
+-config MCA
+- bool
+-
+-config SBUS
+- bool
+-
+ source "drivers/pcmcia/Kconfig"
+
+ source "drivers/pci/hotplug/Kconfig"
+@@ -1659,7 +1726,6 @@ source "fs/Kconfig.binfmt"
+
+ config TRAD_SIGNALS
+ bool
+- default y if 32BIT
+
+ config BUILD_ELF64
+ bool "Use 64-bit ELF format for building"
+@@ -1678,7 +1744,7 @@ config BUILD_ELF64
+
+ 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 @@ config BINFMT_ELF32
+ 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 "drivers/Kconfig"
+
+ source "fs/Kconfig"
+
++source "arch/mips/oprofile/Kconfig"
++
+ source "arch/mips/Kconfig.debug"
+
+ source "security/Kconfig"
+@@ -1737,18 +1822,3 @@ source "security/Kconfig"
+ 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
+--- a/arch/mips/Makefile
++++ b/arch/mips/Makefile
+@@ -52,6 +52,21 @@ ifdef CONFIG_CROSSCOMPILE
+ 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 @@ endif
+ 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 @@ cflags-$(CONFIG_CPU_TX49XX) += \
+ $(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 @@ cflags-$(CONFIG_CPU_RM9000) += \
+ $(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 @@ cflags-$(CONFIG_MIPS_PB1550) += -Iinclud
+ 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 @@ cflags-$(CONFIG_MIPS_DB1550) += -Iinclud
+ 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 @@ load-$(CONFIG_MIPS_XXS1500) += 0xfffffff
+ # 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 @@ core-$(CONFIG_MIPS_SEAD) += arch/mips/mi
+ 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_CASIO_E55) += 0xffffffff80
+ 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 @@ load-$(CONFIG_SGI_IP32) += 0xffffffff80
+ # 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 @@ cflags-$(CONFIG_SIBYTE_SB1250) += -Iincl
+ # 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 @@ libs-$(CONFIG_SIBYTE_SENTOSA) += arch/mi
+ 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/
+ 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 @@ ifdef CONFIG_BOOT_ELF64
+ 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 @@ archclean:
+ @$(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
+--- 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
+--- a/arch/mips/arc/identify.c
++++ b/arch/mips/arc/identify.c
+@@ -44,6 +44,11 @@ static struct smatch mach_table[] = {
+ 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
+--- 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
+--- a/arch/mips/au1000/common/au1xxx_irqmap.c
++++ b/arch/mips/au1000/common/au1xxx_irqmap.c
+@@ -173,14 +173,14 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = {
+ { 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 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = {
+ { 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
+--- a/arch/mips/au1000/common/cputable.c
++++ b/arch/mips/au1000/common/cputable.c
+@@ -37,7 +37,8 @@ struct cpu_spec cpu_specs[] = {
+ { 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
+--- 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 @@ static DEFINE_SPINLOCK(au1xxx_dbdma_spin
+ */
+ #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 @@ static dbdev_tab_t dbdev_tab[] = {
+ { 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 @@ static dbdev_tab_t dbdev_tab[] = {
+
+ { 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 @@ find_dbdev_id (u32 id)
+ 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 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
+ 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_chan_alloc(u32 srcid, u32 d
+ 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 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
+ */
+ ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
+ chan_tab_ptr[i] = ctp;
+- ctp->chan_index = chan = i;
+ break;
+ }
+ }
+@@ -279,10 +299,11 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
+
+ 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 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
+ 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 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
+ 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 @@ au1xxx_dbdma_set_devwidth(u32 chanid, in
+
+ return rv;
+ }
++EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth);
+
+ /* Allocate a descriptor ring, initializing as much as possible.
+ */
+@@ -370,7 +395,8 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
+ * 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 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
+ 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 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
+ 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 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
+ /* 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 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
+ /* 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 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
+ 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 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
+
+ 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 @@ au1xxx_dbdma_put_source(u32 chanid, void
+ */
+ 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 @@ au1xxx_dbdma_put_source(u32 chanid, void
+ */
+ 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 @@ au1xxx_dbdma_put_dest(u32 chanid, void *
+ 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 @@ au1xxx_dbdma_put_dest(u32 chanid, void *
+ */
+ 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 @@ void
+ 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 @@ au1xxx_dbdma_stop(u32 chanid)
+ 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 @@ void
+ 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 @@ au1xxx_dbdma_reset(u32 chanid)
+
+ 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_chan_free(u32 chanid)
+
+ 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 @@ au1xxx_dbdma_chan_free(u32 chanid)
+
+ 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 @@ dbdma_interrupt(int irq, void *dev_id, s
+ (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 @@ au1xxx_dbdma_dump(u32 chanid)
+ 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 @@ au1xxx_dbdma_dump(u32 chanid)
+ 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
+--- 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
+--- /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
+--- a/arch/mips/au1000/common/irq.c
++++ b/arch/mips/au1000/common/irq.c
+@@ -83,7 +83,7 @@ inline void local_disable_irq(unsigned i
+ 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 @@ void restore_local_and_enable(int contro
+
+
+ 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 @@ void __init arch_init_irq(void)
+ 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 @@ void intc0_req0_irqdispatch(struct pt_re
+ 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 @@ void intc0_req0_irqdispatch(struct pt_re
+ 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 @@ void intc0_req1_irqdispatch(struct pt_re
+
+ 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
+--- a/arch/mips/au1000/common/platform.c
++++ b/arch/mips/au1000/common/platform.c
+@@ -7,13 +7,16 @@
+ * 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/platform_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 +44,252 @@ static struct platform_device au1xxx_usb
+ .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
+--- 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 @@ int au_sleep(void)
+ }
+
+ 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_sleep(ctl_table * ctl,
+ }
+
+ 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 @@ static int pm_do_suspend(ctl_table * ctl
+ 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_suspend(ctl_table * ctl
+
+
+ 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 @@ static int pm_do_freq(ctl_table * ctl, i
+
+
+ /* 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 @@ __initcall(pm_init);
+ 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
+--- a/arch/mips/au1000/common/prom.c
++++ b/arch/mips/au1000/common/prom.c
+@@ -75,7 +75,8 @@ void prom_init_cmdline(void)
+ }
+ 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
+--- 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 @@ static inline void slow_down(void)
+ #endif
+
+ void
+-putch(const unsigned char c)
++prom_putchar(const unsigned char c)
+ {
+ unsigned char ch;
+ int i = 0;
+@@ -69,77 +68,3 @@ putch(const unsigned char c)
+ } 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
+--- 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_time_init(void);
+ 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 @@ static int __init au1x00_setup(void)
+ /*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 @@ static int __init au1x00_setup(void)
+ 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 @@ phys_t fixup_bigphys_addr(phys_t phys_ad
+ /* 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
+--- 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 @@ unsigned long missed_heart_beats = 0;
+ 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 @@ null:
+ }
+
+ #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 @@ void counter0_irq(int irq, void *dev_id,
+ 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 @@ void au1xxx_timer_setup(struct irqaction
+ {
+ 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 @@ void au1xxx_timer_setup(struct irqaction
+ 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
+--- a/arch/mips/au1000/common/usbdev.c
++++ b/arch/mips/au1000/common/usbdev.c
+@@ -1005,11 +1005,11 @@ process_ep0_receive (struct usb_dev* dev
+ #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 @@ dma_done_ep0_intr(int irq, void *dev_id,
+ clear_dma_done1(ep0->indma);
+
+ pkt = send_packet_complete(ep0);
+- if (pkt)
+- kfree(pkt);
++ kfree(pkt);
+ }
+
+ /*
+@@ -1302,8 +1301,7 @@ usbdev_exit(void)
+ 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
+--- 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
+--- 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
+--- a/arch/mips/au1000/db1x00/mirage_ts.c
++++ b/arch/mips/au1000/db1x00/mirage_ts.c
+@@ -102,15 +102,15 @@ static struct {
+ } 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
+--- 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
+--- 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
+--- 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
+--- a/arch/mips/au1000/pb1000/init.c
++++ b/arch/mips/au1000/pb1000/init.c
+@@ -65,5 +65,4 @@ void __init prom_init(void)
+ 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
+--- /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
+--- /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
+--- /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 at mvista.com or source at mvista.com
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS 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
+--- /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
+--- 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
+--- 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
+--- a/arch/mips/boot/Makefile
++++ b/arch/mips/boot/Makefile
+@@ -33,6 +33,9 @@ vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINU
+ $(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 @@ archhelp:
+
+ clean-files += addinitrd \
+ elf2ecoff \
++ vmlinux.bin \
+ vmlinux.ecoff \
+ vmlinux.srec
+diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
+--- 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
+--- 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
+--- 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 @@ extern void cobalt_handle_int(void);
+ * 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 @@ extern void cobalt_handle_int(void);
+ * 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;
++ GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS);
++ printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending);
+ }
++}
+
+- if (pending & CAUSEF_IP7) { /* int 23 */
+- do_IRQ(COBALT_QUBE_SLOT_IRQ, regs);
+- return;
+- }
++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
+--- 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 at 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
+--- 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>
++#include <asm/cobalt/cobalt.h>
+
+-void cobalt_machine_restart(char *command)
++void cobalt_machine_halt(void)
+ {
+- *(volatile char *)0xbc000000 = 0x0f;
++ int state, last, diff;
++ unsigned long mark;
+
+ /*
+- * 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.
++ * turn off bar on Qube, flash power off LED on RaQ (0.5Hz)
++ *
++ * restart if ENTER and SELECT are pressed
+ */
+- 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)
++ last = COBALT_KEY_PORT;
+
+-void cobalt_machine_halt(void)
+-{
+- int mark;
++ for (state = 0;;) {
++
++ state ^= COBALT_LED_POWER_OFF;
++ COBALT_LED_PORT = state;
++
++ diff = COBALT_KEY_PORT ^ last;
++ last ^= diff;
+
+- /* 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));
++ 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
+--- 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 @@ extern void cobalt_machine_power_off(voi
+
+ 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);
++
++ /* Enable timer */
++ GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS);
+
+- /* Register our timer interrupt */
+- setup_irq(COBALT_TIMER_IRQ, irq);
++ /* Register interrupt */
++ setup_irq(COBALT_GALILEO_IRQ, irq);
+
+- /* Enable timer ints */
+- GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS);
+- /* Unmask timer int */
+- GALILEO_OUTL(0x100, GT_INTRMASK_OFS);
++ /* 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 @@ static struct pci_controller cobalt_pci_
+ .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 @@ static void __init cobalt_setup(void)
+
+ 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 @@ static void __init cobalt_setup(void)
+ 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,42 +59,72 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -118,15 +153,46 @@ CONFIG_CPU_MIPS32=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -160,199 +221,7 @@ CONFIG_BINFMT_ELF=y
+ CONFIG_TRAD_SIGNALS=y
+
+ #
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-
+-#
+-# 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_CPQ_DA is not set
+-# 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=m
+-CONFIG_BLK_DEV_CRYPTOLOOP=m
+-CONFIG_BLK_DEV_NBD=m
+-# CONFIG_BLK_DEV_SX8 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
+-# 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=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_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 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_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=m
+-CONFIG_BLK_DEV_SR=m
+-CONFIG_BLK_DEV_SR_VENDOR=y
+-CONFIG_CHR_DEV_SG=m
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-CONFIG_SCSI_CONSTANTS=y
+-CONFIG_SCSI_LOGGING=y
+-
+-#
+-# SCSI Transport Attributes
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-CONFIG_SCSI_FC_ATTRS=m
+-CONFIG_SCSI_ISCSI_ATTRS=m
+-
+-#
+-# 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_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=y
+-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+-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_ISP 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_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=y
+-CONFIG_BLK_DEV_MD=m
+-CONFIG_MD_LINEAR=m
+-CONFIG_MD_RAID0=m
+-CONFIG_MD_RAID1=m
+-CONFIG_MD_RAID10=m
+-CONFIG_MD_RAID5=m
+-CONFIG_MD_RAID6=m
+-CONFIG_MD_MULTIPATH=m
+-CONFIG_MD_FAULTY=m
+-CONFIG_BLK_DEV_DM=m
+-CONFIG_DM_CRYPT=m
+-CONFIG_DM_SNAPSHOT=m
+-CONFIG_DM_MIRROR=m
+-CONFIG_DM_ZERO=m
+-
+-#
+-# 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
+-
+-#
+-# Networking support
++# Networking
+ #
+ CONFIG_NET=y
+
+@@ -361,15 +230,20 @@ CONFIG_NET=y
+ #
+ 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=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
+@@ -387,8 +261,10 @@ 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
++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
+@@ -433,6 +309,9 @@ 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
+@@ -440,11 +319,15 @@ CONFIG_BRIDGE_NETFILTER=y
+ 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
+@@ -469,9 +352,12 @@ 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
+@@ -488,12 +374,14 @@ 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
+@@ -503,7 +391,7 @@ CONFIG_IP_NF_ARPFILTER=m
+ CONFIG_IP_NF_ARP_MANGLE=m
+
+ #
+-# IPv6: Netfilter Configuration
++# IPv6: Netfilter Configuration (EXPERIMENTAL)
+ #
+ CONFIG_IP6_NF_QUEUE=m
+ CONFIG_IP6_NF_IPTABLES=m
+@@ -523,8 +411,10 @@ 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
+
+ #
+@@ -550,8 +440,11 @@ 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
++
++#
++# DCCP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_DCCP is not set
+
+ #
+ # SCTP Configuration (EXPERIMENTAL)
+@@ -579,10 +472,6 @@ CONFIG_IPDDP_DECAP=y
+ 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
+@@ -602,6 +491,7 @@ 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
+@@ -612,6 +502,7 @@ 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
+
+@@ -619,17 +510,222 @@ 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_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=y
++
++#
++# 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_CPQ_DA is not set
++# 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=m
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_SX8 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=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=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_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 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=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=m
++CONFIG_CHR_DEV_OSST=m
++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
++#
++CONFIG_SCSI_MULTI_LUN=y
++CONFIG_SCSI_CONSTANTS=y
++CONFIG_SCSI_LOGGING=y
++
++#
++# SCSI Transport Attributes
++#
++CONFIG_SCSI_SPI_ATTRS=y
++CONFIG_SCSI_FC_ATTRS=m
++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_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=y
++CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
++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 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=y
++CONFIG_BLK_DEV_MD=m
++CONFIG_MD_LINEAR=m
++CONFIG_MD_RAID0=m
++CONFIG_MD_RAID1=m
++CONFIG_MD_RAID10=m
++CONFIG_MD_RAID5=m
++CONFIG_MD_RAID6=m
++CONFIG_MD_MULTIPATH=m
++CONFIG_MD_FAULTY=m
++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=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
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++# CONFIG_I2O is not set
++
++#
++# Network device support
++#
+ 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_TUN=m
+ # 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_LAN_SAA9730=y
+ # 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 @@ CONFIG_LAN_SAA9730=y
+ # 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_LAN_SAA9730=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_MOUSE_SERIAL=m
+ # 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -855,13 +987,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_SECURITY=y
+ # 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_QUOTACTL=y
+ 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_UFS_FS=m
+ #
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -1051,7 +1189,9 @@ CONFIG_NLS_UTF8=m
+ #
+ # 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_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
+@@ -1097,9 +1238,12 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- /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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,57 +59,86 @@ CONFIG_KMOD=y
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_VR41XX=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -161,6 +212,81 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_IDE_GENERIC=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ # CONFIG_SCSI is not set
+
+ #
+@@ -254,6 +382,7 @@ CONFIG_IDE_GENERIC=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -266,79 +395,13 @@ CONFIG_IDE_GENERIC=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_ETHERNET=y
+ #
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ 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_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_SERIO_RAW=m
+ # 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 @@ CONFIG_HW_CONSOLE=y
+ #
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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 @@ CONFIG_WATCHDOG=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
+@@ -519,10 +613,20 @@ CONFIG_WATCHDOG=y
+ # 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_WATCHDOG=y
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -552,13 +655,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_AUTOFS4_FS=y
+ 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_NFSD=y
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -676,9 +783,11 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -50,41 +53,69 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -109,14 +142,38 @@ CONFIG_CPU_NEVADA=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -150,6 +202,77 @@ CONFIG_BINFMT_ELF=y
+ 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_PREVENT_FIRMWARE_BUILD=y
+ 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 @@ CONFIG_FW_LOADER=y
+ #
+ # 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_LOOP=y
+ # 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 @@ CONFIG_IDE_GENERIC=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -244,6 +371,7 @@ CONFIG_IDE_GENERIC=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -256,75 +384,13 @@ CONFIG_IDE_GENERIC=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=y
+ # 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_8250_NR_UARTS=4
+ #
+ 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_COBALT_LCD=y
+ # 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_COBALT_LCD=y
+ # 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_COBALT_LCD=y
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -526,13 +628,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_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=y
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -589,12 +694,10 @@ CONFIG_DNOTIFY=y
+ 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_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -651,7 +755,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,63 +59,79 @@ 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=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_MIPS32=y
+ # 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_MMU=y
+ 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_PCMCIA=m
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -238,6 +450,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -248,94 +461,28 @@ CONFIG_ATA_OVER_ETH=m
+ #
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# QoS and/or fair queueing
++# PHY device support
+ #
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
++CONFIG_PHYLIB=m
++CONFIG_PHYCONTROL=y
+
+ #
+-# Network testing
++# MII PHY device drivers
+ #
+-# 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
++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_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
+@@ -418,18 +567,6 @@ CONFIG_INPUT_EVDEV=y
+ # 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_SERIO_RAW=m
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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_SYNCLINK_CS=m
+ # CONFIG_RAW_DRIVER is not set
+
+ #
++# TPM devices
++#
++
++#
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+@@ -499,10 +650,20 @@ CONFIG_SYNCLINK_CS=m
+ # 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_SYNCLINK_CS=m
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -532,12 +692,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # InfiniBand support
+ #
+-# CONFIG_INFINIBAND is not set
++
++#
++# SN Devices
++#
+
+ #
+ # File systems
+@@ -561,6 +721,7 @@ 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
+@@ -579,10 +740,12 @@ 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=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -603,13 +766,10 @@ CONFIG_AUTOFS4_FS=m
+ 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_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=m
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_HPFS_FS is not set
+@@ -641,6 +803,7 @@ CONFIG_NFSD=m
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,63 +59,79 @@ 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=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_MIPS32=y
+ # 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 @@ CONFIG_MMU=y
+ #
+ # 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_PCMCIA=m
+ 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_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
++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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -236,6 +438,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -246,101 +449,35 @@ CONFIG_ATA_OVER_ETH=m
+ #
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# QoS and/or fair queueing
++# PHY device support
+ #
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
++CONFIG_PHYLIB=m
++CONFIG_PHYCONTROL=y
+
+ #
+-# Network testing
++# MII PHY device drivers
+ #
+-# 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
++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_MII=m
+ # 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_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
+@@ -416,18 +542,6 @@ CONFIG_INPUT_EVDEV=y
+ # 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_SERIO_RAW=m
+ # 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 @@ CONFIG_HW_CONSOLE=y
+ #
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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_SYNCLINK_CS=m
+ # 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 @@ CONFIG_SYNCLINK_CS=m
+ #
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # InfiniBand support
+ #
+-# CONFIG_INFINIBAND is not set
++
++#
++# SN Devices
++#
+
+ #
+ # File systems
+@@ -556,6 +722,7 @@ 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
+@@ -574,10 +741,12 @@ 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=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -598,13 +767,10 @@ CONFIG_AUTOFS4_FS=m
+ 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_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=m
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_HPFS_FS is not set
+@@ -636,6 +804,7 @@ CONFIG_NFSD=m
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- /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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,63 +59,81 @@ 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=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_MIPS32=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ 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_PCMCIA_AU1X00=m
+ 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_TRAD_SIGNALS=y
+ #
+ 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_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_XIP is not set
+
+ #
+ # Mapping drivers for chip access
+ #
+ # 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 @@ CONFIG_MTD_DB1X00_USER=y
+ #
+ # 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_LOOP=y
+ # 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 @@ CONFIG_BLK_DEV_IDECS=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -346,6 +488,7 @@ CONFIG_BLK_DEV_IDECS=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -358,94 +501,13 @@ CONFIG_BLK_DEV_IDECS=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_MIPS_AU1X00_ENET=y
+ # 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 @@ CONFIG_MIPS_AU1X00_ENET=y
+ # 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_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
+@@ -549,19 +634,6 @@ CONFIG_INPUT_EVDEV=y
+ # 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_SERIO_RAW=m
+ # 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=y
+ 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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_SYNCLINK_CS=m
+ # 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_SYNCLINK_CS=m
+ # 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 @@ CONFIG_SYNCLINK_CS=m
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -680,7 +779,6 @@ CONFIG_SOUND_AU1000=y
+ # 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 @@ CONFIG_SOUND_AU1000=y
+ #
+ # 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=y
+ # 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_HIDINPUT=y
+ # 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_HIDINPUT=y
+ # 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_HIDINPUT=y
+ # 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_USB_HIDINPUT=y
+ # 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_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=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -855,13 +969,10 @@ CONFIG_AUTOFS4_FS=m
+ 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_NFSD=m
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,63 +59,80 @@ 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=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_MIPS32=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ 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_PCMCIA_AU1X00=m
+ 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_TRAD_SIGNALS=y
+ #
+ 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_CFI_UTIL=y
+ #
+ # 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 @@ CONFIG_MTD_NAND_AU1550=m
+ #
+ # 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_LOOP=y
+ # 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_IDEDMA_PCI=y
+ # 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 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -377,6 +520,7 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -389,94 +533,13 @@ CONFIG_BLK_DEV_IDEDMA=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_MIPS_AU1X00_ENET=y
+ # 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 @@ CONFIG_MIPS_AU1X00_ENET=y
+ # 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_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
+@@ -588,19 +674,6 @@ CONFIG_INPUT_EVDEV=y
+ # 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_SERIO_RAW=m
+ # 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=y
+ 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_SYNCLINK_CS=m
+ # 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_SYNCLINK_CS=m
+ # 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 @@ CONFIG_SYNCLINK_CS=m
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -697,13 +796,9 @@ CONFIG_SYNCLINK_CS=m
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_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=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -769,13 +871,10 @@ CONFIG_AUTOFS4_FS=m
+ 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_NFSD=m
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -50,41 +53,69 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=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
+@@ -110,14 +143,38 @@ CONFIG_CPU_R5432=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # 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_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_IDE_GENERIC=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -254,6 +382,7 @@ CONFIG_IDE_GENERIC=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -266,78 +395,13 @@ CONFIG_IDE_GENERIC=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=y
+ # 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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=y
+ # 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=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -697,7 +809,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -50,42 +53,70 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -110,14 +143,38 @@ CONFIG_CPU_R5432=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -151,6 +203,80 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -222,6 +352,7 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -234,78 +365,13 @@ CONFIG_ATA_OVER_ETH=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_PCNET32=y
+ # 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 @@ CONFIG_PCNET32=y
+ # 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_PCNET32=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=y
+ # 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -527,13 +629,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_AUTOFS4_FS=y
+ 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_NFSD=y
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -651,7 +757,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -49,48 +53,76 @@ CONFIG_MODULES=y
+ 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_MIPS_L1_CACHE_SHIFT=4
+ #
+ # 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_R3000=y
+ # 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -150,6 +205,80 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_NOOP=y
+ 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -213,10 +346,12 @@ 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_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 @@ CONFIG_SCSI_CONSTANTS=y
+ #
+ # 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 @@ CONFIG_SCSI_DECNCR=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -258,78 +395,28 @@ CONFIG_SCSI_DECNCR=y
+ #
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# QoS and/or fair queueing
++# PHY device support
+ #
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
++CONFIG_PHYLIB=m
++CONFIG_PHYCONTROL=y
+
+ #
+-# Network testing
++# MII PHY device drivers
+ #
+-# 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
++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_DECLANCE=y
+ # 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 @@ CONFIG_DECLANCE=y
+ #
+ # Input device support
+ #
+-CONFIG_INPUT=y
++# CONFIG_INPUT is not set
+
+ #
+-# 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 I/O drivers
++# Hardware I/O ports
+ #
++# 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # Graphics support
+ #
+-# CONFIG_FB is not set
+-
+-#
+-# Console display driver support
+-#
+-# CONFIG_VGA_CONSOLE is not set
+-CONFIG_DUMMY_CONSOLE=y
++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
++
++#
++# Logo configuration
++#
++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_DUMMY_CONSOLE=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # InfiniBand support
+ #
+-# CONFIG_INFINIBAND is not set
++
++#
++# SN Devices
++#
+
+ #
+ # File systems
+@@ -529,6 +619,7 @@ 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
+@@ -538,10 +629,12 @@ 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=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -562,12 +655,10 @@ CONFIG_DNOTIFY=y
+ 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_RAMFS=y
+ # 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 @@ CONFIG_ULTRIX_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,56 +59,84 @@ CONFIG_KMOD=y
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_VR41XX=y
+ # 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-CONFIG_PCMCIA_PROBE=y
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -157,6 +207,78 @@ CONFIG_BINFMT_ELF=y
+ 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_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
+@@ -185,18 +312,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_NOOP=y
+ 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 @@ CONFIG_IDE_GENERIC=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ # CONFIG_SCSI is not set
+
+ #
+@@ -252,6 +375,7 @@ CONFIG_IDE_GENERIC=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -262,76 +386,13 @@ CONFIG_IDE_GENERIC=y
+ #
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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=y
+ #
+ 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_SERIO_RAW=m
+ # 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 @@ CONFIG_HW_CONSOLE=y
+ #
+ # 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 @@ CONFIG_WATCHDOG=y
+ #
+ # 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_WATCHDOG=y
+ # 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_WATCHDOG=y
+ # 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_DUMMY_CONSOLE=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_AUTOFS4_FS=y
+ 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 @@ CONFIG_RAMFS=y
+ #
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -654,9 +744,11 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,41 +59,69 @@ CONFIG_MODULE_SRCVERSION_ALL=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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -117,15 +150,39 @@ CONFIG_CPU_R5000=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -159,6 +211,79 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -230,6 +359,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -242,77 +372,13 @@ CONFIG_ATA_OVER_ETH=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_PPP_ASYNC=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=m
+ # 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -521,13 +623,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -643,7 +748,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,40 +59,68 @@ CONFIG_MODULE_SRCVERSION_ALL=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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -116,6 +149,18 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ 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_PAGE_SIZE_4KB=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -158,6 +213,79 @@ CONFIG_BINFMT_ELF=y
+ 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_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
+@@ -185,13 +318,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -224,6 +356,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -234,77 +367,28 @@ CONFIG_ATA_OVER_ETH=m
+ #
+
+ #
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
++# Network device support
+ #
+-# 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
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# QoS and/or fair queueing
++# PHY device support
+ #
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
++CONFIG_PHYLIB=m
++CONFIG_PHYCONTROL=y
+
+ #
+-# Network testing
++# MII PHY device drivers
+ #
+-# 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
++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_MIPS_GT96100ETH=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=m
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -480,10 +576,6 @@ CONFIG_DUMMY_CONSOLE=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -597,7 +695,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -57,41 +60,69 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_ARC_PROMLIB=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
+@@ -120,22 +153,48 @@ CONFIG_CPU_R5000=y
+ # 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -160,115 +215,7 @@ CONFIG_BINFMT_MISC=m
+ 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_NET=y
+ #
+ 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_AH=m
+ 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_INET6_TUNNEL=m
+ 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_NETFILTER=y
+ 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_OWNER=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
+@@ -395,12 +356,14 @@ 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
+@@ -410,7 +373,7 @@ CONFIG_IP_NF_ARPFILTER=m
+ 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_LENGTH=m
+ 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_SCTP_HMAC_MD5=y
+ 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_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
+@@ -489,6 +454,7 @@ CONFIG_NET_CLS_U32=m
+ # 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 @@ 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_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_SGISEEQ=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_MOUSE_SERIAL=m
+ # 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 @@ CONFIG_SGI_DS1286=m
+ #
+ # 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_MAX_RAW_DEVS=256
+ # 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=y
+ # 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_LOGO_SGI_CLUT224=y
+ # 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 @@ CONFIG_LOGO_SGI_CLUT224=y
+ #
+ # 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_FS_MBCACHE=y
+ # 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_QUOTACTL=y
+ CONFIG_DNOTIFY=y
+ CONFIG_AUTOFS_FS=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -781,12 +898,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_UFS_FS=m
+ #
+ 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_CIFS=m
+ 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 @@ CONFIG_NLS_UTF8=m
+ #
+ # 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_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
+@@ -942,10 +1066,10 @@ CONFIG_CRYPTO_TEA=m
+ 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 @@ CONFIG_CRYPTO_TEST=m
+ # 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
+--- 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_64BIT=y
+ 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_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
+@@ -57,55 +62,85 @@ CONFIG_STOP_MACHINE=y
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_R10000=y
+ # 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_HW_HAS_PCI=y
+ CONFIG_PCI=y
+ CONFIG_PCI_DOMAINS=y
+ CONFIG_PCI_LEGACY_PROC=y
+-CONFIG_PCI_NAMES=y
+ CONFIG_MMU=y
+
+ #
+@@ -150,10 +209,6 @@ CONFIG_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -163,7 +218,7 @@ CONFIG_MMU=y
+ #
+ 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_MIPS32_O32=y
+ 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_BINFMT_ELF32=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_CRYPTOLOOP=m
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -241,8 +405,10 @@ CONFIG_SCSI_PROC_FS=y
+ 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_LOGGING=y
+ #
+ 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_SCSI_SPI_ATTRS=y
+ # 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_CRYPT=m
+ 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_DM_ZERO=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_SGI_IOC3_ETH_HW_TX_CSUM=y
+ # 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 @@ CONFIG_SGI_IOC3_ETH_HW_TX_CSUM=y
+ # 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_SGI_IOC3_ETH_HW_TX_CSUM=y
+ # 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_SGI_IOC3_ETH_HW_TX_CSUM=y
+ # CONFIG_INPUT is not set
+
+ #
+-# Userland interfaces
+-#
+-
+-#
+-# Input I/O drivers
++# Hardware I/O ports
+ #
+-# 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_EXTENDED=y
+ 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_8250_SHARE_IRQ=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
+@@ -584,6 +669,11 @@ CONFIG_SGI_IP27_RTC=y
+ # 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_SGI_IP27_RTC=y
+ # 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 @@ CONFIG_SGI_IP27_RTC=y
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -621,13 +720,9 @@ CONFIG_SGI_IP27_RTC=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_FS_MBCACHE=y
+ # 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_AUTOFS_FS=m
+ 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_RAMFS=y
+ #
+ 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_RPCSEC_GSS_KRB5=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -772,7 +874,9 @@ CONFIG_SGI_PARTITION=y
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_TEST=m
+ # 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
+--- 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_64BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_POSIX_MQUEUE is not set
+@@ -25,13 +25,16 @@ CONFIG_BSD_PROCESS_ACCT=y
+ # 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_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
+@@ -50,42 +54,71 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_ARC_PROMLIB=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
+@@ -112,6 +147,17 @@ CONFIG_CPU_R5000=y
+ # 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_PAGE_SIZE_4KB=y
+ 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -160,6 +214,80 @@ CONFIG_MIPS32_O32=y
+ 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_BINFMT_ELF32=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_LOOP=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -233,6 +365,7 @@ CONFIG_CHR_DEV_OSST=y
+ 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 @@ CONFIG_SCSI_LOGGING=y
+ #
+ # 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_AIC7XXX_REG_PRETTY_PRINT=y
+ # 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_QLA2XXX=y
+ # 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 @@ CONFIG_SCSI_QLA2XXX=y
+ # 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_SCSI_QLA2XXX=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_SGI_O2MACE_ETH=y
+ # 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 @@ CONFIG_SGI_O2MACE_ETH=y
+ # 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_SGI_O2MACE_ETH=y
+ # 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,27 +566,25 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_EVBUG is not set
+
+ #
+-# Input I/O drivers
++# 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_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
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
++# CONFIG_GAMEPORT is not set
+
+ #
+ # Character devices
+@@ -518,6 +607,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -587,13 +691,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_RAMFS=y
+ #
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -721,7 +828,9 @@ CONFIG_SGI_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_POSIX_MQUEUE is not set
+@@ -26,13 +25,16 @@ CONFIG_BSD_PROCESS_ACCT=y
+ # 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_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
+@@ -57,41 +60,69 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -117,14 +150,39 @@ CONFIG_CPU_NEVADA=y
+ # 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -155,6 +209,80 @@ CONFIG_BINFMT_ELF=y
+ 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_PREVENT_FIRMWARE_BUILD=y
+ # 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_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_XIP is not set
+
+ #
+ # Mapping drivers for chip access
+@@ -217,6 +349,7 @@ CONFIG_MTD_PHYSMAP=y
+ 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 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+ #
+ # 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 @@ CONFIG_IDE_GENERIC=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -312,6 +444,7 @@ CONFIG_IDE_GENERIC=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -322,78 +455,28 @@ CONFIG_IDE_GENERIC=y
+ #
+
+ #
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
++# Network device support
+ #
+-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
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# SCTP Configuration (EXPERIMENTAL)
++# PHY device support
+ #
+-# 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_PHYLIB=m
++CONFIG_PHYCONTROL=y
+
+ #
+-# QoS and/or fair queueing
++# MII PHY device drivers
+ #
+-# 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
++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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=m
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -574,15 +669,9 @@ CONFIG_SOUND=y
+ # 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_SOUND_IT8172=y
+ # 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 @@ CONFIG_SOUND_IT8172=y
+ #
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -711,7 +802,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_POSIX_MQUEUE is not set
+@@ -26,13 +25,16 @@ CONFIG_BSD_PROCESS_ACCT=y
+ # 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_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
+@@ -57,40 +60,68 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -115,14 +148,38 @@ CONFIG_CPU_NEVADA=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -156,6 +208,80 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_IDE_GENERIC=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -249,6 +379,7 @@ CONFIG_IDE_GENERIC=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -261,78 +392,13 @@ CONFIG_IDE_GENERIC=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=m
+ # 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_8250_NR_UARTS=4
+ #
+ 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_RTC=y
+ # 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_RTC=y
+ # 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_RTC=y
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -535,13 +637,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -657,7 +762,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ # 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_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
+@@ -54,36 +57,70 @@ 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 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_MIPS_SIM is not set
++CONFIG_MOMENCO_JAGUAR_ATX=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_MOMENCO_JAGUAR_ATX=y
+-CONFIG_JAGUAR_DMALOW=y
+-# CONFIG_PMC_YOSEMITE 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 @@ 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
+@@ -112,6 +151,17 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ # 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_PAGE_SIZE_4KB=y
+ 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_HIGHMEM=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -158,6 +214,68 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -228,6 +350,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -240,58 +363,8 @@ CONFIG_ATA_OVER_ETH=m
+ # 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_NETDEVICES=y
+ # 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_EEPRO100=y
+ # 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 @@ CONFIG_MV643XX_ETH_2=y
+ #
+ # Ethernet (10000 Mbit)
+ #
++# CONFIG_CHELSIO_T1 is not set
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+
+@@ -366,6 +457,8 @@ CONFIG_MV643XX_ETH_2=y
+ # 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_MV643XX_ETH_2=y
+ # 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_MV643XX_ETH_2=y
+ # CONFIG_INPUT is not set
+
+ #
+-# Userland interfaces
+-#
+-
+-#
+-# Input I/O drivers
++# Hardware I/O ports
+ #
+-# 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # CONFIG_RAW_DRIVER is not set
+
+ #
++# TPM devices
++#
++
++#
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+@@ -461,10 +551,20 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -488,13 +587,9 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # CONFIG_INFINIBAND is not set
+
+ #
++# SN Devices
++#
++
++#
+ # File systems
+ #
+ # CONFIG_EXT2_FS is not set
+@@ -519,13 +618,16 @@ CONFIG_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -50,40 +53,68 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_TOSHIBA_BOARDS=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=y
+ # CONFIG_CPU_VR41XX is not set
+@@ -109,12 +142,34 @@ CONFIG_CPU_TX39XX=y
+ # 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_RTC_DS1742=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -149,6 +199,80 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -220,6 +348,7 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -232,78 +361,13 @@ CONFIG_ATA_OVER_ETH=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=y
+ # 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_SERIAL_NONSTANDARD=y
+ # 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_SERIAL_NONSTANDARD=y
+ # 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 @@ CONFIG_TXX927_SERIAL_CONSOLE=y
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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=y
+ # 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=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # CONFIG_INFINIBAND is not set
+
+ #
++# SN Devices
++#
++
++#
+ # File systems
+ #
+ # CONFIG_EXT2_FS is not set
+@@ -579,13 +684,16 @@ CONFIG_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -667,7 +776,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,53 +59,83 @@ 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 is not set
+ # CONFIG_MIPS_EV64120 is not set
+ # CONFIG_MIPS_EV96100 is not set
+ # CONFIG_MIPS_IVR is not set
+-CONFIG_LASAT=y
+-CONFIG_PICVUE=y
+-CONFIG_PICVUE_PROC=y
+-CONFIG_DS1603=y
+-CONFIG_LASAT_SYSCTL=y
+ # 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_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_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_PICVUE=y
++CONFIG_PICVUE_PROC=y
++CONFIG_DS1603=y
++CONFIG_LASAT_SYSCTL=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_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_R5000=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -162,6 +214,76 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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_CFI_UTIL=y
+ # 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 @@ CONFIG_MTD_LASAT=y
+ #
+ # 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_MTD_LASAT=y
+ # 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_CMD64X=y
+ # 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 @@ CONFIG_IDEDMA_AUTO=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -353,6 +481,7 @@ CONFIG_IDEDMA_AUTO=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -365,68 +494,8 @@ CONFIG_IDEDMA_AUTO=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=m
+ # 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -633,13 +738,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_JBD=y
+ 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_DNOTIFY=y
+ 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_RAMFS=y
+ #
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -762,7 +871,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,44 +59,75 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+ #
+ # 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_MIPS32=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -162,229 +227,7 @@ CONFIG_BINFMT_ELF=y
+ CONFIG_TRAD_SIGNALS=y
+
+ #
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-
+-#
+-# 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=m
+-# 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=m
+-# 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_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
+-# 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=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_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 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 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=y
+-# 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_SCSI=m
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=m
+-CONFIG_CHR_DEV_ST=m
+-CONFIG_CHR_DEV_OSST=m
+-CONFIG_BLK_DEV_SR=m
+-CONFIG_BLK_DEV_SR_VENDOR=y
+-CONFIG_CHR_DEV_SG=m
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-CONFIG_SCSI_CONSTANTS=y
+-CONFIG_SCSI_LOGGING=y
+-
+-#
+-# SCSI Transport Attributes
+-#
+-CONFIG_SCSI_SPI_ATTRS=m
+-CONFIG_SCSI_FC_ATTRS=m
+-CONFIG_SCSI_ISCSI_ATTRS=m
+-
+-#
+-# SCSI low-level drivers
+-#
+-CONFIG_BLK_DEV_3W_XXXX_RAID=m
+-CONFIG_SCSI_3W_9XXX=m
+-CONFIG_SCSI_ACARD=m
+-CONFIG_SCSI_AACRAID=m
+-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=y
+-# 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_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
+-# 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_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=y
+-CONFIG_BLK_DEV_MD=m
+-CONFIG_MD_LINEAR=m
+-CONFIG_MD_RAID0=m
+-CONFIG_MD_RAID1=m
+-CONFIG_MD_RAID10=m
+-CONFIG_MD_RAID5=m
+-CONFIG_MD_RAID6=m
+-CONFIG_MD_MULTIPATH=m
+-CONFIG_MD_FAULTY=m
+-CONFIG_BLK_DEV_DM=m
+-CONFIG_DM_CRYPT=m
+-CONFIG_DM_SNAPSHOT=m
+-CONFIG_DM_MIRROR=m
+-CONFIG_DM_ZERO=m
+-
+-#
+-# 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
+-
+-#
+-# Networking support
++# Networking
+ #
+ CONFIG_NET=y
+
+@@ -393,15 +236,20 @@ CONFIG_NET=y
+ #
+ 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=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
+@@ -419,8 +267,10 @@ 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
++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
+@@ -465,6 +315,9 @@ 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
+@@ -472,11 +325,15 @@ CONFIG_BRIDGE_NETFILTER=y
+ 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
+@@ -501,9 +358,12 @@ 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
+@@ -520,12 +380,14 @@ 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
+@@ -535,133 +397,373 @@ CONFIG_IP_NF_ARPFILTER=m
+ CONFIG_IP_NF_ARP_MANGLE=m
+
+ #
+-# IPv6: Netfilter Configuration
++# 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
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++
++#
++# 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_FD=m
++# 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=m
++# 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_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=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=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_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 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 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=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_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_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
++CONFIG_RAID_ATTRS=m
++CONFIG_SCSI=m
++CONFIG_SCSI_PROC_FS=y
+
+ #
+-# Bridge: Netfilter Configuration
++# SCSI support type (disk, tape, CD-ROM)
+ #
+-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
++CONFIG_BLK_DEV_SD=m
++CONFIG_CHR_DEV_ST=m
++CONFIG_CHR_DEV_OSST=m
++CONFIG_BLK_DEV_SR=m
++CONFIG_BLK_DEV_SR_VENDOR=y
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
+
+ #
+-# SCTP Configuration (EXPERIMENTAL)
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+ #
+-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_SCSI_MULTI_LUN=y
++CONFIG_SCSI_CONSTANTS=y
++CONFIG_SCSI_LOGGING=y
+
+ #
+-# QoS and/or fair queueing
++# SCSI Transport Attributes
+ #
+-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
++CONFIG_SCSI_SPI_ATTRS=m
++CONFIG_SCSI_FC_ATTRS=m
++CONFIG_SCSI_ISCSI_ATTRS=m
++CONFIG_SCSI_SAS_ATTRS=m
+
+ #
+-# Network testing
++# SCSI low-level drivers
++#
++CONFIG_BLK_DEV_3W_XXXX_RAID=m
++CONFIG_SCSI_3W_9XXX=m
++CONFIG_SCSI_ACARD=m
++CONFIG_SCSI_AACRAID=m
++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=y
++# 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=m
++# 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=y
++CONFIG_BLK_DEV_MD=m
++CONFIG_MD_LINEAR=m
++CONFIG_MD_RAID0=m
++CONFIG_MD_RAID1=m
++CONFIG_MD_RAID10=m
++CONFIG_MD_RAID5=m
++CONFIG_MD_RAID6=m
++CONFIG_MD_MULTIPATH=m
++CONFIG_MD_FAULTY=m
++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=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
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++# CONFIG_I2O is not set
++
++#
++# Network device support
+ #
+-# 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_TUN=m
+ # 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_PCNET32=y
+ # 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 @@ CONFIG_PCNET32=y
+ # 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_PCNET32=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_SERPORT=y
+ # 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_8250_NR_UARTS=4
+ #
+ 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_RTC=y
+ # 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_RTC=y
+ # 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_RTC=y
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -883,13 +1021,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_SECURITY=y
+ # 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_QUOTACTL=y
+ 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_UFS_FS=m
+ #
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -1079,7 +1223,9 @@ CONFIG_NLS_UTF8=m
+ #
+ # 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_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
+@@ -1125,9 +1272,12 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- /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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,57 +59,86 @@ CONFIG_KMOD=y
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_VR41XX=y
+ # 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_CPU_HAS_SYNC=y
+ 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_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -244,79 +408,13 @@ CONFIG_ATA_OVER_ETH=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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
+-#
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_NET_PCI is not set
++# Ethernet (10 or 100Mbit)
++#
++# CONFIG_NET_ETHERNET is not set
++CONFIG_MII=m
+
+ #
+ # Ethernet (1000 Mbit)
+@@ -349,12 +441,16 @@ CONFIG_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ #
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=m
+ # 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 @@ CONFIG_HW_CONSOLE=y
+ #
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -518,13 +686,120 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_AUTOFS4_FS=y
+ 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_FS=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -640,9 +921,11 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -57,40 +60,68 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_MOMENCO_JAGUAR_ATX is not set
+-# CONFIG_PMC_YOSEMITE 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_IRQ_MV64340=y
+@@ -102,8 +133,10 @@ 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
+@@ -119,6 +152,17 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ # 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_PAGE_SIZE_4KB=y
+ 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -166,6 +218,110 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_LOOP=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ CONFIG_SCSI=m
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -237,6 +397,7 @@ CONFIG_SCSI_PROC_FS=y
+ # 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_PROC_FS=y
+ # 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_SCSI_PROC_FS=y
+ # 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_QLA2XXX=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
+@@ -300,6 +459,8 @@ CONFIG_SCSI_QLA2XXX=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
+@@ -312,105 +473,13 @@ CONFIG_SCSI_QLA2XXX=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_TUN=m
+ # 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_NET_PCI=y
+ # 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_E100=y
+ # 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 @@ CONFIG_MV643XX_ETH_2=y
+ #
+ # Ethernet (10000 Mbit)
+ #
++# CONFIG_CHELSIO_T1 is not set
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+
+@@ -486,6 +573,8 @@ CONFIG_MV643XX_ETH_2=y
+ # 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_PPPOE=m
+ # 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=y
+ # 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_SERIO=y
+ # 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_8250_NR_UARTS=4
+ #
+ 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_RTC=y
+ # 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_RTC=y
+ # 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 @@ CONFIG_RTC=y
+ # 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_MODE_HELPERS=y
+ # 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_MODE_HELPERS=y
+ # 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 @@ CONFIG_LOGO_LINUX_CLUT224=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_FS=m
+ # 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_AUTOFS4_FS=m
+ 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_CRAMFS=y
+ #
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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 @@ CONFIG_CMDLINE="ip=any root=nfs"
+ #
+ # 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 @@ CONFIG_CMDLINE="ip=any root=nfs"
+ # 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
+--- 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_64BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -49,39 +53,68 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_MOMENCO_JAGUAR_ATX is not set
+-# CONFIG_PMC_YOSEMITE 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 @@ 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
+@@ -108,6 +143,17 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ 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_PAGE_SIZE_4KB=y
+ 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -156,6 +211,79 @@ CONFIG_MIPS32_N32=y
+ 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_BINFMT_ELF32=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -226,6 +358,7 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -238,77 +371,13 @@ CONFIG_ATA_OVER_ETH=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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 @@ CONFIG_NET_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=y
+ # 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -511,13 +616,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFSD=y
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -635,7 +744,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -50,40 +53,68 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_MOMENCO_JAGUAR_ATX is not set
+-# CONFIG_PMC_YOSEMITE 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 @@ 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
+@@ -113,6 +146,17 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ 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_PAGE_SIZE_4KB=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -155,6 +209,79 @@ CONFIG_BINFMT_ELF=y
+ 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -221,6 +352,7 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -231,77 +363,28 @@ CONFIG_ATA_OVER_ETH=y
+ #
+
+ #
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
++# Network device support
+ #
+-# 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
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# QoS and/or fair queueing
++# PHY device support
+ #
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
++CONFIG_PHYLIB=y
++CONFIG_PHYCONTROL=y
+
+ #
+-# Network testing
++# MII PHY device drivers
+ #
+-# 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
++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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=y
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -476,10 +571,6 @@ CONFIG_DUMMY_CONSOLE=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_DNOTIFY=y
+ 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_NFSD=y
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -595,7 +693,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_64BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -49,39 +53,68 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_MOMENCO_JAGUAR_ATX is not set
+-# CONFIG_PMC_YOSEMITE 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 @@ 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
+@@ -111,6 +146,17 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ 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_PAGE_SIZE_4KB=y
+ 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -159,6 +214,79 @@ CONFIG_MIPS32_N32=y
+ 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_BINFMT_ELF32=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -229,6 +361,7 @@ CONFIG_ATA_OVER_ETH=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -241,77 +374,13 @@ CONFIG_ATA_OVER_ETH=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_GALILEO_64240_ETH=y
+ # 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 @@ CONFIG_GALILEO_64240_ETH=y
+ # 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_GALILEO_64240_ETH=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=y
+ # 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_8250_NR_UARTS=4
+ #
+ 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -514,13 +619,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFSD=y
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -638,7 +747,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,56 +59,70 @@ 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=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -130,15 +149,39 @@ CONFIG_CPU_MIPS32=y
+ # 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_MMU=y
+ 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_PCMCIA=m
+ 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_TRAD_SIGNALS=y
+ #
+ 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_CFI_UTIL=y
+ #
+ # 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 @@ CONFIG_MTD_PB1500_USER=y
+ #
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -310,6 +452,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -320,94 +463,28 @@ CONFIG_ATA_OVER_ETH=m
+ #
+
+ #
+-# Networking 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)
++# Network device support
+ #
+-# 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_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# QoS and/or fair queueing
++# PHY device support
+ #
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
++CONFIG_PHYLIB=m
++CONFIG_PHYCONTROL=y
+
+ #
+-# Network testing
++# MII PHY device drivers
+ #
+-# 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
++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_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
+@@ -482,18 +561,6 @@ CONFIG_INPUT_EVDEV=y
+ # 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_SERIO_RAW=m
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # 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_SYNCLINK_CS=m
+ # CONFIG_RAW_DRIVER is not set
+
+ #
++# TPM devices
++#
++
++#
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+@@ -560,10 +641,20 @@ CONFIG_SYNCLINK_CS=m
+ # 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_SYNCLINK_CS=m
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -593,12 +683,9 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # InfiniBand support
+ #
+-# CONFIG_INFINIBAND is not set
++
++#
++# SN Devices
++#
+
+ #
+ # File systems
+@@ -622,6 +712,7 @@ 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
+@@ -640,10 +731,12 @@ 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=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -664,13 +757,10 @@ CONFIG_AUTOFS4_FS=m
+ 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_NFSD=m
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,63 +59,80 @@ 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=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_MIPS32=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ 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_PCCARD_NONSTATIC=m
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_LOOP=y
+ # 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_IDEDMA_PCI=y
+ 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 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -302,6 +516,7 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -314,94 +529,13 @@ CONFIG_BLK_DEV_IDEDMA=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_MIPS_AU1X00_ENET=y
+ # 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 @@ CONFIG_MIPS_AU1X00_ENET=y
+ # 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_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
+@@ -513,19 +670,6 @@ CONFIG_INPUT_EVDEV=y
+ # 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_SERIO_RAW=m
+ # 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=y
+ 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_SYNCLINK_CS=m
+ # 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_SYNCLINK_CS=m
+ # 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 @@ CONFIG_SYNCLINK_CS=m
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -622,13 +792,9 @@ CONFIG_SYNCLINK_CS=m
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_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=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -694,13 +867,10 @@ CONFIG_AUTOFS4_FS=m
+ 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_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=m
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_HPFS_FS is not set
+@@ -732,6 +904,7 @@ CONFIG_NFSD=m
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_MICHAEL_MIC=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,63 +59,80 @@ 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=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_MIPS32=y
+ # 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_CPU_HAS_SYNC=y
+ 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_MMU=y
+ 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_PCCARD_NONSTATIC=m
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_LOOP=y
+ # 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_IDEDMA_PCI=y
+ 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 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -302,6 +516,7 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -314,94 +529,13 @@ CONFIG_BLK_DEV_IDEDMA=y
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_MIPS_AU1X00_ENET=y
+ # 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 @@ CONFIG_MIPS_AU1X00_ENET=y
+ # 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_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
+@@ -505,19 +662,6 @@ CONFIG_INPUT_EVDEV=y
+ # 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_SERIO_RAW=m
+ # 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=y
+ 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_SYNCLINK_CS=m
+ # 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_SYNCLINK_CS=m
+ # 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 @@ CONFIG_SYNCLINK_CS=m
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -614,13 +784,9 @@ CONFIG_SYNCLINK_CS=m
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_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=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -686,13 +859,10 @@ CONFIG_AUTOFS4_FS=m
+ 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_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=m
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_HPFS_FS is not set
+@@ -724,6 +896,7 @@ CONFIG_NFSD=m
+ 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_SMB_FS=m
+ # 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_CRC32C=m
+ # 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
+--- /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
+--- /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
+--- 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 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
+ # 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_LOCALVERSION=""
+ # 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_BASE_SMALL=1
+ # 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_QEMU=y
+ # 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_QEMU=y
+ # 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 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+ #
+ # 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_HAVE_STD_PC_SERIAL_PORT=y
+ # 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_R4X00=y
+ # 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_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_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_IP_PNP_BOOTP=y
+ # 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 @@ CONFIG_TCP_CONG_BIC=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=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_STANDALONE=y
+ # 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 @@ CONFIG_STANDALONE=y
+ #
+ # 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 @@ CONFIG_IOSCHED_NOOP=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -331,6 +350,21 @@ CONFIG_NETDEVICES=y
+ # 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 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+-# CONFIG_I2C_SENSOR is not set
+
+ #
+ # Dallas's 1-wire bus
+@@ -481,12 +514,17 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # InfiniBand support
+ #
+-# CONFIG_INFINIBAND is not set
+
+ #
+ # SN Devices
+@@ -547,10 +584,6 @@ CONFIG_DUMMY_CONSOLE=y
+ # 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_INOTIFY=y
+ # 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 @@ CONFIG_INOTIFY=y
+ #
+ # 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 @@ CONFIG_CMDLINE="console=ttyS0 debug ip=1
+ # 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 @@ CONFIG_CMDLINE="console=ttyS0 debug ip=1
+ # 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
+--- /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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ CONFIG_POSIX_MQUEUE=y
+@@ -26,14 +25,17 @@ CONFIG_BSD_PROCESS_ACCT=y
+ # 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_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,43 +61,73 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_ARC_PROMLIB=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
+@@ -123,24 +158,49 @@ CONFIG_CPU_R4X00=y
+ # 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_MMU=y
+ # 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_BINFMT_MISC=m
+ 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_TRAD_SIGNALS=y
+ #
+ 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_PREVENT_FIRMWARE_BUILD=y
+ #
+ 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 @@ CONFIG_PARPORT_1284=y
+ # 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_UB=m
+ 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -283,384 +617,131 @@ CONFIG_CHR_DEV_ST=m
+ # CONFIG_CHR_DEV_OSST is not set
+ CONFIG_BLK_DEV_SR=m
+ CONFIG_BLK_DEV_SR_VENDOR=y
+-# 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=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_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_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_SCSI_IN2000 is not set
+-CONFIG_MEGARAID_NEWGEN=y
+-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
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-CONFIG_SCSI_PPA=m
+-CONFIG_SCSI_IMM=m
+-# CONFIG_SCSI_IZIP_EPP16 is not set
+-# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+-# CONFIG_SCSI_NCR53C406A 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_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
+-# 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_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
+-
+-#
+-# Old CD-ROM drivers (not SCSI, not IDE)
+-#
+-# CONFIG_CD_NO_IDESCSI 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=m
+-CONFIG_MD_RAID5=m
+-# CONFIG_MD_RAID6 is not set
+-CONFIG_MD_MULTIPATH=m
+-CONFIG_MD_FAULTY=m
+-CONFIG_BLK_DEV_DM=m
+-# CONFIG_DM_CRYPT is not set
+-CONFIG_DM_SNAPSHOT=m
+-CONFIG_DM_MIRROR=m
+-CONFIG_DM_ZERO=m
+-
+-#
+-# 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
+-
+-#
+-# Networking 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
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
+
+ #
+-# IPv6: Netfilter Configuration
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+ #
+-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
++# CONFIG_SCSI_MULTI_LUN is not set
++CONFIG_SCSI_CONSTANTS=y
++# CONFIG_SCSI_LOGGING is not set
+
+ #
+-# DECnet: Netfilter Configuration
++# SCSI Transport Attributes
+ #
+-CONFIG_DECNET_NF_GRABULATOR=m
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++CONFIG_SCSI_SAS_ATTRS=m
+
+ #
+-# Bridge: Netfilter Configuration
++# SCSI low-level drivers
+ #
+-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
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AHA152X 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_SCSI_IN2000 is not set
++CONFIG_MEGARAID_NEWGEN=y
++CONFIG_MEGARAID_MM=m
++CONFIG_MEGARAID_MAILBOX=m
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_DTC3280 is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GENERIC_NCR5380 is not set
++# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++CONFIG_SCSI_PPA=m
++CONFIG_SCSI_IMM=m
++# CONFIG_SCSI_IZIP_EPP16 is not set
++# CONFIG_SCSI_IZIP_SLOW_CTR is not set
++# CONFIG_SCSI_NCR53C406A 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_PAS16 is not set
++# CONFIG_SCSI_PSI240I is not set
++# CONFIG_SCSI_QLOGIC_FAS 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_SYM53C416 is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_T128 is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
+
+ #
+-# SCTP Configuration (EXPERIMENTAL)
++# Old CD-ROM drivers (not SCSI, not IDE)
+ #
+-# 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_CD_NO_IDESCSI is not set
+
+ #
+-# QoS and/or fair queueing
++# Multi-device support (RAID and LVM)
+ #
+-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
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=m
++CONFIG_MD_LINEAR=m
++CONFIG_MD_RAID0=m
++CONFIG_MD_RAID1=m
++CONFIG_MD_RAID10=m
++CONFIG_MD_RAID5=m
++# CONFIG_MD_RAID6 is not set
++CONFIG_MD_MULTIPATH=m
++CONFIG_MD_FAULTY=m
++CONFIG_BLK_DEV_DM=m
++# CONFIG_DM_CRYPT is not set
++CONFIG_DM_SNAPSHOT=m
++CONFIG_DM_MIRROR=m
++CONFIG_DM_ZERO=m
++CONFIG_DM_MULTIPATH=m
++CONFIG_DM_MULTIPATH_EMC=m
+
+ #
+-# Network testing
++# Fusion MPT device support
+ #
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-CONFIG_HAMRADIO=y
++# CONFIG_FUSION is not set
++# CONFIG_FUSION_SPI is not set
++# CONFIG_FUSION_FC is not set
+
+ #
+-# Packet Radio protocols
++# IEEE 1394 (FireWire) support
+ #
+-CONFIG_AX25=m
+-CONFIG_AX25_DAMA_SLAVE=y
+-CONFIG_NETROM=m
+-CONFIG_ROSE=m
++# CONFIG_IEEE1394 is not set
+
+ #
+-# AX.25 network device drivers
++# I2O device support
++#
++# CONFIG_I2O is not set
++
++#
++# Network device support
+ #
+-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_ETHERTAP=m
+ # 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_MII=y
+ # 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_NET_ISA=y
+ # 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_EEPRO100=m
+ # 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 @@ CONFIG_VIA_VELOCITY=m
+ # 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_PLIP=m
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_MOUSE_PS2=y
+ # 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_EXTENDED=y
+ # 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_RTC=m
+ # 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_RTC=m
+ 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_W1_SMEM=m
+ 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_DEVICEFS=y
+ # 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_ARCH_HAS_OHCI=y
+ 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_PRINTER=m
+ #
+ 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_KBD=m
+ 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_KAWETH=m
+ 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_USS720=m
+ #
+ 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_KLSI=m
+ 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_CYTHERM=m
+ 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_USB_TEST=m
+ # 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_REISERFS_FS_SECURITY=y
+ # 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_NTFS_FS=m
+ 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_UFS_FS=m
+ #
+ 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=m
+ 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 @@ CONFIG_NLS_UTF8=m
+ #
+ # 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_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
+@@ -1360,13 +1486,13 @@ CONFIG_CRYPTO_AES=m
+ 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 @@ CONFIG_CRYPTO_TEST=m
+ # 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
+--- 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_32BIT=y
+ 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_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
+@@ -57,32 +61,49 @@ CONFIG_STOP_MACHINE=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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_SWARM=y
+ # 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_1=y
+ # 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 @@ 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
+@@ -138,22 +166,46 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ # 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_NR_CPUS=2
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -183,7 +230,86 @@ CONFIG_MMU=y
+ #
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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=y
+ 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_BLK_DEV_IDEFLOPPY=y
+ #
+ 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 @@ CONFIG_BLK_DEV_IDE_SWARM=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -282,6 +411,7 @@ CONFIG_BLK_DEV_IDE_SWARM=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -294,78 +424,13 @@ CONFIG_BLK_DEV_IDE_SWARM=y
+ # 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_NETDEVICES=y
+ # 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_MII=y
+ # 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 @@ CONFIG_NET_SB1250_MAC=y
+ # 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_NET_SB1250_MAC=y
+ # 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_NET_SB1250_MAC=y
+ # CONFIG_INPUT is not set
+
+ #
+-# Userland interfaces
+-#
+-
+-#
+-# Input I/O drivers
++# Hardware I/O ports
+ #
+-# 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_SERIO_RAW=m
+ 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 @@ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -552,13 +647,9 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_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=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -615,11 +713,10 @@ CONFIG_DNOTIFY=y
+ 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_RAMFS=y
+ #
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -678,7 +777,9 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ #
+ 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 @@ CONFIG_CRYPTO_MICHAEL_MIC=y
+ # 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
+--- 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_32BIT=y
+ 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_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
+@@ -48,40 +50,69 @@ CONFIG_CC_ALIGN_JUMPS=0
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ 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
+@@ -106,15 +139,42 @@ CONFIG_CPU_MIPS32=y
+ # 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -143,6 +199,11 @@ CONFIG_BINFMT_ELF=y
+ CONFIG_TRAD_SIGNALS=y
+
+ #
++# Networking
++#
++# CONFIG_NET is not set
++
++#
+ # Device Drivers
+ #
+
+@@ -154,6 +215,10 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+
+ #
++# Connector - unified userspace <-> kernelspace linker
++#
++
++#
+ # Memory Technology Devices (MTD)
+ #
+ # CONFIG_MTD is not set
+@@ -170,7 +235,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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=y
+ 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 @@ CONFIG_IOSCHED_CFQ=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=y
+ # CONFIG_SCSI is not set
+
+ #
+@@ -210,6 +272,7 @@ CONFIG_IOSCHED_CFQ=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -220,9 +283,8 @@ CONFIG_IOSCHED_CFQ=y
+ #
+
+ #
+-# 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 @@ CONFIG_IOSCHED_CFQ=y
+ #
+ # Input device support
+ #
+-CONFIG_INPUT=y
++# CONFIG_INPUT is not set
+
+ #
+-# 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 I/O drivers
++# Hardware I/O ports
+ #
++# 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_8250_NR_UARTS=4
+ #
+ 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_DUMMY_CONSOLE=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_DNOTIFY=y
+ 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 @@ CONFIG_RAMFS=y
+ #
+ # 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 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,55 +59,87 @@ CONFIG_KMOD=y
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_VR41XX=y
+ # 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_MMU=y
+ # 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_BINFMT_ELF=y
+ 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_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
+@@ -183,19 +326,21 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # 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_SCSI_PROC_FS=y
+ 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_CONSTANTS=y
+ # 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 @@ CONFIG_SCSI_CONSTANTS=y
+ #
+ # 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
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
++# Network device support
+ #
+-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
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
+
+ #
+-# SCTP Configuration (EXPERIMENTAL)
++# ARCnet devices
+ #
+-# 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_ARCNET is not set
+
+ #
+-# QoS and/or fair queueing
++# PHY device support
+ #
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
++CONFIG_PHYLIB=m
++CONFIG_PHYCONTROL=y
+
+ #
+-# Network testing
++# MII PHY device drivers
+ #
+-# 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
++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 @@ 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_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_SERIO_RAW=m
+ # 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 @@ CONFIG_HW_CONSOLE=y
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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 @@ CONFIG_LEGACY_PTY_COUNT=256
+ #
+ # 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
++# Sound
+ #
+-# CONFIG_LOGO is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++# CONFIG_SOUND is not set
+
+ #
+-# Sound
++# USB support
+ #
+-CONFIG_SOUND=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
+
+ #
+-# Advanced Linux Sound Architecture
++# Miscellaneous USB options
+ #
+-# CONFIG_SND is not set
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
+
+ #
+-# Open Sound System
++# USB Host Controller Drivers
+ #
+-# CONFIG_SOUND_PRIME is not set
++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 support
++# USB Device Class drivers
+ #
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI 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_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_SOUND=y
+ # 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_CRAMFS=m
+ #
+ 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_SMB_NLS_REMOTE="cp932"
+ # 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 @@ CONFIG_NLS_ISO8859_1=m
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,58 +59,87 @@ CONFIG_KMOD=y
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_VR41XX=y
+ # 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_CPU_HAS_SYNC=y
+ #
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -162,6 +213,88 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_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=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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ # CONFIG_SCSI is not set
+
+ #
+@@ -236,6 +374,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -248,83 +387,13 @@ CONFIG_ATA_OVER_ETH=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking 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
++# Network device support
+ #
+-# 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_DUMMY=m
+ # 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_MII=y
+ # 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_EEPRO100=y
+ # 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_EEPRO100=y
+ # 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 @@ CONFIG_EEPRO100=y
+ # 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_SMART=y
+ 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 @@ 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_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_SERIO_RAW=m
+ # 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 @@ CONFIG_HW_CONSOLE=y
+ #
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ # 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_LEGACY_PTY_COUNT=256
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -556,13 +659,122 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_FS=m
+ # 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_CRAMFS=m
+ #
+ 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_SMB_NLS_REMOTE="cp932"
+ # 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 @@ CONFIG_NLS_ISO8859_1=m
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_INIT_ENV_ARG_LIMIT=32
+ 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,74 +56,91 @@ CONFIG_OBSOLETE_MODPARM=y
+ 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_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_TB022X=y
+-# CONFIG_TANBAC_TB0226 is not set
+-CONFIG_TANBAC_TB0287=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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_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_SOC_AU1X00 is not set
+-# CONFIG_SIBYTE_SB1xxx_SOC 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
++# 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
+@@ -138,12 +156,25 @@ CONFIG_CPU_VR41XX=y
+ # 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_MANUAL=y
+ 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 @@ CONFIG_TCP_CONG_HTCP=m
+ # 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_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
+@@ -296,7 +334,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_COUNT=16
+ 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_NOOP=y
+ 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_BLK_DEV_SD=y
+ # 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_BLK_DEV_SD=y
+ # 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_SCSI_QLA2XXX=y
+ # 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_NET_ETHERNET=y
+ 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 @@ CONFIG_R8169=y
+ # Wireless LAN (non-hamradio)
+ #
+ # CONFIG_NET_RADIO is not set
++# CONFIG_HOSTAP is not set
+
+ #
+ # Wan interfaces
+@@ -682,6 +733,7 @@ CONFIG_GPIO_VR41XX=y
+ # TPM devices
+ #
+ # CONFIG_TCG_TPM is not set
++# CONFIG_TELCLOCK is not set
+
+ #
+ # I2C support
+@@ -770,12 +822,15 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ #
+ # 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 @@ CONFIG_USB_MON=y
+ #
+
+ #
++# EDAC - error detection and reporting (RAS)
++#
++# CONFIG_EDAC is not set
++
++#
+ # Distributed Lock Manager
+ #
+ # CONFIG_DLM is not set
+@@ -901,20 +961,22 @@ CONFIG_USB_MON=y
+ 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_SYSFS=y
+ 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_MSDOS_PARTITION=y
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -56,56 +59,84 @@ CONFIG_KMOD=y
+ #
+ # 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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_VR41XX=y
+ # 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 @@ 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
+
+ #
+ # PC-card bridges
+ #
++# CONFIG_I82365 is not set
++# CONFIG_TCIC is not set
+ CONFIG_PCMCIA_PROBE=y
+
+ #
+@@ -157,6 +218,78 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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=y
+ # 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 @@ CONFIG_IDE_GENERIC=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ # CONFIG_SCSI is not set
+
+ #
+@@ -252,6 +387,7 @@ CONFIG_IDE_GENERIC=y
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -262,76 +398,13 @@ CONFIG_IDE_GENERIC=y
+ #
+
+ #
+-# Networking support
+-#
+-CONFIG_NET=y
+-
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_ETHERNET=y
+ # 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_NET_ETHERNET=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_SERIO_RAW=m
+ # 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 @@ CONFIG_HW_CONSOLE=y
+ #
+ # 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 @@ CONFIG_WATCHDOG=y
+ #
+ # 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_WATCHDOG=y
+ # 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_WATCHDOG=y
+ # 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_DUMMY_CONSOLE=y
+ # 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 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # InfiniBand support
+ #
+-# CONFIG_INFINIBAND is not set
++
++#
++# SN Devices
++#
+
+ #
+ # File systems
+@@ -561,6 +677,7 @@ 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
+@@ -570,10 +687,12 @@ 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=y
+ CONFIG_AUTOFS4_FS=y
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -594,12 +713,10 @@ CONFIG_AUTOFS4_FS=y
+ 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=y
+ # 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -658,9 +777,11 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- 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_32BIT=y
+ # 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_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
+@@ -56,34 +60,68 @@ CONFIG_STOP_MACHINE=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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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=y
+-# CONFIG_HYPERTRANSPORT 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 @@ 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
+@@ -110,20 +150,43 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
+ # 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_NR_CPUS=2
+ 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -155,6 +214,69 @@ CONFIG_BINFMT_ELF=y
+ 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_TRAD_SIGNALS=y
+ #
+ 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 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ #
+ # 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_PREVENT_FIRMWARE_BUILD=y
+ # 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 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ # CONFIG_SCSI is not set
+
+ #
+@@ -226,6 +352,7 @@ CONFIG_ATA_OVER_ETH=m
+ #
+ # Fusion MPT device support
+ #
++# CONFIG_FUSION is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -238,59 +365,8 @@ CONFIG_ATA_OVER_ETH=m
+ # 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_NETDEVICES=y
+ # 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_MII=y
+ # 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 @@ CONFIG_TITAN_GE=y
+ # 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_TITAN_GE=y
+ # 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_TITAN_GE=y
+ # CONFIG_INPUT is not set
+
+ #
+-# Userland interfaces
+-#
+-
+-#
+-# Input I/O drivers
++# Hardware I/O ports
+ #
+-# 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_8250_NR_UARTS=4
+ #
+ 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_GEN_RTC_X=y
+ # CONFIG_RAW_DRIVER is not set
+
+ #
++# TPM devices
++#
++
++#
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+@@ -442,10 +535,20 @@ CONFIG_GEN_RTC_X=y
+ # 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 @@ CONFIG_GEN_RTC_X=y
+ # Graphics support
+ #
+ # CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -469,13 +571,9 @@ CONFIG_GEN_RTC_X=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # CONFIG_INFINIBAND is not set
+
+ #
++# SN Devices
++#
++
++#
+ # File systems
+ #
+ # CONFIG_EXT2_FS is not set
+@@ -500,13 +602,16 @@ CONFIG_USB_ARCH_HAS_OHCI=y
+ # 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_DNOTIFY=y
+ 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_NFS_FS=y
+ # 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 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ #
+ # 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 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
+ # 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
+--- /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
+--- a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
++++ b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
+@@ -209,14 +209,13 @@ static void nile4_irq_end(unsigned int i
+ #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
+--- a/arch/mips/ddb5xxx/ddb5074/setup.c
++++ b/arch/mips/ddb5xxx/ddb5074/setup.c
+@@ -85,7 +85,7 @@ static void __init ddb_time_init(void)
+
+
+
+-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 @@ static void __init ddb5074_setup(void)
+ 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
+--- a/arch/mips/ddb5xxx/ddb5476/setup.c
++++ b/arch/mips/ddb5xxx/ddb5476/setup.c
+@@ -124,7 +124,7 @@ static struct {
+
+ 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 @@ static void __init ddb5476_setup(void)
+ 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
+--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
++++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+@@ -53,14 +53,13 @@ static void vrc5476_irq_end(uint irq)
+ }
+
+ 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
+--- a/arch/mips/ddb5xxx/ddb5477/irq_5477.c
++++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
+@@ -90,14 +90,13 @@ vrc5477_irq_end(unsigned int irq)
+ }
+
+ 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
+--- a/arch/mips/ddb5xxx/ddb5477/setup.c
++++ b/arch/mips/ddb5xxx/ddb5477/setup.c
+@@ -170,7 +170,7 @@ static void ddb5477_board_init(void);
+ 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 @@ static int ddb5477_setup(void)
+
+ 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
+--- 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
+--- 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 @@ static int dec_ecc_be_backend(struct pt_
+
+ 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 @@ static int dec_ecc_be_backend(struct pt_
+ 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 @@ static int dec_ecc_be_backend(struct pt_
+
+ 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 @@ static int dec_ecc_be_backend(struct pt_
+ /* 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 @@ static int dec_ecc_be_backend(struct pt_
+ } 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 @@ static int dec_ecc_be_backend(struct pt_
+ 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 @@ static int dec_ecc_be_backend(struct pt_
+ 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 @@ irqreturn_t dec_ecc_be_interrupt(int irq
+ 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 @@ irqreturn_t dec_ecc_be_interrupt(int irq
+ */
+ 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_kn02_be_init(void
+
+ 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 @@ static inline void dec_kn03_be_init(void
+ *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
+--- 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/addrspace.h>
+ #include <asm/asm.h>
+-#include <asm/regdef.h>
+ #include <asm/mipsregs.h>
++#include <asm/regdef.h>
+ #include <asm/stackframe.h>
+-#include <asm/addrspace.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
+--- /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
+--- 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 int kn02_irq_base;
+
+ 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 unmask_kn02_irq(unsig
+
+ 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 @@ static struct hw_interrupt_type kn02_irq
+
+ 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
+--- /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
+--- 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 @@ EXPORT_SYMBOL(dec_rtc_base);
+
+ 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
+--- 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 which_prom(s32 magic, s32 *p
+
+ 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 @@ void __init prom_init(void)
+ #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 @@ void __init prom_init(void)
+ #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
+--- a/arch/mips/dec/prom/memory.c
++++ b/arch/mips/dec/prom/memory.c
+@@ -35,22 +35,22 @@ static inline void pmax_setup_memory_reg
+ 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 @@ static inline void rex_setup_memory_regi
+ 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
+--- a/arch/mips/dec/reset.c
++++ b/arch/mips/dec/reset.c
+@@ -14,7 +14,7 @@ typedef void ATTRIB_NORET (* noret_func_
+
+ 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
+--- 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 irqreturn_t dec_intr_halt(int irq
+
+ 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 @@ unsigned long dec_kn_slot_size;
+ 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 @@ static struct irqaction haltirq = {
+ /*
+ * 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 @@ void __init dec_be_init(void)
+ 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 @@ static void __init decstation_setup(void
+ _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 @@ static int_ptr kn01_cpu_mask_nr_tbl[][2]
+ { .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 @@ static int_ptr kn230_cpu_mask_nr_tbl[][2
+ { .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 @@ static int_ptr kn02_asic_mask_nr_tbl[][2
+ { .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 @@ static int_ptr kn02ba_asic_mask_nr_tbl[]
+ { .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 @@ static int_ptr kn02ca_asic_mask_nr_tbl[]
+ { .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 @@ static int_ptr kn03_asic_mask_nr_tbl[][2
+ { .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 @@ void __init arch_init_irq(void)
+ 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
+--- 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_32BIT=y
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
+
+ #
+ # General setup
+ #
+ CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_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_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
+@@ -57,41 +60,69 @@ 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 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_MIPS_SIM is not set
++# CONFIG_MOMENCO_JAGUAR_ATX 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_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 @@ CONFIG_ARC_PROMLIB=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
+@@ -120,22 +153,48 @@ CONFIG_CPU_R5000=y
+ # 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_MMU=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
+-#
+-
+-#
+ # PCI Hotplug Support
+ #
+
+@@ -160,115 +215,7 @@ CONFIG_BINFMT_MISC=m
+ 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_NET=y
+ #
+ 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_AH=m
+ 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_INET6_TUNNEL=m
+ 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_NETFILTER=y
+ 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_OWNER=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
+@@ -395,12 +356,14 @@ 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
+@@ -410,7 +373,7 @@ CONFIG_IP_NF_ARPFILTER=m
+ 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_LENGTH=m
+ 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_SCTP_HMAC_MD5=y
+ 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_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
+@@ -489,6 +454,7 @@ CONFIG_NET_CLS_U32=m
+ # 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 @@ 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_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_SGISEEQ=y
+ # 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_MOUSEDEV_SCREEN_Y=768
+ # 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_MOUSE_SERIAL=m
+ # 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 @@ CONFIG_SGI_DS1286=m
+ #
+ # 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_MAX_RAW_DEVS=256
+ # 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=y
+ # 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_LOGO_SGI_CLUT224=y
+ # 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 @@ CONFIG_LOGO_SGI_CLUT224=y
+ #
+ # 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_FS_MBCACHE=y
+ # 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_QUOTACTL=y
+ CONFIG_DNOTIFY=y
+ CONFIG_AUTOFS_FS=m
+ CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -781,12 +898,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_UFS_FS=m
+ #
+ 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_CIFS=m
+ 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 @@ CONFIG_NLS_UTF8=m
+ #
+ # 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_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
+@@ -942,10 +1066,10 @@ CONFIG_CRYPTO_TEA=m
+ 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 @@ CONFIG_CRYPTO_TEST=m
+ # 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
+--- a/arch/mips/galileo-boards/ev96100/setup.c
++++ b/arch/mips/galileo-boards/ev96100/setup.c
+@@ -55,7 +55,7 @@ extern void mips_reboot_setup(void);
+
+ 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 @@ static void __init ev96100_setup(void)
+ 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
+--- /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
+--- a/arch/mips/gt64120/ev64120/setup.c
++++ b/arch/mips/gt64120/ev64120/setup.c
+@@ -69,7 +69,7 @@ unsigned long __init prom_free_prom_memo
+ */
+ 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 @@ static void __init ev64120_setup(void)
+ 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
+--- a/arch/mips/gt64120/momenco_ocelot/setup.c
++++ b/arch/mips/gt64120/momenco_ocelot/setup.c
+@@ -150,7 +150,7 @@ void PMON_v2_setup()
+ 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 @@ static void __init momenco_ocelot_setup(
+ 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
+--- /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
+--- a/arch/mips/ite-boards/generic/irq.c
++++ b/arch/mips/ite-boards/generic/irq.c
+@@ -138,14 +138,13 @@ static void end_ite_irq(unsigned int irq
+ }
+
+ 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 @@ static void ack_none(unsigned int irq) {
+ #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 @@ void __init arch_init_irq(void)
+ 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
+--- a/arch/mips/ite-boards/generic/it8172_setup.c
++++ b/arch/mips/ite-boards/generic/it8172_setup.c
+@@ -105,7 +105,7 @@ void __init it8172_init_ram_resource(uns
+ 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 @@ static void __init it8172_setup(void)
+ #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
+--- /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
+--- a/arch/mips/jazz/irq.c
++++ b/arch/mips/jazz/irq.c
+@@ -58,14 +58,13 @@ static void end_r4030_irq(unsigned int i
+ }
+
+ 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
+--- a/arch/mips/jazz/setup.c
++++ b/arch/mips/jazz/setup.c
+@@ -50,7 +50,7 @@ static struct resource jazz_io_resources
+ { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+ };
+
+-static void __init jazz_setup(void)
++void __init plat_setup(void)
+ {
+ int i;
+
+@@ -97,5 +97,3 @@ static void __init jazz_setup(void)
+
+ vdma_init();
+ }
+-
+-early_initcall(jazz_setup);
+diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
+--- a/arch/mips/jmr3927/rbhma3100/irq.c
++++ b/arch/mips/jmr3927/rbhma3100/irq.c
+@@ -412,13 +412,13 @@ void __init arch_init_irq(void)
+ }
+
+ 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
+--- 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 @@ static void jmr3927_board_init(void);
+ 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 @@ static void __init jmr3927_setup(void)
+ */
+ 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 @@ static void __init jmr3927_setup(void)
+ 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 @@ static void __init jmr3927_board_init(vo
+ 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
+--- a/arch/mips/kernel/Makefile
++++ b/arch/mips/kernel/Makefile
+@@ -11,11 +11,7 @@ obj-y += cpu-probe.o branch.o entry.o g
+ 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_CPU_R6000) += r6000_fpu.o
+
+ 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_PROC_FS) += proc.o
+
+ 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
+--- a/arch/mips/kernel/asm-offsets.c
++++ b/arch/mips/kernel/asm-offsets.c
+@@ -95,6 +95,7 @@ void output_thread_info_defines(void)
+ 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 @@ void output_mm_defines(void)
+ linefeed;
+ }
+
++#ifdef CONFIG_32BIT
+ void output_sc_defines(void)
+ {
+ text("/* Linux sigcontext offsets. */");
+@@ -251,10 +253,29 @@ void output_sc_defines(void)
+ 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
+--- a/arch/mips/kernel/binfmt_elfn32.c
++++ b/arch/mips/kernel/binfmt_elfn32.c
+@@ -52,7 +52,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
+
+ #include <asm/processor.h>
+ #include <linux/module.h>
+-#include <linux/config.h>
+ #include <linux/elfcore.h>
+ #include <linux/compat.h>
+
+@@ -116,4 +115,7 @@ MODULE_AUTHOR("Ralf Baechle (ralf at linux-
+ #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
+--- a/arch/mips/kernel/binfmt_elfo32.c
++++ b/arch/mips/kernel/binfmt_elfo32.c
+@@ -54,7 +54,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
+
+ #include <asm/processor.h>
+ #include <linux/module.h>
+-#include <linux/config.h>
+ #include <linux/elfcore.h>
+ #include <linux/compat.h>
+
+@@ -98,7 +97,7 @@ struct elf_prpsinfo32
+ #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 @@ jiffies_to_compat_timeval(unsigned long
+ #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 @@ MODULE_AUTHOR("Ralf Baechle (ralf at linux-
+ #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
+--- 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 @@ int __compute_return_epc(struct pt_regs
+ 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 @@ int __compute_return_epc(struct pt_regs
+ * 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 @@ unaligned:
+ 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
+--- 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 @@ static void r4k_wait(void)
+ ".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 = ¤t_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 @@ static inline void check_wait(void)
+ /* 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 @@ static inline int __cpu_has_fpu(void)
+ 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 @@ static inline void cpu_probe_legacy(stru
+ 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 @@ static inline void cpu_probe_legacy(stru
+ 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 @@ static inline void cpu_probe_legacy(stru
+ 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 @@ static inline void cpu_probe_legacy(stru
+ #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 cpu_probe_legacy(stru
+ }
+ }
+
+-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();
++
++ 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;
+
+- /* 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;
+ 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 @@ static inline void cpu_probe_alchemy(str
+ 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 = ¤t_cpu_data;
+@@ -571,15 +678,24 @@ __init void cpu_probe(void)
+ 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
+--- /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
+--- 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 @@ FEXPORT(ret_from_irq)
+ 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 @@ need_resched:
+ 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 @@ FEXPORT(restore_partial) # restore part
+ 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 @@ work_notifysig: # deal with pending s
+ 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 @@ FEXPORT(syscall_exit_work)
+ /*
+ * 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
+--- 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
+--- a/arch/mips/kernel/gdb-stub.c
++++ b/arch/mips/kernel/gdb-stub.c
+@@ -176,8 +176,10 @@ int kgdb_enabled;
+ /*
+ * 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 @@ static struct gdb_bp_save async_bp;
+ * 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 @@ void handle_exception (struct gdb_regs *
+ * 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 @@ finish_kgdb:
+ 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 @@ void adel(void)
+ * 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
+--- a/arch/mips/kernel/genex.S
++++ b/arch/mips/kernel/genex.S
+@@ -82,7 +82,7 @@ NESTED(except_vec3_r4000, 0, sp)
+ 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 @@ NESTED(except_vec3_r4000, 0, sp)
+
+ /*
+ * 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 @@ NESTED(except_vec_ejtag_debug, 0, sp)
+ __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 @@ NESTED(nmi_handler, PT_SIZE, sp)
+ 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
+--- 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 at mvista.com or jsun at 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
+--- 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 @@ NESTED(kernel_entry, 16, sp) # kernel
+ 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 @@ NESTED(kernel_entry, 16, sp) # kernel
+ 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(kernel_entry, 16, sp) # kernel
+ */
+ 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 @@ NESTED(smp_bootstrap, 16, sp)
+ .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
+--- a/arch/mips/kernel/i8259.c
++++ b/arch/mips/kernel/i8259.c
+@@ -31,7 +31,7 @@ void disable_8259A_irq(unsigned int irq)
+ * 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 unsigned int startup_8259A_irq(un
+ }
+
+ 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 @@ static struct resource pic2_io_resource
+
+ /*
+ * 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 @@ void __init init_i8259_irqs (void)
+
+ 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
+--- a/arch/mips/kernel/ioctl32.c
++++ b/arch/mips/kernel/ioctl32.c
+@@ -41,12 +41,6 @@ IOCTL_TABLE_START
+ #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
+--- a/arch/mips/kernel/irixelf.c
++++ b/arch/mips/kernel/irixelf.c
+@@ -8,7 +8,7 @@
+ *
+ * Copyright (C) 1993 - 1994 Eric Youngdale <ericy at cais.com>
+ * Copyright (C) 1996 - 2004 David S. Miller <dm at engr.sgi.com>
+- * Copyright (C) 2004 Steven J. Hill <sjhill at realitydiluted.com>
++ * Copyright (C) 2004 - 2005 Steven J. Hill <sjhill at 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 @@ static struct linux_binfmt irix_format =
+ #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 @@ static void dump_phdrs(struct elf_phdr *
+ print_phdr(i, ep);
+ }
+ }
+-#endif /* (DEBUG_ELF) */
++#endif /* DEBUG */
+
+ static void set_brk(unsigned long start, unsigned long end)
+ {
+@@ -146,20 +147,20 @@ static void padzero(unsigned long elf_bs
+ 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 @@ static unsigned int load_irix_interp(str
+ 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 @@ static unsigned int load_irix_interp(str
+ (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 @@ static unsigned int load_irix_interp(str
+ 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(¤t->mm->mmap_sem);
+ error = do_mmap(interpreter, vaddr,
+ eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
+@@ -324,14 +322,10 @@ static unsigned int load_irix_interp(str
+ 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 @@ static unsigned int load_irix_interp(str
+ */
+ 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 @@ static unsigned int load_irix_interp(str
+ * 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 @@ static int verify_binary(struct elfhdr *
+
+ /* 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 @@ static int verify_binary(struct elfhdr *
+ * 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 @@ static inline int look_for_irix_interpre
+ 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 @@ static inline int map_interpreter(struct
+ * 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 @@ static int load_irix_binary(struct linux
+
+ 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 @@ static int load_irix_binary(struct linux
+ }
+
+ 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 @@ static int load_irix_binary(struct linux
+ break;
+ };
+ }
+-#ifdef DEBUG_ELF
+- printk("\n");
+-#endif
++
++ pr_debug("\n");
+
+ elf_bss = 0;
+ elf_brk = 0;
+@@ -657,12 +655,19 @@ static int load_irix_binary(struct linux
+ 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 @@ static int load_irix_binary(struct linux
+ /* 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 @@ static int load_irix_binary(struct linux
+ * 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 @@ out_free_dentry:
+ 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 @@ static int load_irix_library(struct file
+
+ /* 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 @@ static int load_irix_library(struct file
+ * 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 @@ unsigned long irix_mapelf(int fd, struct
+ 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(¤t->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(¤t->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 @@ unsigned long irix_mapelf(int fd, struct
+ /* 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 @@ static int irix_core_dump(long signr, st
+ 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 @@ static int irix_core_dump(long signr, st
+ /* 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 @@ static int irix_core_dump(long signr, st
+
+ 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 @@ static int irix_core_dump(long signr, st
+ }
+ 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 @@ static int irix_core_dump(long signr, st
+ 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 @@ static int irix_core_dump(long signr, st
+ #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 @@ end_coredump:
+
+ 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 int __init init_irix_binfmt(void)
+
+ 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
+--- a/arch/mips/kernel/irixinv.c
++++ b/arch/mips/kernel/irixinv.c
+@@ -30,10 +30,10 @@ void add_to_inventory (int class, int ty
+ 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 @@ int dump_inventory_to_user (void *userbu
+
+ 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
+--- a/arch/mips/kernel/irixioctl.c
++++ b/arch/mips/kernel/irixioctl.c
+@@ -59,7 +59,7 @@ asmlinkage int irix_ioctl(int fd, unsign
+ {
+ 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 @@ asmlinkage int irix_ioctl(int fd, unsign
+
+ 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 @@ asmlinkage int irix_ioctl(int fd, unsign
+ 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 @@ asmlinkage int irix_ioctl(int fd, unsign
+ 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;
++
++ 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;
+- __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]);
+ old_fs = get_fs(); set_fs(get_ds());
+ error = sys_ioctl(fd, TCSETS, (unsigned long) &kt);
+ set_fs(old_fs);
+@@ -153,7 +160,7 @@ asmlinkage int irix_ioctl(int fd, unsign
+ #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 @@ asmlinkage int irix_ioctl(int fd, unsign
+ 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 at engr.sgi.com\n";
++ char *msg = "Unimplemented IOCTL cmd tell linux-mips at 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
+--- a/arch/mips/kernel/irixsig.c
++++ b/arch/mips/kernel/irixsig.c
+@@ -76,36 +76,39 @@ static inline void dump_irix5_sigctx(str
+ }
+ #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 @@ static void setup_irix_frame(struct k_si
+ 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 @@ setup_irix_rt_frame(struct k_sigaction *
+ 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 @@ static inline void handle_signal(unsigne
+ 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(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+@@ -161,6 +167,8 @@ static inline void handle_signal(unsigne
+ sigaddset(¤t->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
++
++ return ret;
+ }
+
+ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
+@@ -184,10 +192,8 @@ asmlinkage int do_irix_signal(sigset_t *
+ oldset = ¤t->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 @@ no_signal:
+ 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 @@ irix_sigreturn(struct pt_regs *regs)
+ 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 @@ irix_sigreturn(struct pt_regs *regs)
+ dump_irix5_sigctx(context);
+ #endif
+
+- __get_user(regs->cp0_epc, &context->pc);
+- umask = context->rmask; mask = 2;
++ error = __get_user(regs->cp0_epc, &context->pc);
++ error |= __get_user(umask, &context->rmask);
++
++ mask = 2;
+ for (i = 1; i < 32; i++, mask <<= 1) {
+- if(umask & mask)
+- __get_user(regs->regs[i], &context->regs[i]);
++ if (umask & mask)
++ error |= __get_user(regs->regs[i], &context->regs[i]);
+ }
+- __get_user(regs->hi, &context->hi);
+- __get_user(regs->lo, &context->lo);
++ error |= __get_user(regs->hi, &context->hi);
++ error |= __get_user(regs->lo, &context->lo);
+
+- if ((umask & 1) && context->usedfp) {
++ error |= __get_user(usedfp, &context->usedfp);
++ if ((umask & 1) && usedfp) {
+ fregs = (u64 *) ¤t->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 @@ static inline void dump_sigact_irix5(str
+ #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 @@ irix_sigaction(int sig, const struct sig
+ #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))
++ int err;
++
++ 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);
+
+- __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
++ 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 @@ irix_sigaction(int sig, const struct sig
+ 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;
++
++ 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;
+- __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
+- sizeof(sigset_t));
+ }
+
+ 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(¤t->sighand->siglock);
+@@ -381,20 +405,19 @@ asmlinkage int irix_sigprocmask(int how,
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+- if(old) {
+- if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
+- return -EFAULT;
+- __copy_to_user(old, ¤t->blocked, sizeof(unsigned long)*4);
+- }
++ if (old)
++ return copy_to_user(old, ¤t->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 @@ struct irix5_siginfo {
+ } 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 @@ asmlinkage int irix_sigpoll_sys(unsigned
+ 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 @@ asmlinkage int irix_sigpoll_sys(unsigned
+ }
+
+ 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 @@ asmlinkage int irix_sigpoll_sys(unsigned
+ 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 (¤t->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 @@ extern int getrusage(struct task_struct
+
+ #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 @@ asmlinkage int irix_waitsys(int type, in
+ 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(¤t->signal->wait_chldexit, &wait);
+ repeat:
+ flag = 0;
+@@ -595,18 +609,20 @@ repeat:
+ 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 @@ repeat:
+ 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 @@ end_waitsys:
+ current->state = TASK_RUNNING;
+ remove_wait_queue(¤t->signal->wait_chldexit, &wait);
+
+-out:
+ return retval;
+ }
+
+@@ -675,39 +692,39 @@ struct irix5_context {
+
+ 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, ¤t->blocked, sizeof(irix_sigset_t));
++ error |= __copy_to_user(&ctx->sigmask, ¤t->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 @@ asmlinkage int irix_getcontext(struct pt
+ /* 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" (®s));
++ /* 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 (new) {
+ if (!access_ok(VERIFY_READ, new, sizeof(*new)))
+- goto out;
++ return -EFAULT;
+ }
+
+- if(old) {
++ if (old) {
+ if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
+- goto out;
++ return -EFAULT;
+ }
+- error = 0;
+
+-out:
+- return error;
++ return 0;
+ }
+
+ struct irix_sigaltstack { unsigned long sp; int size; int status; };
+
+-asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
+- struct irix_sigaltstack *old)
++asmlinkage int irix_sigaltstack(struct irix_sigaltstack __user *new,
++ struct irix_sigaltstack __user *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 (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 error;
++ 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
+--- a/arch/mips/kernel/irq-msc01.c
++++ b/arch/mips/kernel/irq-msc01.c
+@@ -74,7 +74,7 @@ static void disable_msc_irq(unsigned int
+ 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 level_mask_and_ack_msc_irq(u
+ 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 @@ msc_bind_eic_interrupt (unsigned int irq
+ #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 @@ void __init init_msc_irqs(unsigned int b
+ 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
+--- a/arch/mips/kernel/irq-mv6434x.c
++++ b/arch/mips/kernel/irq-mv6434x.c
+@@ -135,14 +135,13 @@ void ll_mv64340_irq(struct pt_regs *regs
+ #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
+--- a/arch/mips/kernel/irq-rm7000.c
++++ b/arch/mips/kernel/irq-rm7000.c
+@@ -72,13 +72,13 @@ static void rm7k_cpu_irq_end(unsigned in
+ }
+
+ 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
+--- a/arch/mips/kernel/irq-rm9000.c
++++ b/arch/mips/kernel/irq-rm9000.c
+@@ -106,23 +106,23 @@ static void rm9k_cpu_irq_end(unsigned in
+ }
+
+ 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
+--- a/arch/mips/kernel/irq_cpu.c
++++ b/arch/mips/kernel/irq_cpu.c
+@@ -3,6 +3,8 @@
+ * Author: Jun Sun, jsun at mvista.com or jsun at junsun.net
+ *
+ * Copyright (C) 2001 Ralf Baechle
++ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
++ * Author: Maciej W. Rozycki <macro at 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 @@ static inline void mips_cpu_irq_enable(u
+
+ local_irq_save(flags);
+ unmask_mips_irq(irq);
++ back_to_back_c0_hazard();
+ local_irq_restore(flags);
+ }
+
+@@ -61,6 +66,7 @@ static void mips_cpu_irq_disable(unsigne
+
+ local_irq_save(flags);
+ mask_mips_irq(irq);
++ back_to_back_c0_hazard();
+ local_irq_restore(flags);
+ }
+
+@@ -71,7 +77,7 @@ static unsigned int mips_cpu_irq_startup
+ 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 unsigned int mips_cpu_irq_startup
+ */
+ 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 void mips_cpu_irq_end(unsigned in
+ }
+
+ 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
+--- a/arch/mips/kernel/linux32.c
++++ b/arch/mips/kernel/linux32.c
+@@ -215,81 +215,32 @@ sys32_readdir(unsigned int fd, void * di
+ 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)
++asmlinkage int
++sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options)
+ {
+- 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;
++ return compat_sys_wait4(pid, stat_addr, options, NULL);
+ }
+
+-asmlinkage int
+-sys32_wait4(compat_pid_t pid, unsigned int * stat_addr, int options,
+- struct rusage32 * ru)
++asmlinkage long
++sysn32_waitid(int which, compat_pid_t pid,
++ siginfo_t __user *uinfo, int options,
++ struct compat_rusage __user *uru)
+ {
+- 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();
++ struct rusage ru;
++ long ret;
++ 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;
++ 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;
+- }
+-}
+
+-asmlinkage int
+-sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options)
+-{
+- return sys32_wait4(pid, stat_addr, options, NULL);
++ if (uru)
++ ret = put_compat_rusage(&ru, uru);
++ return ret;
+ }
+
+ struct sysinfo32 {
+@@ -1467,3 +1418,80 @@ asmlinkage long sys32_socketcall(int cal
+ }
+ 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, ®s, 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
+--- 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 at 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
+--- 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 at 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
+--- 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 at 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
+--- 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 @@ static int show_cpuinfo(struct seq_file
+ (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 @@ static int show_cpuinfo(struct seq_file
+ 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
+--- 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 @@ ATTRIB_NORET void cpu_idle(void)
+ }
+ }
+
++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 @@ void start_thread(struct pt_regs * regs,
+ 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 @@ int copy_thread(int nr, unsigned long cl
+ 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 @@ int copy_thread(int nr, unsigned long cl
+ 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 @@ void dump_regs(elf_greg_t *gp, struct pt
+ #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 @@ long kernel_thread(int (*fn)(void *), vo
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 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 @@ static int __init get_frame_info(struct
+ /* 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 get_frame_info(struct
+
+ 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 @@ unsigned long thread_saved_pc(struct tas
+ /* 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;
+-
+- 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;
++ return pc;
+
+-schedule_timeout_caller:
+- /*
+- * The schedule_timeout frame
+- */
+ frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
++ do {
++ int i;
+
+- /*
+- * frame now points to sleep_on_timeout's frame
+- */
+- pc = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
+-
+- 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];
+- }
++ if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
++ return 0;
+
+-out:
++ for (i = ARRAY_SIZE(mfinfo) - 1; i >= 0; i--) {
++ if (pc >= (unsigned long) mfinfo[i].func)
++ break;
++ }
++ if (i < 0)
++ break;
+
+-#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
+--- 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 @@ void ptrace_disable(struct task_struct *
+ /* 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 @@ asmlinkage int sys_ptrace(long request,
+ 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 @@ asmlinkage int sys_ptrace(long request,
+ 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 @@ asmlinkage int sys_ptrace(long request,
+ 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 @@ asmlinkage int sys_ptrace(long request,
+ 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 @@ asmlinkage int sys_ptrace(long request,
+ 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 @@ out:
+
+ static inline int audit_arch(void)
+ {
+-#ifdef CONFIG_CPU_LITTLE_ENDIAN
+-#ifdef CONFIG_64BIT
+- if (!(current->thread.mflags & MF_32BIT_REGS))
+- return AUDIT_ARCH_MIPSEL64;
+-#endif /* MIPS64 */
+- return AUDIT_ARCH_MIPSEL;
+-
+-#else /* big endian... */
++ int arch = EM_MIPS;
+ #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 @@ static inline int audit_arch(void)
+ 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
+--- 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 @@ asmlinkage int sys32_ptrace(int request,
+ 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 @@ asmlinkage int sys32_ptrace(int request,
+ 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 @@ asmlinkage int sys32_ptrace(int request,
+ 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 @@ asmlinkage int sys32_ptrace(int request,
+ 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 @@ asmlinkage int sys32_ptrace(int request,
+ 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 @@ asmlinkage int sys32_ptrace(int request,
+ 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
+--- 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 @@ LEAF(_save_fp_context)
+ 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
+--- /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
+--- a/arch/mips/kernel/scall32-o32.S
++++ b/arch/mips/kernel/scall32-o32.S
+@@ -578,7 +578,7 @@ einval: li v0, -EINVAL
+ 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 @@ einval: li v0, -EINVAL
+ 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 @@ einval: li v0, -EINVAL
+ 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
+--- a/arch/mips/kernel/scall64-64.S
++++ b/arch/mips/kernel/scall64-64.S
+@@ -449,3 +449,7 @@ sys_call_table:
+ 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
+--- a/arch/mips/kernel/scall64-n32.S
++++ b/arch/mips/kernel/scall64-n32.S
+@@ -176,7 +176,7 @@ EXPORT(sysn32_call_table)
+ 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 @@ EXPORT(sysn32_call_table)
+ 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 @@ EXPORT(sysn32_call_table)
+ 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 @@ EXPORT(sysn32_call_table)
+ 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 @@ EXPORT(sysn32_call_table)
+ 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 @@ EXPORT(sysn32_call_table)
+ 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
+--- a/arch/mips/kernel/scall64-o32.S
++++ b/arch/mips/kernel/scall64-o32.S
+@@ -316,13 +316,13 @@ sys_call_table:
+ 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 @@ sys_call_table:
+ 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 @@ sys_call_table:
+ 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 @@ sys_call_table:
+ 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
+--- a/arch/mips/kernel/semaphore.c
++++ b/arch/mips/kernel/semaphore.c
+@@ -42,24 +42,28 @@ static inline int __sem_update_count(str
+
+ 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
+--- 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 @@ EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
+ *
+ * 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 @@ static char command_line[CL_SIZE];
+ * 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 @@ static inline void resource_init(void)
+ #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 @@ void __init setup_arch(char **cmdline_p)
+ #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 @@ int __init fpu_disable(char *s)
+ }
+
+ __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
+--- 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 @@ setup_sigcontext(struct pt_regs *regs, s
+ 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 @@ out:
+ 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 @@ restore_sigcontext(struct pt_regs *regs,
+ 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 @@ get_sigframe(struct k_sigaction *ka, str
+ 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));
++}
++
++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 (void *)((sp - frame_size) & almask);
++ return err;
+ }
+diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
+--- 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 @@ save_static_function(sys_sigsuspend);
+ __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 @@ save_static_function(sys_rt_sigsuspend);
+ __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 @@ _sys_rt_sigsuspend(nabi_no_regargs struc
+ 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_sigaction(int sig, co
+
+ 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 @@ _sys_sigreturn(nabi_no_regargs struct pt
+ 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 @@ badframe:
+ }
+
+ #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 @@ static void inline setup_frame(struct k_
+ 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 @@ static void inline setup_frame(struct k_
+ 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 @@ static void inline setup_rt_frame(struct
+ 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 @@ static void inline setup_rt_frame(struct
+ 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 @@ static inline void handle_signal(unsigne
+
+ 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(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+@@ -431,23 +421,16 @@ static inline void handle_signal(unsigne
+ sigaddset(¤t->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+-}
+
+-extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
+-extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
++ return ret;
++}
+
+-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 @@ static int do_signal(sigset_t *oldset, s
+ oldset = ¤t->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 @@ asmlinkage void do_notify_resume(struct
+ {
+ /* 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
+--- 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 @@ typedef struct compat_siginfo {
+
+ /* 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 @@ asmlinkage int sys32_sigaction(int sig,
+
+ 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 @@ asmlinkage int sys32_sigaltstack(nabi_no
+
+ 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 @@ static int restore_sigcontext32(struct p
+ 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 @@ static int restore_sigcontext32(struct p
+
+ 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 @@ int copy_siginfo_to_user32(compat_siginf
+ 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 @@ __attribute_used__ noinline static void
+ _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 @@ _sys32_rt_sigreturn(nabi_no_regargs stru
+
+ /* 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 @@ static inline int setup_sigcontext32(str
+
+ 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 @@ static inline void *get_sigframe(struct
+ 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 @@ give_sigsegv:
+ 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 @@ give_sigsegv:
+ 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 @@ static inline void handle_signal(unsigne
+ 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(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+@@ -757,6 +803,8 @@ static inline void handle_signal(unsigne
+ sigaddset(¤t->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
++
++ return ret;
+ }
+
+ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
+@@ -780,10 +828,8 @@ int do_signal32(sigset_t *oldset, struct
+ oldset = ¤t->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 @@ asmlinkage int sys32_rt_sigaction(int si
+ 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 @@ asmlinkage int sys32_rt_sigqueueinfo(int
+ 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
+--- 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 @@ struct ucontextn32 {
+ 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 @@ badframe:
+ 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 @@ void setup_rt_frame_n32(struct k_sigacti
+ 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 @@ void setup_rt_frame_n32(struct k_sigacti
+ 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
+--- a/arch/mips/kernel/smp.c
++++ b/arch/mips/kernel/smp.c
+@@ -50,7 +50,6 @@ static void smp_tune_scheduling (void)
+ {
+ struct cache_desc *cd = ¤t_cpu_data.scache;
+ unsigned long cachesize; /* kB */
+- unsigned long bandwidth = 350; /* MB/s */
+ unsigned long cpu_khz;
+
+ /*
+@@ -121,7 +120,19 @@ struct call_data_struct *call_data;
+ * 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 smp_call_function (void (*func) (voi
+ 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 @@ void __init smp_cpus_done(unsigned int m
+ /* 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,23 +251,28 @@ void __devinit smp_prepare_boot_cpu(void
+ }
+
+ /*
+- * Startup the CPU with this logical number
++ * 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.
+ */
+-static int __init do_boot_cpu(int cpu)
++int __devinit __cpu_up(unsigned int cpu)
+ {
+ struct task_struct *idle;
+
+ /*
++ * 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("failed fork for CPU %d\n", cpu);
++ panic(KERN_ERR "Fork failed for CPU %d", cpu);
+
+ prom_boot_secondary(cpu, idle);
+
+- /* XXXKW timeout */
++ /*
++ * Trust is futile. We should really have timeouts ...
++ */
+ while (!cpu_isset(cpu, cpu_callin_map))
+ udelay(100);
+
+@@ -261,23 +281,6 @@ static int __init do_boot_cpu(int cpu)
+ 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;
+-
+- /* Processor goes to start_secondary(), sets online flag */
+- ret = do_boot_cpu(cpu);
+- if (ret < 0)
+- return ret;
+-
+- return 0;
+-}
+-
+ /* Not really SMP stuff ... */
+ int setup_profiling_timer(unsigned int multiplier)
+ {
+diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp_mt.c
+new file mode 100644
+--- /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 at 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
+--- 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 @@ out:
+
+ 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 @@ _sys_clone(nabi_no_regargs struct pt_reg
+ {
+ 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, ®s, 0,
+ parent_tidptr, child_tidptr);
+ }
+@@ -242,6 +260,16 @@ asmlinkage int sys_olduname(struct oldol
+ 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
+--- a/arch/mips/kernel/sysirix.c
++++ b/arch/mips/kernel/sysirix.c
+@@ -73,32 +73,30 @@ asmlinkage int irix_sysmp(struct pt_regs
+ }
+
+ /* 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 @@ asmlinkage int irix_prctl(struct pt_regs
+ 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 @@ asmlinkage int irix_prctl(struct pt_regs
+ }
+
+ 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 @@ asmlinkage int irix_prctl(struct pt_regs
+ 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 @@ asmlinkage int irix_syssgi(struct pt_reg
+ 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 @@ asmlinkage int irix_syssgi(struct pt_reg
+ 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 @@ asmlinkage int irix_syssgi(struct pt_reg
+
+ 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 @@ asmlinkage int irix_syssgi(struct pt_reg
+
+ 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 @@ asmlinkage int irix_syssgi(struct pt_reg
+
+ 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 @@ asmlinkage int irix_syssgi(struct pt_reg
+
+ 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 @@ asmlinkage int irix_pause(void)
+ }
+
+ /* 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 @@ struct irix_statfs {
+ 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 @@ asmlinkage int irix_statfs(const char *p
+ error = -EFAULT;
+ goto out;
+ }
++
+ error = user_path_walk(path, &nd);
+ if (error)
+ goto out;
+@@ -732,18 +717,17 @@ asmlinkage int irix_statfs(const char *p
+ 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 @@ out:
+ 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 @@ asmlinkage int irix_fstatfs(unsigned int
+ error = -EFAULT;
+ goto out;
+ }
++
+ if (!(file = fget(fd))) {
+ error = -EBADF;
+ goto out;
+@@ -770,16 +755,17 @@ asmlinkage int irix_fstatfs(unsigned int
+ 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 @@ asmlinkage int irix_setpgrp(int flags)
+ 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 @@ asmlinkage int irix_exec(struct pt_regs
+
+ 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 @@ asmlinkage int irix_exece(struct pt_regs
+
+ 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 @@ asmlinkage int irix_socket(int family, i
+ 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 @@ asmlinkage int irix_msgsys(int opcode, u
+ 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 @@ asmlinkage int irix_shmsys(int opcode, u
+ {
+ 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 @@ asmlinkage int irix_semsys(int opcode, u
+ 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 @@ static inline loff_t llseek(struct file
+ 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 @@ asmlinkage int irix_sginap(int ticks)
+ 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 @@ asmlinkage unsigned long irix_mmap32(uns
+
+ 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 @@ asmlinkage int irix_madvise(unsigned lon
+ 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 @@ asmlinkage int irix_BSDsetpgrp(int pid,
+ 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 @@ struct iuname {
+ 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 @@ asmlinkage int irix_uname(struct iuname
+
+ #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 @@ static int irix_xstat32_xlate(struct kst
+ 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 @@ static int irix_xstat64_xlate(struct kst
+ 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 @@ asmlinkage int irix_xstat(int version, c
+ 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 @@ asmlinkage int irix_lxstat(int version,
+ 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 @@ asmlinkage int irix_fxstat(int version,
+ 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 @@ asmlinkage int irix_xmknod(int ver, char
+ 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 @@ struct irix_statvfs {
+ 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 @@ asmlinkage int irix_statvfs(char *fname,
+
+ 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 @@ asmlinkage int irix_statvfs(char *fname,
+ 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 @@ out:
+ 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 @@ asmlinkage int irix_fstatvfs(int fd, str
+ 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 @@ asmlinkage int irix_fstatvfs(int fd, str
+ 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 @@ asmlinkage int irix_sigqueue(int pid, in
+ 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 @@ asmlinkage int irix_mmap64(struct pt_reg
+ 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 @@ asmlinkage int irix_mmap64(struct pt_reg
+ 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 @@ asmlinkage int irix_mmap64(struct pt_reg
+
+ 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 @@ asmlinkage int irix_mmap64(struct pt_reg
+ if (file)
+ fput(file);
+
+-out:
+ return error;
+ }
+
+@@ -1597,7 +1573,7 @@ asmlinkage int irix_dmi(struct pt_regs *
+ 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 @@ asmlinkage int irix_pread(int fd, char *
+ 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 @@ struct irix_statvfs64 {
+ 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 @@ asmlinkage int irix_statvfs64(char *fnam
+ error = -EFAULT;
+ goto out;
+ }
++
+ error = user_path_walk(fname, &nd);
+ if (error)
+ goto out;
+@@ -1657,27 +1634,25 @@ asmlinkage int irix_statvfs64(char *fnam
+ 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 @@ out:
+ 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 @@ asmlinkage int irix_fstatvfs64(int fd, s
+ 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 @@ out:
+ 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 @@ asmlinkage int irix_getmountid(char *fna
+ * 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 {
+ };
+
+ 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 @@ struct irix_dirent32_callback {
+ #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 @@ static int irix_filldir32(void *__buf, c
+ 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 @@ asmlinkage int irix_ngetdents(unsigned i
+ 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 {
+ };
+
+ 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 @@ struct irix_dirent64_callback {
+ #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 @@ asmlinkage int irix_getdents64(int fd, v
+ 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 @@ asmlinkage int irix_getdents64(int fd, v
+ 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 @@ out:
+ 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 @@ asmlinkage int irix_ngetdents64(int fd,
+ 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 @@ asmlinkage int irix_ngetdents64(int fd,
+ 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 @@ out:
+ 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
+--- 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 @@ int (*rtc_set_mmss)(unsigned long);
+ 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 @@ static unsigned int null_hpt_read(void)
+ return 0;
+ }
+
+-static void null_hpt_init(unsigned int count) { /* nothing */ }
++static void null_hpt_init(unsigned int count)
++{
++ /* nothing */
++}
+
+
+ /*
+@@ -108,8 +109,10 @@ static void c0_timer_ack(void)
+ {
+ 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 @@ int do_settimeofday(struct timespec *tv)
+ 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
+--- 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 at mips.com and Carsten Langgaard, carstenl at 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_tr(void);
+ 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 @@ void show_regs(struct pt_regs *regs)
+
+ 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 @@ void show_registers(struct pt_regs *regs
+
+ 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 @@ asmlinkage void do_be(struct pt_regs *re
+
+ 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 @@ static inline int get_insn_opcode(struct
+ #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 struct task_struct *ll_task = NUL
+
+ 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 @@ static inline void simulate_ll(struct pt
+ 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 @@ static inline void simulate_ll(struct pt
+
+ preempt_enable();
+
++ compute_return_epc(regs);
++
+ regs->regs[(opcode & RT) >> 16] = value;
+
+- compute_return_epc(regs);
+ return;
+
+ sig:
+@@ -418,7 +437,8 @@ sig:
+
+ 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 @@ static inline void simulate_sc(struct pt
+ 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 @@ static inline void simulate_sc(struct pt
+ 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 @@ static inline void simulate_sc(struct pt
+ goto sig;
+ }
+
++ compute_return_epc(regs);
+ regs->regs[reg] = 1;
+
+- compute_return_epc(regs);
+ return;
+
+ sig:
+@@ -491,6 +512,37 @@ static inline int simulate_llsc(struct p
+ 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 @@ asmlinkage void do_ov(struct pt_regs *re
+ 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 @@ asmlinkage void do_fpe(struct pt_regs *r
+
+ 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 @@ asmlinkage void do_fpe(struct pt_regs *r
+ * 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,
+ ¤t->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 @@ asmlinkage void do_bp(struct pt_regs *re
+ 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 @@ asmlinkage void do_tr(struct pt_regs *re
+ 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 @@ asmlinkage void do_ri(struct pt_regs *re
+ if (!simulate_llsc(regs))
+ return;
+
++ if (!simulate_rdhwr(regs))
++ return;
++
+ force_sig(SIGILL, current);
+ }
+
+@@ -650,11 +720,13 @@ asmlinkage void do_cpu(struct pt_regs *r
+
+ 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 @@ asmlinkage void do_cpu(struct pt_regs *r
+ set_used_math();
+ }
+
++ preempt_enable();
++
+ if (!cpu_has_fpu) {
+- int sig = fpu_emulator_cop1Handler(0, regs,
++ int sig = fpu_emulator_cop1Handler(regs,
+ ¤t->thread.fpu.soft);
+ if (sig)
+ force_sig(sig, current);
+ }
+
+- preempt_enable();
+-
+ return;
+
+ case 2:
+@@ -716,6 +788,22 @@ asmlinkage void do_mcheck(struct pt_regs
+ (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 @@ asmlinkage void do_reserved(struct pt_re
+ (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 @@ static inline void parity_protection_ini
+ {
+ 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 @@ asmlinkage void cache_parity_error(void)
+ 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 @@ void nmi_exception_handler(struct pt_reg
+ 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 @@ void *set_except_vector(int n, void *add
+
+ 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 @@ static inline void signal32_init(void)
+
+ 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 @@ void __init per_cpu_trap_init(void)
+ #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 @@ void __init per_cpu_trap_init(void)
+ 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 @@ void __init trap_init(void)
+ * 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 @@ void __init trap_init(void)
+ * 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 @@ void __init trap_init(void)
+ 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 @@ void __init trap_init(void)
+ 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 @@ void __init trap_init(void)
+ //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
+--- a/arch/mips/kernel/unaligned.c
++++ b/arch/mips/kernel/unaligned.c
+@@ -94,7 +94,7 @@ unsigned long unaligned_instructions;
+ #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 @@ static inline int emulate_load_store_ins
+ /*
+ * 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 @@ asmlinkage void do_ade(struct pt_regs *r
+ {
+ 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 @@ asmlinkage void do_ade(struct pt_regs *r
+ 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 @@ asmlinkage void do_ade(struct pt_regs *r
+ 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,
+ ®ptr, &newval)) {
+ compute_return_epc(regs);
+ /*
+diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
+--- a/arch/mips/kernel/vmlinux.lds.S
++++ b/arch/mips/kernel/vmlinux.lds.S
+@@ -54,13 +54,6 @@ SECTIONS
+
+ *(.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 @@ SECTIONS
+ .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
+--- /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
+--- /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
+--- a/arch/mips/lasat/interrupt.c
++++ b/arch/mips/lasat/interrupt.c
+@@ -71,14 +71,13 @@ static void end_lasat_irq(unsigned int i
+ }
+
+ 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
+--- a/arch/mips/lasat/setup.c
++++ b/arch/mips/lasat/setup.c
+@@ -155,7 +155,7 @@ void __init serial_init(void)
+ }
+ #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 @@ static int __init lasat_setup(void)
+ 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
+--- 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 @@ void dump_tlb(int first, int last)
+ 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 @@ void dump_tlb(int first, int last)
+ 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 @@ void dump_tlb(int first, int last)
+ 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_all(void)
+
+ void dump_tlb_wired(void)
+ {
+- int wired;
++ int wired;
+
+ wired = read_c0_wired();
+ printk("Wired: %d", wired);
+@@ -138,9 +145,10 @@ void dump_tlb_nonwired(void)
+
+ 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 @@ void dump_list_process(struct task_struc
+
+ 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);
+-
+- pmd = pmd_offset(pgd, addr);
+- printk("pmd == %08x, ", (unsigned int) pmd);
+-
+- pte = pte_offset(pmd, addr);
+- printk("pte == %08x, ", (unsigned int) pte);
++ printk("pgd == %08x, ", (unsigned int) pgd);
++ 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);
++ 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 @@ void dump_list_process(struct task_struc
+ #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 @@ void dump_list_current(void *address)
+
+ 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 @@ void dump16(unsigned long *p)
+ 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
+--- a/arch/mips/lib-32/r3k_dump_tlb.c
++++ b/arch/mips/lib-32/r3k_dump_tlb.c
+@@ -105,6 +105,7 @@ void dump_tlb_nonwired(void)
+ 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 @@ void dump_list_process(struct task_struc
+ 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 @@ void dump_list_current(void *address)
+ 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
+--- a/arch/mips/lib-64/dump_tlb.c
++++ b/arch/mips/lib-64/dump_tlb.c
+@@ -140,6 +140,7 @@ void dump_tlb_nonwired(void)
+ 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 @@ void dump_list_process(struct task_struc
+ 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 @@ void dump_list_current(void *address)
+ 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
+--- 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
+--- 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 @@ unsigned int csum_partial_copy_nocheck(c
+ * 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
+--- 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
+--- /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 at 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
+--- a/arch/mips/math-emu/cp1emu.c
++++ b/arch/mips/math-emu/cp1emu.c
+@@ -70,7 +70,7 @@ static int fpux_emu(struct pt_regs *,
+
+ /* 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 @@ struct mips_fpu_emulator_private fpuemup
+
+ /* 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 isBranchInstr(mips_instructio
+ 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 @@ static int cop1Emulate(struct pt_regs *x
+ * 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 @@ static int cop1Emulate(struct pt_regs *x
+ }
+
+ 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 @@ static int cop1Emulate(struct pt_regs *x
+ 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 @@ static int cop1Emulate(struct pt_regs *x
+
+ 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 @@ static int cop1Emulate(struct pt_regs *x
+
+ 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 @@ static int cop1Emulate(struct pt_regs *x
+ }
+ 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 @@ static int cop1Emulate(struct pt_regs *x
+ 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 @@ static int cop1Emulate(struct pt_regs *x
+ * 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 @@ static int cop1Emulate(struct pt_regs *x
+ * 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 @@ static int cop1Emulate(struct pt_regs *x
+ }
+
+ /* 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 const unsigned char cmptab[8] = {
+ 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 @@ static int fpux_emu(struct pt_regs *xcp,
+ {
+ 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 @@ static int fpux_emu(struct pt_regs *xcp,
+ 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 @@ static int fpux_emu(struct pt_regs *xcp,
+ 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 @@ static int fpux_emu(struct pt_regs *xcp,
+ }
+ break;
+ }
+-#endif
+
+ case 0x7: /* 7 */
+ if (MIPSInst_FUNC(ir) != pfetch_op) {
+@@ -810,7 +774,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ #endif
+ } rv; /* resulting value */
+
+- fpuemuprivate.stats.cp1ops++;
++ fpuemustats.cp1ops++;
+ switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
+ case s_fmt:{ /* 0 */
+ union {
+@@ -834,7 +798,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ 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 @@ static int fpu_emu(struct pt_regs *xcp,
+ 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 @@ static int fpu_emu(struct pt_regs *xcp,
+ rfmt = d_fmt;
+ goto copcsr;
+ }
+-#endif
+ case fcvtw_op:{
+ ieee754sp fs;
+
+@@ -933,7 +893,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ goto copcsr;
+ }
+
+-#if __mips >= 2 || __mips64
++#if __mips >= 2 || defined(__mips64)
+ case fround_op:
+ case ftrunc_op:
+ case fceil_op:
+@@ -950,7 +910,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ }
+ #endif /* __mips >= 2 */
+
+-#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
++#if defined(__mips64)
+ case fcvtl_op:{
+ ieee754sp fs;
+
+@@ -974,7 +934,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+-#endif /* __mips64 && !fpu(single) */
++#endif /* defined(__mips64) */
+
+ default:
+ if (MIPSInst_FUNC(ir) >= fcmp_op) {
+@@ -1001,7 +961,6 @@ static int fpu_emu(struct pt_regs *xcp,
+ break;
+ }
+
+-#ifndef SINGLE_ONLY_FPU
+ case d_fmt:{
+ union {
+ ieee754dp(*b) (ieee754dp, ieee754dp);
+@@ -1024,7 +983,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ 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 @@ static int fpu_emu(struct pt_regs *xcp,
+ goto copcsr;
+ }
+
+-#if __mips >= 2 || __mips64
++#if __mips >= 2 || defined(__mips64)
+ case fround_op:
+ case ftrunc_op:
+ case fceil_op:
+@@ -1125,7 +1084,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ }
+ #endif
+
+-#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
++#if defined(__mips64)
+ case fcvtl_op:{
+ ieee754dp fs;
+
+@@ -1149,7 +1108,7 @@ static int fpu_emu(struct pt_regs *xcp,
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+-#endif /* __mips >= 3 && !fpu(single) */
++#endif /* __mips >= 3 */
+
+ default:
+ if (MIPSInst_FUNC(ir) >= fcmp_op) {
+@@ -1177,7 +1136,6 @@ static int fpu_emu(struct pt_regs *xcp,
+ }
+ break;
+ }
+-#endif /* ifndef SINGLE_ONLY_FPU */
+
+ case w_fmt:{
+ ieee754sp fs;
+@@ -1189,21 +1147,19 @@ static int fpu_emu(struct pt_regs *xcp,
+ 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 @@ static int fpu_emu(struct pt_regs *xcp,
+ 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 @@ static int fpu_emu(struct pt_regs *xcp,
+ 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 @@ int fpu_emulator_cop1Handler(int xcptno,
+ 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
+--- a/arch/mips/math-emu/dp_sqrt.c
++++ b/arch/mips/math-emu/dp_sqrt.c
+@@ -37,7 +37,7 @@ static const unsigned table[] = {
+
+ 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
+--- 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 @@ struct emuframe {
+ 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 @@ int mips_dsemul(struct pt_regs *regs, mi
+ */
+
+ /* 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 @@ int mips_dsemul(struct pt_regs *regs, mi
+ 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 mips_dsemul(struct pt_regs *regs, mi
+ 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 @@ int do_dsemulret(struct pt_regs *xcp)
+ 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
+--- 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
+--- 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
+--- 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 at mips.com and Carsten Langgard, carstenl at 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 @@ typedef union _ieee754sp {
+ } 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 @@ ieee754dp ieee754dp_sqrt(ieee754dp x);
+ #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 @@ extern const char *const ieee754_cname[]
+
+ /* "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 *)(¤t->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 @@ static __inline unsigned ieee754_setrm(u
+ /*
+ * 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 @@ static __inline int ieee754_cxtest(unsig
+ /*
+ * 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 @@ extern const struct ieee754sp_konst __ie
+ #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])
+-
+-#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])
++/*
++ * 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])
+
+-/* 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 @@ extern void ieee754_xcpt(struct ieee754x
+ /* 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
+--- 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 @@ int fpu_emulator_save_context(struct sig
+ &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 @@ int fpu_emulator_restore_context(struct
+ &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 @@ int fpu_emulator_save_context32(struct s
+ &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 @@ int fpu_emulator_restore_context32(struc
+ &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
+--- a/arch/mips/mips-boards/atlas/atlas_int.c
++++ b/arch/mips/mips-boards/atlas/atlas_int.c
+@@ -76,14 +76,13 @@ static void end_atlas_irq(unsigned int i
+ }
+
+ 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
+--- a/arch/mips/mips-boards/atlas/atlas_setup.c
++++ b/arch/mips/mips-boards/atlas/atlas_setup.c
+@@ -50,8 +50,10 @@ const char *get_system_type(void)
+ 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 @@ static int __init atlas_setup(void)
+ 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
+--- a/arch/mips/mips-boards/generic/init.c
++++ b/arch/mips/mips-boards/generic/init.c
+@@ -1,6 +1,8 @@
+ /*
+- * Carsten Langgaard, carstenl at 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 at mips.com>
++ * Maciej W. Rozycki <macro at 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 @@ void __init kgdb_config (void)
+ }
+ #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 @@ void __init prom_init(void)
+ #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 @@ void __init prom_init(void)
+ 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 @@ void __init prom_init(void)
+ 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);
++
++ /* 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();
+
+-#ifdef CONFIG_MIPS_MALTA
+ 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 @@ void __init prom_init(void)
+ 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
+--- 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 @@ struct prom_pmemblock * __init prom_getm
+ {
+ 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 {
++ /* 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);
++ prom_printf("prom_memsize = %s\n", memsize_str);
+ #endif
+- memsize = simple_strtol(memsize_str, NULL, 0);
++ 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
+--- 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
+-#endif
++ beqz s0, spurious
++ li a0, 7
+
+- /* 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"
++ 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
+- move a0, sp # delay slot
+
+- j ret_from_irq
+- nop # delay slot
++#ifdef CASCADE_IRQ
++ li a1, CASCADE_IRQ
++ bne a0, a1, 1f
++ addu a0, MIPSCPU_INT_BASE
++
++ jal CASCADE_DISPATCH
++ move a0, 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:
++#else
++ addu a0, MIPSCPU_INT_BASE
+ #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")
++
++ jal do_IRQ
++ move a1, sp
+
+ j ret_from_irq
+ nop
++
++
++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
+--- a/arch/mips/mips-boards/generic/pci.c
++++ b/arch/mips/mips-boards/generic/pci.c
+@@ -1,6 +1,8 @@
+ /*
+- * Carsten Langgaard, carstenl at 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 at mips.com>
++ * Maciej W. Rozycki <macro at mips.com>
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf at 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 @@ static struct pci_controller bonito64_co
+ .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 @@ static struct pci_controller gt64120_con
+ .pci_ops = >64120_pci_ops,
+ .io_resource = >64120_io_resource,
+ .mem_resource = >64120_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 @@ static int __init pcibios_init(void)
+ (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 = >64120_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
+--- 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 char display_string[] = "
+ 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 @@ void __init mips_time_init(void)
+
+ 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_time_init(void)
+
+ 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
+--- 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 @@ static inline int mips_pcibios_iack(void
+ 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 @@ static inline int mips_pcibios_iack(void
+ 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 @@ void corehi_irqdispatch(struct pt_regs *
+ 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
+--- a/arch/mips/mips-boards/malta/malta_setup.c
++++ b/arch/mips/mips-boards/malta/malta_setup.c
+@@ -111,10 +111,12 @@ void __init fd_activate(void)
+ }
+ #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 @@ static int __init malta_setup(void)
+ 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
+--- 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 at mips.com
+ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2003 Ralf Baechle (ralf at 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 @@ asmlinkage void sead_hw1_irqdispatch(str
+
+ 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
+--- a/arch/mips/mips-boards/sead/sead_setup.c
++++ b/arch/mips/mips-boards/sead/sead_setup.c
+@@ -57,8 +57,6 @@ static void __init sead_setup(void)
+ 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
+--- /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
+--- /dev/null
++++ b/arch/mips/mips-boards/sim/cmdline.c
+@@ -0,0 +1,59 @@
++/*
++ * Carsten Langgaard, carstenl at 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
+--- /dev/null
++++ b/arch/mips/mips-boards/sim/sim_IRQ.c
+@@ -0,0 +1,148 @@
++/*
++ * Carsten Langgaard, carstenl at 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
+--- /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
+--- /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
+--- /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
+--- /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
+--- /dev/null
++++ b/arch/mips/mips-boards/sim/sim_printf.c
+@@ -0,0 +1,74 @@
++/*
++ * Carsten Langgaard, carstenl at 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
+--- /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
+--- /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
+--- /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
+--- a/arch/mips/mm/Makefile
++++ b/arch/mips/mm/Makefile
+@@ -22,7 +22,7 @@ obj-$(CONFIG_CPU_R8000) += c-r4k.o cex-
+ 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
+--- a/arch/mips/mm/c-r3k.c
++++ b/arch/mips/mm/c-r3k.c
+@@ -221,12 +221,14 @@ static inline unsigned long get_phys_pag
+ 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 @@ static void r3k_dma_cache_wback_inv(unsi
+ 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
+--- 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 @@ static struct bcache_ops no_sc_ops = {
+
+ 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 @@ static inline void r4k_blast_icache_page
+ 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 @@ static void r4k_flush_cache_mm(struct mm
+
+ 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 @@ static inline void local_r4k_flush_cache
+ */
+ 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 @@ static inline void local_r4k_flush_cache
+ * 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 @@ static void r4k_flush_data_cache_page(un
+ }
+
+ 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 @@ static inline void local_r4k_flush_icach
+ 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 @@ static inline void local_r4k_flush_icach
+ 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 inline void local_r4k_flush_icach
+ }
+ }
+
+-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 @@ static void r4k_flush_icache_range(unsig
+ args.end = end;
+
+ on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
++ instruction_hazard();
+ }
+
+ /*
+@@ -613,7 +626,7 @@ static void r4k_dma_cache_wback_inv(unsi
+ 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 @@ static void r4k_dma_cache_wback_inv(unsi
+ 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 @@ static void r4k_dma_cache_inv(unsigned l
+ 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 @@ static void r4k_dma_cache_inv(unsigned l
+ 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 r4k_dma_cache_inv(unsigned l
+ */
+ 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 @@ static inline void rm7k_erratum31(void)
+
+ 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 @@ static inline void rm7k_erratum31(void)
+ "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 @@ static void __init probe_pcache(void)
+ * 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 @@ static void __init probe_pcache(void)
+ 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 @@ static int __init probe_scache(void)
+ 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 @@ static void __init setup_scache(void)
+ {
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+ unsigned int config = read_c0_config();
+- probe_func_t probe_scache_kseg1;
+ int sc_present = 0;
+
+ /*
+@@ -1123,8 +1148,7 @@ static void __init setup_scache(void)
+ 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 @@ static inline void coherency_setup(void)
+ }
+ }
+
+-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 @@ void __init ld_mmu_r4xx0(void)
+ struct cpuinfo_mips *c = ¤t_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 @@ void __init ld_mmu_r4xx0(void)
+ _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
+--- a/arch/mips/mm/c-sb1.c
++++ b/arch/mips/mm/c-sb1.c
+@@ -235,7 +235,7 @@ static inline void __sb1_flush_icache_ra
+ /*
+ * 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 @@ static __init void probe_cache_sizes(voi
+ }
+
+ /*
+- * 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
+--- a/arch/mips/mm/c-tx39.c
++++ b/arch/mips/mm/c-tx39.c
+@@ -167,15 +167,16 @@ static void tx39_flush_cache_mm(struct m
+ 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 @@ static void tx39_flush_cache_page(struct
+ 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 @@ static void tx39_flush_cache_page(struct
+
+ 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 @@ static __init void tx39_probe_cache(void
+ }
+ }
+
+-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 @@ void __init ld_mmu_tx39(void)
+
+ build_clear_page();
+ build_copy_page();
++ tx39h_flush_icache_all();
+ }
+diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
+--- a/arch/mips/mm/cache.c
++++ b/arch/mips/mm/cache.c
+@@ -23,8 +23,10 @@ void (*__flush_cache_all)(void);
+ 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_cache_sigtramp)(unsigned lo
+ 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 @@ EXPORT_SYMBOL(_dma_cache_inv);
+ * 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 @@ void __update_cache(struct vm_area_struc
+ }
+ }
+
+-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
+-
+- case CPU_R8000:
+- panic("R8000 is unsupported");
+- break;
++ if (cpu_has_3k_cache) {
++ extern void __weak r3k_cache_init(void);
++
++ r3k_cache_init();
++ return;
++ }
++ if (cpu_has_6k_cache) {
++ extern void __weak r6k_cache_init(void);
+
+- default:
+- panic("Yeee, unsupported cache architecture.");
++ 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
+--- 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>
++#include <asm/sibyte/sb1250_regs.h>
+
+-#ifndef CONFIG_SIBYTE_BUS_WATCHER
++#if !defined(CONFIG_SIBYTE_BUS_WATCHER) || defined(CONFIG_SIBYTE_BW_TRACE)
+ #include <asm/io.h>
+-#include <asm/sibyte/sb1250_regs.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 inline void breakout_cerrd(unsign
+ 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 @@ static void check_bus_watcher(void)
+ (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 @@ asmlinkage void sb1_cache_error(void)
+ 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 @@ asmlinkage void sb1_cache_error(void)
+
+ 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 @@ static struct dc_state dc_states[] = {
+ };
+
+ #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 @@ static uint32_t extract_dc(unsigned shor
+ 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 @@ static uint32_t extract_dc(unsigned shor
+ 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 @@ static uint32_t extract_dc(unsigned shor
+ 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
+--- a/arch/mips/mm/cex-sb1.S
++++ b/arch/mips/mm/cex-sb1.S
+@@ -64,6 +64,10 @@ LEAF(except_vec2_sb1)
+ 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:
+ /* 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
+--- 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 @@ void *dma_alloc_noncoherent(struct devic
+ 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
+--- 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 @@ void *dma_alloc_noncoherent(struct devic
+ 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
+--- 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 @@ void *dma_alloc_noncoherent(struct devic
+ 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
+--- 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 @@ void *dma_alloc_noncoherent(struct devic
+ 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 @@ dma_addr_t dma_map_single(struct device
+ {
+ 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 @@ void dma_unmap_single(struct device *dev
+ 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 @@ int dma_map_sg(struct device *dev, struc
+ 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 @@ void dma_unmap_sg(struct device *dev, st
+
+ 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
+--- 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 @@ asmlinkage void do_page_fault(struct pt_
+ * 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 @@ bad_area_nosemaphore:
+ 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 @@ do_sigbus:
+ 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 @@ vmalloc_fault:
+ */
+ 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 @@ vmalloc_fault:
+ 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
+--- a/arch/mips/mm/highmem.c
++++ b/arch/mips/mm/highmem.c
+@@ -83,6 +83,25 @@ void __kunmap_atomic(void *kvaddr, enum
+ 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
+--- a/arch/mips/mm/init.c
++++ b/arch/mips/mm/init.c
+@@ -83,7 +83,7 @@ pte_t *kmap_pte;
+ 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 @@ static void __init kmap_init(void)
+ 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
+--- a/arch/mips/mm/ioremap.c
++++ b/arch/mips/mm/ioremap.c
+@@ -55,7 +55,7 @@ static inline int remap_area_pmd(pmd_t *
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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 @@ fixup_bigphys_addr(phys_t phys_addr, phy
+
+ #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 @@ void * __ioremap(phys_t phys_addr, phys_
+ */
+ 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 @@ void * __ioremap(phys_t phys_addr, phys_
+ 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 @@ void __iounmap(volatile void __iomem *ad
+ 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
+--- 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 @@ static inline void build_cdex_p(void)
+ 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 @@ void __init build_clear_page(void)
+
+ 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 @@ dest = label();
+
+ 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 @@ void __init build_copy_page(void)
+
+ 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 @@ dest = label();
+
+ build_jr_ra();
+
+- flush_icache_range((unsigned long)©_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
+--- a/arch/mips/mm/pg-sb1.c
++++ b/arch/mips/mm/pg-sb1.c
+@@ -60,7 +60,8 @@ static inline void clear_page_cpu(void *
+ " .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 @@ static inline void copy_page_cpu(void *t
+ #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 @@ typedef struct dmadscr_s {
+ 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
+--- 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 @@ void pgd_init(unsigned long page)
+ }
+ }
+
+-#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 @@ void __init pagetable_init(void)
+ 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
+--- 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 @@ static void rm7k_sc_inv(unsigned long ad
+ }
+
+ /*
+- * 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 @@ static __init void __rm7k_sc_enable(void
+ ".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 @@ void __init rm7k_sc_init(void)
+ {
+ 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 @@ void __init rm7k_sc_init(void)
+ * 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
+--- a/arch/mips/mm/tlb-andes.c
++++ b/arch/mips/mm/tlb-andes.c
+@@ -195,6 +195,7 @@ void __update_tlb(struct vm_area_struct
+ {
+ unsigned long flags;
+ pgd_t *pgdp;
++ pud_t *pudp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ int idx, pid;
+@@ -220,7 +221,8 @@ void __update_tlb(struct vm_area_struct
+ 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
+--- 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 @@ void local_flush_tlb_all(void)
+
+ /* 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 @@ void local_flush_tlb_all(void)
+ 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;
++
++ preempt_disable();
+
+- if (cpu_context(cpu, mm) != 0)
+- drop_mmu_context(mm,cpu);
++ 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 @@ void local_flush_tlb_range(struct vm_are
+ 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 @@ void local_flush_tlb_range(struct vm_are
+ 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 @@ void local_flush_tlb_kernel_range(unsign
+ 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 @@ void local_flush_tlb_kernel_range(unsign
+ 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 @@ void local_flush_tlb_page(struct vm_area
+ 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 @@ void local_flush_tlb_one(unsigned long p
+ 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 @@ void local_flush_tlb_one(unsigned long p
+ 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 @@ void __update_tlb(struct vm_area_struct
+ {
+ unsigned long flags;
+ pgd_t *pgdp;
++ pud_t *pudp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ int idx, pid;
+@@ -237,35 +249,34 @@ void __update_tlb(struct vm_area_struct
+ 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 @@ __init int add_temporary_entry(unsigned
+ 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 @@ static void __init probe_tlb(unsigned lo
+ * 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
+--- a/arch/mips/mm/tlb-sb1.c
++++ /dev/null
+@@ -1,376 +0,0 @@
+-/*
+- * Copyright (C) 1996 David S. Miller (dm at engr.sgi.com)
+- * Copyright (C) 1997, 2001 Ralf Baechle (ralf at 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
+--- 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 @@ enum opcode {
+ 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 @@ static __initdata struct insn insn_table
+ { 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(_dsll);
+ 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 @@ enum label_id {
+ 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_tlbs)
+ 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 @@ L_LA(_r3000_write_probe_ok)
+ 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 @@ static void __init build_r3000_tlb_refil
+ 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 @@ static void __init build_r3000_tlb_refil
+ #endif
+
+ memcpy((void *)CAC_BASE, tlb_handler, 0x80);
+- flush_icache_range(CAC_BASE, CAC_BASE + 0x80);
+ }
+
+ /*
+@@ -783,6 +779,8 @@ static __initdata u32 final_handler[64];
+ 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 @@ static __init void build_tlb_write_entry
+ 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 @@ static __init void build_tlb_write_entry
+ 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 @@ static __init void build_tlb_write_entry
+
+ case CPU_4KEC:
+ case CPU_24K:
++ case CPU_34K:
+ i_ehb(p);
+ tlbw(p);
+ break;
+@@ -911,6 +919,7 @@ static __init void build_tlb_write_entry
+
+ case CPU_VR4131:
+ case CPU_VR4133:
++ case CPU_R5432:
+ i_nop(p);
+ i_nop(p);
+ tlbw(p);
+@@ -942,34 +951,29 @@ build_get_pmde64(u32 **p, struct label *
+ /* 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 @@ build_get_pgde32(u32 **p, unsigned int t
+ 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 @@ static void __init build_r4000_tlb_refil
+ {
+ 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_tlbs[FAST
+ 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 @@ iPTE_SW(u32 **p, struct reloc **r, unsig
+ 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 @@ iPTE_SW(u32 **p, struct reloc **r, unsig
+ #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 @@ build_pte_present(u32 **p, struct label
+ 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 @@ static void __init
+ 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 @@ build_pte_writable(u32 **p, struct label
+ 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 @@ static void __init
+ 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 @@ build_pte_modifiable(u32 **p, struct lab
+ {
+ 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 @@ build_r3000_tlbchange_handler_head(u32 *
+ 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 @@ static void __init build_r3000_tlb_load_
+
+ 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 @@ static void __init build_r3000_tlb_load_
+ {
+ 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 @@ static void __init build_r3000_tlb_store
+
+ 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 @@ static void __init build_r3000_tlb_store
+ {
+ 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 @@ static void __init build_r3000_tlb_modif
+
+ 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 @@ static void __init build_r3000_tlb_modif
+ {
+ 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 @@ build_r4000_tlbchange_handler_head(u32 *
+ #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 @@ static void __init build_r4000_tlb_load_
+ {
+ 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 @@ static void __init build_r4000_tlb_store
+ {
+ 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 @@ static void __init build_r4000_tlb_modif
+ {
+ 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 build_tlb_refill_handler(voi
+ }
+ }
+ }
++
++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
+--- /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
+--- a/arch/mips/momentum/jaguar_atx/prom.c
++++ b/arch/mips/momentum/jaguar_atx/prom.c
+@@ -236,8 +236,9 @@ void __init prom_init(void)
+ #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
+--- a/arch/mips/momentum/jaguar_atx/setup.c
++++ b/arch/mips/momentum/jaguar_atx/setup.c
+@@ -351,7 +351,7 @@ static __init int __init ja_pci_init(voi
+
+ 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 @@ static int __init momenco_jaguar_atx_se
+
+ }
+ #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
+--- a/arch/mips/momentum/ocelot_3/prom.c
++++ b/arch/mips/momentum/ocelot_3/prom.c
+@@ -239,8 +239,9 @@ void __init prom_init(void)
+ #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
+--- a/arch/mips/momentum/ocelot_3/setup.c
++++ b/arch/mips/momentum/ocelot_3/setup.c
+@@ -307,7 +307,7 @@ static __init int __init ja_pci_init(voi
+
+ 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 @@ static int __init momenco_ocelot_3_setup
+
+ /* 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
+--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
++++ b/arch/mips/momentum/ocelot_c/cpci-irq.c
+@@ -129,14 +129,13 @@ void ll_cpci_irq(struct pt_regs *regs)
+ #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
+--- a/arch/mips/momentum/ocelot_c/setup.c
++++ b/arch/mips/momentum/ocelot_c/setup.c
+@@ -222,7 +222,7 @@ void momenco_time_init(void)
+ 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 @@ static void __init momenco_ocelot_c_setu
+ }
+ }
+
+-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
+--- a/arch/mips/momentum/ocelot_c/uart-irq.c
++++ b/arch/mips/momentum/ocelot_c/uart-irq.c
+@@ -122,14 +122,13 @@ void ll_uart_irq(struct pt_regs *regs)
+ #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
+--- a/arch/mips/momentum/ocelot_g/setup.c
++++ b/arch/mips/momentum/ocelot_g/setup.c
+@@ -160,7 +160,7 @@ static void __init setup_l3cache(unsigne
+ 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 @@ static int __init momenco_ocelot_g_setu
+
+ /* 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
+--- a/arch/mips/oprofile/Kconfig
++++ b/arch/mips/oprofile/Kconfig
+@@ -11,7 +11,7 @@ config PROFILING
+
+ 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
+--- 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 @@ static int op_mips_create_files(struct s
+ 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 @@ static void op_mips_stop(void)
+ 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 @@ void __init oprofile_arch_init(struct op
+ };
+
+ 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
+--- 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
+--- /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
+--- 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 @@ static irqreturn_t rm9000_perfcount_hand
+ 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
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -34,6 +34,7 @@ obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8
+ 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_PMC_YOSEMITE) += fixup-yose
+ 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
+--- 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 at linux-mips.org)
++ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
++ * Author: Maciej W. Rozycki <macro at 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 @@ static char irq_tab[][5] __initdata = {
+ {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
+--- 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
+--- 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 @@ static void qube_raq_galileo_fixup(struc
+ {
+ 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 @@ static void qube_raq_galileo_fixup(struc
+ 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 @@ static void qube_raq_galileo_fixup(struc
+ */
+ 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 @@ static char irq_tab_raq2[] __initdata =
+
+ 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
+--- /dev/null
++++ b/arch/mips/pci/fixup-pnx8550.c
+@@ -0,0 +1,57 @@
++/*
++ * Philips PNX8550 pci fixups.
++ *
++ * Copyright 2005 Embedded Alley Solutions, Inc
++ * source at 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
+--- /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 at 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
+--- 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 @@ void mod_wired_entry(int entry, unsigned
+ 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 @@ static int config_access(unsigned char a
+ 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
+--- a/arch/mips/pci/ops-bonito64.c
++++ b/arch/mips/pci/ops-bonito64.c
+@@ -1,6 +1,8 @@
+ /*
+- * Carsten Langgaard, carstenl at 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 at mips.com>
++ * Maciej W. Rozycki <macro at 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 @@ static int bonito64_pcibios_config_acces
+ 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
+--- 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
+--- a/arch/mips/pci/ops-gt64120.c
++++ b/arch/mips/pci/ops-gt64120.c
+@@ -1,6 +1,8 @@
+ /*
+- * Carsten Langgaard, carstenl at 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 at mips.com>
++ * Maciej W. Rozycki <macro at 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 @@ static int gt64120_pcibios_config_access
+ 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
+--- 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 @@ static int msc_pcibios_config_access(uns
+ 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 @@ static int msc_pcibios_config_access(uns
+
+ /* 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
+--- 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- a/arch/mips/pci/pci-ip27.c
++++ b/arch/mips/pci/pci-ip27.c
+@@ -485,5 +485,12 @@ static void __init pci_fixup_ioc3(struct
+ 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
+--- a/arch/mips/pci/pci-ip32.c
++++ b/arch/mips/pci/pci-ip32.c
+@@ -136,7 +136,9 @@ static int __init mace_init(void)
+ 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
+--- 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 @@ extern struct pci_ops gt64120_pci_ops;
+ 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 struct pci_controller lasat_pci_c
+
+ 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 = >64120_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 @@ early_initcall(lasat_pci_setup);
+
+ 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
+--- a/arch/mips/pci/pci.c
++++ b/arch/mips/pci/pci.c
+@@ -127,15 +127,20 @@ static int __init pcibios_init(void)
+ 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 @@ static int pcibios_enable_resources(stru
+
+ 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
+--- /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
+--- /dev/null
++++ b/arch/mips/philips/pnx8550/common/Makefile
+@@ -0,0 +1,27 @@
++#
++# Per Hallsmark, per.hallsmark at 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
+--- /dev/null
++++ b/arch/mips/philips/pnx8550/common/gdb_hook.c
+@@ -0,0 +1,109 @@
++/*
++ * Carsten Langgaard, carstenl at 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
+--- /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 at mvista.com
++ * Copyright (C) 2000, 2001 MIPS Technologies, Inc.
++ * Copyright (C) 2001 Ralf Baechle
++ *
++ * Cleaned up and bug fixing: Pete Popov, ppopov at 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
+--- /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
+--- /dev/null
++++ b/arch/mips/philips/pnx8550/common/pci.c
+@@ -0,0 +1,133 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ *
++ * Author: source at 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
+--- /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 at 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
+--- /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
+--- /dev/null
++++ b/arch/mips/philips/pnx8550/common/prom.c
+@@ -0,0 +1,138 @@
++/*
++ *
++ * Per Hallsmark, per.hallsmark at 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
+--- /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
+--- /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 at 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
+--- /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 at mvista.com or jsun at 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
+--- /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
+--- /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
+--- /dev/null
++++ b/arch/mips/philips/pnx8550/jbs/init.c
+@@ -0,0 +1,57 @@
++/*
++ *
++ * Copyright 2005 Embedded Alley Solutions, Inc
++ * source at 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
+--- /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 at 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
+--- /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
+--- 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
+--- 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
+--- 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
+--- a/arch/mips/pmc-sierra/yosemite/prom.c
++++ b/arch/mips/pmc-sierra/yosemite/prom.c
+@@ -132,8 +132,9 @@ void __init prom_init(void)
+ 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
+--- a/arch/mips/pmc-sierra/yosemite/setup.c
++++ b/arch/mips/pmc-sierra/yosemite/setup.c
+@@ -212,7 +212,7 @@ static void __init py_late_time_init(voi
+ 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 @@ static int __init pmc_yosemite_setup(voi
+ 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
+--- a/arch/mips/pmc-sierra/yosemite/smp.c
++++ b/arch/mips/pmc-sierra/yosemite/smp.c
+@@ -9,7 +9,7 @@ extern void (*mips_hpt_init)(unsigned in
+
+ #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
+--- 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
+--- 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
++
++static char __init *decode_eisa_sig(unsigned long addr)
++{
++ static char sig_str[EISA_SIG_LEN];
++ u8 sig[4];
++ u16 rev;
++ int i;
+
+-#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))
++ for (i = 0; i < 4; i++) {
++ sig[i] = inb (addr + i);
+
+-static char *decode_eisa_sig(u8 * sig)
+-{
+- static char sig_str[8];
+- u16 rev;
+-
+- if (sig[0] & 0x80)
+- return NULL;
++ 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 @@ static char *decode_eisa_sig(u8 * sig)
+ 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);
+-
+- 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
++ eisa_irq = inb(EIU_INTRPT_ACK);
++ dma1 = inb(EISA_DMA1_STATUS);
++ dma2 = inb(EISA_DMA2_STATUS);
++
++ 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 @@ static void enable_eisa1_irq(unsigned in
+
+ 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 @@ static unsigned int startup_eisa1_irq(un
+
+ /* 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 @@ static void disable_eisa1_irq(unsigned i
+ {
+ 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 @@ static void mask_and_ack_eisa1_irq(unsig
+ {
+ 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 @@ static void enable_eisa2_irq(unsigned in
+
+ 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 @@ static unsigned int startup_eisa2_irq(un
+
+ /* 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 @@ static void disable_eisa2_irq(unsigned i
+ {
+ 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 @@ static void mask_and_ack_eisa2_irq(unsig
+ {
+ 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 __init ip22_eisa_init(void)
+ {
+ 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 @@ int __init ip22_eisa_init(void)
+ }
+
+ 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 @@ int __init ip22_eisa_init(void)
+ 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
+--- a/arch/mips/sgi-ip22/ip22-setup.c
++++ b/arch/mips/sgi-ip22/ip22-setup.c
+@@ -53,7 +53,7 @@ EXPORT_SYMBOL(ip22_do_break);
+ 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 @@ static int __init ip22_setup(void)
+ }
+ }
+ #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
+--- /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
+--- 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
+--- 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
+--- a/arch/mips/sgi-ip27/ip27-init.c
++++ b/arch/mips/sgi-ip27/ip27-init.c
+@@ -56,12 +56,12 @@ static void __init per_hub_init(cnodeid_
+ {
+ 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 @@ static void __init per_hub_init(cnodeid_
+ __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 @@ void __init per_cpu_init(void)
+
+ 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 @@ void __init per_cpu_init(void)
+ install_cpu_nmi_handler(cputoslice(cpu));
+
+ set_c0_status(SRB_DEV0 | SRB_DEV1);
+-
+- per_hub_init(cnode);
+ }
+
+ /*
+@@ -198,7 +196,7 @@ extern void ip27_setup_console(void);
+ 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 @@ static int __init ip27_setup(void)
+ 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
+--- 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 @@ extern int irq_to_slot[];
+
+ 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 @@ static int intr_connect_level(int cpu, i
+ {
+ 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 @@ static int intr_connect_level(int cpu, i
+ 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 @@ static int intr_disconnect_level(int cpu
+ 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 @@ static unsigned int startup_bridge_irq(u
+ 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 unsigned int startup_bridge_irq(u
+ 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 @@ static void shutdown_bridge_irq(unsigned
+ 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 @@ void install_ipi(void)
+ 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
+--- a/arch/mips/sgi-ip27/ip27-smp.c
++++ b/arch/mips/sgi-ip27/ip27-smp.c
+@@ -127,37 +127,28 @@ void cpu_node_probe(void)
+ 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
+--- a/arch/mips/sgi-ip32/ip32-irq.c
++++ b/arch/mips/sgi-ip32/ip32-irq.c
+@@ -163,14 +163,13 @@ static void end_cpu_irq(unsigned int irq
+ #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 @@ static void end_crime_irq(unsigned int i
+ #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 @@ static void end_macepci_irq(unsigned int
+ #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 @@ static void end_maceisa_irq(unsigned irq
+ #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 @@ static void end_mace_irq(unsigned int ir
+ #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
+--- a/arch/mips/sgi-ip32/ip32-memory.c
++++ b/arch/mips/sgi-ip32/ip32-memory.c
+@@ -36,8 +36,8 @@ void __init prom_meminit (void)
+ 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
+--- a/arch/mips/sgi-ip32/ip32-setup.c
++++ b/arch/mips/sgi-ip32/ip32-setup.c
+@@ -92,7 +92,7 @@ void __init ip32_timer_setup(struct irqa
+ 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 @@ static int __init ip32_setup(void)
+ }
+ }
+ #endif
+-
+- return 0;
+ }
+-
+-early_initcall(ip32_setup);
+diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
+new file mode 100644
+--- /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
+--- /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
+--- /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(®s->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
+--- /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
+--- /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
+--- /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
+--- /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
+--- a/arch/mips/sibyte/cfe/smp.c
++++ b/arch/mips/sibyte/cfe/smp.c
+@@ -70,8 +70,15 @@ void prom_boot_secondary(int cpu, struct
+ */
+ 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_init_secondary(void)
+ */
+ 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
+--- 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 @@ static void arm_tb(void)
+ 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 @@ static irqreturn_t sbprof_tb_intr(int ir
+ /* 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 @@ static irqreturn_t sbprof_tb_intr(int ir
+ } 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 @@ int sbprof_zbprof_start(struct file *fil
+ 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 @@ int sbprof_zbprof_start(struct file *fil
+ /* 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));
+-
+- 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));
+-
+- 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_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));
++
++ __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));
++
++ __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_start(struct file *fil
+
+ int sbprof_zbprof_stop(void)
+ {
++ DEFINE_WAIT(wait);
+ DBG(printk(DEVNAME ": stopping\n"));
+
+ if (sbp.tb_enable) {
+@@ -240,7 +249,9 @@ int sbprof_zbprof_stop(void)
+ 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 @@ static ssize_t sbprof_tb_read(struct fil
+ 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 @@ static int sbprof_tb_ioctl(struct inode
+ 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 @@ static struct file_operations sbprof_tb_
+ .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
+--- a/arch/mips/sibyte/sb1250/bus_watcher.c
++++ b/arch/mips/sibyte/sb1250/bus_watcher.c
+@@ -189,7 +189,7 @@ static irqreturn_t sibyte_bw_int(int irq
+
+ 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
+--- a/arch/mips/sibyte/sb1250/irq.c
++++ b/arch/mips/sibyte/sb1250/irq.c
+@@ -53,7 +53,7 @@ static void disable_sb1250_irq(unsigned
+ 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 @@ extern char sb1250_duart_present[];
+ #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 @@ void sb1250_mask_irq(int cpu, int irq)
+ 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 @@ void sb1250_unmask_irq(int cpu, int irq)
+ 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 @@ static void sb1250_set_affinity(unsigned
+
+ /* 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 @@ static void ack_sb1250_irq(unsigned int
+ * 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 @@ static void ack_sb1250_irq(unsigned int
+ * 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 @@ void __init arch_init_irq(void)
+
+ /* 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 @@ void __init arch_init_irq(void)
+ * 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 @@ void __init arch_init_irq(void)
+ 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
+--- a/arch/mips/sibyte/sb1250/setup.c
++++ b/arch/mips/sibyte/sb1250/setup.c
+@@ -153,7 +153,7 @@ void sb1250_setup(void)
+ 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 @@ void sb1250_setup(void)
+ 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
+--- 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 sb1250_smp_finish(void)
+ */
+ 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 @@ void sb1250_mailbox_interrupt(struct pt_
+
+ 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
+--- a/arch/mips/sibyte/sb1250/time.c
++++ b/arch/mips/sibyte/sb1250/time.c
+@@ -67,24 +67,24 @@ void sb1250_time_init(void)
+ 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_time_init(void)
+
+ 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 @@ void sb1250_timer_interrupt(struct pt_re
+ 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
+--- 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
+--- 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
+--- 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 at 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 @@ void __init swarm_timer_setup(struct irq
+ */
+
+ /* 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 @@ static int __init swarm_setup(void)
+ };
+ /* 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
+--- a/arch/mips/sibyte/swarm/time.c
++++ b/arch/mips/sibyte/swarm/time.c
+@@ -79,48 +79,48 @@ static unsigned int usec_bias = 0;
+
+ 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 @@ void __init swarm_time_init(void)
+ /* 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
+--- a/arch/mips/sni/irq.c
++++ b/arch/mips/sni/irq.c
+@@ -58,14 +58,13 @@ static void end_pciasic_irq(unsigned int
+ }
+
+ 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
+--- a/arch/mips/sni/setup.c
++++ b/arch/mips/sni/setup.c
+@@ -167,7 +167,7 @@ static inline void sni_pcimt_time_init(v
+ 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 @@ static int __init sni_rm200_pci_setup(vo
+ #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
+--- /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
+--- a/arch/mips/tx4927/common/tx4927_setup.c
++++ b/arch/mips/tx4927/common/tx4927_setup.c
+@@ -64,7 +64,7 @@ static void tx4927_write_buffer_flush(vo
+ }
+
+
+-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 @@ static void __init tx4927_setup(void)
+ 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
+--- 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 @@ void __init toshiba_rbtx4927_setup(void)
+
+ #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
+--- /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
+--- /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
+--- /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 at 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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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
+--- 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
+--- a/arch/mips/vr41xx/common/init.c
++++ b/arch/mips/vr41xx/common/init.c
+@@ -58,6 +58,14 @@ static void __init timer_init(void)
+ 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 @@ void __init prom_init(void)
+ 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
+--- a/arch/mips/vr41xx/common/vrc4173.c
++++ b/arch/mips/vr41xx/common/vrc4173.c
+@@ -81,8 +81,8 @@ EXPORT_SYMBOL(vrc4173_io_offset);
+ 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
+--- a/arch/mips/vr41xx/nec-cmbvr4133/setup.c
++++ b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
+@@ -56,7 +56,7 @@ static struct mtd_partition cmbvr4133_mt
+
+ 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 @@ static int __init nec_cmbvr4133_setup(vo
+ #ifdef CONFIG_ROCKHOPPER
+ i8259_init();
+ #endif
+- return 0;
+ }
+-
+-early_initcall(nec_cmbvr4133_setup);
+diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
+--- a/arch/parisc/Kconfig
++++ b/arch/parisc/Kconfig
+@@ -47,10 +47,10 @@ config PM
+
+ 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 HOTPLUG_CPU
+
+ 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
+--- a/arch/parisc/Makefile
++++ b/arch/parisc/Makefile
+@@ -20,7 +20,8 @@ NM = sh $(srctree)/arch/parisc/nm
+ 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 @@ FINAL_LD=$(CROSS_COMPILE)ld --warn-commo
+
+ 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 @@ cflags-y += -mno-space-regs -mfast-indir
+ # 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
+--- 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_EXPERIMENTAL=y
+ # 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_PA7100LC=y
+ # 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_LASI=y
+ # 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_CHASSIS_LCD_LED=y
+ # 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_ELF=y
+ 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_NET=y
+ #
+ 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_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
++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_IP_TCPDIAG=y
+ # 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_NETFILTER=y
+ 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_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_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_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
+@@ -340,10 +240,11 @@ CONFIG_IP_NF_TARGET_NOTRACK=m
+ 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_LLC2=m
+ # 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 @@ CONFIG_LLC2=m
+ # 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_TUN=m
+ 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_NET_RADIO=y
+ #
+ # CONFIG_STRIP is not set
+ # CONFIG_ATMEL is not set
++# CONFIG_HOSTAP is not set
+
+ #
+ # Wan interfaces
+@@ -431,6 +475,8 @@ 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
+@@ -460,19 +506,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # 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_ATKBD_HP_KEYCODES=y
+ # 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_MOUSE_HIL=m
+ # 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_EXTENDED=y
+ 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 @@ CONFIG_GEN_RTC_X=y
+ #
+ # 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_MAX_RAW_DEVS=256
+ # 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 @@ CONFIG_MAX_RAW_DEVS=256
+ # 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=y
+ # 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_SND_HARMONY=y
+ # 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_SND_HARMONY=y
+ # 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_JBD=y
+ # 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_UFS_FS=m
+ #
+ 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_CIFS=m
+ # 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 @@ CONFIG_OPROFILE=m
+ #
+ # 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_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=m
+ CONFIG_CRYPTO_TWOFISH=m
+@@ -882,9 +967,14 @@ CONFIG_CRYPTO_CRC32C=m
+ 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
+--- 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_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
+@@ -19,26 +20,32 @@ CONFIG_EXPERIMENTAL=y
+ 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_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
+@@ -74,7 +82,19 @@ CONFIG_PREFETCH=y
+ 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_NR_CPUS=8
+ # 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_IOMMU_SBA=y
+ 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_CARDBUS=y
+ CONFIG_YENTA=m
+ CONFIG_PD6729=m
+ CONFIG_I82092=m
+-CONFIG_TCIC=m
+ CONFIG_PCCARD_NONSTATIC=m
+
+ #
+@@ -127,6 +148,203 @@ 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=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_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
+@@ -169,7 +392,6 @@ 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
+
+ #
+@@ -189,6 +411,7 @@ CONFIG_IOSCHED_CFQ=y
+ #
+ # SCSI device support
+ #
++CONFIG_RAID_ATTRS=m
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -201,6 +424,7 @@ CONFIG_CHR_DEV_ST=y
+ 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_MULTI_LUN=y
+ 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_ISCSI_ATTRS=m
+ # 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_DEFAULT_TAGS=16
+ 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_QLA2XXX=y
+ # 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 @@ CONFIG_MD_RAID1=y
+ #
+ # 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_FUSION_CTL=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
++# Network device support
+ #
+-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_TUN=m
+ # 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_TULIP_MMIO=y
+ # 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_PCNET32=m
+ # 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_PCMCIA_RAYCS=m
+ 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 @@ CONFIG_PCI_HERMES=m
+ # 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 @@ CONFIG_PCMCIA_WL3501=m
+ # 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_PPP_BSDCOMP=m
+ # 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=y
+ # 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_SOUND_GAMEPORT=y
+ # 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_EXTENDED=y
+ 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_SERIAL_8250_SHARE_IRQ=y
+ 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_RAW_DRIVER=y
+ 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_MAX_RAW_DEVS=256
+ # 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_MAX_RAW_DEVS=256
+ 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 @@ CONFIG_DUMMY_CONSOLE_ROWS=64
+ #
+ # 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 @@ CONFIG_USB_ARCH_HAS_OHCI=y
+ #
+ # 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_FS=m
+ # 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_UFS_FS=m
+ #
+ 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_CIFS=m
+ # 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_437=m
+ # 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_865=m
+ # 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 @@ CONFIG_OPROFILE=m
+ #
+ # 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_KEYS_DEBUG_PROC_KEYS=y
+ 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 @@ CONFIG_CRYPTO_TEST=m
+ # 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
+--- 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_RWSEM_GENERIC_SPINLOCK=y
+ # 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_PA7100LC=y
+ # 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_EISA_NAMES=y
+ 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_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_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_BINFMT_ELF=y
+ #
+ 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_STANDALONE=y
+ #
+ 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 @@ CONFIG_PARPORT_GSC=y
+ #
+ # 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_NOOP=y
+ 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 @@ CONFIG_IOSCHED_CFQ=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -170,6 +261,7 @@ CONFIG_CHR_DEV_ST=y
+ 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_CHR_DEV_SG=y
+ #
+ 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_SPI_ATTRS=y
+ # 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_SPI_ATTRS=y
+ # 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_SYM53C8XX_MAX_TAGS=64
+ # 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_QLA2XXX=y
+ # 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_LINEAR=y
+ 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 @@ CONFIG_MD_RAID5=y
+ # 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_MD_RAID5=y
+ # CONFIG_I2O is not set
+
+ #
+-# 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_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
++# Network device support
+ #
+-# 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_NETDEVICES=y
+ # 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_NET_ETHERNET=y
+ # 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_TULIP=y
+ # 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_TULIP=y
+ # 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 @@ CONFIG_NET_RADIO=y
+ #
+ # 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=y
+ # 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_EVDEV=y
+ # 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_INPUT_KEYBOARD=y
+ # 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_INPUT_MISC=y
+ # 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_EXTENDED=y
+ 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_SERIAL_8250_SHARE_IRQ=y
+ # 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 @@ CONFIG_GEN_RTC=y
+ #
+ # 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_GEN_RTC=y
+ # 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 @@ CONFIG_GEN_RTC=y
+ # 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=y
+ # 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_STI=y
+ # 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_MONO=y
+ 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 @@ CONFIG_LOGO_PARISC_CLUT224=y
+ #
+ # 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_USB_ARCH_HAS_OHCI=y
+ # 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_JOLIET=y
+ 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_RAMFS=y
+ #
+ 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 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # 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=y
+ # 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=y
+ # 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
+--- 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_EXPERIMENTAL=y
+ # 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_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
+@@ -66,10 +76,19 @@ CONFIG_KMOD=y
+ 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_PREFETCH=y
+ # 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,13 +109,17 @@ CONFIG_CHASSIS_LCD_LED=y
+ # CONFIG_PCCARD is not set
+
+ #
+-# PC-card bridges
++# PCI Hotplug Support
+ #
++# CONFIG_HOTPLUG_PCI is not set
+
+ #
+-# PCI Hotplug Support
++# PA-RISC specific drivers
+ #
+-# CONFIG_HOTPLUG_PCI is not set
++CONFIG_SUPERIO=y
++CONFIG_CHASSIS_LCD_LED=y
++# CONFIG_PDC_CHASSIS is not set
++CONFIG_PDC_STABLE=y
+
+ #
+ # Executable file formats
+@@ -108,6 +128,186 @@ 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_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
+@@ -141,14 +346,14 @@ CONFIG_FW_LOADER=y
+ # 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_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
+@@ -201,6 +407,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
+ # 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 @@ CONFIG_BLK_DEV_IDEDMA=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -230,6 +438,7 @@ CONFIG_CHR_DEV_ST=y
+ 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 @@ CONFIG_SCSI_MULTI_LUN=y
+ # 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_FC_ATTRS=m
+ # 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_DEFAULT_TAGS=16
+ 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_RAID1=y
+ # 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_FUSION_CTL=m
+ # CONFIG_I2O is not set
+
+ #
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
++# Network device support
+ #
+-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_TUN=m
+ # 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_TULIP_MMIO=y
+ # 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_E1000=m
+ # 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_PPPOE=m
+ # 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_MOUSEDEV_SCREEN_Y=1200
+ # 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_MOUSE=y
+ # 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_EXTENDED=y
+ 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_SERIAL_8250_SHARE_IRQ=y
+ # 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 @@ CONFIG_GEN_RTC_X=y
+ #
+ # 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_MAX_RAW_DEVS=256
+ # 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 @@ CONFIG_MAX_RAW_DEVS=256
+ # 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=y
+ # 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_STI=y
+ # 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=y
+ # 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 @@ CONFIG_SOUND=y
+ #
+ # 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 @@ CONFIG_SOUND=y
+ #
+ # 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_DEVICEFS=y
+ # 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_PRINTER=m
+ #
+ 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_HID=y
+ 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_HPUSBSCSI=m
+ # 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_HPUSBSCSI=m
+ #
+ # 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_LEGOTOWER=m
+ # 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_USB_LEGOTOWER=m
+ # 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_FAT_DEFAULT_IOCHARSET="iso8859-1"
+ 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_RAMFS=y
+ #
+ 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_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+@@ -1074,13 +1272,19 @@ CONFIG_OPROFILE=m
+ #
+ # 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 @@ CONFIG_MAGIC_SYSRQ=y
+ # 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_CRC32C=m
+ 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
+--- 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_IOSCHED_DEADLINE=y
+ 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_EISA_NAMES=y
+ # 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_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_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_BINFMT_ELF=y
+ #
+ 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 @@ CONFIG_PARPORT_GSC=y
+ #
+ # 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 @@ CONFIG_BLK_DEV_INITRD=y
+ #
+ # SCSI device support
+ #
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -147,53 +285,59 @@ CONFIG_CHR_DEV_ST=y
+ 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_QLA2XXX=y
+ # 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_BLK_DEV_MD=y
+ 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_MD_RAID5=y
+ # CONFIG_I2O is not set
+
+ #
+-# Macintosh device drivers
+-#
+-
+-#
+-# 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
++# Network device support
+ #
+-# 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_NET_ETHERNET=y
+ 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_TULIP=y
+ # 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_NET_PCI=y
+ # 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 @@ CONFIG_NET_RADIO=y
+ #
+ # 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,51 +554,67 @@ CONFIG_INPUT_EVDEV=y
+ # 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=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_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_TWIDDLER 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_INPUT_JOYDUMP 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_PCSPKR is not set
+ # 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
++CONFIG_SERIO_GSCPS2=y
++CONFIG_HP_SDC=y
++CONFIG_HIL_MLC=y
++# CONFIG_SERIO_PCIPS2 is not set
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
+ # Character devices
+ #
+ CONFIG_VT=y
+@@ -522,16 +632,16 @@ CONFIG_SERIAL_8250_EXTENDED=y
+ 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_PRINTER=y
+ # 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 @@ CONFIG_PRINTER=y
+ # 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 @@ CONFIG_GEN_RTC=y
+ #
+ # 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 @@ CONFIG_GEN_RTC=y
+ # 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 @@ CONFIG_FONT_8x16=y
+ # Logo configuration
+ #
+ # CONFIG_LOGO is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+@@ -638,17 +772,94 @@ CONFIG_SOUND=y
+ #
+ # 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_DEBUG=y
+ # 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_OHCI_HCD=y
+ # 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 @@ CONFIG_USB_OHCI_HCD=y
+ #
+
+ #
+-# 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_OHCI_HCD=y
+ #
+ # 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_OHCI_HCD=y
+ # 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 @@ CONFIG_JOLIET=y
+ #
+ # 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_JOLIET=y
+ #
+ 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_RAMFS=y
+ #
+ 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_DEFAULT="iso8859-1"
+ # 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 @@ CONFIG_OPROFILE=y
+ #
+ # 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=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
+@@ -916,11 +1190,23 @@ CONFIG_CRYPTO=y
+ # 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
+--- 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 @@ parisc_cache_init(void)
+
+ /* "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 @@ void flush_dcache_page(struct page *page
+ unsigned long offset;
+ unsigned long addr;
+ pgoff_t pgoff;
+- pte_t *pte;
+ unsigned long pfn = page_to_pfn(page);
+
+
+@@ -297,21 +300,16 @@ void flush_dcache_page(struct page *page
+ * 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 @@ int parisc_cache_flush_threshold = FLUSH
+ 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
+--- a/arch/parisc/kernel/drivers.c
++++ b/arch/parisc/kernel/drivers.c
+@@ -46,36 +46,51 @@ static struct device root = {
+ .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;
++}
++
++static struct device *
++parse_tree_node(struct device *parent, int index, struct hardware_path *modpath);
+
+-#define check_dev(padev) \
+- (padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev)
++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)
+-{
+- 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;
++static int for_each_padev(int (*fn)(struct device *, void *), void * data)
++{
++ struct recurse_struct recurse_data = {
++ .obj = data,
++ .fn = fn,
++ };
++ return device_for_each_child(&root, &recurse_data, descend_children);
+ }
+
+ /**
+@@ -105,12 +120,6 @@ static int match_device(struct parisc_dr
+ 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 @@ static int parisc_driver_probe(struct de
+
+ 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 @@ static int parisc_driver_remove(struct d
+ 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 @@ int register_parisc_driver(struct parisc
+ }
+ 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 @@ EXPORT_SYMBOL(register_parisc_driver);
+ */
+ 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 @@ int unregister_parisc_driver(struct pari
+ }
+ EXPORT_SYMBOL(unregister_parisc_driver);
+
+-static struct parisc_device *find_device_by_addr(unsigned long hpa)
++struct find_data {
++ unsigned long hpa;
++ struct parisc_device * dev;
++};
++
++static int find_device(struct device * dev, void * data)
+ {
+- struct parisc_device *dev;
+- for_each_padev(dev) {
+- if (dev->hpa == hpa)
+- return dev;
++ 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 NULL;
++ return 0;
++}
++
++static struct parisc_device *find_device_by_addr(unsigned long hpa)
++{
++ struct find_data d = {
++ .hpa = hpa,
++ };
++ int ret;
++
++ ret = for_each_padev(find_device, &d);
++ return ret ? d.dev : NULL;
+ }
+
+ /**
+@@ -387,6 +432,23 @@ struct parisc_device * create_tree_node(
+ 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 @@ struct parisc_device * create_tree_node(
+ */
+ 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 @@ alloc_pa_dev(unsigned long hpa, struct h
+
+ 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 @@ alloc_pa_dev(unsigned long hpa, struct h
+ 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 @@ static int match_parisc_device(struct de
+ 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 int match_parisc_device(struct de
+ 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,
++ };
++
++ struct recurse_struct recurse_data = {
++ .obj = &d,
++ .fn = check_parent,
++ };
+
+- return NULL;
++ device_for_each_child(parent, &recurse_data, descend_children);
++ return d.dev;
+ }
+
+ /**
+@@ -636,7 +730,7 @@ EXPORT_SYMBOL(device_to_hwpath);
+ ((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 @@ EXPORT_SYMBOL(device_to_hwpath);
+ #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 @@ void walk_lower_bus(struct parisc_device
+ {
+ 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 @@ static void print_parisc_device(struct p
+
+ 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 @@ void init_parisc_bus(void)
+ 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
+--- 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 @@ fault_vector_20:
+ def 30
+ def 31
+
+-#ifndef __LP64__
++#ifndef CONFIG_64BIT
+
+ .export fault_vector_11
+
+@@ -761,7 +764,7 @@ __kernel_thread:
+
+ 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 @@ __kernel_thread:
+ 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 @@ ret_from_kernel_thread:
+
+ 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 @@ ret_from_kernel_thread:
+ 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 @@ __execve:
+ 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 @@ __execve:
+ _switch_to:
+ STREG %r2, -RP_OFFSET(%r30)
+
++ callee_save_float
+ callee_save
+
+ load32 _switch_to_ret, %r2
+@@ -871,6 +880,7 @@ _switch_to:
+ _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 @@ _switch_to_ret:
+ * 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 @@ syscall_exit_rfi:
+ 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 @@ intr_return:
+ /* 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 @@ intr_return:
+ 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 @@ intr_restore:
+ 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 @@ intr_restore:
+ 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 @@ intr_do_resched:
+ 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 @@ intr_do_signal:
+
+ 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 @@ intr_extint:
+ 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 @@ intr_extint:
+
+ ldil L%intr_return, %r2
+
+-#ifdef __LP64__
++#ifdef CONFIG_64BIT
+ ldo -16(%r30),%r29 /* Reference param save area */
+ #endif
+
+@@ -1153,15 +1146,17 @@ intr_save:
+
+ 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 @@ skip_save_ior:
+ 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 @@ skip_save_ior:
+ 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 @@ nadtlb_emulate:
+ 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 @@ nadtlb_probe_check:
+ nop
+
+
+-#ifdef __LP64__
++#ifdef CONFIG_64BIT
+ itlb_miss_20w:
+
+ /*
+@@ -1588,7 +1583,7 @@ itlb_miss_20:
+
+ #endif
+
+-#ifdef __LP64__
++#ifdef CONFIG_64BIT
+
+ dbit_trap_20w:
+ space_adjust spc,va,t0
+@@ -1797,7 +1792,7 @@ sys_fork_wrapper:
+
+ 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 @@ sys_clone_wrapper:
+
+ 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 @@ sys_vfork_wrapper:
+
+ 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 @@ sys_vfork_wrapper:
+
+ 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 @@ error_\execve:
+ sys_execve_wrapper:
+ execve_wrapper sys_execve
+
+-#ifdef __LP64__
++#ifdef CONFIG_64BIT
+ .export sys32_execve_wrapper
+ .import sys32_execve
+
+@@ -1937,7 +1932,7 @@ sys_rt_sigreturn_wrapper:
+ 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 @@ sys_sigaltstack_wrapper:
+ 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 @@ sys_sigaltstack_wrapper:
+ 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 @@ sys_rt_sigsuspend_wrapper:
+ 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 @@ syscall_check_bh:
+ 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 @@ syscall_check_bh:
+ 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 @@ syscall_restore:
+
+ 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 @@ pt_regs_ok:
+ 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 @@ syscall_do_signal:
+
+ 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
+--- a/arch/parisc/kernel/firmware.c
++++ b/arch/parisc/kernel/firmware.c
+@@ -83,15 +83,15 @@ static unsigned long pdc_result2[32] __a
+ 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
+- *
+- * 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...
++/* 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.
++ *
++ * 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
+--- 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 at 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 @@ boot_args:
+ .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 @@ $bss_loop:
+ 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 @@ $bss_loop:
+ 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 @@ common_stext:
+ 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 @@ stext_pdc_ret:
+ mtctl %r0,%cr12
+ mtctl %r0,%cr13
+
+- /* Prepare to RFI! Man all the cannons! */
+-
+ /* Initialize the global data pointer */
+ loadgp
+
+@@ -235,7 +233,7 @@ stext_pdc_ret:
+ * 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 @@ stext_pdc_ret:
+
+ $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
+-
+-#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
++ pcxt_ssm_bug
+
+-$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
++ rsm PSW_SM_QUIET,%r0 /* off troublesome PSW bits */
++ /* Don't need NOPs, have 8 compliant insn before rfi */
+
+- /* 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 @@ $rfi:
+ 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 @@ $rfi:
+ .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 @@ smp_callin_rtn:
+ 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 @@ smp_slave_stext:
+ 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 @@ smp_slave_stext:
+
+ .procend
+ #endif /* CONFIG_SMP */
+-#ifndef __LP64__
++#ifndef CONFIG_64BIT
+ .data
+
+ .align 4
+@@ -383,4 +354,4 @@ smp_slave_stext:
+ .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
+--- a/arch/parisc/kernel/ioctl32.c
++++ b/arch/parisc/kernel/ioctl32.c
+@@ -104,12 +104,9 @@ static int drm32_version(unsigned int fd
+ }
+
+ 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 @@ static int drm32_getsetunique(unsigned i
+ ret = -EFAULT;
+ }
+
+- if (karg.unique != NULL)
+- kfree(karg.unique);
+-
++ kfree(karg.unique);
+ return ret;
+ }
+
+@@ -265,7 +260,6 @@ static int drm32_info_bufs(unsigned int
+ }
+
+ kfree(karg.list);
+-
+ return ret;
+ }
+
+@@ -305,7 +299,6 @@ static int drm32_free_bufs(unsigned int
+
+ out:
+ kfree(karg.list);
+-
+ return ret;
+ }
+
+@@ -494,15 +487,10 @@ static int drm32_dma(unsigned int fd, un
+ }
+
+ 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 @@ static int drm32_res_ctx(unsigned int fd
+ ret = -EFAULT;
+ }
+
+- if (karg.contexts)
+- kfree(karg.contexts);
+-
++ kfree(karg.contexts);
+ return ret;
+ }
+
+@@ -575,11 +561,6 @@ IOCTL_TABLE_START
+ #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
+--- 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 @@ flush_tlb_all_local:
+ * 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.
+- */
+-
+- rsm PSW_SM_I, %r19 /* relied upon translation! PA 2.0 Arch. F-5 */
++ /* 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
+- 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 @@ fdtonemiddle: /* Loop if LOOP = 1 */
+ ADDIB> -1, %r22, fdtoneloop /* Outer loop count decr */
+ add %r21, %r20, %r20 /* increment space */
+
+-fdtdone:
+
+- /* Switch back to virtual mode */
++fdtdone:
++ /*
++ * Switch back to virtual mode
++ */
++ /* pcxt_ssm_bug */
++ rsm PSW_SM_I, %r0
++ 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
+- 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 @@ flush_instruction_cache_local:
+
+ 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 @@ fioneloop: /* Loop if LOOP = 1 */
+
+ fisync:
+ sync
+- mtsm %r22
++ mtsm %r22 /* restore I-bit */
+ bv %r0(%r2)
+ nop
+ .exit
+@@ -269,7 +269,7 @@ flush_data_cache_local:
+
+ 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 @@ fdoneloop: /* Loop if LOOP = 1 */
+ fdsync:
+ syncdma
+ sync
+- mtsm %r22
++ mtsm %r22 /* restore I-bit */
+ bv %r0(%r2)
+ nop
+ .exit
+@@ -296,7 +296,7 @@ copy_user_page_asm:
+ .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 @@ copy_user_page_asm:
+ 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 @@ copy_user_page_asm:
+ * 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 @@ copy_user_page_asm:
+ 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 @@ copy_user_page_asm:
+ 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 @@ __clear_user_page_asm:
+ 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 @@ __clear_user_page_asm:
+
+ 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 @@ __clear_user_page_asm:
+ ADDIB> -1, %r1, 1b
+ ldo 128(%r28), %r28
+
+-#else /* ! __LP64 */
++#else /* ! CONFIG_64BIT */
+
+ ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
+
+@@ -608,7 +613,7 @@ __clear_user_page_asm:
+ 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 @@ flush_kernel_dcache_page:
+ 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 @@ flush_user_dcache_page:
+ 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 @@ flush_user_icache_page:
+ 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 @@ purge_kernel_dcache_page:
+ 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 @@ flush_alias_page:
+ 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 @@ flush_alias_page:
+ 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 @@ flush_kernel_icache_page:
+ 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 @@ flush_kernel_icache_page:
+ 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 @@ flush_kernel_icache_range_asm:
+ 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 @@ disable_sr_hashing_asm:
+ .callinfo NO_CALLS
+ .entry
+
+- /* Switch to real mode */
+-
+- ssm 0, %r0 /* relied upon translation! */
+- nop
+- nop
++ /*
++ * Switch to real mode
++ */
++ /* pcxt_ssm_bug */
++ rsm PSW_SM_I, %r0
++ load32 PA(1f), %r1
+ 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_pcxl:
+
+ 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:
+
++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
+--- 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 @@ static inline int map_pmd_uncached(pmd_t
+ 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 @@ pcxl_free_range(unsigned long vaddr, siz
+ 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 @@ struct hppa_dma_ops pcxl_dma_ops = {
+ };
+
+ 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 @@ struct hppa_dma_ops pcx_dma_ops = {
+
+ 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 @@ static int pcxl_proc_info(char *buf, cha
+ 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 @@ static int pcxl_proc_info(char *buf, cha
+ 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
+--- a/arch/parisc/kernel/pci.c
++++ b/arch/parisc/kernel/pci.c
+@@ -202,7 +202,8 @@ static void
+ 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
+--- 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 @@ static int pdc_console_setup(struct cons
+ }
+
+ #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 @@ static struct tty_driver * pdc_console_d
+ 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 @@ void __init pdc_console_init(void)
+ }
+
+
+-/* 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 @@ void pdc_console_restart(void)
+ 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
+--- a/arch/parisc/kernel/perf.c
++++ b/arch/parisc/kernel/perf.c
+@@ -746,7 +746,8 @@ static int perf_write_image(uint64_t *me
+ 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 @@ static int perf_write_image(uint64_t *me
+ 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
+--- 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 @@ int
+ 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 @@ sys_clone(unsigned long clone_flags, uns
+ 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 @@ copy_thread(int nr, unsigned long clone_
+ } 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
+--- a/arch/parisc/kernel/processor.c
++++ b/arch/parisc/kernel/processor.c
+@@ -92,7 +92,7 @@ static int __init processor_probe(struct
+ * 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 @@ static int __init processor_probe(struct
+ * 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 @@ static int __init processor_probe(struct
+ 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 @@ static int __init processor_probe(struct
+
+ 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
+--- a/arch/parisc/kernel/ptrace.c
++++ b/arch/parisc/kernel/ptrace.c
+@@ -78,7 +78,7 @@ void ptrace_disable(struct task_struct *
+ 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
+--- a/arch/parisc/kernel/real2.S
++++ b/arch/parisc/kernel/real2.S
+@@ -7,8 +7,10 @@
+ * Copyright (C) 2000 Hewlett Packard (Paul Bame bame at 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 @@ real32_stack:
+ real64_stack:
+ .block 8192
+
+-#ifdef __LP64__
++#ifdef CONFIG_64BIT
+ # define REG_SZ 8
+ #else
+ # define REG_SZ 4
+@@ -50,7 +52,7 @@ save_cr_end:
+
+ 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 @@ real32_call_asm:
+ 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 @@ real32_call_asm:
+ 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 @@ ric_ret:
+
+ 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 @@ restore_control_regs:
+ /* 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 @@ rfi_v2r_1:
+ .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 @@ rfi_real2virt:
+ 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 @@ rfi_r2v_1:
+ 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 @@ pc_in_user_space:
+ ** 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
+--- a/arch/parisc/kernel/signal.c
++++ b/arch/parisc/kernel/signal.c
+@@ -490,15 +490,7 @@ setup_rt_frame(int sig, struct k_sigacti
+
+ 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 @@ do_signal(sigset_t *oldset, struct pt_re
+ 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
+--- 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
+--- 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 @@ linux_gateway_entry:
+ 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 @@ linux_gateway_entry:
+ 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 @@ linux_gateway_entry:
+
+ 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 @@ linux_gateway_entry:
+ /* 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 @@ tracesys_next:
+ 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_next:
+ 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_exit:
+ 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 @@ lws_start:
+ 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 @@ lws_exit_nosys:
+ /* 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 @@ lws_exit:
+
+ /* 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 @@ lws_compare_and_swap64:
+
+ /* 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 @@ cas_action:
+ 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 @@ cas_action:
+ .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 @@ end_linux_gateway_page:
+
+ /* 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 @@ lws_table:
+ 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
+--- 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
+--- 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 @@ irqreturn_t timer_interrupt(int irq, voi
+ }
+ }
+
+-#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 @@ irqreturn_t timer_interrupt(int irq, voi
+ 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
+--- a/arch/parisc/kernel/traps.c
++++ b/arch/parisc/kernel/traps.c
+@@ -74,7 +74,10 @@ void show_regs(struct pt_regs *regs)
+ 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 @@ void show_regs(struct pt_regs *regs)
+ 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
+--- a/arch/parisc/kernel/unaligned.c
++++ b/arch/parisc/kernel/unaligned.c
+@@ -513,15 +513,18 @@ void handle_unaligned(struct pt_regs *re
+ 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 @@ void handle_unaligned(struct pt_regs *re
+ show_regs(regs);
+ #endif
+ }
++
+ if (!unaligned_enabled)
+ goto force_sigbus;
+ }
+diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S
+--- 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
+--- a/arch/parisc/lib/memcpy.c
++++ b/arch/parisc/lib/memcpy.c
+@@ -339,6 +339,7 @@ unsigned long pa_memcpy(void *dstp, cons
+ 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 @@ unsigned long pa_memcpy(void *dstp, cons
+ 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
+--- a/arch/parisc/mm/init.c
++++ b/arch/parisc/mm/init.c
+@@ -505,7 +505,9 @@ void show_mem(void)
+
+ 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 @@ void show_mem(void)
+ 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
+--- a/arch/parisc/mm/ioremap.c
++++ b/arch/parisc/mm/ioremap.c
+@@ -52,7 +52,7 @@ static inline int remap_area_pmd(pmd_t *
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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/Kconfig b/arch/powerpc/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/Kconfig
+@@ -0,0 +1,900 @@
++# For a description of the syntax of this configuration file,
++# see Documentation/kbuild/kconfig-language.txt.
++#
++
++mainmenu "Linux/PowerPC Kernel Configuration"
++
++config PPC64
++ bool "64-bit kernel"
++ default n
++ help
++ This option selects whether a 32-bit or a 64-bit kernel
++ will be built.
++
++config PPC32
++ bool
++ default y if !PPC64
++
++config 64BIT
++ bool
++ default y if PPC64
++
++config PPC_MERGE
++ def_bool y
++
++config MMU
++ bool
++ default y
++
++config UID16
++ bool
++
++config GENERIC_HARDIRQS
++ bool
++ default y
++
++config RWSEM_GENERIC_SPINLOCK
++ bool
++
++config RWSEM_XCHGADD_ALGORITHM
++ bool
++ default y
++
++config GENERIC_CALIBRATE_DELAY
++ bool
++ default y
++
++config PPC
++ bool
++ default y
++
++config EARLY_PRINTK
++ bool
++ default y if PPC64
++
++config COMPAT
++ bool
++ default y if PPC64
++
++config SYSVIPC_COMPAT
++ bool
++ depends on COMPAT && SYSVIPC
++ default y
++
++# All PPC32s use generic nvram driver through ppc_md
++config GENERIC_NVRAM
++ bool
++ default y if PPC32
++
++config SCHED_NO_NO_OMIT_FRAME_POINTER
++ bool
++ default y
++
++config ARCH_MAY_HAVE_PC_FDC
++ bool
++ default y
++
++menu "Processor support"
++choice
++ prompt "Processor Type"
++ depends on PPC32
++ default 6xx
++
++config 6xx
++ bool "6xx/7xx/74xx"
++ select PPC_FPU
++ help
++ There are four families of PowerPC chips supported. The more common
++ types (601, 603, 604, 740, 750, 7400), the Motorola embedded
++ versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
++ embedded versions (403 and 405) and the high end 64 bit Power
++ processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
++
++ Unless you are building a kernel for one of the embedded processor
++ systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
++ Note that the kernel runs in 32-bit mode even on 64-bit chips.
++
++config PPC_52xx
++ bool "Freescale 52xx"
++
++config PPC_82xx
++ bool "Freescale 82xx"
++
++config PPC_83xx
++ bool "Freescale 83xx"
++
++config 40x
++ bool "AMCC 40x"
++
++config 44x
++ bool "AMCC 44x"
++
++config 8xx
++ bool "Freescale 8xx"
++
++config E200
++ bool "Freescale e200"
++
++config E500
++ bool "Freescale e500"
++endchoice
++
++config POWER4_ONLY
++ bool "Optimize for POWER4"
++ depends on PPC64
++ default n
++ ---help---
++ Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
++ The resulting binary will not work on POWER3 or RS64 processors
++ when compiled with binutils 2.15 or later.
++
++config POWER3
++ bool
++ depends on PPC64
++ default y if !POWER4_ONLY
++
++config POWER4
++ depends on PPC64
++ def_bool y
++
++config PPC_FPU
++ bool
++ default y if PPC64
++
++config BOOKE
++ bool
++ depends on E200 || E500
++ default y
++
++config FSL_BOOKE
++ bool
++ depends on E200 || E500
++ default y
++
++config PTE_64BIT
++ bool
++ depends on 44x || E500
++ default y if 44x
++ default y if E500 && PHYS_64BIT
++
++config PHYS_64BIT
++ bool 'Large physical address support' if E500
++ depends on 44x || E500
++ default y if 44x
++ ---help---
++ This option enables kernel support for larger than 32-bit physical
++ addresses. This features is not be available on all e500 cores.
++
++ If in doubt, say N here.
++
++config ALTIVEC
++ bool "AltiVec Support"
++ depends on 6xx || POWER4
++ ---help---
++ This option enables kernel support for the Altivec extensions to the
++ PowerPC processor. The kernel currently supports saving and restoring
++ altivec registers, and turning on the 'altivec enable' bit so user
++ processes can execute altivec instructions.
++
++ This option is only usefully if you have a processor that supports
++ altivec (G4, otherwise known as 74xx series), but does not have
++ any affect on a non-altivec cpu (it does, however add code to the
++ kernel).
++
++ If in doubt, say Y here.
++
++config SPE
++ bool "SPE Support"
++ depends on E200 || E500
++ ---help---
++ This option enables kernel support for the Signal Processing
++ Extensions (SPE) to the PowerPC processor. The kernel currently
++ supports saving and restoring SPE registers, and turning on the
++ 'spe enable' bit so user processes can execute SPE instructions.
++
++ This option is only useful if you have a processor that supports
++ SPE (e500, otherwise known as 85xx series), but does not have any
++ effect on a non-spe cpu (it does, however add code to the kernel).
++
++ If in doubt, say Y here.
++
++config PPC_STD_MMU
++ bool
++ depends on 6xx || POWER3 || POWER4 || PPC64
++ default y
++
++config PPC_STD_MMU_32
++ def_bool y
++ depends on PPC_STD_MMU && PPC32
++
++config SMP
++ depends on PPC_STD_MMU
++ bool "Symmetric multi-processing support"
++ ---help---
++ This enables support for systems with more than one CPU. If you have
++ a system with only one CPU, say N. If you have a system with more
++ than one CPU, say Y. Note that the kernel does not currently
++ support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
++ since they have inadequate hardware support for multiprocessor
++ operation.
++
++ If you say N here, the kernel will run on single and multiprocessor
++ machines, but will use only one CPU of a multiprocessor machine. If
++ you say Y here, the kernel will run on single-processor machines.
++ On a single-processor machine, the kernel will run faster if you say
++ N here.
++
++ If you don't know what to do here, say N.
++
++config NR_CPUS
++ int "Maximum number of CPUs (2-32)"
++ range 2 128
++ depends on SMP
++ default "32" if PPC64
++ default "4"
++
++config NOT_COHERENT_CACHE
++ bool
++ depends on 4xx || 8xx || E200
++ default y
++endmenu
++
++source "init/Kconfig"
++
++menu "Platform support"
++ depends on PPC64 || 6xx
++
++choice
++ prompt "Machine type"
++ default PPC_MULTIPLATFORM
++
++config PPC_MULTIPLATFORM
++ bool "Generic desktop/server/laptop"
++ help
++ Select this option if configuring for an IBM pSeries or
++ RS/6000 machine, an Apple machine, or a PReP, CHRP,
++ Maple or Cell-based machine.
++
++config PPC_ISERIES
++ bool "IBM Legacy iSeries"
++ depends on PPC64
++
++config EMBEDDED6xx
++ bool "Embedded 6xx/7xx/7xxx-based board"
++ depends on PPC32
++
++config APUS
++ bool "Amiga-APUS"
++ depends on PPC32 && BROKEN
++ help
++ Select APUS if configuring for a PowerUP Amiga.
++ More information is available at:
++ <http://linux-apus.sourceforge.net/>.
++endchoice
++
++config PPC_PSERIES
++ depends on PPC_MULTIPLATFORM && PPC64
++ bool " IBM pSeries & new (POWER5-based) iSeries"
++ select PPC_I8259
++ select PPC_RTAS
++ select RTAS_ERROR_LOGGING
++ default y
++
++config PPC_CHRP
++ bool " Common Hardware Reference Platform (CHRP) based machines"
++ depends on PPC_MULTIPLATFORM && PPC32
++ select PPC_I8259
++ select PPC_INDIRECT_PCI
++ select PPC_RTAS
++ select PPC_MPC106
++ default y
++
++config PPC_PMAC
++ bool " Apple PowerMac based machines"
++ depends on PPC_MULTIPLATFORM
++ select PPC_INDIRECT_PCI if PPC32
++ select PPC_MPC106 if PPC32
++ default y
++
++config PPC_PMAC64
++ bool
++ depends on PPC_PMAC && POWER4
++ select U3_DART
++ default y
++
++config PPC_PREP
++ bool " PowerPC Reference Platform (PReP) based machines"
++ depends on PPC_MULTIPLATFORM && PPC32
++ select PPC_I8259
++ select PPC_INDIRECT_PCI
++ default y
++
++config PPC_MAPLE
++ depends on PPC_MULTIPLATFORM && PPC64
++ bool " Maple 970FX Evaluation Board"
++ select U3_DART
++ select MPIC_BROKEN_U3
++ default n
++ help
++ This option enables support for the Maple 970FX Evaluation Board.
++ For more informations, refer to <http://www.970eval.com>
++
++config PPC_BPA
++ bool " Broadband Processor Architecture"
++ depends on PPC_MULTIPLATFORM && PPC64
++ select PPC_RTAS
++
++config PPC_OF
++ bool
++ depends on PPC_MULTIPLATFORM # for now
++ default y
++
++config XICS
++ depends on PPC_PSERIES
++ bool
++ default y
++
++config U3_DART
++ bool
++ depends on PPC_MULTIPLATFORM && PPC64
++ default n
++
++config MPIC
++ depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP
++ bool
++ default y
++
++config PPC_RTAS
++ bool
++ default n
++
++config RTAS_ERROR_LOGGING
++ bool
++ depends on PPC_RTAS
++ default n
++
++config MPIC_BROKEN_U3
++ bool
++ depends on PPC_MAPLE
++ default y
++
++config BPA_IIC
++ depends on PPC_BPA
++ bool
++ default y
++
++config IBMVIO
++ depends on PPC_PSERIES || PPC_ISERIES
++ bool
++ default y
++
++config PPC_MPC106
++ bool
++ default n
++
++source "drivers/cpufreq/Kconfig"
++
++config CPU_FREQ_PMAC
++ bool "Support for Apple PowerBooks"
++ depends on CPU_FREQ && ADB_PMU && PPC32
++ select CPU_FREQ_TABLE
++ help
++ This adds support for frequency switching on Apple PowerBooks,
++ this currently includes some models of iBook & Titanium
++ PowerBook.
++
++config PPC601_SYNC_FIX
++ bool "Workarounds for PPC601 bugs"
++ depends on 6xx && (PPC_PREP || PPC_PMAC)
++ help
++ Some versions of the PPC601 (the first PowerPC chip) have bugs which
++ mean that extra synchronization instructions are required near
++ certain instructions, typically those that make major changes to the
++ CPU state. These extra instructions reduce performance slightly.
++ If you say N here, these extra instructions will not be included,
++ resulting in a kernel which will run faster but may not run at all
++ on some systems with the PPC601 chip.
++
++ If in doubt, say Y here.
++
++config TAU
++ bool "Thermal Management Support"
++ depends on 6xx
++ help
++ G3 and G4 processors have an on-chip temperature sensor called the
++ 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
++ temperature within 2-4 degrees Celsius. This option shows the current
++ on-die temperature in /proc/cpuinfo if the cpu supports it.
++
++ Unfortunately, on some chip revisions, this sensor is very inaccurate
++ and in some cases, does not work at all, so don't assume the cpu
++ temp is actually what /proc/cpuinfo says it is.
++
++config TAU_INT
++ bool "Interrupt driven TAU driver (DANGEROUS)"
++ depends on TAU
++ ---help---
++ The TAU supports an interrupt driven mode which causes an interrupt
++ whenever the temperature goes out of range. This is the fastest way
++ to get notified the temp has exceeded a range. With this option off,
++ a timer is used to re-check the temperature periodically.
++
++ However, on some cpus it appears that the TAU interrupt hardware
++ is buggy and can cause a situation which would lead unexplained hard
++ lockups.
++
++ Unless you are extending the TAU driver, or enjoy kernel/hardware
++ debugging, leave this option off.
++
++config TAU_AVERAGE
++ bool "Average high and low temp"
++ depends on TAU
++ ---help---
++ The TAU hardware can compare the temperature to an upper and lower
++ bound. The default behavior is to show both the upper and lower
++ bound in /proc/cpuinfo. If the range is large, the temperature is
++ either changing a lot, or the TAU hardware is broken (likely on some
++ G4's). If the range is small (around 4 degrees), the temperature is
++ relatively stable. If you say Y here, a single temperature value,
++ halfway between the upper and lower bounds, will be reported in
++ /proc/cpuinfo.
++
++ If in doubt, say N here.
++endmenu
++
++source arch/powerpc/platforms/embedded6xx/Kconfig
++source arch/powerpc/platforms/4xx/Kconfig
++source arch/powerpc/platforms/85xx/Kconfig
++source arch/powerpc/platforms/8xx/Kconfig
++
++menu "Kernel options"
++
++config HIGHMEM
++ bool "High memory support"
++ depends on PPC32
++
++source kernel/Kconfig.hz
++source kernel/Kconfig.preempt
++source "fs/Kconfig.binfmt"
++
++# We optimistically allocate largepages from the VM, so make the limit
++# large enough (16MB). This badly named config option is actually
++# max order + 1
++config FORCE_MAX_ZONEORDER
++ int
++ depends on PPC64
++ default "13"
++
++config MATH_EMULATION
++ bool "Math emulation"
++ depends on 4xx || 8xx || E200 || E500
++ ---help---
++ Some PowerPC chips designed for embedded applications do not have
++ a floating-point unit and therefore do not implement the
++ floating-point instructions in the PowerPC instruction set. If you
++ say Y here, the kernel will include code to emulate a floating-point
++ unit, which will allow programs that use floating-point
++ instructions to run.
++
++config IOMMU_VMERGE
++ bool "Enable IOMMU virtual merging (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && PPC64
++ default n
++ help
++ Cause IO segments sent to a device for DMA to be merged virtually
++ by the IOMMU when they happen to have been allocated contiguously.
++ This doesn't add pressure to the IOMMU allocator. However, some
++ drivers don't support getting large merged segments coming back
++ from *_map_sg(). Say Y if you know the drivers you are using are
++ properly handling this case.
++
++config HOTPLUG_CPU
++ bool "Support for enabling/disabling CPUs"
++ depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
++ ---help---
++ Say Y here to be able to disable and re-enable individual
++ CPUs at runtime on SMP machines.
++
++ Say N if you are unsure.
++
++config KEXEC
++ bool "kexec system call (EXPERIMENTAL)"
++ depends on PPC_MULTIPLATFORM && EXPERIMENTAL
++ help
++ kexec is a system call that implements the ability to shutdown your
++ current kernel, and to start another kernel. It is like a reboot
++ but it is indepedent of the system firmware. And like a reboot
++ you can start any kernel with it, not just Linux.
++
++ The name comes from the similiarity to the exec system call.
++
++ It is an ongoing process to be certain the hardware in a machine
++ is properly shutdown, so do not be surprised if this code does not
++ initially work for you. It may help to enable device hotplugging
++ support. As of this writing the exact hardware interface is
++ strongly in flux, so no good recommendation can be made.
++
++config EMBEDDEDBOOT
++ bool
++ depends on 8xx || 8260
++ default y
++
++config PC_KEYBOARD
++ bool "PC PS/2 style Keyboard"
++ depends on 4xx || CPM2
++
++config PPCBUG_NVRAM
++ bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
++ default y if PPC_PREP
++
++config IRQ_ALL_CPUS
++ bool "Distribute interrupts on all CPUs by default"
++ depends on SMP && !MV64360
++ help
++ This option gives the kernel permission to distribute IRQs across
++ multiple CPUs. Saying N here will route all IRQs to the first
++ CPU. Generally saying Y is safe, although some problems have been
++ reported with SMP Power Macintoshes with this option enabled.
++
++source "arch/powerpc/platforms/pseries/Kconfig"
++
++config NUMA
++ bool "NUMA support"
++ depends on PPC64
++ default y if SMP && PPC_PSERIES
++
++config ARCH_SELECT_MEMORY_MODEL
++ def_bool y
++ depends on PPC64
++
++config ARCH_FLATMEM_ENABLE
++ def_bool y
++ depends on PPC64 && !NUMA
++
++config ARCH_DISCONTIGMEM_ENABLE
++ def_bool y
++ depends on SMP && PPC_PSERIES
++
++config ARCH_DISCONTIGMEM_DEFAULT
++ def_bool y
++ depends on ARCH_DISCONTIGMEM_ENABLE
++
++config ARCH_SPARSEMEM_ENABLE
++ def_bool y
++ depends on ARCH_DISCONTIGMEM_ENABLE
++
++source "mm/Kconfig"
++
++config HAVE_ARCH_EARLY_PFN_TO_NID
++ def_bool y
++ depends on NEED_MULTIPLE_NODES
++
++# Some NUMA nodes have memory ranges that span
++# other nodes. Even though a pfn is valid and
++# between a node's start and end pfns, it may not
++# reside on that node.
++#
++# This is a relatively temporary hack that should
++# be able to go away when sparsemem is fully in
++# place
++
++config NODES_SPAN_OTHER_NODES
++ def_bool y
++ depends on NEED_MULTIPLE_NODES
++
++config SCHED_SMT
++ bool "SMT (Hyperthreading) scheduler support"
++ depends on PPC64 && SMP
++ default off
++ help
++ SMT scheduler support improves the CPU scheduler's decision making
++ when dealing with POWER5 cpus at a cost of slightly increased
++ overhead in some places. If unsure say N here.
++
++config PROC_DEVICETREE
++ bool "Support for device tree in /proc"
++ depends on PROC_FS
++ help
++ This option adds a device-tree directory under /proc which contains
++ an image of the device tree that the kernel copies from Open
++ Firmware or other boot firmware. If unsure, say Y here.
++
++source "arch/powerpc/platforms/prep/Kconfig"
++
++config CMDLINE_BOOL
++ bool "Default bootloader kernel arguments"
++ depends on !PPC_ISERIES
++
++config CMDLINE
++ string "Initial kernel command string"
++ depends on CMDLINE_BOOL
++ default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
++ help
++ On some platforms, there is currently no way for the boot loader to
++ pass arguments to the kernel. For these platforms, you can supply
++ some command-line options at build time by entering them here. In
++ most cases you will need to specify the root device here.
++
++if !44x || BROKEN
++source kernel/power/Kconfig
++endif
++
++config SECCOMP
++ bool "Enable seccomp to safely compute untrusted bytecode"
++ depends on PROC_FS
++ default y
++ help
++ This kernel feature is useful for number crunching applications
++ that may need to compute untrusted bytecode during their
++ 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.
++
++endmenu
++
++config ISA_DMA_API
++ bool
++ default y
++
++menu "Bus options"
++
++config ISA
++ bool "Support for ISA-bus hardware"
++ depends on PPC_PREP || PPC_CHRP
++ select PPC_I8259
++ help
++ Find out whether you have ISA slots on your motherboard. ISA is the
++ name of a bus system, i.e. the way the CPU talks to the other stuff
++ inside your box. If you have an Apple machine, say N here; if you
++ have an IBM RS/6000 or pSeries machine or a PReP machine, say Y. If
++ you have an embedded board, consult your board documentation.
++
++config GENERIC_ISA_DMA
++ bool
++ depends on PPC64 || POWER4 || 6xx && !CPM2
++ default y
++
++config PPC_I8259
++ bool
++ default y if 85xx
++ default n
++
++config PPC_INDIRECT_PCI
++ bool
++ depends on PCI
++ default y if 40x || 44x || 85xx || 83xx
++ default n
++
++config EISA
++ bool
++
++config SBUS
++ bool
++
++# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
++config MCA
++ bool
++
++config PCI
++ bool "PCI support" if 40x || CPM2 || 83xx || 85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
++ default y if !40x && !CPM2 && !8xx && !APUS && !83xx && !85xx
++ default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
++ default PCI_QSPAN if !4xx && !CPM2 && 8xx
++ help
++ Find out whether your system includes a PCI bus. PCI is the name of
++ a bus system, i.e. the way the CPU talks to the other stuff inside
++ your box. If you say Y here, the kernel will include drivers and
++ infrastructure code to support PCI bus devices.
++
++config PCI_DOMAINS
++ bool
++ default PCI
++
++config MPC83xx_PCI2
++ bool " Supprt for 2nd PCI host controller"
++ depends on PCI && MPC834x
++ default y if MPC834x_SYS
++
++config PCI_QSPAN
++ bool "QSpan PCI"
++ depends on !4xx && !CPM2 && 8xx
++ select PPC_I8259
++ help
++ Say Y here if you have a system based on a Motorola 8xx-series
++ embedded processor with a QSPAN PCI interface, otherwise say N.
++
++config PCI_8260
++ bool
++ depends on PCI && 8260
++ select PPC_INDIRECT_PCI
++ default y
++
++config 8260_PCI9
++ bool " Enable workaround for MPC826x erratum PCI 9"
++ depends on PCI_8260 && !ADS8272
++ default y
++
++choice
++ prompt " IDMA channel for PCI 9 workaround"
++ depends on 8260_PCI9
++
++config 8260_PCI9_IDMA1
++ bool "IDMA1"
++
++config 8260_PCI9_IDMA2
++ bool "IDMA2"
++
++config 8260_PCI9_IDMA3
++ bool "IDMA3"
++
++config 8260_PCI9_IDMA4
++ bool "IDMA4"
++
++endchoice
++
++source "drivers/pci/Kconfig"
++
++source "drivers/pcmcia/Kconfig"
++
++source "drivers/pci/hotplug/Kconfig"
++
++endmenu
++
++menu "Advanced setup"
++ depends on PPC32
++
++config ADVANCED_OPTIONS
++ bool "Prompt for advanced kernel configuration options"
++ help
++ This option will enable prompting for a variety of advanced kernel
++ configuration options. These options can cause the kernel to not
++ work if they are set incorrectly, but can be used to optimize certain
++ aspects of kernel memory management.
++
++ Unless you know what you are doing, say N here.
++
++comment "Default settings for advanced configuration options are used"
++ depends on !ADVANCED_OPTIONS
++
++config HIGHMEM_START_BOOL
++ bool "Set high memory pool address"
++ depends on ADVANCED_OPTIONS && HIGHMEM
++ help
++ This option allows you to set the base address of the kernel virtual
++ area used to map high memory pages. This can be useful in
++ optimizing the layout of kernel virtual memory.
++
++ Say N here unless you know what you are doing.
++
++config HIGHMEM_START
++ hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
++ default "0xfe000000"
++
++config LOWMEM_SIZE_BOOL
++ bool "Set maximum low memory"
++ depends on ADVANCED_OPTIONS
++ help
++ This option allows you to set the maximum amount of memory which
++ will be used as "low memory", that is, memory which the kernel can
++ access directly, without having to set up a kernel virtual mapping.
++ This can be useful in optimizing the layout of kernel virtual
++ memory.
++
++ Say N here unless you know what you are doing.
++
++config LOWMEM_SIZE
++ hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
++ default "0x30000000"
++
++config KERNEL_START_BOOL
++ bool "Set custom kernel base address"
++ depends on ADVANCED_OPTIONS
++ help
++ This option allows you to set the kernel virtual address at which
++ the kernel will map low memory (the kernel image will be linked at
++ this address). This can be useful in optimizing the virtual memory
++ layout of the system.
++
++ Say N here unless you know what you are doing.
++
++config KERNEL_START
++ hex "Virtual address of kernel base" if KERNEL_START_BOOL
++ default "0xc0000000"
++
++config TASK_SIZE_BOOL
++ bool "Set custom user task size"
++ depends on ADVANCED_OPTIONS
++ help
++ This option allows you to set the amount of virtual address space
++ allocated to user tasks. This can be useful in optimizing the
++ virtual memory layout of the system.
++
++ Say N here unless you know what you are doing.
++
++config TASK_SIZE
++ hex "Size of user task space" if TASK_SIZE_BOOL
++ default "0x80000000"
++
++config CONSISTENT_START_BOOL
++ bool "Set custom consistent memory pool address"
++ depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
++ help
++ This option allows you to set the base virtual address
++ of the the consistent memory pool. This pool of virtual
++ memory is used to make consistent memory allocations.
++
++config CONSISTENT_START
++ hex "Base virtual address of consistent memory pool" if CONSISTENT_START_BOOL
++ default "0xff100000" if NOT_COHERENT_CACHE
++
++config CONSISTENT_SIZE_BOOL
++ bool "Set custom consistent memory pool size"
++ depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
++ help
++ This option allows you to set the size of the the
++ consistent memory pool. This pool of virtual memory
++ is used to make consistent memory allocations.
++
++config CONSISTENT_SIZE
++ hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
++ default "0x00200000" if NOT_COHERENT_CACHE
++
++config BOOT_LOAD_BOOL
++ bool "Set the boot link/load address"
++ depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
++ help
++ This option allows you to set the initial load address of the zImage
++ or zImage.initrd file. This can be useful if you are on a board
++ which has a small amount of memory.
++
++ Say N here unless you know what you are doing.
++
++config BOOT_LOAD
++ hex "Link/load address for booting" if BOOT_LOAD_BOOL
++ default "0x00400000" if 40x || 8xx || 8260
++ default "0x01000000" if 44x
++ default "0x00800000"
++
++config PIN_TLB
++ bool "Pinned Kernel TLBs (860 ONLY)"
++ depends on ADVANCED_OPTIONS && 8xx
++endmenu
++
++if PPC64
++config KERNEL_START
++ hex
++ default "0xc000000000000000"
++endif
++
++source "net/Kconfig"
++
++source "drivers/Kconfig"
++
++source "fs/Kconfig"
++
++# XXX source "arch/ppc/8xx_io/Kconfig"
++
++# XXX source "arch/ppc/8260_io/Kconfig"
++
++source "arch/powerpc/platforms/iseries/Kconfig"
++
++source "lib/Kconfig"
++
++source "arch/powerpc/oprofile/Kconfig"
++
++source "arch/powerpc/Kconfig.debug"
++
++source "security/Kconfig"
++
++config KEYS_COMPAT
++ bool
++ depends on COMPAT && KEYS
++ default y
++
++source "crypto/Kconfig"
+diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/Kconfig.debug
+@@ -0,0 +1,128 @@
++menu "Kernel hacking"
++
++source "lib/Kconfig.debug"
++
++config DEBUG_STACKOVERFLOW
++ bool "Check for stack overflows"
++ depends on DEBUG_KERNEL && PPC64
++ help
++ This option will cause messages to be printed if free stack space
++ drops below a certain limit.
++
++config KPROBES
++ bool "Kprobes"
++ depends on DEBUG_KERNEL && PPC64
++ help
++ Kprobes allows you to trap at almost any kernel address and
++ execute a callback function. register_kprobe() establishes
++ a probepoint and specifies the callback. Kprobes is useful
++ for kernel debugging, non-intrusive instrumentation and testing.
++ If in doubt, say "N".
++
++config DEBUG_STACK_USAGE
++ bool "Stack utilization instrumentation"
++ depends on DEBUG_KERNEL && PPC64
++ help
++ Enables the display of the minimum amount of free stack which each
++ task has ever had available in the sysrq-T and sysrq-P debug output.
++
++ This option will slow down process creation somewhat.
++
++config DEBUGGER
++ bool "Enable debugger hooks"
++ depends on DEBUG_KERNEL
++ help
++ Include in-kernel hooks for kernel debuggers. Unless you are
++ intending to debug the kernel, say N here.
++
++config KGDB
++ bool "Include kgdb kernel debugger"
++ depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
++ select DEBUG_INFO
++ help
++ Include in-kernel hooks for kgdb, the Linux kernel source level
++ debugger. See <http://kgdb.sourceforge.net/> for more information.
++ Unless you are intending to debug the kernel, say N here.
++
++choice
++ prompt "Serial Port"
++ depends on KGDB
++ default KGDB_TTYS1
++
++config KGDB_TTYS0
++ bool "ttyS0"
++
++config KGDB_TTYS1
++ bool "ttyS1"
++
++config KGDB_TTYS2
++ bool "ttyS2"
++
++config KGDB_TTYS3
++ bool "ttyS3"
++
++endchoice
++
++config KGDB_CONSOLE
++ bool "Enable serial console thru kgdb port"
++ depends on KGDB && 8xx || CPM2
++ help
++ If you enable this, all serial console messages will be sent
++ over the gdb stub.
++ If unsure, say N.
++
++config XMON
++ bool "Include xmon kernel debugger"
++ depends on DEBUGGER && !PPC_ISERIES
++ help
++ Include in-kernel hooks for the xmon kernel monitor/debugger.
++ Unless you are intending to debug the kernel, say N here.
++ Make sure to enable also CONFIG_BOOTX_TEXT on Macs. Otherwise
++ nothing will appear on the screen (xmon writes directly to the
++ framebuffer memory).
++ The cmdline option 'xmon' or 'xmon=early' will drop into xmon
++ very early during boot. 'xmon=on' will just enable the xmon
++ debugger hooks. 'xmon=off' will disable the debugger hooks
++ if CONFIG_XMON_DEFAULT is set.
++
++config XMON_DEFAULT
++ bool "Enable xmon by default"
++ depends on XMON
++ help
++ xmon is normally disabled unless booted with 'xmon=on'.
++ Use 'xmon=off' to disable xmon init during runtime.
++
++config IRQSTACKS
++ bool "Use separate kernel stacks when processing interrupts"
++ depends on PPC64
++ help
++ If you say Y here the kernel will use separate kernel stacks
++ for handling hard and soft interrupts. This can help avoid
++ overflowing the process kernel stacks.
++
++config BDI_SWITCH
++ bool "Include BDI-2000 user context switcher"
++ depends on DEBUG_KERNEL && PPC32
++ help
++ Include in-kernel support for the Abatron BDI2000 debugger.
++ Unless you are intending to debug the kernel with one of these
++ machines, say N here.
++
++config BOOTX_TEXT
++ bool "Support for early boot text console (BootX or OpenFirmware only)"
++ depends PPC_OF && !PPC_ISERIES
++ help
++ Say Y here to see progress messages from the boot firmware in text
++ mode. Requires either BootX or Open Firmware.
++
++config SERIAL_TEXT_DEBUG
++ bool "Support for early boot texts over serial port"
++ depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
++ PPC_GEN550 || PPC_MPC52xx
++
++config PPC_OCP
++ bool
++ depends on IBM_OCP || XILINX_OCP
++ default y
++
++endmenu
+diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/Makefile
+@@ -0,0 +1,222 @@
++# This file is included by the global makefile so that you can add your own
++# architecture-specific flags and dependencies. Remember to do have actions
++# for "archclean" and "archdep" for cleaning up and making dependencies for
++# this architecture.
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 1994 by Linus Torvalds
++# Changes for PPC by Gary Thomas
++# Rewritten by Cort Dougan and Paul Mackerras
++#
++
++# This must match PAGE_OFFSET in include/asm-powerpc/page.h.
++KERNELLOAD := $(CONFIG_KERNEL_START)
++
++HAS_BIARCH := $(call cc-option-yn, -m32)
++
++ifeq ($(CONFIG_PPC64),y)
++OLDARCH := ppc64
++SZ := 64
++
++# Set default 32 bits cross compilers for vdso and boot wrapper
++CROSS32_COMPILE ?=
++
++CROSS32CC := $(CROSS32_COMPILE)gcc
++CROSS32AS := $(CROSS32_COMPILE)as
++CROSS32LD := $(CROSS32_COMPILE)ld
++CROSS32OBJCOPY := $(CROSS32_COMPILE)objcopy
++
++ifeq ($(HAS_BIARCH),y)
++ifeq ($(CROSS32_COMPILE),)
++CROSS32CC := $(CC) -m32
++CROSS32AS := $(AS) -a32
++CROSS32LD := $(LD) -m elf32ppc
++CROSS32OBJCOPY := $(OBJCOPY)
++endif
++endif
++
++export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
++
++new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
++
++ifeq ($(new_nm),y)
++NM := $(NM) --synthetic
++endif
++
++else
++OLDARCH := ppc
++SZ := 32
++endif
++
++UTS_MACHINE := $(OLDARCH)
++
++ifeq ($(HAS_BIARCH),y)
++override AS += -a$(SZ)
++override LD += -m elf$(SZ)ppc
++override CC += -m$(SZ)
++endif
++
++LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic -e $(KERNELLOAD)
++
++# The -Iarch/$(ARCH)/include is temporary while we are merging
++CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include
++AFLAGS += -Iarch/$(ARCH)
++CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe
++CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
++CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
++CFLAGS += $(CFLAGS-y)
++CPP = $(CC) -E $(CFLAGS)
++# Temporary hack until we have migrated to asm-powerpc
++LINUXINCLUDE += -Iarch/$(ARCH)/include
++
++CHECKFLAGS += -m$(SZ) -D__powerpc__ -D__powerpc$(SZ)__
++
++ifeq ($(CONFIG_PPC64),y)
++GCC_VERSION := $(call cc-version)
++GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi)
++
++ifeq ($(CONFIG_POWER4_ONLY),y)
++ifeq ($(CONFIG_ALTIVEC),y)
++ifeq ($(GCC_BROKEN_VEC),y)
++ CFLAGS += $(call cc-option,-mcpu=970)
++else
++ CFLAGS += $(call cc-option,-mcpu=power4)
++endif
++else
++ CFLAGS += $(call cc-option,-mcpu=power4)
++endif
++else
++ CFLAGS += $(call cc-option,-mtune=power4)
++endif
++endif
++
++# No AltiVec instruction when building kernel
++CFLAGS += $(call cc-option,-mno-altivec)
++
++# Enable unit-at-a-time mode when possible. It shrinks the
++# kernel considerably.
++CFLAGS += $(call cc-option,-funit-at-a-time)
++
++ifndef CONFIG_FSL_BOOKE
++CFLAGS += -mstring
++endif
++
++cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge
++cpu-as-$(CONFIG_4xx) += -Wa,-m405
++cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
++cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
++cpu-as-$(CONFIG_E500) += -Wa,-me500
++cpu-as-$(CONFIG_E200) += -Wa,-me200
++
++AFLAGS += $(cpu-as-y)
++CFLAGS += $(cpu-as-y)
++
++# Default to the common case.
++KBUILD_DEFCONFIG := common_defconfig
++
++head-y := arch/powerpc/kernel/head_32.o
++head-$(CONFIG_PPC64) := arch/powerpc/kernel/head_64.o
++head-$(CONFIG_8xx) := arch/powerpc/kernel/head_8xx.o
++head-$(CONFIG_4xx) := arch/powerpc/kernel/head_4xx.o
++head-$(CONFIG_44x) := arch/powerpc/kernel/head_44x.o
++head-$(CONFIG_FSL_BOOKE) := arch/powerpc/kernel/head_fsl_booke.o
++
++head-$(CONFIG_PPC64) += arch/powerpc/kernel/entry_64.o
++head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o
++
++core-y += arch/powerpc/kernel/ \
++ arch/$(OLDARCH)/kernel/ \
++ arch/powerpc/mm/ \
++ arch/powerpc/lib/ \
++ arch/powerpc/sysdev/ \
++ arch/powerpc/platforms/
++core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
++core-$(CONFIG_XMON) += arch/powerpc/xmon/
++core-$(CONFIG_APUS) += arch/ppc/amiga/
++drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
++drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/
++drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
++
++drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
++
++defaultimage-$(CONFIG_PPC32) := uImage zImage
++defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
++defaultimage-$(CONFIG_PPC_PSERIES) := zImage
++KBUILD_IMAGE := $(defaultimage-y)
++all: $(KBUILD_IMAGE)
++
++CPPFLAGS_vmlinux.lds := -Upowerpc
++
++# All the instructions talk about "make bzImage".
++bzImage: zImage
++
++BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
++
++.PHONY: $(BOOT_TARGETS)
++
++boot := arch/$(OLDARCH)/boot
++
++# urk
++ifeq ($(CONFIG_PPC64),y)
++$(BOOT_TARGETS): vmlinux
++ $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
++else
++$(BOOT_TARGETS): vmlinux
++ $(Q)$(MAKE) ARCH=ppc $(build)=$(boot) $@
++endif
++
++uImage: vmlinux
++ $(Q)$(MAKE) ARCH=$(OLDARCH) $(build)=$(boot)/images $(boot)/images/$@
++
++define archhelp
++ @echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/images/zImage.*)'
++ @echo ' uImage - Create a bootable image for U-Boot / PPCBoot'
++ @echo ' install - Install kernel using'
++ @echo ' (your) ~/bin/installkernel or'
++ @echo ' (distribution) /sbin/installkernel or'
++ @echo ' install to $$(INSTALL_PATH) and run lilo'
++ @echo ' *_defconfig - Select default config from arch/$(ARCH)/ppc/configs'
++endef
++
++archclean:
++ $(Q)$(MAKE) $(clean)=$(boot)
++ # Temporary hack until we have migrated to asm-powerpc
++ $(Q)rm -rf arch/$(ARCH)/include
++
++archprepare: checkbin
++
++# Temporary hack until we have migrated to asm-powerpc
++include/asm: arch/$(ARCH)/include/asm
++arch/$(ARCH)/include/asm:
++ $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi
++ $(Q)ln -fsn $(srctree)/include/asm-$(OLDARCH) arch/$(ARCH)/include/asm
++
++# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
++# to stdout and these checks are run even on install targets.
++TOUT := .tmp_gas_check
++# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
++# instructions.
++# gcc-3.4 and binutils-2.14 are a fatal combination.
++GCC_VERSION := $(call cc-version)
++
++checkbin:
++ @if test "$(GCC_VERSION)" = "0304" ; then \
++ if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
++ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
++ echo 'correctly with gcc-3.4 and your version of binutils.'; \
++ echo '*** Please upgrade your binutils or downgrade your gcc'; \
++ false; \
++ fi ; \
++ fi
++ @if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
++ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
++ echo 'correctly with old versions of binutils.' ; \
++ echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
++ false ; \
++ fi
++
++CLEAN_FILES += $(TOUT)
++
+diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/Makefile
+@@ -0,0 +1,56 @@
++#
++# Makefile for the linux kernel.
++#
++
++ifeq ($(CONFIG_PPC64),y)
++EXTRA_CFLAGS += -mno-minimal-toc
++endif
++ifeq ($(CONFIG_PPC32),y)
++CFLAGS_prom_init.o += -fPIC
++CFLAGS_btext.o += -fPIC
++endif
++
++obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
++ signal_32.o pmc.o
++obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
++ ptrace32.o systbl.o
++obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
++obj-$(CONFIG_POWER4) += idle_power4.o
++obj-$(CONFIG_PPC_OF) += of_device.o
++obj-$(CONFIG_PPC_RTAS) += rtas.o
++obj-$(CONFIG_IBMVIO) += vio.o
++
++ifeq ($(CONFIG_PPC_MERGE),y)
++
++extra-$(CONFIG_PPC_STD_MMU) := head_32.o
++extra-$(CONFIG_PPC64) := head_64.o
++extra-$(CONFIG_40x) := head_4xx.o
++extra-$(CONFIG_44x) := head_44x.o
++extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
++extra-$(CONFIG_8xx) := head_8xx.o
++extra-y += vmlinux.lds
++
++obj-y += process.o init_task.o time.o \
++ prom.o traps.o setup-common.o
++obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o
++obj-$(CONFIG_PPC64) += misc_64.o
++obj-$(CONFIG_PPC_OF) += prom_init.o
++obj-$(CONFIG_MODULES) += ppc_ksyms.o
++obj-$(CONFIG_BOOTX_TEXT) += btext.o
++obj-$(CONFIG_6xx) += idle_6xx.o
++
++ifeq ($(CONFIG_PPC_ISERIES),y)
++$(obj)/head_64.o: $(obj)/lparmap.s
++AFLAGS_head_64.o += -I$(obj)
++endif
++
++else
++# stuff used from here for ARCH=ppc or ARCH=ppc64
++obj-$(CONFIG_PPC64) += traps.o process.o init_task.o time.o \
++ setup-common.o
++
++
++endif
++
++extra-$(CONFIG_PPC_FPU) += fpu.o
++extra-$(CONFIG_PPC64) += entry_64.o
+diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/asm-offsets.c
+@@ -0,0 +1,273 @@
++/*
++ * This program is used to generate definitions needed by
++ * assembly language modules.
++ *
++ * We use the technique used in the OSF Mach kernel code:
++ * generate asm statements containing #defines,
++ * compile this file to assembler, and then extract the
++ * #defines from the assembly-language output.
++ *
++ * 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/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#ifdef CONFIG_PPC64
++#include <linux/time.h>
++#include <linux/hardirq.h>
++#else
++#include <linux/ptrace.h>
++#include <linux/suspend.h>
++#endif
++
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/rtas.h>
++#ifdef CONFIG_PPC64
++#include <asm/paca.h>
++#include <asm/lppaca.h>
++#include <asm/iSeries/HvLpEvent.h>
++#include <asm/cache.h>
++#include <asm/systemcfg.h>
++#include <asm/compat.h>
++#endif
++
++#define DEFINE(sym, val) \
++ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
++
++#define BLANK() asm volatile("\n->" : : )
++
++int main(void)
++{
++ DEFINE(THREAD, offsetof(struct task_struct, thread));
++ DEFINE(MM, offsetof(struct task_struct, mm));
++#ifdef CONFIG_PPC64
++ DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
++#else
++ DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info));
++ DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
++#endif /* CONFIG_PPC64 */
++
++ DEFINE(KSP, offsetof(struct thread_struct, ksp));
++ DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
++ DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
++ DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
++ DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
++#ifdef CONFIG_ALTIVEC
++ DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
++ DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
++ DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
++ DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_PPC64
++ DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid));
++#else /* CONFIG_PPC64 */
++ DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
++ DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
++ DEFINE(PT_PTRACED, PT_PTRACED);
++#endif
++#ifdef CONFIG_SPE
++ DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0]));
++ DEFINE(THREAD_ACC, offsetof(struct thread_struct, acc));
++ DEFINE(THREAD_SPEFSCR, offsetof(struct thread_struct, spefscr));
++ DEFINE(THREAD_USED_SPE, offsetof(struct thread_struct, used_spe));
++#endif /* CONFIG_SPE */
++#endif /* CONFIG_PPC64 */
++
++ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
++ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
++ DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
++#ifdef CONFIG_PPC32
++ DEFINE(TI_TASK, offsetof(struct thread_info, task));
++ DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
++ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
++#endif /* CONFIG_PPC32 */
++
++#ifdef CONFIG_PPC64
++ DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
++ DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size));
++ DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, dlines_per_page));
++ DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size));
++ DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
++ DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
++ DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
++ DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
++
++ /* paca */
++ DEFINE(PACA_SIZE, sizeof(struct paca_struct));
++ DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
++ DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start));
++ DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack));
++ DEFINE(PACACURRENT, offsetof(struct paca_struct, __current));
++ DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr));
++ DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real));
++ DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr));
++ DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
++ DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
++ DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
++ DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled));
++ DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
++ DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
++ DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
++#ifdef CONFIG_HUGETLB_PAGE
++ DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
++ DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
++#endif /* CONFIG_HUGETLB_PAGE */
++ DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr));
++ DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
++ DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
++ DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
++ DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi));
++ DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
++ DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca));
++ DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
++
++ DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
++ DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
++ DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
++ DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
++#endif /* CONFIG_PPC64 */
++
++ /* RTAS */
++ DEFINE(RTASBASE, offsetof(struct rtas_t, base));
++ DEFINE(RTASENTRY, offsetof(struct rtas_t, entry));
++
++ /* Interrupt register frame */
++ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
++#ifndef CONFIG_PPC64
++ DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
++#else /* CONFIG_PPC64 */
++ DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
++ /* 288 = # of volatile regs, int & fp, for leaf routines */
++ /* which do not stack a frame. See the PPC64 ABI. */
++ DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288);
++ /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
++ DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
++ DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
++#endif /* CONFIG_PPC64 */
++ DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
++ DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
++ DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
++ DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
++ DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
++ DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
++ DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
++ DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
++ DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
++ DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
++ DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
++ DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
++ DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
++ DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
++#ifndef CONFIG_PPC64
++ DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
++ DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
++ DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
++ DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
++ DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
++ DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
++ DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
++ DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
++ DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
++ DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
++ DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
++ DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
++ DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
++ DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
++ DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
++ DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
++ DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
++ DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
++#endif /* CONFIG_PPC64 */
++ /*
++ * Note: these symbols include _ because they overlap with special
++ * register names
++ */
++ DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
++ DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
++ DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
++ DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
++ DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
++ DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
++ DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
++ DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
++ DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
++ DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
++ DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
++#ifndef CONFIG_PPC64
++ DEFINE(_MQ, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, mq));
++ /*
++ * The PowerPC 400-class & Book-E processors have neither the DAR
++ * nor the DSISR SPRs. Hence, we overload them to hold the similar
++ * DEAR and ESR SPRs for such processors. For critical interrupts
++ * we use them to hold SRR0 and SRR1.
++ */
++ DEFINE(_DEAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
++ DEFINE(_ESR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
++#else /* CONFIG_PPC64 */
++ DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe));
++
++ /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */
++ DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs));
++ DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8);
++#endif /* CONFIG_PPC64 */
++
++ DEFINE(CLONE_VM, CLONE_VM);
++ DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
++
++#ifndef CONFIG_PPC64
++ DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
++#endif /* ! CONFIG_PPC64 */
++
++ /* About the CPU features table */
++ DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec));
++ DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask));
++ DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
++ DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
++ DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
++
++#ifndef CONFIG_PPC64
++ DEFINE(pbe_address, offsetof(struct pbe, address));
++ DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
++ DEFINE(pbe_next, offsetof(struct pbe, next));
++
++ DEFINE(TASK_SIZE, TASK_SIZE);
++ DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
++#else /* CONFIG_PPC64 */
++ /* systemcfg offsets for use by vdso */
++ DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp));
++ DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec));
++ DEFINE(CFG_TB_TO_XS, offsetof(struct systemcfg, tb_to_xs));
++ DEFINE(CFG_STAMP_XSEC, offsetof(struct systemcfg, stamp_xsec));
++ DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct systemcfg, tb_update_count));
++ DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct systemcfg, tz_minuteswest));
++ DEFINE(CFG_TZ_DSTTIME, offsetof(struct systemcfg, tz_dsttime));
++ DEFINE(CFG_SYSCALL_MAP32, offsetof(struct systemcfg, syscall_map_32));
++ DEFINE(CFG_SYSCALL_MAP64, offsetof(struct systemcfg, syscall_map_64));
++
++ /* timeval/timezone offsets for use by vdso */
++ DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
++ DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec));
++ DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec));
++ DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec));
++ DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
++ DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
++#endif /* CONFIG_PPC64 */
++ return 0;
++}
+diff --git a/arch/powerpc/kernel/binfmt_elf32.c b/arch/powerpc/kernel/binfmt_elf32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/binfmt_elf32.c
+@@ -0,0 +1,75 @@
++/*
++ * binfmt_elf32.c: Support 32-bit PPC ELF binaries on Power3 and followons.
++ * based on the SPARC64 version.
++ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem at redhat.com)
++ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj at ultra.linux.cz)
++ *
++ * Copyright (C) 2000,2001 Ken Aaker (kdaaker at rchland.vnet.ibm.com), IBM Corp
++ * Copyright (C) 2001 Anton Blanchard (anton at au.ibm.com), IBM
++ *
++ * 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.
++ */
++
++#define ELF_ARCH EM_PPC
++#define ELF_CLASS ELFCLASS32
++#define ELF_DATA ELFDATA2MSB;
++
++#include <asm/processor.h>
++#include <linux/module.h>
++#include <linux/config.h>
++#include <linux/elfcore.h>
++#include <linux/compat.h>
++
++#define elf_prstatus elf_prstatus32
++struct elf_prstatus32
++{
++ struct elf_siginfo pr_info; /* Info associated with signal */
++ short pr_cursig; /* Current signal */
++ unsigned int pr_sigpend; /* Set of pending signals */
++ unsigned int pr_sighold; /* Set of held signals */
++ pid_t pr_pid;
++ pid_t pr_ppid;
++ pid_t pr_pgrp;
++ pid_t pr_sid;
++ struct compat_timeval pr_utime; /* User time */
++ struct compat_timeval pr_stime; /* System time */
++ struct compat_timeval pr_cutime; /* Cumulative user time */
++ struct compat_timeval pr_cstime; /* Cumulative system time */
++ elf_gregset_t pr_reg; /* General purpose registers. */
++ int pr_fpvalid; /* True if math co-processor being used. */
++};
++
++#define elf_prpsinfo elf_prpsinfo32
++struct elf_prpsinfo32
++{
++ char pr_state; /* numeric process state */
++ char pr_sname; /* char for pr_state */
++ char pr_zomb; /* zombie */
++ char pr_nice; /* nice val */
++ unsigned int pr_flag; /* flags */
++ u32 pr_uid;
++ u32 pr_gid;
++ pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
++ /* Lots missing */
++ char pr_fname[16]; /* filename of executable */
++ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
++};
++
++#include <linux/time.h>
++
++#undef cputime_to_timeval
++#define cputime_to_timeval cputime_to_compat_timeval
++static __inline__ void
++cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
++{
++ unsigned long jiffies = cputime_to_jiffies(cputime);
++ value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
++ value->tv_sec = jiffies / HZ;
++}
++
++#define init_elf_binfmt init_elf32_binfmt
++
++#include "../../../fs/binfmt_elf.c"
+diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/btext.c
+@@ -0,0 +1,853 @@
++/*
++ * Procedures for drawing on the screen early on in the boot process.
++ *
++ * Benjamin Herrenschmidt <benh at kernel.crashing.org>
++ */
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/module.h>
++
++#include <asm/sections.h>
++#include <asm/prom.h>
++#include <asm/btext.h>
++#include <asm/prom.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/io.h>
++#include <asm/lmb.h>
++#include <asm/processor.h>
++
++#define NO_SCROLL
++
++#ifndef NO_SCROLL
++static void scrollscreen(void);
++#endif
++
++static void draw_byte(unsigned char c, long locX, long locY);
++static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);
++static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);
++static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);
++
++static int g_loc_X;
++static int g_loc_Y;
++static int g_max_loc_X;
++static int g_max_loc_Y;
++
++static int dispDeviceRowBytes;
++static int dispDeviceDepth;
++static int dispDeviceRect[4];
++static unsigned char *dispDeviceBase, *logicalDisplayBase;
++
++unsigned long disp_BAT[2] __initdata = {0, 0};
++
++#define cmapsz (16*256)
++
++static unsigned char vga_font[cmapsz];
++
++int boot_text_mapped;
++int force_printk_to_btext = 0;
++
++#ifdef CONFIG_PPC32
++/* Calc BAT values for mapping the display and store them
++ * in disp_BAT. Those values are then used from head.S to map
++ * the display during identify_machine() and MMU_Init()
++ *
++ * The display is mapped to virtual address 0xD0000000, rather
++ * than 1:1, because some some CHRP machines put the frame buffer
++ * in the region starting at 0xC0000000 (KERNELBASE).
++ * This mapping is temporary and will disappear as soon as the
++ * setup done by MMU_Init() is applied.
++ *
++ * For now, we align the BAT and then map 8Mb on 601 and 16Mb
++ * on other PPCs. This may cause trouble if the framebuffer
++ * is really badly aligned, but I didn't encounter this case
++ * yet.
++ */
++void __init
++btext_prepare_BAT(void)
++{
++ unsigned long vaddr = KERNELBASE + 0x10000000;
++ unsigned long addr;
++ unsigned long lowbits;
++
++ addr = (unsigned long)dispDeviceBase;
++ if (!addr) {
++ boot_text_mapped = 0;
++ return;
++ }
++ if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
++ /* 603, 604, G3, G4, ... */
++ lowbits = addr & ~0xFF000000UL;
++ addr &= 0xFF000000UL;
++ disp_BAT[0] = vaddr | (BL_16M<<2) | 2;
++ disp_BAT[1] = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);
++ } else {
++ /* 601 */
++ lowbits = addr & ~0xFF800000UL;
++ addr &= 0xFF800000UL;
++ disp_BAT[0] = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
++ disp_BAT[1] = addr | BL_8M | 0x40;
++ }
++ logicalDisplayBase = (void *) (vaddr + lowbits);
++}
++#endif
++
++/* This function will enable the early boot text when doing OF booting. This
++ * way, xmon output should work too
++ */
++void __init
++btext_setup_display(int width, int height, int depth, int pitch,
++ unsigned long address)
++{
++ g_loc_X = 0;
++ g_loc_Y = 0;
++ g_max_loc_X = width / 8;
++ g_max_loc_Y = height / 16;
++ logicalDisplayBase = (unsigned char *)address;
++ dispDeviceBase = (unsigned char *)address;
++ dispDeviceRowBytes = pitch;
++ dispDeviceDepth = depth;
++ dispDeviceRect[0] = dispDeviceRect[1] = 0;
++ dispDeviceRect[2] = width;
++ dispDeviceRect[3] = height;
++ boot_text_mapped = 1;
++}
++
++/* Here's a small text engine to use during early boot
++ * or for debugging purposes
++ *
++ * todo:
++ *
++ * - build some kind of vgacon with it to enable early printk
++ * - move to a separate file
++ * - add a few video driver hooks to keep in sync with display
++ * changes.
++ */
++
++void map_boot_text(void)
++{
++ unsigned long base, offset, size;
++ unsigned char *vbase;
++
++ /* By default, we are no longer mapped */
++ boot_text_mapped = 0;
++ if (dispDeviceBase == 0)
++ return;
++ base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL;
++ offset = ((unsigned long) dispDeviceBase) - base;
++ size = dispDeviceRowBytes * dispDeviceRect[3] + offset
++ + dispDeviceRect[0];
++ vbase = __ioremap(base, size, _PAGE_NO_CACHE);
++ if (vbase == 0)
++ return;
++ logicalDisplayBase = vbase + offset;
++ boot_text_mapped = 1;
++}
++
++int btext_initialize(struct device_node *np)
++{
++ unsigned int width, height, depth, pitch;
++ unsigned long address = 0;
++ u32 *prop;
++
++ prop = (u32 *)get_property(np, "width", NULL);
++ if (prop == NULL)
++ return -EINVAL;
++ width = *prop;
++ prop = (u32 *)get_property(np, "height", NULL);
++ if (prop == NULL)
++ return -EINVAL;
++ height = *prop;
++ prop = (u32 *)get_property(np, "depth", NULL);
++ if (prop == NULL)
++ return -EINVAL;
++ depth = *prop;
++ pitch = width * ((depth + 7) / 8);
++ prop = (u32 *)get_property(np, "linebytes", NULL);
++ if (prop)
++ pitch = *prop;
++ if (pitch == 1)
++ pitch = 0x1000;
++ prop = (u32 *)get_property(np, "address", NULL);
++ if (prop)
++ address = *prop;
++
++ /* FIXME: Add support for PCI reg properties */
++
++ if (address == 0)
++ return -EINVAL;
++
++ g_loc_X = 0;
++ g_loc_Y = 0;
++ g_max_loc_X = width / 8;
++ g_max_loc_Y = height / 16;
++ logicalDisplayBase = (unsigned char *)address;
++ dispDeviceBase = (unsigned char *)address;
++ dispDeviceRowBytes = pitch;
++ dispDeviceDepth = depth;
++ dispDeviceRect[0] = dispDeviceRect[1] = 0;
++ dispDeviceRect[2] = width;
++ dispDeviceRect[3] = height;
++
++ map_boot_text();
++
++ return 0;
++}
++
++void __init init_boot_display(void)
++{
++ char *name;
++ struct device_node *np = NULL;
++ int rc = -ENODEV;
++
++ printk("trying to initialize btext ...\n");
++
++ name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
++ if (name != NULL) {
++ np = of_find_node_by_path(name);
++ if (np != NULL) {
++ if (strcmp(np->type, "display") != 0) {
++ printk("boot stdout isn't a display !\n");
++ of_node_put(np);
++ np = NULL;
++ }
++ }
++ }
++ if (np)
++ rc = btext_initialize(np);
++ if (rc == 0)
++ return;
++
++ for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
++ if (get_property(np, "linux,opened", NULL)) {
++ printk("trying %s ...\n", np->full_name);
++ rc = btext_initialize(np);
++ printk("result: %d\n", rc);
++ }
++ if (rc == 0)
++ return;
++ }
++}
++
++/* Calc the base address of a given point (x,y) */
++static unsigned char * calc_base(int x, int y)
++{
++ unsigned char *base;
++
++ base = logicalDisplayBase;
++ if (base == 0)
++ base = dispDeviceBase;
++ base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3);
++ base += (y + dispDeviceRect[1]) * dispDeviceRowBytes;
++ return base;
++}
++
++/* Adjust the display to a new resolution */
++void btext_update_display(unsigned long phys, int width, int height,
++ int depth, int pitch)
++{
++ if (dispDeviceBase == 0)
++ return;
++
++ /* check it's the same frame buffer (within 256MB) */
++ if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000)
++ return;
++
++ dispDeviceBase = (__u8 *) phys;
++ dispDeviceRect[0] = 0;
++ dispDeviceRect[1] = 0;
++ dispDeviceRect[2] = width;
++ dispDeviceRect[3] = height;
++ dispDeviceDepth = depth;
++ dispDeviceRowBytes = pitch;
++ if (boot_text_mapped) {
++ iounmap(logicalDisplayBase);
++ boot_text_mapped = 0;
++ }
++ map_boot_text();
++ g_loc_X = 0;
++ g_loc_Y = 0;
++ g_max_loc_X = width / 8;
++ g_max_loc_Y = height / 16;
++}
++EXPORT_SYMBOL(btext_update_display);
++
++void btext_clearscreen(void)
++{
++ unsigned long *base = (unsigned long *)calc_base(0, 0);
++ unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
++ (dispDeviceDepth >> 3)) >> 3;
++ int i,j;
++
++ for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
++ {
++ unsigned long *ptr = base;
++ for(j=width; j; --j)
++ *(ptr++) = 0;
++ base += (dispDeviceRowBytes >> 3);
++ }
++}
++
++#ifndef NO_SCROLL
++static void scrollscreen(void)
++{
++ unsigned long *src = (unsigned long *)calc_base(0,16);
++ unsigned long *dst = (unsigned long *)calc_base(0,0);
++ unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
++ (dispDeviceDepth >> 3)) >> 3;
++ int i,j;
++
++ for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
++ {
++ unsigned long *src_ptr = src;
++ unsigned long *dst_ptr = dst;
++ for(j=width; j; --j)
++ *(dst_ptr++) = *(src_ptr++);
++ src += (dispDeviceRowBytes >> 3);
++ dst += (dispDeviceRowBytes >> 3);
++ }
++ for (i=0; i<16; i++)
++ {
++ unsigned long *dst_ptr = dst;
++ for(j=width; j; --j)
++ *(dst_ptr++) = 0;
++ dst += (dispDeviceRowBytes >> 3);
++ }
++}
++#endif /* ndef NO_SCROLL */
++
++void btext_drawchar(char c)
++{
++ int cline = 0;
++#ifdef NO_SCROLL
++ int x;
++#endif
++ if (!boot_text_mapped)
++ return;
++
++ switch (c) {
++ case '\b':
++ if (g_loc_X > 0)
++ --g_loc_X;
++ break;
++ case '\t':
++ g_loc_X = (g_loc_X & -8) + 8;
++ break;
++ case '\r':
++ g_loc_X = 0;
++ break;
++ case '\n':
++ g_loc_X = 0;
++ g_loc_Y++;
++ cline = 1;
++ break;
++ default:
++ draw_byte(c, g_loc_X++, g_loc_Y);
++ }
++ if (g_loc_X >= g_max_loc_X) {
++ g_loc_X = 0;
++ g_loc_Y++;
++ cline = 1;
++ }
++#ifndef NO_SCROLL
++ while (g_loc_Y >= g_max_loc_Y) {
++ scrollscreen();
++ g_loc_Y--;
++ }
++#else
++ /* wrap around from bottom to top of screen so we don't
++ waste time scrolling each line. -- paulus. */
++ if (g_loc_Y >= g_max_loc_Y)
++ g_loc_Y = 0;
++ if (cline) {
++ for (x = 0; x < g_max_loc_X; ++x)
++ draw_byte(' ', x, g_loc_Y);
++ }
++#endif
++}
++
++void btext_drawstring(const char *c)
++{
++ if (!boot_text_mapped)
++ return;
++ while (*c)
++ btext_drawchar(*c++);
++}
++
++void btext_drawhex(unsigned long v)
++{
++ char *hex_table = "0123456789abcdef";
++
++ if (!boot_text_mapped)
++ return;
++#ifdef CONFIG_PPC64
++ btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 52) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 48) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 44) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 40) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 36) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 32) & 0x0000000FUL]);
++#endif
++ btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]);
++ btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]);
++ btext_drawchar(' ');
++}
++
++static void draw_byte(unsigned char c, long locX, long locY)
++{
++ unsigned char *base = calc_base(locX << 3, locY << 4);
++ unsigned char *font = &vga_font[((unsigned int)c) * 16];
++ int rb = dispDeviceRowBytes;
++
++ switch(dispDeviceDepth) {
++ case 24:
++ case 32:
++ draw_byte_32(font, (unsigned int *)base, rb);
++ break;
++ case 15:
++ case 16:
++ draw_byte_16(font, (unsigned int *)base, rb);
++ break;
++ case 8:
++ draw_byte_8(font, (unsigned int *)base, rb);
++ break;
++ }
++}
++
++static unsigned int expand_bits_8[16] = {
++ 0x00000000,
++ 0x000000ff,
++ 0x0000ff00,
++ 0x0000ffff,
++ 0x00ff0000,
++ 0x00ff00ff,
++ 0x00ffff00,
++ 0x00ffffff,
++ 0xff000000,
++ 0xff0000ff,
++ 0xff00ff00,
++ 0xff00ffff,
++ 0xffff0000,
++ 0xffff00ff,
++ 0xffffff00,
++ 0xffffffff
++};
++
++static unsigned int expand_bits_16[4] = {
++ 0x00000000,
++ 0x0000ffff,
++ 0xffff0000,
++ 0xffffffff
++};
++
++
++static void draw_byte_32(unsigned char *font, unsigned int *base, int rb)
++{
++ int l, bits;
++ int fg = 0xFFFFFFFFUL;
++ int bg = 0x00000000UL;
++
++ for (l = 0; l < 16; ++l)
++ {
++ bits = *font++;
++ base[0] = (-(bits >> 7) & fg) ^ bg;
++ base[1] = (-((bits >> 6) & 1) & fg) ^ bg;
++ base[2] = (-((bits >> 5) & 1) & fg) ^ bg;
++ base[3] = (-((bits >> 4) & 1) & fg) ^ bg;
++ base[4] = (-((bits >> 3) & 1) & fg) ^ bg;
++ base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
++ base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
++ base[7] = (-(bits & 1) & fg) ^ bg;
++ base = (unsigned int *) ((char *)base + rb);
++ }
++}
++
++static void draw_byte_16(unsigned char *font, unsigned int *base, int rb)
++{
++ int l, bits;
++ int fg = 0xFFFFFFFFUL;
++ int bg = 0x00000000UL;
++ unsigned int *eb = (int *)expand_bits_16;
++
++ for (l = 0; l < 16; ++l)
++ {
++ bits = *font++;
++ base[0] = (eb[bits >> 6] & fg) ^ bg;
++ base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg;
++ base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg;
++ base[3] = (eb[bits & 3] & fg) ^ bg;
++ base = (unsigned int *) ((char *)base + rb);
++ }
++}
++
++static void draw_byte_8(unsigned char *font, unsigned int *base, int rb)
++{
++ int l, bits;
++ int fg = 0x0F0F0F0FUL;
++ int bg = 0x00000000UL;
++ unsigned int *eb = (int *)expand_bits_8;
++
++ for (l = 0; l < 16; ++l)
++ {
++ bits = *font++;
++ base[0] = (eb[bits >> 4] & fg) ^ bg;
++ base[1] = (eb[bits & 0xf] & fg) ^ bg;
++ base = (unsigned int *) ((char *)base + rb);
++ }
++}
++
++static unsigned char vga_font[cmapsz] = {
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
++0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
++0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
++0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
++0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
++0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
++0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
++0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
++0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
++0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
++0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
++0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
++0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
++0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
++0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
++0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
++0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
++0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
++0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
++0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
++0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
++0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
++0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
++0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
++0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
++0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
++0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
++0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
++0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
++0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
++0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
++0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
++0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
++0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
++0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
++0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
++0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
++0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
++0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
++0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
++0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
++0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
++0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
++0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
++0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
++0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
++0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
++0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
++0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
++0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
++0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
++0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
++0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
++0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
++0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
++0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
++0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
++0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
++0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
++0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
++0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
++0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
++0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
++0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
++0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb,
++0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
++0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
++0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
++0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
++0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
++0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
++0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
++0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
++0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
++0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
++0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
++0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
++0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
++0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
++0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
++0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
++0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
++0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
++0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
++0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
++0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
++0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
++0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
++0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
++0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
++0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
++0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
++0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
++0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
++0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66,
++0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
++0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
++0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
++0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
++0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
++0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
++0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
++0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
++0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06,
++0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
++0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
++0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
++0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
++0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
++0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
++0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
++0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
++0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
++0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
++0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
++0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
++0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
++0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
++0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
++0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
++0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
++0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
++0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
++0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
++0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
++0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
++0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
++0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
++0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
++0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
++0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
++0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++0x00, 0x00, 0x00, 0x00,
++};
+diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/cputable.c
+@@ -0,0 +1,996 @@
++/*
++ * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * Modifications for ppc64:
++ * Copyright (C) 2003 Dave Engebretsen <engebret at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/config.h>
++#include <linux/string.h>
++#include <linux/sched.h>
++#include <linux/threads.h>
++#include <linux/init.h>
++#include <linux/module.h>
++
++#include <asm/oprofile_impl.h>
++#include <asm/cputable.h>
++
++struct cpu_spec* cur_cpu_spec = NULL;
++EXPORT_SYMBOL(cur_cpu_spec);
++
++/* NOTE:
++ * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's
++ * the responsibility of the appropriate CPU save/restore functions to
++ * eventually copy these settings over. Those save/restore aren't yet
++ * part of the cputable though. That has to be fixed for both ppc32
++ * and ppc64
++ */
++#ifdef CONFIG_PPC64
++extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
++#else
++extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_750cx(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_750fx(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_7400(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
++#endif /* CONFIG_PPC32 */
++extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
++
++/* This table only contains "desktop" CPUs, it need to be filled with embedded
++ * ones as well...
++ */
++#define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \
++ PPC_FEATURE_HAS_MMU)
++#define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64)
++
++
++/* We only set the spe features if the kernel was compiled with
++ * spe support
++ */
++#ifdef CONFIG_SPE
++#define PPC_FEATURE_SPE_COMP PPC_FEATURE_HAS_SPE
++#else
++#define PPC_FEATURE_SPE_COMP 0
++#endif
++
++struct cpu_spec cpu_specs[] = {
++#ifdef CONFIG_PPC64
++ { /* Power3 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00400000,
++ .cpu_name = "POWER3 (630)",
++ .cpu_features = CPU_FTRS_POWER3,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power3,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/power3",
++ .oprofile_model = &op_model_rs64,
++#endif
++ },
++ { /* Power3+ */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00410000,
++ .cpu_name = "POWER3 (630+)",
++ .cpu_features = CPU_FTRS_POWER3,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power3,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/power3",
++ .oprofile_model = &op_model_rs64,
++#endif
++ },
++ { /* Northstar */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00330000,
++ .cpu_name = "RS64-II (northstar)",
++ .cpu_features = CPU_FTRS_RS64,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power3,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/rs64",
++ .oprofile_model = &op_model_rs64,
++#endif
++ },
++ { /* Pulsar */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00340000,
++ .cpu_name = "RS64-III (pulsar)",
++ .cpu_features = CPU_FTRS_RS64,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power3,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/rs64",
++ .oprofile_model = &op_model_rs64,
++#endif
++ },
++ { /* I-star */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00360000,
++ .cpu_name = "RS64-III (icestar)",
++ .cpu_features = CPU_FTRS_RS64,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power3,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/rs64",
++ .oprofile_model = &op_model_rs64,
++#endif
++ },
++ { /* S-star */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00370000,
++ .cpu_name = "RS64-IV (sstar)",
++ .cpu_features = CPU_FTRS_RS64,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power3,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/rs64",
++ .oprofile_model = &op_model_rs64,
++#endif
++ },
++ { /* Power4 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00350000,
++ .cpu_name = "POWER4 (gp)",
++ .cpu_features = CPU_FTRS_POWER4,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power4,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/power4",
++ .oprofile_model = &op_model_rs64,
++#endif
++ },
++ { /* Power4+ */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00380000,
++ .cpu_name = "POWER4+ (gq)",
++ .cpu_features = CPU_FTRS_POWER4,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_power4,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/power4",
++ .oprofile_model = &op_model_power4,
++#endif
++ },
++ { /* PPC970 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00390000,
++ .cpu_name = "PPC970",
++ .cpu_features = CPU_FTRS_PPC970,
++ .cpu_user_features = COMMON_USER_PPC64 |
++ PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_ppc970,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/970",
++ .oprofile_model = &op_model_power4,
++#endif
++ },
++#endif /* CONFIG_PPC64 */
++#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4)
++ { /* PPC970FX */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x003c0000,
++ .cpu_name = "PPC970FX",
++#ifdef CONFIG_PPC32
++ .cpu_features = CPU_FTRS_970_32,
++#else
++ .cpu_features = CPU_FTRS_PPC970,
++#endif
++ .cpu_user_features = COMMON_USER_PPC64 |
++ PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 8,
++ .cpu_setup = __setup_cpu_ppc970,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/970",
++ .oprofile_model = &op_model_power4,
++#endif
++ },
++#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */
++#ifdef CONFIG_PPC64
++ { /* PPC970MP */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00440000,
++ .cpu_name = "PPC970MP",
++ .cpu_features = CPU_FTRS_PPC970,
++ .cpu_user_features = COMMON_USER_PPC64 |
++ PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .cpu_setup = __setup_cpu_ppc970,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/970",
++ .oprofile_model = &op_model_power4,
++#endif
++ },
++ { /* Power5 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x003a0000,
++ .cpu_name = "POWER5 (gr)",
++ .cpu_features = CPU_FTRS_POWER5,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_power4,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/power5",
++ .oprofile_model = &op_model_power4,
++#endif
++ },
++ { /* Power5 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x003b0000,
++ .cpu_name = "POWER5 (gs)",
++ .cpu_features = CPU_FTRS_POWER5,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_power4,
++#ifdef CONFIG_OPROFILE
++ .oprofile_cpu_type = "ppc64/power5",
++ .oprofile_model = &op_model_power4,
++#endif
++ },
++ { /* BE DD1.x */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00700000,
++ .cpu_name = "Cell Broadband Engine",
++ .cpu_features = CPU_FTRS_CELL,
++ .cpu_user_features = COMMON_USER_PPC64 |
++ PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .cpu_setup = __setup_cpu_be,
++ },
++ { /* default match */
++ .pvr_mask = 0x00000000,
++ .pvr_value = 0x00000000,
++ .cpu_name = "POWER4 (compatible)",
++ .cpu_features = CPU_FTRS_COMPATIBLE,
++ .cpu_user_features = COMMON_USER_PPC64,
++ .icache_bsize = 128,
++ .dcache_bsize = 128,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_power4,
++ }
++#endif /* CONFIG_PPC64 */
++#ifdef CONFIG_PPC32
++#if CLASSIC_PPC
++ { /* 601 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00010000,
++ .cpu_name = "601",
++ .cpu_features = CPU_FTRS_PPC601,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_601_INSTR |
++ PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 603 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00030000,
++ .cpu_name = "603",
++ .cpu_features = CPU_FTRS_603,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .cpu_setup = __setup_cpu_603
++ },
++ { /* 603e */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00060000,
++ .cpu_name = "603e",
++ .cpu_features = CPU_FTRS_603,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .cpu_setup = __setup_cpu_603
++ },
++ { /* 603ev */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00070000,
++ .cpu_name = "603ev",
++ .cpu_features = CPU_FTRS_603,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .cpu_setup = __setup_cpu_603
++ },
++ { /* 604 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00040000,
++ .cpu_name = "604",
++ .cpu_features = CPU_FTRS_604,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 2,
++ .cpu_setup = __setup_cpu_604
++ },
++ { /* 604e */
++ .pvr_mask = 0xfffff000,
++ .pvr_value = 0x00090000,
++ .cpu_name = "604e",
++ .cpu_features = CPU_FTRS_604,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_604
++ },
++ { /* 604r */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00090000,
++ .cpu_name = "604r",
++ .cpu_features = CPU_FTRS_604,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_604
++ },
++ { /* 604ev */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x000a0000,
++ .cpu_name = "604ev",
++ .cpu_features = CPU_FTRS_604,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_604
++ },
++ { /* 740/750 (0x4202, don't support TAU ?) */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x00084202,
++ .cpu_name = "740/750",
++ .cpu_features = CPU_FTRS_740_NOTAU,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750
++ },
++ { /* 750CX (80100 and 8010x?) */
++ .pvr_mask = 0xfffffff0,
++ .pvr_value = 0x00080100,
++ .cpu_name = "750CX",
++ .cpu_features = CPU_FTRS_750,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750cx
++ },
++ { /* 750CX (82201 and 82202) */
++ .pvr_mask = 0xfffffff0,
++ .pvr_value = 0x00082200,
++ .cpu_name = "750CX",
++ .cpu_features = CPU_FTRS_750,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750cx
++ },
++ { /* 750CXe (82214) */
++ .pvr_mask = 0xfffffff0,
++ .pvr_value = 0x00082210,
++ .cpu_name = "750CXe",
++ .cpu_features = CPU_FTRS_750,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750cx
++ },
++ { /* 750CXe "Gekko" (83214) */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x00083214,
++ .cpu_name = "750CXe",
++ .cpu_features = CPU_FTRS_750,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750cx
++ },
++ { /* 745/755 */
++ .pvr_mask = 0xfffff000,
++ .pvr_value = 0x00083000,
++ .cpu_name = "745/755",
++ .cpu_features = CPU_FTRS_750,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750
++ },
++ { /* 750FX rev 1.x */
++ .pvr_mask = 0xffffff00,
++ .pvr_value = 0x70000100,
++ .cpu_name = "750FX",
++ .cpu_features = CPU_FTRS_750FX1,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750
++ },
++ { /* 750FX rev 2.0 must disable HID0[DPM] */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x70000200,
++ .cpu_name = "750FX",
++ .cpu_features = CPU_FTRS_750FX2,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750
++ },
++ { /* 750FX (All revs except 2.0) */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x70000000,
++ .cpu_name = "750FX",
++ .cpu_features = CPU_FTRS_750FX,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750fx
++ },
++ { /* 750GX */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x70020000,
++ .cpu_name = "750GX",
++ .cpu_features = CPU_FTRS_750GX,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750fx
++ },
++ { /* 740/750 (L2CR bit need fixup for 740) */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00080000,
++ .cpu_name = "740/750",
++ .cpu_features = CPU_FTRS_740,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_750
++ },
++ { /* 7400 rev 1.1 ? (no TAU) */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x000c1101,
++ .cpu_name = "7400 (1.1)",
++ .cpu_features = CPU_FTRS_7400_NOTAU,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_7400
++ },
++ { /* 7400 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x000c0000,
++ .cpu_name = "7400",
++ .cpu_features = CPU_FTRS_7400,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_7400
++ },
++ { /* 7410 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x800c0000,
++ .cpu_name = "7410",
++ .cpu_features = CPU_FTRS_7400,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ .cpu_setup = __setup_cpu_7410
++ },
++ { /* 7450 2.0 - no doze/nap */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x80000200,
++ .cpu_name = "7450",
++ .cpu_features = CPU_FTRS_7450_20,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7450 2.1 */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x80000201,
++ .cpu_name = "7450",
++ .cpu_features = CPU_FTRS_7450_21,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7450 2.3 and newer */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x80000000,
++ .cpu_name = "7450",
++ .cpu_features = CPU_FTRS_7450_23,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7455 rev 1.x */
++ .pvr_mask = 0xffffff00,
++ .pvr_value = 0x80010100,
++ .cpu_name = "7455",
++ .cpu_features = CPU_FTRS_7455_1,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7455 rev 2.0 */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x80010200,
++ .cpu_name = "7455",
++ .cpu_features = CPU_FTRS_7455_20,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7455 others */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x80010000,
++ .cpu_name = "7455",
++ .cpu_features = CPU_FTRS_7455,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7447/7457 Rev 1.0 */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x80020100,
++ .cpu_name = "7447/7457",
++ .cpu_features = CPU_FTRS_7447_10,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7447/7457 Rev 1.1 */
++ .pvr_mask = 0xffffffff,
++ .pvr_value = 0x80020101,
++ .cpu_name = "7447/7457",
++ .cpu_features = CPU_FTRS_7447_10,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7447/7457 Rev 1.2 and later */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x80020000,
++ .cpu_name = "7447/7457",
++ .cpu_features = CPU_FTRS_7447,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7447A */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x80030000,
++ .cpu_name = "7447A",
++ .cpu_features = CPU_FTRS_7447A,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 7448 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x80040000,
++ .cpu_name = "7448",
++ .cpu_features = CPU_FTRS_7447A,
++ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 6,
++ .cpu_setup = __setup_cpu_745x
++ },
++ { /* 82xx (8240, 8245, 8260 are all 603e cores) */
++ .pvr_mask = 0x7fff0000,
++ .pvr_value = 0x00810000,
++ .cpu_name = "82xx",
++ .cpu_features = CPU_FTRS_82XX,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .cpu_setup = __setup_cpu_603
++ },
++ { /* All G2_LE (603e core, plus some) have the same pvr */
++ .pvr_mask = 0x7fff0000,
++ .pvr_value = 0x00820000,
++ .cpu_name = "G2_LE",
++ .cpu_features = CPU_FTRS_G2_LE,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .cpu_setup = __setup_cpu_603
++ },
++ { /* e300 (a 603e core, plus some) on 83xx */
++ .pvr_mask = 0x7fff0000,
++ .pvr_value = 0x00830000,
++ .cpu_name = "e300",
++ .cpu_features = CPU_FTRS_E300,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .cpu_setup = __setup_cpu_603
++ },
++ { /* default match, we assume split I/D cache & TB (non-601)... */
++ .pvr_mask = 0x00000000,
++ .pvr_value = 0x00000000,
++ .cpu_name = "(generic PPC)",
++ .cpu_features = CPU_FTRS_CLASSIC32,
++ .cpu_user_features = COMMON_USER,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++#endif /* CLASSIC_PPC */
++#ifdef CONFIG_8xx
++ { /* 8xx */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00500000,
++ .cpu_name = "8xx",
++ /* CPU_FTR_MAYBE_CAN_DOZE is possible,
++ * if the 8xx code is there.... */
++ .cpu_features = CPU_FTRS_8XX,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 16,
++ .dcache_bsize = 16,
++ },
++#endif /* CONFIG_8xx */
++#ifdef CONFIG_40x
++ { /* 403GC */
++ .pvr_mask = 0xffffff00,
++ .pvr_value = 0x00200200,
++ .cpu_name = "403GC",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 16,
++ .dcache_bsize = 16,
++ },
++ { /* 403GCX */
++ .pvr_mask = 0xffffff00,
++ .pvr_value = 0x00201400,
++ .cpu_name = "403GCX",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
++ .icache_bsize = 16,
++ .dcache_bsize = 16,
++ },
++ { /* 403G ?? */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x00200000,
++ .cpu_name = "403G ??",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 16,
++ .dcache_bsize = 16,
++ },
++ { /* 405GP */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x40110000,
++ .cpu_name = "405GP",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* STB 03xxx */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x40130000,
++ .cpu_name = "STB03xxx",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* STB 04xxx */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x41810000,
++ .cpu_name = "STB04xxx",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* NP405L */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x41610000,
++ .cpu_name = "NP405L",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* NP4GS3 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x40B10000,
++ .cpu_name = "NP4GS3",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* NP405H */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x41410000,
++ .cpu_name = "NP405H",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 405GPr */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x50910000,
++ .cpu_name = "405GPr",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* STBx25xx */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x51510000,
++ .cpu_name = "STBx25xx",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 405LP */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x41F10000,
++ .cpu_name = "405LP",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* Xilinx Virtex-II Pro */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x20010000,
++ .cpu_name = "Virtex-II Pro",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 405EP */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x51210000,
++ .cpu_name = "405EP",
++ .cpu_features = CPU_FTRS_40X,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++
++#endif /* CONFIG_40x */
++#ifdef CONFIG_44x
++ {
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x40000850,
++ .cpu_name = "440EP Rev. A",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = COMMON_USER, /* 440EP has an FPU */
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ {
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x400008d3,
++ .cpu_name = "440EP Rev. B",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = COMMON_USER, /* 440EP has an FPU */
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 440GP Rev. B */
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x40000440,
++ .cpu_name = "440GP Rev. B",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 440GP Rev. C */
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x40000481,
++ .cpu_name = "440GP Rev. C",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 440GX Rev. A */
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x50000850,
++ .cpu_name = "440GX Rev. A",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 440GX Rev. B */
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x50000851,
++ .cpu_name = "440GX Rev. B",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 440GX Rev. C */
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x50000892,
++ .cpu_name = "440GX Rev. C",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 440GX Rev. F */
++ .pvr_mask = 0xf0000fff,
++ .pvr_value = 0x50000894,
++ .cpu_name = "440GX Rev. F",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++ { /* 440SP Rev. A */
++ .pvr_mask = 0xff000fff,
++ .pvr_value = 0x53000891,
++ .cpu_name = "440SP Rev. A",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ },
++#endif /* CONFIG_44x */
++#ifdef CONFIG_FSL_BOOKE
++ { /* e200z5 */
++ .pvr_mask = 0xfff00000,
++ .pvr_value = 0x81000000,
++ .cpu_name = "e200z5",
++ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
++ .cpu_features = CPU_FTRS_E200,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE |
++ PPC_FEATURE_UNIFIED_CACHE,
++ .dcache_bsize = 32,
++ },
++ { /* e200z6 */
++ .pvr_mask = 0xfff00000,
++ .pvr_value = 0x81100000,
++ .cpu_name = "e200z6",
++ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
++ .cpu_features = CPU_FTRS_E200,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
++ PPC_FEATURE_HAS_EFP_SINGLE |
++ PPC_FEATURE_UNIFIED_CACHE,
++ .dcache_bsize = 32,
++ },
++ { /* e500 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x80200000,
++ .cpu_name = "e500",
++ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
++ .cpu_features = CPU_FTRS_E500,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
++ PPC_FEATURE_HAS_EFP_SINGLE,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ },
++ { /* e500v2 */
++ .pvr_mask = 0xffff0000,
++ .pvr_value = 0x80210000,
++ .cpu_name = "e500v2",
++ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
++ .cpu_features = CPU_FTRS_E500_2,
++ .cpu_user_features = PPC_FEATURE_32 |
++ PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
++ PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .num_pmcs = 4,
++ },
++#endif
++#if !CLASSIC_PPC
++ { /* default match */
++ .pvr_mask = 0x00000000,
++ .pvr_value = 0x00000000,
++ .cpu_name = "(generic PPC)",
++ .cpu_features = CPU_FTRS_GENERIC_32,
++ .cpu_user_features = PPC_FEATURE_32,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ }
++#endif /* !CLASSIC_PPC */
++#endif /* CONFIG_PPC32 */
++};
+diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/entry_32.S
+@@ -0,0 +1,1000 @@
++/*
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ * Rewritten by Cort Dougan (cort at fsmlabs.com) for PReP
++ * Copyright (C) 1996 Cort Dougan <cort at fsmlabs.com>
++ * Adapted for Power Macintosh by Paul Mackerras.
++ * Low-level exception handlers and MMU support
++ * rewritten by Paul Mackerras.
++ * Copyright (C) 1996 Paul Mackerras.
++ * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek at jlc.net).
++ *
++ * This file contains the system call entry code, context switch
++ * code, and exception/interrupt return code for PowerPC.
++ *
++ * 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/errno.h>
++#include <linux/sys.h>
++#include <linux/threads.h>
++#include <asm/reg.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/unistd.h>
++
++#undef SHOW_SYSCALLS
++#undef SHOW_SYSCALLS_TASK
++
++/*
++ * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
++ */
++#if MSR_KERNEL >= 0x10000
++#define LOAD_MSR_KERNEL(r, x) lis r,(x)@h; ori r,r,(x)@l
++#else
++#define LOAD_MSR_KERNEL(r, x) li r,(x)
++#endif
++
++#ifdef CONFIG_BOOKE
++#include "head_booke.h"
++#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level) \
++ mtspr exc_level##_SPRG,r8; \
++ BOOKE_LOAD_EXC_LEVEL_STACK(exc_level); \
++ lwz r0,GPR10-INT_FRAME_SIZE(r8); \
++ stw r0,GPR10(r11); \
++ lwz r0,GPR11-INT_FRAME_SIZE(r8); \
++ stw r0,GPR11(r11); \
++ mfspr r8,exc_level##_SPRG
++
++ .globl mcheck_transfer_to_handler
++mcheck_transfer_to_handler:
++ TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
++ b transfer_to_handler_full
++
++ .globl debug_transfer_to_handler
++debug_transfer_to_handler:
++ TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
++ b transfer_to_handler_full
++
++ .globl crit_transfer_to_handler
++crit_transfer_to_handler:
++ TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
++ /* fall through */
++#endif
++
++#ifdef CONFIG_40x
++ .globl crit_transfer_to_handler
++crit_transfer_to_handler:
++ lwz r0,crit_r10 at l(0)
++ stw r0,GPR10(r11)
++ lwz r0,crit_r11 at l(0)
++ stw r0,GPR11(r11)
++ /* fall through */
++#endif
++
++/*
++ * This code finishes saving the registers to the exception frame
++ * and jumps to the appropriate handler for the exception, turning
++ * on address translation.
++ * Note that we rely on the caller having set cr0.eq iff the exception
++ * occurred in kernel mode (i.e. MSR:PR = 0).
++ */
++ .globl transfer_to_handler_full
++transfer_to_handler_full:
++ SAVE_NVGPRS(r11)
++ /* fall through */
++
++ .globl transfer_to_handler
++transfer_to_handler:
++ stw r2,GPR2(r11)
++ stw r12,_NIP(r11)
++ stw r9,_MSR(r11)
++ andi. r2,r9,MSR_PR
++ mfctr r12
++ mfspr r2,SPRN_XER
++ stw r12,_CTR(r11)
++ stw r2,_XER(r11)
++ mfspr r12,SPRN_SPRG3
++ addi r2,r12,-THREAD
++ tovirt(r2,r2) /* set r2 to current */
++ beq 2f /* if from user, fix up THREAD.regs */
++ addi r11,r1,STACK_FRAME_OVERHEAD
++ stw r11,PT_REGS(r12)
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++ /* Check to see if the dbcr0 register is set up to debug. Use the
++ single-step bit to do this. */
++ lwz r12,THREAD_DBCR0(r12)
++ andis. r12,r12,DBCR0_IC at h
++ beq+ 3f
++ /* From user and task is ptraced - load up global dbcr0 */
++ li r12,-1 /* clear all pending debug events */
++ mtspr SPRN_DBSR,r12
++ lis r11,global_dbcr0 at ha
++ tophys(r11,r11)
++ addi r11,r11,global_dbcr0 at l
++ lwz r12,0(r11)
++ mtspr SPRN_DBCR0,r12
++ lwz r12,4(r11)
++ addi r12,r12,-1
++ stw r12,4(r11)
++#endif
++ b 3f
++2: /* if from kernel, check interrupted DOZE/NAP mode and
++ * check for stack overflow
++ */
++#ifdef CONFIG_6xx
++ mfspr r11,SPRN_HID0
++ mtcr r11
++BEGIN_FTR_SECTION
++ bt- 8,power_save_6xx_restore /* Check DOZE */
++END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
++BEGIN_FTR_SECTION
++ bt- 9,power_save_6xx_restore /* Check NAP */
++END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
++#endif /* CONFIG_6xx */
++ .globl transfer_to_handler_cont
++transfer_to_handler_cont:
++ lwz r11,THREAD_INFO-THREAD(r12)
++ cmplw r1,r11 /* if r1 <= current->thread_info */
++ ble- stack_ovf /* then the kernel stack overflowed */
++3:
++ mflr r9
++ lwz r11,0(r9) /* virtual address of handler */
++ lwz r9,4(r9) /* where to go when done */
++ FIX_SRR1(r10,r12)
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r10
++ mtlr r9
++ SYNC
++ RFI /* jump to handler, enable MMU */
++
++/*
++ * On kernel stack overflow, load up an initial stack pointer
++ * and call StackOverflow(regs), which should not return.
++ */
++stack_ovf:
++ /* sometimes we use a statically-allocated stack, which is OK. */
++ lis r11,_end at h
++ ori r11,r11,_end at l
++ cmplw r1,r11
++ ble 3b /* r1 <= &_end is OK */
++ SAVE_NVGPRS(r11)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ lis r1,init_thread_union at ha
++ addi r1,r1,init_thread_union at l
++ addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
++ lis r9,StackOverflow at ha
++ addi r9,r9,StackOverflow at l
++ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
++ FIX_SRR1(r10,r12)
++ mtspr SPRN_SRR0,r9
++ mtspr SPRN_SRR1,r10
++ SYNC
++ RFI
++
++/*
++ * Handle a system call.
++ */
++ .stabs "arch/powerpc/kernel/",N_SO,0,0,0f
++ .stabs "entry_32.S",N_SO,0,0,0f
++0:
++
++_GLOBAL(DoSyscall)
++ stw r0,THREAD+LAST_SYSCALL(r2)
++ stw r3,ORIG_GPR3(r1)
++ li r12,0
++ stw r12,RESULT(r1)
++ lwz r11,_CCR(r1) /* Clear SO bit in CR */
++ rlwinm r11,r11,0,4,2
++ stw r11,_CCR(r1)
++#ifdef SHOW_SYSCALLS
++ bl do_show_syscall
++#endif /* SHOW_SYSCALLS */
++ rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
++ li r11,0
++ stb r11,TI_SC_NOERR(r10)
++ lwz r11,TI_FLAGS(r10)
++ andi. r11,r11,_TIF_SYSCALL_T_OR_A
++ bne- syscall_dotrace
++syscall_dotrace_cont:
++ cmplwi 0,r0,NR_syscalls
++ lis r10,sys_call_table at h
++ ori r10,r10,sys_call_table at l
++ slwi r0,r0,2
++ bge- 66f
++ lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
++ mtlr r10
++ addi r9,r1,STACK_FRAME_OVERHEAD
++ PPC440EP_ERR42
++ blrl /* Call handler */
++ .globl ret_from_syscall
++ret_from_syscall:
++#ifdef SHOW_SYSCALLS
++ bl do_show_syscall_exit
++#endif
++ mr r6,r3
++ li r11,-_LAST_ERRNO
++ cmplw 0,r3,r11
++ rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
++ blt+ 30f
++ lbz r11,TI_SC_NOERR(r12)
++ cmpwi r11,0
++ bne 30f
++ neg r3,r3
++ lwz r10,_CCR(r1) /* Set SO bit in CR */
++ oris r10,r10,0x1000
++ stw r10,_CCR(r1)
++
++ /* disable interrupts so current_thread_info()->flags can't change */
++30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
++ SYNC
++ MTMSRD(r10)
++ lwz r9,TI_FLAGS(r12)
++ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
++ bne- syscall_exit_work
++syscall_exit_cont:
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ /* If the process has its own DBCR0 value, load it up. The single
++ step bit tells us that dbcr0 should be loaded. */
++ lwz r0,THREAD+THREAD_DBCR0(r2)
++ andis. r10,r0,DBCR0_IC at h
++ bnel- load_dbcr0
++#endif
++ stwcx. r0,0,r1 /* to clear the reservation */
++ lwz r4,_LINK(r1)
++ lwz r5,_CCR(r1)
++ mtlr r4
++ mtcr r5
++ lwz r7,_NIP(r1)
++ lwz r8,_MSR(r1)
++ FIX_SRR1(r8, r0)
++ lwz r2,GPR2(r1)
++ lwz r1,GPR1(r1)
++ mtspr SPRN_SRR0,r7
++ mtspr SPRN_SRR1,r8
++ SYNC
++ RFI
++
++66: li r3,-ENOSYS
++ b ret_from_syscall
++
++ .globl ret_from_fork
++ret_from_fork:
++ REST_NVGPRS(r1)
++ bl schedule_tail
++ li r3,0
++ b ret_from_syscall
++
++/* Traced system call support */
++syscall_dotrace:
++ SAVE_NVGPRS(r1)
++ li r0,0xc00
++ stw r0,_TRAP(r1)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl do_syscall_trace_enter
++ lwz r0,GPR0(r1) /* Restore original registers */
++ lwz r3,GPR3(r1)
++ lwz r4,GPR4(r1)
++ lwz r5,GPR5(r1)
++ lwz r6,GPR6(r1)
++ lwz r7,GPR7(r1)
++ lwz r8,GPR8(r1)
++ REST_NVGPRS(r1)
++ b syscall_dotrace_cont
++
++syscall_exit_work:
++ stw r6,RESULT(r1) /* Save result */
++ stw r3,GPR3(r1) /* Update return value */
++ andi. r0,r9,_TIF_SYSCALL_T_OR_A
++ beq 5f
++ ori r10,r10,MSR_EE
++ SYNC
++ MTMSRD(r10) /* re-enable interrupts */
++ lwz r4,_TRAP(r1)
++ andi. r4,r4,1
++ beq 4f
++ SAVE_NVGPRS(r1)
++ li r4,0xc00
++ stw r4,_TRAP(r1)
++4:
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl do_syscall_trace_leave
++ REST_NVGPRS(r1)
++2:
++ lwz r3,GPR3(r1)
++ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
++ SYNC
++ MTMSRD(r10) /* disable interrupts again */
++ rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
++ lwz r9,TI_FLAGS(r12)
++5:
++ andi. r0,r9,_TIF_NEED_RESCHED
++ bne 1f
++ lwz r5,_MSR(r1)
++ andi. r5,r5,MSR_PR
++ beq syscall_exit_cont
++ andi. r0,r9,_TIF_SIGPENDING
++ beq syscall_exit_cont
++ b do_user_signal
++1:
++ ori r10,r10,MSR_EE
++ SYNC
++ MTMSRD(r10) /* re-enable interrupts */
++ bl schedule
++ b 2b
++
++#ifdef SHOW_SYSCALLS
++do_show_syscall:
++#ifdef SHOW_SYSCALLS_TASK
++ lis r11,show_syscalls_task at ha
++ lwz r11,show_syscalls_task at l(r11)
++ cmp 0,r2,r11
++ bnelr
++#endif
++ stw r31,GPR31(r1)
++ mflr r31
++ lis r3,7f at ha
++ addi r3,r3,7f at l
++ lwz r4,GPR0(r1)
++ lwz r5,GPR3(r1)
++ lwz r6,GPR4(r1)
++ lwz r7,GPR5(r1)
++ lwz r8,GPR6(r1)
++ lwz r9,GPR7(r1)
++ bl printk
++ lis r3,77f at ha
++ addi r3,r3,77f at l
++ lwz r4,GPR8(r1)
++ mr r5,r2
++ bl printk
++ lwz r0,GPR0(r1)
++ lwz r3,GPR3(r1)
++ lwz r4,GPR4(r1)
++ lwz r5,GPR5(r1)
++ lwz r6,GPR6(r1)
++ lwz r7,GPR7(r1)
++ lwz r8,GPR8(r1)
++ mtlr r31
++ lwz r31,GPR31(r1)
++ blr
++
++do_show_syscall_exit:
++#ifdef SHOW_SYSCALLS_TASK
++ lis r11,show_syscalls_task at ha
++ lwz r11,show_syscalls_task at l(r11)
++ cmp 0,r2,r11
++ bnelr
++#endif
++ stw r31,GPR31(r1)
++ mflr r31
++ stw r3,RESULT(r1) /* Save result */
++ mr r4,r3
++ lis r3,79f at ha
++ addi r3,r3,79f at l
++ bl printk
++ lwz r3,RESULT(r1)
++ mtlr r31
++ lwz r31,GPR31(r1)
++ blr
++
++7: .string "syscall %d(%x, %x, %x, %x, %x, "
++77: .string "%x), current=%p\n"
++79: .string " -> %x\n"
++ .align 2,0
++
++#ifdef SHOW_SYSCALLS_TASK
++ .data
++ .globl show_syscalls_task
++show_syscalls_task:
++ .long -1
++ .text
++#endif
++#endif /* SHOW_SYSCALLS */
++
++/*
++ * The sigsuspend and rt_sigsuspend system calls can call do_signal
++ * and thus put the process into the stopped state where we might
++ * want to examine its user state with ptrace. Therefore we need
++ * to save all the nonvolatile registers (r13 - r31) before calling
++ * the C code.
++ */
++ .globl ppc_sigsuspend
++ppc_sigsuspend:
++ SAVE_NVGPRS(r1)
++ lwz r0,_TRAP(r1)
++ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
++ stw r0,_TRAP(r1) /* register set saved */
++ b sys_sigsuspend
++
++ .globl ppc_rt_sigsuspend
++ppc_rt_sigsuspend:
++ SAVE_NVGPRS(r1)
++ lwz r0,_TRAP(r1)
++ rlwinm r0,r0,0,0,30
++ stw r0,_TRAP(r1)
++ b sys_rt_sigsuspend
++
++ .globl ppc_fork
++ppc_fork:
++ SAVE_NVGPRS(r1)
++ lwz r0,_TRAP(r1)
++ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
++ stw r0,_TRAP(r1) /* register set saved */
++ b sys_fork
++
++ .globl ppc_vfork
++ppc_vfork:
++ SAVE_NVGPRS(r1)
++ lwz r0,_TRAP(r1)
++ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
++ stw r0,_TRAP(r1) /* register set saved */
++ b sys_vfork
++
++ .globl ppc_clone
++ppc_clone:
++ SAVE_NVGPRS(r1)
++ lwz r0,_TRAP(r1)
++ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
++ stw r0,_TRAP(r1) /* register set saved */
++ b sys_clone
++
++ .globl ppc_swapcontext
++ppc_swapcontext:
++ SAVE_NVGPRS(r1)
++ lwz r0,_TRAP(r1)
++ rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
++ stw r0,_TRAP(r1) /* register set saved */
++ b sys_swapcontext
++
++/*
++ * Top-level page fault handling.
++ * This is in assembler because if do_page_fault tells us that
++ * it is a bad kernel page fault, we want to save the non-volatile
++ * registers before calling bad_page_fault.
++ */
++ .globl handle_page_fault
++handle_page_fault:
++ stw r4,_DAR(r1)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl do_page_fault
++ cmpwi r3,0
++ beq+ ret_from_except
++ SAVE_NVGPRS(r1)
++ lwz r0,_TRAP(r1)
++ clrrwi r0,r0,1
++ stw r0,_TRAP(r1)
++ mr r5,r3
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ lwz r4,_DAR(r1)
++ bl bad_page_fault
++ b ret_from_except_full
++
++/*
++ * This routine switches between two different tasks. The process
++ * state of one is saved on its kernel stack. Then the state
++ * of the other is restored from its kernel stack. The memory
++ * management hardware is updated to the second process's state.
++ * Finally, we can return to the second process.
++ * On entry, r3 points to the THREAD for the current task, r4
++ * points to the THREAD for the new task.
++ *
++ * This routine is always called with interrupts disabled.
++ *
++ * Note: there are two ways to get to the "going out" portion
++ * of this code; either by coming in via the entry (_switch)
++ * or via "fork" which must set up an environment equivalent
++ * to the "_switch" path. If you change this , you'll have to
++ * change the fork code also.
++ *
++ * The code which creates the new task context is in 'copy_thread'
++ * in arch/ppc/kernel/process.c
++ */
++_GLOBAL(_switch)
++ stwu r1,-INT_FRAME_SIZE(r1)
++ mflr r0
++ stw r0,INT_FRAME_SIZE+4(r1)
++ /* r3-r12 are caller saved -- Cort */
++ SAVE_NVGPRS(r1)
++ stw r0,_NIP(r1) /* Return to switch caller */
++ mfmsr r11
++ li r0,MSR_FP /* Disable floating-point */
++#ifdef CONFIG_ALTIVEC
++BEGIN_FTR_SECTION
++ oris r0,r0,MSR_VEC at h /* Disable altivec */
++ mfspr r12,SPRN_VRSAVE /* save vrsave register value */
++ stw r12,THREAD+THREAD_VRSAVE(r2)
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ oris r0,r0,MSR_SPE at h /* Disable SPE */
++ mfspr r12,SPRN_SPEFSCR /* save spefscr register value */
++ stw r12,THREAD+THREAD_SPEFSCR(r2)
++#endif /* CONFIG_SPE */
++ and. r0,r0,r11 /* FP or altivec or SPE enabled? */
++ beq+ 1f
++ andc r11,r11,r0
++ MTMSRD(r11)
++ isync
++1: stw r11,_MSR(r1)
++ mfcr r10
++ stw r10,_CCR(r1)
++ stw r1,KSP(r3) /* Set old stack pointer */
++
++#ifdef CONFIG_SMP
++ /* We need a sync somewhere here to make sure that if the
++ * previous task gets rescheduled on another CPU, it sees all
++ * stores it has performed on this one.
++ */
++ sync
++#endif /* CONFIG_SMP */
++
++ tophys(r0,r4)
++ CLR_TOP32(r0)
++ mtspr SPRN_SPRG3,r0 /* Update current THREAD phys addr */
++ lwz r1,KSP(r4) /* Load new stack pointer */
++
++ /* save the old current 'last' for return value */
++ mr r3,r2
++ addi r2,r4,-THREAD /* Update current */
++
++#ifdef CONFIG_ALTIVEC
++BEGIN_FTR_SECTION
++ lwz r0,THREAD+THREAD_VRSAVE(r2)
++ mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ lwz r0,THREAD+THREAD_SPEFSCR(r2)
++ mtspr SPRN_SPEFSCR,r0 /* restore SPEFSCR reg */
++#endif /* CONFIG_SPE */
++
++ lwz r0,_CCR(r1)
++ mtcrf 0xFF,r0
++ /* r3-r12 are destroyed -- Cort */
++ REST_NVGPRS(r1)
++
++ lwz r4,_NIP(r1) /* Return to _switch caller in new task */
++ mtlr r4
++ addi r1,r1,INT_FRAME_SIZE
++ blr
++
++ .globl fast_exception_return
++fast_exception_return:
++#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
++ andi. r10,r9,MSR_RI /* check for recoverable interrupt */
++ beq 1f /* if not, we've got problems */
++#endif
++
++2: REST_4GPRS(3, r11)
++ lwz r10,_CCR(r11)
++ REST_GPR(1, r11)
++ mtcr r10
++ lwz r10,_LINK(r11)
++ mtlr r10
++ REST_GPR(10, r11)
++ mtspr SPRN_SRR1,r9
++ mtspr SPRN_SRR0,r12
++ REST_GPR(9, r11)
++ REST_GPR(12, r11)
++ lwz r11,GPR11(r11)
++ SYNC
++ RFI
++
++#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
++/* check if the exception happened in a restartable section */
++1: lis r3,exc_exit_restart_end at ha
++ addi r3,r3,exc_exit_restart_end at l
++ cmplw r12,r3
++ bge 3f
++ lis r4,exc_exit_restart at ha
++ addi r4,r4,exc_exit_restart at l
++ cmplw r12,r4
++ blt 3f
++ lis r3,fee_restarts at ha
++ tophys(r3,r3)
++ lwz r5,fee_restarts at l(r3)
++ addi r5,r5,1
++ stw r5,fee_restarts at l(r3)
++ mr r12,r4 /* restart at exc_exit_restart */
++ b 2b
++
++ .comm fee_restarts,4
++
++/* aargh, a nonrecoverable interrupt, panic */
++/* aargh, we don't know which trap this is */
++/* but the 601 doesn't implement the RI bit, so assume it's OK */
++3:
++BEGIN_FTR_SECTION
++ b 2b
++END_FTR_SECTION_IFSET(CPU_FTR_601)
++ li r10,-1
++ stw r10,_TRAP(r11)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ lis r10,MSR_KERNEL at h
++ ori r10,r10,MSR_KERNEL at l
++ bl transfer_to_handler_full
++ .long nonrecoverable_exception
++ .long ret_from_except
++#endif
++
++ .globl sigreturn_exit
++sigreturn_exit:
++ subi r1,r3,STACK_FRAME_OVERHEAD
++ rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
++ lwz r9,TI_FLAGS(r12)
++ andi. r0,r9,_TIF_SYSCALL_T_OR_A
++ beq+ ret_from_except_full
++ bl do_syscall_trace_leave
++ /* fall through */
++
++ .globl ret_from_except_full
++ret_from_except_full:
++ REST_NVGPRS(r1)
++ /* fall through */
++
++ .globl ret_from_except
++ret_from_except:
++ /* Hard-disable interrupts so that current_thread_info()->flags
++ * can't change between when we test it and when we return
++ * from the interrupt. */
++ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
++ SYNC /* Some chip revs have problems here... */
++ MTMSRD(r10) /* disable interrupts */
++
++ lwz r3,_MSR(r1) /* Returning to user mode? */
++ andi. r0,r3,MSR_PR
++ beq resume_kernel
++
++user_exc_return: /* r10 contains MSR_KERNEL here */
++ /* Check current_thread_info()->flags */
++ rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
++ lwz r9,TI_FLAGS(r9)
++ andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED)
++ bne do_work
++
++restore_user:
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ /* Check whether this process has its own DBCR0 value. The single
++ step bit tells us that dbcr0 should be loaded. */
++ lwz r0,THREAD+THREAD_DBCR0(r2)
++ andis. r10,r0,DBCR0_IC at h
++ bnel- load_dbcr0
++#endif
++
++#ifdef CONFIG_PREEMPT
++ b restore
++
++/* N.B. the only way to get here is from the beq following ret_from_except. */
++resume_kernel:
++ /* check current_thread_info->preempt_count */
++ rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
++ lwz r0,TI_PREEMPT(r9)
++ cmpwi 0,r0,0 /* if non-zero, just restore regs and return */
++ bne restore
++ lwz r0,TI_FLAGS(r9)
++ andi. r0,r0,_TIF_NEED_RESCHED
++ beq+ restore
++ andi. r0,r3,MSR_EE /* interrupts off? */
++ beq restore /* don't schedule if so */
++1: bl preempt_schedule_irq
++ rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
++ lwz r3,TI_FLAGS(r9)
++ andi. r0,r3,_TIF_NEED_RESCHED
++ bne- 1b
++#else
++resume_kernel:
++#endif /* CONFIG_PREEMPT */
++
++ /* interrupts are hard-disabled at this point */
++restore:
++ lwz r0,GPR0(r1)
++ lwz r2,GPR2(r1)
++ REST_4GPRS(3, r1)
++ REST_2GPRS(7, r1)
++
++ lwz r10,_XER(r1)
++ lwz r11,_CTR(r1)
++ mtspr SPRN_XER,r10
++ mtctr r11
++
++ PPC405_ERR77(0,r1)
++ stwcx. r0,0,r1 /* to clear the reservation */
++
++#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
++ lwz r9,_MSR(r1)
++ andi. r10,r9,MSR_RI /* check if this exception occurred */
++ beql nonrecoverable /* at a bad place (MSR:RI = 0) */
++
++ lwz r10,_CCR(r1)
++ lwz r11,_LINK(r1)
++ mtcrf 0xFF,r10
++ mtlr r11
++
++ /*
++ * Once we put values in SRR0 and SRR1, we are in a state
++ * where exceptions are not recoverable, since taking an
++ * exception will trash SRR0 and SRR1. Therefore we clear the
++ * MSR:RI bit to indicate this. If we do take an exception,
++ * we can't return to the point of the exception but we
++ * can restart the exception exit path at the label
++ * exc_exit_restart below. -- paulus
++ */
++ LOAD_MSR_KERNEL(r10,MSR_KERNEL & ~MSR_RI)
++ SYNC
++ MTMSRD(r10) /* clear the RI bit */
++ .globl exc_exit_restart
++exc_exit_restart:
++ lwz r9,_MSR(r1)
++ lwz r12,_NIP(r1)
++ FIX_SRR1(r9,r10)
++ mtspr SPRN_SRR0,r12
++ mtspr SPRN_SRR1,r9
++ REST_4GPRS(9, r1)
++ lwz r1,GPR1(r1)
++ .globl exc_exit_restart_end
++exc_exit_restart_end:
++ SYNC
++ RFI
++
++#else /* !(CONFIG_4xx || CONFIG_BOOKE) */
++ /*
++ * This is a bit different on 4xx/Book-E because it doesn't have
++ * the RI bit in the MSR.
++ * The TLB miss handler checks if we have interrupted
++ * the exception exit path and restarts it if so
++ * (well maybe one day it will... :).
++ */
++ lwz r11,_LINK(r1)
++ mtlr r11
++ lwz r10,_CCR(r1)
++ mtcrf 0xff,r10
++ REST_2GPRS(9, r1)
++ .globl exc_exit_restart
++exc_exit_restart:
++ lwz r11,_NIP(r1)
++ lwz r12,_MSR(r1)
++exc_exit_start:
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r12
++ REST_2GPRS(11, r1)
++ lwz r1,GPR1(r1)
++ .globl exc_exit_restart_end
++exc_exit_restart_end:
++ PPC405_ERR77_SYNC
++ rfi
++ b . /* prevent prefetch past rfi */
++
++/*
++ * Returning from a critical interrupt in user mode doesn't need
++ * to be any different from a normal exception. For a critical
++ * interrupt in the kernel, we just return (without checking for
++ * preemption) since the interrupt may have happened at some crucial
++ * place (e.g. inside the TLB miss handler), and because we will be
++ * running with r1 pointing into critical_stack, not the current
++ * process's kernel stack (and therefore current_thread_info() will
++ * give the wrong answer).
++ * We have to restore various SPRs that may have been in use at the
++ * time of the critical interrupt.
++ *
++ */
++#ifdef CONFIG_40x
++#define PPC_40x_TURN_OFF_MSR_DR \
++ /* avoid any possible TLB misses here by turning off MSR.DR, we \
++ * assume the instructions here are mapped by a pinned TLB entry */ \
++ li r10,MSR_IR; \
++ mtmsr r10; \
++ isync; \
++ tophys(r1, r1);
++#else
++#define PPC_40x_TURN_OFF_MSR_DR
++#endif
++
++#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi) \
++ REST_NVGPRS(r1); \
++ lwz r3,_MSR(r1); \
++ andi. r3,r3,MSR_PR; \
++ LOAD_MSR_KERNEL(r10,MSR_KERNEL); \
++ bne user_exc_return; \
++ lwz r0,GPR0(r1); \
++ lwz r2,GPR2(r1); \
++ REST_4GPRS(3, r1); \
++ REST_2GPRS(7, r1); \
++ lwz r10,_XER(r1); \
++ lwz r11,_CTR(r1); \
++ mtspr SPRN_XER,r10; \
++ mtctr r11; \
++ PPC405_ERR77(0,r1); \
++ stwcx. r0,0,r1; /* to clear the reservation */ \
++ lwz r11,_LINK(r1); \
++ mtlr r11; \
++ lwz r10,_CCR(r1); \
++ mtcrf 0xff,r10; \
++ PPC_40x_TURN_OFF_MSR_DR; \
++ lwz r9,_DEAR(r1); \
++ lwz r10,_ESR(r1); \
++ mtspr SPRN_DEAR,r9; \
++ mtspr SPRN_ESR,r10; \
++ lwz r11,_NIP(r1); \
++ lwz r12,_MSR(r1); \
++ mtspr exc_lvl_srr0,r11; \
++ mtspr exc_lvl_srr1,r12; \
++ lwz r9,GPR9(r1); \
++ lwz r12,GPR12(r1); \
++ lwz r10,GPR10(r1); \
++ lwz r11,GPR11(r1); \
++ lwz r1,GPR1(r1); \
++ PPC405_ERR77_SYNC; \
++ exc_lvl_rfi; \
++ b .; /* prevent prefetch past exc_lvl_rfi */
++
++ .globl ret_from_crit_exc
++ret_from_crit_exc:
++ RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
++
++#ifdef CONFIG_BOOKE
++ .globl ret_from_debug_exc
++ret_from_debug_exc:
++ RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
++
++ .globl ret_from_mcheck_exc
++ret_from_mcheck_exc:
++ RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
++#endif /* CONFIG_BOOKE */
++
++/*
++ * Load the DBCR0 value for a task that is being ptraced,
++ * having first saved away the global DBCR0. Note that r0
++ * has the dbcr0 value to set upon entry to this.
++ */
++load_dbcr0:
++ mfmsr r10 /* first disable debug exceptions */
++ rlwinm r10,r10,0,~MSR_DE
++ mtmsr r10
++ isync
++ mfspr r10,SPRN_DBCR0
++ lis r11,global_dbcr0 at ha
++ addi r11,r11,global_dbcr0 at l
++ stw r10,0(r11)
++ mtspr SPRN_DBCR0,r0
++ lwz r10,4(r11)
++ addi r10,r10,1
++ stw r10,4(r11)
++ li r11,-1
++ mtspr SPRN_DBSR,r11 /* clear all pending debug events */
++ blr
++
++ .comm global_dbcr0,8
++#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
++
++do_work: /* r10 contains MSR_KERNEL here */
++ andi. r0,r9,_TIF_NEED_RESCHED
++ beq do_user_signal
++
++do_resched: /* r10 contains MSR_KERNEL here */
++ ori r10,r10,MSR_EE
++ SYNC
++ MTMSRD(r10) /* hard-enable interrupts */
++ bl schedule
++recheck:
++ LOAD_MSR_KERNEL(r10,MSR_KERNEL)
++ SYNC
++ MTMSRD(r10) /* disable interrupts */
++ rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
++ lwz r9,TI_FLAGS(r9)
++ andi. r0,r9,_TIF_NEED_RESCHED
++ bne- do_resched
++ andi. r0,r9,_TIF_SIGPENDING
++ beq restore_user
++do_user_signal: /* r10 contains MSR_KERNEL here */
++ ori r10,r10,MSR_EE
++ SYNC
++ MTMSRD(r10) /* hard-enable interrupts */
++ /* save r13-r31 in the exception frame, if not already done */
++ lwz r3,_TRAP(r1)
++ andi. r0,r3,1
++ beq 2f
++ SAVE_NVGPRS(r1)
++ rlwinm r3,r3,0,0,30
++ stw r3,_TRAP(r1)
++2: li r3,0
++ addi r4,r1,STACK_FRAME_OVERHEAD
++ bl do_signal
++ REST_NVGPRS(r1)
++ b recheck
++
++/*
++ * We come here when we are at the end of handling an exception
++ * that occurred at a place where taking an exception will lose
++ * state information, such as the contents of SRR0 and SRR1.
++ */
++nonrecoverable:
++ lis r10,exc_exit_restart_end at ha
++ addi r10,r10,exc_exit_restart_end at l
++ cmplw r12,r10
++ bge 3f
++ lis r11,exc_exit_restart at ha
++ addi r11,r11,exc_exit_restart at l
++ cmplw r12,r11
++ blt 3f
++ lis r10,ee_restarts at ha
++ lwz r12,ee_restarts at l(r10)
++ addi r12,r12,1
++ stw r12,ee_restarts at l(r10)
++ mr r12,r11 /* restart at exc_exit_restart */
++ blr
++3: /* OK, we can't recover, kill this process */
++ /* but the 601 doesn't implement the RI bit, so assume it's OK */
++BEGIN_FTR_SECTION
++ blr
++END_FTR_SECTION_IFSET(CPU_FTR_601)
++ lwz r3,_TRAP(r1)
++ andi. r0,r3,1
++ beq 4f
++ SAVE_NVGPRS(r1)
++ rlwinm r3,r3,0,0,30
++ stw r3,_TRAP(r1)
++4: addi r3,r1,STACK_FRAME_OVERHEAD
++ bl nonrecoverable_exception
++ /* shouldn't return */
++ b 4b
++
++ .comm ee_restarts,4
++
++/*
++ * PROM code for specific machines follows. Put it
++ * here so it's easy to add arch-specific sections later.
++ * -- Cort
++ */
++#ifdef CONFIG_PPC_RTAS
++/*
++ * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
++ * called with the MMU off.
++ */
++_GLOBAL(enter_rtas)
++ stwu r1,-INT_FRAME_SIZE(r1)
++ mflr r0
++ stw r0,INT_FRAME_SIZE+4(r1)
++ LOADADDR(r4, rtas)
++ lis r6,1f at ha /* physical return address for rtas */
++ addi r6,r6,1f at l
++ tophys(r6,r6)
++ tophys(r7,r1)
++ lwz r8,RTASENTRY(r4)
++ lwz r4,RTASBASE(r4)
++ mfmsr r9
++ stw r9,8(r1)
++ LOAD_MSR_KERNEL(r0,MSR_KERNEL)
++ SYNC /* disable interrupts so SRR0/1 */
++ MTMSRD(r0) /* don't get trashed */
++ li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
++ mtlr r6
++ mtspr SPRN_SPRG2,r7
++ mtspr SPRN_SRR0,r8
++ mtspr SPRN_SRR1,r9
++ RFI
++1: tophys(r9,r1)
++ lwz r8,INT_FRAME_SIZE+4(r9) /* get return address */
++ lwz r9,8(r9) /* original msr value */
++ FIX_SRR1(r9,r0)
++ addi r1,r1,INT_FRAME_SIZE
++ li r0,0
++ mtspr SPRN_SPRG2,r0
++ mtspr SPRN_SRR0,r8
++ mtspr SPRN_SRR1,r9
++ RFI /* return to caller */
++
++ .globl machine_check_in_rtas
++machine_check_in_rtas:
++ twi 31,0,0
++ /* XXX load up BATs and panic */
++
++#endif /* CONFIG_PPC_RTAS */
+diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/entry_64.S
+@@ -0,0 +1,842 @@
++/*
++ * arch/ppc64/kernel/entry.S
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ * Rewritten by Cort Dougan (cort at cs.nmt.edu) for PReP
++ * Copyright (C) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Adapted for Power Macintosh by Paul Mackerras.
++ * Low-level exception handlers and MMU support
++ * rewritten by Paul Mackerras.
++ * Copyright (C) 1996 Paul Mackerras.
++ * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek at jlc.net).
++ *
++ * This file contains the system call entry code, context switch
++ * code, and exception/interrupt return code for PowerPC.
++ *
++ * 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/errno.h>
++#include <asm/unistd.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/cputable.h>
++
++#ifdef CONFIG_PPC_ISERIES
++#define DO_SOFT_DISABLE
++#endif
++
++/*
++ * System calls.
++ */
++ .section ".toc","aw"
++.SYS_CALL_TABLE:
++ .tc .sys_call_table[TC],.sys_call_table
++
++/* This value is used to mark exception frames on the stack. */
++exception_marker:
++ .tc ID_72656773_68657265[TC],0x7265677368657265
++
++ .section ".text"
++ .align 7
++
++#undef SHOW_SYSCALLS
++
++ .globl system_call_common
++system_call_common:
++ andi. r10,r12,MSR_PR
++ mr r10,r1
++ addi r1,r1,-INT_FRAME_SIZE
++ beq- 1f
++ ld r1,PACAKSAVE(r13)
++1: std r10,0(r1)
++ std r11,_NIP(r1)
++ std r12,_MSR(r1)
++ std r0,GPR0(r1)
++ std r10,GPR1(r1)
++ std r2,GPR2(r1)
++ std r3,GPR3(r1)
++ std r4,GPR4(r1)
++ std r5,GPR5(r1)
++ std r6,GPR6(r1)
++ std r7,GPR7(r1)
++ std r8,GPR8(r1)
++ li r11,0
++ std r11,GPR9(r1)
++ std r11,GPR10(r1)
++ std r11,GPR11(r1)
++ std r11,GPR12(r1)
++ std r9,GPR13(r1)
++ crclr so
++ mfcr r9
++ mflr r10
++ li r11,0xc01
++ std r9,_CCR(r1)
++ std r10,_LINK(r1)
++ std r11,_TRAP(r1)
++ mfxer r9
++ mfctr r10
++ std r9,_XER(r1)
++ std r10,_CTR(r1)
++ std r3,ORIG_GPR3(r1)
++ ld r2,PACATOC(r13)
++ addi r9,r1,STACK_FRAME_OVERHEAD
++ ld r11,exception_marker at toc(r2)
++ std r11,-16(r9) /* "regshere" marker */
++#ifdef CONFIG_PPC_ISERIES
++ /* Hack for handling interrupts when soft-enabling on iSeries */
++ cmpdi cr1,r0,0x5555 /* syscall 0x5555 */
++ andi. r10,r12,MSR_PR /* from kernel */
++ crand 4*cr0+eq,4*cr1+eq,4*cr0+eq
++ beq hardware_interrupt_entry
++ lbz r10,PACAPROCENABLED(r13)
++ std r10,SOFTE(r1)
++#endif
++ mfmsr r11
++ ori r11,r11,MSR_EE
++ mtmsrd r11,1
++
++#ifdef SHOW_SYSCALLS
++ bl .do_show_syscall
++ REST_GPR(0,r1)
++ REST_4GPRS(3,r1)
++ REST_2GPRS(7,r1)
++ addi r9,r1,STACK_FRAME_OVERHEAD
++#endif
++ clrrdi r11,r1,THREAD_SHIFT
++ li r12,0
++ ld r10,TI_FLAGS(r11)
++ stb r12,TI_SC_NOERR(r11)
++ andi. r11,r10,_TIF_SYSCALL_T_OR_A
++ bne- syscall_dotrace
++syscall_dotrace_cont:
++ cmpldi 0,r0,NR_syscalls
++ bge- syscall_enosys
++
++system_call: /* label this so stack traces look sane */
++/*
++ * Need to vector to 32 Bit or default sys_call_table here,
++ * based on caller's run-mode / personality.
++ */
++ ld r11,.SYS_CALL_TABLE at toc(2)
++ andi. r10,r10,_TIF_32BIT
++ beq 15f
++ addi r11,r11,8 /* use 32-bit syscall entries */
++ clrldi r3,r3,32
++ clrldi r4,r4,32
++ clrldi r5,r5,32
++ clrldi r6,r6,32
++ clrldi r7,r7,32
++ clrldi r8,r8,32
++15:
++ slwi r0,r0,4
++ ldx r10,r11,r0 /* Fetch system call handler [ptr] */
++ mtctr r10
++ bctrl /* Call handler */
++
++syscall_exit:
++#ifdef SHOW_SYSCALLS
++ std r3,GPR3(r1)
++ bl .do_show_syscall_exit
++ ld r3,GPR3(r1)
++#endif
++ std r3,RESULT(r1)
++ ld r5,_CCR(r1)
++ li r10,-_LAST_ERRNO
++ cmpld r3,r10
++ clrrdi r12,r1,THREAD_SHIFT
++ bge- syscall_error
++syscall_error_cont:
++
++ /* check for syscall tracing or audit */
++ ld r9,TI_FLAGS(r12)
++ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
++ bne- syscall_exit_trace
++syscall_exit_trace_cont:
++
++ /* disable interrupts so current_thread_info()->flags can't change,
++ and so that we don't get interrupted after loading SRR0/1. */
++ ld r8,_MSR(r1)
++ andi. r10,r8,MSR_RI
++ beq- unrecov_restore
++ mfmsr r10
++ rldicl r10,r10,48,1
++ rotldi r10,r10,16
++ mtmsrd r10,1
++ ld r9,TI_FLAGS(r12)
++ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
++ bne- syscall_exit_work
++ ld r7,_NIP(r1)
++ stdcx. r0,0,r1 /* to clear the reservation */
++ andi. r6,r8,MSR_PR
++ ld r4,_LINK(r1)
++ beq- 1f /* only restore r13 if */
++ ld r13,GPR13(r1) /* returning to usermode */
++1: ld r2,GPR2(r1)
++ li r12,MSR_RI
++ andc r10,r10,r12
++ mtmsrd r10,1 /* clear MSR.RI */
++ ld r1,GPR1(r1)
++ mtlr r4
++ mtcr r5
++ mtspr SPRN_SRR0,r7
++ mtspr SPRN_SRR1,r8
++ rfid
++ b . /* prevent speculative execution */
++
++syscall_enosys:
++ li r3,-ENOSYS
++ std r3,RESULT(r1)
++ clrrdi r12,r1,THREAD_SHIFT
++ ld r5,_CCR(r1)
++
++syscall_error:
++ lbz r11,TI_SC_NOERR(r12)
++ cmpwi 0,r11,0
++ bne- syscall_error_cont
++ neg r3,r3
++ oris r5,r5,0x1000 /* Set SO bit in CR */
++ std r5,_CCR(r1)
++ b syscall_error_cont
++
++/* Traced system call support */
++syscall_dotrace:
++ bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .do_syscall_trace_enter
++ ld r0,GPR0(r1) /* Restore original registers */
++ ld r3,GPR3(r1)
++ ld r4,GPR4(r1)
++ ld r5,GPR5(r1)
++ ld r6,GPR6(r1)
++ ld r7,GPR7(r1)
++ ld r8,GPR8(r1)
++ addi r9,r1,STACK_FRAME_OVERHEAD
++ clrrdi r10,r1,THREAD_SHIFT
++ ld r10,TI_FLAGS(r10)
++ b syscall_dotrace_cont
++
++syscall_exit_trace:
++ std r3,GPR3(r1)
++ bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .do_syscall_trace_leave
++ REST_NVGPRS(r1)
++ ld r3,GPR3(r1)
++ ld r5,_CCR(r1)
++ clrrdi r12,r1,THREAD_SHIFT
++ b syscall_exit_trace_cont
++
++/* Stuff to do on exit from a system call. */
++syscall_exit_work:
++ std r3,GPR3(r1)
++ std r5,_CCR(r1)
++ b .ret_from_except_lite
++
++/* Save non-volatile GPRs, if not already saved. */
++_GLOBAL(save_nvgprs)
++ ld r11,_TRAP(r1)
++ andi. r0,r11,1
++ beqlr-
++ SAVE_NVGPRS(r1)
++ clrrdi r0,r11,1
++ std r0,_TRAP(r1)
++ blr
++
++/*
++ * The sigsuspend and rt_sigsuspend system calls can call do_signal
++ * and thus put the process into the stopped state where we might
++ * want to examine its user state with ptrace. Therefore we need
++ * to save all the nonvolatile registers (r14 - r31) before calling
++ * the C code. Similarly, fork, vfork and clone need the full
++ * register state on the stack so that it can be copied to the child.
++ */
++_GLOBAL(ppc32_sigsuspend)
++ bl .save_nvgprs
++ bl .compat_sys_sigsuspend
++ b 70f
++
++_GLOBAL(ppc64_rt_sigsuspend)
++ bl .save_nvgprs
++ bl .sys_rt_sigsuspend
++ b 70f
++
++_GLOBAL(ppc32_rt_sigsuspend)
++ bl .save_nvgprs
++ bl .compat_sys_rt_sigsuspend
++70: cmpdi 0,r3,0
++ /* If it returned an error, we need to return via syscall_exit to set
++ the SO bit in cr0 and potentially stop for ptrace. */
++ bne syscall_exit
++ /* If sigsuspend() returns zero, we are going into a signal handler. We
++ may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
++#ifdef CONFIG_AUDITSYSCALL
++ ld r3,PACACURRENT(r13)
++ ld r4,AUDITCONTEXT(r3)
++ cmpdi 0,r4,0
++ beq .ret_from_except /* No audit_context: Leave immediately. */
++ li r4, 2 /* AUDITSC_FAILURE */
++ li r5,-4 /* It's always -EINTR */
++ bl .audit_syscall_exit
++#endif
++ b .ret_from_except
++
++_GLOBAL(ppc_fork)
++ bl .save_nvgprs
++ bl .sys_fork
++ b syscall_exit
++
++_GLOBAL(ppc_vfork)
++ bl .save_nvgprs
++ bl .sys_vfork
++ b syscall_exit
++
++_GLOBAL(ppc_clone)
++ bl .save_nvgprs
++ bl .sys_clone
++ b syscall_exit
++
++_GLOBAL(ppc32_swapcontext)
++ bl .save_nvgprs
++ bl .compat_sys_swapcontext
++ b 80f
++
++_GLOBAL(ppc64_swapcontext)
++ bl .save_nvgprs
++ bl .sys_swapcontext
++ b 80f
++
++_GLOBAL(ppc32_sigreturn)
++ bl .compat_sys_sigreturn
++ b 80f
++
++_GLOBAL(ppc32_rt_sigreturn)
++ bl .compat_sys_rt_sigreturn
++ b 80f
++
++_GLOBAL(ppc64_rt_sigreturn)
++ bl .sys_rt_sigreturn
++
++80: cmpdi 0,r3,0
++ blt syscall_exit
++ clrrdi r4,r1,THREAD_SHIFT
++ ld r4,TI_FLAGS(r4)
++ andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
++ beq+ 81f
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .do_syscall_trace_leave
++81: b .ret_from_except
++
++_GLOBAL(ret_from_fork)
++ bl .schedule_tail
++ REST_NVGPRS(r1)
++ li r3,0
++ b syscall_exit
++
++/*
++ * This routine switches between two different tasks. The process
++ * state of one is saved on its kernel stack. Then the state
++ * of the other is restored from its kernel stack. The memory
++ * management hardware is updated to the second process's state.
++ * Finally, we can return to the second process, via ret_from_except.
++ * On entry, r3 points to the THREAD for the current task, r4
++ * points to the THREAD for the new task.
++ *
++ * Note: there are two ways to get to the "going out" portion
++ * of this code; either by coming in via the entry (_switch)
++ * or via "fork" which must set up an environment equivalent
++ * to the "_switch" path. If you change this you'll have to change
++ * the fork code also.
++ *
++ * The code which creates the new task context is in 'copy_thread'
++ * in arch/ppc64/kernel/process.c
++ */
++ .align 7
++_GLOBAL(_switch)
++ mflr r0
++ std r0,16(r1)
++ stdu r1,-SWITCH_FRAME_SIZE(r1)
++ /* r3-r13 are caller saved -- Cort */
++ SAVE_8GPRS(14, r1)
++ SAVE_10GPRS(22, r1)
++ mflr r20 /* Return to switch caller */
++ mfmsr r22
++ li r0, MSR_FP
++#ifdef CONFIG_ALTIVEC
++BEGIN_FTR_SECTION
++ oris r0,r0,MSR_VEC at h /* Disable altivec */
++ mfspr r24,SPRN_VRSAVE /* save vrsave register value */
++ std r24,THREAD_VRSAVE(r3)
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++#endif /* CONFIG_ALTIVEC */
++ and. r0,r0,r22
++ beq+ 1f
++ andc r22,r22,r0
++ mtmsrd r22
++ isync
++1: std r20,_NIP(r1)
++ mfcr r23
++ std r23,_CCR(r1)
++ std r1,KSP(r3) /* Set old stack pointer */
++
++#ifdef CONFIG_SMP
++ /* We need a sync somewhere here to make sure that if the
++ * previous task gets rescheduled on another CPU, it sees all
++ * stores it has performed on this one.
++ */
++ sync
++#endif /* CONFIG_SMP */
++
++ addi r6,r4,-THREAD /* Convert THREAD to 'current' */
++ std r6,PACACURRENT(r13) /* Set new 'current' */
++
++ ld r8,KSP(r4) /* new stack pointer */
++BEGIN_FTR_SECTION
++ clrrdi r6,r8,28 /* get its ESID */
++ clrrdi r9,r1,28 /* get current sp ESID */
++ clrldi. r0,r6,2 /* is new ESID c00000000? */
++ cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */
++ cror eq,4*cr1+eq,eq
++ beq 2f /* if yes, don't slbie it */
++
++ /* Bolt in the new stack SLB entry */
++ ld r7,KSP_VSID(r4) /* Get new stack's VSID */
++ oris r0,r6,(SLB_ESID_V)@h
++ ori r0,r0,(SLB_NUM_BOLTED-1)@l
++ slbie r6
++ slbie r6 /* Workaround POWER5 < DD2.1 issue */
++ slbmte r7,r0
++ isync
++
++2:
++END_FTR_SECTION_IFSET(CPU_FTR_SLB)
++ clrrdi r7,r8,THREAD_SHIFT /* base of new stack */
++ /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
++ because we don't need to leave the 288-byte ABI gap at the
++ top of the kernel stack. */
++ addi r7,r7,THREAD_SIZE-SWITCH_FRAME_SIZE
++
++ mr r1,r8 /* start using new stack pointer */
++ std r7,PACAKSAVE(r13)
++
++ ld r6,_CCR(r1)
++ mtcrf 0xFF,r6
++
++#ifdef CONFIG_ALTIVEC
++BEGIN_FTR_SECTION
++ ld r0,THREAD_VRSAVE(r4)
++ mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++#endif /* CONFIG_ALTIVEC */
++
++ /* r3-r13 are destroyed -- Cort */
++ REST_8GPRS(14, r1)
++ REST_10GPRS(22, r1)
++
++ /* convert old thread to its task_struct for return value */
++ addi r3,r3,-THREAD
++ ld r7,_NIP(r1) /* Return to _switch caller in new task */
++ mtlr r7
++ addi r1,r1,SWITCH_FRAME_SIZE
++ blr
++
++ .align 7
++_GLOBAL(ret_from_except)
++ ld r11,_TRAP(r1)
++ andi. r0,r11,1
++ bne .ret_from_except_lite
++ REST_NVGPRS(r1)
++
++_GLOBAL(ret_from_except_lite)
++ /*
++ * Disable interrupts so that current_thread_info()->flags
++ * can't change between when we test it and when we return
++ * from the interrupt.
++ */
++ mfmsr r10 /* Get current interrupt state */
++ rldicl r9,r10,48,1 /* clear MSR_EE */
++ rotldi r9,r9,16
++ mtmsrd r9,1 /* Update machine state */
++
++#ifdef CONFIG_PREEMPT
++ clrrdi r9,r1,THREAD_SHIFT /* current_thread_info() */
++ li r0,_TIF_NEED_RESCHED /* bits to check */
++ ld r3,_MSR(r1)
++ ld r4,TI_FLAGS(r9)
++ /* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */
++ rlwimi r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING
++ and. r0,r4,r0 /* check NEED_RESCHED and maybe SIGPENDING */
++ bne do_work
++
++#else /* !CONFIG_PREEMPT */
++ ld r3,_MSR(r1) /* Returning to user mode? */
++ andi. r3,r3,MSR_PR
++ beq restore /* if not, just restore regs and return */
++
++ /* Check current_thread_info()->flags */
++ clrrdi r9,r1,THREAD_SHIFT
++ ld r4,TI_FLAGS(r9)
++ andi. r0,r4,_TIF_USER_WORK_MASK
++ bne do_work
++#endif
++
++restore:
++#ifdef CONFIG_PPC_ISERIES
++ ld r5,SOFTE(r1)
++ cmpdi 0,r5,0
++ beq 4f
++ /* Check for pending interrupts (iSeries) */
++ ld r3,PACALPPACA+LPPACAANYINT(r13)
++ cmpdi r3,0
++ beq+ 4f /* skip do_IRQ if no interrupts */
++
++ li r3,0
++ stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */
++ ori r10,r10,MSR_EE
++ mtmsrd r10 /* hard-enable again */
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .do_IRQ
++ b .ret_from_except_lite /* loop back and handle more */
++
++4: stb r5,PACAPROCENABLED(r13)
++#endif
++
++ ld r3,_MSR(r1)
++ andi. r0,r3,MSR_RI
++ beq- unrecov_restore
++
++ andi. r0,r3,MSR_PR
++
++ /*
++ * r13 is our per cpu area, only restore it if we are returning to
++ * userspace
++ */
++ beq 1f
++ REST_GPR(13, r1)
++1:
++ ld r3,_CTR(r1)
++ ld r0,_LINK(r1)
++ mtctr r3
++ mtlr r0
++ ld r3,_XER(r1)
++ mtspr SPRN_XER,r3
++
++ REST_8GPRS(5, r1)
++
++ stdcx. r0,0,r1 /* to clear the reservation */
++
++ mfmsr r0
++ li r2, MSR_RI
++ andc r0,r0,r2
++ mtmsrd r0,1
++
++ ld r0,_MSR(r1)
++ mtspr SPRN_SRR1,r0
++
++ ld r2,_CCR(r1)
++ mtcrf 0xFF,r2
++ ld r2,_NIP(r1)
++ mtspr SPRN_SRR0,r2
++
++ ld r0,GPR0(r1)
++ ld r2,GPR2(r1)
++ ld r3,GPR3(r1)
++ ld r4,GPR4(r1)
++ ld r1,GPR1(r1)
++
++ rfid
++ b . /* prevent speculative execution */
++
++/* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */
++do_work:
++#ifdef CONFIG_PREEMPT
++ andi. r0,r3,MSR_PR /* Returning to user mode? */
++ bne user_work
++ /* Check that preempt_count() == 0 and interrupts are enabled */
++ lwz r8,TI_PREEMPT(r9)
++ cmpwi cr1,r8,0
++#ifdef CONFIG_PPC_ISERIES
++ ld r0,SOFTE(r1)
++ cmpdi r0,0
++#else
++ andi. r0,r3,MSR_EE
++#endif
++ crandc eq,cr1*4+eq,eq
++ bne restore
++ /* here we are preempting the current task */
++1:
++#ifdef CONFIG_PPC_ISERIES
++ li r0,1
++ stb r0,PACAPROCENABLED(r13)
++#endif
++ ori r10,r10,MSR_EE
++ mtmsrd r10,1 /* reenable interrupts */
++ bl .preempt_schedule
++ mfmsr r10
++ clrrdi r9,r1,THREAD_SHIFT
++ rldicl r10,r10,48,1 /* disable interrupts again */
++ rotldi r10,r10,16
++ mtmsrd r10,1
++ ld r4,TI_FLAGS(r9)
++ andi. r0,r4,_TIF_NEED_RESCHED
++ bne 1b
++ b restore
++
++user_work:
++#endif
++ /* Enable interrupts */
++ ori r10,r10,MSR_EE
++ mtmsrd r10,1
++
++ andi. r0,r4,_TIF_NEED_RESCHED
++ beq 1f
++ bl .schedule
++ b .ret_from_except_lite
++
++1: bl .save_nvgprs
++ li r3,0
++ addi r4,r1,STACK_FRAME_OVERHEAD
++ bl .do_signal
++ b .ret_from_except
++
++unrecov_restore:
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .unrecoverable_exception
++ b unrecov_restore
++
++#ifdef CONFIG_PPC_RTAS
++/*
++ * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
++ * called with the MMU off.
++ *
++ * In addition, we need to be in 32b mode, at least for now.
++ *
++ * Note: r3 is an input parameter to rtas, so don't trash it...
++ */
++_GLOBAL(enter_rtas)
++ mflr r0
++ std r0,16(r1)
++ stdu r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */
++
++ /* Because RTAS is running in 32b mode, it clobbers the high order half
++ * of all registers that it saves. We therefore save those registers
++ * RTAS might touch to the stack. (r0, r3-r13 are caller saved)
++ */
++ SAVE_GPR(2, r1) /* Save the TOC */
++ SAVE_GPR(13, r1) /* Save paca */
++ SAVE_8GPRS(14, r1) /* Save the non-volatiles */
++ SAVE_10GPRS(22, r1) /* ditto */
++
++ mfcr r4
++ std r4,_CCR(r1)
++ mfctr r5
++ std r5,_CTR(r1)
++ mfspr r6,SPRN_XER
++ std r6,_XER(r1)
++ mfdar r7
++ std r7,_DAR(r1)
++ mfdsisr r8
++ std r8,_DSISR(r1)
++ mfsrr0 r9
++ std r9,_SRR0(r1)
++ mfsrr1 r10
++ std r10,_SRR1(r1)
++
++ /* There is no way it is acceptable to get here with interrupts enabled,
++ * check it with the asm equivalent of WARN_ON
++ */
++ mfmsr r6
++ andi. r0,r6,MSR_EE
++1: tdnei r0,0
++.section __bug_table,"a"
++ .llong 1b,__LINE__ + 0x1000000, 1f, 2f
++.previous
++.section .rodata,"a"
++1: .asciz __FILE__
++2: .asciz "enter_rtas"
++.previous
++
++ /* Unfortunately, the stack pointer and the MSR are also clobbered,
++ * so they are saved in the PACA which allows us to restore
++ * our original state after RTAS returns.
++ */
++ std r1,PACAR1(r13)
++ std r6,PACASAVEDMSR(r13)
++
++ /* Setup our real return addr */
++ SET_REG_TO_LABEL(r4,.rtas_return_loc)
++ SET_REG_TO_CONST(r9,KERNELBASE)
++ sub r4,r4,r9
++ mtlr r4
++
++ li r0,0
++ ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_RI
++ andc r0,r6,r0
++
++ li r9,1
++ rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
++ ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP
++ andc r6,r0,r9
++ ori r6,r6,MSR_RI
++ sync /* disable interrupts so SRR0/1 */
++ mtmsrd r0 /* don't get trashed */
++
++ SET_REG_TO_LABEL(r4,rtas)
++ ld r5,RTASENTRY(r4) /* get the rtas->entry value */
++ ld r4,RTASBASE(r4) /* get the rtas->base value */
++
++ mtspr SPRN_SRR0,r5
++ mtspr SPRN_SRR1,r6
++ rfid
++ b . /* prevent speculative execution */
++
++_STATIC(rtas_return_loc)
++ /* relocation is off at this point */
++ mfspr r4,SPRN_SPRG3 /* Get PACA */
++ SET_REG_TO_CONST(r5, KERNELBASE)
++ sub r4,r4,r5 /* RELOC the PACA base pointer */
++
++ mfmsr r6
++ li r0,MSR_RI
++ andc r6,r6,r0
++ sync
++ mtmsrd r6
++
++ ld r1,PACAR1(r4) /* Restore our SP */
++ LOADADDR(r3,.rtas_restore_regs)
++ ld r4,PACASAVEDMSR(r4) /* Restore our MSR */
++
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
++ rfid
++ b . /* prevent speculative execution */
++
++_STATIC(rtas_restore_regs)
++ /* relocation is on at this point */
++ REST_GPR(2, r1) /* Restore the TOC */
++ REST_GPR(13, r1) /* Restore paca */
++ REST_8GPRS(14, r1) /* Restore the non-volatiles */
++ REST_10GPRS(22, r1) /* ditto */
++
++ mfspr r13,SPRN_SPRG3
++
++ ld r4,_CCR(r1)
++ mtcr r4
++ ld r5,_CTR(r1)
++ mtctr r5
++ ld r6,_XER(r1)
++ mtspr SPRN_XER,r6
++ ld r7,_DAR(r1)
++ mtdar r7
++ ld r8,_DSISR(r1)
++ mtdsisr r8
++ ld r9,_SRR0(r1)
++ mtsrr0 r9
++ ld r10,_SRR1(r1)
++ mtsrr1 r10
++
++ addi r1,r1,RTAS_FRAME_SIZE /* Unstack our frame */
++ ld r0,16(r1) /* get return address */
++
++ mtlr r0
++ blr /* return to caller */
++
++#endif /* CONFIG_PPC_RTAS */
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++
++_GLOBAL(enter_prom)
++ mflr r0
++ std r0,16(r1)
++ stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
++
++ /* Because PROM is running in 32b mode, it clobbers the high order half
++ * of all registers that it saves. We therefore save those registers
++ * PROM might touch to the stack. (r0, r3-r13 are caller saved)
++ */
++ SAVE_8GPRS(2, r1)
++ SAVE_GPR(13, r1)
++ SAVE_8GPRS(14, r1)
++ SAVE_10GPRS(22, r1)
++ mfcr r4
++ std r4,_CCR(r1)
++ mfctr r5
++ std r5,_CTR(r1)
++ mfspr r6,SPRN_XER
++ std r6,_XER(r1)
++ mfdar r7
++ std r7,_DAR(r1)
++ mfdsisr r8
++ std r8,_DSISR(r1)
++ mfsrr0 r9
++ std r9,_SRR0(r1)
++ mfsrr1 r10
++ std r10,_SRR1(r1)
++ mfmsr r11
++ std r11,_MSR(r1)
++
++ /* Get the PROM entrypoint */
++ ld r0,GPR4(r1)
++ mtlr r0
++
++ /* Switch MSR to 32 bits mode
++ */
++ mfmsr r11
++ li r12,1
++ rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
++ andc r11,r11,r12
++ li r12,1
++ rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
++ andc r11,r11,r12
++ mtmsrd r11
++ isync
++
++ /* Restore arguments & enter PROM here... */
++ ld r3,GPR3(r1)
++ blrl
++
++ /* Just make sure that r1 top 32 bits didn't get
++ * corrupt by OF
++ */
++ rldicl r1,r1,0,32
++
++ /* Restore the MSR (back to 64 bits) */
++ ld r0,_MSR(r1)
++ mtmsrd r0
++ isync
++
++ /* Restore other registers */
++ REST_GPR(2, r1)
++ REST_GPR(13, r1)
++ REST_8GPRS(14, r1)
++ REST_10GPRS(22, r1)
++ ld r4,_CCR(r1)
++ mtcr r4
++ ld r5,_CTR(r1)
++ mtctr r5
++ ld r6,_XER(r1)
++ mtspr SPRN_XER,r6
++ ld r7,_DAR(r1)
++ mtdar r7
++ ld r8,_DSISR(r1)
++ mtdsisr r8
++ ld r9,_SRR0(r1)
++ mtsrr0 r9
++ ld r10,_SRR1(r1)
++ mtsrr1 r10
++
++ addi r1,r1,PROM_FRAME_SIZE
++ ld r0,16(r1)
++ mtlr r0
++ blr
++
++#endif /* CONFIG_PPC_MULTIPLATFORM */
+diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/fpu.S
+@@ -0,0 +1,144 @@
++/*
++ * FPU support code, moved here from head.S so that it can be used
++ * by chips which use other head-whatever.S files.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <asm/reg.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/cputable.h>
++#include <asm/cache.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++
++/*
++ * This task wants to use the FPU now.
++ * On UP, disable FP for the task which had the FPU previously,
++ * and save its floating-point registers in its thread_struct.
++ * Load up this task's FP registers from its thread_struct,
++ * enable the FPU for the current task and return to the task.
++ */
++_GLOBAL(load_up_fpu)
++ mfmsr r5
++ ori r5,r5,MSR_FP
++ SYNC
++ MTMSRD(r5) /* enable use of fpu now */
++ isync
++/*
++ * For SMP, we don't do lazy FPU switching because it just gets too
++ * horrendously complex, especially when a task switches from one CPU
++ * to another. Instead we call giveup_fpu in switch_to.
++ */
++#ifndef CONFIG_SMP
++ LOADBASE(r3, last_task_used_math)
++ toreal(r3)
++ LDL r4,OFF(last_task_used_math)(r3)
++ CMPI 0,r4,0
++ beq 1f
++ toreal(r4)
++ addi r4,r4,THREAD /* want last_task_used_math->thread */
++ SAVE_32FPRS(0, r4)
++ mffs fr0
++ stfd fr0,THREAD_FPSCR(r4)
++ LDL r5,PT_REGS(r4)
++ toreal(r5)
++ LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ li r10,MSR_FP|MSR_FE0|MSR_FE1
++ andc r4,r4,r10 /* disable FP for previous task */
++ STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#endif /* CONFIG_SMP */
++ /* enable use of FP after return */
++#ifdef CONFIG_PPC32
++ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
++ lwz r4,THREAD_FPEXC_MODE(r5)
++ ori r9,r9,MSR_FP /* enable FP for current */
++ or r9,r9,r4
++#else
++ ld r4,PACACURRENT(r13)
++ addi r5,r4,THREAD /* Get THREAD */
++ ld r4,THREAD_FPEXC_MODE(r5)
++ ori r12,r12,MSR_FP
++ or r12,r12,r4
++ std r12,_MSR(r1)
++#endif
++ lfd fr0,THREAD_FPSCR(r5)
++ mtfsf 0xff,fr0
++ REST_32FPRS(0, r5)
++#ifndef CONFIG_SMP
++ subi r4,r5,THREAD
++ fromreal(r4)
++ STL r4,OFF(last_task_used_math)(r3)
++#endif /* CONFIG_SMP */
++ /* restore registers and return */
++ /* we haven't used ctr or xer or lr */
++ b fast_exception_return
++
++/*
++ * giveup_fpu(tsk)
++ * Disable FP for the task given as the argument,
++ * and save the floating-point registers in its thread_struct.
++ * Enables the FPU for use in the kernel on return.
++ */
++_GLOBAL(giveup_fpu)
++ mfmsr r5
++ ori r5,r5,MSR_FP
++ SYNC_601
++ ISYNC_601
++ MTMSRD(r5) /* enable use of fpu now */
++ SYNC_601
++ isync
++ CMPI 0,r3,0
++ beqlr- /* if no previous owner, done */
++ addi r3,r3,THREAD /* want THREAD of task */
++ LDL r5,PT_REGS(r3)
++ CMPI 0,r5,0
++ SAVE_32FPRS(0, r3)
++ mffs fr0
++ stfd fr0,THREAD_FPSCR(r3)
++ beq 1f
++ LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ li r3,MSR_FP|MSR_FE0|MSR_FE1
++ andc r4,r4,r3 /* disable FP for previous task */
++ STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#ifndef CONFIG_SMP
++ li r5,0
++ LOADBASE(r4,last_task_used_math)
++ STL r5,OFF(last_task_used_math)(r4)
++#endif /* CONFIG_SMP */
++ blr
++
++/*
++ * These are used in the alignment trap handler when emulating
++ * single-precision loads and stores.
++ * We restore and save the fpscr so the task gets the same result
++ * and exceptions as if the cpu had performed the load or store.
++ */
++
++_GLOBAL(cvt_fd)
++ lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */
++ mtfsf 0xff,0
++ lfs 0,0(r3)
++ stfd 0,0(r4)
++ mffs 0
++ stfd 0,THREAD_FPSCR(r5) /* save new fpscr value */
++ blr
++
++_GLOBAL(cvt_df)
++ lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */
++ mtfsf 0xff,0
++ lfd 0,0(r3)
++ stfs 0,0(r4)
++ mffs 0
++ stfd 0,THREAD_FPSCR(r5) /* save new fpscr value */
++ blr
+diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/head_32.S
+@@ -0,0 +1,1381 @@
++/*
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Rewritten by Cort Dougan (cort at cs.nmt.edu) for PReP
++ * Copyright (C) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Adapted for Power Macintosh by Paul Mackerras.
++ * Low-level exception handlers and MMU support
++ * rewritten by Paul Mackerras.
++ * Copyright (C) 1996 Paul Mackerras.
++ * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek at jlc.net).
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * This file contains the low-level support and setup for the
++ * PowerPC platform, including trap and interrupt dispatch.
++ * (The PPC 8xx embedded CPUs use head_8xx.S instead.)
++ *
++ * 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/reg.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/cputable.h>
++#include <asm/cache.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++
++#ifdef CONFIG_APUS
++#include <asm/amigappc.h>
++#endif
++
++/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
++#define LOAD_BAT(n, reg, RA, RB) \
++ /* see the comment for clear_bats() -- Cort */ \
++ li RA,0; \
++ mtspr SPRN_IBAT##n##U,RA; \
++ mtspr SPRN_DBAT##n##U,RA; \
++ lwz RA,(n*16)+0(reg); \
++ lwz RB,(n*16)+4(reg); \
++ mtspr SPRN_IBAT##n##U,RA; \
++ mtspr SPRN_IBAT##n##L,RB; \
++ beq 1f; \
++ lwz RA,(n*16)+8(reg); \
++ lwz RB,(n*16)+12(reg); \
++ mtspr SPRN_DBAT##n##U,RA; \
++ mtspr SPRN_DBAT##n##L,RB; \
++1:
++
++ .text
++ .stabs "arch/powerpc/kernel/",N_SO,0,0,0f
++ .stabs "head_32.S",N_SO,0,0,0f
++0:
++ .globl _stext
++_stext:
++
++/*
++ * _start is defined this way because the XCOFF loader in the OpenFirmware
++ * on the powermac expects the entry point to be a procedure descriptor.
++ */
++ .text
++ .globl _start
++_start:
++ /*
++ * These are here for legacy reasons, the kernel used to
++ * need to look like a coff function entry for the pmac
++ * but we're always started by some kind of bootloader now.
++ * -- Cort
++ */
++ nop /* used by __secondary_hold on prep (mtx) and chrp smp */
++ nop /* used by __secondary_hold on prep (mtx) and chrp smp */
++ nop
++
++/* PMAC
++ * Enter here with the kernel text, data and bss loaded starting at
++ * 0, running with virtual == physical mapping.
++ * r5 points to the prom entry point (the client interface handler
++ * address). Address translation is turned on, with the prom
++ * managing the hash table. Interrupts are disabled. The stack
++ * pointer (r1) points to just below the end of the half-meg region
++ * from 0x380000 - 0x400000, which is mapped in already.
++ *
++ * If we are booted from MacOS via BootX, we enter with the kernel
++ * image loaded somewhere, and the following values in registers:
++ * r3: 'BooX' (0x426f6f58)
++ * r4: virtual address of boot_infos_t
++ * r5: 0
++ *
++ * APUS
++ * r3: 'APUS'
++ * r4: physical address of memory base
++ * Linux/m68k style BootInfo structure at &_end.
++ *
++ * PREP
++ * This is jumped to on prep systems right after the kernel is relocated
++ * to its proper place in memory by the boot loader. The expected layout
++ * of the regs is:
++ * r3: ptr to residual data
++ * r4: initrd_start or if no initrd then 0
++ * r5: initrd_end - unused if r4 is 0
++ * r6: Start of command line string
++ * r7: End of command line string
++ *
++ * This just gets a minimal mmu environment setup so we can call
++ * start_here() to do the real work.
++ * -- Cort
++ */
++
++ .globl __start
++__start:
++/*
++ * We have to do any OF calls before we map ourselves to KERNELBASE,
++ * because OF may have I/O devices mapped into that area
++ * (particularly on CHRP).
++ */
++ cmpwi 0,r5,0
++ beq 1f
++ bl prom_init
++ trap
++
++1: mr r31,r3 /* save parameters */
++ mr r30,r4
++ li r24,0 /* cpu # */
++
++/*
++ * early_init() does the early machine identification and does
++ * the necessary low-level setup and clears the BSS
++ * -- Cort <cort at fsmlabs.com>
++ */
++ bl early_init
++
++#ifdef CONFIG_APUS
++/* On APUS the __va/__pa constants need to be set to the correct
++ * values before continuing.
++ */
++ mr r4,r30
++ bl fix_mem_constants
++#endif /* CONFIG_APUS */
++
++/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
++ * the physical address we are running at, returned by early_init()
++ */
++ bl mmu_off
++__after_mmu_off:
++ bl clear_bats
++ bl flush_tlbs
++
++ bl initial_bats
++
++/*
++ * Call setup_cpu for CPU 0 and initialize 6xx Idle
++ */
++ bl reloc_offset
++ li r24,0 /* cpu# */
++ bl call_setup_cpu /* Call setup_cpu for this CPU */
++#ifdef CONFIG_6xx
++ bl reloc_offset
++ bl init_idle_6xx
++#endif /* CONFIG_6xx */
++
++
++#ifndef CONFIG_APUS
++/*
++ * We need to run with _start at physical address 0.
++ * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
++ * the exception vectors at 0 (and therefore this copy
++ * overwrites OF's exception vectors with our own).
++ * The MMU is off at this point.
++ */
++ bl reloc_offset
++ mr r26,r3
++ addis r4,r3,KERNELBASE at h /* current address of _start */
++ cmpwi 0,r4,0 /* are we already running at 0? */
++ bne relocate_kernel
++#endif /* CONFIG_APUS */
++/*
++ * we now have the 1st 16M of ram mapped with the bats.
++ * prep needs the mmu to be turned on here, but pmac already has it on.
++ * this shouldn't bother the pmac since it just gets turned on again
++ * as we jump to our code at KERNELBASE. -- Cort
++ * Actually no, pmac doesn't have it on any more. BootX enters with MMU
++ * off, and in other cases, we now turn it off before changing BATs above.
++ */
++turn_on_mmu:
++ mfmsr r0
++ ori r0,r0,MSR_DR|MSR_IR
++ mtspr SPRN_SRR1,r0
++ lis r0,start_here at h
++ ori r0,r0,start_here at l
++ mtspr SPRN_SRR0,r0
++ SYNC
++ RFI /* enables MMU */
++
++/*
++ * We need __secondary_hold as a place to hold the other cpus on
++ * an SMP machine, even when we are running a UP kernel.
++ */
++ . = 0xc0 /* for prep bootloader */
++ li r3,1 /* MTX only has 1 cpu */
++ .globl __secondary_hold
++__secondary_hold:
++ /* tell the master we're here */
++ stw r3,__secondary_hold_acknowledge at l(0)
++#ifdef CONFIG_SMP
++100: lwz r4,0(0)
++ /* wait until we're told to start */
++ cmpw 0,r4,r3
++ bne 100b
++ /* our cpu # was at addr 0 - go */
++ mr r24,r3 /* cpu # */
++ b __secondary_start
++#else
++ b .
++#endif /* CONFIG_SMP */
++
++ .globl __secondary_hold_spinloop
++__secondary_hold_spinloop:
++ .long 0
++ .globl __secondary_hold_acknowledge
++__secondary_hold_acknowledge:
++ .long -1
++
++/*
++ * Exception entry code. This code runs with address translation
++ * turned off, i.e. using physical addresses.
++ * We assume sprg3 has the physical address of the current
++ * task's thread_struct.
++ */
++#define EXCEPTION_PROLOG \
++ mtspr SPRN_SPRG0,r10; \
++ mtspr SPRN_SPRG1,r11; \
++ mfcr r10; \
++ EXCEPTION_PROLOG_1; \
++ EXCEPTION_PROLOG_2
++
++#define EXCEPTION_PROLOG_1 \
++ mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
++ andi. r11,r11,MSR_PR; \
++ tophys(r11,r1); /* use tophys(r1) if kernel */ \
++ beq 1f; \
++ mfspr r11,SPRN_SPRG3; \
++ lwz r11,THREAD_INFO-THREAD(r11); \
++ addi r11,r11,THREAD_SIZE; \
++ tophys(r11,r11); \
++1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */
++
++
++#define EXCEPTION_PROLOG_2 \
++ CLR_TOP32(r11); \
++ stw r10,_CCR(r11); /* save registers */ \
++ stw r12,GPR12(r11); \
++ stw r9,GPR9(r11); \
++ mfspr r10,SPRN_SPRG0; \
++ stw r10,GPR10(r11); \
++ mfspr r12,SPRN_SPRG1; \
++ stw r12,GPR11(r11); \
++ mflr r10; \
++ stw r10,_LINK(r11); \
++ mfspr r12,SPRN_SRR0; \
++ mfspr r9,SPRN_SRR1; \
++ stw r1,GPR1(r11); \
++ stw r1,0(r11); \
++ tovirt(r1,r11); /* set new kernel sp */ \
++ li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
++ MTMSRD(r10); /* (except for mach check in rtas) */ \
++ stw r0,GPR0(r11); \
++ lis r10,0x7265; /* put exception frame marker */ \
++ addi r10,r10,0x6773; \
++ stw r10,8(r11); \
++ SAVE_4GPRS(3, r11); \
++ SAVE_2GPRS(7, r11)
++
++/*
++ * Note: code which follows this uses cr0.eq (set if from kernel),
++ * r11, r12 (SRR0), and r9 (SRR1).
++ *
++ * Note2: once we have set r1 we are in a position to take exceptions
++ * again, and we could thus set MSR:RI at that point.
++ */
++
++/*
++ * Exception vectors.
++ */
++#define EXCEPTION(n, label, hdlr, xfer) \
++ . = n; \
++label: \
++ EXCEPTION_PROLOG; \
++ addi r3,r1,STACK_FRAME_OVERHEAD; \
++ xfer(n, hdlr)
++
++#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret) \
++ li r10,trap; \
++ stw r10,_TRAP(r11); \
++ li r10,MSR_KERNEL; \
++ copyee(r10, r9); \
++ bl tfer; \
++i##n: \
++ .long hdlr; \
++ .long ret
++
++#define COPY_EE(d, s) rlwimi d,s,0,16,16
++#define NOCOPY(d, s)
++
++#define EXC_XFER_STD(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
++ ret_from_except_full)
++
++#define EXC_XFER_LITE(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
++ ret_from_except)
++
++#define EXC_XFER_EE(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
++ ret_from_except_full)
++
++#define EXC_XFER_EE_LITE(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
++ ret_from_except)
++
++/* System reset */
++/* core99 pmac starts the seconary here by changing the vector, and
++ putting it back to what it was (unknown_exception) when done. */
++#if defined(CONFIG_GEMINI) && defined(CONFIG_SMP)
++ . = 0x100
++ b __secondary_start_gemini
++#else
++ EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
++#endif
++
++/* Machine check */
++/*
++ * On CHRP, this is complicated by the fact that we could get a
++ * machine check inside RTAS, and we have no guarantee that certain
++ * critical registers will have the values we expect. The set of
++ * registers that might have bad values includes all the GPRs
++ * and all the BATs. We indicate that we are in RTAS by putting
++ * a non-zero value, the address of the exception frame to use,
++ * in SPRG2. The machine check handler checks SPRG2 and uses its
++ * value if it is non-zero. If we ever needed to free up SPRG2,
++ * we could use a field in the thread_info or thread_struct instead.
++ * (Other exception handlers assume that r1 is a valid kernel stack
++ * pointer when we take an exception from supervisor mode.)
++ * -- paulus.
++ */
++ . = 0x200
++ mtspr SPRN_SPRG0,r10
++ mtspr SPRN_SPRG1,r11
++ mfcr r10
++#ifdef CONFIG_PPC_CHRP
++ mfspr r11,SPRN_SPRG2
++ cmpwi 0,r11,0
++ bne 7f
++#endif /* CONFIG_PPC_CHRP */
++ EXCEPTION_PROLOG_1
++7: EXCEPTION_PROLOG_2
++ addi r3,r1,STACK_FRAME_OVERHEAD
++#ifdef CONFIG_PPC_CHRP
++ mfspr r4,SPRN_SPRG2
++ cmpwi cr1,r4,0
++ bne cr1,1f
++#endif
++ EXC_XFER_STD(0x200, machine_check_exception)
++#ifdef CONFIG_PPC_CHRP
++1: b machine_check_in_rtas
++#endif
++
++/* Data access exception. */
++ . = 0x300
++DataAccess:
++ EXCEPTION_PROLOG
++ mfspr r10,SPRN_DSISR
++ andis. r0,r10,0xa470 /* weird error? */
++ bne 1f /* if not, try to put a PTE */
++ mfspr r4,SPRN_DAR /* into the hash table */
++ rlwinm r3,r10,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */
++ bl hash_page
++1: stw r10,_DSISR(r11)
++ mr r5,r10
++ mfspr r4,SPRN_DAR
++ EXC_XFER_EE_LITE(0x300, handle_page_fault)
++
++
++/* Instruction access exception. */
++ . = 0x400
++InstructionAccess:
++ EXCEPTION_PROLOG
++ andis. r0,r9,0x4000 /* no pte found? */
++ beq 1f /* if so, try to put a PTE */
++ li r3,0 /* into the hash table */
++ mr r4,r12 /* SRR0 is fault address */
++ bl hash_page
++1: mr r4,r12
++ mr r5,r9
++ EXC_XFER_EE_LITE(0x400, handle_page_fault)
++
++/* External interrupt */
++ EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
++
++/* Alignment exception */
++ . = 0x600
++Alignment:
++ EXCEPTION_PROLOG
++ mfspr r4,SPRN_DAR
++ stw r4,_DAR(r11)
++ mfspr r5,SPRN_DSISR
++ stw r5,_DSISR(r11)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_EE(0x600, alignment_exception)
++
++/* Program check exception */
++ EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
++
++/* Floating-point unavailable */
++ . = 0x800
++FPUnavailable:
++ EXCEPTION_PROLOG
++ bne load_up_fpu /* if from user, just load it up */
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
++
++/* Decrementer */
++ EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
++
++ EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
++
++/* System call */
++ . = 0xc00
++SystemCall:
++ EXCEPTION_PROLOG
++ EXC_XFER_EE_LITE(0xc00, DoSyscall)
++
++/* Single step - not used on 601 */
++ EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
++ EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
++
++/*
++ * The Altivec unavailable trap is at 0x0f20. Foo.
++ * We effectively remap it to 0x3000.
++ * We include an altivec unavailable exception vector even if
++ * not configured for Altivec, so that you can't panic a
++ * non-altivec kernel running on a machine with altivec just
++ * by executing an altivec instruction.
++ */
++ . = 0xf00
++ b Trap_0f
++
++ . = 0xf20
++ b AltiVecUnavailable
++
++Trap_0f:
++ EXCEPTION_PROLOG
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_EE(0xf00, unknown_exception)
++
++/*
++ * Handle TLB miss for instruction on 603/603e.
++ * Note: we get an alternate set of r0 - r3 to use automatically.
++ */
++ . = 0x1000
++InstructionTLBMiss:
++/*
++ * r0: stored ctr
++ * r1: linux style pte ( later becomes ppc hardware pte )
++ * r2: ptr to linux-style pte
++ * r3: scratch
++ */
++ mfctr r0
++ /* Get PTE (linux-style) and check access */
++ mfspr r3,SPRN_IMISS
++ lis r1,KERNELBASE at h /* check if kernel address */
++ cmplw 0,r3,r1
++ mfspr r2,SPRN_SPRG3
++ li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
++ lwz r2,PGDIR(r2)
++ blt+ 112f
++ lis r2,swapper_pg_dir at ha /* if kernel address, use */
++ addi r2,r2,swapper_pg_dir at l /* kernel page table */
++ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
++ rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
++112: tophys(r2,r2)
++ rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
++ lwz r2,0(r2) /* get pmd entry */
++ rlwinm. r2,r2,0,0,19 /* extract address of pte page */
++ beq- InstructionAddressInvalid /* return if no mapping */
++ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
++ lwz r3,0(r2) /* get linux-style pte */
++ andc. r1,r1,r3 /* check access & ~permission */
++ bne- InstructionAddressInvalid /* return if access not permitted */
++ ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */
++ /*
++ * NOTE! We are assuming this is not an SMP system, otherwise
++ * we would need to update the pte atomically with lwarx/stwcx.
++ */
++ stw r3,0(r2) /* update PTE (accessed bit) */
++ /* Convert linux-style PTE to low word of PPC-style PTE */
++ rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */
++ rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
++ and r1,r1,r2 /* writable if _RW and _DIRTY */
++ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
++ rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */
++ ori r1,r1,0xe14 /* clear out reserved bits and M */
++ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
++ mtspr SPRN_RPA,r1
++ mfspr r3,SPRN_IMISS
++ tlbli r3
++ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
++ mtcrf 0x80,r3
++ rfi
++InstructionAddressInvalid:
++ mfspr r3,SPRN_SRR1
++ rlwinm r1,r3,9,6,6 /* Get load/store bit */
++
++ addis r1,r1,0x2000
++ mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */
++ mtctr r0 /* Restore CTR */
++ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
++ or r2,r2,r1
++ mtspr SPRN_SRR1,r2
++ mfspr r1,SPRN_IMISS /* Get failing address */
++ rlwinm. r2,r2,0,31,31 /* Check for little endian access */
++ rlwimi r2,r2,1,30,30 /* change 1 -> 3 */
++ xor r1,r1,r2
++ mtspr SPRN_DAR,r1 /* Set fault address */
++ mfmsr r0 /* Restore "normal" registers */
++ xoris r0,r0,MSR_TGPR>>16
++ mtcrf 0x80,r3 /* Restore CR0 */
++ mtmsr r0
++ b InstructionAccess
++
++/*
++ * Handle TLB miss for DATA Load operation on 603/603e
++ */
++ . = 0x1100
++DataLoadTLBMiss:
++/*
++ * r0: stored ctr
++ * r1: linux style pte ( later becomes ppc hardware pte )
++ * r2: ptr to linux-style pte
++ * r3: scratch
++ */
++ mfctr r0
++ /* Get PTE (linux-style) and check access */
++ mfspr r3,SPRN_DMISS
++ lis r1,KERNELBASE at h /* check if kernel address */
++ cmplw 0,r3,r1
++ mfspr r2,SPRN_SPRG3
++ li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
++ lwz r2,PGDIR(r2)
++ blt+ 112f
++ lis r2,swapper_pg_dir at ha /* if kernel address, use */
++ addi r2,r2,swapper_pg_dir at l /* kernel page table */
++ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
++ rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
++112: tophys(r2,r2)
++ rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
++ lwz r2,0(r2) /* get pmd entry */
++ rlwinm. r2,r2,0,0,19 /* extract address of pte page */
++ beq- DataAddressInvalid /* return if no mapping */
++ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
++ lwz r3,0(r2) /* get linux-style pte */
++ andc. r1,r1,r3 /* check access & ~permission */
++ bne- DataAddressInvalid /* return if access not permitted */
++ ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */
++ /*
++ * NOTE! We are assuming this is not an SMP system, otherwise
++ * we would need to update the pte atomically with lwarx/stwcx.
++ */
++ stw r3,0(r2) /* update PTE (accessed bit) */
++ /* Convert linux-style PTE to low word of PPC-style PTE */
++ rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */
++ rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
++ and r1,r1,r2 /* writable if _RW and _DIRTY */
++ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
++ rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */
++ ori r1,r1,0xe14 /* clear out reserved bits and M */
++ andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
++ mtspr SPRN_RPA,r1
++ mfspr r3,SPRN_DMISS
++ tlbld r3
++ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
++ mtcrf 0x80,r3
++ rfi
++DataAddressInvalid:
++ mfspr r3,SPRN_SRR1
++ rlwinm r1,r3,9,6,6 /* Get load/store bit */
++ addis r1,r1,0x2000
++ mtspr SPRN_DSISR,r1
++ mtctr r0 /* Restore CTR */
++ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
++ mtspr SPRN_SRR1,r2
++ mfspr r1,SPRN_DMISS /* Get failing address */
++ rlwinm. r2,r2,0,31,31 /* Check for little endian access */
++ beq 20f /* Jump if big endian */
++ xori r1,r1,3
++20: mtspr SPRN_DAR,r1 /* Set fault address */
++ mfmsr r0 /* Restore "normal" registers */
++ xoris r0,r0,MSR_TGPR>>16
++ mtcrf 0x80,r3 /* Restore CR0 */
++ mtmsr r0
++ b DataAccess
++
++/*
++ * Handle TLB miss for DATA Store on 603/603e
++ */
++ . = 0x1200
++DataStoreTLBMiss:
++/*
++ * r0: stored ctr
++ * r1: linux style pte ( later becomes ppc hardware pte )
++ * r2: ptr to linux-style pte
++ * r3: scratch
++ */
++ mfctr r0
++ /* Get PTE (linux-style) and check access */
++ mfspr r3,SPRN_DMISS
++ lis r1,KERNELBASE at h /* check if kernel address */
++ cmplw 0,r3,r1
++ mfspr r2,SPRN_SPRG3
++ li r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */
++ lwz r2,PGDIR(r2)
++ blt+ 112f
++ lis r2,swapper_pg_dir at ha /* if kernel address, use */
++ addi r2,r2,swapper_pg_dir at l /* kernel page table */
++ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
++ rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
++112: tophys(r2,r2)
++ rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
++ lwz r2,0(r2) /* get pmd entry */
++ rlwinm. r2,r2,0,0,19 /* extract address of pte page */
++ beq- DataAddressInvalid /* return if no mapping */
++ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
++ lwz r3,0(r2) /* get linux-style pte */
++ andc. r1,r1,r3 /* check access & ~permission */
++ bne- DataAddressInvalid /* return if access not permitted */
++ ori r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY
++ /*
++ * NOTE! We are assuming this is not an SMP system, otherwise
++ * we would need to update the pte atomically with lwarx/stwcx.
++ */
++ stw r3,0(r2) /* update PTE (accessed/dirty bits) */
++ /* Convert linux-style PTE to low word of PPC-style PTE */
++ rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */
++ li r1,0xe15 /* clear out reserved bits and M */
++ andc r1,r3,r1 /* PP = user? 2: 0 */
++ mtspr SPRN_RPA,r1
++ mfspr r3,SPRN_DMISS
++ tlbld r3
++ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
++ mtcrf 0x80,r3
++ rfi
++
++#ifndef CONFIG_ALTIVEC
++#define altivec_assist_exception unknown_exception
++#endif
++
++ EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_EE)
++ EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
++ EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1600, Trap_16, altivec_assist_exception, EXC_XFER_EE)
++ EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
++ EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2000, RunMode, RunModeException, EXC_XFER_EE)
++ EXCEPTION(0x2100, Trap_21, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2200, Trap_22, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2300, Trap_23, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2400, Trap_24, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2500, Trap_25, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2600, Trap_26, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2700, Trap_27, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2800, Trap_28, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2900, Trap_29, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2a00, Trap_2a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2b00, Trap_2b, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2c00, Trap_2c, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2d00, Trap_2d, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2e00, Trap_2e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2f00, MOLTrampoline, unknown_exception, EXC_XFER_EE_LITE)
++
++ .globl mol_trampoline
++ .set mol_trampoline, i0x2f00
++
++ . = 0x3000
++
++AltiVecUnavailable:
++ EXCEPTION_PROLOG
++#ifdef CONFIG_ALTIVEC
++ bne load_up_altivec /* if from user, just load it up */
++#endif /* CONFIG_ALTIVEC */
++ EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
++
++#ifdef CONFIG_ALTIVEC
++/* Note that the AltiVec support is closely modeled after the FP
++ * support. Changes to one are likely to be applicable to the
++ * other! */
++load_up_altivec:
++/*
++ * Disable AltiVec for the task which had AltiVec previously,
++ * and save its AltiVec registers in its thread_struct.
++ * Enables AltiVec for use in the kernel on return.
++ * On SMP we know the AltiVec units are free, since we give it up every
++ * switch. -- Kumar
++ */
++ mfmsr r5
++ oris r5,r5,MSR_VEC at h
++ MTMSRD(r5) /* enable use of AltiVec now */
++ isync
++/*
++ * For SMP, we don't do lazy AltiVec switching because it just gets too
++ * horrendously complex, especially when a task switches from one CPU
++ * to another. Instead we call giveup_altivec in switch_to.
++ */
++#ifndef CONFIG_SMP
++ tophys(r6,0)
++ addis r3,r6,last_task_used_altivec at ha
++ lwz r4,last_task_used_altivec at l(r3)
++ cmpwi 0,r4,0
++ beq 1f
++ add r4,r4,r6
++ addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */
++ SAVE_32VRS(0,r10,r4)
++ mfvscr vr0
++ li r10,THREAD_VSCR
++ stvx vr0,r10,r4
++ lwz r5,PT_REGS(r4)
++ add r5,r5,r6
++ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ lis r10,MSR_VEC at h
++ andc r4,r4,r10 /* disable altivec for previous task */
++ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#endif /* CONFIG_SMP */
++ /* enable use of AltiVec after return */
++ oris r9,r9,MSR_VEC at h
++ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
++ li r4,1
++ li r10,THREAD_VSCR
++ stw r4,THREAD_USED_VR(r5)
++ lvx vr0,r10,r5
++ mtvscr vr0
++ REST_32VRS(0,r10,r5)
++#ifndef CONFIG_SMP
++ subi r4,r5,THREAD
++ sub r4,r4,r6
++ stw r4,last_task_used_altivec at l(r3)
++#endif /* CONFIG_SMP */
++ /* restore registers and return */
++ /* we haven't used ctr or xer or lr */
++ b fast_exception_return
++
++/*
++ * AltiVec unavailable trap from kernel - print a message, but let
++ * the task use AltiVec in the kernel until it returns to user mode.
++ */
++KernelAltiVec:
++ lwz r3,_MSR(r1)
++ oris r3,r3,MSR_VEC at h
++ stw r3,_MSR(r1) /* enable use of AltiVec after return */
++ lis r3,87f at h
++ ori r3,r3,87f at l
++ mr r4,r2 /* current */
++ lwz r5,_NIP(r1)
++ bl printk
++ b ret_from_except
++87: .string "AltiVec used in kernel (task=%p, pc=%x) \n"
++ .align 4,0
++
++/*
++ * giveup_altivec(tsk)
++ * Disable AltiVec for the task given as the argument,
++ * and save the AltiVec registers in its thread_struct.
++ * Enables AltiVec for use in the kernel on return.
++ */
++
++ .globl giveup_altivec
++giveup_altivec:
++ mfmsr r5
++ oris r5,r5,MSR_VEC at h
++ SYNC
++ MTMSRD(r5) /* enable use of AltiVec now */
++ isync
++ cmpwi 0,r3,0
++ beqlr- /* if no previous owner, done */
++ addi r3,r3,THREAD /* want THREAD of task */
++ lwz r5,PT_REGS(r3)
++ cmpwi 0,r5,0
++ SAVE_32VRS(0, r4, r3)
++ mfvscr vr0
++ li r4,THREAD_VSCR
++ stvx vr0,r4,r3
++ beq 1f
++ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ lis r3,MSR_VEC at h
++ andc r4,r4,r3 /* disable AltiVec for previous task */
++ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#ifndef CONFIG_SMP
++ li r5,0
++ lis r4,last_task_used_altivec at ha
++ stw r5,last_task_used_altivec at l(r4)
++#endif /* CONFIG_SMP */
++ blr
++#endif /* CONFIG_ALTIVEC */
++
++/*
++ * This code is jumped to from the startup code to copy
++ * the kernel image to physical address 0.
++ */
++relocate_kernel:
++ addis r9,r26,klimit at ha /* fetch klimit */
++ lwz r25,klimit at l(r9)
++ addis r25,r25,-KERNELBASE at h
++ li r3,0 /* Destination base address */
++ li r6,0 /* Destination offset */
++ li r5,0x4000 /* # bytes of memory to copy */
++ bl copy_and_flush /* copy the first 0x4000 bytes */
++ addi r0,r3,4f at l /* jump to the address of 4f */
++ mtctr r0 /* in copy and do the rest. */
++ bctr /* jump to the copy */
++4: mr r5,r25
++ bl copy_and_flush /* copy the rest */
++ b turn_on_mmu
++
++/*
++ * Copy routine used to copy the kernel to start at physical address 0
++ * and flush and invalidate the caches as needed.
++ * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
++ * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
++ */
++_GLOBAL(copy_and_flush)
++ addi r5,r5,-4
++ addi r6,r6,-4
++4: li r0,L1_CACHE_BYTES/4
++ mtctr r0
++3: addi r6,r6,4 /* copy a cache line */
++ lwzx r0,r6,r4
++ stwx r0,r6,r3
++ bdnz 3b
++ dcbst r6,r3 /* write it to memory */
++ sync
++ icbi r6,r3 /* flush the icache line */
++ cmplw 0,r6,r5
++ blt 4b
++ sync /* additional sync needed on g4 */
++ isync
++ addi r5,r5,4
++ addi r6,r6,4
++ blr
++
++#ifdef CONFIG_APUS
++/*
++ * On APUS the physical base address of the kernel is not known at compile
++ * time, which means the __pa/__va constants used are incorrect. In the
++ * __init section is recorded the virtual addresses of instructions using
++ * these constants, so all that has to be done is fix these before
++ * continuing the kernel boot.
++ *
++ * r4 = The physical address of the kernel base.
++ */
++fix_mem_constants:
++ mr r10,r4
++ addis r10,r10,-KERNELBASE at h /* virt_to_phys constant */
++ neg r11,r10 /* phys_to_virt constant */
++
++ lis r12,__vtop_table_begin at h
++ ori r12,r12,__vtop_table_begin at l
++ add r12,r12,r10 /* table begin phys address */
++ lis r13,__vtop_table_end at h
++ ori r13,r13,__vtop_table_end at l
++ add r13,r13,r10 /* table end phys address */
++ subi r12,r12,4
++ subi r13,r13,4
++1: lwzu r14,4(r12) /* virt address of instruction */
++ add r14,r14,r10 /* phys address of instruction */
++ lwz r15,0(r14) /* instruction, now insert top */
++ rlwimi r15,r10,16,16,31 /* half of vp const in low half */
++ stw r15,0(r14) /* of instruction and restore. */
++ dcbst r0,r14 /* write it to memory */
++ sync
++ icbi r0,r14 /* flush the icache line */
++ cmpw r12,r13
++ bne 1b
++ sync /* additional sync needed on g4 */
++ isync
++
++/*
++ * Map the memory where the exception handlers will
++ * be copied to when hash constants have been patched.
++ */
++#ifdef CONFIG_APUS_FAST_EXCEPT
++ lis r8,0xfff0
++#else
++ lis r8,0
++#endif
++ ori r8,r8,0x2 /* 128KB, supervisor */
++ mtspr SPRN_DBAT3U,r8
++ mtspr SPRN_DBAT3L,r8
++
++ lis r12,__ptov_table_begin at h
++ ori r12,r12,__ptov_table_begin at l
++ add r12,r12,r10 /* table begin phys address */
++ lis r13,__ptov_table_end at h
++ ori r13,r13,__ptov_table_end at l
++ add r13,r13,r10 /* table end phys address */
++ subi r12,r12,4
++ subi r13,r13,4
++1: lwzu r14,4(r12) /* virt address of instruction */
++ add r14,r14,r10 /* phys address of instruction */
++ lwz r15,0(r14) /* instruction, now insert top */
++ rlwimi r15,r11,16,16,31 /* half of pv const in low half*/
++ stw r15,0(r14) /* of instruction and restore. */
++ dcbst r0,r14 /* write it to memory */
++ sync
++ icbi r0,r14 /* flush the icache line */
++ cmpw r12,r13
++ bne 1b
++
++ sync /* additional sync needed on g4 */
++ isync /* No speculative loading until now */
++ blr
++
++/***********************************************************************
++ * Please note that on APUS the exception handlers are located at the
++ * physical address 0xfff0000. For this reason, the exception handlers
++ * cannot use relative branches to access the code below.
++ ***********************************************************************/
++#endif /* CONFIG_APUS */
++
++#ifdef CONFIG_SMP
++#ifdef CONFIG_GEMINI
++ .globl __secondary_start_gemini
++__secondary_start_gemini:
++ mfspr r4,SPRN_HID0
++ ori r4,r4,HID0_ICFI
++ li r3,0
++ ori r3,r3,HID0_ICE
++ andc r4,r4,r3
++ mtspr SPRN_HID0,r4
++ sync
++ b __secondary_start
++#endif /* CONFIG_GEMINI */
++
++ .globl __secondary_start_pmac_0
++__secondary_start_pmac_0:
++ /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
++ li r24,0
++ b 1f
++ li r24,1
++ b 1f
++ li r24,2
++ b 1f
++ li r24,3
++1:
++ /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0
++ set to map the 0xf0000000 - 0xffffffff region */
++ mfmsr r0
++ rlwinm r0,r0,0,28,26 /* clear DR (0x10) */
++ SYNC
++ mtmsr r0
++ isync
++
++ .globl __secondary_start
++__secondary_start:
++ /* Copy some CPU settings from CPU 0 */
++ bl __restore_cpu_setup
++
++ lis r3,-KERNELBASE at h
++ mr r4,r24
++ bl call_setup_cpu /* Call setup_cpu for this CPU */
++#ifdef CONFIG_6xx
++ lis r3,-KERNELBASE at h
++ bl init_idle_6xx
++#endif /* CONFIG_6xx */
++
++ /* get current_thread_info and current */
++ lis r1,secondary_ti at ha
++ tophys(r1,r1)
++ lwz r1,secondary_ti at l(r1)
++ tophys(r2,r1)
++ lwz r2,TI_TASK(r2)
++
++ /* stack */
++ addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
++ li r0,0
++ tophys(r3,r1)
++ stw r0,0(r3)
++
++ /* load up the MMU */
++ bl load_up_mmu
++
++ /* ptr to phys current thread */
++ tophys(r4,r2)
++ addi r4,r4,THREAD /* phys address of our thread_struct */
++ CLR_TOP32(r4)
++ mtspr SPRN_SPRG3,r4
++ li r3,0
++ mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
++
++ /* enable MMU and jump to start_secondary */
++ li r4,MSR_KERNEL
++ FIX_SRR1(r4,r5)
++ lis r3,start_secondary at h
++ ori r3,r3,start_secondary at l
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
++ SYNC
++ RFI
++#endif /* CONFIG_SMP */
++
++/*
++ * Those generic dummy functions are kept for CPUs not
++ * included in CONFIG_6xx
++ */
++#if !defined(CONFIG_6xx)
++_GLOBAL(__save_cpu_setup)
++ blr
++_GLOBAL(__restore_cpu_setup)
++ blr
++#endif /* !defined(CONFIG_6xx) */
++
++
++/*
++ * Load stuff into the MMU. Intended to be called with
++ * IR=0 and DR=0.
++ */
++load_up_mmu:
++ sync /* Force all PTE updates to finish */
++ isync
++ tlbia /* Clear all TLB entries */
++ sync /* wait for tlbia/tlbie to finish */
++ TLBSYNC /* ... on all CPUs */
++ /* Load the SDR1 register (hash table base & size) */
++ lis r6,_SDR1 at ha
++ tophys(r6,r6)
++ lwz r6,_SDR1 at l(r6)
++ mtspr SPRN_SDR1,r6
++ li r0,16 /* load up segment register values */
++ mtctr r0 /* for context 0 */
++ lis r3,0x2000 /* Ku = 1, VSID = 0 */
++ li r4,0
++3: mtsrin r3,r4
++ addi r3,r3,0x111 /* increment VSID */
++ addis r4,r4,0x1000 /* address of next segment */
++ bdnz 3b
++
++/* Load the BAT registers with the values set up by MMU_init.
++ MMU_init takes care of whether we're on a 601 or not. */
++ mfpvr r3
++ srwi r3,r3,16
++ cmpwi r3,1
++ lis r3,BATS at ha
++ addi r3,r3,BATS at l
++ tophys(r3,r3)
++ LOAD_BAT(0,r3,r4,r5)
++ LOAD_BAT(1,r3,r4,r5)
++ LOAD_BAT(2,r3,r4,r5)
++ LOAD_BAT(3,r3,r4,r5)
++
++ blr
++
++/*
++ * This is where the main kernel code starts.
++ */
++start_here:
++ /* ptr to current */
++ lis r2,init_task at h
++ ori r2,r2,init_task at l
++ /* Set up for using our exception vectors */
++ /* ptr to phys current thread */
++ tophys(r4,r2)
++ addi r4,r4,THREAD /* init task's THREAD */
++ CLR_TOP32(r4)
++ mtspr SPRN_SPRG3,r4
++ li r3,0
++ mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
++
++ /* stack */
++ lis r1,init_thread_union at ha
++ addi r1,r1,init_thread_union at l
++ li r0,0
++ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
++/*
++ * Do early platform-specific initialization,
++ * and set up the MMU.
++ */
++ mr r3,r31
++ mr r4,r30
++ bl machine_init
++ bl MMU_init
++
++#ifdef CONFIG_APUS
++ /* Copy exception code to exception vector base on APUS. */
++ lis r4,KERNELBASE at h
++#ifdef CONFIG_APUS_FAST_EXCEPT
++ lis r3,0xfff0 /* Copy to 0xfff00000 */
++#else
++ lis r3,0 /* Copy to 0x00000000 */
++#endif
++ li r5,0x4000 /* # bytes of memory to copy */
++ li r6,0
++ bl copy_and_flush /* copy the first 0x4000 bytes */
++#endif /* CONFIG_APUS */
++
++/*
++ * Go back to running unmapped so we can load up new values
++ * for SDR1 (hash table pointer) and the segment registers
++ * and change to using our exception vectors.
++ */
++ lis r4,2f at h
++ ori r4,r4,2f at l
++ tophys(r4,r4)
++ li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
++ FIX_SRR1(r3,r5)
++ mtspr SPRN_SRR0,r4
++ mtspr SPRN_SRR1,r3
++ SYNC
++ RFI
++/* Load up the kernel context */
++2: bl load_up_mmu
++
++#ifdef CONFIG_BDI_SWITCH
++ /* Add helper information for the Abatron bdiGDB debugger.
++ * We do this here because we know the mmu is disabled, and
++ * will be enabled for real in just a few instructions.
++ */
++ lis r5, abatron_pteptrs at h
++ ori r5, r5, abatron_pteptrs at l
++ stw r5, 0xf0(r0) /* This much match your Abatron config */
++ lis r6, swapper_pg_dir at h
++ ori r6, r6, swapper_pg_dir at l
++ tophys(r5, r5)
++ stw r6, 0(r5)
++#endif /* CONFIG_BDI_SWITCH */
++
++/* Now turn on the MMU for real! */
++ li r4,MSR_KERNEL
++ FIX_SRR1(r4,r5)
++ lis r3,start_kernel at h
++ ori r3,r3,start_kernel at l
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
++ SYNC
++ RFI
++
++/*
++ * Set up the segment registers for a new context.
++ */
++_GLOBAL(set_context)
++ mulli r3,r3,897 /* multiply context by skew factor */
++ rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */
++ addis r3,r3,0x6000 /* Set Ks, Ku bits */
++ li r0,NUM_USER_SEGMENTS
++ mtctr r0
++
++#ifdef CONFIG_BDI_SWITCH
++ /* Context switch the PTE pointer for the Abatron BDI2000.
++ * The PGDIR is passed as second argument.
++ */
++ lis r5, KERNELBASE at h
++ lwz r5, 0xf0(r5)
++ stw r4, 0x4(r5)
++#endif
++ li r4,0
++ isync
++3:
++ mtsrin r3,r4
++ addi r3,r3,0x111 /* next VSID */
++ rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
++ addis r4,r4,0x1000 /* address of next segment */
++ bdnz 3b
++ sync
++ isync
++ blr
++
++/*
++ * An undocumented "feature" of 604e requires that the v bit
++ * be cleared before changing BAT values.
++ *
++ * Also, newer IBM firmware does not clear bat3 and 4 so
++ * this makes sure it's done.
++ * -- Cort
++ */
++clear_bats:
++ li r10,0
++ mfspr r9,SPRN_PVR
++ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
++ cmpwi r9, 1
++ beq 1f
++
++ mtspr SPRN_DBAT0U,r10
++ mtspr SPRN_DBAT0L,r10
++ mtspr SPRN_DBAT1U,r10
++ mtspr SPRN_DBAT1L,r10
++ mtspr SPRN_DBAT2U,r10
++ mtspr SPRN_DBAT2L,r10
++ mtspr SPRN_DBAT3U,r10
++ mtspr SPRN_DBAT3L,r10
++1:
++ mtspr SPRN_IBAT0U,r10
++ mtspr SPRN_IBAT0L,r10
++ mtspr SPRN_IBAT1U,r10
++ mtspr SPRN_IBAT1L,r10
++ mtspr SPRN_IBAT2U,r10
++ mtspr SPRN_IBAT2L,r10
++ mtspr SPRN_IBAT3U,r10
++ mtspr SPRN_IBAT3L,r10
++BEGIN_FTR_SECTION
++ /* Here's a tweak: at this point, CPU setup have
++ * not been called yet, so HIGH_BAT_EN may not be
++ * set in HID0 for the 745x processors. However, it
++ * seems that doesn't affect our ability to actually
++ * write to these SPRs.
++ */
++ mtspr SPRN_DBAT4U,r10
++ mtspr SPRN_DBAT4L,r10
++ mtspr SPRN_DBAT5U,r10
++ mtspr SPRN_DBAT5L,r10
++ mtspr SPRN_DBAT6U,r10
++ mtspr SPRN_DBAT6L,r10
++ mtspr SPRN_DBAT7U,r10
++ mtspr SPRN_DBAT7L,r10
++ mtspr SPRN_IBAT4U,r10
++ mtspr SPRN_IBAT4L,r10
++ mtspr SPRN_IBAT5U,r10
++ mtspr SPRN_IBAT5L,r10
++ mtspr SPRN_IBAT6U,r10
++ mtspr SPRN_IBAT6L,r10
++ mtspr SPRN_IBAT7U,r10
++ mtspr SPRN_IBAT7L,r10
++END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
++ blr
++
++flush_tlbs:
++ lis r10, 0x40
++1: addic. r10, r10, -0x1000
++ tlbie r10
++ blt 1b
++ sync
++ blr
++
++mmu_off:
++ addi r4, r3, __after_mmu_off - _start
++ mfmsr r3
++ andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */
++ beqlr
++ andc r3,r3,r0
++ mtspr SPRN_SRR0,r4
++ mtspr SPRN_SRR1,r3
++ sync
++ RFI
++
++/*
++ * Use the first pair of BAT registers to map the 1st 16MB
++ * of RAM to KERNELBASE. From this point on we can't safely
++ * call OF any more.
++ */
++initial_bats:
++ lis r11,KERNELBASE at h
++ mfspr r9,SPRN_PVR
++ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
++ cmpwi 0,r9,1
++ bne 4f
++ ori r11,r11,4 /* set up BAT registers for 601 */
++ li r8,0x7f /* valid, block length = 8MB */
++ oris r9,r11,0x800000 at h /* set up BAT reg for 2nd 8M */
++ oris r10,r8,0x800000 at h /* set up BAT reg for 2nd 8M */
++ mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */
++ mtspr SPRN_IBAT0L,r8 /* lower BAT register */
++ mtspr SPRN_IBAT1U,r9
++ mtspr SPRN_IBAT1L,r10
++ isync
++ blr
++
++4: tophys(r8,r11)
++#ifdef CONFIG_SMP
++ ori r8,r8,0x12 /* R/W access, M=1 */
++#else
++ ori r8,r8,2 /* R/W access */
++#endif /* CONFIG_SMP */
++#ifdef CONFIG_APUS
++ ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */
++#else
++ ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
++#endif /* CONFIG_APUS */
++
++ mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
++ mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
++ mtspr SPRN_IBAT0L,r8
++ mtspr SPRN_IBAT0U,r11
++ isync
++ blr
++
++
++#ifdef CONFIG_8260
++/* Jump into the system reset for the rom.
++ * We first disable the MMU, and then jump to the ROM reset address.
++ *
++ * r3 is the board info structure, r4 is the location for starting.
++ * I use this for building a small kernel that can load other kernels,
++ * rather than trying to write or rely on a rom monitor that can tftp load.
++ */
++ .globl m8260_gorom
++m8260_gorom:
++ mfmsr r0
++ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
++ sync
++ mtmsr r0
++ sync
++ mfspr r11, SPRN_HID0
++ lis r10, 0
++ ori r10,r10,HID0_ICE|HID0_DCE
++ andc r11, r11, r10
++ mtspr SPRN_HID0, r11
++ isync
++ li r5, MSR_ME|MSR_RI
++ lis r6,2f at h
++ addis r6,r6,-KERNELBASE at h
++ ori r6,r6,2f at l
++ mtspr SPRN_SRR0,r6
++ mtspr SPRN_SRR1,r5
++ isync
++ sync
++ rfi
++2:
++ mtlr r4
++ blr
++#endif
++
++
++/*
++ * We put a few things here that have to be page-aligned.
++ * This stuff goes at the beginning of the data segment,
++ * which is page-aligned.
++ */
++ .data
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
++ .space 4096
++
++ .globl swapper_pg_dir
++swapper_pg_dir:
++ .space 4096
++
++/*
++ * This space gets a copy of optional info passed to us by the bootstrap
++ * Used to pass parameters into the kernel like root=/dev/sda1, etc.
++ */
++ .globl cmd_line
++cmd_line:
++ .space 512
++
++ .globl intercept_table
++intercept_table:
++ .long 0, 0, i0x200, i0x300, i0x400, 0, i0x600, i0x700
++ .long i0x800, 0, 0, 0, 0, i0xd00, 0, 0
++ .long 0, 0, 0, i0x1300, 0, 0, 0, 0
++ .long 0, 0, 0, 0, 0, 0, 0, 0
++ .long 0, 0, 0, 0, 0, 0, 0, 0
++ .long 0, 0, 0, 0, 0, 0, 0, 0
++
++/* Room for two PTE pointers, usually the kernel and current user pointers
++ * to their respective root page table.
++ */
++abatron_pteptrs:
++ .space 8
+diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/head_44x.S
+@@ -0,0 +1,782 @@
++/*
++ * arch/ppc/kernel/head_44x.S
++ *
++ * Kernel execution entry point code.
++ *
++ * Copyright (c) 1995-1996 Gary Thomas <gdt at linuxppc.org>
++ * Initial PowerPC version.
++ * Copyright (c) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Rewritten for PReP
++ * Copyright (c) 1996 Paul Mackerras <paulus at cs.anu.edu.au>
++ * Low-level exception handers, MMU support, and rewrite.
++ * Copyright (c) 1997 Dan Malek <dmalek at jlc.net>
++ * PowerPC 8xx modifications.
++ * Copyright (c) 1998-1999 TiVo, Inc.
++ * PowerPC 403GCX modifications.
++ * Copyright (c) 1999 Grant Erickson <grant at lcse.umn.edu>
++ * PowerPC 403GCX/405GP modifications.
++ * Copyright 2000 MontaVista Software Inc.
++ * PPC405 modifications
++ * PowerPC 403GCX/405GP modifications.
++ * Author: MontaVista Software, Inc.
++ * frank_rowand at mvista.com or source at mvista.com
++ * debbie_chu at mvista.com
++ * Copyright 2002-2005 MontaVista Software, Inc.
++ * PowerPC 44x support, Matt Porter <mporter at kernel.crashing.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/ibm4xx.h>
++#include <asm/ibm44x.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include "head_booke.h"
++
++
++/* As with the other PowerPC ports, it is expected that when code
++ * execution begins here, the following registers contain valid, yet
++ * optional, information:
++ *
++ * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
++ * r4 - Starting address of the init RAM disk
++ * r5 - Ending address of the init RAM disk
++ * r6 - Start of kernel command line string (e.g. "mem=128")
++ * r7 - End of kernel command line string
++ *
++ */
++ .text
++_GLOBAL(_stext)
++_GLOBAL(_start)
++ /*
++ * Reserve a word at a fixed location to store the address
++ * of abatron_pteptrs
++ */
++ nop
++/*
++ * Save parameters we are passed
++ */
++ mr r31,r3
++ mr r30,r4
++ mr r29,r5
++ mr r28,r6
++ mr r27,r7
++ li r24,0 /* CPU number */
++
++/*
++ * Set up the initial MMU state
++ *
++ * We are still executing code at the virtual address
++ * mappings set by the firmware for the base of RAM.
++ *
++ * We first invalidate all TLB entries but the one
++ * we are running from. We then load the KERNELBASE
++ * mappings so we can begin to use kernel addresses
++ * natively and so the interrupt vector locations are
++ * permanently pinned (necessary since Book E
++ * implementations always have translation enabled).
++ *
++ * TODO: Use the known TLB entry we are running from to
++ * determine which physical region we are located
++ * in. This can be used to determine where in RAM
++ * (on a shared CPU system) or PCI memory space
++ * (on a DRAMless system) we are located.
++ * For now, we assume a perfect world which means
++ * we are located at the base of DRAM (physical 0).
++ */
++
++/*
++ * Search TLB for entry that we are currently using.
++ * Invalidate all entries but the one we are using.
++ */
++ /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
++ mfspr r3,SPRN_PID /* Get PID */
++ mfmsr r4 /* Get MSR */
++ andi. r4,r4,MSR_IS at l /* TS=1? */
++ beq wmmucr /* If not, leave STS=0 */
++ oris r3,r3,PPC44x_MMUCR_STS at h /* Set STS=1 */
++wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */
++ sync
++
++ bl invstr /* Find our address */
++invstr: mflr r5 /* Make it accessible */
++ tlbsx r23,0,r5 /* Find entry we are in */
++ li r4,0 /* Start at TLB entry 0 */
++ li r3,0 /* Set PAGEID inval value */
++1: cmpw r23,r4 /* Is this our entry? */
++ beq skpinv /* If so, skip the inval */
++ tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
++skpinv: addi r4,r4,1 /* Increment */
++ cmpwi r4,64 /* Are we done? */
++ bne 1b /* If not, repeat */
++ isync /* If so, context change */
++
++/*
++ * Configure and load pinned entry into TLB slot 63.
++ */
++
++ lis r3,KERNELBASE at h /* Load the kernel virtual address */
++ ori r3,r3,KERNELBASE at l
++
++ /* Kernel is at the base of RAM */
++ li r4, 0 /* Load the kernel physical address */
++
++ /* Load the kernel PID = 0 */
++ li r0,0
++ mtspr SPRN_PID,r0
++ sync
++
++ /* Initialize MMUCR */
++ li r5,0
++ mtspr SPRN_MMUCR,r5
++ sync
++
++ /* pageid fields */
++ clrrwi r3,r3,10 /* Mask off the effective page number */
++ ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
++
++ /* xlat fields */
++ clrrwi r4,r4,10 /* Mask off the real page number */
++ /* ERPN is 0 for first 4GB page */
++
++ /* attrib fields */
++ /* Added guarded bit to protect against speculative loads/stores */
++ li r5,0
++ ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
++
++ li r0,63 /* TLB slot 63 */
++
++ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
++ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
++ tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
++
++ /* Force context change */
++ mfmsr r0
++ mtspr SPRN_SRR1, r0
++ lis r0,3f at h
++ ori r0,r0,3f at l
++ mtspr SPRN_SRR0,r0
++ sync
++ rfi
++
++ /* If necessary, invalidate original entry we used */
++3: cmpwi r23,63
++ beq 4f
++ li r6,0
++ tlbwe r6,r23,PPC44x_TLB_PAGEID
++ isync
++
++4:
++#ifdef CONFIG_SERIAL_TEXT_DEBUG
++ /*
++ * Add temporary UART mapping for early debug.
++ * We can map UART registers wherever we want as long as they don't
++ * interfere with other system mappings (e.g. with pinned entries).
++ * For an example of how we handle this - see ocotea.h. --ebs
++ */
++ /* pageid fields */
++ lis r3,UART0_IO_BASE at h
++ ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K
++
++ /* xlat fields */
++ lis r4,UART0_PHYS_IO_BASE at h /* RPN depends on SoC */
++#ifndef CONFIG_440EP
++ ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */
++#endif
++
++ /* attrib fields */
++ li r5,0
++ ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
++
++ li r0,0 /* TLB slot 0 */
++
++ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
++ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
++ tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
++
++ /* Force context change */
++ isync
++#endif /* CONFIG_SERIAL_TEXT_DEBUG */
++
++ /* Establish the interrupt vector offsets */
++ SET_IVOR(0, CriticalInput);
++ SET_IVOR(1, MachineCheck);
++ SET_IVOR(2, DataStorage);
++ SET_IVOR(3, InstructionStorage);
++ SET_IVOR(4, ExternalInput);
++ SET_IVOR(5, Alignment);
++ SET_IVOR(6, Program);
++ SET_IVOR(7, FloatingPointUnavailable);
++ SET_IVOR(8, SystemCall);
++ SET_IVOR(9, AuxillaryProcessorUnavailable);
++ SET_IVOR(10, Decrementer);
++ SET_IVOR(11, FixedIntervalTimer);
++ SET_IVOR(12, WatchdogTimer);
++ SET_IVOR(13, DataTLBError);
++ SET_IVOR(14, InstructionTLBError);
++ SET_IVOR(15, Debug);
++
++ /* Establish the interrupt vector base */
++ lis r4,interrupt_base at h /* IVPR only uses the high 16-bits */
++ mtspr SPRN_IVPR,r4
++
++#ifdef CONFIG_440EP
++ /* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */
++ mfspr r2,SPRN_CCR0
++ lis r3,0xffef
++ ori r3,r3,0xffff
++ and r2,r2,r3
++ mtspr SPRN_CCR0,r2
++ isync
++#endif
++
++ /*
++ * This is where the main kernel code starts.
++ */
++
++ /* ptr to current */
++ lis r2,init_task at h
++ ori r2,r2,init_task at l
++
++ /* ptr to current thread */
++ addi r4,r2,THREAD /* init task's THREAD */
++ mtspr SPRN_SPRG3,r4
++
++ /* stack */
++ lis r1,init_thread_union at h
++ ori r1,r1,init_thread_union at l
++ li r0,0
++ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
++
++ bl early_init
++
++/*
++ * Decide what sort of machine this is and initialize the MMU.
++ */
++ mr r3,r31
++ mr r4,r30
++ mr r5,r29
++ mr r6,r28
++ mr r7,r27
++ bl machine_init
++ bl MMU_init
++
++ /* Setup PTE pointers for the Abatron bdiGDB */
++ lis r6, swapper_pg_dir at h
++ ori r6, r6, swapper_pg_dir at l
++ lis r5, abatron_pteptrs at h
++ ori r5, r5, abatron_pteptrs at l
++ lis r4, KERNELBASE at h
++ ori r4, r4, KERNELBASE at l
++ stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */
++ stw r6, 0(r5)
++
++ /* Let's move on */
++ lis r4,start_kernel at h
++ ori r4,r4,start_kernel at l
++ lis r3,MSR_KERNEL at h
++ ori r3,r3,MSR_KERNEL at l
++ mtspr SPRN_SRR0,r4
++ mtspr SPRN_SRR1,r3
++ rfi /* change context and jump to start_kernel */
++
++/*
++ * Interrupt vector entry code
++ *
++ * The Book E MMUs are always on so we don't need to handle
++ * interrupts in real mode as with previous PPC processors. In
++ * this case we handle interrupts in the kernel virtual address
++ * space.
++ *
++ * Interrupt vectors are dynamically placed relative to the
++ * interrupt prefix as determined by the address of interrupt_base.
++ * The interrupt vectors offsets are programmed using the labels
++ * for each interrupt vector entry.
++ *
++ * Interrupt vectors must be aligned on a 16 byte boundary.
++ * We align on a 32 byte cache line boundary for good measure.
++ */
++
++interrupt_base:
++ /* Critical Input Interrupt */
++ CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
++
++ /* Machine Check Interrupt */
++#ifdef CONFIG_440A
++ MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
++#else
++ CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
++#endif
++
++ /* Data Storage Interrupt */
++ START_EXCEPTION(DataStorage)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++ mtspr SPRN_SPRG4W, r12
++ mtspr SPRN_SPRG5W, r13
++ mfcr r11
++ mtspr SPRN_SPRG7W, r11
++
++ /*
++ * Check if it was a store fault, if not then bail
++ * because a user tried to access a kernel or
++ * read-protected page. Otherwise, get the
++ * offending address and handle it.
++ */
++ mfspr r10, SPRN_ESR
++ andis. r10, r10, ESR_ST at h
++ beq 2f
++
++ mfspr r10, SPRN_DEAR /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ cmplw r10, r11
++ blt+ 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++
++ mfspr r12,SPRN_MMUCR
++ rlwinm r12,r12,0,0,23 /* Clear TID */
++
++ b 4f
++
++ /* Get the PGD for the current thread */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++
++ /* Load PID into MMUCR TID */
++ mfspr r12,SPRN_MMUCR /* Get MMUCR */
++ mfspr r13,SPRN_PID /* Get PID */
++ rlwimi r12,r13,0,24,31 /* Set TID */
++
++4:
++ mtspr SPRN_MMUCR,r12
++
++ rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
++ lwzx r11, r12, r11 /* Get pgd/pmd entry */
++ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
++ beq 2f /* Bail if no table */
++
++ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
++ lwz r11, 4(r12) /* Get pte entry */
++
++ andi. r13, r11, _PAGE_RW /* Is it writeable? */
++ beq 2f /* Bail if not */
++
++ /* Update 'changed'.
++ */
++ ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
++ stw r11, 4(r12) /* Update Linux page table */
++
++ li r13, PPC44x_TLB_SR at l /* Set SR */
++ rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */
++ rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */
++ rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */
++ rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */
++ rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */
++ and r12, r12, r11 /* HWEXEC/RW & USER */
++ rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */
++ rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */
++
++ rlwimi r11,r13,0,26,31 /* Insert static perms */
++
++ rlwinm r11,r11,0,20,15 /* Clear U0-U3 */
++
++ /* find the TLB index that caused the fault. It has to be here. */
++ tlbsx r10, 0, r10
++
++ tlbwe r11, r10, PPC44x_TLB_ATTRIB /* Write ATTRIB */
++
++ /* Done...restore registers and get out of here.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ rfi /* Force context change */
++
++2:
++ /*
++ * The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b data_access
++
++ /* Instruction Storage Interrupt */
++ INSTRUCTION_STORAGE_EXCEPTION
++
++ /* External Input Interrupt */
++ EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
++
++ /* Alignment Interrupt */
++ ALIGNMENT_EXCEPTION
++
++ /* Program Interrupt */
++ PROGRAM_EXCEPTION
++
++ /* Floating Point Unavailable Interrupt */
++#ifdef CONFIG_PPC_FPU
++ FP_UNAVAILABLE_EXCEPTION
++#else
++ EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
++#endif
++
++ /* System Call Interrupt */
++ START_EXCEPTION(SystemCall)
++ NORMAL_EXCEPTION_PROLOG
++ EXC_XFER_EE_LITE(0x0c00, DoSyscall)
++
++ /* Auxillary Processor Unavailable Interrupt */
++ EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
++
++ /* Decrementer Interrupt */
++ DECREMENTER_EXCEPTION
++
++ /* Fixed Internal Timer Interrupt */
++ /* TODO: Add FIT support */
++ EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
++
++ /* Watchdog Timer Interrupt */
++ /* TODO: Add watchdog support */
++#ifdef CONFIG_BOOKE_WDT
++ CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException)
++#else
++ CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception)
++#endif
++
++ /* Data TLB Error Interrupt */
++ START_EXCEPTION(DataTLBError)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++ mtspr SPRN_SPRG4W, r12
++ mtspr SPRN_SPRG5W, r13
++ mfcr r11
++ mtspr SPRN_SPRG7W, r11
++ mfspr r10, SPRN_DEAR /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ cmplw r10, r11
++ blt+ 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++
++ mfspr r12,SPRN_MMUCR
++ rlwinm r12,r12,0,0,23 /* Clear TID */
++
++ b 4f
++
++ /* Get the PGD for the current thread */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++
++ /* Load PID into MMUCR TID */
++ mfspr r12,SPRN_MMUCR
++ mfspr r13,SPRN_PID /* Get PID */
++ rlwimi r12,r13,0,24,31 /* Set TID */
++
++4:
++ mtspr SPRN_MMUCR,r12
++
++ rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
++ lwzx r11, r12, r11 /* Get pgd/pmd entry */
++ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
++ beq 2f /* Bail if no table */
++
++ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
++ lwz r11, 4(r12) /* Get pte entry */
++ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
++ beq 2f /* Bail if not present */
++
++ ori r11, r11, _PAGE_ACCESSED
++ stw r11, 4(r12)
++
++ /* Jump to common tlb load */
++ b finish_tlb_load
++
++2:
++ /* The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b data_access
++
++ /* Instruction TLB Error Interrupt */
++ /*
++ * Nearly the same as above, except we get our
++ * information from different registers and bailout
++ * to a different point.
++ */
++ START_EXCEPTION(InstructionTLBError)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++ mtspr SPRN_SPRG4W, r12
++ mtspr SPRN_SPRG5W, r13
++ mfcr r11
++ mtspr SPRN_SPRG7W, r11
++ mfspr r10, SPRN_SRR0 /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ cmplw r10, r11
++ blt+ 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++
++ mfspr r12,SPRN_MMUCR
++ rlwinm r12,r12,0,0,23 /* Clear TID */
++
++ b 4f
++
++ /* Get the PGD for the current thread */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++
++ /* Load PID into MMUCR TID */
++ mfspr r12,SPRN_MMUCR
++ mfspr r13,SPRN_PID /* Get PID */
++ rlwimi r12,r13,0,24,31 /* Set TID */
++
++4:
++ mtspr SPRN_MMUCR,r12
++
++ rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */
++ lwzx r11, r12, r11 /* Get pgd/pmd entry */
++ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */
++ beq 2f /* Bail if no table */
++
++ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */
++ lwz r11, 4(r12) /* Get pte entry */
++ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
++ beq 2f /* Bail if not present */
++
++ ori r11, r11, _PAGE_ACCESSED
++ stw r11, 4(r12)
++
++ /* Jump to common TLB load point */
++ b finish_tlb_load
++
++2:
++ /* The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b InstructionStorage
++
++ /* Debug Interrupt */
++ DEBUG_EXCEPTION
++
++/*
++ * Local functions
++ */
++ /*
++ * Data TLB exceptions will bail out to this point
++ * if they can't resolve the lightweight TLB fault.
++ */
++data_access:
++ NORMAL_EXCEPTION_PROLOG
++ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
++ stw r5,_ESR(r11)
++ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
++ EXC_XFER_EE_LITE(0x0300, handle_page_fault)
++
++/*
++
++ * Both the instruction and data TLB miss get to this
++ * point to load the TLB.
++ * r10 - EA of fault
++ * r11 - available to use
++ * r12 - Pointer to the 64-bit PTE
++ * r13 - available to use
++ * MMUCR - loaded with proper value when we get here
++ * Upon exit, we reload everything and RFI.
++ */
++finish_tlb_load:
++ /*
++ * We set execute, because we don't have the granularity to
++ * properly set this at the page level (Linux problem).
++ * If shared is set, we cause a zero PID->TID load.
++ * Many of these bits are software only. Bits we don't set
++ * here we (properly should) assume have the appropriate value.
++ */
++
++ /* Load the next available TLB index */
++ lis r13, tlb_44x_index at ha
++ lwz r13, tlb_44x_index at l(r13)
++ /* Load the TLB high watermark */
++ lis r11, tlb_44x_hwater at ha
++ lwz r11, tlb_44x_hwater at l(r11)
++
++ /* Increment, rollover, and store TLB index */
++ addi r13, r13, 1
++ cmpw 0, r13, r11 /* reserve entries */
++ ble 7f
++ li r13, 0
++7:
++ /* Store the next available TLB index */
++ lis r11, tlb_44x_index at ha
++ stw r13, tlb_44x_index at l(r11)
++
++ lwz r11, 0(r12) /* Get MS word of PTE */
++ lwz r12, 4(r12) /* Get LS word of PTE */
++ rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */
++ tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */
++
++ /*
++ * Create PAGEID. This is the faulting address,
++ * page size, and valid flag.
++ */
++ li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K
++ rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */
++ tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */
++
++ li r10, PPC44x_TLB_SR at l /* Set SR */
++ rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */
++ rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */
++ rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */
++ rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */
++ and r11, r12, r11 /* HWEXEC & USER */
++ rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */
++
++ rlwimi r12, r10, 0, 26, 31 /* Insert static perms */
++ rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */
++ tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */
++
++ /* Done...restore registers and get out of here.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ rfi /* Force context change */
++
++/*
++ * Global functions
++ */
++
++/*
++ * extern void giveup_altivec(struct task_struct *prev)
++ *
++ * The 44x core does not have an AltiVec unit.
++ */
++_GLOBAL(giveup_altivec)
++ blr
++
++/*
++ * extern void giveup_fpu(struct task_struct *prev)
++ *
++ * The 44x core does not have an FPU.
++ */
++#ifndef CONFIG_PPC_FPU
++_GLOBAL(giveup_fpu)
++ blr
++#endif
++
++/*
++ * extern void abort(void)
++ *
++ * At present, this routine just applies a system reset.
++ */
++_GLOBAL(abort)
++ mfspr r13,SPRN_DBCR0
++ oris r13,r13,DBCR0_RST_SYSTEM at h
++ mtspr SPRN_DBCR0,r13
++
++_GLOBAL(set_context)
++
++#ifdef CONFIG_BDI_SWITCH
++ /* Context switch the PTE pointer for the Abatron BDI2000.
++ * The PGDIR is the second parameter.
++ */
++ lis r5, abatron_pteptrs at h
++ ori r5, r5, abatron_pteptrs at l
++ stw r4, 0x4(r5)
++#endif
++ mtspr SPRN_PID,r3
++ isync /* Force context change */
++ blr
++
++/*
++ * We put a few things here that have to be page-aligned. This stuff
++ * goes at the beginning of the data segment, which is page-aligned.
++ */
++ .data
++ .align 12
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
++ .space 4096
++
++/*
++ * To support >32-bit physical addresses, we use an 8KB pgdir.
++ */
++ .globl swapper_pg_dir
++swapper_pg_dir:
++ .space 8192
++
++/* Reserved 4k for the critical exception stack & 4k for the machine
++ * check stack per CPU for kernel mode exceptions */
++ .section .bss
++ .align 12
++exception_stack_bottom:
++ .space BOOKE_EXCEPTION_STACK_SIZE
++ .globl exception_stack_top
++exception_stack_top:
++
++/*
++ * This space gets a copy of optional info passed to us by the bootstrap
++ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
++ */
++ .globl cmd_line
++cmd_line:
++ .space 512
++
++/*
++ * Room for two PTE pointers, usually the kernel and current user pointers
++ * to their respective root page table.
++ */
++abatron_pteptrs:
++ .space 8
+diff --git a/arch/powerpc/kernel/head_4xx.S b/arch/powerpc/kernel/head_4xx.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/head_4xx.S
+@@ -0,0 +1,1022 @@
++/*
++ * Copyright (c) 1995-1996 Gary Thomas <gdt at linuxppc.org>
++ * Initial PowerPC version.
++ * Copyright (c) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Rewritten for PReP
++ * Copyright (c) 1996 Paul Mackerras <paulus at cs.anu.edu.au>
++ * Low-level exception handers, MMU support, and rewrite.
++ * Copyright (c) 1997 Dan Malek <dmalek at jlc.net>
++ * PowerPC 8xx modifications.
++ * Copyright (c) 1998-1999 TiVo, Inc.
++ * PowerPC 403GCX modifications.
++ * Copyright (c) 1999 Grant Erickson <grant at lcse.umn.edu>
++ * PowerPC 403GCX/405GP modifications.
++ * Copyright 2000 MontaVista Software Inc.
++ * PPC405 modifications
++ * PowerPC 403GCX/405GP modifications.
++ * Author: MontaVista Software, Inc.
++ * frank_rowand at mvista.com or source at mvista.com
++ * debbie_chu at mvista.com
++ *
++ *
++ * Module name: head_4xx.S
++ *
++ * Description:
++ * Kernel execution entry point code.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/ibm4xx.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++
++/* As with the other PowerPC ports, it is expected that when code
++ * execution begins here, the following registers contain valid, yet
++ * optional, information:
++ *
++ * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
++ * r4 - Starting address of the init RAM disk
++ * r5 - Ending address of the init RAM disk
++ * r6 - Start of kernel command line string (e.g. "mem=96m")
++ * r7 - End of kernel command line string
++ *
++ * This is all going to change RSN when we add bi_recs....... -- Dan
++ */
++ .text
++_GLOBAL(_stext)
++_GLOBAL(_start)
++
++ /* Save parameters we are passed.
++ */
++ mr r31,r3
++ mr r30,r4
++ mr r29,r5
++ mr r28,r6
++ mr r27,r7
++
++ /* We have to turn on the MMU right away so we get cache modes
++ * set correctly.
++ */
++ bl initial_mmu
++
++/* We now have the lower 16 Meg mapped into TLB entries, and the caches
++ * ready to work.
++ */
++turn_on_mmu:
++ lis r0,MSR_KERNEL at h
++ ori r0,r0,MSR_KERNEL at l
++ mtspr SPRN_SRR1,r0
++ lis r0,start_here at h
++ ori r0,r0,start_here at l
++ mtspr SPRN_SRR0,r0
++ SYNC
++ rfi /* enables MMU */
++ b . /* prevent prefetch past rfi */
++
++/*
++ * This area is used for temporarily saving registers during the
++ * critical exception prolog.
++ */
++ . = 0xc0
++crit_save:
++_GLOBAL(crit_r10)
++ .space 4
++_GLOBAL(crit_r11)
++ .space 4
++
++/*
++ * Exception vector entry code. This code runs with address translation
++ * turned off (i.e. using physical addresses). We assume SPRG3 has the
++ * physical address of the current task thread_struct.
++ * Note that we have to have decremented r1 before we write to any fields
++ * of the exception frame, since a critical interrupt could occur at any
++ * time, and it will write to the area immediately below the current r1.
++ */
++#define NORMAL_EXCEPTION_PROLOG \
++ mtspr SPRN_SPRG0,r10; /* save two registers to work with */\
++ mtspr SPRN_SPRG1,r11; \
++ mtspr SPRN_SPRG2,r1; \
++ mfcr r10; /* save CR in r10 for now */\
++ mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
++ andi. r11,r11,MSR_PR; \
++ beq 1f; \
++ mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\
++ lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
++ addi r1,r1,THREAD_SIZE; \
++1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
++ tophys(r11,r1); \
++ stw r10,_CCR(r11); /* save various registers */\
++ stw r12,GPR12(r11); \
++ stw r9,GPR9(r11); \
++ mfspr r10,SPRN_SPRG0; \
++ stw r10,GPR10(r11); \
++ mfspr r12,SPRN_SPRG1; \
++ stw r12,GPR11(r11); \
++ mflr r10; \
++ stw r10,_LINK(r11); \
++ mfspr r10,SPRN_SPRG2; \
++ mfspr r12,SPRN_SRR0; \
++ stw r10,GPR1(r11); \
++ mfspr r9,SPRN_SRR1; \
++ stw r10,0(r11); \
++ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
++ stw r0,GPR0(r11); \
++ SAVE_4GPRS(3, r11); \
++ SAVE_2GPRS(7, r11)
++
++/*
++ * Exception prolog for critical exceptions. This is a little different
++ * from the normal exception prolog above since a critical exception
++ * can potentially occur at any point during normal exception processing.
++ * Thus we cannot use the same SPRG registers as the normal prolog above.
++ * Instead we use a couple of words of memory at low physical addresses.
++ * This is OK since we don't support SMP on these processors.
++ */
++#define CRITICAL_EXCEPTION_PROLOG \
++ stw r10,crit_r10 at l(0); /* save two registers to work with */\
++ stw r11,crit_r11 at l(0); \
++ mfcr r10; /* save CR in r10 for now */\
++ mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
++ andi. r11,r11,MSR_PR; \
++ lis r11,critical_stack_top at h; \
++ ori r11,r11,critical_stack_top at l; \
++ beq 1f; \
++ /* COMING FROM USER MODE */ \
++ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
++ lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
++ addi r11,r11,THREAD_SIZE; \
++1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
++ tophys(r11,r11); \
++ stw r10,_CCR(r11); /* save various registers */\
++ stw r12,GPR12(r11); \
++ stw r9,GPR9(r11); \
++ mflr r10; \
++ stw r10,_LINK(r11); \
++ mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
++ stw r12,_DEAR(r11); /* since they may have had stuff */\
++ mfspr r9,SPRN_ESR; /* in them at the point where the */\
++ stw r9,_ESR(r11); /* exception was taken */\
++ mfspr r12,SPRN_SRR2; \
++ stw r1,GPR1(r11); \
++ mfspr r9,SPRN_SRR3; \
++ stw r1,0(r11); \
++ tovirt(r1,r11); \
++ rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
++ stw r0,GPR0(r11); \
++ SAVE_4GPRS(3, r11); \
++ SAVE_2GPRS(7, r11)
++
++ /*
++ * State at this point:
++ * r9 saved in stack frame, now saved SRR3 & ~MSR_WE
++ * r10 saved in crit_r10 and in stack frame, trashed
++ * r11 saved in crit_r11 and in stack frame,
++ * now phys stack/exception frame pointer
++ * r12 saved in stack frame, now saved SRR2
++ * CR saved in stack frame, CR0.EQ = !SRR3.PR
++ * LR, DEAR, ESR in stack frame
++ * r1 saved in stack frame, now virt stack/excframe pointer
++ * r0, r3-r8 saved in stack frame
++ */
++
++/*
++ * Exception vectors.
++ */
++#define START_EXCEPTION(n, label) \
++ . = n; \
++label:
++
++#define EXCEPTION(n, label, hdlr, xfer) \
++ START_EXCEPTION(n, label); \
++ NORMAL_EXCEPTION_PROLOG; \
++ addi r3,r1,STACK_FRAME_OVERHEAD; \
++ xfer(n, hdlr)
++
++#define CRITICAL_EXCEPTION(n, label, hdlr) \
++ START_EXCEPTION(n, label); \
++ CRITICAL_EXCEPTION_PROLOG; \
++ addi r3,r1,STACK_FRAME_OVERHEAD; \
++ EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
++ NOCOPY, crit_transfer_to_handler, \
++ ret_from_crit_exc)
++
++#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
++ li r10,trap; \
++ stw r10,_TRAP(r11); \
++ lis r10,msr at h; \
++ ori r10,r10,msr at l; \
++ copyee(r10, r9); \
++ bl tfer; \
++ .long hdlr; \
++ .long ret
++
++#define COPY_EE(d, s) rlwimi d,s,0,16,16
++#define NOCOPY(d, s)
++
++#define EXC_XFER_STD(n, hdlr) \
++ EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
++ ret_from_except_full)
++
++#define EXC_XFER_LITE(n, hdlr) \
++ EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
++ ret_from_except)
++
++#define EXC_XFER_EE(n, hdlr) \
++ EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
++ ret_from_except_full)
++
++#define EXC_XFER_EE_LITE(n, hdlr) \
++ EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
++ ret_from_except)
++
++
++/*
++ * 0x0100 - Critical Interrupt Exception
++ */
++ CRITICAL_EXCEPTION(0x0100, CriticalInterrupt, unknown_exception)
++
++/*
++ * 0x0200 - Machine Check Exception
++ */
++ CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
++
++/*
++ * 0x0300 - Data Storage Exception
++ * This happens for just a few reasons. U0 set (but we don't do that),
++ * or zone protection fault (user violation, write to protected page).
++ * If this is just an update of modified status, we do that quickly
++ * and exit. Otherwise, we call heavywight functions to do the work.
++ */
++ START_EXCEPTION(0x0300, DataStorage)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++#ifdef CONFIG_403GCX
++ stw r12, 0(r0)
++ stw r9, 4(r0)
++ mfcr r11
++ mfspr r12, SPRN_PID
++ stw r11, 8(r0)
++ stw r12, 12(r0)
++#else
++ mtspr SPRN_SPRG4, r12
++ mtspr SPRN_SPRG5, r9
++ mfcr r11
++ mfspr r12, SPRN_PID
++ mtspr SPRN_SPRG7, r11
++ mtspr SPRN_SPRG6, r12
++#endif
++
++ /* First, check if it was a zone fault (which means a user
++ * tried to access a kernel or read-protected page - always
++ * a SEGV). All other faults here must be stores, so no
++ * need to check ESR_DST as well. */
++ mfspr r10, SPRN_ESR
++ andis. r10, r10, ESR_DIZ at h
++ bne 2f
++
++ mfspr r10, SPRN_DEAR /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ cmplw r10, r11
++ blt+ 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++ li r9, 0
++ mtspr SPRN_PID, r9 /* TLB will have 0 TID */
++ b 4f
++
++ /* Get the PGD for the current thread.
++ */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++4:
++ tophys(r11, r11)
++ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
++ lwz r11, 0(r11) /* Get L1 entry */
++ rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */
++ beq 2f /* Bail if no table */
++
++ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
++ lwz r11, 0(r12) /* Get Linux PTE */
++
++ andi. r9, r11, _PAGE_RW /* Is it writeable? */
++ beq 2f /* Bail if not */
++
++ /* Update 'changed'.
++ */
++ ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
++ stw r11, 0(r12) /* Update Linux page table */
++
++ /* Most of the Linux PTE is ready to load into the TLB LO.
++ * We set ZSEL, where only the LS-bit determines user access.
++ * We set execute, because we don't have the granularity to
++ * properly set this at the page level (Linux problem).
++ * If shared is set, we cause a zero PID->TID load.
++ * Many of these bits are software only. Bits we don't set
++ * here we (properly should) assume have the appropriate value.
++ */
++ li r12, 0x0ce2
++ andc r11, r11, r12 /* Make sure 20, 21 are zero */
++
++ /* find the TLB index that caused the fault. It has to be here.
++ */
++ tlbsx r9, 0, r10
++
++ tlbwe r11, r9, TLB_DATA /* Load TLB LO */
++
++ /* Done...restore registers and get out of here.
++ */
++#ifdef CONFIG_403GCX
++ lwz r12, 12(r0)
++ lwz r11, 8(r0)
++ mtspr SPRN_PID, r12
++ mtcr r11
++ lwz r9, 4(r0)
++ lwz r12, 0(r0)
++#else
++ mfspr r12, SPRN_SPRG6
++ mfspr r11, SPRN_SPRG7
++ mtspr SPRN_PID, r12
++ mtcr r11
++ mfspr r9, SPRN_SPRG5
++ mfspr r12, SPRN_SPRG4
++#endif
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ PPC405_ERR77_SYNC
++ rfi /* Should sync shadow TLBs */
++ b . /* prevent prefetch past rfi */
++
++2:
++ /* The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++#ifdef CONFIG_403GCX
++ lwz r12, 12(r0)
++ lwz r11, 8(r0)
++ mtspr SPRN_PID, r12
++ mtcr r11
++ lwz r9, 4(r0)
++ lwz r12, 0(r0)
++#else
++ mfspr r12, SPRN_SPRG6
++ mfspr r11, SPRN_SPRG7
++ mtspr SPRN_PID, r12
++ mtcr r11
++ mfspr r9, SPRN_SPRG5
++ mfspr r12, SPRN_SPRG4
++#endif
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b DataAccess
++
++/*
++ * 0x0400 - Instruction Storage Exception
++ * This is caused by a fetch from non-execute or guarded pages.
++ */
++ START_EXCEPTION(0x0400, InstructionAccess)
++ NORMAL_EXCEPTION_PROLOG
++ mr r4,r12 /* Pass SRR0 as arg2 */
++ li r5,0 /* Pass zero as arg3 */
++ EXC_XFER_EE_LITE(0x400, handle_page_fault)
++
++/* 0x0500 - External Interrupt Exception */
++ EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
++
++/* 0x0600 - Alignment Exception */
++ START_EXCEPTION(0x0600, Alignment)
++ NORMAL_EXCEPTION_PROLOG
++ mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */
++ stw r4,_DEAR(r11)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_EE(0x600, alignment_exception)
++
++/* 0x0700 - Program Exception */
++ START_EXCEPTION(0x0700, ProgramCheck)
++ NORMAL_EXCEPTION_PROLOG
++ mfspr r4,SPRN_ESR /* Grab the ESR and save it */
++ stw r4,_ESR(r11)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_STD(0x700, program_check_exception)
++
++ EXCEPTION(0x0800, Trap_08, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0900, Trap_09, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0A00, Trap_0A, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0B00, Trap_0B, unknown_exception, EXC_XFER_EE)
++
++/* 0x0C00 - System Call Exception */
++ START_EXCEPTION(0x0C00, SystemCall)
++ NORMAL_EXCEPTION_PROLOG
++ EXC_XFER_EE_LITE(0xc00, DoSyscall)
++
++ EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_EE)
++
++/* 0x1000 - Programmable Interval Timer (PIT) Exception */
++ START_EXCEPTION(0x1000, Decrementer)
++ NORMAL_EXCEPTION_PROLOG
++ lis r0,TSR_PIS at h
++ mtspr SPRN_TSR,r0 /* Clear the PIT exception */
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_LITE(0x1000, timer_interrupt)
++
++#if 0
++/* NOTE:
++ * FIT and WDT handlers are not implemented yet.
++ */
++
++/* 0x1010 - Fixed Interval Timer (FIT) Exception
++*/
++ STND_EXCEPTION(0x1010, FITException, unknown_exception)
++
++/* 0x1020 - Watchdog Timer (WDT) Exception
++*/
++#ifdef CONFIG_BOOKE_WDT
++ CRITICAL_EXCEPTION(0x1020, WDTException, WatchdogException)
++#else
++ CRITICAL_EXCEPTION(0x1020, WDTException, unknown_exception)
++#endif
++#endif
++
++/* 0x1100 - Data TLB Miss Exception
++ * As the name implies, translation is not in the MMU, so search the
++ * page tables and fix it. The only purpose of this function is to
++ * load TLB entries from the page table if they exist.
++ */
++ START_EXCEPTION(0x1100, DTLBMiss)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++#ifdef CONFIG_403GCX
++ stw r12, 0(r0)
++ stw r9, 4(r0)
++ mfcr r11
++ mfspr r12, SPRN_PID
++ stw r11, 8(r0)
++ stw r12, 12(r0)
++#else
++ mtspr SPRN_SPRG4, r12
++ mtspr SPRN_SPRG5, r9
++ mfcr r11
++ mfspr r12, SPRN_PID
++ mtspr SPRN_SPRG7, r11
++ mtspr SPRN_SPRG6, r12
++#endif
++ mfspr r10, SPRN_DEAR /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ cmplw r10, r11
++ blt+ 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++ li r9, 0
++ mtspr SPRN_PID, r9 /* TLB will have 0 TID */
++ b 4f
++
++ /* Get the PGD for the current thread.
++ */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++4:
++ tophys(r11, r11)
++ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
++ lwz r12, 0(r11) /* Get L1 entry */
++ andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
++ beq 2f /* Bail if no table */
++
++ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
++ lwz r11, 0(r12) /* Get Linux PTE */
++ andi. r9, r11, _PAGE_PRESENT
++ beq 5f
++
++ ori r11, r11, _PAGE_ACCESSED
++ stw r11, 0(r12)
++
++ /* Create TLB tag. This is the faulting address plus a static
++ * set of bits. These are size, valid, E, U0.
++ */
++ li r12, 0x00c0
++ rlwimi r10, r12, 0, 20, 31
++
++ b finish_tlb_load
++
++2: /* Check for possible large-page pmd entry */
++ rlwinm. r9, r12, 2, 22, 24
++ beq 5f
++
++ /* Create TLB tag. This is the faulting address, plus a static
++ * set of bits (valid, E, U0) plus the size from the PMD.
++ */
++ ori r9, r9, 0x40
++ rlwimi r10, r9, 0, 20, 31
++ mr r11, r12
++
++ b finish_tlb_load
++
++5:
++ /* The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++#ifdef CONFIG_403GCX
++ lwz r12, 12(r0)
++ lwz r11, 8(r0)
++ mtspr SPRN_PID, r12
++ mtcr r11
++ lwz r9, 4(r0)
++ lwz r12, 0(r0)
++#else
++ mfspr r12, SPRN_SPRG6
++ mfspr r11, SPRN_SPRG7
++ mtspr SPRN_PID, r12
++ mtcr r11
++ mfspr r9, SPRN_SPRG5
++ mfspr r12, SPRN_SPRG4
++#endif
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b DataAccess
++
++/* 0x1200 - Instruction TLB Miss Exception
++ * Nearly the same as above, except we get our information from different
++ * registers and bailout to a different point.
++ */
++ START_EXCEPTION(0x1200, ITLBMiss)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++#ifdef CONFIG_403GCX
++ stw r12, 0(r0)
++ stw r9, 4(r0)
++ mfcr r11
++ mfspr r12, SPRN_PID
++ stw r11, 8(r0)
++ stw r12, 12(r0)
++#else
++ mtspr SPRN_SPRG4, r12
++ mtspr SPRN_SPRG5, r9
++ mfcr r11
++ mfspr r12, SPRN_PID
++ mtspr SPRN_SPRG7, r11
++ mtspr SPRN_SPRG6, r12
++#endif
++ mfspr r10, SPRN_SRR0 /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ cmplw r10, r11
++ blt+ 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++ li r9, 0
++ mtspr SPRN_PID, r9 /* TLB will have 0 TID */
++ b 4f
++
++ /* Get the PGD for the current thread.
++ */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++4:
++ tophys(r11, r11)
++ rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
++ lwz r12, 0(r11) /* Get L1 entry */
++ andi. r9, r12, _PMD_PRESENT /* Check if it points to a PTE page */
++ beq 2f /* Bail if no table */
++
++ rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */
++ lwz r11, 0(r12) /* Get Linux PTE */
++ andi. r9, r11, _PAGE_PRESENT
++ beq 5f
++
++ ori r11, r11, _PAGE_ACCESSED
++ stw r11, 0(r12)
++
++ /* Create TLB tag. This is the faulting address plus a static
++ * set of bits. These are size, valid, E, U0.
++ */
++ li r12, 0x00c0
++ rlwimi r10, r12, 0, 20, 31
++
++ b finish_tlb_load
++
++2: /* Check for possible large-page pmd entry */
++ rlwinm. r9, r12, 2, 22, 24
++ beq 5f
++
++ /* Create TLB tag. This is the faulting address, plus a static
++ * set of bits (valid, E, U0) plus the size from the PMD.
++ */
++ ori r9, r9, 0x40
++ rlwimi r10, r9, 0, 20, 31
++ mr r11, r12
++
++ b finish_tlb_load
++
++5:
++ /* The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++#ifdef CONFIG_403GCX
++ lwz r12, 12(r0)
++ lwz r11, 8(r0)
++ mtspr SPRN_PID, r12
++ mtcr r11
++ lwz r9, 4(r0)
++ lwz r12, 0(r0)
++#else
++ mfspr r12, SPRN_SPRG6
++ mfspr r11, SPRN_SPRG7
++ mtspr SPRN_PID, r12
++ mtcr r11
++ mfspr r9, SPRN_SPRG5
++ mfspr r12, SPRN_SPRG4
++#endif
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b InstructionAccess
++
++ EXCEPTION(0x1300, Trap_13, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1400, Trap_14, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
++#ifdef CONFIG_IBM405_ERR51
++ /* 405GP errata 51 */
++ START_EXCEPTION(0x1700, Trap_17)
++ b DTLBMiss
++#else
++ EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_EE)
++#endif
++ EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1A00, Trap_1A, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1B00, Trap_1B, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1C00, Trap_1C, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1D00, Trap_1D, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1E00, Trap_1E, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1F00, Trap_1F, unknown_exception, EXC_XFER_EE)
++
++/* Check for a single step debug exception while in an exception
++ * handler before state has been saved. This is to catch the case
++ * where an instruction that we are trying to single step causes
++ * an exception (eg ITLB/DTLB miss) and thus the first instruction of
++ * the exception handler generates a single step debug exception.
++ *
++ * If we get a debug trap on the first instruction of an exception handler,
++ * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
++ * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
++ * The exception handler was handling a non-critical interrupt, so it will
++ * save (and later restore) the MSR via SPRN_SRR1, which will still have
++ * the MSR_DE bit set.
++ */
++ /* 0x2000 - Debug Exception */
++ START_EXCEPTION(0x2000, DebugTrap)
++ CRITICAL_EXCEPTION_PROLOG
++
++ /*
++ * If this is a single step or branch-taken exception in an
++ * exception entry sequence, it was probably meant to apply to
++ * the code where the exception occurred (since exception entry
++ * doesn't turn off DE automatically). We simulate the effect
++ * of turning off DE on entry to an exception handler by turning
++ * off DE in the SRR3 value and clearing the debug status.
++ */
++ mfspr r10,SPRN_DBSR /* check single-step/branch taken */
++ andis. r10,r10,DBSR_IC at h
++ beq+ 2f
++
++ andi. r10,r9,MSR_IR|MSR_PR /* check supervisor + MMU off */
++ beq 1f /* branch and fix it up */
++
++ mfspr r10,SPRN_SRR2 /* Faulting instruction address */
++ cmplwi r10,0x2100
++ bgt+ 2f /* address above exception vectors */
++
++ /* here it looks like we got an inappropriate debug exception. */
++1: rlwinm r9,r9,0,~MSR_DE /* clear DE in the SRR3 value */
++ lis r10,DBSR_IC at h /* clear the IC event */
++ mtspr SPRN_DBSR,r10
++ /* restore state and get out */
++ lwz r10,_CCR(r11)
++ lwz r0,GPR0(r11)
++ lwz r1,GPR1(r11)
++ mtcrf 0x80,r10
++ mtspr SPRN_SRR2,r12
++ mtspr SPRN_SRR3,r9
++ lwz r9,GPR9(r11)
++ lwz r12,GPR12(r11)
++ lwz r10,crit_r10 at l(0)
++ lwz r11,crit_r11 at l(0)
++ PPC405_ERR77_SYNC
++ rfci
++ b .
++
++ /* continue normal handling for a critical exception... */
++2: mfspr r4,SPRN_DBSR
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_TEMPLATE(DebugException, 0x2002, \
++ (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
++ NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
++
++/*
++ * The other Data TLB exceptions bail out to this point
++ * if they can't resolve the lightweight TLB fault.
++ */
++DataAccess:
++ NORMAL_EXCEPTION_PROLOG
++ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
++ stw r5,_ESR(r11)
++ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
++ EXC_XFER_EE_LITE(0x300, handle_page_fault)
++
++/* Other PowerPC processors, namely those derived from the 6xx-series
++ * have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
++ * However, for the 4xx-series processors these are neither defined nor
++ * reserved.
++ */
++
++ /* Damn, I came up one instruction too many to fit into the
++ * exception space :-). Both the instruction and data TLB
++ * miss get to this point to load the TLB.
++ * r10 - TLB_TAG value
++ * r11 - Linux PTE
++ * r12, r9 - avilable to use
++ * PID - loaded with proper value when we get here
++ * Upon exit, we reload everything and RFI.
++ * Actually, it will fit now, but oh well.....a common place
++ * to load the TLB.
++ */
++tlb_4xx_index:
++ .long 0
++finish_tlb_load:
++ /* load the next available TLB index.
++ */
++ lwz r9, tlb_4xx_index at l(0)
++ addi r9, r9, 1
++ andi. r9, r9, (PPC4XX_TLB_SIZE-1)
++ stw r9, tlb_4xx_index at l(0)
++
++6:
++ /*
++ * Clear out the software-only bits in the PTE to generate the
++ * TLB_DATA value. These are the bottom 2 bits of the RPM, the
++ * top 3 bits of the zone field, and M.
++ */
++ li r12, 0x0ce2
++ andc r11, r11, r12
++
++ tlbwe r11, r9, TLB_DATA /* Load TLB LO */
++ tlbwe r10, r9, TLB_TAG /* Load TLB HI */
++
++ /* Done...restore registers and get out of here.
++ */
++#ifdef CONFIG_403GCX
++ lwz r12, 12(r0)
++ lwz r11, 8(r0)
++ mtspr SPRN_PID, r12
++ mtcr r11
++ lwz r9, 4(r0)
++ lwz r12, 0(r0)
++#else
++ mfspr r12, SPRN_SPRG6
++ mfspr r11, SPRN_SPRG7
++ mtspr SPRN_PID, r12
++ mtcr r11
++ mfspr r9, SPRN_SPRG5
++ mfspr r12, SPRN_SPRG4
++#endif
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ PPC405_ERR77_SYNC
++ rfi /* Should sync shadow TLBs */
++ b . /* prevent prefetch past rfi */
++
++/* extern void giveup_fpu(struct task_struct *prev)
++ *
++ * The PowerPC 4xx family of processors do not have an FPU, so this just
++ * returns.
++ */
++_GLOBAL(giveup_fpu)
++ blr
++
++/* This is where the main kernel code starts.
++ */
++start_here:
++
++ /* ptr to current */
++ lis r2,init_task at h
++ ori r2,r2,init_task at l
++
++ /* ptr to phys current thread */
++ tophys(r4,r2)
++ addi r4,r4,THREAD /* init task's THREAD */
++ mtspr SPRN_SPRG3,r4
++
++ /* stack */
++ lis r1,init_thread_union at ha
++ addi r1,r1,init_thread_union at l
++ li r0,0
++ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
++
++ bl early_init /* We have to do this with MMU on */
++
++/*
++ * Decide what sort of machine this is and initialize the MMU.
++ */
++ mr r3,r31
++ mr r4,r30
++ mr r5,r29
++ mr r6,r28
++ mr r7,r27
++ bl machine_init
++ bl MMU_init
++
++/* Go back to running unmapped so we can load up new values
++ * and change to using our exception vectors.
++ * On the 4xx, all we have to do is invalidate the TLB to clear
++ * the old 16M byte TLB mappings.
++ */
++ lis r4,2f at h
++ ori r4,r4,2f at l
++ tophys(r4,r4)
++ lis r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@h
++ ori r3,r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@l
++ mtspr SPRN_SRR0,r4
++ mtspr SPRN_SRR1,r3
++ rfi
++ b . /* prevent prefetch past rfi */
++
++/* Load up the kernel context */
++2:
++ sync /* Flush to memory before changing TLB */
++ tlbia
++ isync /* Flush shadow TLBs */
++
++ /* set up the PTE pointers for the Abatron bdiGDB.
++ */
++ lis r6, swapper_pg_dir at h
++ ori r6, r6, swapper_pg_dir at l
++ lis r5, abatron_pteptrs at h
++ ori r5, r5, abatron_pteptrs at l
++ stw r5, 0xf0(r0) /* Must match your Abatron config file */
++ tophys(r5,r5)
++ stw r6, 0(r5)
++
++/* Now turn on the MMU for real! */
++ lis r4,MSR_KERNEL at h
++ ori r4,r4,MSR_KERNEL at l
++ lis r3,start_kernel at h
++ ori r3,r3,start_kernel at l
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
++ rfi /* enable MMU and jump to start_kernel */
++ b . /* prevent prefetch past rfi */
++
++/* Set up the initial MMU state so we can do the first level of
++ * kernel initialization. This maps the first 16 MBytes of memory 1:1
++ * virtual to physical and more importantly sets the cache mode.
++ */
++initial_mmu:
++ tlbia /* Invalidate all TLB entries */
++ isync
++
++ /* We should still be executing code at physical address 0x0000xxxx
++ * at this point. However, start_here is at virtual address
++ * 0xC000xxxx. So, set up a TLB mapping to cover this once
++ * translation is enabled.
++ */
++
++ lis r3,KERNELBASE at h /* Load the kernel virtual address */
++ ori r3,r3,KERNELBASE at l
++ tophys(r4,r3) /* Load the kernel physical address */
++
++ iccci r0,r3 /* Invalidate the i-cache before use */
++
++ /* Load the kernel PID.
++ */
++ li r0,0
++ mtspr SPRN_PID,r0
++ sync
++
++ /* Configure and load two entries into TLB slots 62 and 63.
++ * In case we are pinning TLBs, these are reserved in by the
++ * other TLB functions. If not reserving, then it doesn't
++ * matter where they are loaded.
++ */
++ clrrwi r4,r4,10 /* Mask off the real page number */
++ ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */
++
++ clrrwi r3,r3,10 /* Mask off the effective page number */
++ ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
++
++ li r0,63 /* TLB slot 63 */
++
++ tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */
++ tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */
++
++#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(SERIAL_DEBUG_IO_BASE)
++
++ /* Load a TLB entry for the UART, so that ppc4xx_progress() can use
++ * the UARTs nice and early. We use a 4k real==virtual mapping. */
++
++ lis r3,SERIAL_DEBUG_IO_BASE at h
++ ori r3,r3,SERIAL_DEBUG_IO_BASE at l
++ mr r4,r3
++ clrrwi r4,r4,12
++ ori r4,r4,(TLB_WR|TLB_I|TLB_M|TLB_G)
++
++ clrrwi r3,r3,12
++ ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))
++
++ li r0,0 /* TLB slot 0 */
++ tlbwe r4,r0,TLB_DATA
++ tlbwe r3,r0,TLB_TAG
++#endif /* CONFIG_SERIAL_DEBUG_TEXT && SERIAL_DEBUG_IO_BASE */
++
++ isync
++
++ /* Establish the exception vector base
++ */
++ lis r4,KERNELBASE at h /* EVPR only uses the high 16-bits */
++ tophys(r0,r4) /* Use the physical address */
++ mtspr SPRN_EVPR,r0
++
++ blr
++
++_GLOBAL(abort)
++ mfspr r13,SPRN_DBCR0
++ oris r13,r13,DBCR0_RST_SYSTEM at h
++ mtspr SPRN_DBCR0,r13
++
++_GLOBAL(set_context)
++
++#ifdef CONFIG_BDI_SWITCH
++ /* Context switch the PTE pointer for the Abatron BDI2000.
++ * The PGDIR is the second parameter.
++ */
++ lis r5, KERNELBASE at h
++ lwz r5, 0xf0(r5)
++ stw r4, 0x4(r5)
++#endif
++ sync
++ mtspr SPRN_PID,r3
++ isync /* Need an isync to flush shadow */
++ /* TLBs after changing PID */
++ blr
++
++/* We put a few things here that have to be page-aligned. This stuff
++ * goes at the beginning of the data segment, which is page-aligned.
++ */
++ .data
++ .align 12
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
++ .space 4096
++ .globl swapper_pg_dir
++swapper_pg_dir:
++ .space 4096
++
++
++/* Stack for handling critical exceptions from kernel mode */
++ .section .bss
++ .align 12
++exception_stack_bottom:
++ .space 4096
++critical_stack_top:
++ .globl exception_stack_top
++exception_stack_top:
++
++/* This space gets a copy of optional info passed to us by the bootstrap
++ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
++ */
++ .globl cmd_line
++cmd_line:
++ .space 512
++
++/* Room for two PTE pointers, usually the kernel and current user pointers
++ * to their respective root page table.
++ */
++abatron_pteptrs:
++ .space 8
+diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/head_64.S
+@@ -0,0 +1,1957 @@
++/*
++ * arch/ppc64/kernel/head.S
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Rewritten by Cort Dougan (cort at cs.nmt.edu) for PReP
++ * Copyright (C) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Adapted for Power Macintosh by Paul Mackerras.
++ * Low-level exception handlers and MMU support
++ * rewritten by Paul Mackerras.
++ * Copyright (C) 1996 Paul Mackerras.
++ *
++ * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
++ * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
++ *
++ * This file contains the low-level support and setup for the
++ * PowerPC-64 platform, including trap and interrupt dispatch.
++ *
++ * 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/threads.h>
++#include <asm/reg.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/systemcfg.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/bug.h>
++#include <asm/cputable.h>
++#include <asm/setup.h>
++#include <asm/hvcall.h>
++#include <asm/iSeries/LparMap.h>
++#include <asm/thread_info.h>
++
++#ifdef CONFIG_PPC_ISERIES
++#define DO_SOFT_DISABLE
++#endif
++
++/*
++ * We layout physical memory as follows:
++ * 0x0000 - 0x00ff : Secondary processor spin code
++ * 0x0100 - 0x2fff : pSeries Interrupt prologs
++ * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs
++ * 0x6000 - 0x6fff : Initial (CPU0) segment table
++ * 0x7000 - 0x7fff : FWNMI data area
++ * 0x8000 - : Early init and support code
++ */
++
++/*
++ * SPRG Usage
++ *
++ * Register Definition
++ *
++ * SPRG0 reserved for hypervisor
++ * SPRG1 temp - used to save gpr
++ * SPRG2 temp - used to save gpr
++ * SPRG3 virt addr of paca
++ */
++
++/*
++ * Entering into this code we make the following assumptions:
++ * For pSeries:
++ * 1. The MMU is off & open firmware is running in real mode.
++ * 2. The kernel is entered at __start
++ *
++ * For iSeries:
++ * 1. The MMU is on (as it always is for iSeries)
++ * 2. The kernel is entered at system_reset_iSeries
++ */
++
++ .text
++ .globl _stext
++_stext:
++#ifdef CONFIG_PPC_MULTIPLATFORM
++_GLOBAL(__start)
++ /* NOP this out unconditionally */
++BEGIN_FTR_SECTION
++ b .__start_initialization_multiplatform
++END_FTR_SECTION(0, 1)
++#endif /* CONFIG_PPC_MULTIPLATFORM */
++
++ /* Catch branch to 0 in real mode */
++ trap
++
++#ifdef CONFIG_PPC_ISERIES
++ /*
++ * At offset 0x20, there is a pointer to iSeries LPAR data.
++ * This is required by the hypervisor
++ */
++ . = 0x20
++ .llong hvReleaseData-KERNELBASE
++
++ /*
++ * At offset 0x28 and 0x30 are offsets to the mschunks_map
++ * array (used by the iSeries LPAR debugger to do translation
++ * between physical addresses and absolute addresses) and
++ * to the pidhash table (also used by the debugger)
++ */
++ .llong mschunks_map-KERNELBASE
++ .llong 0 /* pidhash-KERNELBASE SFRXXX */
++
++ /* Offset 0x38 - Pointer to start of embedded System.map */
++ .globl embedded_sysmap_start
++embedded_sysmap_start:
++ .llong 0
++ /* Offset 0x40 - Pointer to end of embedded System.map */
++ .globl embedded_sysmap_end
++embedded_sysmap_end:
++ .llong 0
++
++#endif /* CONFIG_PPC_ISERIES */
++
++ /* Secondary processors spin on this value until it goes to 1. */
++ .globl __secondary_hold_spinloop
++__secondary_hold_spinloop:
++ .llong 0x0
++
++ /* Secondary processors write this value with their cpu # */
++ /* after they enter the spin loop immediately below. */
++ .globl __secondary_hold_acknowledge
++__secondary_hold_acknowledge:
++ .llong 0x0
++
++ . = 0x60
++/*
++ * The following code is used on pSeries to hold secondary processors
++ * in a spin loop after they have been freed from OpenFirmware, but
++ * before the bulk of the kernel has been relocated. This code
++ * is relocated to physical address 0x60 before prom_init is run.
++ * All of it must fit below the first exception vector at 0x100.
++ */
++_GLOBAL(__secondary_hold)
++ mfmsr r24
++ ori r24,r24,MSR_RI
++ mtmsrd r24 /* RI on */
++
++ /* Grab our linux cpu number */
++ mr r24,r3
++
++ /* Tell the master cpu we're here */
++ /* Relocation is off & we are located at an address less */
++ /* than 0x100, so only need to grab low order offset. */
++ std r24,__secondary_hold_acknowledge at l(0)
++ sync
++
++ /* All secondary cpus wait here until told to start. */
++100: ld r4,__secondary_hold_spinloop at l(0)
++ cmpdi 0,r4,1
++ bne 100b
++
++#ifdef CONFIG_HMT
++ b .hmt_init
++#else
++#ifdef CONFIG_SMP
++ mr r3,r24
++ b .pSeries_secondary_smp_init
++#else
++ BUG_OPCODE
++#endif
++#endif
++
++/* This value is used to mark exception frames on the stack. */
++ .section ".toc","aw"
++exception_marker:
++ .tc ID_72656773_68657265[TC],0x7265677368657265
++ .text
++
++/*
++ * The following macros define the code that appears as
++ * the prologue to each of the exception handlers. They
++ * are split into two parts to allow a single kernel binary
++ * to be used for pSeries and iSeries.
++ * LOL. One day... - paulus
++ */
++
++/*
++ * We make as much of the exception code common between native
++ * exception handlers (including pSeries LPAR) and iSeries LPAR
++ * implementations as possible.
++ */
++
++/*
++ * This is the start of the interrupt handlers for pSeries
++ * This code runs with relocation off.
++ */
++#define EX_R9 0
++#define EX_R10 8
++#define EX_R11 16
++#define EX_R12 24
++#define EX_R13 32
++#define EX_SRR0 40
++#define EX_R3 40 /* SLB miss saves R3, but not SRR0 */
++#define EX_DAR 48
++#define EX_LR 48 /* SLB miss saves LR, but not DAR */
++#define EX_DSISR 56
++#define EX_CCR 60
++
++#define EXCEPTION_PROLOG_PSERIES(area, label) \
++ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
++ std r9,area+EX_R9(r13); /* save r9 - r12 */ \
++ std r10,area+EX_R10(r13); \
++ std r11,area+EX_R11(r13); \
++ std r12,area+EX_R12(r13); \
++ mfspr r9,SPRN_SPRG1; \
++ std r9,area+EX_R13(r13); \
++ mfcr r9; \
++ clrrdi r12,r13,32; /* get high part of &label */ \
++ mfmsr r10; \
++ mfspr r11,SPRN_SRR0; /* save SRR0 */ \
++ ori r12,r12,(label)@l; /* virt addr of handler */ \
++ ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
++ mtspr SPRN_SRR0,r12; \
++ mfspr r12,SPRN_SRR1; /* and SRR1 */ \
++ mtspr SPRN_SRR1,r10; \
++ rfid; \
++ b . /* prevent speculative execution */
++
++/*
++ * This is the start of the interrupt handlers for iSeries
++ * This code runs with relocation on.
++ */
++#define EXCEPTION_PROLOG_ISERIES_1(area) \
++ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
++ std r9,area+EX_R9(r13); /* save r9 - r12 */ \
++ std r10,area+EX_R10(r13); \
++ std r11,area+EX_R11(r13); \
++ std r12,area+EX_R12(r13); \
++ mfspr r9,SPRN_SPRG1; \
++ std r9,area+EX_R13(r13); \
++ mfcr r9
++
++#define EXCEPTION_PROLOG_ISERIES_2 \
++ mfmsr r10; \
++ ld r11,PACALPPACA+LPPACASRR0(r13); \
++ ld r12,PACALPPACA+LPPACASRR1(r13); \
++ ori r10,r10,MSR_RI; \
++ mtmsrd r10,1
++
++/*
++ * The common exception prolog is used for all except a few exceptions
++ * such as a segment miss on a kernel address. We have to be prepared
++ * to take another exception from the point where we first touch the
++ * kernel stack onwards.
++ *
++ * On entry r13 points to the paca, r9-r13 are saved in the paca,
++ * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and
++ * SRR1, and relocation is on.
++ */
++#define EXCEPTION_PROLOG_COMMON(n, area) \
++ andi. r10,r12,MSR_PR; /* See if coming from user */ \
++ mr r10,r1; /* Save r1 */ \
++ subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \
++ beq- 1f; \
++ ld r1,PACAKSAVE(r13); /* kernel stack to use */ \
++1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \
++ bge- cr1,bad_stack; /* abort if it is */ \
++ std r9,_CCR(r1); /* save CR in stackframe */ \
++ std r11,_NIP(r1); /* save SRR0 in stackframe */ \
++ std r12,_MSR(r1); /* save SRR1 in stackframe */ \
++ std r10,0(r1); /* make stack chain pointer */ \
++ std r0,GPR0(r1); /* save r0 in stackframe */ \
++ std r10,GPR1(r1); /* save r1 in stackframe */ \
++ std r2,GPR2(r1); /* save r2 in stackframe */ \
++ SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \
++ SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \
++ ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \
++ ld r10,area+EX_R10(r13); \
++ std r9,GPR9(r1); \
++ std r10,GPR10(r1); \
++ ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \
++ ld r10,area+EX_R12(r13); \
++ ld r11,area+EX_R13(r13); \
++ std r9,GPR11(r1); \
++ std r10,GPR12(r1); \
++ std r11,GPR13(r1); \
++ ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \
++ mflr r9; /* save LR in stackframe */ \
++ std r9,_LINK(r1); \
++ mfctr r10; /* save CTR in stackframe */ \
++ std r10,_CTR(r1); \
++ mfspr r11,SPRN_XER; /* save XER in stackframe */ \
++ std r11,_XER(r1); \
++ li r9,(n)+1; \
++ std r9,_TRAP(r1); /* set trap number */ \
++ li r10,0; \
++ ld r11,exception_marker at toc(r2); \
++ std r10,RESULT(r1); /* clear regs->result */ \
++ std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */
++
++/*
++ * Exception vectors.
++ */
++#define STD_EXCEPTION_PSERIES(n, label) \
++ . = n; \
++ .globl label##_pSeries; \
++label##_pSeries: \
++ HMT_MEDIUM; \
++ mtspr SPRN_SPRG1,r13; /* save r13 */ \
++ RUNLATCH_ON(r13); \
++ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
++
++#define STD_EXCEPTION_ISERIES(n, label, area) \
++ .globl label##_iSeries; \
++label##_iSeries: \
++ HMT_MEDIUM; \
++ mtspr SPRN_SPRG1,r13; /* save r13 */ \
++ RUNLATCH_ON(r13); \
++ EXCEPTION_PROLOG_ISERIES_1(area); \
++ EXCEPTION_PROLOG_ISERIES_2; \
++ b label##_common
++
++#define MASKABLE_EXCEPTION_ISERIES(n, label) \
++ .globl label##_iSeries; \
++label##_iSeries: \
++ HMT_MEDIUM; \
++ mtspr SPRN_SPRG1,r13; /* save r13 */ \
++ RUNLATCH_ON(r13); \
++ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \
++ lbz r10,PACAPROCENABLED(r13); \
++ cmpwi 0,r10,0; \
++ beq- label##_iSeries_masked; \
++ EXCEPTION_PROLOG_ISERIES_2; \
++ b label##_common; \
++
++#ifdef DO_SOFT_DISABLE
++#define DISABLE_INTS \
++ lbz r10,PACAPROCENABLED(r13); \
++ li r11,0; \
++ std r10,SOFTE(r1); \
++ mfmsr r10; \
++ stb r11,PACAPROCENABLED(r13); \
++ ori r10,r10,MSR_EE; \
++ mtmsrd r10,1
++
++#define ENABLE_INTS \
++ lbz r10,PACAPROCENABLED(r13); \
++ mfmsr r11; \
++ std r10,SOFTE(r1); \
++ ori r11,r11,MSR_EE; \
++ mtmsrd r11,1
++
++#else /* hard enable/disable interrupts */
++#define DISABLE_INTS
++
++#define ENABLE_INTS \
++ ld r12,_MSR(r1); \
++ mfmsr r11; \
++ rlwimi r11,r12,0,MSR_EE; \
++ mtmsrd r11,1
++
++#endif
++
++#define STD_EXCEPTION_COMMON(trap, label, hdlr) \
++ .align 7; \
++ .globl label##_common; \
++label##_common: \
++ EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
++ DISABLE_INTS; \
++ bl .save_nvgprs; \
++ addi r3,r1,STACK_FRAME_OVERHEAD; \
++ bl hdlr; \
++ b .ret_from_except
++
++#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \
++ .align 7; \
++ .globl label##_common; \
++label##_common: \
++ EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
++ DISABLE_INTS; \
++ addi r3,r1,STACK_FRAME_OVERHEAD; \
++ bl hdlr; \
++ b .ret_from_except_lite
++
++/*
++ * Start of pSeries system interrupt routines
++ */
++ . = 0x100
++ .globl __start_interrupts
++__start_interrupts:
++
++ STD_EXCEPTION_PSERIES(0x100, system_reset)
++
++ . = 0x200
++_machine_check_pSeries:
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13 /* save r13 */
++ RUNLATCH_ON(r13)
++ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
++
++ . = 0x300
++ .globl data_access_pSeries
++data_access_pSeries:
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13
++BEGIN_FTR_SECTION
++ mtspr SPRN_SPRG2,r12
++ mfspr r13,SPRN_DAR
++ mfspr r12,SPRN_DSISR
++ srdi r13,r13,60
++ rlwimi r13,r12,16,0x20
++ mfcr r12
++ cmpwi r13,0x2c
++ beq .do_stab_bolted_pSeries
++ mtcrf 0x80,r12
++ mfspr r12,SPRN_SPRG2
++END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
++ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common)
++
++ . = 0x380
++ .globl data_access_slb_pSeries
++data_access_slb_pSeries:
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13
++ RUNLATCH_ON(r13)
++ mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
++ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
++ std r10,PACA_EXSLB+EX_R10(r13)
++ std r11,PACA_EXSLB+EX_R11(r13)
++ std r12,PACA_EXSLB+EX_R12(r13)
++ std r3,PACA_EXSLB+EX_R3(r13)
++ mfspr r9,SPRN_SPRG1
++ std r9,PACA_EXSLB+EX_R13(r13)
++ mfcr r9
++ mfspr r12,SPRN_SRR1 /* and SRR1 */
++ mfspr r3,SPRN_DAR
++ b .do_slb_miss /* Rel. branch works in real mode */
++
++ STD_EXCEPTION_PSERIES(0x400, instruction_access)
++
++ . = 0x480
++ .globl instruction_access_slb_pSeries
++instruction_access_slb_pSeries:
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13
++ RUNLATCH_ON(r13)
++ mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
++ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
++ std r10,PACA_EXSLB+EX_R10(r13)
++ std r11,PACA_EXSLB+EX_R11(r13)
++ std r12,PACA_EXSLB+EX_R12(r13)
++ std r3,PACA_EXSLB+EX_R3(r13)
++ mfspr r9,SPRN_SPRG1
++ std r9,PACA_EXSLB+EX_R13(r13)
++ mfcr r9
++ mfspr r12,SPRN_SRR1 /* and SRR1 */
++ mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
++ b .do_slb_miss /* Rel. branch works in real mode */
++
++ STD_EXCEPTION_PSERIES(0x500, hardware_interrupt)
++ STD_EXCEPTION_PSERIES(0x600, alignment)
++ STD_EXCEPTION_PSERIES(0x700, program_check)
++ STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
++ STD_EXCEPTION_PSERIES(0x900, decrementer)
++ STD_EXCEPTION_PSERIES(0xa00, trap_0a)
++ STD_EXCEPTION_PSERIES(0xb00, trap_0b)
++
++ . = 0xc00
++ .globl system_call_pSeries
++system_call_pSeries:
++ HMT_MEDIUM
++ RUNLATCH_ON(r9)
++ mr r9,r13
++ mfmsr r10
++ mfspr r13,SPRN_SPRG3
++ mfspr r11,SPRN_SRR0
++ clrrdi r12,r13,32
++ oris r12,r12,system_call_common at h
++ ori r12,r12,system_call_common at l
++ mtspr SPRN_SRR0,r12
++ ori r10,r10,MSR_IR|MSR_DR|MSR_RI
++ mfspr r12,SPRN_SRR1
++ mtspr SPRN_SRR1,r10
++ rfid
++ b . /* prevent speculative execution */
++
++ STD_EXCEPTION_PSERIES(0xd00, single_step)
++ STD_EXCEPTION_PSERIES(0xe00, trap_0e)
++
++ /* We need to deal with the Altivec unavailable exception
++ * here which is at 0xf20, thus in the middle of the
++ * prolog code of the PerformanceMonitor one. A little
++ * trickery is thus necessary
++ */
++ . = 0xf00
++ b performance_monitor_pSeries
++
++ STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable)
++
++ STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
++ STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
++
++ . = 0x3000
++
++/*** pSeries interrupt support ***/
++
++ /* moved from 0xf00 */
++ STD_EXCEPTION_PSERIES(., performance_monitor)
++
++ .align 7
++_GLOBAL(do_stab_bolted_pSeries)
++ mtcrf 0x80,r12
++ mfspr r12,SPRN_SPRG2
++ EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
++
++/*
++ * Vectors for the FWNMI option. Share common code.
++ */
++ .globl system_reset_fwnmi
++system_reset_fwnmi:
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13 /* save r13 */
++ RUNLATCH_ON(r13)
++ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
++
++ .globl machine_check_fwnmi
++machine_check_fwnmi:
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13 /* save r13 */
++ RUNLATCH_ON(r13)
++ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
++
++#ifdef CONFIG_PPC_ISERIES
++/*** ISeries-LPAR interrupt handlers ***/
++
++ STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC)
++
++ .globl data_access_iSeries
++data_access_iSeries:
++ mtspr SPRN_SPRG1,r13
++BEGIN_FTR_SECTION
++ mtspr SPRN_SPRG2,r12
++ mfspr r13,SPRN_DAR
++ mfspr r12,SPRN_DSISR
++ srdi r13,r13,60
++ rlwimi r13,r12,16,0x20
++ mfcr r12
++ cmpwi r13,0x2c
++ beq .do_stab_bolted_iSeries
++ mtcrf 0x80,r12
++ mfspr r12,SPRN_SPRG2
++END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
++ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN)
++ EXCEPTION_PROLOG_ISERIES_2
++ b data_access_common
++
++.do_stab_bolted_iSeries:
++ mtcrf 0x80,r12
++ mfspr r12,SPRN_SPRG2
++ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
++ EXCEPTION_PROLOG_ISERIES_2
++ b .do_stab_bolted
++
++ .globl data_access_slb_iSeries
++data_access_slb_iSeries:
++ mtspr SPRN_SPRG1,r13 /* save r13 */
++ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
++ std r3,PACA_EXSLB+EX_R3(r13)
++ ld r12,PACALPPACA+LPPACASRR1(r13)
++ mfspr r3,SPRN_DAR
++ b .do_slb_miss
++
++ STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN)
++
++ .globl instruction_access_slb_iSeries
++instruction_access_slb_iSeries:
++ mtspr SPRN_SPRG1,r13 /* save r13 */
++ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
++ std r3,PACA_EXSLB+EX_R3(r13)
++ ld r12,PACALPPACA+LPPACASRR1(r13)
++ ld r3,PACALPPACA+LPPACASRR0(r13)
++ b .do_slb_miss
++
++ MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt)
++ STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN)
++ STD_EXCEPTION_ISERIES(0x700, program_check, PACA_EXGEN)
++ STD_EXCEPTION_ISERIES(0x800, fp_unavailable, PACA_EXGEN)
++ MASKABLE_EXCEPTION_ISERIES(0x900, decrementer)
++ STD_EXCEPTION_ISERIES(0xa00, trap_0a, PACA_EXGEN)
++ STD_EXCEPTION_ISERIES(0xb00, trap_0b, PACA_EXGEN)
++
++ .globl system_call_iSeries
++system_call_iSeries:
++ mr r9,r13
++ mfspr r13,SPRN_SPRG3
++ EXCEPTION_PROLOG_ISERIES_2
++ b system_call_common
++
++ STD_EXCEPTION_ISERIES( 0xd00, single_step, PACA_EXGEN)
++ STD_EXCEPTION_ISERIES( 0xe00, trap_0e, PACA_EXGEN)
++ STD_EXCEPTION_ISERIES( 0xf00, performance_monitor, PACA_EXGEN)
++
++ .globl system_reset_iSeries
++system_reset_iSeries:
++ mfspr r13,SPRN_SPRG3 /* Get paca address */
++ mfmsr r24
++ ori r24,r24,MSR_RI
++ mtmsrd r24 /* RI on */
++ lhz r24,PACAPACAINDEX(r13) /* Get processor # */
++ cmpwi 0,r24,0 /* Are we processor 0? */
++ beq .__start_initialization_iSeries /* Start up the first processor */
++ mfspr r4,SPRN_CTRLF
++ li r5,CTRL_RUNLATCH /* Turn off the run light */
++ andc r4,r4,r5
++ mtspr SPRN_CTRLT,r4
++
++1:
++ HMT_LOW
++#ifdef CONFIG_SMP
++ lbz r23,PACAPROCSTART(r13) /* Test if this processor
++ * should start */
++ sync
++ LOADADDR(r3,current_set)
++ sldi r28,r24,3 /* get current_set[cpu#] */
++ ldx r3,r3,r28
++ addi r1,r3,THREAD_SIZE
++ subi r1,r1,STACK_FRAME_OVERHEAD
++
++ cmpwi 0,r23,0
++ beq iSeries_secondary_smp_loop /* Loop until told to go */
++ bne .__secondary_start /* Loop until told to go */
++iSeries_secondary_smp_loop:
++ /* Let the Hypervisor know we are alive */
++ /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
++ lis r3,0x8002
++ rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
++#else /* CONFIG_SMP */
++ /* Yield the processor. This is required for non-SMP kernels
++ which are running on multi-threaded machines. */
++ lis r3,0x8000
++ rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */
++ addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */
++ li r4,0 /* "yield timed" */
++ li r5,-1 /* "yield forever" */
++#endif /* CONFIG_SMP */
++ li r0,-1 /* r0=-1 indicates a Hypervisor call */
++ sc /* Invoke the hypervisor via a system call */
++ mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */
++ b 1b /* If SMP not configured, secondaries
++ * loop forever */
++
++ .globl decrementer_iSeries_masked
++decrementer_iSeries_masked:
++ li r11,1
++ stb r11,PACALPPACA+LPPACADECRINT(r13)
++ lwz r12,PACADEFAULTDECR(r13)
++ mtspr SPRN_DEC,r12
++ /* fall through */
++
++ .globl hardware_interrupt_iSeries_masked
++hardware_interrupt_iSeries_masked:
++ mtcrf 0x80,r9 /* Restore regs */
++ ld r11,PACALPPACA+LPPACASRR0(r13)
++ ld r12,PACALPPACA+LPPACASRR1(r13)
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r12
++ ld r9,PACA_EXGEN+EX_R9(r13)
++ ld r10,PACA_EXGEN+EX_R10(r13)
++ ld r11,PACA_EXGEN+EX_R11(r13)
++ ld r12,PACA_EXGEN+EX_R12(r13)
++ ld r13,PACA_EXGEN+EX_R13(r13)
++ rfid
++ b . /* prevent speculative execution */
++#endif /* CONFIG_PPC_ISERIES */
++
++/*** Common interrupt handlers ***/
++
++ STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
++
++ /*
++ * Machine check is different because we use a different
++ * save area: PACA_EXMC instead of PACA_EXGEN.
++ */
++ .align 7
++ .globl machine_check_common
++machine_check_common:
++ EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
++ DISABLE_INTS
++ bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .machine_check_exception
++ b .ret_from_except
++
++ STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt)
++ STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)
++ STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
++ STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
++ STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
++ STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception)
++ STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
++#ifdef CONFIG_ALTIVEC
++ STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
++#else
++ STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
++#endif
++
++/*
++ * Here we have detected that the kernel stack pointer is bad.
++ * R9 contains the saved CR, r13 points to the paca,
++ * r10 contains the (bad) kernel stack pointer,
++ * r11 and r12 contain the saved SRR0 and SRR1.
++ * We switch to using an emergency stack, save the registers there,
++ * and call kernel_bad_stack(), which panics.
++ */
++bad_stack:
++ ld r1,PACAEMERGSP(r13)
++ subi r1,r1,64+INT_FRAME_SIZE
++ std r9,_CCR(r1)
++ std r10,GPR1(r1)
++ std r11,_NIP(r1)
++ std r12,_MSR(r1)
++ mfspr r11,SPRN_DAR
++ mfspr r12,SPRN_DSISR
++ std r11,_DAR(r1)
++ std r12,_DSISR(r1)
++ mflr r10
++ mfctr r11
++ mfxer r12
++ std r10,_LINK(r1)
++ std r11,_CTR(r1)
++ std r12,_XER(r1)
++ SAVE_GPR(0,r1)
++ SAVE_GPR(2,r1)
++ SAVE_4GPRS(3,r1)
++ SAVE_2GPRS(7,r1)
++ SAVE_10GPRS(12,r1)
++ SAVE_10GPRS(22,r1)
++ addi r11,r1,INT_FRAME_SIZE
++ std r11,0(r1)
++ li r12,0
++ std r12,0(r11)
++ ld r2,PACATOC(r13)
++1: addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .kernel_bad_stack
++ b 1b
++
++/*
++ * Return from an exception with minimal checks.
++ * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
++ * If interrupts have been enabled, or anything has been
++ * done that might have changed the scheduling status of
++ * any task or sent any task a signal, you should use
++ * ret_from_except or ret_from_except_lite instead of this.
++ */
++ .globl fast_exception_return
++fast_exception_return:
++ ld r12,_MSR(r1)
++ ld r11,_NIP(r1)
++ andi. r3,r12,MSR_RI /* check if RI is set */
++ beq- unrecov_fer
++ ld r3,_CCR(r1)
++ ld r4,_LINK(r1)
++ ld r5,_CTR(r1)
++ ld r6,_XER(r1)
++ mtcr r3
++ mtlr r4
++ mtctr r5
++ mtxer r6
++ REST_GPR(0, r1)
++ REST_8GPRS(2, r1)
++
++ mfmsr r10
++ clrrdi r10,r10,2 /* clear RI (LE is 0 already) */
++ mtmsrd r10,1
++
++ mtspr SPRN_SRR1,r12
++ mtspr SPRN_SRR0,r11
++ REST_4GPRS(10, r1)
++ ld r1,GPR1(r1)
++ rfid
++ b . /* prevent speculative execution */
++
++unrecov_fer:
++ bl .save_nvgprs
++1: addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .unrecoverable_exception
++ b 1b
++
++/*
++ * Here r13 points to the paca, r9 contains the saved CR,
++ * SRR0 and SRR1 are saved in r11 and r12,
++ * r9 - r13 are saved in paca->exgen.
++ */
++ .align 7
++ .globl data_access_common
++data_access_common:
++ RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */
++ mfspr r10,SPRN_DAR
++ std r10,PACA_EXGEN+EX_DAR(r13)
++ mfspr r10,SPRN_DSISR
++ stw r10,PACA_EXGEN+EX_DSISR(r13)
++ EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
++ ld r3,PACA_EXGEN+EX_DAR(r13)
++ lwz r4,PACA_EXGEN+EX_DSISR(r13)
++ li r5,0x300
++ b .do_hash_page /* Try to handle as hpte fault */
++
++ .align 7
++ .globl instruction_access_common
++instruction_access_common:
++ EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
++ ld r3,_NIP(r1)
++ andis. r4,r12,0x5820
++ li r5,0x400
++ b .do_hash_page /* Try to handle as hpte fault */
++
++ .align 7
++ .globl hardware_interrupt_common
++ .globl hardware_interrupt_entry
++hardware_interrupt_common:
++ EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
++hardware_interrupt_entry:
++ DISABLE_INTS
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .do_IRQ
++ b .ret_from_except_lite
++
++ .align 7
++ .globl alignment_common
++alignment_common:
++ mfspr r10,SPRN_DAR
++ std r10,PACA_EXGEN+EX_DAR(r13)
++ mfspr r10,SPRN_DSISR
++ stw r10,PACA_EXGEN+EX_DSISR(r13)
++ EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)
++ ld r3,PACA_EXGEN+EX_DAR(r13)
++ lwz r4,PACA_EXGEN+EX_DSISR(r13)
++ std r3,_DAR(r1)
++ std r4,_DSISR(r1)
++ bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ ENABLE_INTS
++ bl .alignment_exception
++ b .ret_from_except
++
++ .align 7
++ .globl program_check_common
++program_check_common:
++ EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
++ bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ ENABLE_INTS
++ bl .program_check_exception
++ b .ret_from_except
++
++ .align 7
++ .globl fp_unavailable_common
++fp_unavailable_common:
++ EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
++ bne .load_up_fpu /* if from user, just load it up */
++ bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ ENABLE_INTS
++ bl .kernel_fp_unavailable_exception
++ BUG_OPCODE
++
++ .align 7
++ .globl altivec_unavailable_common
++altivec_unavailable_common:
++ EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)
++#ifdef CONFIG_ALTIVEC
++BEGIN_FTR_SECTION
++ bne .load_up_altivec /* if from user, just load it up */
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++#endif
++ bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ ENABLE_INTS
++ bl .altivec_unavailable_exception
++ b .ret_from_except
++
++#ifdef CONFIG_ALTIVEC
++/*
++ * load_up_altivec(unused, unused, tsk)
++ * Disable VMX for the task which had it previously,
++ * and save its vector registers in its thread_struct.
++ * Enables the VMX for use in the kernel on return.
++ * On SMP we know the VMX is free, since we give it up every
++ * switch (ie, no lazy save of the vector registers).
++ * On entry: r13 == 'current' && last_task_used_altivec != 'current'
++ */
++_STATIC(load_up_altivec)
++ mfmsr r5 /* grab the current MSR */
++ oris r5,r5,MSR_VEC at h
++ mtmsrd r5 /* enable use of VMX now */
++ isync
++
++/*
++ * For SMP, we don't do lazy VMX switching because it just gets too
++ * horrendously complex, especially when a task switches from one CPU
++ * to another. Instead we call giveup_altvec in switch_to.
++ * VRSAVE isn't dealt with here, that is done in the normal context
++ * switch code. Note that we could rely on vrsave value to eventually
++ * avoid saving all of the VREGs here...
++ */
++#ifndef CONFIG_SMP
++ ld r3,last_task_used_altivec at got(r2)
++ ld r4,0(r3)
++ cmpdi 0,r4,0
++ beq 1f
++ /* Save VMX state to last_task_used_altivec's THREAD struct */
++ addi r4,r4,THREAD
++ SAVE_32VRS(0,r5,r4)
++ mfvscr vr0
++ li r10,THREAD_VSCR
++ stvx vr0,r10,r4
++ /* Disable VMX for last_task_used_altivec */
++ ld r5,PT_REGS(r4)
++ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ lis r6,MSR_VEC at h
++ andc r4,r4,r6
++ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#endif /* CONFIG_SMP */
++ /* Hack: if we get an altivec unavailable trap with VRSAVE
++ * set to all zeros, we assume this is a broken application
++ * that fails to set it properly, and thus we switch it to
++ * all 1's
++ */
++ mfspr r4,SPRN_VRSAVE
++ cmpdi 0,r4,0
++ bne+ 1f
++ li r4,-1
++ mtspr SPRN_VRSAVE,r4
++1:
++ /* enable use of VMX after return */
++ ld r4,PACACURRENT(r13)
++ addi r5,r4,THREAD /* Get THREAD */
++ oris r12,r12,MSR_VEC at h
++ std r12,_MSR(r1)
++ li r4,1
++ li r10,THREAD_VSCR
++ stw r4,THREAD_USED_VR(r5)
++ lvx vr0,r10,r5
++ mtvscr vr0
++ REST_32VRS(0,r4,r5)
++#ifndef CONFIG_SMP
++ /* Update last_task_used_math to 'current' */
++ subi r4,r5,THREAD /* Back to 'current' */
++ std r4,0(r3)
++#endif /* CONFIG_SMP */
++ /* restore registers and return */
++ b fast_exception_return
++#endif /* CONFIG_ALTIVEC */
++
++/*
++ * Hash table stuff
++ */
++ .align 7
++_GLOBAL(do_hash_page)
++ std r3,_DAR(r1)
++ std r4,_DSISR(r1)
++
++ andis. r0,r4,0xa450 /* weird error? */
++ bne- .handle_page_fault /* if not, try to insert a HPTE */
++BEGIN_FTR_SECTION
++ andis. r0,r4,0x0020 /* Is it a segment table fault? */
++ bne- .do_ste_alloc /* If so handle it */
++END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
++
++ /*
++ * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
++ * accessing a userspace segment (even from the kernel). We assume
++ * kernel addresses always have the high bit set.
++ */
++ rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */
++ rotldi r0,r3,15 /* Move high bit into MSR_PR posn */
++ orc r0,r12,r0 /* MSR_PR | ~high_bit */
++ rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */
++ ori r4,r4,1 /* add _PAGE_PRESENT */
++ rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */
++
++ /*
++ * On iSeries, we soft-disable interrupts here, then
++ * hard-enable interrupts so that the hash_page code can spin on
++ * the hash_table_lock without problems on a shared processor.
++ */
++ DISABLE_INTS
++
++ /*
++ * r3 contains the faulting address
++ * r4 contains the required access permissions
++ * r5 contains the trap number
++ *
++ * at return r3 = 0 for success
++ */
++ bl .hash_page /* build HPTE if possible */
++ cmpdi r3,0 /* see if hash_page succeeded */
++
++#ifdef DO_SOFT_DISABLE
++ /*
++ * If we had interrupts soft-enabled at the point where the
++ * DSI/ISI occurred, and an interrupt came in during hash_page,
++ * handle it now.
++ * We jump to ret_from_except_lite rather than fast_exception_return
++ * because ret_from_except_lite will check for and handle pending
++ * interrupts if necessary.
++ */
++ beq .ret_from_except_lite
++ /* For a hash failure, we don't bother re-enabling interrupts */
++ ble- 12f
++
++ /*
++ * hash_page couldn't handle it, set soft interrupt enable back
++ * to what it was before the trap. Note that .local_irq_restore
++ * handles any interrupts pending at this point.
++ */
++ ld r3,SOFTE(r1)
++ bl .local_irq_restore
++ b 11f
++#else
++ beq fast_exception_return /* Return from exception on success */
++ ble- 12f /* Failure return from hash_page */
++
++ /* fall through */
++#endif
++
++/* Here we have a page fault that hash_page can't handle. */
++_GLOBAL(handle_page_fault)
++ ENABLE_INTS
++11: ld r4,_DAR(r1)
++ ld r5,_DSISR(r1)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .do_page_fault
++ cmpdi r3,0
++ beq+ .ret_from_except_lite
++ bl .save_nvgprs
++ mr r5,r3
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ lwz r4,_DAR(r1)
++ bl .bad_page_fault
++ b .ret_from_except
++
++/* We have a page fault that hash_page could handle but HV refused
++ * the PTE insertion
++ */
++12: bl .save_nvgprs
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ lwz r4,_DAR(r1)
++ bl .low_hash_fault
++ b .ret_from_except
++
++ /* here we have a segment miss */
++_GLOBAL(do_ste_alloc)
++ bl .ste_allocate /* try to insert stab entry */
++ cmpdi r3,0
++ beq+ fast_exception_return
++ b .handle_page_fault
++
++/*
++ * r13 points to the PACA, r9 contains the saved CR,
++ * r11 and r12 contain the saved SRR0 and SRR1.
++ * r9 - r13 are saved in paca->exslb.
++ * We assume we aren't going to take any exceptions during this procedure.
++ * We assume (DAR >> 60) == 0xc.
++ */
++ .align 7
++_GLOBAL(do_stab_bolted)
++ stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
++ std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */
++
++ /* Hash to the primary group */
++ ld r10,PACASTABVIRT(r13)
++ mfspr r11,SPRN_DAR
++ srdi r11,r11,28
++ rldimi r10,r11,7,52 /* r10 = first ste of the group */
++
++ /* Calculate VSID */
++ /* This is a kernel address, so protovsid = ESID */
++ ASM_VSID_SCRAMBLE(r11, r9)
++ rldic r9,r11,12,16 /* r9 = vsid << 12 */
++
++ /* Search the primary group for a free entry */
++1: ld r11,0(r10) /* Test valid bit of the current ste */
++ andi. r11,r11,0x80
++ beq 2f
++ addi r10,r10,16
++ andi. r11,r10,0x70
++ bne 1b
++
++ /* Stick for only searching the primary group for now. */
++ /* At least for now, we use a very simple random castout scheme */
++ /* Use the TB as a random number ; OR in 1 to avoid entry 0 */
++ mftb r11
++ rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */
++ ori r11,r11,0x10
++
++ /* r10 currently points to an ste one past the group of interest */
++ /* make it point to the randomly selected entry */
++ subi r10,r10,128
++ or r10,r10,r11 /* r10 is the entry to invalidate */
++
++ isync /* mark the entry invalid */
++ ld r11,0(r10)
++ rldicl r11,r11,56,1 /* clear the valid bit */
++ rotldi r11,r11,8
++ std r11,0(r10)
++ sync
++
++ clrrdi r11,r11,28 /* Get the esid part of the ste */
++ slbie r11
++
++2: std r9,8(r10) /* Store the vsid part of the ste */
++ eieio
++
++ mfspr r11,SPRN_DAR /* Get the new esid */
++ clrrdi r11,r11,28 /* Permits a full 32b of ESID */
++ ori r11,r11,0x90 /* Turn on valid and kp */
++ std r11,0(r10) /* Put new entry back into the stab */
++
++ sync
++
++ /* All done -- return from exception. */
++ lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
++ ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */
++
++ andi. r10,r12,MSR_RI
++ beq- unrecov_slb
++
++ mtcrf 0x80,r9 /* restore CR */
++
++ mfmsr r10
++ clrrdi r10,r10,2
++ mtmsrd r10,1
++
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r12
++ ld r9,PACA_EXSLB+EX_R9(r13)
++ ld r10,PACA_EXSLB+EX_R10(r13)
++ ld r11,PACA_EXSLB+EX_R11(r13)
++ ld r12,PACA_EXSLB+EX_R12(r13)
++ ld r13,PACA_EXSLB+EX_R13(r13)
++ rfid
++ b . /* prevent speculative execution */
++
++/*
++ * r13 points to the PACA, r9 contains the saved CR,
++ * r11 and r12 contain the saved SRR0 and SRR1.
++ * r3 has the faulting address
++ * r9 - r13 are saved in paca->exslb.
++ * r3 is saved in paca->slb_r3
++ * We assume we aren't going to take any exceptions during this procedure.
++ */
++_GLOBAL(do_slb_miss)
++ mflr r10
++
++ stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
++ std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
++
++ bl .slb_allocate /* handle it */
++
++ /* All done -- return from exception. */
++
++ ld r10,PACA_EXSLB+EX_LR(r13)
++ ld r3,PACA_EXSLB+EX_R3(r13)
++ lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
++#ifdef CONFIG_PPC_ISERIES
++ ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */
++#endif /* CONFIG_PPC_ISERIES */
++
++ mtlr r10
++
++ andi. r10,r12,MSR_RI /* check for unrecoverable exception */
++ beq- unrecov_slb
++
++.machine push
++.machine "power4"
++ mtcrf 0x80,r9
++ mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
++.machine pop
++
++#ifdef CONFIG_PPC_ISERIES
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r12
++#endif /* CONFIG_PPC_ISERIES */
++ ld r9,PACA_EXSLB+EX_R9(r13)
++ ld r10,PACA_EXSLB+EX_R10(r13)
++ ld r11,PACA_EXSLB+EX_R11(r13)
++ ld r12,PACA_EXSLB+EX_R12(r13)
++ ld r13,PACA_EXSLB+EX_R13(r13)
++ rfid
++ b . /* prevent speculative execution */
++
++unrecov_slb:
++ EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
++ DISABLE_INTS
++ bl .save_nvgprs
++1: addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .unrecoverable_exception
++ b 1b
++
++/*
++ * Space for CPU0's segment table.
++ *
++ * On iSeries, the hypervisor must fill in at least one entry before
++ * we get control (with relocate on). The address is give to the hv
++ * as a page number (see xLparMap in lpardata.c), so this must be at a
++ * fixed address (the linker can't compute (u64)&initial_stab >>
++ * PAGE_SHIFT).
++ */
++ . = STAB0_PHYS_ADDR /* 0x6000 */
++ .globl initial_stab
++initial_stab:
++ .space 4096
++
++/*
++ * Data area reserved for FWNMI option.
++ * This address (0x7000) is fixed by the RPA.
++ */
++ .= 0x7000
++ .globl fwnmi_data_area
++fwnmi_data_area:
++
++ /* iSeries does not use the FWNMI stuff, so it is safe to put
++ * this here, even if we later allow kernels that will boot on
++ * both pSeries and iSeries */
++#ifdef CONFIG_PPC_ISERIES
++ . = LPARMAP_PHYS
++#include "lparmap.s"
++/*
++ * This ".text" is here for old compilers that generate a trailing
++ * .note section when compiling .c files to .s
++ */
++ .text
++#endif /* CONFIG_PPC_ISERIES */
++
++ . = 0x8000
++
++/*
++ * On pSeries, secondary processors spin in the following code.
++ * At entry, r3 = this processor's number (physical cpu id)
++ */
++_GLOBAL(pSeries_secondary_smp_init)
++ mr r24,r3
++
++ /* turn on 64-bit mode */
++ bl .enable_64b_mode
++ isync
++
++ /* Copy some CPU settings from CPU 0 */
++ bl .__restore_cpu_setup
++
++ /* Set up a paca value for this processor. Since we have the
++ * physical cpu id in r24, we need to search the pacas to find
++ * which logical id maps to our physical one.
++ */
++ LOADADDR(r13, paca) /* Get base vaddr of paca array */
++ li r5,0 /* logical cpu id */
++1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */
++ cmpw r6,r24 /* Compare to our id */
++ beq 2f
++ addi r13,r13,PACA_SIZE /* Loop to next PACA on miss */
++ addi r5,r5,1
++ cmpwi r5,NR_CPUS
++ blt 1b
++
++ mr r3,r24 /* not found, copy phys to r3 */
++ b .kexec_wait /* next kernel might do better */
++
++2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
++ /* From now on, r24 is expected to be logical cpuid */
++ mr r24,r5
++3: HMT_LOW
++ lbz r23,PACAPROCSTART(r13) /* Test if this processor should */
++ /* start. */
++ sync
++
++ /* Create a temp kernel stack for use before relocation is on. */
++ ld r1,PACAEMERGSP(r13)
++ subi r1,r1,STACK_FRAME_OVERHEAD
++
++ cmpwi 0,r23,0
++#ifdef CONFIG_SMP
++ bne .__secondary_start
++#endif
++ b 3b /* Loop until told to go */
++
++#ifdef CONFIG_PPC_ISERIES
++_STATIC(__start_initialization_iSeries)
++ /* Clear out the BSS */
++ LOADADDR(r11,__bss_stop)
++ LOADADDR(r8,__bss_start)
++ sub r11,r11,r8 /* bss size */
++ addi r11,r11,7 /* round up to an even double word */
++ rldicl. r11,r11,61,3 /* shift right by 3 */
++ beq 4f
++ addi r8,r8,-8
++ li r0,0
++ mtctr r11 /* zero this many doublewords */
++3: stdu r0,8(r8)
++ bdnz 3b
++4:
++ LOADADDR(r1,init_thread_union)
++ addi r1,r1,THREAD_SIZE
++ li r0,0
++ stdu r0,-STACK_FRAME_OVERHEAD(r1)
++
++ LOADADDR(r3,cpu_specs)
++ LOADADDR(r4,cur_cpu_spec)
++ li r5,0
++ bl .identify_cpu
++
++ LOADADDR(r2,__toc_start)
++ addi r2,r2,0x4000
++ addi r2,r2,0x4000
++
++ bl .iSeries_early_setup
++ bl .early_setup
++
++ /* relocation is on at this point */
++
++ b .start_here_common
++#endif /* CONFIG_PPC_ISERIES */
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++
++_STATIC(__mmu_off)
++ mfmsr r3
++ andi. r0,r3,MSR_IR|MSR_DR
++ beqlr
++ andc r3,r3,r0
++ mtspr SPRN_SRR0,r4
++ mtspr SPRN_SRR1,r3
++ sync
++ rfid
++ b . /* prevent speculative execution */
++
++
++/*
++ * Here is our main kernel entry point. We support currently 2 kind of entries
++ * depending on the value of r5.
++ *
++ * r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content
++ * in r3...r7
++ *
++ * r5 == NULL -> kexec style entry. r3 is a physical pointer to the
++ * DT block, r4 is a physical pointer to the kernel itself
++ *
++ */
++_GLOBAL(__start_initialization_multiplatform)
++ /*
++ * Are we booted from a PROM Of-type client-interface ?
++ */
++ cmpldi cr0,r5,0
++ bne .__boot_from_prom /* yes -> prom */
++
++ /* Save parameters */
++ mr r31,r3
++ mr r30,r4
++
++ /* Make sure we are running in 64 bits mode */
++ bl .enable_64b_mode
++
++ /* Setup some critical 970 SPRs before switching MMU off */
++ bl .__970_cpu_preinit
++
++ /* cpu # */
++ li r24,0
++
++ /* Switch off MMU if not already */
++ LOADADDR(r4, .__after_prom_start - KERNELBASE)
++ add r4,r4,r30
++ bl .__mmu_off
++ b .__after_prom_start
++
++_STATIC(__boot_from_prom)
++ /* Save parameters */
++ mr r31,r3
++ mr r30,r4
++ mr r29,r5
++ mr r28,r6
++ mr r27,r7
++
++ /* Make sure we are running in 64 bits mode */
++ bl .enable_64b_mode
++
++ /* put a relocation offset into r3 */
++ bl .reloc_offset
++
++ LOADADDR(r2,__toc_start)
++ addi r2,r2,0x4000
++ addi r2,r2,0x4000
++
++ /* Relocate the TOC from a virt addr to a real addr */
++ add r2,r2,r3
++
++ /* Restore parameters */
++ mr r3,r31
++ mr r4,r30
++ mr r5,r29
++ mr r6,r28
++ mr r7,r27
++
++ /* Do all of the interaction with OF client interface */
++ bl .prom_init
++ /* We never return */
++ trap
++
++/*
++ * At this point, r3 contains the physical address we are running at,
++ * returned by prom_init()
++ */
++_STATIC(__after_prom_start)
++
++/*
++ * We need to run with __start at physical address 0.
++ * This will leave some code in the first 256B of
++ * real memory, which are reserved for software use.
++ * The remainder of the first page is loaded with the fixed
++ * interrupt vectors. The next two pages are filled with
++ * unknown exception placeholders.
++ *
++ * Note: This process overwrites the OF exception vectors.
++ * r26 == relocation offset
++ * r27 == KERNELBASE
++ */
++ bl .reloc_offset
++ mr r26,r3
++ SET_REG_TO_CONST(r27,KERNELBASE)
++
++ li r3,0 /* target addr */
++
++ // XXX FIXME: Use phys returned by OF (r30)
++ add r4,r27,r26 /* source addr */
++ /* current address of _start */
++ /* i.e. where we are running */
++ /* the source addr */
++
++ LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */
++ sub r5,r5,r27
++
++ li r6,0x100 /* Start offset, the first 0x100 */
++ /* bytes were copied earlier. */
++
++ bl .copy_and_flush /* copy the first n bytes */
++ /* this includes the code being */
++ /* executed here. */
++
++ LOADADDR(r0, 4f) /* Jump to the copy of this code */
++ mtctr r0 /* that we just made/relocated */
++ bctr
++
++4: LOADADDR(r5,klimit)
++ add r5,r5,r26
++ ld r5,0(r5) /* get the value of klimit */
++ sub r5,r5,r27
++ bl .copy_and_flush /* copy the rest */
++ b .start_here_multiplatform
++
++#endif /* CONFIG_PPC_MULTIPLATFORM */
++
++/*
++ * Copy routine used to copy the kernel to start at physical address 0
++ * and flush and invalidate the caches as needed.
++ * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
++ * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
++ *
++ * Note: this routine *only* clobbers r0, r6 and lr
++ */
++_GLOBAL(copy_and_flush)
++ addi r5,r5,-8
++ addi r6,r6,-8
++4: li r0,16 /* Use the least common */
++ /* denominator cache line */
++ /* size. This results in */
++ /* extra cache line flushes */
++ /* but operation is correct. */
++ /* Can't get cache line size */
++ /* from NACA as it is being */
++ /* moved too. */
++
++ mtctr r0 /* put # words/line in ctr */
++3: addi r6,r6,8 /* copy a cache line */
++ ldx r0,r6,r4
++ stdx r0,r6,r3
++ bdnz 3b
++ dcbst r6,r3 /* write it to memory */
++ sync
++ icbi r6,r3 /* flush the icache line */
++ cmpld 0,r6,r5
++ blt 4b
++ sync
++ addi r5,r5,8
++ addi r6,r6,8
++ blr
++
++.align 8
++copy_to_here:
++
++#ifdef CONFIG_SMP
++#ifdef CONFIG_PPC_PMAC
++/*
++ * On PowerMac, secondary processors starts from the reset vector, which
++ * is temporarily turned into a call to one of the functions below.
++ */
++ .section ".text";
++ .align 2 ;
++
++ .globl __secondary_start_pmac_0
++__secondary_start_pmac_0:
++ /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
++ li r24,0
++ b 1f
++ li r24,1
++ b 1f
++ li r24,2
++ b 1f
++ li r24,3
++1:
++
++_GLOBAL(pmac_secondary_start)
++ /* turn on 64-bit mode */
++ bl .enable_64b_mode
++ isync
++
++ /* Copy some CPU settings from CPU 0 */
++ bl .__restore_cpu_setup
++
++ /* pSeries do that early though I don't think we really need it */
++ mfmsr r3
++ ori r3,r3,MSR_RI
++ mtmsrd r3 /* RI on */
++
++ /* Set up a paca value for this processor. */
++ LOADADDR(r4, paca) /* Get base vaddr of paca array */
++ mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
++ add r13,r13,r4 /* for this processor. */
++ mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
++
++ /* Create a temp kernel stack for use before relocation is on. */
++ ld r1,PACAEMERGSP(r13)
++ subi r1,r1,STACK_FRAME_OVERHEAD
++
++ b .__secondary_start
++
++#endif /* CONFIG_PPC_PMAC */
++
++/*
++ * This function is called after the master CPU has released the
++ * secondary processors. The execution environment is relocation off.
++ * The paca for this processor has the following fields initialized at
++ * this point:
++ * 1. Processor number
++ * 2. Segment table pointer (virtual address)
++ * On entry the following are set:
++ * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries
++ * r24 = cpu# (in Linux terms)
++ * r13 = paca virtual address
++ * SPRG3 = paca virtual address
++ */
++_GLOBAL(__secondary_start)
++
++ HMT_MEDIUM /* Set thread priority to MEDIUM */
++
++ ld r2,PACATOC(r13)
++ li r6,0
++ stb r6,PACAPROCENABLED(r13)
++
++#ifndef CONFIG_PPC_ISERIES
++ /* Initialize the page table pointer register. */
++ LOADADDR(r6,_SDR1)
++ ld r6,0(r6) /* get the value of _SDR1 */
++ mtspr SPRN_SDR1,r6 /* set the htab location */
++#endif
++ /* Initialize the first segment table (or SLB) entry */
++ ld r3,PACASTABVIRT(r13) /* get addr of segment table */
++ bl .stab_initialize
++
++ /* Initialize the kernel stack. Just a repeat for iSeries. */
++ LOADADDR(r3,current_set)
++ sldi r28,r24,3 /* get current_set[cpu#] */
++ ldx r1,r3,r28
++ addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
++ std r1,PACAKSAVE(r13)
++
++ ld r3,PACASTABREAL(r13) /* get raddr of segment table */
++ ori r4,r3,1 /* turn on valid bit */
++
++#ifdef CONFIG_PPC_ISERIES
++ li r0,-1 /* hypervisor call */
++ li r3,1
++ sldi r3,r3,63 /* 0x8000000000000000 */
++ ori r3,r3,4 /* 0x8000000000000004 */
++ sc /* HvCall_setASR */
++#else
++ /* set the ASR */
++ ld r3,systemcfg at got(r2) /* r3 = ptr to systemcfg */
++ ld r3,0(r3)
++ lwz r3,PLATFORM(r3) /* r3 = platform flags */
++ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
++ beq 98f /* branch if result is 0 */
++ mfspr r3,SPRN_PVR
++ srwi r3,r3,16
++ cmpwi r3,0x37 /* SStar */
++ beq 97f
++ cmpwi r3,0x36 /* IStar */
++ beq 97f
++ cmpwi r3,0x34 /* Pulsar */
++ bne 98f
++97: li r3,H_SET_ASR /* hcall = H_SET_ASR */
++ HVSC /* Invoking hcall */
++ b 99f
++98: /* !(rpa hypervisor) || !(star) */
++ mtasr r4 /* set the stab location */
++99:
++#endif
++ li r7,0
++ mtlr r7
++
++ /* enable MMU and jump to start_secondary */
++ LOADADDR(r3,.start_secondary_prolog)
++ SET_REG_TO_CONST(r4, MSR_KERNEL)
++#ifdef DO_SOFT_DISABLE
++ ori r4,r4,MSR_EE
++#endif
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
++ rfid
++ b . /* prevent speculative execution */
++
++/*
++ * Running with relocation on at this point. All we want to do is
++ * zero the stack back-chain pointer before going into C code.
++ */
++_GLOBAL(start_secondary_prolog)
++ li r3,0
++ std r3,0(r1) /* Zero the stack frame pointer */
++ bl .start_secondary
++#endif
++
++/*
++ * This subroutine clobbers r11 and r12
++ */
++_GLOBAL(enable_64b_mode)
++ mfmsr r11 /* grab the current MSR */
++ li r12,1
++ rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
++ or r11,r11,r12
++ li r12,1
++ rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
++ or r11,r11,r12
++ mtmsrd r11
++ isync
++ blr
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++/*
++ * This is where the main kernel code starts.
++ */
++_STATIC(start_here_multiplatform)
++ /* get a new offset, now that the kernel has moved. */
++ bl .reloc_offset
++ mr r26,r3
++
++ /* Clear out the BSS. It may have been done in prom_init,
++ * already but that's irrelevant since prom_init will soon
++ * be detached from the kernel completely. Besides, we need
++ * to clear it now for kexec-style entry.
++ */
++ LOADADDR(r11,__bss_stop)
++ LOADADDR(r8,__bss_start)
++ sub r11,r11,r8 /* bss size */
++ addi r11,r11,7 /* round up to an even double word */
++ rldicl. r11,r11,61,3 /* shift right by 3 */
++ beq 4f
++ addi r8,r8,-8
++ li r0,0
++ mtctr r11 /* zero this many doublewords */
++3: stdu r0,8(r8)
++ bdnz 3b
++4:
++
++ mfmsr r6
++ ori r6,r6,MSR_RI
++ mtmsrd r6 /* RI on */
++
++#ifdef CONFIG_HMT
++ /* Start up the second thread on cpu 0 */
++ mfspr r3,SPRN_PVR
++ srwi r3,r3,16
++ cmpwi r3,0x34 /* Pulsar */
++ beq 90f
++ cmpwi r3,0x36 /* Icestar */
++ beq 90f
++ cmpwi r3,0x37 /* SStar */
++ beq 90f
++ b 91f /* HMT not supported */
++90: li r3,0
++ bl .hmt_start_secondary
++91:
++#endif
++
++ /* The following gets the stack and TOC set up with the regs */
++ /* pointing to the real addr of the kernel stack. This is */
++ /* all done to support the C function call below which sets */
++ /* up the htab. This is done because we have relocated the */
++ /* kernel but are still running in real mode. */
++
++ LOADADDR(r3,init_thread_union)
++ add r3,r3,r26
++
++ /* set up a stack pointer (physical address) */
++ addi r1,r3,THREAD_SIZE
++ li r0,0
++ stdu r0,-STACK_FRAME_OVERHEAD(r1)
++
++ /* set up the TOC (physical address) */
++ LOADADDR(r2,__toc_start)
++ addi r2,r2,0x4000
++ addi r2,r2,0x4000
++ add r2,r2,r26
++
++ LOADADDR(r3,cpu_specs)
++ add r3,r3,r26
++ LOADADDR(r4,cur_cpu_spec)
++ add r4,r4,r26
++ mr r5,r26
++ bl .identify_cpu
++
++ /* Save some low level config HIDs of CPU0 to be copied to
++ * other CPUs later on, or used for suspend/resume
++ */
++ bl .__save_cpu_setup
++ sync
++
++ /* Setup a valid physical PACA pointer in SPRG3 for early_setup
++ * note that boot_cpuid can always be 0 nowadays since there is
++ * nowhere it can be initialized differently before we reach this
++ * code
++ */
++ LOADADDR(r27, boot_cpuid)
++ add r27,r27,r26
++ lwz r27,0(r27)
++
++ LOADADDR(r24, paca) /* Get base vaddr of paca array */
++ mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
++ add r13,r13,r24 /* for this processor. */
++ add r13,r13,r26 /* convert to physical addr */
++ mtspr SPRN_SPRG3,r13 /* PPPBBB: Temp... -Peter */
++
++ /* Do very early kernel initializations, including initial hash table,
++ * stab and slb setup before we turn on relocation. */
++
++ /* Restore parameters passed from prom_init/kexec */
++ mr r3,r31
++ bl .early_setup
++
++ /* set the ASR */
++ ld r3,PACASTABREAL(r13)
++ ori r4,r3,1 /* turn on valid bit */
++ ld r3,systemcfg at got(r2) /* r3 = ptr to systemcfg */
++ ld r3,0(r3)
++ lwz r3,PLATFORM(r3) /* r3 = platform flags */
++ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
++ beq 98f /* branch if result is 0 */
++ mfspr r3,SPRN_PVR
++ srwi r3,r3,16
++ cmpwi r3,0x37 /* SStar */
++ beq 97f
++ cmpwi r3,0x36 /* IStar */
++ beq 97f
++ cmpwi r3,0x34 /* Pulsar */
++ bne 98f
++97: li r3,H_SET_ASR /* hcall = H_SET_ASR */
++ HVSC /* Invoking hcall */
++ b 99f
++98: /* !(rpa hypervisor) || !(star) */
++ mtasr r4 /* set the stab location */
++99:
++ /* Set SDR1 (hash table pointer) */
++ ld r3,systemcfg at got(r2) /* r3 = ptr to systemcfg */
++ ld r3,0(r3)
++ lwz r3,PLATFORM(r3) /* r3 = platform flags */
++ /* Test if bit 0 is set (LPAR bit) */
++ andi. r3,r3,PLATFORM_LPAR
++ bne 98f /* branch if result is !0 */
++ LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
++ add r6,r6,r26
++ ld r6,0(r6) /* get the value of _SDR1 */
++ mtspr SPRN_SDR1,r6 /* set the htab location */
++98:
++ LOADADDR(r3,.start_here_common)
++ SET_REG_TO_CONST(r4, MSR_KERNEL)
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
++ rfid
++ b . /* prevent speculative execution */
++#endif /* CONFIG_PPC_MULTIPLATFORM */
++
++ /* This is where all platforms converge execution */
++_STATIC(start_here_common)
++ /* relocation is on at this point */
++
++ /* The following code sets up the SP and TOC now that we are */
++ /* running with translation enabled. */
++
++ LOADADDR(r3,init_thread_union)
++
++ /* set up the stack */
++ addi r1,r3,THREAD_SIZE
++ li r0,0
++ stdu r0,-STACK_FRAME_OVERHEAD(r1)
++
++ /* Apply the CPUs-specific fixups (nop out sections not relevant
++ * to this CPU
++ */
++ li r3,0
++ bl .do_cpu_ftr_fixups
++
++ LOADADDR(r26, boot_cpuid)
++ lwz r26,0(r26)
++
++ LOADADDR(r24, paca) /* Get base vaddr of paca array */
++ mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */
++ add r13,r13,r24 /* for this processor. */
++ mtspr SPRN_SPRG3,r13
++
++ /* ptr to current */
++ LOADADDR(r4,init_task)
++ std r4,PACACURRENT(r13)
++
++ /* Load the TOC */
++ ld r2,PACATOC(r13)
++ std r1,PACAKSAVE(r13)
++
++ bl .setup_system
++
++ /* Load up the kernel context */
++5:
++#ifdef DO_SOFT_DISABLE
++ li r5,0
++ stb r5,PACAPROCENABLED(r13) /* Soft Disabled */
++ mfmsr r5
++ ori r5,r5,MSR_EE /* Hard Enabled */
++ mtmsrd r5
++#endif
++
++ bl .start_kernel
++
++_GLOBAL(hmt_init)
++#ifdef CONFIG_HMT
++ LOADADDR(r5, hmt_thread_data)
++ mfspr r7,SPRN_PVR
++ srwi r7,r7,16
++ cmpwi r7,0x34 /* Pulsar */
++ beq 90f
++ cmpwi r7,0x36 /* Icestar */
++ beq 91f
++ cmpwi r7,0x37 /* SStar */
++ beq 91f
++ b 101f
++90: mfspr r6,SPRN_PIR
++ andi. r6,r6,0x1f
++ b 92f
++91: mfspr r6,SPRN_PIR
++ andi. r6,r6,0x3ff
++92: sldi r4,r24,3
++ stwx r6,r5,r4
++ bl .hmt_start_secondary
++ b 101f
++
++__hmt_secondary_hold:
++ LOADADDR(r5, hmt_thread_data)
++ clrldi r5,r5,4
++ li r7,0
++ mfspr r6,SPRN_PIR
++ mfspr r8,SPRN_PVR
++ srwi r8,r8,16
++ cmpwi r8,0x34
++ bne 93f
++ andi. r6,r6,0x1f
++ b 103f
++93: andi. r6,r6,0x3f
++
++103: lwzx r8,r5,r7
++ cmpw r8,r6
++ beq 104f
++ addi r7,r7,8
++ b 103b
++
++104: addi r7,r7,4
++ lwzx r9,r5,r7
++ mr r24,r9
++101:
++#endif
++ mr r3,r24
++ b .pSeries_secondary_smp_init
++
++#ifdef CONFIG_HMT
++_GLOBAL(hmt_start_secondary)
++ LOADADDR(r4,__hmt_secondary_hold)
++ clrldi r4,r4,4
++ mtspr SPRN_NIADORM, r4
++ mfspr r4, SPRN_MSRDORM
++ li r5, -65
++ and r4, r4, r5
++ mtspr SPRN_MSRDORM, r4
++ lis r4,0xffef
++ ori r4,r4,0x7403
++ mtspr SPRN_TSC, r4
++ li r4,0x1f4
++ mtspr SPRN_TST, r4
++ mfspr r4, SPRN_HID0
++ ori r4, r4, 0x1
++ mtspr SPRN_HID0, r4
++ mfspr r4, SPRN_CTRLF
++ oris r4, r4, 0x40
++ mtspr SPRN_CTRLT, r4
++ blr
++#endif
++
++#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP)
++_GLOBAL(smp_release_cpus)
++ /* All secondary cpus are spinning on a common
++ * spinloop, release them all now so they can start
++ * to spin on their individual paca spinloops.
++ * For non SMP kernels, the secondary cpus never
++ * get out of the common spinloop.
++ * XXX This does nothing useful on iSeries, secondaries are
++ * already waiting on their paca.
++ */
++ li r3,1
++ LOADADDR(r5,__secondary_hold_spinloop)
++ std r3,0(r5)
++ sync
++ blr
++#endif /* CONFIG_SMP */
++
++
++/*
++ * We put a few things here that have to be page-aligned.
++ * This stuff goes at the beginning of the bss, which is page-aligned.
++ */
++ .section ".bss"
++
++ .align PAGE_SHIFT
++
++ .globl empty_zero_page
++empty_zero_page:
++ .space PAGE_SIZE
++
++ .globl swapper_pg_dir
++swapper_pg_dir:
++ .space PAGE_SIZE
++
++/*
++ * This space gets a copy of optional info passed to us by the bootstrap
++ * Used to pass parameters into the kernel like root=/dev/sda1, etc.
++ */
++ .globl cmd_line
++cmd_line:
++ .space COMMAND_LINE_SIZE
+diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/head_8xx.S
+@@ -0,0 +1,860 @@
++/*
++ * arch/ppc/kernel/except_8xx.S
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ * Rewritten by Cort Dougan (cort at cs.nmt.edu) for PReP
++ * Copyright (C) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Low-level exception handlers and MMU support
++ * rewritten by Paul Mackerras.
++ * Copyright (C) 1996 Paul Mackerras.
++ * MPC8xx modifications by Dan Malek
++ * Copyright (C) 1997 Dan Malek (dmalek at jlc.net).
++ *
++ * This file contains low-level support and setup for PowerPC 8xx
++ * embedded processors, including trap and interrupt dispatch.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/cache.h>
++#include <asm/pgtable.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++
++/* Macro to make the code more readable. */
++#ifdef CONFIG_8xx_CPU6
++#define DO_8xx_CPU6(val, reg) \
++ li reg, val; \
++ stw reg, 12(r0); \
++ lwz reg, 12(r0);
++#else
++#define DO_8xx_CPU6(val, reg)
++#endif
++ .text
++ .globl _stext
++_stext:
++ .text
++ .globl _start
++_start:
++
++/* MPC8xx
++ * This port was done on an MBX board with an 860. Right now I only
++ * support an ELF compressed (zImage) boot from EPPC-Bug because the
++ * code there loads up some registers before calling us:
++ * r3: ptr to board info data
++ * r4: initrd_start or if no initrd then 0
++ * r5: initrd_end - unused if r4 is 0
++ * r6: Start of command line string
++ * r7: End of command line string
++ *
++ * I decided to use conditional compilation instead of checking PVR and
++ * adding more processor specific branches around code I don't need.
++ * Since this is an embedded processor, I also appreciate any memory
++ * savings I can get.
++ *
++ * The MPC8xx does not have any BATs, but it supports large page sizes.
++ * We first initialize the MMU to support 8M byte pages, then load one
++ * entry into each of the instruction and data TLBs to map the first
++ * 8M 1:1. I also mapped an additional I/O space 1:1 so we can get to
++ * the "internal" processor registers before MMU_init is called.
++ *
++ * The TLB code currently contains a major hack. Since I use the condition
++ * code register, I have to save and restore it. I am out of registers, so
++ * I just store it in memory location 0 (the TLB handlers are not reentrant).
++ * To avoid making any decisions, I need to use the "segment" valid bit
++ * in the first level table, but that would require many changes to the
++ * Linux page directory/table functions that I don't want to do right now.
++ *
++ * I used to use SPRG2 for a temporary register in the TLB handler, but it
++ * has since been put to other uses. I now use a hack to save a register
++ * and the CCR at memory location 0.....Someday I'll fix this.....
++ * -- Dan
++ */
++ .globl __start
++__start:
++ mr r31,r3 /* save parameters */
++ mr r30,r4
++ mr r29,r5
++ mr r28,r6
++ mr r27,r7
++
++ /* We have to turn on the MMU right away so we get cache modes
++ * set correctly.
++ */
++ bl initial_mmu
++
++/* We now have the lower 8 Meg mapped into TLB entries, and the caches
++ * ready to work.
++ */
++
++turn_on_mmu:
++ mfmsr r0
++ ori r0,r0,MSR_DR|MSR_IR
++ mtspr SPRN_SRR1,r0
++ lis r0,start_here at h
++ ori r0,r0,start_here at l
++ mtspr SPRN_SRR0,r0
++ SYNC
++ rfi /* enables MMU */
++
++/*
++ * Exception entry code. This code runs with address translation
++ * turned off, i.e. using physical addresses.
++ * We assume sprg3 has the physical address of the current
++ * task's thread_struct.
++ */
++#define EXCEPTION_PROLOG \
++ mtspr SPRN_SPRG0,r10; \
++ mtspr SPRN_SPRG1,r11; \
++ mfcr r10; \
++ EXCEPTION_PROLOG_1; \
++ EXCEPTION_PROLOG_2
++
++#define EXCEPTION_PROLOG_1 \
++ mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
++ andi. r11,r11,MSR_PR; \
++ tophys(r11,r1); /* use tophys(r1) if kernel */ \
++ beq 1f; \
++ mfspr r11,SPRN_SPRG3; \
++ lwz r11,THREAD_INFO-THREAD(r11); \
++ addi r11,r11,THREAD_SIZE; \
++ tophys(r11,r11); \
++1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */
++
++
++#define EXCEPTION_PROLOG_2 \
++ CLR_TOP32(r11); \
++ stw r10,_CCR(r11); /* save registers */ \
++ stw r12,GPR12(r11); \
++ stw r9,GPR9(r11); \
++ mfspr r10,SPRN_SPRG0; \
++ stw r10,GPR10(r11); \
++ mfspr r12,SPRN_SPRG1; \
++ stw r12,GPR11(r11); \
++ mflr r10; \
++ stw r10,_LINK(r11); \
++ mfspr r12,SPRN_SRR0; \
++ mfspr r9,SPRN_SRR1; \
++ stw r1,GPR1(r11); \
++ stw r1,0(r11); \
++ tovirt(r1,r11); /* set new kernel sp */ \
++ li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
++ MTMSRD(r10); /* (except for mach check in rtas) */ \
++ stw r0,GPR0(r11); \
++ SAVE_4GPRS(3, r11); \
++ SAVE_2GPRS(7, r11)
++
++/*
++ * Note: code which follows this uses cr0.eq (set if from kernel),
++ * r11, r12 (SRR0), and r9 (SRR1).
++ *
++ * Note2: once we have set r1 we are in a position to take exceptions
++ * again, and we could thus set MSR:RI at that point.
++ */
++
++/*
++ * Exception vectors.
++ */
++#define EXCEPTION(n, label, hdlr, xfer) \
++ . = n; \
++label: \
++ EXCEPTION_PROLOG; \
++ addi r3,r1,STACK_FRAME_OVERHEAD; \
++ xfer(n, hdlr)
++
++#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret) \
++ li r10,trap; \
++ stw r10,_TRAP(r11); \
++ li r10,MSR_KERNEL; \
++ copyee(r10, r9); \
++ bl tfer; \
++i##n: \
++ .long hdlr; \
++ .long ret
++
++#define COPY_EE(d, s) rlwimi d,s,0,16,16
++#define NOCOPY(d, s)
++
++#define EXC_XFER_STD(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
++ ret_from_except_full)
++
++#define EXC_XFER_LITE(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
++ ret_from_except)
++
++#define EXC_XFER_EE(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
++ ret_from_except_full)
++
++#define EXC_XFER_EE_LITE(n, hdlr) \
++ EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
++ ret_from_except)
++
++/* System reset */
++ EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
++
++/* Machine check */
++ . = 0x200
++MachineCheck:
++ EXCEPTION_PROLOG
++ mfspr r4,SPRN_DAR
++ stw r4,_DAR(r11)
++ mfspr r5,SPRN_DSISR
++ stw r5,_DSISR(r11)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_STD(0x200, machine_check_exception)
++
++/* Data access exception.
++ * This is "never generated" by the MPC8xx. We jump to it for other
++ * translation errors.
++ */
++ . = 0x300
++DataAccess:
++ EXCEPTION_PROLOG
++ mfspr r10,SPRN_DSISR
++ stw r10,_DSISR(r11)
++ mr r5,r10
++ mfspr r4,SPRN_DAR
++ EXC_XFER_EE_LITE(0x300, handle_page_fault)
++
++/* Instruction access exception.
++ * This is "never generated" by the MPC8xx. We jump to it for other
++ * translation errors.
++ */
++ . = 0x400
++InstructionAccess:
++ EXCEPTION_PROLOG
++ mr r4,r12
++ mr r5,r9
++ EXC_XFER_EE_LITE(0x400, handle_page_fault)
++
++/* External interrupt */
++ EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
++
++/* Alignment exception */
++ . = 0x600
++Alignment:
++ EXCEPTION_PROLOG
++ mfspr r4,SPRN_DAR
++ stw r4,_DAR(r11)
++ mfspr r5,SPRN_DSISR
++ stw r5,_DSISR(r11)
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_EE(0x600, alignment_exception)
++
++/* Program check exception */
++ EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
++
++/* No FPU on MPC8xx. This exception is not supposed to happen.
++*/
++ EXCEPTION(0x800, FPUnavailable, unknown_exception, EXC_XFER_STD)
++
++/* Decrementer */
++ EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
++
++ EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
++
++/* System call */
++ . = 0xc00
++SystemCall:
++ EXCEPTION_PROLOG
++ EXC_XFER_EE_LITE(0xc00, DoSyscall)
++
++/* Single step - not used on 601 */
++ EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
++ EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0xf00, Trap_0f, unknown_exception, EXC_XFER_EE)
++
++/* On the MPC8xx, this is a software emulation interrupt. It occurs
++ * for all unimplemented and illegal instructions.
++ */
++ EXCEPTION(0x1000, SoftEmu, SoftwareEmulation, EXC_XFER_STD)
++
++ . = 0x1100
++/*
++ * For the MPC8xx, this is a software tablewalk to load the instruction
++ * TLB. It is modelled after the example in the Motorola manual. The task
++ * switch loads the M_TWB register with the pointer to the first level table.
++ * If we discover there is no second level table (value is zero) or if there
++ * is an invalid pte, we load that into the TLB, which causes another fault
++ * into the TLB Error interrupt where we can handle such problems.
++ * We have to use the MD_xxx registers for the tablewalk because the
++ * equivalent MI_xxx registers only perform the attribute functions.
++ */
++InstructionTLBMiss:
++#ifdef CONFIG_8xx_CPU6
++ stw r3, 8(r0)
++#endif
++ DO_8xx_CPU6(0x3f80, r3)
++ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
++ mfcr r10
++ stw r10, 0(r0)
++ stw r11, 4(r0)
++ mfspr r10, SPRN_SRR0 /* Get effective address of fault */
++ DO_8xx_CPU6(0x3780, r3)
++ mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
++ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ andi. r11, r10, 0x0800 /* Address >= 0x80000000 */
++ beq 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++ rlwimi r10, r11, 0, 2, 19
++3:
++ lwz r11, 0(r10) /* Get the level 1 entry */
++ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
++ beq 2f /* If zero, don't try to find a pte */
++
++ /* We have a pte table, so load the MI_TWC with the attributes
++ * for this "segment."
++ */
++ ori r11,r11,1 /* Set valid bit */
++ DO_8xx_CPU6(0x2b80, r3)
++ mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
++ DO_8xx_CPU6(0x3b80, r3)
++ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
++ mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
++ lwz r10, 0(r11) /* Get the pte */
++
++ ori r10, r10, _PAGE_ACCESSED
++ stw r10, 0(r11)
++
++ /* The Linux PTE won't go exactly into the MMU TLB.
++ * Software indicator bits 21, 22 and 28 must be clear.
++ * Software indicator bits 24, 25, 26, and 27 must be
++ * set. All other Linux PTE bits control the behavior
++ * of the MMU.
++ */
++2: li r11, 0x00f0
++ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
++ DO_8xx_CPU6(0x2d80, r3)
++ mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
++
++ mfspr r10, SPRN_M_TW /* Restore registers */
++ lwz r11, 0(r0)
++ mtcr r11
++ lwz r11, 4(r0)
++#ifdef CONFIG_8xx_CPU6
++ lwz r3, 8(r0)
++#endif
++ rfi
++
++ . = 0x1200
++DataStoreTLBMiss:
++#ifdef CONFIG_8xx_CPU6
++ stw r3, 8(r0)
++#endif
++ DO_8xx_CPU6(0x3f80, r3)
++ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
++ mfcr r10
++ stw r10, 0(r0)
++ stw r11, 4(r0)
++ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ andi. r11, r10, 0x0800
++ beq 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++ rlwimi r10, r11, 0, 2, 19
++3:
++ lwz r11, 0(r10) /* Get the level 1 entry */
++ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
++ beq 2f /* If zero, don't try to find a pte */
++
++ /* We have a pte table, so load fetch the pte from the table.
++ */
++ ori r11, r11, 1 /* Set valid bit in physical L2 page */
++ DO_8xx_CPU6(0x3b80, r3)
++ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
++ mfspr r10, SPRN_MD_TWC /* ....and get the pte address */
++ lwz r10, 0(r10) /* Get the pte */
++
++ /* Insert the Guarded flag into the TWC from the Linux PTE.
++ * It is bit 27 of both the Linux PTE and the TWC (at least
++ * I got that right :-). It will be better when we can put
++ * this into the Linux pgd/pmd and load it in the operation
++ * above.
++ */
++ rlwimi r11, r10, 0, 27, 27
++ DO_8xx_CPU6(0x3b80, r3)
++ mtspr SPRN_MD_TWC, r11
++
++ mfspr r11, SPRN_MD_TWC /* get the pte address again */
++ ori r10, r10, _PAGE_ACCESSED
++ stw r10, 0(r11)
++
++ /* The Linux PTE won't go exactly into the MMU TLB.
++ * Software indicator bits 21, 22 and 28 must be clear.
++ * Software indicator bits 24, 25, 26, and 27 must be
++ * set. All other Linux PTE bits control the behavior
++ * of the MMU.
++ */
++2: li r11, 0x00f0
++ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
++ DO_8xx_CPU6(0x3d80, r3)
++ mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
++
++ mfspr r10, SPRN_M_TW /* Restore registers */
++ lwz r11, 0(r0)
++ mtcr r11
++ lwz r11, 4(r0)
++#ifdef CONFIG_8xx_CPU6
++ lwz r3, 8(r0)
++#endif
++ rfi
++
++/* This is an instruction TLB error on the MPC8xx. This could be due
++ * to many reasons, such as executing guarded memory or illegal instruction
++ * addresses. There is nothing to do but handle a big time error fault.
++ */
++ . = 0x1300
++InstructionTLBError:
++ b InstructionAccess
++
++/* This is the data TLB error on the MPC8xx. This could be due to
++ * many reasons, including a dirty update to a pte. We can catch that
++ * one here, but anything else is an error. First, we track down the
++ * Linux pte. If it is valid, write access is allowed, but the
++ * page dirty bit is not set, we will set it and reload the TLB. For
++ * any other case, we bail out to a higher level function that can
++ * handle it.
++ */
++ . = 0x1400
++DataTLBError:
++#ifdef CONFIG_8xx_CPU6
++ stw r3, 8(r0)
++#endif
++ DO_8xx_CPU6(0x3f80, r3)
++ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
++ mfcr r10
++ stw r10, 0(r0)
++ stw r11, 4(r0)
++
++ /* First, make sure this was a store operation.
++ */
++ mfspr r10, SPRN_DSISR
++ andis. r11, r10, 0x0200 /* If set, indicates store op */
++ beq 2f
++
++ /* The EA of a data TLB miss is automatically stored in the MD_EPN
++ * register. The EA of a data TLB error is automatically stored in
++ * the DAR, but not the MD_EPN register. We must copy the 20 most
++ * significant bits of the EA from the DAR to MD_EPN before we
++ * start walking the page tables. We also need to copy the CASID
++ * value from the M_CASID register.
++ * Addendum: The EA of a data TLB error is _supposed_ to be stored
++ * in DAR, but it seems that this doesn't happen in some cases, such
++ * as when the error is due to a dcbi instruction to a page with a
++ * TLB that doesn't have the changed bit set. In such cases, there
++ * does not appear to be any way to recover the EA of the error
++ * since it is neither in DAR nor MD_EPN. As a workaround, the
++ * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs
++ * are initialized in mapin_ram(). This will avoid the problem,
++ * assuming we only use the dcbi instruction on kernel addresses.
++ */
++ mfspr r10, SPRN_DAR
++ rlwinm r11, r10, 0, 0, 19
++ ori r11, r11, MD_EVALID
++ mfspr r10, SPRN_M_CASID
++ rlwimi r11, r10, 0, 28, 31
++ DO_8xx_CPU6(0x3780, r3)
++ mtspr SPRN_MD_EPN, r11
++
++ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ andi. r11, r10, 0x0800
++ beq 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++ rlwimi r10, r11, 0, 2, 19
++3:
++ lwz r11, 0(r10) /* Get the level 1 entry */
++ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
++ beq 2f /* If zero, bail */
++
++ /* We have a pte table, so fetch the pte from the table.
++ */
++ ori r11, r11, 1 /* Set valid bit in physical L2 page */
++ DO_8xx_CPU6(0x3b80, r3)
++ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
++ mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
++ lwz r10, 0(r11) /* Get the pte */
++
++ andi. r11, r10, _PAGE_RW /* Is it writeable? */
++ beq 2f /* Bail out if not */
++
++ /* Update 'changed', among others.
++ */
++ ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
++ mfspr r11, SPRN_MD_TWC /* Get pte address again */
++ stw r10, 0(r11) /* and update pte in table */
++
++ /* The Linux PTE won't go exactly into the MMU TLB.
++ * Software indicator bits 21, 22 and 28 must be clear.
++ * Software indicator bits 24, 25, 26, and 27 must be
++ * set. All other Linux PTE bits control the behavior
++ * of the MMU.
++ */
++ li r11, 0x00f0
++ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
++ DO_8xx_CPU6(0x3d80, r3)
++ mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
++
++ mfspr r10, SPRN_M_TW /* Restore registers */
++ lwz r11, 0(r0)
++ mtcr r11
++ lwz r11, 4(r0)
++#ifdef CONFIG_8xx_CPU6
++ lwz r3, 8(r0)
++#endif
++ rfi
++2:
++ mfspr r10, SPRN_M_TW /* Restore registers */
++ lwz r11, 0(r0)
++ mtcr r11
++ lwz r11, 4(r0)
++#ifdef CONFIG_8xx_CPU6
++ lwz r3, 8(r0)
++#endif
++ b DataAccess
++
++ EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
++
++/* On the MPC8xx, these next four traps are used for development
++ * support of breakpoints and such. Someday I will get around to
++ * using them.
++ */
++ EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
++
++ . = 0x2000
++
++ .globl giveup_fpu
++giveup_fpu:
++ blr
++
++/*
++ * This is where the main kernel code starts.
++ */
++start_here:
++ /* ptr to current */
++ lis r2,init_task at h
++ ori r2,r2,init_task at l
++
++ /* ptr to phys current thread */
++ tophys(r4,r2)
++ addi r4,r4,THREAD /* init task's THREAD */
++ mtspr SPRN_SPRG3,r4
++ li r3,0
++ mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */
++
++ /* stack */
++ lis r1,init_thread_union at ha
++ addi r1,r1,init_thread_union at l
++ li r0,0
++ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
++
++ bl early_init /* We have to do this with MMU on */
++
++/*
++ * Decide what sort of machine this is and initialize the MMU.
++ */
++ mr r3,r31
++ mr r4,r30
++ mr r5,r29
++ mr r6,r28
++ mr r7,r27
++ bl machine_init
++ bl MMU_init
++
++/*
++ * Go back to running unmapped so we can load up new values
++ * and change to using our exception vectors.
++ * On the 8xx, all we have to do is invalidate the TLB to clear
++ * the old 8M byte TLB mappings and load the page table base register.
++ */
++ /* The right way to do this would be to track it down through
++ * init's THREAD like the context switch code does, but this is
++ * easier......until someone changes init's static structures.
++ */
++ lis r6, swapper_pg_dir at h
++ ori r6, r6, swapper_pg_dir at l
++ tophys(r6,r6)
++#ifdef CONFIG_8xx_CPU6
++ lis r4, cpu6_errata_word at h
++ ori r4, r4, cpu6_errata_word at l
++ li r3, 0x3980
++ stw r3, 12(r4)
++ lwz r3, 12(r4)
++#endif
++ mtspr SPRN_M_TWB, r6
++ lis r4,2f at h
++ ori r4,r4,2f at l
++ tophys(r4,r4)
++ li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
++ mtspr SPRN_SRR0,r4
++ mtspr SPRN_SRR1,r3
++ rfi
++/* Load up the kernel context */
++2:
++ SYNC /* Force all PTE updates to finish */
++ tlbia /* Clear all TLB entries */
++ sync /* wait for tlbia/tlbie to finish */
++ TLBSYNC /* ... on all CPUs */
++
++ /* set up the PTE pointers for the Abatron bdiGDB.
++ */
++ tovirt(r6,r6)
++ lis r5, abatron_pteptrs at h
++ ori r5, r5, abatron_pteptrs at l
++ stw r5, 0xf0(r0) /* Must match your Abatron config file */
++ tophys(r5,r5)
++ stw r6, 0(r5)
++
++/* Now turn on the MMU for real! */
++ li r4,MSR_KERNEL
++ lis r3,start_kernel at h
++ ori r3,r3,start_kernel at l
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
++ rfi /* enable MMU and jump to start_kernel */
++
++/* Set up the initial MMU state so we can do the first level of
++ * kernel initialization. This maps the first 8 MBytes of memory 1:1
++ * virtual to physical. Also, set the cache mode since that is defined
++ * by TLB entries and perform any additional mapping (like of the IMMR).
++ * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel,
++ * 24 Mbytes of data, and the 8M IMMR space. Anything not covered by
++ * these mappings is mapped by page tables.
++ */
++initial_mmu:
++ tlbia /* Invalidate all TLB entries */
++#ifdef CONFIG_PIN_TLB
++ lis r8, MI_RSV4I at h
++ ori r8, r8, 0x1c00
++#else
++ li r8, 0
++#endif
++ mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
++
++#ifdef CONFIG_PIN_TLB
++ lis r10, (MD_RSV4I | MD_RESETVAL)@h
++ ori r10, r10, 0x1c00
++ mr r8, r10
++#else
++ lis r10, MD_RESETVAL at h
++#endif
++#ifndef CONFIG_8xx_COPYBACK
++ oris r10, r10, MD_WTDEF at h
++#endif
++ mtspr SPRN_MD_CTR, r10 /* Set data TLB control */
++
++ /* Now map the lower 8 Meg into the TLBs. For this quick hack,
++ * we can load the instruction and data TLB registers with the
++ * same values.
++ */
++ lis r8, KERNELBASE at h /* Create vaddr for TLB */
++ ori r8, r8, MI_EVALID /* Mark it valid */
++ mtspr SPRN_MI_EPN, r8
++ mtspr SPRN_MD_EPN, r8
++ li r8, MI_PS8MEG /* Set 8M byte page */
++ ori r8, r8, MI_SVALID /* Make it valid */
++ mtspr SPRN_MI_TWC, r8
++ mtspr SPRN_MD_TWC, r8
++ li r8, MI_BOOTINIT /* Create RPN for address 0 */
++ mtspr SPRN_MI_RPN, r8 /* Store TLB entry */
++ mtspr SPRN_MD_RPN, r8
++ lis r8, MI_Kp at h /* Set the protection mode */
++ mtspr SPRN_MI_AP, r8
++ mtspr SPRN_MD_AP, r8
++
++ /* Map another 8 MByte at the IMMR to get the processor
++ * internal registers (among other things).
++ */
++#ifdef CONFIG_PIN_TLB
++ addi r10, r10, 0x0100
++ mtspr SPRN_MD_CTR, r10
++#endif
++ mfspr r9, 638 /* Get current IMMR */
++ andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */
++
++ mr r8, r9 /* Create vaddr for TLB */
++ ori r8, r8, MD_EVALID /* Mark it valid */
++ mtspr SPRN_MD_EPN, r8
++ li r8, MD_PS8MEG /* Set 8M byte page */
++ ori r8, r8, MD_SVALID /* Make it valid */
++ mtspr SPRN_MD_TWC, r8
++ mr r8, r9 /* Create paddr for TLB */
++ ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
++ mtspr SPRN_MD_RPN, r8
++
++#ifdef CONFIG_PIN_TLB
++ /* Map two more 8M kernel data pages.
++ */
++ addi r10, r10, 0x0100
++ mtspr SPRN_MD_CTR, r10
++
++ lis r8, KERNELBASE at h /* Create vaddr for TLB */
++ addis r8, r8, 0x0080 /* Add 8M */
++ ori r8, r8, MI_EVALID /* Mark it valid */
++ mtspr SPRN_MD_EPN, r8
++ li r9, MI_PS8MEG /* Set 8M byte page */
++ ori r9, r9, MI_SVALID /* Make it valid */
++ mtspr SPRN_MD_TWC, r9
++ li r11, MI_BOOTINIT /* Create RPN for address 0 */
++ addis r11, r11, 0x0080 /* Add 8M */
++ mtspr SPRN_MD_RPN, r8
++
++ addis r8, r8, 0x0080 /* Add 8M */
++ mtspr SPRN_MD_EPN, r8
++ mtspr SPRN_MD_TWC, r9
++ addis r11, r11, 0x0080 /* Add 8M */
++ mtspr SPRN_MD_RPN, r8
++#endif
++
++ /* Since the cache is enabled according to the information we
++ * just loaded into the TLB, invalidate and enable the caches here.
++ * We should probably check/set other modes....later.
++ */
++ lis r8, IDC_INVALL at h
++ mtspr SPRN_IC_CST, r8
++ mtspr SPRN_DC_CST, r8
++ lis r8, IDC_ENABLE at h
++ mtspr SPRN_IC_CST, r8
++#ifdef CONFIG_8xx_COPYBACK
++ mtspr SPRN_DC_CST, r8
++#else
++ /* For a debug option, I left this here to easily enable
++ * the write through cache mode
++ */
++ lis r8, DC_SFWT at h
++ mtspr SPRN_DC_CST, r8
++ lis r8, IDC_ENABLE at h
++ mtspr SPRN_DC_CST, r8
++#endif
++ blr
++
++
++/*
++ * Set up to use a given MMU context.
++ * r3 is context number, r4 is PGD pointer.
++ *
++ * We place the physical address of the new task page directory loaded
++ * into the MMU base register, and set the ASID compare register with
++ * the new "context."
++ */
++_GLOBAL(set_context)
++
++#ifdef CONFIG_BDI_SWITCH
++ /* Context switch the PTE pointer for the Abatron BDI2000.
++ * The PGDIR is passed as second argument.
++ */
++ lis r5, KERNELBASE at h
++ lwz r5, 0xf0(r5)
++ stw r4, 0x4(r5)
++#endif
++
++#ifdef CONFIG_8xx_CPU6
++ lis r6, cpu6_errata_word at h
++ ori r6, r6, cpu6_errata_word at l
++ tophys (r4, r4)
++ li r7, 0x3980
++ stw r7, 12(r6)
++ lwz r7, 12(r6)
++ mtspr SPRN_M_TWB, r4 /* Update MMU base address */
++ li r7, 0x3380
++ stw r7, 12(r6)
++ lwz r7, 12(r6)
++ mtspr SPRN_M_CASID, r3 /* Update context */
++#else
++ mtspr SPRN_M_CASID,r3 /* Update context */
++ tophys (r4, r4)
++ mtspr SPRN_M_TWB, r4 /* and pgd */
++#endif
++ SYNC
++ blr
++
++#ifdef CONFIG_8xx_CPU6
++/* It's here because it is unique to the 8xx.
++ * It is important we get called with interrupts disabled. I used to
++ * do that, but it appears that all code that calls this already had
++ * interrupt disabled.
++ */
++ .globl set_dec_cpu6
++set_dec_cpu6:
++ lis r7, cpu6_errata_word at h
++ ori r7, r7, cpu6_errata_word at l
++ li r4, 0x2c00
++ stw r4, 8(r7)
++ lwz r4, 8(r7)
++ mtspr 22, r3 /* Update Decrementer */
++ SYNC
++ blr
++#endif
++
++/*
++ * We put a few things here that have to be page-aligned.
++ * This stuff goes at the beginning of the data segment,
++ * which is page-aligned.
++ */
++ .data
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
++ .space 4096
++
++ .globl swapper_pg_dir
++swapper_pg_dir:
++ .space 4096
++
++/*
++ * This space gets a copy of optional info passed to us by the bootstrap
++ * Used to pass parameters into the kernel like root=/dev/sda1, etc.
++ */
++ .globl cmd_line
++cmd_line:
++ .space 512
++
++/* Room for two PTE table poiners, usually the kernel and current user
++ * pointer to their respective root page table (pgdir).
++ */
++abatron_pteptrs:
++ .space 8
++
++#ifdef CONFIG_8xx_CPU6
++ .globl cpu6_errata_word
++cpu6_errata_word:
++ .space 16
++#endif
++
+diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/head_fsl_booke.S
+@@ -0,0 +1,1063 @@
++/*
++ * arch/ppc/kernel/head_fsl_booke.S
++ *
++ * Kernel execution entry point code.
++ *
++ * Copyright (c) 1995-1996 Gary Thomas <gdt at linuxppc.org>
++ * Initial PowerPC version.
++ * Copyright (c) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Rewritten for PReP
++ * Copyright (c) 1996 Paul Mackerras <paulus at cs.anu.edu.au>
++ * Low-level exception handers, MMU support, and rewrite.
++ * Copyright (c) 1997 Dan Malek <dmalek at jlc.net>
++ * PowerPC 8xx modifications.
++ * Copyright (c) 1998-1999 TiVo, Inc.
++ * PowerPC 403GCX modifications.
++ * Copyright (c) 1999 Grant Erickson <grant at lcse.umn.edu>
++ * PowerPC 403GCX/405GP modifications.
++ * Copyright 2000 MontaVista Software Inc.
++ * PPC405 modifications
++ * PowerPC 403GCX/405GP modifications.
++ * Author: MontaVista Software, Inc.
++ * frank_rowand at mvista.com or source at mvista.com
++ * debbie_chu at mvista.com
++ * Copyright 2002-2004 MontaVista Software, Inc.
++ * PowerPC 44x support, Matt Porter <mporter at kernel.crashing.org>
++ * Copyright 2004 Freescale Semiconductor, Inc
++ * PowerPC e500 modifications, Kumar Gala <kumar.gala at freescale.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/config.h>
++#include <linux/threads.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include "head_booke.h"
++
++/* As with the other PowerPC ports, it is expected that when code
++ * execution begins here, the following registers contain valid, yet
++ * optional, information:
++ *
++ * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
++ * r4 - Starting address of the init RAM disk
++ * r5 - Ending address of the init RAM disk
++ * r6 - Start of kernel command line string (e.g. "mem=128")
++ * r7 - End of kernel command line string
++ *
++ */
++ .text
++_GLOBAL(_stext)
++_GLOBAL(_start)
++ /*
++ * Reserve a word at a fixed location to store the address
++ * of abatron_pteptrs
++ */
++ nop
++/*
++ * Save parameters we are passed
++ */
++ mr r31,r3
++ mr r30,r4
++ mr r29,r5
++ mr r28,r6
++ mr r27,r7
++ li r24,0 /* CPU number */
++
++/* We try to not make any assumptions about how the boot loader
++ * setup or used the TLBs. We invalidate all mappings from the
++ * boot loader and load a single entry in TLB1[0] to map the
++ * first 16M of kernel memory. Any boot info passed from the
++ * bootloader needs to live in this first 16M.
++ *
++ * Requirement on bootloader:
++ * - The page we're executing in needs to reside in TLB1 and
++ * have IPROT=1. If not an invalidate broadcast could
++ * evict the entry we're currently executing in.
++ *
++ * r3 = Index of TLB1 were executing in
++ * r4 = Current MSR[IS]
++ * r5 = Index of TLB1 temp mapping
++ *
++ * Later in mapin_ram we will correctly map lowmem, and resize TLB1[0]
++ * if needed
++ */
++
++/* 1. Find the index of the entry we're executing in */
++ bl invstr /* Find our address */
++invstr: mflr r6 /* Make it accessible */
++ mfmsr r7
++ rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
++ mfspr r7, SPRN_PID0
++ slwi r7,r7,16
++ or r7,r7,r4
++ mtspr SPRN_MAS6,r7
++ tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
++#ifndef CONFIG_E200
++ mfspr r7,SPRN_MAS1
++ andis. r7,r7,MAS1_VALID at h
++ bne match_TLB
++ mfspr r7,SPRN_PID1
++ slwi r7,r7,16
++ or r7,r7,r4
++ mtspr SPRN_MAS6,r7
++ tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
++ mfspr r7,SPRN_MAS1
++ andis. r7,r7,MAS1_VALID at h
++ bne match_TLB
++ mfspr r7, SPRN_PID2
++ slwi r7,r7,16
++ or r7,r7,r4
++ mtspr SPRN_MAS6,r7
++ tlbsx 0,r6 /* Fall through, we had to match */
++#endif
++match_TLB:
++ mfspr r7,SPRN_MAS0
++ rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
++
++ mfspr r7,SPRN_MAS1 /* Insure IPROT set */
++ oris r7,r7,MAS1_IPROT at h
++ mtspr SPRN_MAS1,r7
++ tlbwe
++
++/* 2. Invalidate all entries except the entry we're executing in */
++ mfspr r9,SPRN_TLB1CFG
++ andi. r9,r9,0xfff
++ li r6,0 /* Set Entry counter to 0 */
++1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
++ rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
++ mtspr SPRN_MAS0,r7
++ tlbre
++ mfspr r7,SPRN_MAS1
++ rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
++ cmpw r3,r6
++ beq skpinv /* Dont update the current execution TLB */
++ mtspr SPRN_MAS1,r7
++ tlbwe
++ isync
++skpinv: addi r6,r6,1 /* Increment */
++ cmpw r6,r9 /* Are we done? */
++ bne 1b /* If not, repeat */
++
++ /* Invalidate TLB0 */
++ li r6,0x04
++ tlbivax 0,r6
++#ifdef CONFIG_SMP
++ tlbsync
++#endif
++ /* Invalidate TLB1 */
++ li r6,0x0c
++ tlbivax 0,r6
++#ifdef CONFIG_SMP
++ tlbsync
++#endif
++ msync
++
++/* 3. Setup a temp mapping and jump to it */
++ andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
++ addi r5, r5, 0x1
++ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
++ rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
++ mtspr SPRN_MAS0,r7
++ tlbre
++
++ /* Just modify the entry ID and EPN for the temp mapping */
++ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
++ rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
++ mtspr SPRN_MAS0,r7
++ xori r6,r4,1 /* Setup TMP mapping in the other Address space */
++ slwi r6,r6,12
++ oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h
++ ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
++ mtspr SPRN_MAS1,r6
++ mfspr r6,SPRN_MAS2
++ li r7,0 /* temp EPN = 0 */
++ rlwimi r7,r6,0,20,31
++ mtspr SPRN_MAS2,r7
++ tlbwe
++
++ xori r6,r4,1
++ slwi r6,r6,5 /* setup new context with other address space */
++ bl 1f /* Find our address */
++1: mflr r9
++ rlwimi r7,r9,0,20,31
++ addi r7,r7,24
++ mtspr SPRN_SRR0,r7
++ mtspr SPRN_SRR1,r6
++ rfi
++
++/* 4. Clear out PIDs & Search info */
++ li r6,0
++ mtspr SPRN_PID0,r6
++#ifndef CONFIG_E200
++ mtspr SPRN_PID1,r6
++ mtspr SPRN_PID2,r6
++#endif
++ mtspr SPRN_MAS6,r6
++
++/* 5. Invalidate mapping we started in */
++ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
++ rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
++ mtspr SPRN_MAS0,r7
++ tlbre
++ li r6,0
++ mtspr SPRN_MAS1,r6
++ tlbwe
++ /* Invalidate TLB1 */
++ li r9,0x0c
++ tlbivax 0,r9
++#ifdef CONFIG_SMP
++ tlbsync
++#endif
++ msync
++
++/* 6. Setup KERNELBASE mapping in TLB1[0] */
++ lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
++ mtspr SPRN_MAS0,r6
++ lis r6,(MAS1_VALID|MAS1_IPROT)@h
++ ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_16M))@l
++ mtspr SPRN_MAS1,r6
++ li r7,0
++ lis r6,KERNELBASE at h
++ ori r6,r6,KERNELBASE at l
++ rlwimi r6,r7,0,20,31
++ mtspr SPRN_MAS2,r6
++ li r7,(MAS3_SX|MAS3_SW|MAS3_SR)
++ mtspr SPRN_MAS3,r7
++ tlbwe
++
++/* 7. Jump to KERNELBASE mapping */
++ lis r7,MSR_KERNEL at h
++ ori r7,r7,MSR_KERNEL at l
++ bl 1f /* Find our address */
++1: mflr r9
++ rlwimi r6,r9,0,20,31
++ addi r6,r6,24
++ mtspr SPRN_SRR0,r6
++ mtspr SPRN_SRR1,r7
++ rfi /* start execution out of TLB1[0] entry */
++
++/* 8. Clear out the temp mapping */
++ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
++ rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
++ mtspr SPRN_MAS0,r7
++ tlbre
++ mtspr SPRN_MAS1,r8
++ tlbwe
++ /* Invalidate TLB1 */
++ li r9,0x0c
++ tlbivax 0,r9
++#ifdef CONFIG_SMP
++ tlbsync
++#endif
++ msync
++
++ /* Establish the interrupt vector offsets */
++ SET_IVOR(0, CriticalInput);
++ SET_IVOR(1, MachineCheck);
++ SET_IVOR(2, DataStorage);
++ SET_IVOR(3, InstructionStorage);
++ SET_IVOR(4, ExternalInput);
++ SET_IVOR(5, Alignment);
++ SET_IVOR(6, Program);
++ SET_IVOR(7, FloatingPointUnavailable);
++ SET_IVOR(8, SystemCall);
++ SET_IVOR(9, AuxillaryProcessorUnavailable);
++ SET_IVOR(10, Decrementer);
++ SET_IVOR(11, FixedIntervalTimer);
++ SET_IVOR(12, WatchdogTimer);
++ SET_IVOR(13, DataTLBError);
++ SET_IVOR(14, InstructionTLBError);
++ SET_IVOR(15, Debug);
++ SET_IVOR(32, SPEUnavailable);
++ SET_IVOR(33, SPEFloatingPointData);
++ SET_IVOR(34, SPEFloatingPointRound);
++#ifndef CONFIG_E200
++ SET_IVOR(35, PerformanceMonitor);
++#endif
++
++ /* Establish the interrupt vector base */
++ lis r4,interrupt_base at h /* IVPR only uses the high 16-bits */
++ mtspr SPRN_IVPR,r4
++
++ /* Setup the defaults for TLB entries */
++ li r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
++#ifdef CONFIG_E200
++ oris r2,r2,MAS4_TLBSELD(1)@h
++#endif
++ mtspr SPRN_MAS4, r2
++
++#if 0
++ /* Enable DOZE */
++ mfspr r2,SPRN_HID0
++ oris r2,r2,HID0_DOZE at h
++ mtspr SPRN_HID0, r2
++#endif
++#ifdef CONFIG_E200
++ /* enable dedicated debug exception handling resources (Debug APU) */
++ mfspr r2,SPRN_HID0
++ ori r2,r2,HID0_DAPUEN at l
++ mtspr SPRN_HID0,r2
++#endif
++
++#if !defined(CONFIG_BDI_SWITCH)
++ /*
++ * The Abatron BDI JTAG debugger does not tolerate others
++ * mucking with the debug registers.
++ */
++ lis r2,DBCR0_IDM at h
++ mtspr SPRN_DBCR0,r2
++ /* clear any residual debug events */
++ li r2,-1
++ mtspr SPRN_DBSR,r2
++#endif
++
++ /*
++ * This is where the main kernel code starts.
++ */
++
++ /* ptr to current */
++ lis r2,init_task at h
++ ori r2,r2,init_task at l
++
++ /* ptr to current thread */
++ addi r4,r2,THREAD /* init task's THREAD */
++ mtspr SPRN_SPRG3,r4
++
++ /* stack */
++ lis r1,init_thread_union at h
++ ori r1,r1,init_thread_union at l
++ li r0,0
++ stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
++
++ bl early_init
++
++ mfspr r3,SPRN_TLB1CFG
++ andi. r3,r3,0xfff
++ lis r4,num_tlbcam_entries at ha
++ stw r3,num_tlbcam_entries at l(r4)
++/*
++ * Decide what sort of machine this is and initialize the MMU.
++ */
++ mr r3,r31
++ mr r4,r30
++ mr r5,r29
++ mr r6,r28
++ mr r7,r27
++ bl machine_init
++ bl MMU_init
++
++ /* Setup PTE pointers for the Abatron bdiGDB */
++ lis r6, swapper_pg_dir at h
++ ori r6, r6, swapper_pg_dir at l
++ lis r5, abatron_pteptrs at h
++ ori r5, r5, abatron_pteptrs at l
++ lis r4, KERNELBASE at h
++ ori r4, r4, KERNELBASE at l
++ stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */
++ stw r6, 0(r5)
++
++ /* Let's move on */
++ lis r4,start_kernel at h
++ ori r4,r4,start_kernel at l
++ lis r3,MSR_KERNEL at h
++ ori r3,r3,MSR_KERNEL at l
++ mtspr SPRN_SRR0,r4
++ mtspr SPRN_SRR1,r3
++ rfi /* change context and jump to start_kernel */
++
++/* Macros to hide the PTE size differences
++ *
++ * FIND_PTE -- walks the page tables given EA & pgdir pointer
++ * r10 -- EA of fault
++ * r11 -- PGDIR pointer
++ * r12 -- free
++ * label 2: is the bailout case
++ *
++ * if we find the pte (fall through):
++ * r11 is low pte word
++ * r12 is pointer to the pte
++ */
++#ifdef CONFIG_PTE_64BIT
++#define PTE_FLAGS_OFFSET 4
++#define FIND_PTE \
++ rlwinm r12, r10, 13, 19, 29; /* Compute pgdir/pmd offset */ \
++ lwzx r11, r12, r11; /* Get pgd/pmd entry */ \
++ rlwinm. r12, r11, 0, 0, 20; /* Extract pt base address */ \
++ beq 2f; /* Bail if no table */ \
++ rlwimi r12, r10, 23, 20, 28; /* Compute pte address */ \
++ lwz r11, 4(r12); /* Get pte entry */
++#else
++#define PTE_FLAGS_OFFSET 0
++#define FIND_PTE \
++ rlwimi r11, r10, 12, 20, 29; /* Create L1 (pgdir/pmd) address */ \
++ lwz r11, 0(r11); /* Get L1 entry */ \
++ rlwinm. r12, r11, 0, 0, 19; /* Extract L2 (pte) base address */ \
++ beq 2f; /* Bail if no table */ \
++ rlwimi r12, r10, 22, 20, 29; /* Compute PTE address */ \
++ lwz r11, 0(r12); /* Get Linux PTE */
++#endif
++
++/*
++ * Interrupt vector entry code
++ *
++ * The Book E MMUs are always on so we don't need to handle
++ * interrupts in real mode as with previous PPC processors. In
++ * this case we handle interrupts in the kernel virtual address
++ * space.
++ *
++ * Interrupt vectors are dynamically placed relative to the
++ * interrupt prefix as determined by the address of interrupt_base.
++ * The interrupt vectors offsets are programmed using the labels
++ * for each interrupt vector entry.
++ *
++ * Interrupt vectors must be aligned on a 16 byte boundary.
++ * We align on a 32 byte cache line boundary for good measure.
++ */
++
++interrupt_base:
++ /* Critical Input Interrupt */
++ CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
++
++ /* Machine Check Interrupt */
++#ifdef CONFIG_E200
++ /* no RFMCI, MCSRRs on E200 */
++ CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
++#else
++ MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
++#endif
++
++ /* Data Storage Interrupt */
++ START_EXCEPTION(DataStorage)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++ mtspr SPRN_SPRG4W, r12
++ mtspr SPRN_SPRG5W, r13
++ mfcr r11
++ mtspr SPRN_SPRG7W, r11
++
++ /*
++ * Check if it was a store fault, if not then bail
++ * because a user tried to access a kernel or
++ * read-protected page. Otherwise, get the
++ * offending address and handle it.
++ */
++ mfspr r10, SPRN_ESR
++ andis. r10, r10, ESR_ST at h
++ beq 2f
++
++ mfspr r10, SPRN_DEAR /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ ori r11, r11, TASK_SIZE at l
++ cmplw 0, r10, r11
++ bge 2f
++
++ /* Get the PGD for the current thread */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++4:
++ FIND_PTE
++
++ /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
++ andi. r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
++ cmpwi 0, r13, _PAGE_RW|_PAGE_USER
++ bne 2f /* Bail if not */
++
++ /* Update 'changed'. */
++ ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
++ stw r11, PTE_FLAGS_OFFSET(r12) /* Update Linux page table */
++
++ /* MAS2 not updated as the entry does exist in the tlb, this
++ fault taken to detect state transition (eg: COW -> DIRTY)
++ */
++ andi. r11, r11, _PAGE_HWEXEC
++ rlwimi r11, r11, 31, 27, 27 /* SX <- _PAGE_HWEXEC */
++ ori r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
++
++ /* update search PID in MAS6, AS = 0 */
++ mfspr r12, SPRN_PID0
++ slwi r12, r12, 16
++ mtspr SPRN_MAS6, r12
++
++ /* find the TLB index that caused the fault. It has to be here. */
++ tlbsx 0, r10
++
++ /* only update the perm bits, assume the RPN is fine */
++ mfspr r12, SPRN_MAS3
++ rlwimi r12, r11, 0, 20, 31
++ mtspr SPRN_MAS3,r12
++ tlbwe
++
++ /* Done...restore registers and get out of here. */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ rfi /* Force context change */
++
++2:
++ /*
++ * The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b data_access
++
++ /* Instruction Storage Interrupt */
++ INSTRUCTION_STORAGE_EXCEPTION
++
++ /* External Input Interrupt */
++ EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
++
++ /* Alignment Interrupt */
++ ALIGNMENT_EXCEPTION
++
++ /* Program Interrupt */
++ PROGRAM_EXCEPTION
++
++ /* Floating Point Unavailable Interrupt */
++#ifdef CONFIG_PPC_FPU
++ FP_UNAVAILABLE_EXCEPTION
++#else
++#ifdef CONFIG_E200
++ /* E200 treats 'normal' floating point instructions as FP Unavail exception */
++ EXCEPTION(0x0800, FloatingPointUnavailable, program_check_exception, EXC_XFER_EE)
++#else
++ EXCEPTION(0x0800, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
++#endif
++#endif
++
++ /* System Call Interrupt */
++ START_EXCEPTION(SystemCall)
++ NORMAL_EXCEPTION_PROLOG
++ EXC_XFER_EE_LITE(0x0c00, DoSyscall)
++
++ /* Auxillary Processor Unavailable Interrupt */
++ EXCEPTION(0x2900, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
++
++ /* Decrementer Interrupt */
++ DECREMENTER_EXCEPTION
++
++ /* Fixed Internal Timer Interrupt */
++ /* TODO: Add FIT support */
++ EXCEPTION(0x3100, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
++
++ /* Watchdog Timer Interrupt */
++#ifdef CONFIG_BOOKE_WDT
++ CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException)
++#else
++ CRITICAL_EXCEPTION(0x3200, WatchdogTimer, unknown_exception)
++#endif
++
++ /* Data TLB Error Interrupt */
++ START_EXCEPTION(DataTLBError)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++ mtspr SPRN_SPRG4W, r12
++ mtspr SPRN_SPRG5W, r13
++ mfcr r11
++ mtspr SPRN_SPRG7W, r11
++ mfspr r10, SPRN_DEAR /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ ori r11, r11, TASK_SIZE at l
++ cmplw 5, r10, r11
++ blt 5, 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++
++ mfspr r12,SPRN_MAS1 /* Set TID to 0 */
++ rlwinm r12,r12,0,16,1
++ mtspr SPRN_MAS1,r12
++
++ b 4f
++
++ /* Get the PGD for the current thread */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++
++4:
++ FIND_PTE
++ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
++ beq 2f /* Bail if not present */
++
++#ifdef CONFIG_PTE_64BIT
++ lwz r13, 0(r12)
++#endif
++ ori r11, r11, _PAGE_ACCESSED
++ stw r11, PTE_FLAGS_OFFSET(r12)
++
++ /* Jump to common tlb load */
++ b finish_tlb_load
++2:
++ /* The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b data_access
++
++ /* Instruction TLB Error Interrupt */
++ /*
++ * Nearly the same as above, except we get our
++ * information from different registers and bailout
++ * to a different point.
++ */
++ START_EXCEPTION(InstructionTLBError)
++ mtspr SPRN_SPRG0, r10 /* Save some working registers */
++ mtspr SPRN_SPRG1, r11
++ mtspr SPRN_SPRG4W, r12
++ mtspr SPRN_SPRG5W, r13
++ mfcr r11
++ mtspr SPRN_SPRG7W, r11
++ mfspr r10, SPRN_SRR0 /* Get faulting address */
++
++ /* If we are faulting a kernel address, we have to use the
++ * kernel page tables.
++ */
++ lis r11, TASK_SIZE at h
++ ori r11, r11, TASK_SIZE at l
++ cmplw 5, r10, r11
++ blt 5, 3f
++ lis r11, swapper_pg_dir at h
++ ori r11, r11, swapper_pg_dir at l
++
++ mfspr r12,SPRN_MAS1 /* Set TID to 0 */
++ rlwinm r12,r12,0,16,1
++ mtspr SPRN_MAS1,r12
++
++ b 4f
++
++ /* Get the PGD for the current thread */
++3:
++ mfspr r11,SPRN_SPRG3
++ lwz r11,PGDIR(r11)
++
++4:
++ FIND_PTE
++ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
++ beq 2f /* Bail if not present */
++
++#ifdef CONFIG_PTE_64BIT
++ lwz r13, 0(r12)
++#endif
++ ori r11, r11, _PAGE_ACCESSED
++ stw r11, PTE_FLAGS_OFFSET(r12)
++
++ /* Jump to common TLB load point */
++ b finish_tlb_load
++
++2:
++ /* The bailout. Restore registers to pre-exception conditions
++ * and call the heavyweights to help us out.
++ */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ b InstructionStorage
++
++#ifdef CONFIG_SPE
++ /* SPE Unavailable */
++ START_EXCEPTION(SPEUnavailable)
++ NORMAL_EXCEPTION_PROLOG
++ bne load_up_spe
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_EE_LITE(0x2010, KernelSPE)
++#else
++ EXCEPTION(0x2020, SPEUnavailable, unknown_exception, EXC_XFER_EE)
++#endif /* CONFIG_SPE */
++
++ /* SPE Floating Point Data */
++#ifdef CONFIG_SPE
++ EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
++#else
++ EXCEPTION(0x2040, SPEFloatingPointData, unknown_exception, EXC_XFER_EE)
++#endif /* CONFIG_SPE */
++
++ /* SPE Floating Point Round */
++ EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception, EXC_XFER_EE)
++
++ /* Performance Monitor */
++ EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
++
++
++ /* Debug Interrupt */
++ DEBUG_EXCEPTION
++
++/*
++ * Local functions
++ */
++
++ /*
++ * Data TLB exceptions will bail out to this point
++ * if they can't resolve the lightweight TLB fault.
++ */
++data_access:
++ NORMAL_EXCEPTION_PROLOG
++ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
++ stw r5,_ESR(r11)
++ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
++ andis. r10,r5,(ESR_ILK|ESR_DLK)@h
++ bne 1f
++ EXC_XFER_EE_LITE(0x0300, handle_page_fault)
++1:
++ addi r3,r1,STACK_FRAME_OVERHEAD
++ EXC_XFER_EE_LITE(0x0300, CacheLockingException)
++
++/*
++
++ * Both the instruction and data TLB miss get to this
++ * point to load the TLB.
++ * r10 - EA of fault
++ * r11 - TLB (info from Linux PTE)
++ * r12, r13 - available to use
++ * CR5 - results of addr < TASK_SIZE
++ * MAS0, MAS1 - loaded with proper value when we get here
++ * MAS2, MAS3 - will need additional info from Linux PTE
++ * Upon exit, we reload everything and RFI.
++ */
++finish_tlb_load:
++ /*
++ * We set execute, because we don't have the granularity to
++ * properly set this at the page level (Linux problem).
++ * Many of these bits are software only. Bits we don't set
++ * here we (properly should) assume have the appropriate value.
++ */
++
++ mfspr r12, SPRN_MAS2
++#ifdef CONFIG_PTE_64BIT
++ rlwimi r12, r11, 26, 24, 31 /* extract ...WIMGE from pte */
++#else
++ rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */
++#endif
++ mtspr SPRN_MAS2, r12
++
++ bge 5, 1f
++
++ /* is user addr */
++ andi. r12, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
++ andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */
++ srwi r10, r12, 1
++ or r12, r12, r10 /* Copy user perms into supervisor */
++ iseleq r12, 0, r12
++ b 2f
++
++ /* is kernel addr */
++1: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */
++ ori r12, r12, (MAS3_SX | MAS3_SR)
++
++#ifdef CONFIG_PTE_64BIT
++2: rlwimi r12, r13, 24, 0, 7 /* grab RPN[32:39] */
++ rlwimi r12, r11, 24, 8, 19 /* grab RPN[40:51] */
++ mtspr SPRN_MAS3, r12
++BEGIN_FTR_SECTION
++ srwi r10, r13, 8 /* grab RPN[8:31] */
++ mtspr SPRN_MAS7, r10
++END_FTR_SECTION_IFSET(CPU_FTR_BIG_PHYS)
++#else
++2: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */
++ mtspr SPRN_MAS3, r11
++#endif
++#ifdef CONFIG_E200
++ /* Round robin TLB1 entries assignment */
++ mfspr r12, SPRN_MAS0
++
++ /* Extract TLB1CFG(NENTRY) */
++ mfspr r11, SPRN_TLB1CFG
++ andi. r11, r11, 0xfff
++
++ /* Extract MAS0(NV) */
++ andi. r13, r12, 0xfff
++ addi r13, r13, 1
++ cmpw 0, r13, r11
++ addi r12, r12, 1
++
++ /* check if we need to wrap */
++ blt 7f
++
++ /* wrap back to first free tlbcam entry */
++ lis r13, tlbcam_index at ha
++ lwz r13, tlbcam_index at l(r13)
++ rlwimi r12, r13, 0, 20, 31
++7:
++ mtspr SPRN_MAS0,r12
++#endif /* CONFIG_E200 */
++
++ tlbwe
++
++ /* Done...restore registers and get out of here. */
++ mfspr r11, SPRN_SPRG7R
++ mtcr r11
++ mfspr r13, SPRN_SPRG5R
++ mfspr r12, SPRN_SPRG4R
++ mfspr r11, SPRN_SPRG1
++ mfspr r10, SPRN_SPRG0
++ rfi /* Force context change */
++
++#ifdef CONFIG_SPE
++/* Note that the SPE support is closely modeled after the AltiVec
++ * support. Changes to one are likely to be applicable to the
++ * other! */
++load_up_spe:
++/*
++ * Disable SPE for the task which had SPE previously,
++ * and save its SPE registers in its thread_struct.
++ * Enables SPE for use in the kernel on return.
++ * On SMP we know the SPE units are free, since we give it up every
++ * switch. -- Kumar
++ */
++ mfmsr r5
++ oris r5,r5,MSR_SPE at h
++ mtmsr r5 /* enable use of SPE now */
++ isync
++/*
++ * For SMP, we don't do lazy SPE switching because it just gets too
++ * horrendously complex, especially when a task switches from one CPU
++ * to another. Instead we call giveup_spe in switch_to.
++ */
++#ifndef CONFIG_SMP
++ lis r3,last_task_used_spe at ha
++ lwz r4,last_task_used_spe at l(r3)
++ cmpi 0,r4,0
++ beq 1f
++ addi r4,r4,THREAD /* want THREAD of last_task_used_spe */
++ SAVE_32EVRS(0,r10,r4)
++ evxor evr10, evr10, evr10 /* clear out evr10 */
++ evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */
++ li r5,THREAD_ACC
++ evstddx evr10, r4, r5 /* save off accumulator */
++ lwz r5,PT_REGS(r4)
++ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ lis r10,MSR_SPE at h
++ andc r4,r4,r10 /* disable SPE for previous task */
++ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#endif /* CONFIG_SMP */
++ /* enable use of SPE after return */
++ oris r9,r9,MSR_SPE at h
++ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
++ li r4,1
++ li r10,THREAD_ACC
++ stw r4,THREAD_USED_SPE(r5)
++ evlddx evr4,r10,r5
++ evmra evr4,evr4
++ REST_32EVRS(0,r10,r5)
++#ifndef CONFIG_SMP
++ subi r4,r5,THREAD
++ stw r4,last_task_used_spe at l(r3)
++#endif /* CONFIG_SMP */
++ /* restore registers and return */
++2: REST_4GPRS(3, r11)
++ lwz r10,_CCR(r11)
++ REST_GPR(1, r11)
++ mtcr r10
++ lwz r10,_LINK(r11)
++ mtlr r10
++ REST_GPR(10, r11)
++ mtspr SPRN_SRR1,r9
++ mtspr SPRN_SRR0,r12
++ REST_GPR(9, r11)
++ REST_GPR(12, r11)
++ lwz r11,GPR11(r11)
++ SYNC
++ rfi
++
++/*
++ * SPE unavailable trap from kernel - print a message, but let
++ * the task use SPE in the kernel until it returns to user mode.
++ */
++KernelSPE:
++ lwz r3,_MSR(r1)
++ oris r3,r3,MSR_SPE at h
++ stw r3,_MSR(r1) /* enable use of SPE after return */
++ lis r3,87f at h
++ ori r3,r3,87f at l
++ mr r4,r2 /* current */
++ lwz r5,_NIP(r1)
++ bl printk
++ b ret_from_except
++87: .string "SPE used in kernel (task=%p, pc=%x) \n"
++ .align 4,0
++
++#endif /* CONFIG_SPE */
++
++/*
++ * Global functions
++ */
++
++/*
++ * extern void loadcam_entry(unsigned int index)
++ *
++ * Load TLBCAM[index] entry in to the L2 CAM MMU
++ */
++_GLOBAL(loadcam_entry)
++ lis r4,TLBCAM at ha
++ addi r4,r4,TLBCAM at l
++ mulli r5,r3,20
++ add r3,r5,r4
++ lwz r4,0(r3)
++ mtspr SPRN_MAS0,r4
++ lwz r4,4(r3)
++ mtspr SPRN_MAS1,r4
++ lwz r4,8(r3)
++ mtspr SPRN_MAS2,r4
++ lwz r4,12(r3)
++ mtspr SPRN_MAS3,r4
++ tlbwe
++ isync
++ blr
++
++/*
++ * extern void giveup_altivec(struct task_struct *prev)
++ *
++ * The e500 core does not have an AltiVec unit.
++ */
++_GLOBAL(giveup_altivec)
++ blr
++
++#ifdef CONFIG_SPE
++/*
++ * extern void giveup_spe(struct task_struct *prev)
++ *
++ */
++_GLOBAL(giveup_spe)
++ mfmsr r5
++ oris r5,r5,MSR_SPE at h
++ SYNC
++ mtmsr r5 /* enable use of SPE now */
++ isync
++ cmpi 0,r3,0
++ beqlr- /* if no previous owner, done */
++ addi r3,r3,THREAD /* want THREAD of task */
++ lwz r5,PT_REGS(r3)
++ cmpi 0,r5,0
++ SAVE_32EVRS(0, r4, r3)
++ evxor evr6, evr6, evr6 /* clear out evr6 */
++ evmwumiaa evr6, evr6, evr6 /* evr6 <- ACC = 0 * 0 + ACC */
++ li r4,THREAD_ACC
++ evstddx evr6, r4, r3 /* save off accumulator */
++ mfspr r6,SPRN_SPEFSCR
++ stw r6,THREAD_SPEFSCR(r3) /* save spefscr register value */
++ beq 1f
++ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ lis r3,MSR_SPE at h
++ andc r4,r4,r3 /* disable SPE for previous task */
++ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#ifndef CONFIG_SMP
++ li r5,0
++ lis r4,last_task_used_spe at ha
++ stw r5,last_task_used_spe at l(r4)
++#endif /* CONFIG_SMP */
++ blr
++#endif /* CONFIG_SPE */
++
++/*
++ * extern void giveup_fpu(struct task_struct *prev)
++ *
++ * Not all FSL Book-E cores have an FPU
++ */
++#ifndef CONFIG_PPC_FPU
++_GLOBAL(giveup_fpu)
++ blr
++#endif
++
++/*
++ * extern void abort(void)
++ *
++ * At present, this routine just applies a system reset.
++ */
++_GLOBAL(abort)
++ li r13,0
++ mtspr SPRN_DBCR0,r13 /* disable all debug events */
++ mfmsr r13
++ ori r13,r13,MSR_DE at l /* Enable Debug Events */
++ mtmsr r13
++ mfspr r13,SPRN_DBCR0
++ lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h
++ mtspr SPRN_DBCR0,r13
++
++_GLOBAL(set_context)
++
++#ifdef CONFIG_BDI_SWITCH
++ /* Context switch the PTE pointer for the Abatron BDI2000.
++ * The PGDIR is the second parameter.
++ */
++ lis r5, abatron_pteptrs at h
++ ori r5, r5, abatron_pteptrs at l
++ stw r4, 0x4(r5)
++#endif
++ mtspr SPRN_PID,r3
++ isync /* Force context change */
++ blr
++
++/*
++ * We put a few things here that have to be page-aligned. This stuff
++ * goes at the beginning of the data segment, which is page-aligned.
++ */
++ .data
++ .align 12
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
++ .space 4096
++ .globl swapper_pg_dir
++swapper_pg_dir:
++ .space 4096
++
++/* Reserved 4k for the critical exception stack & 4k for the machine
++ * check stack per CPU for kernel mode exceptions */
++ .section .bss
++ .align 12
++exception_stack_bottom:
++ .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
++ .globl exception_stack_top
++exception_stack_top:
++
++/*
++ * This space gets a copy of optional info passed to us by the bootstrap
++ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
++ */
++ .globl cmd_line
++cmd_line:
++ .space 512
++
++/*
++ * Room for two PTE pointers, usually the kernel and current user pointers
++ * to their respective root page table.
++ */
++abatron_pteptrs:
++ .space 8
+diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/idle_6xx.S
+@@ -0,0 +1,233 @@
++/*
++ * This file contains the power_save function for 6xx & 7xxx CPUs
++ * rewritten in assembler
++ *
++ * Warning ! This code assumes that if your machine has a 750fx
++ * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
++ * if this is not the case some additional changes will have to
++ * be done to check a runtime var (a bit like powersave-nap)
++ *
++ * 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/threads.h>
++#include <asm/reg.h>
++#include <asm/page.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++
++#undef DEBUG
++
++ .text
++
++/*
++ * Init idle, called at early CPU setup time from head.S for each CPU
++ * Make sure no rest of NAP mode remains in HID0, save default
++ * values for some CPU specific registers. Called with r24
++ * containing CPU number and r3 reloc offset
++ */
++_GLOBAL(init_idle_6xx)
++BEGIN_FTR_SECTION
++ mfspr r4,SPRN_HID0
++ rlwinm r4,r4,0,10,8 /* Clear NAP */
++ mtspr SPRN_HID0, r4
++ b 1f
++END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
++ blr
++1:
++ slwi r5,r24,2
++ add r5,r5,r3
++BEGIN_FTR_SECTION
++ mfspr r4,SPRN_MSSCR0
++ addis r6,r5, nap_save_msscr0 at ha
++ stw r4,nap_save_msscr0 at l(r6)
++END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
++BEGIN_FTR_SECTION
++ mfspr r4,SPRN_HID1
++ addis r6,r5,nap_save_hid1 at ha
++ stw r4,nap_save_hid1 at l(r6)
++END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
++ blr
++
++/*
++ * Here is the power_save_6xx function. This could eventually be
++ * split into several functions & changing the function pointer
++ * depending on the various features.
++ */
++_GLOBAL(ppc6xx_idle)
++ /* Check if we can nap or doze, put HID0 mask in r3
++ */
++ lis r3, 0
++BEGIN_FTR_SECTION
++ lis r3,HID0_DOZE at h
++END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
++BEGIN_FTR_SECTION
++ /* We must dynamically check for the NAP feature as it
++ * can be cleared by CPU init after the fixups are done
++ */
++ lis r4,cur_cpu_spec at ha
++ lwz r4,cur_cpu_spec at l(r4)
++ lwz r4,CPU_SPEC_FEATURES(r4)
++ andi. r0,r4,CPU_FTR_CAN_NAP
++ beq 1f
++ /* Now check if user or arch enabled NAP mode */
++ lis r4,powersave_nap at ha
++ lwz r4,powersave_nap at l(r4)
++ cmpwi 0,r4,0
++ beq 1f
++ lis r3,HID0_NAP at h
++1:
++END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
++ cmpwi 0,r3,0
++ beqlr
++
++ /* Clear MSR:EE */
++ mfmsr r7
++ rlwinm r0,r7,0,17,15
++ mtmsr r0
++
++ /* Check current_thread_info()->flags */
++ rlwinm r4,r1,0,0,18
++ lwz r4,TI_FLAGS(r4)
++ andi. r0,r4,_TIF_NEED_RESCHED
++ beq 1f
++ mtmsr r7 /* out of line this ? */
++ blr
++1:
++ /* Some pre-nap cleanups needed on some CPUs */
++ andis. r0,r3,HID0_NAP at h
++ beq 2f
++BEGIN_FTR_SECTION
++ /* Disable L2 prefetch on some 745x and try to ensure
++ * L2 prefetch engines are idle. As explained by errata
++ * text, we can't be sure they are, we just hope very hard
++ * that well be enough (sic !). At least I noticed Apple
++ * doesn't even bother doing the dcbf's here...
++ */
++ mfspr r4,SPRN_MSSCR0
++ rlwinm r4,r4,0,0,29
++ sync
++ mtspr SPRN_MSSCR0,r4
++ sync
++ isync
++ lis r4,KERNELBASE at h
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
++#ifdef DEBUG
++ lis r6,nap_enter_count at ha
++ lwz r4,nap_enter_count at l(r6)
++ addi r4,r4,1
++ stw r4,nap_enter_count at l(r6)
++#endif
++2:
++BEGIN_FTR_SECTION
++ /* Go to low speed mode on some 750FX */
++ lis r4,powersave_lowspeed at ha
++ lwz r4,powersave_lowspeed at l(r4)
++ cmpwi 0,r4,0
++ beq 1f
++ mfspr r4,SPRN_HID1
++ oris r4,r4,0x0001
++ mtspr SPRN_HID1,r4
++1:
++END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
++
++ /* Go to NAP or DOZE now */
++ mfspr r4,SPRN_HID0
++ lis r5,(HID0_NAP|HID0_SLEEP)@h
++BEGIN_FTR_SECTION
++ oris r5,r5,HID0_DOZE at h
++END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
++ andc r4,r4,r5
++ or r4,r4,r3
++BEGIN_FTR_SECTION
++ oris r4,r4,HID0_DPM at h /* that should be done once for all */
++END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
++ mtspr SPRN_HID0,r4
++BEGIN_FTR_SECTION
++ DSSALL
++ sync
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++ ori r7,r7,MSR_EE /* Could be ommited (already set) */
++ oris r7,r7,MSR_POW at h
++ sync
++ isync
++ mtmsr r7
++ isync
++ sync
++ blr
++
++/*
++ * Return from NAP/DOZE mode, restore some CPU specific registers,
++ * we are called with DR/IR still off and r2 containing physical
++ * address of current.
++ */
++_GLOBAL(power_save_6xx_restore)
++ mfspr r11,SPRN_HID0
++ rlwinm. r11,r11,0,10,8 /* Clear NAP & copy NAP bit !state to cr1 EQ */
++ cror 4*cr1+eq,4*cr0+eq,4*cr0+eq
++BEGIN_FTR_SECTION
++ rlwinm r11,r11,0,9,7 /* Clear DOZE */
++END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
++ mtspr SPRN_HID0, r11
++
++#ifdef DEBUG
++ beq cr1,1f
++ lis r11,(nap_return_count-KERNELBASE)@ha
++ lwz r9,nap_return_count at l(r11)
++ addi r9,r9,1
++ stw r9,nap_return_count at l(r11)
++1:
++#endif
++
++ rlwinm r9,r1,0,0,18
++ tophys(r9,r9)
++ lwz r11,TI_CPU(r9)
++ slwi r11,r11,2
++ /* Todo make sure all these are in the same page
++ * and load r22 (@ha part + CPU offset) only once
++ */
++BEGIN_FTR_SECTION
++ beq cr1,1f
++ addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
++ lwz r9,nap_save_msscr0 at l(r9)
++ mtspr SPRN_MSSCR0, r9
++ sync
++ isync
++1:
++END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
++BEGIN_FTR_SECTION
++ addis r9,r11,(nap_save_hid1-KERNELBASE)@ha
++ lwz r9,nap_save_hid1 at l(r9)
++ mtspr SPRN_HID1, r9
++END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
++ b transfer_to_handler_cont
++
++ .data
++
++_GLOBAL(nap_save_msscr0)
++ .space 4*NR_CPUS
++
++_GLOBAL(nap_save_hid1)
++ .space 4*NR_CPUS
++
++_GLOBAL(powersave_nap)
++ .long 0
++_GLOBAL(powersave_lowspeed)
++ .long 0
++
++#ifdef DEBUG
++_GLOBAL(nap_enter_count)
++ .space 4
++_GLOBAL(nap_return_count)
++ .space 4
++#endif
+diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/idle_power4.S
+@@ -0,0 +1,78 @@
++/*
++ * This file contains the power_save function for 6xx & 7xxx CPUs
++ * rewritten in assembler
++ *
++ * Warning ! This code assumes that if your machine has a 750fx
++ * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
++ * if this is not the case some additional changes will have to
++ * be done to check a runtime var (a bit like powersave-nap)
++ *
++ * 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/threads.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++
++#undef DEBUG
++
++ .text
++
++/*
++ * Here is the power_save_6xx function. This could eventually be
++ * split into several functions & changing the function pointer
++ * depending on the various features.
++ */
++_GLOBAL(power4_idle)
++BEGIN_FTR_SECTION
++ blr
++END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
++ /* We must dynamically check for the NAP feature as it
++ * can be cleared by CPU init after the fixups are done
++ */
++ LOADBASE(r3,cur_cpu_spec)
++ ld r4,OFF(cur_cpu_spec)(r3)
++ ld r4,CPU_SPEC_FEATURES(r4)
++ andi. r0,r4,CPU_FTR_CAN_NAP
++ beqlr
++ /* Now check if user or arch enabled NAP mode */
++ LOADBASE(r3,powersave_nap)
++ lwz r4,OFF(powersave_nap)(r3)
++ cmpwi 0,r4,0
++ beqlr
++
++ /* Clear MSR:EE */
++ mfmsr r7
++ li r4,0
++ ori r4,r4,MSR_EE
++ andc r0,r7,r4
++ mtmsrd r0
++
++ /* Check current_thread_info()->flags */
++ clrrdi r4,r1,THREAD_SHIFT
++ ld r4,TI_FLAGS(r4)
++ andi. r0,r4,_TIF_NEED_RESCHED
++ beq 1f
++ mtmsrd r7 /* out of line this ? */
++ blr
++1:
++ /* Go to NAP now */
++BEGIN_FTR_SECTION
++ DSSALL
++ sync
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++ oris r7,r7,MSR_POW at h
++ sync
++ isync
++ mtmsrd r7
++ isync
++ sync
++ blr
+diff --git a/arch/powerpc/kernel/init_task.c b/arch/powerpc/kernel/init_task.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/init_task.c
+@@ -0,0 +1,36 @@
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/init_task.h>
++#include <linux/fs.h>
++#include <linux/mqueue.h>
++#include <asm/uaccess.h>
++
++static struct fs_struct init_fs = INIT_FS;
++static struct files_struct init_files = INIT_FILES;
++static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
++static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
++struct mm_struct init_mm = INIT_MM(init_mm);
++
++EXPORT_SYMBOL(init_mm);
++
++/*
++ * Initial thread structure.
++ *
++ * We need to make sure that this is 16384-byte aligned due to the
++ * way process stacks are handled. This is done by having a special
++ * "init_task" linker map entry..
++ */
++union thread_union init_thread_union
++ __attribute__((__section__(".data.init_task"))) =
++ { INIT_THREAD_INFO(init_task) };
++
++/*
++ * Initial task structure.
++ *
++ * All other task structs will be allocated on slabs in fork.c
++ */
++struct task_struct init_task = INIT_TASK(init_task);
++
++EXPORT_SYMBOL(init_task);
+diff --git a/arch/powerpc/kernel/lparmap.c b/arch/powerpc/kernel/lparmap.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/lparmap.c
+@@ -0,0 +1,31 @@
++/*
++ * Copyright (C) 2005 Stephen Rothwell IBM Corp.
++ *
++ * 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 <asm/mmu.h>
++#include <asm/page.h>
++#include <asm/iSeries/LparMap.h>
++
++const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
++ .xNumberEsids = HvEsidsToMap,
++ .xNumberRanges = HvRangesToMap,
++ .xSegmentTableOffs = STAB0_PAGE,
++
++ .xEsids = {
++ { .xKernelEsid = GET_ESID(KERNELBASE),
++ .xKernelVsid = KERNEL_VSID(KERNELBASE), },
++ { .xKernelEsid = GET_ESID(VMALLOCBASE),
++ .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
++ },
++
++ .xRanges = {
++ { .xPages = HvPagesToMap,
++ .xOffset = 0,
++ .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
++ },
++ },
++};
+diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/misc_32.S
+@@ -0,0 +1,1037 @@
++/*
++ * This file contains miscellaneous low-level functions.
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Largely rewritten by Cort Dougan (cort at cs.nmt.edu)
++ * and Paul Mackerras.
++ *
++ * 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/sys.h>
++#include <asm/unistd.h>
++#include <asm/errno.h>
++#include <asm/reg.h>
++#include <asm/page.h>
++#include <asm/cache.h>
++#include <asm/cputable.h>
++#include <asm/mmu.h>
++#include <asm/ppc_asm.h>
++#include <asm/thread_info.h>
++#include <asm/asm-offsets.h>
++
++ .text
++
++ .align 5
++_GLOBAL(__delay)
++ cmpwi 0,r3,0
++ mtctr r3
++ beqlr
++1: bdnz 1b
++ blr
++
++/*
++ * This returns the high 64 bits of the product of two 64-bit numbers.
++ */
++_GLOBAL(mulhdu)
++ cmpwi r6,0
++ cmpwi cr1,r3,0
++ mr r10,r4
++ mulhwu r4,r4,r5
++ beq 1f
++ mulhwu r0,r10,r6
++ mullw r7,r10,r5
++ addc r7,r0,r7
++ addze r4,r4
++1: beqlr cr1 /* all done if high part of A is 0 */
++ mr r10,r3
++ mullw r9,r3,r5
++ mulhwu r3,r3,r5
++ beq 2f
++ mullw r0,r10,r6
++ mulhwu r8,r10,r6
++ addc r7,r0,r7
++ adde r4,r4,r8
++ addze r3,r3
++2: addc r4,r4,r9
++ addze r3,r3
++ blr
++
++/*
++ * Returns (address we're running at) - (address we were linked at)
++ * for use before the text and data are mapped to KERNELBASE.
++ */
++_GLOBAL(reloc_offset)
++ mflr r0
++ bl 1f
++1: mflr r3
++ LOADADDR(r4,1b)
++ subf r3,r4,r3
++ mtlr r0
++ blr
++
++/*
++ * add_reloc_offset(x) returns x + reloc_offset().
++ */
++_GLOBAL(add_reloc_offset)
++ mflr r0
++ bl 1f
++1: mflr r5
++ LOADADDR(r4,1b)
++ subf r5,r4,r5
++ add r3,r3,r5
++ mtlr r0
++ blr
++
++/*
++ * sub_reloc_offset(x) returns x - reloc_offset().
++ */
++_GLOBAL(sub_reloc_offset)
++ mflr r0
++ bl 1f
++1: mflr r5
++ lis r4,1b at ha
++ addi r4,r4,1b at l
++ subf r5,r4,r5
++ subf r3,r5,r3
++ mtlr r0
++ blr
++
++/*
++ * reloc_got2 runs through the .got2 section adding an offset
++ * to each entry.
++ */
++_GLOBAL(reloc_got2)
++ mflr r11
++ lis r7,__got2_start at ha
++ addi r7,r7,__got2_start at l
++ lis r8,__got2_end at ha
++ addi r8,r8,__got2_end at l
++ subf r8,r7,r8
++ srwi. r8,r8,2
++ beqlr
++ mtctr r8
++ bl 1f
++1: mflr r0
++ lis r4,1b at ha
++ addi r4,r4,1b at l
++ subf r0,r4,r0
++ add r7,r0,r7
++2: lwz r0,0(r7)
++ add r0,r0,r3
++ stw r0,0(r7)
++ addi r7,r7,4
++ bdnz 2b
++ mtlr r11
++ blr
++
++/*
++ * identify_cpu,
++ * called with r3 = data offset and r4 = CPU number
++ * doesn't change r3
++ */
++_GLOBAL(identify_cpu)
++ addis r8,r3,cpu_specs at ha
++ addi r8,r8,cpu_specs at l
++ mfpvr r7
++1:
++ lwz r5,CPU_SPEC_PVR_MASK(r8)
++ and r5,r5,r7
++ lwz r6,CPU_SPEC_PVR_VALUE(r8)
++ cmplw 0,r6,r5
++ beq 1f
++ addi r8,r8,CPU_SPEC_ENTRY_SIZE
++ b 1b
++1:
++ addis r6,r3,cur_cpu_spec at ha
++ addi r6,r6,cur_cpu_spec at l
++ sub r8,r8,r3
++ stw r8,0(r6)
++ blr
++
++/*
++ * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
++ * and writes nop's over sections of code that don't apply for this cpu.
++ * r3 = data offset (not changed)
++ */
++_GLOBAL(do_cpu_ftr_fixups)
++ /* Get CPU 0 features */
++ addis r6,r3,cur_cpu_spec at ha
++ addi r6,r6,cur_cpu_spec at l
++ lwz r4,0(r6)
++ add r4,r4,r3
++ lwz r4,CPU_SPEC_FEATURES(r4)
++
++ /* Get the fixup table */
++ addis r6,r3,__start___ftr_fixup at ha
++ addi r6,r6,__start___ftr_fixup at l
++ addis r7,r3,__stop___ftr_fixup at ha
++ addi r7,r7,__stop___ftr_fixup at l
++
++ /* Do the fixup */
++1: cmplw 0,r6,r7
++ bgelr
++ addi r6,r6,16
++ lwz r8,-16(r6) /* mask */
++ and r8,r8,r4
++ lwz r9,-12(r6) /* value */
++ cmplw 0,r8,r9
++ beq 1b
++ lwz r8,-8(r6) /* section begin */
++ lwz r9,-4(r6) /* section end */
++ subf. r9,r8,r9
++ beq 1b
++ /* write nops over the section of code */
++ /* todo: if large section, add a branch at the start of it */
++ srwi r9,r9,2
++ mtctr r9
++ add r8,r8,r3
++ lis r0,0x60000000 at h /* nop */
++3: stw r0,0(r8)
++ andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE at l
++ beq 2f
++ dcbst 0,r8 /* suboptimal, but simpler */
++ sync
++ icbi 0,r8
++2: addi r8,r8,4
++ bdnz 3b
++ sync /* additional sync needed on g4 */
++ isync
++ b 1b
++
++/*
++ * call_setup_cpu - call the setup_cpu function for this cpu
++ * r3 = data offset, r24 = cpu number
++ *
++ * Setup function is called with:
++ * r3 = data offset
++ * r4 = ptr to CPU spec (relocated)
++ */
++_GLOBAL(call_setup_cpu)
++ addis r4,r3,cur_cpu_spec at ha
++ addi r4,r4,cur_cpu_spec at l
++ lwz r4,0(r4)
++ add r4,r4,r3
++ lwz r5,CPU_SPEC_SETUP(r4)
++ cmpi 0,r5,0
++ add r5,r5,r3
++ beqlr
++ mtctr r5
++ bctr
++
++#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)
++
++/* This gets called by via-pmu.c to switch the PLL selection
++ * on 750fx CPU. This function should really be moved to some
++ * other place (as most of the cpufreq code in via-pmu
++ */
++_GLOBAL(low_choose_750fx_pll)
++ /* Clear MSR:EE */
++ mfmsr r7
++ rlwinm r0,r7,0,17,15
++ mtmsr r0
++
++ /* If switching to PLL1, disable HID0:BTIC */
++ cmplwi cr0,r3,0
++ beq 1f
++ mfspr r5,SPRN_HID0
++ rlwinm r5,r5,0,27,25
++ sync
++ mtspr SPRN_HID0,r5
++ isync
++ sync
++
++1:
++ /* Calc new HID1 value */
++ mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */
++ rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */
++ rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */
++ or r4,r4,r5
++ mtspr SPRN_HID1,r4
++
++ /* Store new HID1 image */
++ rlwinm r6,r1,0,0,18
++ lwz r6,TI_CPU(r6)
++ slwi r6,r6,2
++ addis r6,r6,nap_save_hid1 at ha
++ stw r4,nap_save_hid1 at l(r6)
++
++ /* If switching to PLL0, enable HID0:BTIC */
++ cmplwi cr0,r3,0
++ bne 1f
++ mfspr r5,SPRN_HID0
++ ori r5,r5,HID0_BTIC
++ sync
++ mtspr SPRN_HID0,r5
++ isync
++ sync
++
++1:
++ /* Return */
++ mtmsr r7
++ blr
++
++_GLOBAL(low_choose_7447a_dfs)
++ /* Clear MSR:EE */
++ mfmsr r7
++ rlwinm r0,r7,0,17,15
++ mtmsr r0
++
++ /* Calc new HID1 value */
++ mfspr r4,SPRN_HID1
++ insrwi r4,r3,1,9 /* insert parameter into bit 9 */
++ sync
++ mtspr SPRN_HID1,r4
++ sync
++ isync
++
++ /* Return */
++ mtmsr r7
++ blr
++
++#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
++
++/*
++ * complement mask on the msr then "or" some values on.
++ * _nmask_and_or_msr(nmask, value_to_or)
++ */
++_GLOBAL(_nmask_and_or_msr)
++ mfmsr r0 /* Get current msr */
++ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
++ or r0,r0,r4 /* Or on the bits in r4 (second parm) */
++ SYNC /* Some chip revs have problems here... */
++ mtmsr r0 /* Update machine state */
++ isync
++ blr /* Done */
++
++
++/*
++ * Flush MMU TLB
++ */
++_GLOBAL(_tlbia)
++#if defined(CONFIG_40x)
++ sync /* Flush to memory before changing mapping */
++ tlbia
++ isync /* Flush shadow TLB */
++#elif defined(CONFIG_44x)
++ li r3,0
++ sync
++
++ /* Load high watermark */
++ lis r4,tlb_44x_hwater at ha
++ lwz r5,tlb_44x_hwater at l(r4)
++
++1: tlbwe r3,r3,PPC44x_TLB_PAGEID
++ addi r3,r3,1
++ cmpw 0,r3,r5
++ ble 1b
++
++ isync
++#elif defined(CONFIG_FSL_BOOKE)
++ /* Invalidate all entries in TLB0 */
++ li r3, 0x04
++ tlbivax 0,3
++ /* Invalidate all entries in TLB1 */
++ li r3, 0x0c
++ tlbivax 0,3
++ /* Invalidate all entries in TLB2 */
++ li r3, 0x14
++ tlbivax 0,3
++ /* Invalidate all entries in TLB3 */
++ li r3, 0x1c
++ tlbivax 0,3
++ msync
++#ifdef CONFIG_SMP
++ tlbsync
++#endif /* CONFIG_SMP */
++#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
++#if defined(CONFIG_SMP)
++ rlwinm r8,r1,0,0,18
++ lwz r8,TI_CPU(r8)
++ oris r8,r8,10
++ mfmsr r10
++ SYNC
++ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
++ rlwinm r0,r0,0,28,26 /* clear DR */
++ mtmsr r0
++ SYNC_601
++ isync
++ lis r9,mmu_hash_lock at h
++ ori r9,r9,mmu_hash_lock at l
++ tophys(r9,r9)
++10: lwarx r7,0,r9
++ cmpwi 0,r7,0
++ bne- 10b
++ stwcx. r8,0,r9
++ bne- 10b
++ sync
++ tlbia
++ sync
++ TLBSYNC
++ li r0,0
++ stw r0,0(r9) /* clear mmu_hash_lock */
++ mtmsr r10
++ SYNC_601
++ isync
++#else /* CONFIG_SMP */
++ sync
++ tlbia
++ sync
++#endif /* CONFIG_SMP */
++#endif /* ! defined(CONFIG_40x) */
++ blr
++
++/*
++ * Flush MMU TLB for a particular address
++ */
++_GLOBAL(_tlbie)
++#if defined(CONFIG_40x)
++ tlbsx. r3, 0, r3
++ bne 10f
++ sync
++ /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.
++ * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate
++ * the TLB entry. */
++ tlbwe r3, r3, TLB_TAG
++ isync
++10:
++#elif defined(CONFIG_44x)
++ mfspr r4,SPRN_MMUCR
++ mfspr r5,SPRN_PID /* Get PID */
++ rlwimi r4,r5,0,24,31 /* Set TID */
++ mtspr SPRN_MMUCR,r4
++
++ tlbsx. r3, 0, r3
++ bne 10f
++ sync
++ /* There are only 64 TLB entries, so r3 < 64,
++ * which means bit 22, is clear. Since 22 is
++ * the V bit in the TLB_PAGEID, loading this
++ * value will invalidate the TLB entry.
++ */
++ tlbwe r3, r3, PPC44x_TLB_PAGEID
++ isync
++10:
++#elif defined(CONFIG_FSL_BOOKE)
++ rlwinm r4, r3, 0, 0, 19
++ ori r5, r4, 0x08 /* TLBSEL = 1 */
++ ori r6, r4, 0x10 /* TLBSEL = 2 */
++ ori r7, r4, 0x18 /* TLBSEL = 3 */
++ tlbivax 0, r4
++ tlbivax 0, r5
++ tlbivax 0, r6
++ tlbivax 0, r7
++ msync
++#if defined(CONFIG_SMP)
++ tlbsync
++#endif /* CONFIG_SMP */
++#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
++#if defined(CONFIG_SMP)
++ rlwinm r8,r1,0,0,18
++ lwz r8,TI_CPU(r8)
++ oris r8,r8,11
++ mfmsr r10
++ SYNC
++ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
++ rlwinm r0,r0,0,28,26 /* clear DR */
++ mtmsr r0
++ SYNC_601
++ isync
++ lis r9,mmu_hash_lock at h
++ ori r9,r9,mmu_hash_lock at l
++ tophys(r9,r9)
++10: lwarx r7,0,r9
++ cmpwi 0,r7,0
++ bne- 10b
++ stwcx. r8,0,r9
++ bne- 10b
++ eieio
++ tlbie r3
++ sync
++ TLBSYNC
++ li r0,0
++ stw r0,0(r9) /* clear mmu_hash_lock */
++ mtmsr r10
++ SYNC_601
++ isync
++#else /* CONFIG_SMP */
++ tlbie r3
++ sync
++#endif /* CONFIG_SMP */
++#endif /* ! CONFIG_40x */
++ blr
++
++/*
++ * Flush instruction cache.
++ * This is a no-op on the 601.
++ */
++_GLOBAL(flush_instruction_cache)
++#if defined(CONFIG_8xx)
++ isync
++ lis r5, IDC_INVALL at h
++ mtspr SPRN_IC_CST, r5
++#elif defined(CONFIG_4xx)
++#ifdef CONFIG_403GCX
++ li r3, 512
++ mtctr r3
++ lis r4, KERNELBASE at h
++1: iccci 0, r4
++ addi r4, r4, 16
++ bdnz 1b
++#else
++ lis r3, KERNELBASE at h
++ iccci 0,r3
++#endif
++#elif CONFIG_FSL_BOOKE
++BEGIN_FTR_SECTION
++ mfspr r3,SPRN_L1CSR0
++ ori r3,r3,L1CSR0_CFI|L1CSR0_CLFC
++ /* msync; isync recommended here */
++ mtspr SPRN_L1CSR0,r3
++ isync
++ blr
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
++ mfspr r3,SPRN_L1CSR1
++ ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
++ mtspr SPRN_L1CSR1,r3
++#else
++ mfspr r3,SPRN_PVR
++ rlwinm r3,r3,16,16,31
++ cmpwi 0,r3,1
++ beqlr /* for 601, do nothing */
++ /* 603/604 processor - use invalidate-all bit in HID0 */
++ mfspr r3,SPRN_HID0
++ ori r3,r3,HID0_ICFI
++ mtspr SPRN_HID0,r3
++#endif /* CONFIG_8xx/4xx */
++ isync
++ blr
++
++/*
++ * Write any modified data cache blocks out to memory
++ * and invalidate the corresponding instruction cache blocks.
++ * This is a no-op on the 601.
++ *
++ * flush_icache_range(unsigned long start, unsigned long stop)
++ */
++_GLOBAL(flush_icache_range)
++BEGIN_FTR_SECTION
++ blr /* for 601, do nothing */
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
++ li r5,L1_CACHE_BYTES-1
++ andc r3,r3,r5
++ subf r4,r3,r4
++ add r4,r4,r5
++ srwi. r4,r4,L1_CACHE_SHIFT
++ beqlr
++ mtctr r4
++ mr r6,r3
++1: dcbst 0,r3
++ addi r3,r3,L1_CACHE_BYTES
++ bdnz 1b
++ sync /* wait for dcbst's to get to ram */
++ mtctr r4
++2: icbi 0,r6
++ addi r6,r6,L1_CACHE_BYTES
++ bdnz 2b
++ sync /* additional sync needed on g4 */
++ isync
++ blr
++/*
++ * Write any modified data cache blocks out to memory.
++ * Does not invalidate the corresponding cache lines (especially for
++ * any corresponding instruction cache).
++ *
++ * clean_dcache_range(unsigned long start, unsigned long stop)
++ */
++_GLOBAL(clean_dcache_range)
++ li r5,L1_CACHE_BYTES-1
++ andc r3,r3,r5
++ subf r4,r3,r4
++ add r4,r4,r5
++ srwi. r4,r4,L1_CACHE_SHIFT
++ beqlr
++ mtctr r4
++
++1: dcbst 0,r3
++ addi r3,r3,L1_CACHE_BYTES
++ bdnz 1b
++ sync /* wait for dcbst's to get to ram */
++ blr
++
++/*
++ * Write any modified data cache blocks out to memory and invalidate them.
++ * Does not invalidate the corresponding instruction cache blocks.
++ *
++ * flush_dcache_range(unsigned long start, unsigned long stop)
++ */
++_GLOBAL(flush_dcache_range)
++ li r5,L1_CACHE_BYTES-1
++ andc r3,r3,r5
++ subf r4,r3,r4
++ add r4,r4,r5
++ srwi. r4,r4,L1_CACHE_SHIFT
++ beqlr
++ mtctr r4
++
++1: dcbf 0,r3
++ addi r3,r3,L1_CACHE_BYTES
++ bdnz 1b
++ sync /* wait for dcbst's to get to ram */
++ blr
++
++/*
++ * Like above, but invalidate the D-cache. This is used by the 8xx
++ * to invalidate the cache so the PPC core doesn't get stale data
++ * from the CPM (no cache snooping here :-).
++ *
++ * invalidate_dcache_range(unsigned long start, unsigned long stop)
++ */
++_GLOBAL(invalidate_dcache_range)
++ li r5,L1_CACHE_BYTES-1
++ andc r3,r3,r5
++ subf r4,r3,r4
++ add r4,r4,r5
++ srwi. r4,r4,L1_CACHE_SHIFT
++ beqlr
++ mtctr r4
++
++1: dcbi 0,r3
++ addi r3,r3,L1_CACHE_BYTES
++ bdnz 1b
++ sync /* wait for dcbi's to get to ram */
++ blr
++
++#ifdef CONFIG_NOT_COHERENT_CACHE
++/*
++ * 40x cores have 8K or 16K dcache and 32 byte line size.
++ * 44x has a 32K dcache and 32 byte line size.
++ * 8xx has 1, 2, 4, 8K variants.
++ * For now, cover the worst case of the 44x.
++ * Must be called with external interrupts disabled.
++ */
++#define CACHE_NWAYS 64
++#define CACHE_NLINES 16
++
++_GLOBAL(flush_dcache_all)
++ li r4, (2 * CACHE_NWAYS * CACHE_NLINES)
++ mtctr r4
++ lis r5, KERNELBASE at h
++1: lwz r3, 0(r5) /* Load one word from every line */
++ addi r5, r5, L1_CACHE_BYTES
++ bdnz 1b
++ blr
++#endif /* CONFIG_NOT_COHERENT_CACHE */
++
++/*
++ * Flush a particular page from the data cache to RAM.
++ * Note: this is necessary because the instruction cache does *not*
++ * snoop from the data cache.
++ * This is a no-op on the 601 which has a unified cache.
++ *
++ * void __flush_dcache_icache(void *page)
++ */
++_GLOBAL(__flush_dcache_icache)
++BEGIN_FTR_SECTION
++ blr /* for 601, do nothing */
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
++ rlwinm r3,r3,0,0,19 /* Get page base address */
++ li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
++ mtctr r4
++ mr r6,r3
++0: dcbst 0,r3 /* Write line to ram */
++ addi r3,r3,L1_CACHE_BYTES
++ bdnz 0b
++ sync
++ mtctr r4
++1: icbi 0,r6
++ addi r6,r6,L1_CACHE_BYTES
++ bdnz 1b
++ sync
++ isync
++ blr
++
++/*
++ * Flush a particular page from the data cache to RAM, identified
++ * by its physical address. We turn off the MMU so we can just use
++ * the physical address (this may be a highmem page without a kernel
++ * mapping).
++ *
++ * void __flush_dcache_icache_phys(unsigned long physaddr)
++ */
++_GLOBAL(__flush_dcache_icache_phys)
++BEGIN_FTR_SECTION
++ blr /* for 601, do nothing */
++END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
++ mfmsr r10
++ rlwinm r0,r10,0,28,26 /* clear DR */
++ mtmsr r0
++ isync
++ rlwinm r3,r3,0,0,19 /* Get page base address */
++ li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
++ mtctr r4
++ mr r6,r3
++0: dcbst 0,r3 /* Write line to ram */
++ addi r3,r3,L1_CACHE_BYTES
++ bdnz 0b
++ sync
++ mtctr r4
++1: icbi 0,r6
++ addi r6,r6,L1_CACHE_BYTES
++ bdnz 1b
++ sync
++ mtmsr r10 /* restore DR */
++ isync
++ blr
++
++/*
++ * Clear pages using the dcbz instruction, which doesn't cause any
++ * memory traffic (except to write out any cache lines which get
++ * displaced). This only works on cacheable memory.
++ *
++ * void clear_pages(void *page, int order) ;
++ */
++_GLOBAL(clear_pages)
++ li r0,4096/L1_CACHE_BYTES
++ slw r0,r0,r4
++ mtctr r0
++#ifdef CONFIG_8xx
++ li r4, 0
++1: stw r4, 0(r3)
++ stw r4, 4(r3)
++ stw r4, 8(r3)
++ stw r4, 12(r3)
++#else
++1: dcbz 0,r3
++#endif
++ addi r3,r3,L1_CACHE_BYTES
++ bdnz 1b
++ blr
++
++/*
++ * Copy a whole page. We use the dcbz instruction on the destination
++ * to reduce memory traffic (it eliminates the unnecessary reads of
++ * the destination into cache). This requires that the destination
++ * is cacheable.
++ */
++#define COPY_16_BYTES \
++ lwz r6,4(r4); \
++ lwz r7,8(r4); \
++ lwz r8,12(r4); \
++ lwzu r9,16(r4); \
++ stw r6,4(r3); \
++ stw r7,8(r3); \
++ stw r8,12(r3); \
++ stwu r9,16(r3)
++
++_GLOBAL(copy_page)
++ addi r3,r3,-4
++ addi r4,r4,-4
++
++#ifdef CONFIG_8xx
++ /* don't use prefetch on 8xx */
++ li r0,4096/L1_CACHE_BYTES
++ mtctr r0
++1: COPY_16_BYTES
++ bdnz 1b
++ blr
++
++#else /* not 8xx, we can prefetch */
++ li r5,4
++
++#if MAX_COPY_PREFETCH > 1
++ li r0,MAX_COPY_PREFETCH
++ li r11,4
++ mtctr r0
++11: dcbt r11,r4
++ addi r11,r11,L1_CACHE_BYTES
++ bdnz 11b
++#else /* MAX_COPY_PREFETCH == 1 */
++ dcbt r5,r4
++ li r11,L1_CACHE_BYTES+4
++#endif /* MAX_COPY_PREFETCH */
++ li r0,4096/L1_CACHE_BYTES - MAX_COPY_PREFETCH
++ crclr 4*cr0+eq
++2:
++ mtctr r0
++1:
++ dcbt r11,r4
++ dcbz r5,r3
++ COPY_16_BYTES
++#if L1_CACHE_BYTES >= 32
++ COPY_16_BYTES
++#if L1_CACHE_BYTES >= 64
++ COPY_16_BYTES
++ COPY_16_BYTES
++#if L1_CACHE_BYTES >= 128
++ COPY_16_BYTES
++ COPY_16_BYTES
++ COPY_16_BYTES
++ COPY_16_BYTES
++#endif
++#endif
++#endif
++ bdnz 1b
++ beqlr
++ crnot 4*cr0+eq,4*cr0+eq
++ li r0,MAX_COPY_PREFETCH
++ li r11,4
++ b 2b
++#endif /* CONFIG_8xx */
++
++/*
++ * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
++ * void atomic_set_mask(atomic_t mask, atomic_t *addr);
++ */
++_GLOBAL(atomic_clear_mask)
++10: lwarx r5,0,r4
++ andc r5,r5,r3
++ PPC405_ERR77(0,r4)
++ stwcx. r5,0,r4
++ bne- 10b
++ blr
++_GLOBAL(atomic_set_mask)
++10: lwarx r5,0,r4
++ or r5,r5,r3
++ PPC405_ERR77(0,r4)
++ stwcx. r5,0,r4
++ bne- 10b
++ blr
++
++/*
++ * I/O string operations
++ *
++ * insb(port, buf, len)
++ * outsb(port, buf, len)
++ * insw(port, buf, len)
++ * outsw(port, buf, len)
++ * insl(port, buf, len)
++ * outsl(port, buf, len)
++ * insw_ns(port, buf, len)
++ * outsw_ns(port, buf, len)
++ * insl_ns(port, buf, len)
++ * outsl_ns(port, buf, len)
++ *
++ * The *_ns versions don't do byte-swapping.
++ */
++_GLOBAL(_insb)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,1
++ blelr-
++00: lbz r5,0(r3)
++ eieio
++ stbu r5,1(r4)
++ bdnz 00b
++ blr
++
++_GLOBAL(_outsb)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,1
++ blelr-
++00: lbzu r5,1(r4)
++ stb r5,0(r3)
++ eieio
++ bdnz 00b
++ blr
++
++_GLOBAL(_insw)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhbrx r5,0,r3
++ eieio
++ sthu r5,2(r4)
++ bdnz 00b
++ blr
++
++_GLOBAL(_outsw)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhzu r5,2(r4)
++ eieio
++ sthbrx r5,0,r3
++ bdnz 00b
++ blr
++
++_GLOBAL(_insl)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwbrx r5,0,r3
++ eieio
++ stwu r5,4(r4)
++ bdnz 00b
++ blr
++
++_GLOBAL(_outsl)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwzu r5,4(r4)
++ stwbrx r5,0,r3
++ eieio
++ bdnz 00b
++ blr
++
++_GLOBAL(__ide_mm_insw)
++_GLOBAL(_insw_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhz r5,0(r3)
++ eieio
++ sthu r5,2(r4)
++ bdnz 00b
++ blr
++
++_GLOBAL(__ide_mm_outsw)
++_GLOBAL(_outsw_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhzu r5,2(r4)
++ sth r5,0(r3)
++ eieio
++ bdnz 00b
++ blr
++
++_GLOBAL(__ide_mm_insl)
++_GLOBAL(_insl_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwz r5,0(r3)
++ eieio
++ stwu r5,4(r4)
++ bdnz 00b
++ blr
++
++_GLOBAL(__ide_mm_outsl)
++_GLOBAL(_outsl_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwzu r5,4(r4)
++ stw r5,0(r3)
++ eieio
++ bdnz 00b
++ blr
++
++/*
++ * Extended precision shifts.
++ *
++ * Updated to be valid for shift counts from 0 to 63 inclusive.
++ * -- Gabriel
++ *
++ * R3/R4 has 64 bit value
++ * R5 has shift count
++ * result in R3/R4
++ *
++ * ashrdi3: arithmetic right shift (sign propagation)
++ * lshrdi3: logical right shift
++ * ashldi3: left shift
++ */
++_GLOBAL(__ashrdi3)
++ subfic r6,r5,32
++ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
++ addi r7,r5,32 # could be xori, or addi with -32
++ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
++ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
++ sraw r7,r3,r7 # t2 = MSW >> (count-32)
++ or r4,r4,r6 # LSW |= t1
++ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
++ sraw r3,r3,r5 # MSW = MSW >> count
++ or r4,r4,r7 # LSW |= t2
++ blr
++
++_GLOBAL(__ashldi3)
++ subfic r6,r5,32
++ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
++ addi r7,r5,32 # could be xori, or addi with -32
++ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
++ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
++ or r3,r3,r6 # MSW |= t1
++ slw r4,r4,r5 # LSW = LSW << count
++ or r3,r3,r7 # MSW |= t2
++ blr
++
++_GLOBAL(__lshrdi3)
++ subfic r6,r5,32
++ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
++ addi r7,r5,32 # could be xori, or addi with -32
++ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
++ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
++ or r4,r4,r6 # LSW |= t1
++ srw r3,r3,r5 # MSW = MSW >> count
++ or r4,r4,r7 # LSW |= t2
++ blr
++
++_GLOBAL(abs)
++ srawi r4,r3,31
++ xor r3,r3,r4
++ sub r3,r3,r4
++ blr
++
++_GLOBAL(_get_SP)
++ mr r3,r1 /* Close enough */
++ blr
++
++/*
++ * Create a kernel thread
++ * kernel_thread(fn, arg, flags)
++ */
++_GLOBAL(kernel_thread)
++ stwu r1,-16(r1)
++ stw r30,8(r1)
++ stw r31,12(r1)
++ mr r30,r3 /* function */
++ mr r31,r4 /* argument */
++ ori r3,r5,CLONE_VM /* flags */
++ oris r3,r3,CLONE_UNTRACED>>16
++ li r4,0 /* new sp (unused) */
++ li r0,__NR_clone
++ sc
++ cmpwi 0,r3,0 /* parent or child? */
++ bne 1f /* return if parent */
++ li r0,0 /* make top-level stack frame */
++ stwu r0,-16(r1)
++ mtlr r30 /* fn addr in lr */
++ mr r3,r31 /* load arg and call fn */
++ PPC440EP_ERR42
++ blrl
++ li r0,__NR_exit /* exit if function returns */
++ li r3,0
++ sc
++1: lwz r30,8(r1)
++ lwz r31,12(r1)
++ addi r1,r1,16
++ blr
++
++_GLOBAL(execve)
++ li r0,__NR_execve
++ sc
++ bnslr
++ neg r3,r3
++ blr
++
++/*
++ * This routine is just here to keep GCC happy - sigh...
++ */
++_GLOBAL(__main)
++ blr
+diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/misc_64.S
+@@ -0,0 +1,880 @@
++/*
++ * arch/powerpc/kernel/misc64.S
++ *
++ * This file contains miscellaneous low-level functions.
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Largely rewritten by Cort Dougan (cort at cs.nmt.edu)
++ * and Paul Mackerras.
++ * Adapted for iSeries by Mike Corrigan (mikejc at us.ibm.com)
++ * PPC64 updates by Dave Engebretsen (engebret at us.ibm.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/sys.h>
++#include <asm/unistd.h>
++#include <asm/errno.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/cache.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/cputable.h>
++#include <asm/thread_info.h>
++
++ .text
++
++/*
++ * Returns (address we are running at) - (address we were linked at)
++ * for use before the text and data are mapped to KERNELBASE.
++ */
++
++_GLOBAL(reloc_offset)
++ mflr r0
++ bl 1f
++1: mflr r3
++ LOADADDR(r4,1b)
++ subf r3,r4,r3
++ mtlr r0
++ blr
++
++/*
++ * add_reloc_offset(x) returns x + reloc_offset().
++ */
++_GLOBAL(add_reloc_offset)
++ mflr r0
++ bl 1f
++1: mflr r5
++ LOADADDR(r4,1b)
++ subf r5,r4,r5
++ add r3,r3,r5
++ mtlr r0
++ blr
++
++_GLOBAL(get_msr)
++ mfmsr r3
++ blr
++
++_GLOBAL(get_dar)
++ mfdar r3
++ blr
++
++_GLOBAL(get_srr0)
++ mfsrr0 r3
++ blr
++
++_GLOBAL(get_srr1)
++ mfsrr1 r3
++ blr
++
++_GLOBAL(get_sp)
++ mr r3,r1
++ blr
++
++#ifdef CONFIG_IRQSTACKS
++_GLOBAL(call_do_softirq)
++ mflr r0
++ std r0,16(r1)
++ stdu r1,THREAD_SIZE-112(r3)
++ mr r1,r3
++ bl .__do_softirq
++ ld r1,0(r1)
++ ld r0,16(r1)
++ mtlr r0
++ blr
++
++_GLOBAL(call_handle_IRQ_event)
++ mflr r0
++ std r0,16(r1)
++ stdu r1,THREAD_SIZE-112(r6)
++ mr r1,r6
++ bl .handle_IRQ_event
++ ld r1,0(r1)
++ ld r0,16(r1)
++ mtlr r0
++ blr
++#endif /* CONFIG_IRQSTACKS */
++
++ /*
++ * To be called by C code which needs to do some operations with MMU
++ * disabled. Note that interrupts have to be disabled by the caller
++ * prior to calling us. The code called _MUST_ be in the RMO of course
++ * and part of the linear mapping as we don't attempt to translate the
++ * stack pointer at all. The function is called with the stack switched
++ * to this CPU emergency stack
++ *
++ * prototype is void *call_with_mmu_off(void *func, void *data);
++ *
++ * the called function is expected to be of the form
++ *
++ * void *called(void *data);
++ */
++_GLOBAL(call_with_mmu_off)
++ mflr r0 /* get link, save it on stackframe */
++ std r0,16(r1)
++ mr r1,r5 /* save old stack ptr */
++ ld r1,PACAEMERGSP(r13) /* get emerg. stack */
++ subi r1,r1,STACK_FRAME_OVERHEAD
++ std r0,16(r1) /* save link on emerg. stack */
++ std r5,0(r1) /* save old stack ptr in backchain */
++ ld r3,0(r3) /* get to real function ptr (assume same TOC) */
++ bl 2f /* we need LR to return, continue at label 2 */
++
++ ld r0,16(r1) /* we return here from the call, get LR and */
++ ld r1,0(r1) /* .. old stack ptr */
++ mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */
++ mfmsr r4
++ ori r4,r4,MSR_IR|MSR_DR
++ mtspr SPRN_SRR1,r4
++ rfid
++
++2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */
++ mr r3,r4 /* get parameter */
++ mfmsr r0
++ ori r0,r0,MSR_IR|MSR_DR
++ xori r0,r0,MSR_IR|MSR_DR
++ mtspr SPRN_SRR1,r0
++ rfid
++
++
++ .section ".toc","aw"
++PPC64_CACHES:
++ .tc ppc64_caches[TC],ppc64_caches
++ .section ".text"
++
++/*
++ * Write any modified data cache blocks out to memory
++ * and invalidate the corresponding instruction cache blocks.
++ *
++ * flush_icache_range(unsigned long start, unsigned long stop)
++ *
++ * flush all bytes from start through stop-1 inclusive
++ */
++
++_KPROBE(__flush_icache_range)
++
++/*
++ * Flush the data cache to memory
++ *
++ * Different systems have different cache line sizes
++ * and in some cases i-cache and d-cache line sizes differ from
++ * each other.
++ */
++ ld r10,PPC64_CACHES at toc(r2)
++ lwz r7,DCACHEL1LINESIZE(r10)/* Get cache line size */
++ addi r5,r7,-1
++ andc r6,r3,r5 /* round low to line bdy */
++ subf r8,r6,r4 /* compute length */
++ add r8,r8,r5 /* ensure we get enough */
++ lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */
++ srw. r8,r8,r9 /* compute line count */
++ beqlr /* nothing to do? */
++ mtctr r8
++1: dcbst 0,r6
++ add r6,r6,r7
++ bdnz 1b
++ sync
++
++/* Now invalidate the instruction cache */
++
++ lwz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */
++ addi r5,r7,-1
++ andc r6,r3,r5 /* round low to line bdy */
++ subf r8,r6,r4 /* compute length */
++ add r8,r8,r5
++ lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */
++ srw. r8,r8,r9 /* compute line count */
++ beqlr /* nothing to do? */
++ mtctr r8
++2: icbi 0,r6
++ add r6,r6,r7
++ bdnz 2b
++ isync
++ blr
++ .previous .text
++/*
++ * Like above, but only do the D-cache.
++ *
++ * flush_dcache_range(unsigned long start, unsigned long stop)
++ *
++ * flush all bytes from start to stop-1 inclusive
++ */
++_GLOBAL(flush_dcache_range)
++
++/*
++ * Flush the data cache to memory
++ *
++ * Different systems have different cache line sizes
++ */
++ ld r10,PPC64_CACHES at toc(r2)
++ lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */
++ addi r5,r7,-1
++ andc r6,r3,r5 /* round low to line bdy */
++ subf r8,r6,r4 /* compute length */
++ add r8,r8,r5 /* ensure we get enough */
++ lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */
++ srw. r8,r8,r9 /* compute line count */
++ beqlr /* nothing to do? */
++ mtctr r8
++0: dcbst 0,r6
++ add r6,r6,r7
++ bdnz 0b
++ sync
++ blr
++
++/*
++ * Like above, but works on non-mapped physical addresses.
++ * Use only for non-LPAR setups ! It also assumes real mode
++ * is cacheable. Used for flushing out the DART before using
++ * it as uncacheable memory
++ *
++ * flush_dcache_phys_range(unsigned long start, unsigned long stop)
++ *
++ * flush all bytes from start to stop-1 inclusive
++ */
++_GLOBAL(flush_dcache_phys_range)
++ ld r10,PPC64_CACHES at toc(r2)
++ lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */
++ addi r5,r7,-1
++ andc r6,r3,r5 /* round low to line bdy */
++ subf r8,r6,r4 /* compute length */
++ add r8,r8,r5 /* ensure we get enough */
++ lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */
++ srw. r8,r8,r9 /* compute line count */
++ beqlr /* nothing to do? */
++ mfmsr r5 /* Disable MMU Data Relocation */
++ ori r0,r5,MSR_DR
++ xori r0,r0,MSR_DR
++ sync
++ mtmsr r0
++ sync
++ isync
++ mtctr r8
++0: dcbst 0,r6
++ add r6,r6,r7
++ bdnz 0b
++ sync
++ isync
++ mtmsr r5 /* Re-enable MMU Data Relocation */
++ sync
++ isync
++ blr
++
++_GLOBAL(flush_inval_dcache_range)
++ ld r10,PPC64_CACHES at toc(r2)
++ lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */
++ addi r5,r7,-1
++ andc r6,r3,r5 /* round low to line bdy */
++ subf r8,r6,r4 /* compute length */
++ add r8,r8,r5 /* ensure we get enough */
++ lwz r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */
++ srw. r8,r8,r9 /* compute line count */
++ beqlr /* nothing to do? */
++ sync
++ isync
++ mtctr r8
++0: dcbf 0,r6
++ add r6,r6,r7
++ bdnz 0b
++ sync
++ isync
++ blr
++
++
++/*
++ * Flush a particular page from the data cache to RAM.
++ * Note: this is necessary because the instruction cache does *not*
++ * snoop from the data cache.
++ *
++ * void __flush_dcache_icache(void *page)
++ */
++_GLOBAL(__flush_dcache_icache)
++/*
++ * Flush the data cache to memory
++ *
++ * Different systems have different cache line sizes
++ */
++
++/* Flush the dcache */
++ ld r7,PPC64_CACHES at toc(r2)
++ clrrdi r3,r3,PAGE_SHIFT /* Page align */
++ lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */
++ lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */
++ mr r6,r3
++ mtctr r4
++0: dcbst 0,r6
++ add r6,r6,r5
++ bdnz 0b
++ sync
++
++/* Now invalidate the icache */
++
++ lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */
++ lwz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */
++ mtctr r4
++1: icbi 0,r3
++ add r3,r3,r5
++ bdnz 1b
++ isync
++ blr
++
++/*
++ * I/O string operations
++ *
++ * insb(port, buf, len)
++ * outsb(port, buf, len)
++ * insw(port, buf, len)
++ * outsw(port, buf, len)
++ * insl(port, buf, len)
++ * outsl(port, buf, len)
++ * insw_ns(port, buf, len)
++ * outsw_ns(port, buf, len)
++ * insl_ns(port, buf, len)
++ * outsl_ns(port, buf, len)
++ *
++ * The *_ns versions don't do byte-swapping.
++ */
++_GLOBAL(_insb)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,1
++ blelr-
++00: lbz r5,0(r3)
++ eieio
++ stbu r5,1(r4)
++ bdnz 00b
++ twi 0,r5,0
++ isync
++ blr
++
++_GLOBAL(_outsb)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,1
++ blelr-
++00: lbzu r5,1(r4)
++ stb r5,0(r3)
++ bdnz 00b
++ sync
++ blr
++
++_GLOBAL(_insw)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhbrx r5,0,r3
++ eieio
++ sthu r5,2(r4)
++ bdnz 00b
++ twi 0,r5,0
++ isync
++ blr
++
++_GLOBAL(_outsw)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhzu r5,2(r4)
++ sthbrx r5,0,r3
++ bdnz 00b
++ sync
++ blr
++
++_GLOBAL(_insl)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwbrx r5,0,r3
++ eieio
++ stwu r5,4(r4)
++ bdnz 00b
++ twi 0,r5,0
++ isync
++ blr
++
++_GLOBAL(_outsl)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwzu r5,4(r4)
++ stwbrx r5,0,r3
++ bdnz 00b
++ sync
++ blr
++
++/* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */
++_GLOBAL(_insw_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhz r5,0(r3)
++ eieio
++ sthu r5,2(r4)
++ bdnz 00b
++ twi 0,r5,0
++ isync
++ blr
++
++/* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */
++_GLOBAL(_outsw_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,2
++ blelr-
++00: lhzu r5,2(r4)
++ sth r5,0(r3)
++ bdnz 00b
++ sync
++ blr
++
++_GLOBAL(_insl_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwz r5,0(r3)
++ eieio
++ stwu r5,4(r4)
++ bdnz 00b
++ twi 0,r5,0
++ isync
++ blr
++
++_GLOBAL(_outsl_ns)
++ cmpwi 0,r5,0
++ mtctr r5
++ subi r4,r4,4
++ blelr-
++00: lwzu r5,4(r4)
++ stw r5,0(r3)
++ bdnz 00b
++ sync
++ blr
++
++/*
++ * identify_cpu and calls setup_cpu
++ * In: r3 = base of the cpu_specs array
++ * r4 = address of cur_cpu_spec
++ * r5 = relocation offset
++ */
++_GLOBAL(identify_cpu)
++ mfpvr r7
++1:
++ lwz r8,CPU_SPEC_PVR_MASK(r3)
++ and r8,r8,r7
++ lwz r9,CPU_SPEC_PVR_VALUE(r3)
++ cmplw 0,r9,r8
++ beq 1f
++ addi r3,r3,CPU_SPEC_ENTRY_SIZE
++ b 1b
++1:
++ sub r0,r3,r5
++ std r0,0(r4)
++ ld r4,CPU_SPEC_SETUP(r3)
++ add r4,r4,r5
++ ld r4,0(r4)
++ add r4,r4,r5
++ mtctr r4
++ /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */
++ mr r4,r3
++ mr r3,r5
++ bctr
++
++/*
++ * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
++ * and writes nop's over sections of code that don't apply for this cpu.
++ * r3 = data offset (not changed)
++ */
++_GLOBAL(do_cpu_ftr_fixups)
++ /* Get CPU 0 features */
++ LOADADDR(r6,cur_cpu_spec)
++ sub r6,r6,r3
++ ld r4,0(r6)
++ sub r4,r4,r3
++ ld r4,CPU_SPEC_FEATURES(r4)
++ /* Get the fixup table */
++ LOADADDR(r6,__start___ftr_fixup)
++ sub r6,r6,r3
++ LOADADDR(r7,__stop___ftr_fixup)
++ sub r7,r7,r3
++ /* Do the fixup */
++1: cmpld r6,r7
++ bgelr
++ addi r6,r6,32
++ ld r8,-32(r6) /* mask */
++ and r8,r8,r4
++ ld r9,-24(r6) /* value */
++ cmpld r8,r9
++ beq 1b
++ ld r8,-16(r6) /* section begin */
++ ld r9,-8(r6) /* section end */
++ subf. r9,r8,r9
++ beq 1b
++ /* write nops over the section of code */
++ /* todo: if large section, add a branch at the start of it */
++ srwi r9,r9,2
++ mtctr r9
++ sub r8,r8,r3
++ lis r0,0x60000000 at h /* nop */
++3: stw r0,0(r8)
++ andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE at l
++ beq 2f
++ dcbst 0,r8 /* suboptimal, but simpler */
++ sync
++ icbi 0,r8
++2: addi r8,r8,4
++ bdnz 3b
++ sync /* additional sync needed on g4 */
++ isync
++ b 1b
++
++#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
++/*
++ * Do an IO access in real mode
++ */
++_GLOBAL(real_readb)
++ mfmsr r7
++ ori r0,r7,MSR_DR
++ xori r0,r0,MSR_DR
++ sync
++ mtmsrd r0
++ sync
++ isync
++ mfspr r6,SPRN_HID4
++ rldicl r5,r6,32,0
++ ori r5,r5,0x100
++ rldicl r5,r5,32,0
++ sync
++ mtspr SPRN_HID4,r5
++ isync
++ slbia
++ isync
++ lbz r3,0(r3)
++ sync
++ mtspr SPRN_HID4,r6
++ isync
++ slbia
++ isync
++ mtmsrd r7
++ sync
++ isync
++ blr
++
++ /*
++ * Do an IO access in real mode
++ */
++_GLOBAL(real_writeb)
++ mfmsr r7
++ ori r0,r7,MSR_DR
++ xori r0,r0,MSR_DR
++ sync
++ mtmsrd r0
++ sync
++ isync
++ mfspr r6,SPRN_HID4
++ rldicl r5,r6,32,0
++ ori r5,r5,0x100
++ rldicl r5,r5,32,0
++ sync
++ mtspr SPRN_HID4,r5
++ isync
++ slbia
++ isync
++ stb r3,0(r4)
++ sync
++ mtspr SPRN_HID4,r6
++ isync
++ slbia
++ isync
++ mtmsrd r7
++ sync
++ isync
++ blr
++#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
++
++/*
++ * Create a kernel thread
++ * kernel_thread(fn, arg, flags)
++ */
++_GLOBAL(kernel_thread)
++ std r29,-24(r1)
++ std r30,-16(r1)
++ stdu r1,-STACK_FRAME_OVERHEAD(r1)
++ mr r29,r3
++ mr r30,r4
++ ori r3,r5,CLONE_VM /* flags */
++ oris r3,r3,(CLONE_UNTRACED>>16)
++ li r4,0 /* new sp (unused) */
++ li r0,__NR_clone
++ sc
++ cmpdi 0,r3,0 /* parent or child? */
++ bne 1f /* return if parent */
++ li r0,0
++ stdu r0,-STACK_FRAME_OVERHEAD(r1)
++ ld r2,8(r29)
++ ld r29,0(r29)
++ mtlr r29 /* fn addr in lr */
++ mr r3,r30 /* load arg and call fn */
++ blrl
++ li r0,__NR_exit /* exit after child exits */
++ li r3,0
++ sc
++1: addi r1,r1,STACK_FRAME_OVERHEAD
++ ld r29,-24(r1)
++ ld r30,-16(r1)
++ blr
++
++/*
++ * disable_kernel_fp()
++ * Disable the FPU.
++ */
++_GLOBAL(disable_kernel_fp)
++ mfmsr r3
++ rldicl r0,r3,(63-MSR_FP_LG),1
++ rldicl r3,r0,(MSR_FP_LG+1),0
++ mtmsrd r3 /* disable use of fpu now */
++ isync
++ blr
++
++#ifdef CONFIG_ALTIVEC
++
++#if 0 /* this has no callers for now */
++/*
++ * disable_kernel_altivec()
++ * Disable the VMX.
++ */
++_GLOBAL(disable_kernel_altivec)
++ mfmsr r3
++ rldicl r0,r3,(63-MSR_VEC_LG),1
++ rldicl r3,r0,(MSR_VEC_LG+1),0
++ mtmsrd r3 /* disable use of VMX now */
++ isync
++ blr
++#endif /* 0 */
++
++/*
++ * giveup_altivec(tsk)
++ * Disable VMX for the task given as the argument,
++ * and save the vector registers in its thread_struct.
++ * Enables the VMX for use in the kernel on return.
++ */
++_GLOBAL(giveup_altivec)
++ mfmsr r5
++ oris r5,r5,MSR_VEC at h
++ mtmsrd r5 /* enable use of VMX now */
++ isync
++ cmpdi 0,r3,0
++ beqlr- /* if no previous owner, done */
++ addi r3,r3,THREAD /* want THREAD of task */
++ ld r5,PT_REGS(r3)
++ cmpdi 0,r5,0
++ SAVE_32VRS(0,r4,r3)
++ mfvscr vr0
++ li r4,THREAD_VSCR
++ stvx vr0,r4,r3
++ beq 1f
++ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++ lis r3,MSR_VEC at h
++ andc r4,r4,r3 /* disable FP for previous task */
++ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
++1:
++#ifndef CONFIG_SMP
++ li r5,0
++ ld r4,last_task_used_altivec at got(r2)
++ std r5,0(r4)
++#endif /* CONFIG_SMP */
++ blr
++
++#endif /* CONFIG_ALTIVEC */
++
++_GLOBAL(__setup_cpu_power3)
++ blr
++
++_GLOBAL(execve)
++ li r0,__NR_execve
++ sc
++ bnslr
++ neg r3,r3
++ blr
++
++/* kexec_wait(phys_cpu)
++ *
++ * wait for the flag to change, indicating this kernel is going away but
++ * the slave code for the next one is at addresses 0 to 100.
++ *
++ * This is used by all slaves.
++ *
++ * Physical (hardware) cpu id should be in r3.
++ */
++_GLOBAL(kexec_wait)
++ bl 1f
++1: mflr r5
++ addi r5,r5,kexec_flag-1b
++
++99: HMT_LOW
++#ifdef CONFIG_KEXEC /* use no memory without kexec */
++ lwz r4,0(r5)
++ cmpwi 0,r4,0
++ bnea 0x60
++#endif
++ b 99b
++
++/* this can be in text because we won't change it until we are
++ * running in real anyways
++ */
++kexec_flag:
++ .long 0
++
++
++#ifdef CONFIG_KEXEC
++
++/* kexec_smp_wait(void)
++ *
++ * call with interrupts off
++ * note: this is a terminal routine, it does not save lr
++ *
++ * get phys id from paca
++ * set paca id to -1 to say we got here
++ * switch to real mode
++ * join other cpus in kexec_wait(phys_id)
++ */
++_GLOBAL(kexec_smp_wait)
++ lhz r3,PACAHWCPUID(r13)
++ li r4,-1
++ sth r4,PACAHWCPUID(r13) /* let others know we left */
++ bl real_mode
++ b .kexec_wait
++
++/*
++ * switch to real mode (turn mmu off)
++ * we use the early kernel trick that the hardware ignores bits
++ * 0 and 1 (big endian) of the effective address in real mode
++ *
++ * don't overwrite r3 here, it is live for kexec_wait above.
++ */
++real_mode: /* assume normal blr return */
++1: li r9,MSR_RI
++ li r10,MSR_DR|MSR_IR
++ mflr r11 /* return address to SRR0 */
++ mfmsr r12
++ andc r9,r12,r9
++ andc r10,r12,r10
++
++ mtmsrd r9,1
++ mtspr SPRN_SRR1,r10
++ mtspr SPRN_SRR0,r11
++ rfid
++
++
++/*
++ * kexec_sequence(newstack, start, image, control, clear_all())
++ *
++ * does the grungy work with stack switching and real mode switches
++ * also does simple calls to other code
++ */
++
++_GLOBAL(kexec_sequence)
++ mflr r0
++ std r0,16(r1)
++
++ /* switch stacks to newstack -- &kexec_stack.stack */
++ stdu r1,THREAD_SIZE-112(r3)
++ mr r1,r3
++
++ li r0,0
++ std r0,16(r1)
++
++ /* save regs for local vars on new stack.
++ * yes, we won't go back, but ...
++ */
++ std r31,-8(r1)
++ std r30,-16(r1)
++ std r29,-24(r1)
++ std r28,-32(r1)
++ std r27,-40(r1)
++ std r26,-48(r1)
++ std r25,-56(r1)
++
++ stdu r1,-112-64(r1)
++
++ /* save args into preserved regs */
++ mr r31,r3 /* newstack (both) */
++ mr r30,r4 /* start (real) */
++ mr r29,r5 /* image (virt) */
++ mr r28,r6 /* control, unused */
++ mr r27,r7 /* clear_all() fn desc */
++ mr r26,r8 /* spare */
++ lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */
++
++ /* disable interrupts, we are overwriting kernel data next */
++ mfmsr r3
++ rlwinm r3,r3,0,17,15
++ mtmsrd r3,1
++
++ /* copy dest pages, flush whole dest image */
++ mr r3,r29
++ bl .kexec_copy_flush /* (image) */
++
++ /* turn off mmu */
++ bl real_mode
++
++ /* clear out hardware hash page table and tlb */
++ ld r5,0(r27) /* deref function descriptor */
++ mtctr r5
++ bctrl /* ppc_md.hash_clear_all(void); */
++
++/*
++ * kexec image calling is:
++ * the first 0x100 bytes of the entry point are copied to 0
++ *
++ * all slaves branch to slave = 0x60 (absolute)
++ * slave(phys_cpu_id);
++ *
++ * master goes to start = entry point
++ * start(phys_cpu_id, start, 0);
++ *
++ *
++ * a wrapper is needed to call existing kernels, here is an approximate
++ * description of one method:
++ *
++ * v2: (2.6.10)
++ * start will be near the boot_block (maybe 0x100 bytes before it?)
++ * it will have a 0x60, which will b to boot_block, where it will wait
++ * and 0 will store phys into struct boot-block and load r3 from there,
++ * copy kernel 0-0x100 and tell slaves to back down to 0x60 again
++ *
++ * v1: (2.6.9)
++ * boot block will have all cpus scanning device tree to see if they
++ * are the boot cpu ?????
++ * other device tree differences (prop sizes, va vs pa, etc)...
++ */
++
++ /* copy 0x100 bytes starting at start to 0 */
++ li r3,0
++ mr r4,r30
++ li r5,0x100
++ li r6,0
++ bl .copy_and_flush /* (dest, src, copy limit, start offset) */
++1: /* assume normal blr return */
++
++ /* release other cpus to the new kernel secondary start at 0x60 */
++ mflr r5
++ li r6,1
++ stw r6,kexec_flag-1b(5)
++ mr r3,r25 # my phys cpu
++ mr r4,r30 # start, aka phys mem offset
++ mtlr 4
++ li r5,0
++ blr /* image->start(physid, image->start, 0); */
++#endif /* CONFIG_KEXEC */
+diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/of_device.c
+@@ -0,0 +1,276 @@
++#include <linux/config.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/mod_devicetable.h>
++#include <linux/slab.h>
++
++#include <asm/errno.h>
++#include <asm/of_device.h>
++
++/**
++ * of_match_device - Tell if an of_device structure has a matching
++ * of_match structure
++ * @ids: array of of device match structures to search in
++ * @dev: the of device structure to match against
++ *
++ * Used by a driver to check whether an of_device present in the
++ * system is in its list of supported devices.
++ */
++const struct of_device_id *of_match_device(const struct of_device_id *matches,
++ const struct of_device *dev)
++{
++ if (!dev->node)
++ return NULL;
++ while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
++ int match = 1;
++ if (matches->name[0])
++ match &= dev->node->name
++ && !strcmp(matches->name, dev->node->name);
++ if (matches->type[0])
++ match &= dev->node->type
++ && !strcmp(matches->type, dev->node->type);
++ if (matches->compatible[0])
++ match &= device_is_compatible(dev->node,
++ matches->compatible);
++ if (match)
++ return matches;
++ matches++;
++ }
++ return NULL;
++}
++
++static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
++{
++ struct of_device * of_dev = to_of_device(dev);
++ struct of_platform_driver * of_drv = to_of_platform_driver(drv);
++ const struct of_device_id * matches = of_drv->match_table;
++
++ if (!matches)
++ return 0;
++
++ return of_match_device(matches, of_dev) != NULL;
++}
++
++struct of_device *of_dev_get(struct of_device *dev)
++{
++ struct device *tmp;
++
++ if (!dev)
++ return NULL;
++ tmp = get_device(&dev->dev);
++ if (tmp)
++ return to_of_device(tmp);
++ else
++ return NULL;
++}
++
++void of_dev_put(struct of_device *dev)
++{
++ if (dev)
++ put_device(&dev->dev);
++}
++
++
++static int of_device_probe(struct device *dev)
++{
++ int error = -ENODEV;
++ struct of_platform_driver *drv;
++ struct of_device *of_dev;
++ const struct of_device_id *match;
++
++ drv = to_of_platform_driver(dev->driver);
++ of_dev = to_of_device(dev);
++
++ if (!drv->probe)
++ return error;
++
++ of_dev_get(of_dev);
++
++ match = of_match_device(drv->match_table, of_dev);
++ if (match)
++ error = drv->probe(of_dev, match);
++ if (error)
++ of_dev_put(of_dev);
++
++ return error;
++}
++
++static int of_device_remove(struct device *dev)
++{
++ struct of_device * of_dev = to_of_device(dev);
++ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
++
++ if (dev->driver && drv->remove)
++ drv->remove(of_dev);
++ return 0;
++}
++
++static int of_device_suspend(struct device *dev, pm_message_t state)
++{
++ struct of_device * of_dev = to_of_device(dev);
++ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
++ int error = 0;
++
++ if (dev->driver && drv->suspend)
++ error = drv->suspend(of_dev, state);
++ return error;
++}
++
++static int of_device_resume(struct device * dev)
++{
++ struct of_device * of_dev = to_of_device(dev);
++ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
++ int error = 0;
++
++ if (dev->driver && drv->resume)
++ error = drv->resume(of_dev);
++ return error;
++}
++
++struct bus_type of_platform_bus_type = {
++ .name = "of_platform",
++ .match = of_platform_bus_match,
++ .suspend = of_device_suspend,
++ .resume = of_device_resume,
++};
++
++static int __init of_bus_driver_init(void)
++{
++ return bus_register(&of_platform_bus_type);
++}
++
++postcore_initcall(of_bus_driver_init);
++
++int of_register_driver(struct of_platform_driver *drv)
++{
++ int count = 0;
++
++ /* initialize common driver fields */
++ drv->driver.name = drv->name;
++ drv->driver.bus = &of_platform_bus_type;
++ drv->driver.probe = of_device_probe;
++ drv->driver.remove = of_device_remove;
++
++ /* register with core */
++ count = driver_register(&drv->driver);
++ return count ? count : 1;
++}
++
++void of_unregister_driver(struct of_platform_driver *drv)
++{
++ driver_unregister(&drv->driver);
++}
++
++
++static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct of_device *ofdev;
++
++ ofdev = to_of_device(dev);
++ return sprintf(buf, "%s", ofdev->node->full_name);
++}
++
++static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
++
++/**
++ * of_release_dev - free an of device structure when all users of it are finished.
++ * @dev: device that's been disconnected
++ *
++ * Will be called only by the device core when all users of this of device are
++ * done.
++ */
++void of_release_dev(struct device *dev)
++{
++ struct of_device *ofdev;
++
++ ofdev = to_of_device(dev);
++ of_node_put(ofdev->node);
++ kfree(ofdev);
++}
++
++int of_device_register(struct of_device *ofdev)
++{
++ int rc;
++ struct of_device **odprop;
++
++ BUG_ON(ofdev->node == NULL);
++
++ odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
++ if (!odprop) {
++ struct property *new_prop;
++
++ new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
++ GFP_KERNEL);
++ if (new_prop == NULL)
++ return -ENOMEM;
++ new_prop->name = "linux,device";
++ new_prop->length = sizeof(sizeof(struct of_device *));
++ new_prop->value = (unsigned char *)&new_prop[1];
++ odprop = (struct of_device **)new_prop->value;
++ *odprop = NULL;
++ prom_add_property(ofdev->node, new_prop);
++ }
++ *odprop = ofdev;
++
++ rc = device_register(&ofdev->dev);
++ if (rc)
++ return rc;
++
++ device_create_file(&ofdev->dev, &dev_attr_devspec);
++
++ return 0;
++}
++
++void of_device_unregister(struct of_device *ofdev)
++{
++ struct of_device **odprop;
++
++ device_remove_file(&ofdev->dev, &dev_attr_devspec);
++
++ odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
++ if (odprop)
++ *odprop = NULL;
++
++ device_unregister(&ofdev->dev);
++}
++
++struct of_device* of_platform_device_create(struct device_node *np,
++ const char *bus_id,
++ struct device *parent)
++{
++ struct of_device *dev;
++
++ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
++ if (!dev)
++ return NULL;
++ memset(dev, 0, sizeof(*dev));
++
++ dev->node = of_node_get(np);
++ dev->dma_mask = 0xffffffffUL;
++ dev->dev.dma_mask = &dev->dma_mask;
++ dev->dev.parent = parent;
++ dev->dev.bus = &of_platform_bus_type;
++ dev->dev.release = of_release_dev;
++
++ strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
++
++ if (of_device_register(dev) != 0) {
++ kfree(dev);
++ return NULL;
++ }
++
++ return dev;
++}
++
++EXPORT_SYMBOL(of_match_device);
++EXPORT_SYMBOL(of_platform_bus_type);
++EXPORT_SYMBOL(of_register_driver);
++EXPORT_SYMBOL(of_unregister_driver);
++EXPORT_SYMBOL(of_device_register);
++EXPORT_SYMBOL(of_device_unregister);
++EXPORT_SYMBOL(of_dev_get);
++EXPORT_SYMBOL(of_dev_put);
++EXPORT_SYMBOL(of_platform_device_create);
++EXPORT_SYMBOL(of_release_dev);
+diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/pmc.c
+@@ -0,0 +1,112 @@
++/*
++ * arch/powerpc/kernel/pmc.c
++ *
++ * Copyright (C) 2004 David Gibson, IBM Corporation.
++ * Includes code formerly from arch/ppc/kernel/perfmon.c:
++ * Author: Andy Fleming
++ * Copyright (c) 2004 Freescale Semiconductor, Inc
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/config.h>
++#include <linux/errno.h>
++#include <linux/spinlock.h>
++#include <linux/module.h>
++
++#include <asm/processor.h>
++#include <asm/pmc.h>
++
++#if defined(CONFIG_FSL_BOOKE) && !defined(CONFIG_E200)
++static void dummy_perf(struct pt_regs *regs)
++{
++ unsigned int pmgc0 = mfpmr(PMRN_PMGC0);
++
++ pmgc0 &= ~PMGC0_PMIE;
++ mtpmr(PMRN_PMGC0, pmgc0);
++}
++#elif defined(CONFIG_PPC64) || defined(CONFIG_6xx)
++
++#ifndef MMCR0_PMAO
++#define MMCR0_PMAO 0
++#endif
++
++/* Ensure exceptions are disabled */
++static void dummy_perf(struct pt_regs *regs)
++{
++ unsigned int mmcr0 = mfspr(SPRN_MMCR0);
++
++ mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
++ mtspr(SPRN_MMCR0, mmcr0);
++}
++#else
++static void dummy_perf(struct pt_regs *regs)
++{
++}
++#endif
++
++static DEFINE_SPINLOCK(pmc_owner_lock);
++static void *pmc_owner_caller; /* mostly for debugging */
++perf_irq_t perf_irq = dummy_perf;
++
++int reserve_pmc_hardware(perf_irq_t new_perf_irq)
++{
++ int err = 0;
++
++ spin_lock(&pmc_owner_lock);
++
++ if (pmc_owner_caller) {
++ printk(KERN_WARNING "reserve_pmc_hardware: "
++ "PMC hardware busy (reserved by caller %p)\n",
++ pmc_owner_caller);
++ err = -EBUSY;
++ goto out;
++ }
++
++ pmc_owner_caller = __builtin_return_address(0);
++ perf_irq = new_perf_irq ? : dummy_perf;
++
++ out:
++ spin_unlock(&pmc_owner_lock);
++ return err;
++}
++EXPORT_SYMBOL_GPL(reserve_pmc_hardware);
++
++void release_pmc_hardware(void)
++{
++ spin_lock(&pmc_owner_lock);
++
++ WARN_ON(! pmc_owner_caller);
++
++ pmc_owner_caller = NULL;
++ perf_irq = dummy_perf;
++
++ spin_unlock(&pmc_owner_lock);
++}
++EXPORT_SYMBOL_GPL(release_pmc_hardware);
++
++#ifdef CONFIG_PPC64
++void power4_enable_pmcs(void)
++{
++ unsigned long hid0;
++
++ hid0 = mfspr(SPRN_HID0);
++ hid0 |= 1UL << (63 - 20);
++
++ /* POWER4 requires the following sequence */
++ asm volatile(
++ "sync\n"
++ "mtspr %1, %0\n"
++ "mfspr %0, %1\n"
++ "mfspr %0, %1\n"
++ "mfspr %0, %1\n"
++ "mfspr %0, %1\n"
++ "mfspr %0, %1\n"
++ "mfspr %0, %1\n"
++ "isync" : "=&r" (hid0) : "i" (SPRN_HID0), "0" (hid0):
++ "memory");
++}
++#endif /* CONFIG_PPC64 */
+diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/ppc_ksyms.c
+@@ -0,0 +1,273 @@
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/threads.h>
++#include <linux/smp.h>
++#include <linux/sched.h>
++#include <linux/elfcore.h>
++#include <linux/string.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/vt_kern.h>
++#include <linux/nvram.h>
++#include <linux/console.h>
++#include <linux/irq.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/ide.h>
++#include <linux/bitops.h>
++
++#include <asm/page.h>
++#include <asm/semaphore.h>
++#include <asm/processor.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/ide.h>
++#include <asm/atomic.h>
++#include <asm/checksum.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++#include <linux/adb.h>
++#include <linux/cuda.h>
++#include <linux/pmu.h>
++#include <asm/prom.h>
++#include <asm/system.h>
++#include <asm/pci-bridge.h>
++#include <asm/irq.h>
++#include <asm/pmac_feature.h>
++#include <asm/dma.h>
++#include <asm/machdep.h>
++#include <asm/hw_irq.h>
++#include <asm/nvram.h>
++#include <asm/mmu_context.h>
++#include <asm/backlight.h>
++#include <asm/time.h>
++#include <asm/cputable.h>
++#include <asm/btext.h>
++#include <asm/div64.h>
++
++#ifdef CONFIG_8xx
++#include <asm/commproc.h>
++#endif
++
++#ifdef CONFIG_PPC32
++extern void transfer_to_handler(void);
++extern void do_IRQ(struct pt_regs *regs);
++extern void machine_check_exception(struct pt_regs *regs);
++extern void alignment_exception(struct pt_regs *regs);
++extern void program_check_exception(struct pt_regs *regs);
++extern void single_step_exception(struct pt_regs *regs);
++extern int do_signal(sigset_t *, struct pt_regs *);
++extern int pmac_newworld;
++extern int sys_sigreturn(struct pt_regs *regs);
++
++EXPORT_SYMBOL(clear_pages);
++EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
++EXPORT_SYMBOL(DMA_MODE_READ);
++EXPORT_SYMBOL(DMA_MODE_WRITE);
++EXPORT_SYMBOL(__div64_32);
++
++EXPORT_SYMBOL(do_signal);
++EXPORT_SYMBOL(transfer_to_handler);
++EXPORT_SYMBOL(do_IRQ);
++EXPORT_SYMBOL(machine_check_exception);
++EXPORT_SYMBOL(alignment_exception);
++EXPORT_SYMBOL(program_check_exception);
++EXPORT_SYMBOL(single_step_exception);
++EXPORT_SYMBOL(sys_sigreturn);
++#endif
++
++#if defined(CONFIG_PPC_PREP)
++EXPORT_SYMBOL(_prep_type);
++EXPORT_SYMBOL(ucSystemType);
++#endif
++
++#if !defined(__INLINE_BITOPS)
++EXPORT_SYMBOL(set_bit);
++EXPORT_SYMBOL(clear_bit);
++EXPORT_SYMBOL(change_bit);
++EXPORT_SYMBOL(test_and_set_bit);
++EXPORT_SYMBOL(test_and_clear_bit);
++EXPORT_SYMBOL(test_and_change_bit);
++#endif /* __INLINE_BITOPS */
++
++EXPORT_SYMBOL(strcpy);
++EXPORT_SYMBOL(strncpy);
++EXPORT_SYMBOL(strcat);
++EXPORT_SYMBOL(strncat);
++EXPORT_SYMBOL(strchr);
++EXPORT_SYMBOL(strrchr);
++EXPORT_SYMBOL(strpbrk);
++EXPORT_SYMBOL(strstr);
++EXPORT_SYMBOL(strlen);
++EXPORT_SYMBOL(strnlen);
++EXPORT_SYMBOL(strcmp);
++EXPORT_SYMBOL(strncmp);
++EXPORT_SYMBOL(strcasecmp);
++
++EXPORT_SYMBOL(csum_partial);
++EXPORT_SYMBOL(csum_partial_copy_generic);
++EXPORT_SYMBOL(ip_fast_csum);
++EXPORT_SYMBOL(csum_tcpudp_magic);
++
++EXPORT_SYMBOL(__copy_tofrom_user);
++EXPORT_SYMBOL(__clear_user);
++EXPORT_SYMBOL(__strncpy_from_user);
++EXPORT_SYMBOL(__strnlen_user);
++
++EXPORT_SYMBOL(_insb);
++EXPORT_SYMBOL(_outsb);
++EXPORT_SYMBOL(_insw);
++EXPORT_SYMBOL(_outsw);
++EXPORT_SYMBOL(_insl);
++EXPORT_SYMBOL(_outsl);
++EXPORT_SYMBOL(_insw_ns);
++EXPORT_SYMBOL(_outsw_ns);
++EXPORT_SYMBOL(_insl_ns);
++EXPORT_SYMBOL(_outsl_ns);
++EXPORT_SYMBOL(ioremap);
++#ifdef CONFIG_44x
++EXPORT_SYMBOL(ioremap64);
++#endif
++EXPORT_SYMBOL(__ioremap);
++EXPORT_SYMBOL(iounmap);
++#ifdef CONFIG_PPC32
++EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
++#endif
++
++#if defined(CONFIG_PPC32) && (defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE))
++EXPORT_SYMBOL(ppc_ide_md);
++#endif
++
++#if defined(CONFIG_PCI) && defined(CONFIG_PPC32)
++EXPORT_SYMBOL(isa_io_base);
++EXPORT_SYMBOL(isa_mem_base);
++EXPORT_SYMBOL(pci_dram_offset);
++EXPORT_SYMBOL(pci_alloc_consistent);
++EXPORT_SYMBOL(pci_free_consistent);
++EXPORT_SYMBOL(pci_bus_io_base);
++EXPORT_SYMBOL(pci_bus_io_base_phys);
++EXPORT_SYMBOL(pci_bus_mem_base_phys);
++EXPORT_SYMBOL(pci_bus_to_hose);
++EXPORT_SYMBOL(pci_resource_to_bus);
++EXPORT_SYMBOL(pci_phys_to_bus);
++EXPORT_SYMBOL(pci_bus_to_phys);
++#endif /* CONFIG_PCI */
++
++#ifdef CONFIG_NOT_COHERENT_CACHE
++EXPORT_SYMBOL(flush_dcache_all);
++#endif
++
++EXPORT_SYMBOL(start_thread);
++EXPORT_SYMBOL(kernel_thread);
++
++EXPORT_SYMBOL(giveup_fpu);
++#ifdef CONFIG_ALTIVEC
++EXPORT_SYMBOL(giveup_altivec);
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++EXPORT_SYMBOL(giveup_spe);
++#endif /* CONFIG_SPE */
++
++#ifdef CONFIG_PPC64
++EXPORT_SYMBOL(__flush_icache_range);
++#else
++EXPORT_SYMBOL(flush_instruction_cache);
++EXPORT_SYMBOL(flush_icache_range);
++EXPORT_SYMBOL(flush_tlb_kernel_range);
++EXPORT_SYMBOL(flush_tlb_page);
++EXPORT_SYMBOL(_tlbie);
++#endif
++EXPORT_SYMBOL(flush_dcache_range);
++
++#ifdef CONFIG_SMP
++EXPORT_SYMBOL(smp_call_function);
++#ifdef CONFIG_PPC32
++EXPORT_SYMBOL(smp_hw_index);
++#endif
++#endif
++
++#ifdef CONFIG_ADB
++EXPORT_SYMBOL(adb_request);
++EXPORT_SYMBOL(adb_register);
++EXPORT_SYMBOL(adb_unregister);
++EXPORT_SYMBOL(adb_poll);
++EXPORT_SYMBOL(adb_try_handler_change);
++#endif /* CONFIG_ADB */
++#ifdef CONFIG_ADB_CUDA
++EXPORT_SYMBOL(cuda_request);
++EXPORT_SYMBOL(cuda_poll);
++#endif /* CONFIG_ADB_CUDA */
++#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32)
++EXPORT_SYMBOL(_machine);
++#endif
++#ifdef CONFIG_PPC_PMAC
++EXPORT_SYMBOL(sys_ctrler);
++#endif
++#ifdef CONFIG_VT
++EXPORT_SYMBOL(kd_mksound);
++#endif
++EXPORT_SYMBOL(to_tm);
++
++#ifdef CONFIG_PPC32
++long long __ashrdi3(long long, int);
++long long __ashldi3(long long, int);
++long long __lshrdi3(long long, int);
++EXPORT_SYMBOL(__ashrdi3);
++EXPORT_SYMBOL(__ashldi3);
++EXPORT_SYMBOL(__lshrdi3);
++#endif
++
++EXPORT_SYMBOL(memcpy);
++EXPORT_SYMBOL(memset);
++EXPORT_SYMBOL(memmove);
++EXPORT_SYMBOL(memscan);
++EXPORT_SYMBOL(memcmp);
++EXPORT_SYMBOL(memchr);
++
++#if defined(CONFIG_FB_VGA16_MODULE)
++EXPORT_SYMBOL(screen_info);
++#endif
++
++#ifdef CONFIG_PPC32
++EXPORT_SYMBOL(__delay);
++EXPORT_SYMBOL(timer_interrupt);
++EXPORT_SYMBOL(irq_desc);
++EXPORT_SYMBOL(tb_ticks_per_jiffy);
++EXPORT_SYMBOL(console_drivers);
++EXPORT_SYMBOL(cacheable_memcpy);
++#endif
++
++EXPORT_SYMBOL(__up);
++EXPORT_SYMBOL(__down);
++EXPORT_SYMBOL(__down_interruptible);
++
++#ifdef CONFIG_8xx
++EXPORT_SYMBOL(cpm_install_handler);
++EXPORT_SYMBOL(cpm_free_handler);
++#endif /* CONFIG_8xx */
++#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\
++ defined(CONFIG_83xx)
++EXPORT_SYMBOL(__res);
++#endif
++
++#ifdef CONFIG_PPC32
++EXPORT_SYMBOL(next_mmu_context);
++EXPORT_SYMBOL(set_context);
++#endif
++
++#ifdef CONFIG_PPC_STD_MMU_32
++extern long mol_trampoline;
++EXPORT_SYMBOL(mol_trampoline); /* For MOL */
++EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
++EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */
++#ifdef CONFIG_SMP
++extern int mmu_hash_lock;
++EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
++#endif /* CONFIG_SMP */
++extern long *intercept_table;
++EXPORT_SYMBOL(intercept_table);
++#endif /* CONFIG_PPC_STD_MMU_32 */
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++EXPORT_SYMBOL(__mtdcr);
++EXPORT_SYMBOL(__mfdcr);
++#endif
+diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/process.c
+@@ -0,0 +1,919 @@
++/*
++ * arch/ppc/kernel/process.c
++ *
++ * Derived from "arch/i386/kernel/process.c"
++ * Copyright (C) 1995 Linus Torvalds
++ *
++ * Updated and modified by Cort Dougan (cort at cs.nmt.edu) and
++ * Paul Mackerras (paulus at cs.anu.edu.au)
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.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/config.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/elf.h>
++#include <linux/init.h>
++#include <linux/prctl.h>
++#include <linux/init_task.h>
++#include <linux/module.h>
++#include <linux/kallsyms.h>
++#include <linux/mqueue.h>
++#include <linux/hardirq.h>
++#include <linux/utsname.h>
++#include <linux/kprobes.h>
++
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/processor.h>
++#include <asm/mmu.h>
++#include <asm/prom.h>
++#ifdef CONFIG_PPC64
++#include <asm/firmware.h>
++#include <asm/plpar_wrappers.h>
++#include <asm/time.h>
++#endif
++
++extern unsigned long _get_SP(void);
++
++#ifndef CONFIG_SMP
++struct task_struct *last_task_used_math = NULL;
++struct task_struct *last_task_used_altivec = NULL;
++struct task_struct *last_task_used_spe = NULL;
++#endif
++
++/*
++ * Make sure the floating-point register state in the
++ * the thread_struct is up to date for task tsk.
++ */
++void flush_fp_to_thread(struct task_struct *tsk)
++{
++ if (tsk->thread.regs) {
++ /*
++ * We need to disable preemption here because if we didn't,
++ * another process could get scheduled after the regs->msr
++ * test but before we have finished saving the FP registers
++ * to the thread_struct. That process could take over the
++ * FPU, and then when we get scheduled again we would store
++ * bogus values for the remaining FP registers.
++ */
++ preempt_disable();
++ if (tsk->thread.regs->msr & MSR_FP) {
++#ifdef CONFIG_SMP
++ /*
++ * This should only ever be called for current or
++ * for a stopped child process. Since we save away
++ * the FP register state on context switch on SMP,
++ * there is something wrong if a stopped child appears
++ * to still have its FP state in the CPU registers.
++ */
++ BUG_ON(tsk != current);
++#endif
++ giveup_fpu(current);
++ }
++ preempt_enable();
++ }
++}
++
++void enable_kernel_fp(void)
++{
++ WARN_ON(preemptible());
++
++#ifdef CONFIG_SMP
++ if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
++ giveup_fpu(current);
++ else
++ giveup_fpu(NULL); /* just enables FP for kernel */
++#else
++ giveup_fpu(last_task_used_math);
++#endif /* CONFIG_SMP */
++}
++EXPORT_SYMBOL(enable_kernel_fp);
++
++int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
++{
++ if (!tsk->thread.regs)
++ return 0;
++ flush_fp_to_thread(current);
++
++ memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
++
++ return 1;
++}
++
++#ifdef CONFIG_ALTIVEC
++void enable_kernel_altivec(void)
++{
++ WARN_ON(preemptible());
++
++#ifdef CONFIG_SMP
++ if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
++ giveup_altivec(current);
++ else
++ giveup_altivec(NULL); /* just enable AltiVec for kernel - force */
++#else
++ giveup_altivec(last_task_used_altivec);
++#endif /* CONFIG_SMP */
++}
++EXPORT_SYMBOL(enable_kernel_altivec);
++
++/*
++ * Make sure the VMX/Altivec register state in the
++ * the thread_struct is up to date for task tsk.
++ */
++void flush_altivec_to_thread(struct task_struct *tsk)
++{
++ if (tsk->thread.regs) {
++ preempt_disable();
++ if (tsk->thread.regs->msr & MSR_VEC) {
++#ifdef CONFIG_SMP
++ BUG_ON(tsk != current);
++#endif
++ giveup_altivec(current);
++ }
++ preempt_enable();
++ }
++}
++
++int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
++{
++ flush_altivec_to_thread(current);
++ memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs));
++ return 1;
++}
++#endif /* CONFIG_ALTIVEC */
++
++#ifdef CONFIG_SPE
++
++void enable_kernel_spe(void)
++{
++ WARN_ON(preemptible());
++
++#ifdef CONFIG_SMP
++ if (current->thread.regs && (current->thread.regs->msr & MSR_SPE))
++ giveup_spe(current);
++ else
++ giveup_spe(NULL); /* just enable SPE for kernel - force */
++#else
++ giveup_spe(last_task_used_spe);
++#endif /* __SMP __ */
++}
++EXPORT_SYMBOL(enable_kernel_spe);
++
++void flush_spe_to_thread(struct task_struct *tsk)
++{
++ if (tsk->thread.regs) {
++ preempt_disable();
++ if (tsk->thread.regs->msr & MSR_SPE) {
++#ifdef CONFIG_SMP
++ BUG_ON(tsk != current);
++#endif
++ giveup_spe(current);
++ }
++ preempt_enable();
++ }
++}
++
++int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
++{
++ flush_spe_to_thread(current);
++ /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
++ memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35);
++ return 1;
++}
++#endif /* CONFIG_SPE */
++
++static void set_dabr_spr(unsigned long val)
++{
++ mtspr(SPRN_DABR, val);
++}
++
++int set_dabr(unsigned long dabr)
++{
++ int ret = 0;
++
++#ifdef CONFIG_PPC64
++ if (firmware_has_feature(FW_FEATURE_XDABR)) {
++ /* We want to catch accesses from kernel and userspace */
++ unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER;
++ ret = plpar_set_xdabr(dabr, flags);
++ } else if (firmware_has_feature(FW_FEATURE_DABR)) {
++ ret = plpar_set_dabr(dabr);
++ } else
++#endif
++ set_dabr_spr(dabr);
++
++ return ret;
++}
++
++#ifdef CONFIG_PPC64
++DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
++static DEFINE_PER_CPU(unsigned long, current_dabr);
++#endif
++
++struct task_struct *__switch_to(struct task_struct *prev,
++ struct task_struct *new)
++{
++ struct thread_struct *new_thread, *old_thread;
++ unsigned long flags;
++ struct task_struct *last;
++
++#ifdef CONFIG_SMP
++ /* avoid complexity of lazy save/restore of fpu
++ * by just saving it every time we switch out if
++ * this task used the fpu during the last quantum.
++ *
++ * If it tries to use the fpu again, it'll trap and
++ * reload its fp regs. So we don't have to do a restore
++ * every switch, just a save.
++ * -- Cort
++ */
++ if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
++ giveup_fpu(prev);
++#ifdef CONFIG_ALTIVEC
++ /*
++ * If the previous thread used altivec in the last quantum
++ * (thus changing altivec regs) then save them.
++ * We used to check the VRSAVE register but not all apps
++ * set it, so we don't rely on it now (and in fact we need
++ * to save & restore VSCR even if VRSAVE == 0). -- paulus
++ *
++ * On SMP we always save/restore altivec regs just to avoid the
++ * complexity of changing processors.
++ * -- Cort
++ */
++ if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))
++ giveup_altivec(prev);
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ /*
++ * If the previous thread used spe in the last quantum
++ * (thus changing spe regs) then save them.
++ *
++ * On SMP we always save/restore spe regs just to avoid the
++ * complexity of changing processors.
++ */
++ if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE)))
++ giveup_spe(prev);
++#endif /* CONFIG_SPE */
++
++#else /* CONFIG_SMP */
++#ifdef CONFIG_ALTIVEC
++ /* Avoid the trap. On smp this this never happens since
++ * we don't set last_task_used_altivec -- Cort
++ */
++ if (new->thread.regs && last_task_used_altivec == new)
++ new->thread.regs->msr |= MSR_VEC;
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ /* Avoid the trap. On smp this this never happens since
++ * we don't set last_task_used_spe
++ */
++ if (new->thread.regs && last_task_used_spe == new)
++ new->thread.regs->msr |= MSR_SPE;
++#endif /* CONFIG_SPE */
++
++#endif /* CONFIG_SMP */
++
++#ifdef CONFIG_PPC64 /* for now */
++ if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
++ set_dabr(new->thread.dabr);
++ __get_cpu_var(current_dabr) = new->thread.dabr;
++ }
++
++ flush_tlb_pending();
++#endif
++
++ new_thread = &new->thread;
++ old_thread = ¤t->thread;
++
++#ifdef CONFIG_PPC64
++ /*
++ * Collect processor utilization data per process
++ */
++ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
++ struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
++ long unsigned start_tb, current_tb;
++ start_tb = old_thread->start_tb;
++ cu->current_tb = current_tb = mfspr(SPRN_PURR);
++ old_thread->accum_tb += (current_tb - start_tb);
++ new_thread->start_tb = current_tb;
++ }
++#endif
++
++ local_irq_save(flags);
++ last = _switch(old_thread, new_thread);
++
++ local_irq_restore(flags);
++
++ return last;
++}
++
++static int instructions_to_print = 16;
++
++#ifdef CONFIG_PPC64
++#define BAD_PC(pc) ((REGION_ID(pc) != KERNEL_REGION_ID) && \
++ (REGION_ID(pc) != VMALLOC_REGION_ID))
++#else
++#define BAD_PC(pc) ((pc) < KERNELBASE)
++#endif
++
++static void show_instructions(struct pt_regs *regs)
++{
++ int i;
++ unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 *
++ sizeof(int));
++
++ printk("Instruction dump:");
++
++ for (i = 0; i < instructions_to_print; i++) {
++ int instr;
++
++ if (!(i % 8))
++ printk("\n");
++
++ if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) {
++ printk("XXXXXXXX ");
++ } else {
++ if (regs->nip == pc)
++ printk("<%08x> ", instr);
++ else
++ printk("%08x ", instr);
++ }
++
++ pc += sizeof(int);
++ }
++
++ printk("\n");
++}
++
++static struct regbit {
++ unsigned long bit;
++ const char *name;
++} msr_bits[] = {
++ {MSR_EE, "EE"},
++ {MSR_PR, "PR"},
++ {MSR_FP, "FP"},
++ {MSR_ME, "ME"},
++ {MSR_IR, "IR"},
++ {MSR_DR, "DR"},
++ {0, NULL}
++};
++
++static void printbits(unsigned long val, struct regbit *bits)
++{
++ const char *sep = "";
++
++ printk("<");
++ for (; bits->bit; ++bits)
++ if (val & bits->bit) {
++ printk("%s%s", sep, bits->name);
++ sep = ",";
++ }
++ printk(">");
++}
++
++#ifdef CONFIG_PPC64
++#define REG "%016lX"
++#define REGS_PER_LINE 4
++#define LAST_VOLATILE 13
++#else
++#define REG "%08lX"
++#define REGS_PER_LINE 8
++#define LAST_VOLATILE 12
++#endif
++
++void show_regs(struct pt_regs * regs)
++{
++ int i, trap;
++
++ printk("NIP: "REG" LR: "REG" CTR: "REG"\n",
++ regs->nip, regs->link, regs->ctr);
++ printk("REGS: %p TRAP: %04lx %s (%s)\n",
++ regs, regs->trap, print_tainted(), system_utsname.release);
++ printk("MSR: "REG" ", regs->msr);
++ printbits(regs->msr, msr_bits);
++ printk(" CR: %08lX XER: %08lX\n", regs->ccr, regs->xer);
++ trap = TRAP(regs);
++ if (trap == 0x300 || trap == 0x600)
++ printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
++ printk("TASK = %p[%d] '%s' THREAD: %p",
++ current, current->pid, current->comm, current->thread_info);
++
++#ifdef CONFIG_SMP
++ printk(" CPU: %d", smp_processor_id());
++#endif /* CONFIG_SMP */
++
++ for (i = 0; i < 32; i++) {
++ if ((i % REGS_PER_LINE) == 0)
++ printk("\n" KERN_INFO "GPR%02d: ", i);
++ printk(REG " ", regs->gpr[i]);
++ if (i == LAST_VOLATILE && !FULL_REGS(regs))
++ break;
++ }
++ printk("\n");
++#ifdef CONFIG_KALLSYMS
++ /*
++ * Lookup NIP late so we have the best change of getting the
++ * above info out without failing
++ */
++ printk("NIP ["REG"] ", regs->nip);
++ print_symbol("%s\n", regs->nip);
++ printk("LR ["REG"] ", regs->link);
++ print_symbol("%s\n", regs->link);
++#endif
++ show_stack(current, (unsigned long *) regs->gpr[1]);
++ if (!user_mode(regs))
++ show_instructions(regs);
++}
++
++void exit_thread(void)
++{
++ kprobe_flush_task(current);
++
++#ifndef CONFIG_SMP
++ if (last_task_used_math == current)
++ last_task_used_math = NULL;
++#ifdef CONFIG_ALTIVEC
++ if (last_task_used_altivec == current)
++ last_task_used_altivec = NULL;
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ if (last_task_used_spe == current)
++ last_task_used_spe = NULL;
++#endif
++#endif /* CONFIG_SMP */
++}
++
++void flush_thread(void)
++{
++#ifdef CONFIG_PPC64
++ struct thread_info *t = current_thread_info();
++
++ if (t->flags & _TIF_ABI_PENDING)
++ t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
++#endif
++ kprobe_flush_task(current);
++
++#ifndef CONFIG_SMP
++ if (last_task_used_math == current)
++ last_task_used_math = NULL;
++#ifdef CONFIG_ALTIVEC
++ if (last_task_used_altivec == current)
++ last_task_used_altivec = NULL;
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ if (last_task_used_spe == current)
++ last_task_used_spe = NULL;
++#endif
++#endif /* CONFIG_SMP */
++
++#ifdef CONFIG_PPC64 /* for now */
++ if (current->thread.dabr) {
++ current->thread.dabr = 0;
++ set_dabr(0);
++ }
++#endif
++}
++
++void
++release_thread(struct task_struct *t)
++{
++}
++
++/*
++ * This gets called before we allocate a new thread and copy
++ * the current task into it.
++ */
++void prepare_to_copy(struct task_struct *tsk)
++{
++ flush_fp_to_thread(current);
++ flush_altivec_to_thread(current);
++ flush_spe_to_thread(current);
++}
++
++/*
++ * Copy a thread..
++ */
++int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
++ unsigned long unused, struct task_struct *p,
++ struct pt_regs *regs)
++{
++ struct pt_regs *childregs, *kregs;
++ extern void ret_from_fork(void);
++ unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
++
++ CHECK_FULL_REGS(regs);
++ /* Copy registers */
++ sp -= sizeof(struct pt_regs);
++ childregs = (struct pt_regs *) sp;
++ *childregs = *regs;
++ if ((childregs->msr & MSR_PR) == 0) {
++ /* for kernel thread, set `current' and stackptr in new task */
++ childregs->gpr[1] = sp + sizeof(struct pt_regs);
++#ifdef CONFIG_PPC32
++ childregs->gpr[2] = (unsigned long) p;
++#else
++ clear_ti_thread_flag(p->thread_info, TIF_32BIT);
++#endif
++ p->thread.regs = NULL; /* no user register state */
++ } else {
++ childregs->gpr[1] = usp;
++ p->thread.regs = childregs;
++ if (clone_flags & CLONE_SETTLS) {
++#ifdef CONFIG_PPC64
++ if (!test_thread_flag(TIF_32BIT))
++ childregs->gpr[13] = childregs->gpr[6];
++ else
++#endif
++ childregs->gpr[2] = childregs->gpr[6];
++ }
++ }
++ childregs->gpr[3] = 0; /* Result from fork() */
++ sp -= STACK_FRAME_OVERHEAD;
++
++ /*
++ * The way this works is that at some point in the future
++ * some task will call _switch to switch to the new task.
++ * That will pop off the stack frame created below and start
++ * the new task running at ret_from_fork. The new task will
++ * do some house keeping and then return from the fork or clone
++ * system call, using the stack frame created above.
++ */
++ sp -= sizeof(struct pt_regs);
++ kregs = (struct pt_regs *) sp;
++ sp -= STACK_FRAME_OVERHEAD;
++ p->thread.ksp = sp;
++
++#ifdef CONFIG_PPC64
++ if (cpu_has_feature(CPU_FTR_SLB)) {
++ unsigned long sp_vsid = get_kernel_vsid(sp);
++
++ sp_vsid <<= SLB_VSID_SHIFT;
++ sp_vsid |= SLB_VSID_KERNEL;
++ if (cpu_has_feature(CPU_FTR_16M_PAGE))
++ sp_vsid |= SLB_VSID_L;
++
++ p->thread.ksp_vsid = sp_vsid;
++ }
++
++ /*
++ * The PPC64 ABI makes use of a TOC to contain function
++ * pointers. The function (ret_from_except) is actually a pointer
++ * to the TOC entry. The first entry is a pointer to the actual
++ * function.
++ */
++ kregs->nip = *((unsigned long *)ret_from_fork);
++#else
++ kregs->nip = (unsigned long)ret_from_fork;
++ p->thread.last_syscall = -1;
++#endif
++
++ return 0;
++}
++
++/*
++ * Set up a thread for executing a new program
++ */
++void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
++{
++#ifdef CONFIG_PPC64
++ unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */
++#endif
++
++ set_fs(USER_DS);
++
++ /*
++ * If we exec out of a kernel thread then thread.regs will not be
++ * set. Do it now.
++ */
++ if (!current->thread.regs) {
++ unsigned long childregs = (unsigned long)current->thread_info +
++ THREAD_SIZE;
++ childregs -= sizeof(struct pt_regs);
++ current->thread.regs = (struct pt_regs *)childregs;
++ }
++
++ memset(regs->gpr, 0, sizeof(regs->gpr));
++ regs->ctr = 0;
++ regs->link = 0;
++ regs->xer = 0;
++ regs->ccr = 0;
++ regs->gpr[1] = sp;
++
++#ifdef CONFIG_PPC32
++ regs->mq = 0;
++ regs->nip = start;
++ regs->msr = MSR_USER;
++#else
++ if (!test_thread_flag(TIF_32BIT)) {
++ unsigned long entry, toc;
++
++ /* start is a relocated pointer to the function descriptor for
++ * the elf _start routine. The first entry in the function
++ * descriptor is the entry address of _start and the second
++ * entry is the TOC value we need to use.
++ */
++ __get_user(entry, (unsigned long __user *)start);
++ __get_user(toc, (unsigned long __user *)start+1);
++
++ /* Check whether the e_entry function descriptor entries
++ * need to be relocated before we can use them.
++ */
++ if (load_addr != 0) {
++ entry += load_addr;
++ toc += load_addr;
++ }
++ regs->nip = entry;
++ regs->gpr[2] = toc;
++ regs->msr = MSR_USER64;
++ } else {
++ regs->nip = start;
++ regs->gpr[2] = 0;
++ regs->msr = MSR_USER32;
++ }
++#endif
++
++#ifndef CONFIG_SMP
++ if (last_task_used_math == current)
++ last_task_used_math = NULL;
++#ifdef CONFIG_ALTIVEC
++ if (last_task_used_altivec == current)
++ last_task_used_altivec = NULL;
++#endif
++#ifdef CONFIG_SPE
++ if (last_task_used_spe == current)
++ last_task_used_spe = NULL;
++#endif
++#endif /* CONFIG_SMP */
++ memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
++ current->thread.fpscr.val = 0;
++#ifdef CONFIG_ALTIVEC
++ memset(current->thread.vr, 0, sizeof(current->thread.vr));
++ memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr));
++ current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */
++ current->thread.vrsave = 0;
++ current->thread.used_vr = 0;
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ memset(current->thread.evr, 0, sizeof(current->thread.evr));
++ current->thread.acc = 0;
++ current->thread.spefscr = 0;
++ current->thread.used_spe = 0;
++#endif /* CONFIG_SPE */
++}
++
++#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \
++ | PR_FP_EXC_RES | PR_FP_EXC_INV)
++
++int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
++{
++ struct pt_regs *regs = tsk->thread.regs;
++
++ /* This is a bit hairy. If we are an SPE enabled processor
++ * (have embedded fp) we store the IEEE exception enable flags in
++ * fpexc_mode. fpexc_mode is also used for setting FP exception
++ * mode (asyn, precise, disabled) for 'Classic' FP. */
++ if (val & PR_FP_EXC_SW_ENABLE) {
++#ifdef CONFIG_SPE
++ tsk->thread.fpexc_mode = val &
++ (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);
++ return 0;
++#else
++ return -EINVAL;
++#endif
++ }
++
++ /* on a CONFIG_SPE this does not hurt us. The bits that
++ * __pack_fe01 use do not overlap with bits used for
++ * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits
++ * on CONFIG_SPE implementations are reserved so writing to
++ * them does not change anything */
++ if (val > PR_FP_EXC_PRECISE)
++ return -EINVAL;
++ tsk->thread.fpexc_mode = __pack_fe01(val);
++ if (regs != NULL && (regs->msr & MSR_FP) != 0)
++ regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
++ | tsk->thread.fpexc_mode;
++ return 0;
++}
++
++int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
++{
++ unsigned int val;
++
++ if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
++#ifdef CONFIG_SPE
++ val = tsk->thread.fpexc_mode;
++#else
++ return -EINVAL;
++#endif
++ else
++ val = __unpack_fe01(tsk->thread.fpexc_mode);
++ return put_user(val, (unsigned int __user *) adr);
++}
++
++#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
++
++int sys_clone(unsigned long clone_flags, unsigned long usp,
++ int __user *parent_tidp, void __user *child_threadptr,
++ int __user *child_tidp, int p6,
++ struct pt_regs *regs)
++{
++ CHECK_FULL_REGS(regs);
++ if (usp == 0)
++ usp = regs->gpr[1]; /* stack pointer for child */
++#ifdef CONFIG_PPC64
++ if (test_thread_flag(TIF_32BIT)) {
++ parent_tidp = TRUNC_PTR(parent_tidp);
++ child_tidp = TRUNC_PTR(child_tidp);
++ }
++#endif
++ return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
++}
++
++int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5, unsigned long p6,
++ struct pt_regs *regs)
++{
++ CHECK_FULL_REGS(regs);
++ return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
++}
++
++int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5, unsigned long p6,
++ struct pt_regs *regs)
++{
++ CHECK_FULL_REGS(regs);
++ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],
++ regs, 0, NULL, NULL);
++}
++
++int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
++ unsigned long a3, unsigned long a4, unsigned long a5,
++ struct pt_regs *regs)
++{
++ int error;
++ char *filename;
++
++ filename = getname((char __user *) a0);
++ error = PTR_ERR(filename);
++ if (IS_ERR(filename))
++ goto out;
++ flush_fp_to_thread(current);
++ flush_altivec_to_thread(current);
++ flush_spe_to_thread(current);
++ error = do_execve(filename, (char __user * __user *) a1,
++ (char __user * __user *) a2, regs);
++ if (error == 0) {
++ task_lock(current);
++ current->ptrace &= ~PT_DTRACE;
++ task_unlock(current);
++ }
++ putname(filename);
++out:
++ return error;
++}
++
++static int validate_sp(unsigned long sp, struct task_struct *p,
++ unsigned long nbytes)
++{
++ unsigned long stack_page = (unsigned long)p->thread_info;
++
++ if (sp >= stack_page + sizeof(struct thread_struct)
++ && sp <= stack_page + THREAD_SIZE - nbytes)
++ return 1;
++
++#ifdef CONFIG_IRQSTACKS
++ stack_page = (unsigned long) hardirq_ctx[task_cpu(p)];
++ if (sp >= stack_page + sizeof(struct thread_struct)
++ && sp <= stack_page + THREAD_SIZE - nbytes)
++ return 1;
++
++ stack_page = (unsigned long) softirq_ctx[task_cpu(p)];
++ if (sp >= stack_page + sizeof(struct thread_struct)
++ && sp <= stack_page + THREAD_SIZE - nbytes)
++ return 1;
++#endif
++
++ return 0;
++}
++
++#ifdef CONFIG_PPC64
++#define MIN_STACK_FRAME 112 /* same as STACK_FRAME_OVERHEAD, in fact */
++#define FRAME_LR_SAVE 2
++#define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288)
++#define REGS_MARKER 0x7265677368657265ul
++#define FRAME_MARKER 12
++#else
++#define MIN_STACK_FRAME 16
++#define FRAME_LR_SAVE 1
++#define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
++#define REGS_MARKER 0x72656773ul
++#define FRAME_MARKER 2
++#endif
++
++unsigned long get_wchan(struct task_struct *p)
++{
++ unsigned long ip, sp;
++ int count = 0;
++
++ if (!p || p == current || p->state == TASK_RUNNING)
++ return 0;
++
++ sp = p->thread.ksp;
++ if (!validate_sp(sp, p, MIN_STACK_FRAME))
++ return 0;
++
++ do {
++ sp = *(unsigned long *)sp;
++ if (!validate_sp(sp, p, MIN_STACK_FRAME))
++ return 0;
++ if (count > 0) {
++ ip = ((unsigned long *)sp)[FRAME_LR_SAVE];
++ if (!in_sched_functions(ip))
++ return ip;
++ }
++ } while (count++ < 16);
++ return 0;
++}
++EXPORT_SYMBOL(get_wchan);
++
++static int kstack_depth_to_print = 64;
++
++void show_stack(struct task_struct *tsk, unsigned long *stack)
++{
++ unsigned long sp, ip, lr, newsp;
++ int count = 0;
++ int firstframe = 1;
++
++ sp = (unsigned long) stack;
++ if (tsk == NULL)
++ tsk = current;
++ if (sp == 0) {
++ if (tsk == current)
++ asm("mr %0,1" : "=r" (sp));
++ else
++ sp = tsk->thread.ksp;
++ }
++
++ lr = 0;
++ printk("Call Trace:\n");
++ do {
++ if (!validate_sp(sp, tsk, MIN_STACK_FRAME))
++ return;
++
++ stack = (unsigned long *) sp;
++ newsp = stack[0];
++ ip = stack[FRAME_LR_SAVE];
++ if (!firstframe || ip != lr) {
++ printk("["REG"] ["REG"] ", sp, ip);
++ print_symbol("%s", ip);
++ if (firstframe)
++ printk(" (unreliable)");
++ printk("\n");
++ }
++ firstframe = 0;
++
++ /*
++ * See if this is an exception frame.
++ * We look for the "regshere" marker in the current frame.
++ */
++ if (validate_sp(sp, tsk, INT_FRAME_SIZE)
++ && stack[FRAME_MARKER] == REGS_MARKER) {
++ struct pt_regs *regs = (struct pt_regs *)
++ (sp + STACK_FRAME_OVERHEAD);
++ printk("--- Exception: %lx", regs->trap);
++ print_symbol(" at %s\n", regs->nip);
++ lr = regs->link;
++ print_symbol(" LR = %s\n", lr);
++ firstframe = 1;
++ }
++
++ sp = newsp;
++ } while (count++ < kstack_depth_to_print);
++}
++
++void dump_stack(void)
++{
++ show_stack(current, NULL);
++}
++EXPORT_SYMBOL(dump_stack);
+diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/prom.c
+@@ -0,0 +1,2170 @@
++/*
++ * Procedures for creating, accessing and interpreting the device tree.
++ *
++ * Paul Mackerras August 1996.
++ * Copyright (C) 1996-2005 Paul Mackerras.
++ *
++ * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
++ * {engebret|bergner}@us.ibm.com
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#undef DEBUG
++
++#include <stdarg.h>
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/threads.h>
++#include <linux/spinlock.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/stringify.h>
++#include <linux/delay.h>
++#include <linux/initrd.h>
++#include <linux/bitops.h>
++#include <linux/module.h>
++
++#include <asm/prom.h>
++#include <asm/rtas.h>
++#include <asm/lmb.h>
++#include <asm/page.h>
++#include <asm/processor.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/system.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/pci.h>
++#include <asm/iommu.h>
++#include <asm/btext.h>
++#include <asm/sections.h>
++#include <asm/machdep.h>
++#include <asm/pSeries_reconfig.h>
++#include <asm/pci-bridge.h>
++#ifdef CONFIG_PPC64
++#include <asm/systemcfg.h>
++#endif
++
++#ifdef DEBUG
++#define DBG(fmt...) printk(KERN_ERR fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++struct pci_reg_property {
++ struct pci_address addr;
++ u32 size_hi;
++ u32 size_lo;
++};
++
++struct isa_reg_property {
++ u32 space;
++ u32 address;
++ u32 size;
++};
++
++
++typedef int interpret_func(struct device_node *, unsigned long *,
++ int, int, int);
++
++extern struct rtas_t rtas;
++extern struct lmb lmb;
++extern unsigned long klimit;
++
++static int __initdata dt_root_addr_cells;
++static int __initdata dt_root_size_cells;
++
++#ifdef CONFIG_PPC64
++static int __initdata iommu_is_off;
++int __initdata iommu_force_on;
++unsigned long tce_alloc_start, tce_alloc_end;
++#endif
++
++typedef u32 cell_t;
++
++#if 0
++static struct boot_param_header *initial_boot_params __initdata;
++#else
++struct boot_param_header *initial_boot_params;
++#endif
++
++static struct device_node *allnodes = NULL;
++
++/* use when traversing tree through the allnext, child, sibling,
++ * or parent members of struct device_node.
++ */
++static DEFINE_RWLOCK(devtree_lock);
++
++/* export that to outside world */
++struct device_node *of_chosen;
++
++struct device_node *dflt_interrupt_controller;
++int num_interrupt_controllers;
++
++/*
++ * Wrapper for allocating memory for various data that needs to be
++ * attached to device nodes as they are processed at boot or when
++ * added to the device tree later (e.g. DLPAR). At boot there is
++ * already a region reserved so we just increment *mem_start by size;
++ * otherwise we call kmalloc.
++ */
++static void * prom_alloc(unsigned long size, unsigned long *mem_start)
++{
++ unsigned long tmp;
++
++ if (!mem_start)
++ return kmalloc(size, GFP_KERNEL);
++
++ tmp = *mem_start;
++ *mem_start += size;
++ return (void *)tmp;
++}
++
++/*
++ * Find the device_node with a given phandle.
++ */
++static struct device_node * find_phandle(phandle ph)
++{
++ struct device_node *np;
++
++ for (np = allnodes; np != 0; np = np->allnext)
++ if (np->linux_phandle == ph)
++ return np;
++ return NULL;
++}
++
++/*
++ * Find the interrupt parent of a node.
++ */
++static struct device_node * __devinit intr_parent(struct device_node *p)
++{
++ phandle *parp;
++
++ parp = (phandle *) get_property(p, "interrupt-parent", NULL);
++ if (parp == NULL)
++ return p->parent;
++ p = find_phandle(*parp);
++ if (p != NULL)
++ return p;
++ /*
++ * On a powermac booted with BootX, we don't get to know the
++ * phandles for any nodes, so find_phandle will return NULL.
++ * Fortunately these machines only have one interrupt controller
++ * so there isn't in fact any ambiguity. -- paulus
++ */
++ if (num_interrupt_controllers == 1)
++ p = dflt_interrupt_controller;
++ return p;
++}
++
++/*
++ * Find out the size of each entry of the interrupts property
++ * for a node.
++ */
++int __devinit prom_n_intr_cells(struct device_node *np)
++{
++ struct device_node *p;
++ unsigned int *icp;
++
++ for (p = np; (p = intr_parent(p)) != NULL; ) {
++ icp = (unsigned int *)
++ get_property(p, "#interrupt-cells", NULL);
++ if (icp != NULL)
++ return *icp;
++ if (get_property(p, "interrupt-controller", NULL) != NULL
++ || get_property(p, "interrupt-map", NULL) != NULL) {
++ printk("oops, node %s doesn't have #interrupt-cells\n",
++ p->full_name);
++ return 1;
++ }
++ }
++#ifdef DEBUG_IRQ
++ printk("prom_n_intr_cells failed for %s\n", np->full_name);
++#endif
++ return 1;
++}
++
++/*
++ * Map an interrupt from a device up to the platform interrupt
++ * descriptor.
++ */
++static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler,
++ struct device_node *np, unsigned int *ints,
++ int nintrc)
++{
++ struct device_node *p, *ipar;
++ unsigned int *imap, *imask, *ip;
++ int i, imaplen, match;
++ int newintrc = 0, newaddrc = 0;
++ unsigned int *reg;
++ int naddrc;
++
++ reg = (unsigned int *) get_property(np, "reg", NULL);
++ naddrc = prom_n_addr_cells(np);
++ p = intr_parent(np);
++ while (p != NULL) {
++ if (get_property(p, "interrupt-controller", NULL) != NULL)
++ /* this node is an interrupt controller, stop here */
++ break;
++ imap = (unsigned int *)
++ get_property(p, "interrupt-map", &imaplen);
++ if (imap == NULL) {
++ p = intr_parent(p);
++ continue;
++ }
++ imask = (unsigned int *)
++ get_property(p, "interrupt-map-mask", NULL);
++ if (imask == NULL) {
++ printk("oops, %s has interrupt-map but no mask\n",
++ p->full_name);
++ return 0;
++ }
++ imaplen /= sizeof(unsigned int);
++ match = 0;
++ ipar = NULL;
++ while (imaplen > 0 && !match) {
++ /* check the child-interrupt field */
++ match = 1;
++ for (i = 0; i < naddrc && match; ++i)
++ match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
++ for (; i < naddrc + nintrc && match; ++i)
++ match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
++ imap += naddrc + nintrc;
++ imaplen -= naddrc + nintrc;
++ /* grab the interrupt parent */
++ ipar = find_phandle((phandle) *imap++);
++ --imaplen;
++ if (ipar == NULL && num_interrupt_controllers == 1)
++ /* cope with BootX not giving us phandles */
++ ipar = dflt_interrupt_controller;
++ if (ipar == NULL) {
++ printk("oops, no int parent %x in map of %s\n",
++ imap[-1], p->full_name);
++ return 0;
++ }
++ /* find the parent's # addr and intr cells */
++ ip = (unsigned int *)
++ get_property(ipar, "#interrupt-cells", NULL);
++ if (ip == NULL) {
++ printk("oops, no #interrupt-cells on %s\n",
++ ipar->full_name);
++ return 0;
++ }
++ newintrc = *ip;
++ ip = (unsigned int *)
++ get_property(ipar, "#address-cells", NULL);
++ newaddrc = (ip == NULL)? 0: *ip;
++ imap += newaddrc + newintrc;
++ imaplen -= newaddrc + newintrc;
++ }
++ if (imaplen < 0) {
++ printk("oops, error decoding int-map on %s, len=%d\n",
++ p->full_name, imaplen);
++ return 0;
++ }
++ if (!match) {
++#ifdef DEBUG_IRQ
++ printk("oops, no match in %s int-map for %s\n",
++ p->full_name, np->full_name);
++#endif
++ return 0;
++ }
++ p = ipar;
++ naddrc = newaddrc;
++ nintrc = newintrc;
++ ints = imap - nintrc;
++ reg = ints - naddrc;
++ }
++ if (p == NULL) {
++#ifdef DEBUG_IRQ
++ printk("hmmm, int tree for %s doesn't have ctrler\n",
++ np->full_name);
++#endif
++ return 0;
++ }
++ *irq = ints;
++ *ictrler = p;
++ return nintrc;
++}
++
++static unsigned char map_isa_senses[4] = {
++ IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
++ IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
++ IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
++ IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE
++};
++
++static unsigned char map_mpic_senses[4] = {
++ IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE,
++ IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
++ /* 2 seems to be used for the 8259 cascade... */
++ IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
++ IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
++};
++
++static int __devinit finish_node_interrupts(struct device_node *np,
++ unsigned long *mem_start,
++ int measure_only)
++{
++ unsigned int *ints;
++ int intlen, intrcells, intrcount;
++ int i, j, n, sense;
++ unsigned int *irq, virq;
++ struct device_node *ic;
++
++ if (num_interrupt_controllers == 0) {
++ /*
++ * Old machines just have a list of interrupt numbers
++ * and no interrupt-controller nodes.
++ */
++ ints = (unsigned int *) get_property(np, "AAPL,interrupts",
++ &intlen);
++ /* XXX old interpret_pci_props looked in parent too */
++ /* XXX old interpret_macio_props looked for interrupts
++ before AAPL,interrupts */
++ if (ints == NULL)
++ ints = (unsigned int *) get_property(np, "interrupts",
++ &intlen);
++ if (ints == NULL)
++ return 0;
++
++ np->n_intrs = intlen / sizeof(unsigned int);
++ np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]),
++ mem_start);
++ if (!np->intrs)
++ return -ENOMEM;
++ if (measure_only)
++ return 0;
++
++ for (i = 0; i < np->n_intrs; ++i) {
++ np->intrs[i].line = *ints++;
++ np->intrs[i].sense = IRQ_SENSE_LEVEL
++ | IRQ_POLARITY_NEGATIVE;
++ }
++ return 0;
++ }
++
++ ints = (unsigned int *) get_property(np, "interrupts", &intlen);
++ if (ints == NULL)
++ return 0;
++ intrcells = prom_n_intr_cells(np);
++ intlen /= intrcells * sizeof(unsigned int);
++
++ np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start);
++ if (!np->intrs)
++ return -ENOMEM;
++
++ if (measure_only)
++ return 0;
++
++ intrcount = 0;
++ for (i = 0; i < intlen; ++i, ints += intrcells) {
++ n = map_interrupt(&irq, &ic, np, ints, intrcells);
++ if (n <= 0)
++ continue;
++
++ /* don't map IRQ numbers under a cascaded 8259 controller */
++ if (ic && device_is_compatible(ic, "chrp,iic")) {
++ np->intrs[intrcount].line = irq[0];
++ sense = (n > 1)? (irq[1] & 3): 3;
++ np->intrs[intrcount].sense = map_isa_senses[sense];
++ } else {
++ virq = virt_irq_create_mapping(irq[0]);
++#ifdef CONFIG_PPC64
++ if (virq == NO_IRQ) {
++ printk(KERN_CRIT "Could not allocate interrupt"
++ " number for %s\n", np->full_name);
++ continue;
++ }
++#endif
++ np->intrs[intrcount].line = irq_offset_up(virq);
++ sense = (n > 1)? (irq[1] & 3): 1;
++ np->intrs[intrcount].sense = map_mpic_senses[sense];
++ }
++
++#ifdef CONFIG_PPC64
++ /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
++ if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) {
++ char *name = get_property(ic->parent, "name", NULL);
++ if (name && !strcmp(name, "u3"))
++ np->intrs[intrcount].line += 128;
++ else if (!(name && !strcmp(name, "mac-io")))
++ /* ignore other cascaded controllers, such as
++ the k2-sata-root */
++ break;
++ }
++#endif
++ if (n > 2) {
++ printk("hmmm, got %d intr cells for %s:", n,
++ np->full_name);
++ for (j = 0; j < n; ++j)
++ printk(" %d", irq[j]);
++ printk("\n");
++ }
++ ++intrcount;
++ }
++ np->n_intrs = intrcount;
++
++ return 0;
++}
++
++static int __devinit interpret_pci_props(struct device_node *np,
++ unsigned long *mem_start,
++ int naddrc, int nsizec,
++ int measure_only)
++{
++ struct address_range *adr;
++ struct pci_reg_property *pci_addrs;
++ int i, l, n_addrs;
++
++ pci_addrs = (struct pci_reg_property *)
++ get_property(np, "assigned-addresses", &l);
++ if (!pci_addrs)
++ return 0;
++
++ n_addrs = l / sizeof(*pci_addrs);
++
++ adr = prom_alloc(n_addrs * sizeof(*adr), mem_start);
++ if (!adr)
++ return -ENOMEM;
++
++ if (measure_only)
++ return 0;
++
++ np->addrs = adr;
++ np->n_addrs = n_addrs;
++
++ for (i = 0; i < n_addrs; i++) {
++ adr[i].space = pci_addrs[i].addr.a_hi;
++ adr[i].address = pci_addrs[i].addr.a_lo |
++ ((u64)pci_addrs[i].addr.a_mid << 32);
++ adr[i].size = pci_addrs[i].size_lo;
++ }
++
++ return 0;
++}
++
++static int __init interpret_dbdma_props(struct device_node *np,
++ unsigned long *mem_start,
++ int naddrc, int nsizec,
++ int measure_only)
++{
++ struct reg_property32 *rp;
++ struct address_range *adr;
++ unsigned long base_address;
++ int i, l;
++ struct device_node *db;
++
++ base_address = 0;
++ if (!measure_only) {
++ for (db = np->parent; db != NULL; db = db->parent) {
++ if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
++ base_address = db->addrs[0].address;
++ break;
++ }
++ }
++ }
++
++ rp = (struct reg_property32 *) get_property(np, "reg", &l);
++ if (rp != 0 && l >= sizeof(struct reg_property32)) {
++ i = 0;
++ adr = (struct address_range *) (*mem_start);
++ while ((l -= sizeof(struct reg_property32)) >= 0) {
++ if (!measure_only) {
++ adr[i].space = 2;
++ adr[i].address = rp[i].address + base_address;
++ adr[i].size = rp[i].size;
++ }
++ ++i;
++ }
++ np->addrs = adr;
++ np->n_addrs = i;
++ (*mem_start) += i * sizeof(struct address_range);
++ }
++
++ return 0;
++}
++
++static int __init interpret_macio_props(struct device_node *np,
++ unsigned long *mem_start,
++ int naddrc, int nsizec,
++ int measure_only)
++{
++ struct reg_property32 *rp;
++ struct address_range *adr;
++ unsigned long base_address;
++ int i, l;
++ struct device_node *db;
++
++ base_address = 0;
++ if (!measure_only) {
++ for (db = np->parent; db != NULL; db = db->parent) {
++ if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
++ base_address = db->addrs[0].address;
++ break;
++ }
++ }
++ }
++
++ rp = (struct reg_property32 *) get_property(np, "reg", &l);
++ if (rp != 0 && l >= sizeof(struct reg_property32)) {
++ i = 0;
++ adr = (struct address_range *) (*mem_start);
++ while ((l -= sizeof(struct reg_property32)) >= 0) {
++ if (!measure_only) {
++ adr[i].space = 2;
++ adr[i].address = rp[i].address + base_address;
++ adr[i].size = rp[i].size;
++ }
++ ++i;
++ }
++ np->addrs = adr;
++ np->n_addrs = i;
++ (*mem_start) += i * sizeof(struct address_range);
++ }
++
++ return 0;
++}
++
++static int __init interpret_isa_props(struct device_node *np,
++ unsigned long *mem_start,
++ int naddrc, int nsizec,
++ int measure_only)
++{
++ struct isa_reg_property *rp;
++ struct address_range *adr;
++ int i, l;
++
++ rp = (struct isa_reg_property *) get_property(np, "reg", &l);
++ if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
++ i = 0;
++ adr = (struct address_range *) (*mem_start);
++ while ((l -= sizeof(struct isa_reg_property)) >= 0) {
++ if (!measure_only) {
++ adr[i].space = rp[i].space;
++ adr[i].address = rp[i].address;
++ adr[i].size = rp[i].size;
++ }
++ ++i;
++ }
++ np->addrs = adr;
++ np->n_addrs = i;
++ (*mem_start) += i * sizeof(struct address_range);
++ }
++
++ return 0;
++}
++
++static int __init interpret_root_props(struct device_node *np,
++ unsigned long *mem_start,
++ int naddrc, int nsizec,
++ int measure_only)
++{
++ struct address_range *adr;
++ int i, l;
++ unsigned int *rp;
++ int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
++
++ rp = (unsigned int *) get_property(np, "reg", &l);
++ if (rp != 0 && l >= rpsize) {
++ i = 0;
++ adr = (struct address_range *) (*mem_start);
++ while ((l -= rpsize) >= 0) {
++ if (!measure_only) {
++ adr[i].space = 0;
++ adr[i].address = rp[naddrc - 1];
++ adr[i].size = rp[naddrc + nsizec - 1];
++ }
++ ++i;
++ rp += naddrc + nsizec;
++ }
++ np->addrs = adr;
++ np->n_addrs = i;
++ (*mem_start) += i * sizeof(struct address_range);
++ }
++
++ return 0;
++}
++
++static int __devinit finish_node(struct device_node *np,
++ unsigned long *mem_start,
++ interpret_func *ifunc,
++ int naddrc, int nsizec,
++ int measure_only)
++{
++ struct device_node *child;
++ int *ip, rc = 0;
++
++ /* get the device addresses and interrupts */
++ if (ifunc != NULL)
++ rc = ifunc(np, mem_start, naddrc, nsizec, measure_only);
++ if (rc)
++ goto out;
++
++ rc = finish_node_interrupts(np, mem_start, measure_only);
++ if (rc)
++ goto out;
++
++ /* Look for #address-cells and #size-cells properties. */
++ ip = (int *) get_property(np, "#address-cells", NULL);
++ if (ip != NULL)
++ naddrc = *ip;
++ ip = (int *) get_property(np, "#size-cells", NULL);
++ if (ip != NULL)
++ nsizec = *ip;
++
++ if (!strcmp(np->name, "device-tree") || np->parent == NULL)
++ ifunc = interpret_root_props;
++ else if (np->type == 0)
++ ifunc = NULL;
++ else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
++ ifunc = interpret_pci_props;
++ else if (!strcmp(np->type, "dbdma"))
++ ifunc = interpret_dbdma_props;
++ else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props)
++ ifunc = interpret_macio_props;
++ else if (!strcmp(np->type, "isa"))
++ ifunc = interpret_isa_props;
++ else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
++ ifunc = interpret_root_props;
++ else if (!((ifunc == interpret_dbdma_props
++ || ifunc == interpret_macio_props)
++ && (!strcmp(np->type, "escc")
++ || !strcmp(np->type, "media-bay"))))
++ ifunc = NULL;
++
++ for (child = np->child; child != NULL; child = child->sibling) {
++ rc = finish_node(child, mem_start, ifunc,
++ naddrc, nsizec, measure_only);
++ if (rc)
++ goto out;
++ }
++out:
++ return rc;
++}
++
++static void __init scan_interrupt_controllers(void)
++{
++ struct device_node *np;
++ int n = 0;
++ char *name, *ic;
++ int iclen;
++
++ for (np = allnodes; np != NULL; np = np->allnext) {
++ ic = get_property(np, "interrupt-controller", &iclen);
++ name = get_property(np, "name", NULL);
++ /* checking iclen makes sure we don't get a false
++ match on /chosen.interrupt_controller */
++ if ((name != NULL
++ && strcmp(name, "interrupt-controller") == 0)
++ || (ic != NULL && iclen == 0
++ && strcmp(name, "AppleKiwi"))) {
++ if (n == 0)
++ dflt_interrupt_controller = np;
++ ++n;
++ }
++ }
++ num_interrupt_controllers = n;
++}
++
++/**
++ * finish_device_tree is called once things are running normally
++ * (i.e. with text and data mapped to the address they were linked at).
++ * It traverses the device tree and fills in some of the additional,
++ * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt
++ * mapping is also initialized at this point.
++ */
++void __init finish_device_tree(void)
++{
++ unsigned long start, end, size = 0;
++
++ DBG(" -> finish_device_tree\n");
++
++#ifdef CONFIG_PPC64
++ /* Initialize virtual IRQ map */
++ virt_irq_init();
++#endif
++ scan_interrupt_controllers();
++
++ /*
++ * Finish device-tree (pre-parsing some properties etc...)
++ * We do this in 2 passes. One with "measure_only" set, which
++ * will only measure the amount of memory needed, then we can
++ * allocate that memory, and call finish_node again. However,
++ * we must be careful as most routines will fail nowadays when
++ * prom_alloc() returns 0, so we must make sure our first pass
++ * doesn't start at 0. We pre-initialize size to 16 for that
++ * reason and then remove those additional 16 bytes
++ */
++ size = 16;
++ finish_node(allnodes, &size, NULL, 0, 0, 1);
++ size -= 16;
++ end = start = (unsigned long) __va(lmb_alloc(size, 128));
++ finish_node(allnodes, &end, NULL, 0, 0, 0);
++ BUG_ON(end != start + size);
++
++ DBG(" <- finish_device_tree\n");
++}
++
++static inline char *find_flat_dt_string(u32 offset)
++{
++ return ((char *)initial_boot_params) +
++ initial_boot_params->off_dt_strings + offset;
++}
++
++/**
++ * This function is used to scan the flattened device-tree, it is
++ * used to extract the memory informations at boot before we can
++ * unflatten the tree
++ */
++static int __init scan_flat_dt(int (*it)(unsigned long node,
++ const char *uname, int depth,
++ void *data),
++ void *data)
++{
++ unsigned long p = ((unsigned long)initial_boot_params) +
++ initial_boot_params->off_dt_struct;
++ int rc = 0;
++ int depth = -1;
++
++ do {
++ u32 tag = *((u32 *)p);
++ char *pathp;
++
++ p += 4;
++ if (tag == OF_DT_END_NODE) {
++ depth --;
++ continue;
++ }
++ if (tag == OF_DT_NOP)
++ continue;
++ if (tag == OF_DT_END)
++ break;
++ if (tag == OF_DT_PROP) {
++ u32 sz = *((u32 *)p);
++ p += 8;
++ if (initial_boot_params->version < 0x10)
++ p = _ALIGN(p, sz >= 8 ? 8 : 4);
++ p += sz;
++ p = _ALIGN(p, 4);
++ continue;
++ }
++ if (tag != OF_DT_BEGIN_NODE) {
++ printk(KERN_WARNING "Invalid tag %x scanning flattened"
++ " device tree !\n", tag);
++ return -EINVAL;
++ }
++ depth++;
++ pathp = (char *)p;
++ p = _ALIGN(p + strlen(pathp) + 1, 4);
++ if ((*pathp) == '/') {
++ char *lp, *np;
++ for (lp = NULL, np = pathp; *np; np++)
++ if ((*np) == '/')
++ lp = np+1;
++ if (lp != NULL)
++ pathp = lp;
++ }
++ rc = it(p, pathp, depth, data);
++ if (rc != 0)
++ break;
++ } while(1);
++
++ return rc;
++}
++
++/**
++ * This function can be used within scan_flattened_dt callback to get
++ * access to properties
++ */
++static void* __init get_flat_dt_prop(unsigned long node, const char *name,
++ unsigned long *size)
++{
++ unsigned long p = node;
++
++ do {
++ u32 tag = *((u32 *)p);
++ u32 sz, noff;
++ const char *nstr;
++
++ p += 4;
++ if (tag == OF_DT_NOP)
++ continue;
++ if (tag != OF_DT_PROP)
++ return NULL;
++
++ sz = *((u32 *)p);
++ noff = *((u32 *)(p + 4));
++ p += 8;
++ if (initial_boot_params->version < 0x10)
++ p = _ALIGN(p, sz >= 8 ? 8 : 4);
++
++ nstr = find_flat_dt_string(noff);
++ if (nstr == NULL) {
++ printk(KERN_WARNING "Can't find property index"
++ " name !\n");
++ return NULL;
++ }
++ if (strcmp(name, nstr) == 0) {
++ if (size)
++ *size = sz;
++ return (void *)p;
++ }
++ p += sz;
++ p = _ALIGN(p, 4);
++ } while(1);
++}
++
++static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
++ unsigned long align)
++{
++ void *res;
++
++ *mem = _ALIGN(*mem, align);
++ res = (void *)*mem;
++ *mem += size;
++
++ return res;
++}
++
++static unsigned long __init unflatten_dt_node(unsigned long mem,
++ unsigned long *p,
++ struct device_node *dad,
++ struct device_node ***allnextpp,
++ unsigned long fpsize)
++{
++ struct device_node *np;
++ struct property *pp, **prev_pp = NULL;
++ char *pathp;
++ u32 tag;
++ unsigned int l, allocl;
++ int has_name = 0;
++ int new_format = 0;
++
++ tag = *((u32 *)(*p));
++ if (tag != OF_DT_BEGIN_NODE) {
++ printk("Weird tag at start of node: %x\n", tag);
++ return mem;
++ }
++ *p += 4;
++ pathp = (char *)*p;
++ l = allocl = strlen(pathp) + 1;
++ *p = _ALIGN(*p + l, 4);
++
++ /* version 0x10 has a more compact unit name here instead of the full
++ * path. we accumulate the full path size using "fpsize", we'll rebuild
++ * it later. We detect this because the first character of the name is
++ * not '/'.
++ */
++ if ((*pathp) != '/') {
++ new_format = 1;
++ if (fpsize == 0) {
++ /* root node: special case. fpsize accounts for path
++ * plus terminating zero. root node only has '/', so
++ * fpsize should be 2, but we want to avoid the first
++ * level nodes to have two '/' so we use fpsize 1 here
++ */
++ fpsize = 1;
++ allocl = 2;
++ } else {
++ /* account for '/' and path size minus terminal 0
++ * already in 'l'
++ */
++ fpsize += l;
++ allocl = fpsize;
++ }
++ }
++
++
++ np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
++ __alignof__(struct device_node));
++ if (allnextpp) {
++ memset(np, 0, sizeof(*np));
++ np->full_name = ((char*)np) + sizeof(struct device_node);
++ if (new_format) {
++ char *p = np->full_name;
++ /* rebuild full path for new format */
++ if (dad && dad->parent) {
++ strcpy(p, dad->full_name);
++#ifdef DEBUG
++ if ((strlen(p) + l + 1) != allocl) {
++ DBG("%s: p: %d, l: %d, a: %d\n",
++ pathp, strlen(p), l, allocl);
++ }
++#endif
++ p += strlen(p);
++ }
++ *(p++) = '/';
++ memcpy(p, pathp, l);
++ } else
++ memcpy(np->full_name, pathp, l);
++ prev_pp = &np->properties;
++ **allnextpp = np;
++ *allnextpp = &np->allnext;
++ if (dad != NULL) {
++ np->parent = dad;
++ /* we temporarily use the next field as `last_child'*/
++ if (dad->next == 0)
++ dad->child = np;
++ else
++ dad->next->sibling = np;
++ dad->next = np;
++ }
++ kref_init(&np->kref);
++ }
++ while(1) {
++ u32 sz, noff;
++ char *pname;
++
++ tag = *((u32 *)(*p));
++ if (tag == OF_DT_NOP) {
++ *p += 4;
++ continue;
++ }
++ if (tag != OF_DT_PROP)
++ break;
++ *p += 4;
++ sz = *((u32 *)(*p));
++ noff = *((u32 *)((*p) + 4));
++ *p += 8;
++ if (initial_boot_params->version < 0x10)
++ *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
++
++ pname = find_flat_dt_string(noff);
++ if (pname == NULL) {
++ printk("Can't find property name in list !\n");
++ break;
++ }
++ if (strcmp(pname, "name") == 0)
++ has_name = 1;
++ l = strlen(pname) + 1;
++ pp = unflatten_dt_alloc(&mem, sizeof(struct property),
++ __alignof__(struct property));
++ if (allnextpp) {
++ if (strcmp(pname, "linux,phandle") == 0) {
++ np->node = *((u32 *)*p);
++ if (np->linux_phandle == 0)
++ np->linux_phandle = np->node;
++ }
++ if (strcmp(pname, "ibm,phandle") == 0)
++ np->linux_phandle = *((u32 *)*p);
++ pp->name = pname;
++ pp->length = sz;
++ pp->value = (void *)*p;
++ *prev_pp = pp;
++ prev_pp = &pp->next;
++ }
++ *p = _ALIGN((*p) + sz, 4);
++ }
++ /* with version 0x10 we may not have the name property, recreate
++ * it here from the unit name if absent
++ */
++ if (!has_name) {
++ char *p = pathp, *ps = pathp, *pa = NULL;
++ int sz;
++
++ while (*p) {
++ if ((*p) == '@')
++ pa = p;
++ if ((*p) == '/')
++ ps = p + 1;
++ p++;
++ }
++ if (pa < ps)
++ pa = p;
++ sz = (pa - ps) + 1;
++ pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
++ __alignof__(struct property));
++ if (allnextpp) {
++ pp->name = "name";
++ pp->length = sz;
++ pp->value = (unsigned char *)(pp + 1);
++ *prev_pp = pp;
++ prev_pp = &pp->next;
++ memcpy(pp->value, ps, sz - 1);
++ ((char *)pp->value)[sz - 1] = 0;
++ DBG("fixed up name for %s -> %s\n", pathp, pp->value);
++ }
++ }
++ if (allnextpp) {
++ *prev_pp = NULL;
++ np->name = get_property(np, "name", NULL);
++ np->type = get_property(np, "device_type", NULL);
++
++ if (!np->name)
++ np->name = "<NULL>";
++ if (!np->type)
++ np->type = "<NULL>";
++ }
++ while (tag == OF_DT_BEGIN_NODE) {
++ mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
++ tag = *((u32 *)(*p));
++ }
++ if (tag != OF_DT_END_NODE) {
++ printk("Weird tag at end of node: %x\n", tag);
++ return mem;
++ }
++ *p += 4;
++ return mem;
++}
++
++
++/**
++ * unflattens the device-tree passed by the firmware, creating the
++ * tree of struct device_node. It also fills the "name" and "type"
++ * pointers of the nodes so the normal device-tree walking functions
++ * can be used (this used to be done by finish_device_tree)
++ */
++void __init unflatten_device_tree(void)
++{
++ unsigned long start, mem, size;
++ struct device_node **allnextp = &allnodes;
++ char *p = NULL;
++ int l = 0;
++
++ DBG(" -> unflatten_device_tree()\n");
++
++ /* First pass, scan for size */
++ start = ((unsigned long)initial_boot_params) +
++ initial_boot_params->off_dt_struct;
++ size = unflatten_dt_node(0, &start, NULL, NULL, 0);
++ size = (size | 3) + 1;
++
++ DBG(" size is %lx, allocating...\n", size);
++
++ /* Allocate memory for the expanded device tree */
++ mem = lmb_alloc(size + 4, __alignof__(struct device_node));
++ if (!mem) {
++ DBG("Couldn't allocate memory with lmb_alloc()!\n");
++ panic("Couldn't allocate memory with lmb_alloc()!\n");
++ }
++ mem = (unsigned long) __va(mem);
++
++ ((u32 *)mem)[size / 4] = 0xdeadbeef;
++
++ DBG(" unflattening %lx...\n", mem);
++
++ /* Second pass, do actual unflattening */
++ start = ((unsigned long)initial_boot_params) +
++ initial_boot_params->off_dt_struct;
++ unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
++ if (*((u32 *)start) != OF_DT_END)
++ printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));
++ if (((u32 *)mem)[size / 4] != 0xdeadbeef)
++ printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
++ ((u32 *)mem)[size / 4] );
++ *allnextp = NULL;
++
++ /* Get pointer to OF "/chosen" node for use everywhere */
++ of_chosen = of_find_node_by_path("/chosen");
++ if (of_chosen == NULL)
++ of_chosen = of_find_node_by_path("/chosen at 0");
++
++ /* Retreive command line */
++ if (of_chosen != NULL) {
++ p = (char *)get_property(of_chosen, "bootargs", &l);
++ if (p != NULL && l > 0)
++ strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE));
++ }
++#ifdef CONFIG_CMDLINE
++ if (l == 0 || (l == 1 && (*p) == 0))
++ strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
++#endif /* CONFIG_CMDLINE */
++
++ DBG("Command line is: %s\n", cmd_line);
++
++ DBG(" <- unflatten_device_tree()\n");
++}
++
++
++static int __init early_init_dt_scan_cpus(unsigned long node,
++ const char *uname, int depth, void *data)
++{
++ char *type = get_flat_dt_prop(node, "device_type", NULL);
++ u32 *prop;
++ unsigned long size = 0;
++
++ /* We are scanning "cpu" nodes only */
++ if (type == NULL || strcmp(type, "cpu") != 0)
++ return 0;
++
++#ifdef CONFIG_PPC_PSERIES
++ /* On LPAR, look for the first ibm,pft-size property for the hash table size
++ */
++ if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) {
++ u32 *pft_size;
++ pft_size = get_flat_dt_prop(node, "ibm,pft-size", NULL);
++ if (pft_size != NULL) {
++ /* pft_size[0] is the NUMA CEC cookie */
++ ppc64_pft_size = pft_size[1];
++ }
++ }
++#endif
++
++ boot_cpuid = 0;
++ boot_cpuid_phys = 0;
++ if (initial_boot_params && initial_boot_params->version >= 2) {
++ /* version 2 of the kexec param format adds the phys cpuid
++ * of booted proc.
++ */
++ boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
++ } else {
++ /* Check if it's the boot-cpu, set it's hw index now */
++ if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {
++ prop = get_flat_dt_prop(node, "reg", NULL);
++ if (prop != NULL)
++ boot_cpuid_phys = *prop;
++ }
++ }
++ set_hard_smp_processor_id(0, boot_cpuid_phys);
++
++#ifdef CONFIG_ALTIVEC
++ /* Check if we have a VMX and eventually update CPU features */
++ prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", &size);
++ if (prop && (*prop) > 0) {
++ cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
++ cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
++ }
++
++ /* Same goes for Apple's "altivec" property */
++ prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL);
++ if (prop) {
++ cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
++ cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
++ }
++#endif /* CONFIG_ALTIVEC */
++
++#ifdef CONFIG_PPC_PSERIES
++ /*
++ * Check for an SMT capable CPU and set the CPU feature. We do
++ * this by looking at the size of the ibm,ppc-interrupt-server#s
++ * property
++ */
++ prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
++ &size);
++ cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
++ if (prop && ((size / sizeof(u32)) > 1))
++ cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
++#endif
++
++ return 0;
++}
++
++static int __init early_init_dt_scan_chosen(unsigned long node,
++ const char *uname, int depth, void *data)
++{
++ u32 *prop;
++ unsigned long *lprop;
++
++ DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
++
++ if (depth != 1 ||
++ (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen at 0") != 0))
++ return 0;
++
++ /* get platform type */
++ prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);
++ if (prop == NULL)
++ return 0;
++#ifdef CONFIG_PPC64
++ systemcfg->platform = *prop;
++#else
++#ifdef CONFIG_PPC_MULTIPLATFORM
++ _machine = *prop;
++#endif
++#endif
++
++#ifdef CONFIG_PPC64
++ /* check if iommu is forced on or off */
++ if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
++ iommu_is_off = 1;
++ if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
++ iommu_force_on = 1;
++#endif
++
++ lprop = get_flat_dt_prop(node, "linux,memory-limit", NULL);
++ if (lprop)
++ memory_limit = *lprop;
++
++#ifdef CONFIG_PPC64
++ lprop = get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
++ if (lprop)
++ tce_alloc_start = *lprop;
++ lprop = get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
++ if (lprop)
++ tce_alloc_end = *lprop;
++#endif
++
++#ifdef CONFIG_PPC_RTAS
++ /* To help early debugging via the front panel, we retreive a minimal
++ * set of RTAS infos now if available
++ */
++ {
++ u64 *basep, *entryp;
++
++ basep = get_flat_dt_prop(node, "linux,rtas-base", NULL);
++ entryp = get_flat_dt_prop(node, "linux,rtas-entry", NULL);
++ prop = get_flat_dt_prop(node, "linux,rtas-size", NULL);
++ if (basep && entryp && prop) {
++ rtas.base = *basep;
++ rtas.entry = *entryp;
++ rtas.size = *prop;
++ }
++ }
++#endif /* CONFIG_PPC_RTAS */
++
++ /* break now */
++ return 1;
++}
++
++static int __init early_init_dt_scan_root(unsigned long node,
++ const char *uname, int depth, void *data)
++{
++ u32 *prop;
++
++ if (depth != 0)
++ return 0;
++
++ prop = get_flat_dt_prop(node, "#size-cells", NULL);
++ dt_root_size_cells = (prop == NULL) ? 1 : *prop;
++ DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
++
++ prop = get_flat_dt_prop(node, "#address-cells", NULL);
++ dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
++ DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
++
++ /* break now */
++ return 1;
++}
++
++static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
++{
++ cell_t *p = *cellp;
++ unsigned long r;
++
++ /* Ignore more than 2 cells */
++ while (s > sizeof(unsigned long) / 4) {
++ p++;
++ s--;
++ }
++ r = *p++;
++#ifdef CONFIG_PPC64
++ if (s > 1) {
++ r <<= 32;
++ r |= *(p++);
++ s--;
++ }
++#endif
++
++ *cellp = p;
++ return r;
++}
++
++
++static int __init early_init_dt_scan_memory(unsigned long node,
++ const char *uname, int depth, void *data)
++{
++ char *type = get_flat_dt_prop(node, "device_type", NULL);
++ cell_t *reg, *endp;
++ unsigned long l;
++
++ /* We are scanning "memory" nodes only */
++ if (type == NULL || strcmp(type, "memory") != 0)
++ return 0;
++
++ reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);
++ if (reg == NULL)
++ return 0;
++
++ endp = reg + (l / sizeof(cell_t));
++
++ DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
++ uname, l, reg[0], reg[1], reg[2], reg[3]);
++
++ while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
++ unsigned long base, size;
++
++ base = dt_mem_next_cell(dt_root_addr_cells, ®);
++ size = dt_mem_next_cell(dt_root_size_cells, ®);
++
++ if (size == 0)
++ continue;
++ DBG(" - %lx , %lx\n", base, size);
++#ifdef CONFIG_PPC64
++ if (iommu_is_off) {
++ if (base >= 0x80000000ul)
++ continue;
++ if ((base + size) > 0x80000000ul)
++ size = 0x80000000ul - base;
++ }
++#endif
++ lmb_add(base, size);
++ }
++ return 0;
++}
++
++static void __init early_reserve_mem(void)
++{
++ unsigned long base, size;
++ unsigned long *reserve_map;
++
++ reserve_map = (unsigned long *)(((unsigned long)initial_boot_params) +
++ initial_boot_params->off_mem_rsvmap);
++ while (1) {
++ base = *(reserve_map++);
++ size = *(reserve_map++);
++ if (size == 0)
++ break;
++ DBG("reserving: %lx -> %lx\n", base, size);
++ lmb_reserve(base, size);
++ }
++
++#if 0
++ DBG("memory reserved, lmbs :\n");
++ lmb_dump_all();
++#endif
++}
++
++void __init early_init_devtree(void *params)
++{
++ DBG(" -> early_init_devtree()\n");
++
++ /* Setup flat device-tree pointer */
++ initial_boot_params = params;
++
++ /* Retrieve various informations from the /chosen node of the
++ * device-tree, including the platform type, initrd location and
++ * size, TCE reserve, and more ...
++ */
++ scan_flat_dt(early_init_dt_scan_chosen, NULL);
++
++ /* Scan memory nodes and rebuild LMBs */
++ lmb_init();
++ scan_flat_dt(early_init_dt_scan_root, NULL);
++ scan_flat_dt(early_init_dt_scan_memory, NULL);
++ lmb_enforce_memory_limit(memory_limit);
++ lmb_analyze();
++#ifdef CONFIG_PPC64
++ systemcfg->physicalMemorySize = lmb_phys_mem_size();
++#endif
++ lmb_reserve(0, __pa(klimit));
++
++ DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
++
++ /* Reserve LMB regions used by kernel, initrd, dt, etc... */
++ early_reserve_mem();
++
++ DBG("Scanning CPUs ...\n");
++
++ /* Retreive hash table size from flattened tree plus other
++ * CPU related informations (altivec support, boot CPU ID, ...)
++ */
++ scan_flat_dt(early_init_dt_scan_cpus, NULL);
++
++ DBG(" <- early_init_devtree()\n");
++}
++
++#undef printk
++
++int
++prom_n_addr_cells(struct device_node* np)
++{
++ int* ip;
++ do {
++ if (np->parent)
++ np = np->parent;
++ ip = (int *) get_property(np, "#address-cells", NULL);
++ if (ip != NULL)
++ return *ip;
++ } while (np->parent);
++ /* No #address-cells property for the root node, default to 1 */
++ return 1;
++}
++
++int
++prom_n_size_cells(struct device_node* np)
++{
++ int* ip;
++ do {
++ if (np->parent)
++ np = np->parent;
++ ip = (int *) get_property(np, "#size-cells", NULL);
++ if (ip != NULL)
++ return *ip;
++ } while (np->parent);
++ /* No #size-cells property for the root node, default to 1 */
++ return 1;
++}
++
++/**
++ * Work out the sense (active-low level / active-high edge)
++ * of each interrupt from the device tree.
++ */
++void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
++{
++ struct device_node *np;
++ int i, j;
++
++ /* default to level-triggered */
++ memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off);
++
++ for (np = allnodes; np != 0; np = np->allnext) {
++ for (j = 0; j < np->n_intrs; j++) {
++ i = np->intrs[j].line;
++ if (i >= off && i < max)
++ senses[i-off] = np->intrs[j].sense;
++ }
++ }
++}
++
++/**
++ * Construct and return a list of the device_nodes with a given name.
++ */
++struct device_node *find_devices(const char *name)
++{
++ struct device_node *head, **prevp, *np;
++
++ prevp = &head;
++ for (np = allnodes; np != 0; np = np->allnext) {
++ if (np->name != 0 && strcasecmp(np->name, name) == 0) {
++ *prevp = np;
++ prevp = &np->next;
++ }
++ }
++ *prevp = NULL;
++ return head;
++}
++EXPORT_SYMBOL(find_devices);
++
++/**
++ * Construct and return a list of the device_nodes with a given type.
++ */
++struct device_node *find_type_devices(const char *type)
++{
++ struct device_node *head, **prevp, *np;
++
++ prevp = &head;
++ for (np = allnodes; np != 0; np = np->allnext) {
++ if (np->type != 0 && strcasecmp(np->type, type) == 0) {
++ *prevp = np;
++ prevp = &np->next;
++ }
++ }
++ *prevp = NULL;
++ return head;
++}
++EXPORT_SYMBOL(find_type_devices);
++
++/**
++ * Returns all nodes linked together
++ */
++struct device_node *find_all_nodes(void)
++{
++ struct device_node *head, **prevp, *np;
++
++ prevp = &head;
++ for (np = allnodes; np != 0; np = np->allnext) {
++ *prevp = np;
++ prevp = &np->next;
++ }
++ *prevp = NULL;
++ return head;
++}
++EXPORT_SYMBOL(find_all_nodes);
++
++/** Checks if the given "compat" string matches one of the strings in
++ * the device's "compatible" property
++ */
++int device_is_compatible(struct device_node *device, const char *compat)
++{
++ const char* cp;
++ int cplen, l;
++
++ cp = (char *) get_property(device, "compatible", &cplen);
++ if (cp == NULL)
++ return 0;
++ while (cplen > 0) {
++ if (strncasecmp(cp, compat, strlen(compat)) == 0)
++ return 1;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(device_is_compatible);
++
++
++/**
++ * Indicates whether the root node has a given value in its
++ * compatible property.
++ */
++int machine_is_compatible(const char *compat)
++{
++ struct device_node *root;
++ int rc = 0;
++
++ root = of_find_node_by_path("/");
++ if (root) {
++ rc = device_is_compatible(root, compat);
++ of_node_put(root);
++ }
++ return rc;
++}
++EXPORT_SYMBOL(machine_is_compatible);
++
++/**
++ * Construct and return a list of the device_nodes with a given type
++ * and compatible property.
++ */
++struct device_node *find_compatible_devices(const char *type,
++ const char *compat)
++{
++ struct device_node *head, **prevp, *np;
++
++ prevp = &head;
++ for (np = allnodes; np != 0; np = np->allnext) {
++ if (type != NULL
++ && !(np->type != 0 && strcasecmp(np->type, type) == 0))
++ continue;
++ if (device_is_compatible(np, compat)) {
++ *prevp = np;
++ prevp = &np->next;
++ }
++ }
++ *prevp = NULL;
++ return head;
++}
++EXPORT_SYMBOL(find_compatible_devices);
++
++/**
++ * Find the device_node with a given full_name.
++ */
++struct device_node *find_path_device(const char *path)
++{
++ struct device_node *np;
++
++ for (np = allnodes; np != 0; np = np->allnext)
++ if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
++ return np;
++ return NULL;
++}
++EXPORT_SYMBOL(find_path_device);
++
++/*******
++ *
++ * New implementation of the OF "find" APIs, return a refcounted
++ * object, call of_node_put() when done. The device tree and list
++ * are protected by a rw_lock.
++ *
++ * Note that property management will need some locking as well,
++ * this isn't dealt with yet.
++ *
++ *******/
++
++/**
++ * of_find_node_by_name - Find a node by its "name" property
++ * @from: The node to start searching from or NULL, the node
++ * you pass will not be searched, only the next one
++ * will; typically, you pass what the previous call
++ * returned. of_node_put() will be called on it
++ * @name: The name string to match against
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_find_node_by_name(struct device_node *from,
++ const char *name)
++{
++ struct device_node *np;
++
++ read_lock(&devtree_lock);
++ np = from ? from->allnext : allnodes;
++ for (; np != 0; np = np->allnext)
++ if (np->name != 0 && strcasecmp(np->name, name) == 0
++ && of_node_get(np))
++ break;
++ if (from)
++ of_node_put(from);
++ read_unlock(&devtree_lock);
++ return np;
++}
++EXPORT_SYMBOL(of_find_node_by_name);
++
++/**
++ * of_find_node_by_type - Find a node by its "device_type" property
++ * @from: The node to start searching from or NULL, the node
++ * you pass will not be searched, only the next one
++ * will; typically, you pass what the previous call
++ * returned. of_node_put() will be called on it
++ * @name: The type string to match against
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_find_node_by_type(struct device_node *from,
++ const char *type)
++{
++ struct device_node *np;
++
++ read_lock(&devtree_lock);
++ np = from ? from->allnext : allnodes;
++ for (; np != 0; np = np->allnext)
++ if (np->type != 0 && strcasecmp(np->type, type) == 0
++ && of_node_get(np))
++ break;
++ if (from)
++ of_node_put(from);
++ read_unlock(&devtree_lock);
++ return np;
++}
++EXPORT_SYMBOL(of_find_node_by_type);
++
++/**
++ * of_find_compatible_node - Find a node based on type and one of the
++ * tokens in its "compatible" property
++ * @from: The node to start searching from or NULL, the node
++ * you pass will not be searched, only the next one
++ * will; typically, you pass what the previous call
++ * returned. of_node_put() will be called on it
++ * @type: The type string to match "device_type" or NULL to ignore
++ * @compatible: The string to match to one of the tokens in the device
++ * "compatible" list.
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_find_compatible_node(struct device_node *from,
++ const char *type, const char *compatible)
++{
++ struct device_node *np;
++
++ read_lock(&devtree_lock);
++ np = from ? from->allnext : allnodes;
++ for (; np != 0; np = np->allnext) {
++ if (type != NULL
++ && !(np->type != 0 && strcasecmp(np->type, type) == 0))
++ continue;
++ if (device_is_compatible(np, compatible) && of_node_get(np))
++ break;
++ }
++ if (from)
++ of_node_put(from);
++ read_unlock(&devtree_lock);
++ return np;
++}
++EXPORT_SYMBOL(of_find_compatible_node);
++
++/**
++ * of_find_node_by_path - Find a node matching a full OF path
++ * @path: The full path to match
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_find_node_by_path(const char *path)
++{
++ struct device_node *np = allnodes;
++
++ read_lock(&devtree_lock);
++ for (; np != 0; np = np->allnext) {
++ if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0
++ && of_node_get(np))
++ break;
++ }
++ read_unlock(&devtree_lock);
++ return np;
++}
++EXPORT_SYMBOL(of_find_node_by_path);
++
++/**
++ * of_find_node_by_phandle - Find a node given a phandle
++ * @handle: phandle of the node to find
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_find_node_by_phandle(phandle handle)
++{
++ struct device_node *np;
++
++ read_lock(&devtree_lock);
++ for (np = allnodes; np != 0; np = np->allnext)
++ if (np->linux_phandle == handle)
++ break;
++ if (np)
++ of_node_get(np);
++ read_unlock(&devtree_lock);
++ return np;
++}
++EXPORT_SYMBOL(of_find_node_by_phandle);
++
++/**
++ * of_find_all_nodes - Get next node in global list
++ * @prev: Previous node or NULL to start iteration
++ * of_node_put() will be called on it
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_find_all_nodes(struct device_node *prev)
++{
++ struct device_node *np;
++
++ read_lock(&devtree_lock);
++ np = prev ? prev->allnext : allnodes;
++ for (; np != 0; np = np->allnext)
++ if (of_node_get(np))
++ break;
++ if (prev)
++ of_node_put(prev);
++ read_unlock(&devtree_lock);
++ return np;
++}
++EXPORT_SYMBOL(of_find_all_nodes);
++
++/**
++ * of_get_parent - Get a node's parent if any
++ * @node: Node to get parent
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_get_parent(const struct device_node *node)
++{
++ struct device_node *np;
++
++ if (!node)
++ return NULL;
++
++ read_lock(&devtree_lock);
++ np = of_node_get(node->parent);
++ read_unlock(&devtree_lock);
++ return np;
++}
++EXPORT_SYMBOL(of_get_parent);
++
++/**
++ * of_get_next_child - Iterate a node childs
++ * @node: parent node
++ * @prev: previous child of the parent node, or NULL to get first
++ *
++ * Returns a node pointer with refcount incremented, use
++ * of_node_put() on it when done.
++ */
++struct device_node *of_get_next_child(const struct device_node *node,
++ struct device_node *prev)
++{
++ struct device_node *next;
++
++ read_lock(&devtree_lock);
++ next = prev ? prev->sibling : node->child;
++ for (; next != 0; next = next->sibling)
++ if (of_node_get(next))
++ break;
++ if (prev)
++ of_node_put(prev);
++ read_unlock(&devtree_lock);
++ return next;
++}
++EXPORT_SYMBOL(of_get_next_child);
++
++/**
++ * of_node_get - Increment refcount of a node
++ * @node: Node to inc refcount, NULL is supported to
++ * simplify writing of callers
++ *
++ * Returns node.
++ */
++struct device_node *of_node_get(struct device_node *node)
++{
++ if (node)
++ kref_get(&node->kref);
++ return node;
++}
++EXPORT_SYMBOL(of_node_get);
++
++static inline struct device_node * kref_to_device_node(struct kref *kref)
++{
++ return container_of(kref, struct device_node, kref);
++}
++
++/**
++ * of_node_release - release a dynamically allocated node
++ * @kref: kref element of the node to be released
++ *
++ * In of_node_put() this function is passed to kref_put()
++ * as the destructor.
++ */
++static void of_node_release(struct kref *kref)
++{
++ struct device_node *node = kref_to_device_node(kref);
++ struct property *prop = node->properties;
++
++ if (!OF_IS_DYNAMIC(node))
++ return;
++ while (prop) {
++ struct property *next = prop->next;
++ kfree(prop->name);
++ kfree(prop->value);
++ kfree(prop);
++ prop = next;
++ }
++ kfree(node->intrs);
++ kfree(node->addrs);
++ kfree(node->full_name);
++ kfree(node->data);
++ kfree(node);
++}
++
++/**
++ * of_node_put - Decrement refcount of a node
++ * @node: Node to dec refcount, NULL is supported to
++ * simplify writing of callers
++ *
++ */
++void of_node_put(struct device_node *node)
++{
++ if (node)
++ kref_put(&node->kref, of_node_release);
++}
++EXPORT_SYMBOL(of_node_put);
++
++/*
++ * Plug a device node into the tree and global list.
++ */
++void of_attach_node(struct device_node *np)
++{
++ write_lock(&devtree_lock);
++ np->sibling = np->parent->child;
++ np->allnext = allnodes;
++ np->parent->child = np;
++ allnodes = np;
++ write_unlock(&devtree_lock);
++}
++
++/*
++ * "Unplug" a node from the device tree. The caller must hold
++ * a reference to the node. The memory associated with the node
++ * is not freed until its refcount goes to zero.
++ */
++void of_detach_node(const struct device_node *np)
++{
++ struct device_node *parent;
++
++ write_lock(&devtree_lock);
++
++ parent = np->parent;
++
++ if (allnodes == np)
++ allnodes = np->allnext;
++ else {
++ struct device_node *prev;
++ for (prev = allnodes;
++ prev->allnext != np;
++ prev = prev->allnext)
++ ;
++ prev->allnext = np->allnext;
++ }
++
++ if (parent->child == np)
++ parent->child = np->sibling;
++ else {
++ struct device_node *prevsib;
++ for (prevsib = np->parent->child;
++ prevsib->sibling != np;
++ prevsib = prevsib->sibling)
++ ;
++ prevsib->sibling = np->sibling;
++ }
++
++ write_unlock(&devtree_lock);
++}
++
++#ifdef CONFIG_PPC_PSERIES
++/*
++ * Fix up the uninitialized fields in a new device node:
++ * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields
++ *
++ * A lot of boot-time code is duplicated here, because functions such
++ * as finish_node_interrupts, interpret_pci_props, etc. cannot use the
++ * slab allocator.
++ *
++ * This should probably be split up into smaller chunks.
++ */
++
++static int of_finish_dynamic_node(struct device_node *node,
++ unsigned long *unused1, int unused2,
++ int unused3, int unused4)
++{
++ struct device_node *parent = of_get_parent(node);
++ int err = 0;
++ phandle *ibm_phandle;
++
++ node->name = get_property(node, "name", NULL);
++ node->type = get_property(node, "device_type", NULL);
++
++ if (!parent) {
++ err = -ENODEV;
++ goto out;
++ }
++
++ /* We don't support that function on PowerMac, at least
++ * not yet
++ */
++ if (systemcfg->platform == PLATFORM_POWERMAC)
++ return -ENODEV;
++
++ /* fix up new node's linux_phandle field */
++ if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL)))
++ node->linux_phandle = *ibm_phandle;
++
++out:
++ of_node_put(parent);
++ return err;
++}
++
++static int prom_reconfig_notifier(struct notifier_block *nb,
++ unsigned long action, void *node)
++{
++ int err;
++
++ switch (action) {
++ case PSERIES_RECONFIG_ADD:
++ err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0);
++ if (err < 0) {
++ printk(KERN_ERR "finish_node returned %d\n", err);
++ err = NOTIFY_BAD;
++ }
++ break;
++ default:
++ err = NOTIFY_DONE;
++ break;
++ }
++ return err;
++}
++
++static struct notifier_block prom_reconfig_nb = {
++ .notifier_call = prom_reconfig_notifier,
++ .priority = 10, /* This one needs to run first */
++};
++
++static int __init prom_reconfig_setup(void)
++{
++ return pSeries_reconfig_notifier_register(&prom_reconfig_nb);
++}
++__initcall(prom_reconfig_setup);
++#endif
++
++/*
++ * Find a property with a given name for a given node
++ * and return the value.
++ */
++unsigned char *get_property(struct device_node *np, const char *name,
++ int *lenp)
++{
++ struct property *pp;
++
++ for (pp = np->properties; pp != 0; pp = pp->next)
++ if (strcmp(pp->name, name) == 0) {
++ if (lenp != 0)
++ *lenp = pp->length;
++ return pp->value;
++ }
++ return NULL;
++}
++EXPORT_SYMBOL(get_property);
++
++/*
++ * Add a property to a node
++ */
++void prom_add_property(struct device_node* np, struct property* prop)
++{
++ struct property **next = &np->properties;
++
++ prop->next = NULL;
++ while (*next)
++ next = &(*next)->next;
++ *next = prop;
++}
++
++/* I quickly hacked that one, check against spec ! */
++static inline unsigned long
++bus_space_to_resource_flags(unsigned int bus_space)
++{
++ u8 space = (bus_space >> 24) & 0xf;
++ if (space == 0)
++ space = 0x02;
++ if (space == 0x02)
++ return IORESOURCE_MEM;
++ else if (space == 0x01)
++ return IORESOURCE_IO;
++ else {
++ printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
++ bus_space);
++ return 0;
++ }
++}
++
++#ifdef CONFIG_PCI
++static struct resource *find_parent_pci_resource(struct pci_dev* pdev,
++ struct address_range *range)
++{
++ unsigned long mask;
++ int i;
++
++ /* Check this one */
++ mask = bus_space_to_resource_flags(range->space);
++ for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
++ if ((pdev->resource[i].flags & mask) == mask &&
++ pdev->resource[i].start <= range->address &&
++ pdev->resource[i].end > range->address) {
++ if ((range->address + range->size - 1) > pdev->resource[i].end) {
++ /* Add better message */
++ printk(KERN_WARNING "PCI/OF resource overlap !\n");
++ return NULL;
++ }
++ break;
++ }
++ }
++ if (i == DEVICE_COUNT_RESOURCE)
++ return NULL;
++ return &pdev->resource[i];
++}
++
++/*
++ * Request an OF device resource. Currently handles child of PCI devices,
++ * or other nodes attached to the root node. Ultimately, put some
++ * link to resources in the OF node.
++ */
++struct resource *request_OF_resource(struct device_node* node, int index,
++ const char* name_postfix)
++{
++ struct pci_dev* pcidev;
++ u8 pci_bus, pci_devfn;
++ unsigned long iomask;
++ struct device_node* nd;
++ struct resource* parent;
++ struct resource *res = NULL;
++ int nlen, plen;
++
++ if (index >= node->n_addrs)
++ goto fail;
++
++ /* Sanity check on bus space */
++ iomask = bus_space_to_resource_flags(node->addrs[index].space);
++ if (iomask & IORESOURCE_MEM)
++ parent = &iomem_resource;
++ else if (iomask & IORESOURCE_IO)
++ parent = &ioport_resource;
++ else
++ goto fail;
++
++ /* Find a PCI parent if any */
++ nd = node;
++ pcidev = NULL;
++ while (nd) {
++ if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
++ pcidev = pci_find_slot(pci_bus, pci_devfn);
++ if (pcidev) break;
++ nd = nd->parent;
++ }
++ if (pcidev)
++ parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
++ if (!parent) {
++ printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
++ node->name);
++ goto fail;
++ }
++
++ res = __request_region(parent, node->addrs[index].address,
++ node->addrs[index].size, NULL);
++ if (!res)
++ goto fail;
++ nlen = strlen(node->name);
++ plen = name_postfix ? strlen(name_postfix) : 0;
++ res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
++ if (res->name) {
++ strcpy((char *)res->name, node->name);
++ if (plen)
++ strcpy((char *)res->name+nlen, name_postfix);
++ }
++ return res;
++fail:
++ return NULL;
++}
++EXPORT_SYMBOL(request_OF_resource);
++
++int release_OF_resource(struct device_node *node, int index)
++{
++ struct pci_dev* pcidev;
++ u8 pci_bus, pci_devfn;
++ unsigned long iomask, start, end;
++ struct device_node* nd;
++ struct resource* parent;
++ struct resource *res = NULL;
++
++ if (index >= node->n_addrs)
++ return -EINVAL;
++
++ /* Sanity check on bus space */
++ iomask = bus_space_to_resource_flags(node->addrs[index].space);
++ if (iomask & IORESOURCE_MEM)
++ parent = &iomem_resource;
++ else if (iomask & IORESOURCE_IO)
++ parent = &ioport_resource;
++ else
++ return -EINVAL;
++
++ /* Find a PCI parent if any */
++ nd = node;
++ pcidev = NULL;
++ while(nd) {
++ if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
++ pcidev = pci_find_slot(pci_bus, pci_devfn);
++ if (pcidev) break;
++ nd = nd->parent;
++ }
++ if (pcidev)
++ parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
++ if (!parent) {
++ printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
++ node->name);
++ return -ENODEV;
++ }
++
++ /* Find us in the parent and its childs */
++ res = parent->child;
++ start = node->addrs[index].address;
++ end = start + node->addrs[index].size - 1;
++ while (res) {
++ if (res->start == start && res->end == end &&
++ (res->flags & IORESOURCE_BUSY))
++ break;
++ if (res->start <= start && res->end >= end)
++ res = res->child;
++ else
++ res = res->sibling;
++ }
++ if (!res)
++ return -ENODEV;
++
++ if (res->name) {
++ kfree(res->name);
++ res->name = NULL;
++ }
++ release_resource(res);
++ kfree(res);
++
++ return 0;
++}
++EXPORT_SYMBOL(release_OF_resource);
++#endif /* CONFIG_PCI */
+diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/prom_init.c
+@@ -0,0 +1,2109 @@
++/*
++ * Procedures for interfacing to Open Firmware.
++ *
++ * Paul Mackerras August 1996.
++ * Copyright (C) 1996-2005 Paul Mackerras.
++ *
++ * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
++ * {engebret|bergner}@us.ibm.com
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#undef DEBUG_PROM
++
++#include <stdarg.h>
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/threads.h>
++#include <linux/spinlock.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/proc_fs.h>
++#include <linux/stringify.h>
++#include <linux/delay.h>
++#include <linux/initrd.h>
++#include <linux/bitops.h>
++#include <asm/prom.h>
++#include <asm/rtas.h>
++#include <asm/page.h>
++#include <asm/processor.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/system.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/pci.h>
++#include <asm/iommu.h>
++#include <asm/btext.h>
++#include <asm/sections.h>
++#include <asm/machdep.h>
++
++#ifdef CONFIG_LOGO_LINUX_CLUT224
++#include <linux/linux_logo.h>
++extern const struct linux_logo logo_linux_clut224;
++#endif
++
++/*
++ * Properties whose value is longer than this get excluded from our
++ * copy of the device tree. This value does need to be big enough to
++ * ensure that we don't lose things like the interrupt-map property
++ * on a PCI-PCI bridge.
++ */
++#define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024)
++
++/*
++ * Eventually bump that one up
++ */
++#define DEVTREE_CHUNK_SIZE 0x100000
++
++/*
++ * This is the size of the local memory reserve map that gets copied
++ * into the boot params passed to the kernel. That size is totally
++ * flexible as the kernel just reads the list until it encounters an
++ * entry with size 0, so it can be changed without breaking binary
++ * compatibility
++ */
++#define MEM_RESERVE_MAP_SIZE 8
++
++/*
++ * prom_init() is called very early on, before the kernel text
++ * and data have been mapped to KERNELBASE. At this point the code
++ * is running at whatever address it has been loaded at.
++ * On ppc32 we compile with -mrelocatable, which means that references
++ * to extern and static variables get relocated automatically.
++ * On ppc64 we have to relocate the references explicitly with
++ * RELOC. (Note that strings count as static variables.)
++ *
++ * Because OF may have mapped I/O devices into the area starting at
++ * KERNELBASE, particularly on CHRP machines, we can't safely call
++ * OF once the kernel has been mapped to KERNELBASE. Therefore all
++ * OF calls must be done within prom_init().
++ *
++ * ADDR is used in calls to call_prom. The 4th and following
++ * arguments to call_prom should be 32-bit values.
++ * On ppc64, 64 bit values are truncated to 32 bits (and
++ * fortunately don't get interpreted as two arguments).
++ */
++#ifdef CONFIG_PPC64
++#define RELOC(x) (*PTRRELOC(&(x)))
++#define ADDR(x) (u32) add_reloc_offset((unsigned long)(x))
++#else
++#define RELOC(x) (x)
++#define ADDR(x) (u32) (x)
++#endif
++
++#define PROM_BUG() do { \
++ prom_printf("kernel BUG at %s line 0x%x!\n", \
++ RELOC(__FILE__), __LINE__); \
++ __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
++} while (0)
++
++#ifdef DEBUG_PROM
++#define prom_debug(x...) prom_printf(x)
++#else
++#define prom_debug(x...)
++#endif
++
++#ifdef CONFIG_PPC32
++#define PLATFORM_POWERMAC _MACH_Pmac
++#define PLATFORM_CHRP _MACH_chrp
++#endif
++
++
++typedef u32 prom_arg_t;
++
++struct prom_args {
++ u32 service;
++ u32 nargs;
++ u32 nret;
++ prom_arg_t args[10];
++};
++
++struct prom_t {
++ ihandle root;
++ ihandle chosen;
++ int cpu;
++ ihandle stdout;
++ ihandle mmumap;
++};
++
++struct mem_map_entry {
++ unsigned long base;
++ unsigned long size;
++};
++
++typedef u32 cell_t;
++
++extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
++
++#ifdef CONFIG_PPC64
++extern int enter_prom(struct prom_args *args, unsigned long entry);
++#else
++static inline int enter_prom(struct prom_args *args, unsigned long entry)
++{
++ return ((int (*)(struct prom_args *))entry)(args);
++}
++#endif
++
++extern void copy_and_flush(unsigned long dest, unsigned long src,
++ unsigned long size, unsigned long offset);
++
++/* prom structure */
++static struct prom_t __initdata prom;
++
++static unsigned long prom_entry __initdata;
++
++#define PROM_SCRATCH_SIZE 256
++
++static char __initdata of_stdout_device[256];
++static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
++
++static unsigned long __initdata dt_header_start;
++static unsigned long __initdata dt_struct_start, dt_struct_end;
++static unsigned long __initdata dt_string_start, dt_string_end;
++
++static unsigned long __initdata prom_initrd_start, prom_initrd_end;
++
++#ifdef CONFIG_PPC64
++static int __initdata iommu_force_on;
++static int __initdata ppc64_iommu_off;
++static unsigned long __initdata prom_tce_alloc_start;
++static unsigned long __initdata prom_tce_alloc_end;
++#endif
++
++static int __initdata of_platform;
++
++static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
++
++static unsigned long __initdata prom_memory_limit;
++
++static unsigned long __initdata alloc_top;
++static unsigned long __initdata alloc_top_high;
++static unsigned long __initdata alloc_bottom;
++static unsigned long __initdata rmo_top;
++static unsigned long __initdata ram_top;
++
++static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
++static int __initdata mem_reserve_cnt;
++
++static cell_t __initdata regbuf[1024];
++
++
++#define MAX_CPU_THREADS 2
++
++/* TO GO */
++#ifdef CONFIG_HMT
++struct {
++ unsigned int pir;
++ unsigned int threadid;
++} hmt_thread_data[NR_CPUS];
++#endif /* CONFIG_HMT */
++
++/*
++ * Error results ... some OF calls will return "-1" on error, some
++ * will return 0, some will return either. To simplify, here are
++ * macros to use with any ihandle or phandle return value to check if
++ * it is valid
++ */
++
++#define PROM_ERROR (-1u)
++#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
++#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
++
++
++/* This is the one and *ONLY* place where we actually call open
++ * firmware.
++ */
++
++static int __init call_prom(const char *service, int nargs, int nret, ...)
++{
++ int i;
++ struct prom_args args;
++ va_list list;
++
++ args.service = ADDR(service);
++ args.nargs = nargs;
++ args.nret = nret;
++
++ va_start(list, nret);
++ for (i = 0; i < nargs; i++)
++ args.args[i] = va_arg(list, prom_arg_t);
++ va_end(list);
++
++ for (i = 0; i < nret; i++)
++ args.args[nargs+i] = 0;
++
++ if (enter_prom(&args, RELOC(prom_entry)) < 0)
++ return PROM_ERROR;
++
++ return (nret > 0) ? args.args[nargs] : 0;
++}
++
++static int __init call_prom_ret(const char *service, int nargs, int nret,
++ prom_arg_t *rets, ...)
++{
++ int i;
++ struct prom_args args;
++ va_list list;
++
++ args.service = ADDR(service);
++ args.nargs = nargs;
++ args.nret = nret;
++
++ va_start(list, rets);
++ for (i = 0; i < nargs; i++)
++ args.args[i] = va_arg(list, prom_arg_t);
++ va_end(list);
++
++ for (i = 0; i < nret; i++)
++ rets[nargs+i] = 0;
++
++ if (enter_prom(&args, RELOC(prom_entry)) < 0)
++ return PROM_ERROR;
++
++ if (rets != NULL)
++ for (i = 1; i < nret; ++i)
++ rets[i-1] = args.args[nargs+i];
++
++ return (nret > 0) ? args.args[nargs] : 0;
++}
++
++
++static void __init prom_print(const char *msg)
++{
++ const char *p, *q;
++ struct prom_t *_prom = &RELOC(prom);
++
++ if (_prom->stdout == 0)
++ return;
++
++ for (p = msg; *p != 0; p = q) {
++ for (q = p; *q != 0 && *q != '\n'; ++q)
++ ;
++ if (q > p)
++ call_prom("write", 3, 1, _prom->stdout, p, q - p);
++ if (*q == 0)
++ break;
++ ++q;
++ call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);
++ }
++}
++
++
++static void __init prom_print_hex(unsigned long val)
++{
++ int i, nibbles = sizeof(val)*2;
++ char buf[sizeof(val)*2+1];
++ struct prom_t *_prom = &RELOC(prom);
++
++ for (i = nibbles-1; i >= 0; i--) {
++ buf[i] = (val & 0xf) + '0';
++ if (buf[i] > '9')
++ buf[i] += ('a'-'0'-10);
++ val >>= 4;
++ }
++ buf[nibbles] = '\0';
++ call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
++}
++
++
++static void __init prom_printf(const char *format, ...)
++{
++ const char *p, *q, *s;
++ va_list args;
++ unsigned long v;
++ struct prom_t *_prom = &RELOC(prom);
++
++ va_start(args, format);
++#ifdef CONFIG_PPC64
++ format = PTRRELOC(format);
++#endif
++ for (p = format; *p != 0; p = q) {
++ for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
++ ;
++ if (q > p)
++ call_prom("write", 3, 1, _prom->stdout, p, q - p);
++ if (*q == 0)
++ break;
++ if (*q == '\n') {
++ ++q;
++ call_prom("write", 3, 1, _prom->stdout,
++ ADDR("\r\n"), 2);
++ continue;
++ }
++ ++q;
++ if (*q == 0)
++ break;
++ switch (*q) {
++ case 's':
++ ++q;
++ s = va_arg(args, const char *);
++ prom_print(s);
++ break;
++ case 'x':
++ ++q;
++ v = va_arg(args, unsigned long);
++ prom_print_hex(v);
++ break;
++ }
++ }
++}
++
++
++static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
++ unsigned long align)
++{
++ int ret;
++ struct prom_t *_prom = &RELOC(prom);
++
++ ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
++ (prom_arg_t)align);
++ if (ret != -1 && _prom->mmumap != 0)
++ /* old pmacs need us to map as well */
++ call_prom("call-method", 6, 1,
++ ADDR("map"), _prom->mmumap, 0, size, virt, virt);
++ return ret;
++}
++
++static void __init __attribute__((noreturn)) prom_panic(const char *reason)
++{
++#ifdef CONFIG_PPC64
++ reason = PTRRELOC(reason);
++#endif
++ prom_print(reason);
++ /* ToDo: should put up an SRC here on p/iSeries */
++ call_prom("exit", 0, 0);
++
++ for (;;) /* should never get here */
++ ;
++}
++
++
++static int __init prom_next_node(phandle *nodep)
++{
++ phandle node;
++
++ if ((node = *nodep) != 0
++ && (*nodep = call_prom("child", 1, 1, node)) != 0)
++ return 1;
++ if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
++ return 1;
++ for (;;) {
++ if ((node = call_prom("parent", 1, 1, node)) == 0)
++ return 0;
++ if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
++ return 1;
++ }
++}
++
++static int __init prom_getprop(phandle node, const char *pname,
++ void *value, size_t valuelen)
++{
++ return call_prom("getprop", 4, 1, node, ADDR(pname),
++ (u32)(unsigned long) value, (u32) valuelen);
++}
++
++static int __init prom_getproplen(phandle node, const char *pname)
++{
++ return call_prom("getproplen", 2, 1, node, ADDR(pname));
++}
++
++static int __init prom_setprop(phandle node, const char *pname,
++ void *value, size_t valuelen)
++{
++ return call_prom("setprop", 4, 1, node, ADDR(pname),
++ (u32)(unsigned long) value, (u32) valuelen);
++}
++
++/* We can't use the standard versions because of RELOC headaches. */
++#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
++ || ('a' <= (c) && (c) <= 'f') \
++ || ('A' <= (c) && (c) <= 'F'))
++
++#define isdigit(c) ('0' <= (c) && (c) <= '9')
++#define islower(c) ('a' <= (c) && (c) <= 'z')
++#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
++
++unsigned long prom_strtoul(const char *cp, const char **endp)
++{
++ unsigned long result = 0, base = 10, value;
++
++ if (*cp == '0') {
++ base = 8;
++ cp++;
++ if (toupper(*cp) == 'X') {
++ cp++;
++ base = 16;
++ }
++ }
++
++ while (isxdigit(*cp) &&
++ (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
++ result = result * base + value;
++ cp++;
++ }
++
++ if (endp)
++ *endp = cp;
++
++ return result;
++}
++
++unsigned long prom_memparse(const char *ptr, const char **retptr)
++{
++ unsigned long ret = prom_strtoul(ptr, retptr);
++ int shift = 0;
++
++ /*
++ * We can't use a switch here because GCC *may* generate a
++ * jump table which won't work, because we're not running at
++ * the address we're linked at.
++ */
++ if ('G' == **retptr || 'g' == **retptr)
++ shift = 30;
++
++ if ('M' == **retptr || 'm' == **retptr)
++ shift = 20;
++
++ if ('K' == **retptr || 'k' == **retptr)
++ shift = 10;
++
++ if (shift) {
++ ret <<= shift;
++ (*retptr)++;
++ }
++
++ return ret;
++}
++
++/*
++ * Early parsing of the command line passed to the kernel, used for
++ * "mem=x" and the options that affect the iommu
++ */
++static void __init early_cmdline_parse(void)
++{
++ struct prom_t *_prom = &RELOC(prom);
++ char *opt, *p;
++ int l = 0;
++
++ RELOC(prom_cmd_line[0]) = 0;
++ p = RELOC(prom_cmd_line);
++ if ((long)_prom->chosen > 0)
++ l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
++#ifdef CONFIG_CMDLINE
++ if (l == 0) /* dbl check */
++ strlcpy(RELOC(prom_cmd_line),
++ RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
++#endif /* CONFIG_CMDLINE */
++ prom_printf("command line: %s\n", RELOC(prom_cmd_line));
++
++#ifdef CONFIG_PPC64
++ opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));
++ if (opt) {
++ prom_printf("iommu opt is: %s\n", opt);
++ opt += 6;
++ while (*opt && *opt == ' ')
++ opt++;
++ if (!strncmp(opt, RELOC("off"), 3))
++ RELOC(ppc64_iommu_off) = 1;
++ else if (!strncmp(opt, RELOC("force"), 5))
++ RELOC(iommu_force_on) = 1;
++ }
++#endif
++
++ opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
++ if (opt) {
++ opt += 4;
++ RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
++#ifdef CONFIG_PPC64
++ /* Align to 16 MB == size of ppc64 large page */
++ RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
++#endif
++ }
++}
++
++#ifdef CONFIG_PPC_PSERIES
++/*
++ * To tell the firmware what our capabilities are, we have to pass
++ * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
++ * that contain structures that contain the actual values.
++ */
++static struct fake_elf {
++ Elf32_Ehdr elfhdr;
++ Elf32_Phdr phdr[2];
++ struct chrpnote {
++ u32 namesz;
++ u32 descsz;
++ u32 type;
++ char name[8]; /* "PowerPC" */
++ struct chrpdesc {
++ u32 real_mode;
++ u32 real_base;
++ u32 real_size;
++ u32 virt_base;
++ u32 virt_size;
++ u32 load_base;
++ } chrpdesc;
++ } chrpnote;
++ struct rpanote {
++ u32 namesz;
++ u32 descsz;
++ u32 type;
++ char name[24]; /* "IBM,RPA-Client-Config" */
++ struct rpadesc {
++ u32 lpar_affinity;
++ u32 min_rmo_size;
++ u32 min_rmo_percent;
++ u32 max_pft_size;
++ u32 splpar;
++ u32 min_load;
++ u32 new_mem_def;
++ u32 ignore_me;
++ } rpadesc;
++ } rpanote;
++} fake_elf = {
++ .elfhdr = {
++ .e_ident = { 0x7f, 'E', 'L', 'F',
++ ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
++ .e_type = ET_EXEC, /* yeah right */
++ .e_machine = EM_PPC,
++ .e_version = EV_CURRENT,
++ .e_phoff = offsetof(struct fake_elf, phdr),
++ .e_phentsize = sizeof(Elf32_Phdr),
++ .e_phnum = 2
++ },
++ .phdr = {
++ [0] = {
++ .p_type = PT_NOTE,
++ .p_offset = offsetof(struct fake_elf, chrpnote),
++ .p_filesz = sizeof(struct chrpnote)
++ }, [1] = {
++ .p_type = PT_NOTE,
++ .p_offset = offsetof(struct fake_elf, rpanote),
++ .p_filesz = sizeof(struct rpanote)
++ }
++ },
++ .chrpnote = {
++ .namesz = sizeof("PowerPC"),
++ .descsz = sizeof(struct chrpdesc),
++ .type = 0x1275,
++ .name = "PowerPC",
++ .chrpdesc = {
++ .real_mode = ~0U, /* ~0 means "don't care" */
++ .real_base = ~0U,
++ .real_size = ~0U,
++ .virt_base = ~0U,
++ .virt_size = ~0U,
++ .load_base = ~0U
++ },
++ },
++ .rpanote = {
++ .namesz = sizeof("IBM,RPA-Client-Config"),
++ .descsz = sizeof(struct rpadesc),
++ .type = 0x12759999,
++ .name = "IBM,RPA-Client-Config",
++ .rpadesc = {
++ .lpar_affinity = 0,
++ .min_rmo_size = 64, /* in megabytes */
++ .min_rmo_percent = 0,
++ .max_pft_size = 48, /* 2^48 bytes max PFT size */
++ .splpar = 1,
++ .min_load = ~0U,
++ .new_mem_def = 0
++ }
++ }
++};
++
++static void __init prom_send_capabilities(void)
++{
++ ihandle elfloader;
++
++ elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
++ if (elfloader == 0) {
++ prom_printf("couldn't open /packages/elf-loader\n");
++ return;
++ }
++ call_prom("call-method", 3, 1, ADDR("process-elf-header"),
++ elfloader, ADDR(&fake_elf));
++ call_prom("close", 1, 0, elfloader);
++}
++#endif
++
++/*
++ * Memory allocation strategy... our layout is normally:
++ *
++ * at 14Mb or more we have vmlinux, then a gap and initrd. In some
++ * rare cases, initrd might end up being before the kernel though.
++ * We assume this won't override the final kernel at 0, we have no
++ * provision to handle that in this version, but it should hopefully
++ * never happen.
++ *
++ * alloc_top is set to the top of RMO, eventually shrink down if the
++ * TCEs overlap
++ *
++ * alloc_bottom is set to the top of kernel/initrd
++ *
++ * from there, allocations are done this way : rtas is allocated
++ * topmost, and the device-tree is allocated from the bottom. We try
++ * to grow the device-tree allocation as we progress. If we can't,
++ * then we fail, we don't currently have a facility to restart
++ * elsewhere, but that shouldn't be necessary.
++ *
++ * Note that calls to reserve_mem have to be done explicitly, memory
++ * allocated with either alloc_up or alloc_down isn't automatically
++ * reserved.
++ */
++
++
++/*
++ * Allocates memory in the RMO upward from the kernel/initrd
++ *
++ * When align is 0, this is a special case, it means to allocate in place
++ * at the current location of alloc_bottom or fail (that is basically
++ * extending the previous allocation). Used for the device-tree flattening
++ */
++static unsigned long __init alloc_up(unsigned long size, unsigned long align)
++{
++ unsigned long base = RELOC(alloc_bottom);
++ unsigned long addr = 0;
++
++ if (align)
++ base = _ALIGN_UP(base, align);
++ prom_debug("alloc_up(%x, %x)\n", size, align);
++ if (RELOC(ram_top) == 0)
++ prom_panic("alloc_up() called with mem not initialized\n");
++
++ if (align)
++ base = _ALIGN_UP(RELOC(alloc_bottom), align);
++ else
++ base = RELOC(alloc_bottom);
++
++ for(; (base + size) <= RELOC(alloc_top);
++ base = _ALIGN_UP(base + 0x100000, align)) {
++ prom_debug(" trying: 0x%x\n\r", base);
++ addr = (unsigned long)prom_claim(base, size, 0);
++ if (addr != PROM_ERROR && addr != 0)
++ break;
++ addr = 0;
++ if (align == 0)
++ break;
++ }
++ if (addr == 0)
++ return 0;
++ RELOC(alloc_bottom) = addr;
++
++ prom_debug(" -> %x\n", addr);
++ prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom));
++ prom_debug(" alloc_top : %x\n", RELOC(alloc_top));
++ prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
++ prom_debug(" rmo_top : %x\n", RELOC(rmo_top));
++ prom_debug(" ram_top : %x\n", RELOC(ram_top));
++
++ return addr;
++}
++
++/*
++ * Allocates memory downward, either from top of RMO, or if highmem
++ * is set, from the top of RAM. Note that this one doesn't handle
++ * failures. It does claim memory if highmem is not set.
++ */
++static unsigned long __init alloc_down(unsigned long size, unsigned long align,
++ int highmem)
++{
++ unsigned long base, addr = 0;
++
++ prom_debug("alloc_down(%x, %x, %s)\n", size, align,
++ highmem ? RELOC("(high)") : RELOC("(low)"));
++ if (RELOC(ram_top) == 0)
++ prom_panic("alloc_down() called with mem not initialized\n");
++
++ if (highmem) {
++ /* Carve out storage for the TCE table. */
++ addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align);
++ if (addr <= RELOC(alloc_bottom))
++ return 0;
++ /* Will we bump into the RMO ? If yes, check out that we
++ * didn't overlap existing allocations there, if we did,
++ * we are dead, we must be the first in town !
++ */
++ if (addr < RELOC(rmo_top)) {
++ /* Good, we are first */
++ if (RELOC(alloc_top) == RELOC(rmo_top))
++ RELOC(alloc_top) = RELOC(rmo_top) = addr;
++ else
++ return 0;
++ }
++ RELOC(alloc_top_high) = addr;
++ goto bail;
++ }
++
++ base = _ALIGN_DOWN(RELOC(alloc_top) - size, align);
++ for (; base > RELOC(alloc_bottom);
++ base = _ALIGN_DOWN(base - 0x100000, align)) {
++ prom_debug(" trying: 0x%x\n\r", base);
++ addr = (unsigned long)prom_claim(base, size, 0);
++ if (addr != PROM_ERROR && addr != 0)
++ break;
++ addr = 0;
++ }
++ if (addr == 0)
++ return 0;
++ RELOC(alloc_top) = addr;
++
++ bail:
++ prom_debug(" -> %x\n", addr);
++ prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom));
++ prom_debug(" alloc_top : %x\n", RELOC(alloc_top));
++ prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
++ prom_debug(" rmo_top : %x\n", RELOC(rmo_top));
++ prom_debug(" ram_top : %x\n", RELOC(ram_top));
++
++ return addr;
++}
++
++/*
++ * Parse a "reg" cell
++ */
++static unsigned long __init prom_next_cell(int s, cell_t **cellp)
++{
++ cell_t *p = *cellp;
++ unsigned long r = 0;
++
++ /* Ignore more than 2 cells */
++ while (s > sizeof(unsigned long) / 4) {
++ p++;
++ s--;
++ }
++ r = *p++;
++#ifdef CONFIG_PPC64
++ if (s > 1) {
++ r <<= 32;
++ r |= *(p++);
++ }
++#endif
++ *cellp = p;
++ return r;
++}
++
++/*
++ * Very dumb function for adding to the memory reserve list, but
++ * we don't need anything smarter at this point
++ *
++ * XXX Eventually check for collisions. They should NEVER happen.
++ * If problems seem to show up, it would be a good start to track
++ * them down.
++ */
++static void reserve_mem(unsigned long base, unsigned long size)
++{
++ unsigned long top = base + size;
++ unsigned long cnt = RELOC(mem_reserve_cnt);
++
++ if (size == 0)
++ return;
++
++ /* We need to always keep one empty entry so that we
++ * have our terminator with "size" set to 0 since we are
++ * dumb and just copy this entire array to the boot params
++ */
++ base = _ALIGN_DOWN(base, PAGE_SIZE);
++ top = _ALIGN_UP(top, PAGE_SIZE);
++ size = top - base;
++
++ if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
++ prom_panic("Memory reserve map exhausted !\n");
++ RELOC(mem_reserve_map)[cnt].base = base;
++ RELOC(mem_reserve_map)[cnt].size = size;
++ RELOC(mem_reserve_cnt) = cnt + 1;
++}
++
++/*
++ * Initialize memory allocation mecanism, parse "memory" nodes and
++ * obtain that way the top of memory and RMO to setup out local allocator
++ */
++static void __init prom_init_mem(void)
++{
++ phandle node;
++ char *path, type[64];
++ unsigned int plen;
++ cell_t *p, *endp;
++ struct prom_t *_prom = &RELOC(prom);
++ u32 rac, rsc;
++
++ /*
++ * We iterate the memory nodes to find
++ * 1) top of RMO (first node)
++ * 2) top of memory
++ */
++ rac = 2;
++ prom_getprop(_prom->root, "#address-cells", &rac, sizeof(rac));
++ rsc = 1;
++ prom_getprop(_prom->root, "#size-cells", &rsc, sizeof(rsc));
++ prom_debug("root_addr_cells: %x\n", (unsigned long) rac);
++ prom_debug("root_size_cells: %x\n", (unsigned long) rsc);
++
++ prom_debug("scanning memory:\n");
++ path = RELOC(prom_scratch);
++
++ for (node = 0; prom_next_node(&node); ) {
++ type[0] = 0;
++ prom_getprop(node, "device_type", type, sizeof(type));
++
++ if (type[0] == 0) {
++ /*
++ * CHRP Longtrail machines have no device_type
++ * on the memory node, so check the name instead...
++ */
++ prom_getprop(node, "name", type, sizeof(type));
++ }
++ if (strcmp(type, RELOC("memory")))
++ continue;
++
++ plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf));
++ if (plen > sizeof(regbuf)) {
++ prom_printf("memory node too large for buffer !\n");
++ plen = sizeof(regbuf);
++ }
++ p = RELOC(regbuf);
++ endp = p + (plen / sizeof(cell_t));
++
++#ifdef DEBUG_PROM
++ memset(path, 0, PROM_SCRATCH_SIZE);
++ call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
++ prom_debug(" node %s :\n", path);
++#endif /* DEBUG_PROM */
++
++ while ((endp - p) >= (rac + rsc)) {
++ unsigned long base, size;
++
++ base = prom_next_cell(rac, &p);
++ size = prom_next_cell(rsc, &p);
++
++ if (size == 0)
++ continue;
++ prom_debug(" %x %x\n", base, size);
++ if (base == 0)
++ RELOC(rmo_top) = size;
++ if ((base + size) > RELOC(ram_top))
++ RELOC(ram_top) = base + size;
++ }
++ }
++
++ RELOC(alloc_bottom) = PAGE_ALIGN((unsigned long)&RELOC(_end) + 0x4000);
++
++ /* Check if we have an initrd after the kernel, if we do move our bottom
++ * point to after it
++ */
++ if (RELOC(prom_initrd_start)) {
++ if (RELOC(prom_initrd_end) > RELOC(alloc_bottom))
++ RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
++ }
++
++ /*
++ * If prom_memory_limit is set we reduce the upper limits *except* for
++ * alloc_top_high. This must be the real top of RAM so we can put
++ * TCE's up there.
++ */
++
++ RELOC(alloc_top_high) = RELOC(ram_top);
++
++ if (RELOC(prom_memory_limit)) {
++ if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
++ prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
++ RELOC(prom_memory_limit));
++ RELOC(prom_memory_limit) = 0;
++ } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
++ prom_printf("Ignoring mem=%x >= ram_top.\n",
++ RELOC(prom_memory_limit));
++ RELOC(prom_memory_limit) = 0;
++ } else {
++ RELOC(ram_top) = RELOC(prom_memory_limit);
++ RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
++ }
++ }
++
++ /*
++ * Setup our top alloc point, that is top of RMO or top of
++ * segment 0 when running non-LPAR.
++ * Some RS64 machines have buggy firmware where claims up at
++ * 1GB fail. Cap at 768MB as a workaround.
++ * Since 768MB is plenty of room, and we need to cap to something
++ * reasonable on 32-bit, cap at 768MB on all machines.
++ */
++ if (!RELOC(rmo_top))
++ RELOC(rmo_top) = RELOC(ram_top);
++ RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top));
++ RELOC(alloc_top) = RELOC(rmo_top);
++
++ prom_printf("memory layout at init:\n");
++ prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
++ prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
++ prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
++ prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
++ prom_printf(" rmo_top : %x\n", RELOC(rmo_top));
++ prom_printf(" ram_top : %x\n", RELOC(ram_top));
++}
++
++
++/*
++ * Allocate room for and instantiate RTAS
++ */
++static void __init prom_instantiate_rtas(void)
++{
++ phandle rtas_node;
++ ihandle rtas_inst;
++ u32 base, entry = 0;
++ u32 size = 0;
++
++ prom_debug("prom_instantiate_rtas: start...\n");
++
++ rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
++ prom_debug("rtas_node: %x\n", rtas_node);
++ if (!PHANDLE_VALID(rtas_node))
++ return;
++
++ prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
++ if (size == 0)
++ return;
++
++ base = alloc_down(size, PAGE_SIZE, 0);
++ if (base == 0) {
++ prom_printf("RTAS allocation failed !\n");
++ return;
++ }
++
++ rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
++ if (!IHANDLE_VALID(rtas_inst)) {
++ prom_printf("opening rtas package failed");
++ return;
++ }
++
++ prom_printf("instantiating rtas at 0x%x ...", base);
++
++ if (call_prom_ret("call-method", 3, 2, &entry,
++ ADDR("instantiate-rtas"),
++ rtas_inst, base) == PROM_ERROR
++ || entry == 0) {
++ prom_printf(" failed\n");
++ return;
++ }
++ prom_printf(" done\n");
++
++ reserve_mem(base, size);
++
++ prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
++ prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
++
++ prom_debug("rtas base = 0x%x\n", base);
++ prom_debug("rtas entry = 0x%x\n", entry);
++ prom_debug("rtas size = 0x%x\n", (long)size);
++
++ prom_debug("prom_instantiate_rtas: end...\n");
++}
++
++#ifdef CONFIG_PPC64
++/*
++ * Allocate room for and initialize TCE tables
++ */
++static void __init prom_initialize_tce_table(void)
++{
++ phandle node;
++ ihandle phb_node;
++ char compatible[64], type[64], model[64];
++ char *path = RELOC(prom_scratch);
++ u64 base, align;
++ u32 minalign, minsize;
++ u64 tce_entry, *tce_entryp;
++ u64 local_alloc_top, local_alloc_bottom;
++ u64 i;
++
++ if (RELOC(ppc64_iommu_off))
++ return;
++
++ prom_debug("starting prom_initialize_tce_table\n");
++
++ /* Cache current top of allocs so we reserve a single block */
++ local_alloc_top = RELOC(alloc_top_high);
++ local_alloc_bottom = local_alloc_top;
++
++ /* Search all nodes looking for PHBs. */
++ for (node = 0; prom_next_node(&node); ) {
++ compatible[0] = 0;
++ type[0] = 0;
++ model[0] = 0;
++ prom_getprop(node, "compatible",
++ compatible, sizeof(compatible));
++ prom_getprop(node, "device_type", type, sizeof(type));
++ prom_getprop(node, "model", model, sizeof(model));
++
++ if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL))
++ continue;
++
++ /* Keep the old logic in tack to avoid regression. */
++ if (compatible[0] != 0) {
++ if ((strstr(compatible, RELOC("python")) == NULL) &&
++ (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
++ (strstr(compatible, RELOC("Winnipeg")) == NULL))
++ continue;
++ } else if (model[0] != 0) {
++ if ((strstr(model, RELOC("ython")) == NULL) &&
++ (strstr(model, RELOC("peedwagon")) == NULL) &&
++ (strstr(model, RELOC("innipeg")) == NULL))
++ continue;
++ }
++
++ if (prom_getprop(node, "tce-table-minalign", &minalign,
++ sizeof(minalign)) == PROM_ERROR)
++ minalign = 0;
++ if (prom_getprop(node, "tce-table-minsize", &minsize,
++ sizeof(minsize)) == PROM_ERROR)
++ minsize = 4UL << 20;
++
++ /*
++ * Even though we read what OF wants, we just set the table
++ * size to 4 MB. This is enough to map 2GB of PCI DMA space.
++ * By doing this, we avoid the pitfalls of trying to DMA to
++ * MMIO space and the DMA alias hole.
++ *
++ * On POWER4, firmware sets the TCE region by assuming
++ * each TCE table is 8MB. Using this memory for anything
++ * else will impact performance, so we always allocate 8MB.
++ * Anton
++ */
++ if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
++ minsize = 8UL << 20;
++ else
++ minsize = 4UL << 20;
++
++ /* Align to the greater of the align or size */
++ align = max(minalign, minsize);
++ base = alloc_down(minsize, align, 1);
++ if (base == 0)
++ prom_panic("ERROR, cannot find space for TCE table.\n");
++ if (base < local_alloc_bottom)
++ local_alloc_bottom = base;
++
++ /* Save away the TCE table attributes for later use. */
++ prom_setprop(node, "linux,tce-base", &base, sizeof(base));
++ prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
++
++ /* It seems OF doesn't null-terminate the path :-( */
++ memset(path, 0, sizeof(path));
++ /* Call OF to setup the TCE hardware */
++ if (call_prom("package-to-path", 3, 1, node,
++ path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
++ prom_printf("package-to-path failed\n");
++ }
++
++ prom_debug("TCE table: %s\n", path);
++ prom_debug("\tnode = 0x%x\n", node);
++ prom_debug("\tbase = 0x%x\n", base);
++ prom_debug("\tsize = 0x%x\n", minsize);
++
++ /* Initialize the table to have a one-to-one mapping
++ * over the allocated size.
++ */
++ tce_entryp = (unsigned long *)base;
++ for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
++ tce_entry = (i << PAGE_SHIFT);
++ tce_entry |= 0x3;
++ *tce_entryp = tce_entry;
++ }
++
++ prom_printf("opening PHB %s", path);
++ phb_node = call_prom("open", 1, 1, path);
++ if (phb_node == 0)
++ prom_printf("... failed\n");
++ else
++ prom_printf("... done\n");
++
++ call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
++ phb_node, -1, minsize,
++ (u32) base, (u32) (base >> 32));
++ call_prom("close", 1, 0, phb_node);
++ }
++
++ reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
++
++ if (RELOC(prom_memory_limit)) {
++ /*
++ * We align the start to a 16MB boundary so we can map
++ * the TCE area using large pages if possible.
++ * The end should be the top of RAM so no need to align it.
++ */
++ RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom,
++ 0x1000000);
++ RELOC(prom_tce_alloc_end) = local_alloc_top;
++ }
++
++ /* Flag the first invalid entry */
++ prom_debug("ending prom_initialize_tce_table\n");
++}
++#endif
++
++/*
++ * With CHRP SMP we need to use the OF to start the other processors.
++ * We can't wait until smp_boot_cpus (the OF is trashed by then)
++ * so we have to put the processors into a holding pattern controlled
++ * by the kernel (not OF) before we destroy the OF.
++ *
++ * This uses a chunk of low memory, puts some holding pattern
++ * code there and sends the other processors off to there until
++ * smp_boot_cpus tells them to do something. The holding pattern
++ * checks that address until its cpu # is there, when it is that
++ * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
++ * of setting those values.
++ *
++ * We also use physical address 0x4 here to tell when a cpu
++ * is in its holding pattern code.
++ *
++ * -- Cort
++ */
++extern void __secondary_hold(void);
++extern unsigned long __secondary_hold_spinloop;
++extern unsigned long __secondary_hold_acknowledge;
++
++/*
++ * We want to reference the copy of __secondary_hold_* in the
++ * 0 - 0x100 address range
++ */
++#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
++
++static void __init prom_hold_cpus(void)
++{
++ unsigned long i;
++ unsigned int reg;
++ phandle node;
++ char type[64];
++ int cpuid = 0;
++ unsigned int interrupt_server[MAX_CPU_THREADS];
++ unsigned int cpu_threads, hw_cpu_num;
++ int propsize;
++ struct prom_t *_prom = &RELOC(prom);
++ unsigned long *spinloop
++ = (void *) LOW_ADDR(__secondary_hold_spinloop);
++ unsigned long *acknowledge
++ = (void *) LOW_ADDR(__secondary_hold_acknowledge);
++#ifdef CONFIG_PPC64
++ /* __secondary_hold is actually a descriptor, not the text address */
++ unsigned long secondary_hold
++ = __pa(*PTRRELOC((unsigned long *)__secondary_hold));
++#else
++ unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
++#endif
++
++ prom_debug("prom_hold_cpus: start...\n");
++ prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
++ prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
++ prom_debug(" 1) acknowledge = 0x%x\n",
++ (unsigned long)acknowledge);
++ prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge);
++ prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold);
++
++ /* Set the common spinloop variable, so all of the secondary cpus
++ * will block when they are awakened from their OF spinloop.
++ * This must occur for both SMP and non SMP kernels, since OF will
++ * be trashed when we move the kernel.
++ */
++ *spinloop = 0;
++
++#ifdef CONFIG_HMT
++ for (i = 0; i < NR_CPUS; i++)
++ RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
++#endif
++ /* look for cpus */
++ for (node = 0; prom_next_node(&node); ) {
++ type[0] = 0;
++ prom_getprop(node, "device_type", type, sizeof(type));
++ if (strcmp(type, RELOC("cpu")) != 0)
++ continue;
++
++ /* Skip non-configured cpus. */
++ if (prom_getprop(node, "status", type, sizeof(type)) > 0)
++ if (strcmp(type, RELOC("okay")) != 0)
++ continue;
++
++ reg = -1;
++ prom_getprop(node, "reg", ®, sizeof(reg));
++
++ prom_debug("\ncpuid = 0x%x\n", cpuid);
++ prom_debug("cpu hw idx = 0x%x\n", reg);
++
++ /* Init the acknowledge var which will be reset by
++ * the secondary cpu when it awakens from its OF
++ * spinloop.
++ */
++ *acknowledge = (unsigned long)-1;
++
++ propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
++ &interrupt_server,
++ sizeof(interrupt_server));
++ if (propsize < 0) {
++ /* no property. old hardware has no SMT */
++ cpu_threads = 1;
++ interrupt_server[0] = reg; /* fake it with phys id */
++ } else {
++ /* We have a threaded processor */
++ cpu_threads = propsize / sizeof(u32);
++ if (cpu_threads > MAX_CPU_THREADS) {
++ prom_printf("SMT: too many threads!\n"
++ "SMT: found %x, max is %x\n",
++ cpu_threads, MAX_CPU_THREADS);
++ cpu_threads = 1; /* ToDo: panic? */
++ }
++ }
++
++ hw_cpu_num = interrupt_server[0];
++ if (hw_cpu_num != _prom->cpu) {
++ /* Primary Thread of non-boot cpu */
++ prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);
++ call_prom("start-cpu", 3, 0, node,
++ secondary_hold, reg);
++
++ for (i = 0; (i < 100000000) &&
++ (*acknowledge == ((unsigned long)-1)); i++ )
++ mb();
++
++ if (*acknowledge == reg)
++ prom_printf("done\n");
++ else
++ prom_printf("failed: %x\n", *acknowledge);
++ }
++#ifdef CONFIG_SMP
++ else
++ prom_printf("%x : boot cpu %x\n", cpuid, reg);
++#endif /* CONFIG_SMP */
++
++ /* Reserve cpu #s for secondary threads. They start later. */
++ cpuid += cpu_threads;
++ }
++#ifdef CONFIG_HMT
++ /* Only enable HMT on processors that provide support. */
++ if (__is_processor(PV_PULSAR) ||
++ __is_processor(PV_ICESTAR) ||
++ __is_processor(PV_SSTAR)) {
++ prom_printf(" starting secondary threads\n");
++
++ for (i = 0; i < NR_CPUS; i += 2) {
++ if (!cpu_online(i))
++ continue;
++
++ if (i == 0) {
++ unsigned long pir = mfspr(SPRN_PIR);
++ if (__is_processor(PV_PULSAR)) {
++ RELOC(hmt_thread_data)[i].pir =
++ pir & 0x1f;
++ } else {
++ RELOC(hmt_thread_data)[i].pir =
++ pir & 0x3ff;
++ }
++ }
++ }
++ } else {
++ prom_printf("Processor is not HMT capable\n");
++ }
++#endif
++
++ if (cpuid > NR_CPUS)
++ prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
++ ") exceeded: ignoring extras\n");
++
++ prom_debug("prom_hold_cpus: end...\n");
++}
++
++
++static void __init prom_init_client_services(unsigned long pp)
++{
++ struct prom_t *_prom = &RELOC(prom);
++
++ /* Get a handle to the prom entry point before anything else */
++ RELOC(prom_entry) = pp;
++
++ /* get a handle for the stdout device */
++ _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
++ if (!PHANDLE_VALID(_prom->chosen))
++ prom_panic("cannot find chosen"); /* msg won't be printed :( */
++
++ /* get device tree root */
++ _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
++ if (!PHANDLE_VALID(_prom->root))
++ prom_panic("cannot find device tree root"); /* msg won't be printed :( */
++
++ _prom->mmumap = 0;
++}
++
++#ifdef CONFIG_PPC32
++/*
++ * For really old powermacs, we need to map things we claim.
++ * For that, we need the ihandle of the mmu.
++ */
++static void __init prom_find_mmu(void)
++{
++ struct prom_t *_prom = &RELOC(prom);
++ phandle oprom;
++ char version[64];
++
++ oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
++ if (!PHANDLE_VALID(oprom))
++ return;
++ if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
++ return;
++ version[sizeof(version) - 1] = 0;
++ prom_printf("OF version is '%s'\n", version);
++ /* XXX might need to add other versions here */
++ if (strcmp(version, "Open Firmware, 1.0.5") != 0)
++ return;
++ prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
++ sizeof(_prom->mmumap));
++}
++#else
++#define prom_find_mmu()
++#endif
++
++static void __init prom_init_stdout(void)
++{
++ struct prom_t *_prom = &RELOC(prom);
++ char *path = RELOC(of_stdout_device);
++ char type[16];
++ u32 val;
++
++ if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)
++ prom_panic("cannot find stdout");
++
++ _prom->stdout = val;
++
++ /* Get the full OF pathname of the stdout device */
++ memset(path, 0, 256);
++ call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
++ val = call_prom("instance-to-package", 1, 1, _prom->stdout);
++ prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));
++ prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
++ prom_setprop(_prom->chosen, "linux,stdout-path",
++ RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);
++
++ /* If it's a display, note it */
++ memset(type, 0, sizeof(type));
++ prom_getprop(val, "device_type", type, sizeof(type));
++ if (strcmp(type, RELOC("display")) == 0)
++ prom_setprop(val, "linux,boot-display", NULL, 0);
++}
++
++static void __init prom_close_stdin(void)
++{
++ struct prom_t *_prom = &RELOC(prom);
++ ihandle val;
++
++ if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
++ call_prom("close", 1, 0, val);
++}
++
++static int __init prom_find_machine_type(void)
++{
++ struct prom_t *_prom = &RELOC(prom);
++ char compat[256];
++ int len, i = 0;
++ phandle rtas;
++
++ len = prom_getprop(_prom->root, "compatible",
++ compat, sizeof(compat)-1);
++ if (len > 0) {
++ compat[len] = 0;
++ while (i < len) {
++ char *p = &compat[i];
++ int sl = strlen(p);
++ if (sl == 0)
++ break;
++ if (strstr(p, RELOC("Power Macintosh")) ||
++ strstr(p, RELOC("MacRISC")))
++ return PLATFORM_POWERMAC;
++#ifdef CONFIG_PPC64
++ if (strstr(p, RELOC("Momentum,Maple")))
++ return PLATFORM_MAPLE;
++#endif
++ i += sl + 1;
++ }
++ }
++#ifdef CONFIG_PPC64
++ /* Default to pSeries. We need to know if we are running LPAR */
++ rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
++ if (PHANDLE_VALID(rtas)) {
++ int x = prom_getproplen(rtas, "ibm,hypertas-functions");
++ if (x != PROM_ERROR) {
++ prom_printf("Hypertas detected, assuming LPAR !\n");
++ return PLATFORM_PSERIES_LPAR;
++ }
++ }
++ return PLATFORM_PSERIES;
++#else
++ return PLATFORM_CHRP;
++#endif
++}
++
++static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
++{
++ return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
++}
++
++/*
++ * If we have a display that we don't know how to drive,
++ * we will want to try to execute OF's open method for it
++ * later. However, OF will probably fall over if we do that
++ * we've taken over the MMU.
++ * So we check whether we will need to open the display,
++ * and if so, open it now.
++ */
++static void __init prom_check_displays(void)
++{
++ char type[16], *path;
++ phandle node;
++ ihandle ih;
++ int i;
++
++ static unsigned char default_colors[] = {
++ 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xaa,
++ 0x00, 0xaa, 0x00,
++ 0x00, 0xaa, 0xaa,
++ 0xaa, 0x00, 0x00,
++ 0xaa, 0x00, 0xaa,
++ 0xaa, 0xaa, 0x00,
++ 0xaa, 0xaa, 0xaa,
++ 0x55, 0x55, 0x55,
++ 0x55, 0x55, 0xff,
++ 0x55, 0xff, 0x55,
++ 0x55, 0xff, 0xff,
++ 0xff, 0x55, 0x55,
++ 0xff, 0x55, 0xff,
++ 0xff, 0xff, 0x55,
++ 0xff, 0xff, 0xff
++ };
++ const unsigned char *clut;
++
++ prom_printf("Looking for displays\n");
++ for (node = 0; prom_next_node(&node); ) {
++ memset(type, 0, sizeof(type));
++ prom_getprop(node, "device_type", type, sizeof(type));
++ if (strcmp(type, RELOC("display")) != 0)
++ continue;
++
++ /* It seems OF doesn't null-terminate the path :-( */
++ path = RELOC(prom_scratch);
++ memset(path, 0, PROM_SCRATCH_SIZE);
++
++ /*
++ * leave some room at the end of the path for appending extra
++ * arguments
++ */
++ if (call_prom("package-to-path", 3, 1, node, path,
++ PROM_SCRATCH_SIZE-10) == PROM_ERROR)
++ continue;
++ prom_printf("found display : %s, opening ... ", path);
++
++ ih = call_prom("open", 1, 1, path);
++ if (ih == 0) {
++ prom_printf("failed\n");
++ continue;
++ }
++
++ /* Success */
++ prom_printf("done\n");
++ prom_setprop(node, "linux,opened", NULL, 0);
++
++ /* Setup a usable color table when the appropriate
++ * method is available. Should update this to set-colors */
++ clut = RELOC(default_colors);
++ for (i = 0; i < 32; i++, clut += 3)
++ if (prom_set_color(ih, i, clut[0], clut[1],
++ clut[2]) != 0)
++ break;
++
++#ifdef CONFIG_LOGO_LINUX_CLUT224
++ clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
++ for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
++ if (prom_set_color(ih, i + 32, clut[0], clut[1],
++ clut[2]) != 0)
++ break;
++#endif /* CONFIG_LOGO_LINUX_CLUT224 */
++ }
++}
++
++
++/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
++static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
++ unsigned long needed, unsigned long align)
++{
++ void *ret;
++
++ *mem_start = _ALIGN(*mem_start, align);
++ while ((*mem_start + needed) > *mem_end) {
++ unsigned long room, chunk;
++
++ prom_debug("Chunk exhausted, claiming more at %x...\n",
++ RELOC(alloc_bottom));
++ room = RELOC(alloc_top) - RELOC(alloc_bottom);
++ if (room > DEVTREE_CHUNK_SIZE)
++ room = DEVTREE_CHUNK_SIZE;
++ if (room < PAGE_SIZE)
++ prom_panic("No memory for flatten_device_tree (no room)");
++ chunk = alloc_up(room, 0);
++ if (chunk == 0)
++ prom_panic("No memory for flatten_device_tree (claim failed)");
++ *mem_end = RELOC(alloc_top);
++ }
++
++ ret = (void *)*mem_start;
++ *mem_start += needed;
++
++ return ret;
++}
++
++#define dt_push_token(token, mem_start, mem_end) \
++ do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0)
++
++static unsigned long __init dt_find_string(char *str)
++{
++ char *s, *os;
++
++ s = os = (char *)RELOC(dt_string_start);
++ s += 4;
++ while (s < (char *)RELOC(dt_string_end)) {
++ if (strcmp(s, str) == 0)
++ return s - os;
++ s += strlen(s) + 1;
++ }
++ return 0;
++}
++
++/*
++ * The Open Firmware 1275 specification states properties must be 31 bytes or
++ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
++ */
++#define MAX_PROPERTY_NAME 64
++
++static void __init scan_dt_build_strings(phandle node,
++ unsigned long *mem_start,
++ unsigned long *mem_end)
++{
++ char *prev_name, *namep, *sstart;
++ unsigned long soff;
++ phandle child;
++
++ sstart = (char *)RELOC(dt_string_start);
++
++ /* get and store all property names */
++ prev_name = RELOC("");
++ for (;;) {
++ /* 64 is max len of name including nul. */
++ namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
++ if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
++ /* No more nodes: unwind alloc */
++ *mem_start = (unsigned long)namep;
++ break;
++ }
++
++ /* skip "name" */
++ if (strcmp(namep, RELOC("name")) == 0) {
++ *mem_start = (unsigned long)namep;
++ prev_name = RELOC("name");
++ continue;
++ }
++ /* get/create string entry */
++ soff = dt_find_string(namep);
++ if (soff != 0) {
++ *mem_start = (unsigned long)namep;
++ namep = sstart + soff;
++ } else {
++ /* Trim off some if we can */
++ *mem_start = (unsigned long)namep + strlen(namep) + 1;
++ RELOC(dt_string_end) = *mem_start;
++ }
++ prev_name = namep;
++ }
++
++ /* do all our children */
++ child = call_prom("child", 1, 1, node);
++ while (child != 0) {
++ scan_dt_build_strings(child, mem_start, mem_end);
++ child = call_prom("peer", 1, 1, child);
++ }
++}
++
++static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
++ unsigned long *mem_end)
++{
++ phandle child;
++ char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
++ unsigned long soff;
++ unsigned char *valp;
++ static char pname[MAX_PROPERTY_NAME];
++ int l, room;
++
++ dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
++
++ /* get the node's full name */
++ namep = (char *)*mem_start;
++ room = *mem_end - *mem_start;
++ if (room > 255)
++ room = 255;
++ l = call_prom("package-to-path", 3, 1, node, namep, room);
++ if (l >= 0) {
++ /* Didn't fit? Get more room. */
++ if (l >= room) {
++ if (l >= *mem_end - *mem_start)
++ namep = make_room(mem_start, mem_end, l+1, 1);
++ call_prom("package-to-path", 3, 1, node, namep, l);
++ }
++ namep[l] = '\0';
++
++ /* Fixup an Apple bug where they have bogus \0 chars in the
++ * middle of the path in some properties, and extract
++ * the unit name (everything after the last '/').
++ */
++ for (lp = p = namep, ep = namep + l; p < ep; p++) {
++ if (*p == '/')
++ lp = namep;
++ else if (*p != 0)
++ *lp++ = *p;
++ }
++ *lp = 0;
++ *mem_start = _ALIGN((unsigned long)lp + 1, 4);
++ }
++
++ /* get it again for debugging */
++ path = RELOC(prom_scratch);
++ memset(path, 0, PROM_SCRATCH_SIZE);
++ call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
++
++ /* get and store all properties */
++ prev_name = RELOC("");
++ sstart = (char *)RELOC(dt_string_start);
++ for (;;) {
++ if (call_prom("nextprop", 3, 1, node, prev_name,
++ RELOC(pname)) != 1)
++ break;
++
++ /* skip "name" */
++ if (strcmp(RELOC(pname), RELOC("name")) == 0) {
++ prev_name = RELOC("name");
++ continue;
++ }
++
++ /* find string offset */
++ soff = dt_find_string(RELOC(pname));
++ if (soff == 0) {
++ prom_printf("WARNING: Can't find string index for"
++ " <%s>, node %s\n", RELOC(pname), path);
++ break;
++ }
++ prev_name = sstart + soff;
++
++ /* get length */
++ l = call_prom("getproplen", 2, 1, node, RELOC(pname));
++
++ /* sanity checks */
++ if (l == PROM_ERROR)
++ continue;
++ if (l > MAX_PROPERTY_LENGTH) {
++ prom_printf("WARNING: ignoring large property ");
++ /* It seems OF doesn't null-terminate the path :-( */
++ prom_printf("[%s] ", path);
++ prom_printf("%s length 0x%x\n", RELOC(pname), l);
++ continue;
++ }
++
++ /* push property head */
++ dt_push_token(OF_DT_PROP, mem_start, mem_end);
++ dt_push_token(l, mem_start, mem_end);
++ dt_push_token(soff, mem_start, mem_end);
++
++ /* push property content */
++ valp = make_room(mem_start, mem_end, l, 4);
++ call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
++ *mem_start = _ALIGN(*mem_start, 4);
++ }
++
++ /* Add a "linux,phandle" property. */
++ soff = dt_find_string(RELOC("linux,phandle"));
++ if (soff == 0)
++ prom_printf("WARNING: Can't find string index for"
++ " <linux-phandle> node %s\n", path);
++ else {
++ dt_push_token(OF_DT_PROP, mem_start, mem_end);
++ dt_push_token(4, mem_start, mem_end);
++ dt_push_token(soff, mem_start, mem_end);
++ valp = make_room(mem_start, mem_end, 4, 4);
++ *(u32 *)valp = node;
++ }
++
++ /* do all our children */
++ child = call_prom("child", 1, 1, node);
++ while (child != 0) {
++ scan_dt_build_struct(child, mem_start, mem_end);
++ child = call_prom("peer", 1, 1, child);
++ }
++
++ dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
++}
++
++static void __init flatten_device_tree(void)
++{
++ phandle root;
++ unsigned long mem_start, mem_end, room;
++ struct boot_param_header *hdr;
++ struct prom_t *_prom = &RELOC(prom);
++ char *namep;
++ u64 *rsvmap;
++
++ /*
++ * Check how much room we have between alloc top & bottom (+/- a
++ * few pages), crop to 4Mb, as this is our "chuck" size
++ */
++ room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;
++ if (room > DEVTREE_CHUNK_SIZE)
++ room = DEVTREE_CHUNK_SIZE;
++ prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom));
++
++ /* Now try to claim that */
++ mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
++ if (mem_start == 0)
++ prom_panic("Can't allocate initial device-tree chunk\n");
++ mem_end = RELOC(alloc_top);
++
++ /* Get root of tree */
++ root = call_prom("peer", 1, 1, (phandle)0);
++ if (root == (phandle)0)
++ prom_panic ("couldn't get device tree root\n");
++
++ /* Build header and make room for mem rsv map */
++ mem_start = _ALIGN(mem_start, 4);
++ hdr = make_room(&mem_start, &mem_end,
++ sizeof(struct boot_param_header), 4);
++ RELOC(dt_header_start) = (unsigned long)hdr;
++ rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
++
++ /* Start of strings */
++ mem_start = PAGE_ALIGN(mem_start);
++ RELOC(dt_string_start) = mem_start;
++ mem_start += 4; /* hole */
++
++ /* Add "linux,phandle" in there, we'll need it */
++ namep = make_room(&mem_start, &mem_end, 16, 1);
++ strcpy(namep, RELOC("linux,phandle"));
++ mem_start = (unsigned long)namep + strlen(namep) + 1;
++
++ /* Build string array */
++ prom_printf("Building dt strings...\n");
++ scan_dt_build_strings(root, &mem_start, &mem_end);
++ RELOC(dt_string_end) = mem_start;
++
++ /* Build structure */
++ mem_start = PAGE_ALIGN(mem_start);
++ RELOC(dt_struct_start) = mem_start;
++ prom_printf("Building dt structure...\n");
++ scan_dt_build_struct(root, &mem_start, &mem_end);
++ dt_push_token(OF_DT_END, &mem_start, &mem_end);
++ RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
++
++ /* Finish header */
++ hdr->boot_cpuid_phys = _prom->cpu;
++ hdr->magic = OF_DT_HEADER;
++ hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
++ hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
++ hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
++ hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
++ hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
++ hdr->version = OF_DT_VERSION;
++ /* Version 16 is not backward compatible */
++ hdr->last_comp_version = 0x10;
++
++ /* Reserve the whole thing and copy the reserve map in, we
++ * also bump mem_reserve_cnt to cause further reservations to
++ * fail since it's too late.
++ */
++ reserve_mem(RELOC(dt_header_start), hdr->totalsize);
++ memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
++
++#ifdef DEBUG_PROM
++ {
++ int i;
++ prom_printf("reserved memory map:\n");
++ for (i = 0; i < RELOC(mem_reserve_cnt); i++)
++ prom_printf(" %x - %x\n",
++ RELOC(mem_reserve_map)[i].base,
++ RELOC(mem_reserve_map)[i].size);
++ }
++#endif
++ RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
++
++ prom_printf("Device tree strings 0x%x -> 0x%x\n",
++ RELOC(dt_string_start), RELOC(dt_string_end));
++ prom_printf("Device tree struct 0x%x -> 0x%x\n",
++ RELOC(dt_struct_start), RELOC(dt_struct_end));
++
++}
++
++
++static void __init fixup_device_tree(void)
++{
++#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
++ phandle u3, i2c, mpic;
++ u32 u3_rev;
++ u32 interrupts[2];
++ u32 parent;
++
++ /* Some G5s have a missing interrupt definition, fix it up here */
++ u3 = call_prom("finddevice", 1, 1, ADDR("/u3 at 0,f8000000"));
++ if (!PHANDLE_VALID(u3))
++ return;
++ i2c = call_prom("finddevice", 1, 1, ADDR("/u3 at 0,f8000000/i2c at f8001000"));
++ if (!PHANDLE_VALID(i2c))
++ return;
++ mpic = call_prom("finddevice", 1, 1, ADDR("/u3 at 0,f8000000/mpic at f8040000"));
++ if (!PHANDLE_VALID(mpic))
++ return;
++
++ /* check if proper rev of u3 */
++ if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
++ == PROM_ERROR)
++ return;
++ if (u3_rev != 0x35 && u3_rev != 0x37)
++ return;
++ /* does it need fixup ? */
++ if (prom_getproplen(i2c, "interrupts") > 0)
++ return;
++
++ prom_printf("fixing up bogus interrupts for u3 i2c...\n");
++
++ /* interrupt on this revision of u3 is number 0 and level */
++ interrupts[0] = 0;
++ interrupts[1] = 1;
++ prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
++ parent = (u32)mpic;
++ prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
++#endif
++}
++
++
++static void __init prom_find_boot_cpu(void)
++{
++ struct prom_t *_prom = &RELOC(prom);
++ u32 getprop_rval;
++ ihandle prom_cpu;
++ phandle cpu_pkg;
++
++ _prom->cpu = 0;
++ if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
++ return;
++
++ cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
++
++ prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
++ _prom->cpu = getprop_rval;
++
++ prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
++}
++
++static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
++{
++#ifdef CONFIG_BLK_DEV_INITRD
++ struct prom_t *_prom = &RELOC(prom);
++
++ if (r3 && r4 && r4 != 0xdeadbeef) {
++ unsigned long val;
++
++ RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
++ RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
++
++ val = RELOC(prom_initrd_start);
++ prom_setprop(_prom->chosen, "linux,initrd-start", &val,
++ sizeof(val));
++ val = RELOC(prom_initrd_end);
++ prom_setprop(_prom->chosen, "linux,initrd-end", &val,
++ sizeof(val));
++
++ reserve_mem(RELOC(prom_initrd_start),
++ RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
++
++ prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start));
++ prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end));
++ }
++#endif /* CONFIG_BLK_DEV_INITRD */
++}
++
++/*
++ * We enter here early on, when the Open Firmware prom is still
++ * handling exceptions and the MMU hash table for us.
++ */
++
++unsigned long __init prom_init(unsigned long r3, unsigned long r4,
++ unsigned long pp,
++ unsigned long r6, unsigned long r7)
++{
++ struct prom_t *_prom;
++ unsigned long hdr;
++ u32 getprop_rval;
++ unsigned long offset = reloc_offset();
++
++#ifdef CONFIG_PPC32
++ reloc_got2(offset);
++#endif
++
++ _prom = &RELOC(prom);
++
++ /*
++ * First zero the BSS
++ */
++ memset(&RELOC(__bss_start), 0, __bss_stop - __bss_start);
++
++ /*
++ * Init interface to Open Firmware, get some node references,
++ * like /chosen
++ */
++ prom_init_client_services(pp);
++
++ /*
++ * Init prom stdout device
++ */
++ prom_init_stdout();
++
++ /*
++ * See if this OF is old enough that we need to do explicit maps
++ */
++ prom_find_mmu();
++
++ /*
++ * Check for an initrd
++ */
++ prom_check_initrd(r3, r4);
++
++ /*
++ * Get default machine type. At this point, we do not differentiate
++ * between pSeries SMP and pSeries LPAR
++ */
++ RELOC(of_platform) = prom_find_machine_type();
++ getprop_rval = RELOC(of_platform);
++ prom_setprop(_prom->chosen, "linux,platform",
++ &getprop_rval, sizeof(getprop_rval));
++
++#ifdef CONFIG_PPC_PSERIES
++ /*
++ * On pSeries, inform the firmware about our capabilities
++ */
++ if (RELOC(of_platform) & PLATFORM_PSERIES)
++ prom_send_capabilities();
++#endif
++
++ /*
++ * On pSeries and BPA, copy the CPU hold code
++ */
++ if (RELOC(of_platform) != PLATFORM_POWERMAC)
++ copy_and_flush(0, KERNELBASE + offset, 0x100, 0);
++
++ /*
++ * Do early parsing of command line
++ */
++ early_cmdline_parse();
++
++ /*
++ * Initialize memory management within prom_init
++ */
++ prom_init_mem();
++
++ /*
++ * Determine which cpu is actually running right _now_
++ */
++ prom_find_boot_cpu();
++
++ /*
++ * Initialize display devices
++ */
++ prom_check_displays();
++
++#ifdef CONFIG_PPC64
++ /*
++ * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
++ * that uses the allocator, we need to make sure we get the top of memory
++ * available for us here...
++ */
++ if (RELOC(of_platform) == PLATFORM_PSERIES)
++ prom_initialize_tce_table();
++#endif
++
++ /*
++ * On non-powermacs, try to instantiate RTAS and puts all CPUs
++ * in spin-loops. PowerMacs don't have a working RTAS and use
++ * a different way to spin CPUs
++ */
++ if (RELOC(of_platform) != PLATFORM_POWERMAC) {
++ prom_instantiate_rtas();
++ prom_hold_cpus();
++ }
++
++ /*
++ * Fill in some infos for use by the kernel later on
++ */
++ if (RELOC(prom_memory_limit))
++ prom_setprop(_prom->chosen, "linux,memory-limit",
++ &RELOC(prom_memory_limit),
++ sizeof(prom_memory_limit));
++#ifdef CONFIG_PPC64
++ if (RELOC(ppc64_iommu_off))
++ prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
++
++ if (RELOC(iommu_force_on))
++ prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
++
++ if (RELOC(prom_tce_alloc_start)) {
++ prom_setprop(_prom->chosen, "linux,tce-alloc-start",
++ &RELOC(prom_tce_alloc_start),
++ sizeof(prom_tce_alloc_start));
++ prom_setprop(_prom->chosen, "linux,tce-alloc-end",
++ &RELOC(prom_tce_alloc_end),
++ sizeof(prom_tce_alloc_end));
++ }
++#endif
++
++ /*
++ * Fixup any known bugs in the device-tree
++ */
++ fixup_device_tree();
++
++ /*
++ * Now finally create the flattened device-tree
++ */
++ prom_printf("copying OF device tree ...\n");
++ flatten_device_tree();
++
++ /* in case stdin is USB and still active on IBM machines... */
++ prom_close_stdin();
++
++ /*
++ * Call OF "quiesce" method to shut down pending DMA's from
++ * devices etc...
++ */
++ prom_printf("Calling quiesce ...\n");
++ call_prom("quiesce", 0, 0);
++
++ /*
++ * And finally, call the kernel passing it the flattened device
++ * tree and NULL as r5, thus triggering the new entry point which
++ * is common to us and kexec
++ */
++ hdr = RELOC(dt_header_start);
++ prom_printf("returning from prom_init\n");
++ prom_debug("->dt_header_start=0x%x\n", hdr);
++
++#ifdef CONFIG_PPC32
++ reloc_got2(-offset);
++#endif
++
++ __start(hdr, KERNELBASE + offset, 0);
++
++ return 0;
++}
+diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/ptrace.c
+@@ -0,0 +1,613 @@
++/*
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Derived from "arch/m68k/kernel/ptrace.c"
++ * Copyright (C) 1994 by Hamish Macdonald
++ * Taken from linux/kernel/ptrace.c and modified for M680x0.
++ * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
++ *
++ * Modified by Cort Dougan (cort at hq.fsmlabs.com)
++ * and Paul Mackerras (paulus at samba.org).
++ *
++ * This file is subject to the terms and conditions of the GNU General
++ * Public License. See the file README.legal in the main directory of
++ * this archive for more details.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/errno.h>
++#include <linux/ptrace.h>
++#include <linux/user.h>
++#include <linux/security.h>
++#include <linux/signal.h>
++#include <linux/seccomp.h>
++#include <linux/audit.h>
++#ifdef CONFIG_PPC32
++#include <linux/module.h>
++#endif
++
++#include <asm/uaccess.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#ifdef CONFIG_PPC64
++#include <asm/ptrace-common.h>
++#endif
++
++#ifdef CONFIG_PPC32
++/*
++ * Set of msr bits that gdb can change on behalf of a process.
++ */
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++#define MSR_DEBUGCHANGE 0
++#else
++#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
++#endif
++#endif /* CONFIG_PPC32 */
++
++/*
++ * does not yet catch signals sent when the child dies.
++ * in exit.c or in signal.c.
++ */
++
++#ifdef CONFIG_PPC32
++/*
++ * Get contents of register REGNO in task TASK.
++ */
++static inline unsigned long get_reg(struct task_struct *task, int regno)
++{
++ if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
++ && task->thread.regs != NULL)
++ return ((unsigned long *)task->thread.regs)[regno];
++ return (0);
++}
++
++/*
++ * Write contents of register REGNO in task TASK.
++ */
++static inline int put_reg(struct task_struct *task, int regno,
++ unsigned long data)
++{
++ if (regno <= PT_MQ && task->thread.regs != NULL) {
++ if (regno == PT_MSR)
++ data = (data & MSR_DEBUGCHANGE)
++ | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
++ ((unsigned long *)task->thread.regs)[regno] = data;
++ return 0;
++ }
++ return -EIO;
++}
++
++#ifdef CONFIG_ALTIVEC
++/*
++ * Get contents of AltiVec register state in task TASK
++ */
++static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
++{
++ int i, j;
++
++ if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
++ return -EFAULT;
++
++ /* copy AltiVec registers VR[0] .. VR[31] */
++ for (i = 0; i < 32; i++)
++ for (j = 0; j < 4; j++, data++)
++ if (__put_user(task->thread.vr[i].u[j], data))
++ return -EFAULT;
++
++ /* copy VSCR */
++ for (i = 0; i < 4; i++, data++)
++ if (__put_user(task->thread.vscr.u[i], data))
++ return -EFAULT;
++
++ /* copy VRSAVE */
++ if (__put_user(task->thread.vrsave, data))
++ return -EFAULT;
++
++ return 0;
++}
++
++/*
++ * Write contents of AltiVec register state into task TASK.
++ */
++static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
++{
++ int i, j;
++
++ if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
++ return -EFAULT;
++
++ /* copy AltiVec registers VR[0] .. VR[31] */
++ for (i = 0; i < 32; i++)
++ for (j = 0; j < 4; j++, data++)
++ if (__get_user(task->thread.vr[i].u[j], data))
++ return -EFAULT;
++
++ /* copy VSCR */
++ for (i = 0; i < 4; i++, data++)
++ if (__get_user(task->thread.vscr.u[i], data))
++ return -EFAULT;
++
++ /* copy VRSAVE */
++ if (__get_user(task->thread.vrsave, data))
++ return -EFAULT;
++
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SPE
++
++/*
++ * For get_evrregs/set_evrregs functions 'data' has the following layout:
++ *
++ * struct {
++ * u32 evr[32];
++ * u64 acc;
++ * u32 spefscr;
++ * }
++ */
++
++/*
++ * Get contents of SPE register state in task TASK.
++ */
++static inline int get_evrregs(unsigned long *data, struct task_struct *task)
++{
++ int i;
++
++ if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
++ return -EFAULT;
++
++ /* copy SPEFSCR */
++ if (__put_user(task->thread.spefscr, &data[34]))
++ return -EFAULT;
++
++ /* copy SPE registers EVR[0] .. EVR[31] */
++ for (i = 0; i < 32; i++, data++)
++ if (__put_user(task->thread.evr[i], data))
++ return -EFAULT;
++
++ /* copy ACC */
++ if (__put_user64(task->thread.acc, (unsigned long long *)data))
++ return -EFAULT;
++
++ return 0;
++}
++
++/*
++ * Write contents of SPE register state into task TASK.
++ */
++static inline int set_evrregs(struct task_struct *task, unsigned long *data)
++{
++ int i;
++
++ if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
++ return -EFAULT;
++
++ /* copy SPEFSCR */
++ if (__get_user(task->thread.spefscr, &data[34]))
++ return -EFAULT;
++
++ /* copy SPE registers EVR[0] .. EVR[31] */
++ for (i = 0; i < 32; i++, data++)
++ if (__get_user(task->thread.evr[i], data))
++ return -EFAULT;
++ /* copy ACC */
++ if (__get_user64(task->thread.acc, (unsigned long long*)data))
++ return -EFAULT;
++
++ return 0;
++}
++#endif /* CONFIG_SPE */
++
++static inline void
++set_single_step(struct task_struct *task)
++{
++ struct pt_regs *regs = task->thread.regs;
++
++ if (regs != NULL) {
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++ task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
++ regs->msr |= MSR_DE;
++#else
++ regs->msr |= MSR_SE;
++#endif
++ }
++}
++
++static inline void
++clear_single_step(struct task_struct *task)
++{
++ struct pt_regs *regs = task->thread.regs;
++
++ if (regs != NULL) {
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++ task->thread.dbcr0 = 0;
++ regs->msr &= ~MSR_DE;
++#else
++ regs->msr &= ~MSR_SE;
++#endif
++ }
++}
++#endif /* CONFIG_PPC32 */
++
++/*
++ * Called by kernel/ptrace.c when detaching..
++ *
++ * Make sure single step bits etc are not set.
++ */
++void ptrace_disable(struct task_struct *child)
++{
++ /* make sure the single step bit is not set. */
++ clear_single_step(child);
++}
++
++long sys_ptrace(long request, long pid, long addr, long data)
++{
++ struct task_struct *child;
++ int ret = -EPERM;
++
++ lock_kernel();
++ if (request == PTRACE_TRACEME) {
++ /* are we already being traced? */
++ if (current->ptrace & PT_PTRACED)
++ goto out;
++ ret = security_ptrace(current->parent, current);
++ if (ret)
++ goto out;
++ /* set the ptrace bit in the process flags. */
++ current->ptrace |= PT_PTRACED;
++ ret = 0;
++ goto out;
++ }
++ ret = -ESRCH;
++ read_lock(&tasklist_lock);
++ child = find_task_by_pid(pid);
++ if (child)
++ get_task_struct(child);
++ read_unlock(&tasklist_lock);
++ if (!child)
++ goto out;
++
++ ret = -EPERM;
++ if (pid == 1) /* you may not mess with init */
++ goto out_tsk;
++
++ if (request == PTRACE_ATTACH) {
++ ret = ptrace_attach(child);
++ goto out_tsk;
++ }
++
++ ret = ptrace_check_attach(child, request == PTRACE_KILL);
++ if (ret < 0)
++ goto out_tsk;
++
++ switch (request) {
++ /* when I and D space are separate, these will need to be fixed. */
++ case PTRACE_PEEKTEXT: /* read word at location addr. */
++ case PTRACE_PEEKDATA: {
++ unsigned long tmp;
++ int copied;
++
++ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
++ ret = -EIO;
++ if (copied != sizeof(tmp))
++ break;
++ ret = put_user(tmp,(unsigned long __user *) data);
++ break;
++ }
++
++ /* read the word at location addr in the USER area. */
++ case PTRACE_PEEKUSR: {
++ unsigned long index, tmp;
++
++ ret = -EIO;
++ /* convert to index and check */
++#ifdef CONFIG_PPC32
++ index = (unsigned long) addr >> 2;
++ if ((addr & 3) || (index > PT_FPSCR)
++ || (child->thread.regs == NULL))
++#else
++ index = (unsigned long) addr >> 3;
++ if ((addr & 7) || (index > PT_FPSCR))
++#endif
++ break;
++
++#ifdef CONFIG_PPC32
++ CHECK_FULL_REGS(child->thread.regs);
++#endif
++ if (index < PT_FPR0) {
++ tmp = get_reg(child, (int) index);
++ } else {
++ flush_fp_to_thread(child);
++ tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
++ }
++ ret = put_user(tmp,(unsigned long __user *) data);
++ break;
++ }
++
++ /* If I and D space are separate, this will have to be fixed. */
++ case PTRACE_POKETEXT: /* write the word at location addr. */
++ case PTRACE_POKEDATA:
++ ret = 0;
++ if (access_process_vm(child, addr, &data, sizeof(data), 1)
++ == sizeof(data))
++ break;
++ ret = -EIO;
++ break;
++
++ /* write the word at location addr in the USER area */
++ case PTRACE_POKEUSR: {
++ unsigned long index;
++
++ ret = -EIO;
++ /* convert to index and check */
++#ifdef CONFIG_PPC32
++ index = (unsigned long) addr >> 2;
++ if ((addr & 3) || (index > PT_FPSCR)
++ || (child->thread.regs == NULL))
++#else
++ index = (unsigned long) addr >> 3;
++ if ((addr & 7) || (index > PT_FPSCR))
++#endif
++ break;
++
++#ifdef CONFIG_PPC32
++ CHECK_FULL_REGS(child->thread.regs);
++#endif
++ if (index == PT_ORIG_R3)
++ break;
++ if (index < PT_FPR0) {
++ ret = put_reg(child, index, data);
++ } else {
++ flush_fp_to_thread(child);
++ ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
++ ret = 0;
++ }
++ break;
++ }
++
++ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
++ case PTRACE_CONT: { /* restart after signal. */
++ ret = -EIO;
++ if (!valid_signal(data))
++ break;
++ if (request == PTRACE_SYSCALL)
++ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ else
++ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ child->exit_code = data;
++ /* make sure the single step bit is not set. */
++ clear_single_step(child);
++ wake_up_process(child);
++ ret = 0;
++ break;
++ }
++
++/*
++ * make the child exit. Best I can do is send it a sigkill.
++ * perhaps it should be put in the status that it wants to
++ * exit.
++ */
++ case PTRACE_KILL: {
++ ret = 0;
++ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
++ break;
++ child->exit_code = SIGKILL;
++ /* make sure the single step bit is not set. */
++ clear_single_step(child);
++ wake_up_process(child);
++ break;
++ }
++
++ case PTRACE_SINGLESTEP: { /* set the trap flag. */
++ ret = -EIO;
++ if (!valid_signal(data))
++ break;
++ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ set_single_step(child);
++ child->exit_code = data;
++ /* give it a chance to run. */
++ wake_up_process(child);
++ ret = 0;
++ break;
++ }
++
++#ifdef CONFIG_PPC64
++ case PTRACE_GET_DEBUGREG: {
++ ret = -EINVAL;
++ /* We only support one DABR and no IABRS at the moment */
++ if (addr > 0)
++ break;
++ ret = put_user(child->thread.dabr,
++ (unsigned long __user *)data);
++ break;
++ }
++
++ case PTRACE_SET_DEBUGREG:
++ ret = ptrace_set_debugreg(child, addr, data);
++ break;
++#endif
++
++ case PTRACE_DETACH:
++ ret = ptrace_detach(child, data);
++ break;
++
++#ifdef CONFIG_PPC64
++ case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++ unsigned long __user *tmp = (unsigned long __user *)addr;
++
++ for (i = 0; i < 32; i++) {
++ ret = put_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++
++ case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++ unsigned long __user *tmp = (unsigned long __user *)addr;
++
++ for (i = 0; i < 32; i++) {
++ ret = get_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++
++ case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++ unsigned long __user *tmp = (unsigned long __user *)addr;
++
++ flush_fp_to_thread(child);
++
++ for (i = 0; i < 32; i++) {
++ ret = put_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++
++ case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++ unsigned long __user *tmp = (unsigned long __user *)addr;
++
++ flush_fp_to_thread(child);
++
++ for (i = 0; i < 32; i++) {
++ ret = get_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++#endif /* CONFIG_PPC64 */
++
++#ifdef CONFIG_ALTIVEC
++ case PTRACE_GETVRREGS:
++ /* Get the child altivec register state. */
++ flush_altivec_to_thread(child);
++ ret = get_vrregs((unsigned long __user *)data, child);
++ break;
++
++ case PTRACE_SETVRREGS:
++ /* Set the child altivec register state. */
++ flush_altivec_to_thread(child);
++ ret = set_vrregs(child, (unsigned long __user *)data);
++ break;
++#endif
++#ifdef CONFIG_SPE
++ case PTRACE_GETEVRREGS:
++ /* Get the child spe register state. */
++ if (child->thread.regs->msr & MSR_SPE)
++ giveup_spe(child);
++ ret = get_evrregs((unsigned long __user *)data, child);
++ break;
++
++ case PTRACE_SETEVRREGS:
++ /* Set the child spe register state. */
++ /* this is to clear the MSR_SPE bit to force a reload
++ * of register state from memory */
++ if (child->thread.regs->msr & MSR_SPE)
++ giveup_spe(child);
++ ret = set_evrregs(child, (unsigned long __user *)data);
++ break;
++#endif
++
++ default:
++ ret = ptrace_request(child, request, addr, data);
++ break;
++ }
++out_tsk:
++ put_task_struct(child);
++out:
++ unlock_kernel();
++ return ret;
++}
++
++static void do_syscall_trace(void)
++{
++ /* the 0x80 provides a way for the tracing parent to distinguish
++ between a syscall stop and SIGTRAP delivery */
++ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
++ ? 0x80 : 0));
++
++ /*
++ * this isn't the same as continuing with a signal, but it will do
++ * for normal use. strace only continues with a signal if the
++ * stopping signal is not SIGTRAP. -brl
++ */
++ if (current->exit_code) {
++ send_sig(current->exit_code, current, 1);
++ current->exit_code = 0;
++ }
++}
++
++void do_syscall_trace_enter(struct pt_regs *regs)
++{
++#ifdef CONFIG_PPC64
++ secure_computing(regs->gpr[0]);
++#endif
++
++ if (test_thread_flag(TIF_SYSCALL_TRACE)
++ && (current->ptrace & PT_PTRACED))
++ do_syscall_trace();
++
++ if (unlikely(current->audit_context))
++ audit_syscall_entry(current,
++#ifdef CONFIG_PPC32
++ AUDIT_ARCH_PPC,
++#else
++ test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
++#endif
++ regs->gpr[0],
++ regs->gpr[3], regs->gpr[4],
++ regs->gpr[5], regs->gpr[6]);
++}
++
++void do_syscall_trace_leave(struct pt_regs *regs)
++{
++#ifdef CONFIG_PPC32
++ secure_computing(regs->gpr[0]);
++#endif
++
++ if (unlikely(current->audit_context))
++ audit_syscall_exit(current,
++ (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
++ regs->result);
++
++ if ((test_thread_flag(TIF_SYSCALL_TRACE)
++#ifdef CONFIG_PPC64
++ || test_thread_flag(TIF_SINGLESTEP)
++#endif
++ )
++ && (current->ptrace & PT_PTRACED))
++ do_syscall_trace();
++}
++
++#ifdef CONFIG_PPC32
++EXPORT_SYMBOL(do_syscall_trace_enter);
++EXPORT_SYMBOL(do_syscall_trace_leave);
++#endif
+diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/ptrace32.c
+@@ -0,0 +1,450 @@
++/*
++ * ptrace for 32-bit processes running on a 64-bit kernel.
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Derived from "arch/m68k/kernel/ptrace.c"
++ * Copyright (C) 1994 by Hamish Macdonald
++ * Taken from linux/kernel/ptrace.c and modified for M680x0.
++ * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
++ *
++ * Modified by Cort Dougan (cort at hq.fsmlabs.com)
++ * and Paul Mackerras (paulus at samba.org).
++ *
++ * 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.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/errno.h>
++#include <linux/ptrace.h>
++#include <linux/user.h>
++#include <linux/security.h>
++#include <linux/signal.h>
++
++#include <asm/uaccess.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/ptrace-common.h>
++
++/*
++ * does not yet catch signals sent when the child dies.
++ * in exit.c or in signal.c.
++ */
++
++long compat_sys_ptrace(int request, int pid, unsigned long addr,
++ unsigned long data)
++{
++ struct task_struct *child;
++ int ret = -EPERM;
++
++ lock_kernel();
++ if (request == PTRACE_TRACEME) {
++ /* are we already being traced? */
++ if (current->ptrace & PT_PTRACED)
++ goto out;
++ ret = security_ptrace(current->parent, current);
++ if (ret)
++ goto out;
++ /* set the ptrace bit in the process flags. */
++ current->ptrace |= PT_PTRACED;
++ ret = 0;
++ goto out;
++ }
++ ret = -ESRCH;
++ read_lock(&tasklist_lock);
++ child = find_task_by_pid(pid);
++ if (child)
++ get_task_struct(child);
++ read_unlock(&tasklist_lock);
++ if (!child)
++ goto out;
++
++ ret = -EPERM;
++ if (pid == 1) /* you may not mess with init */
++ goto out_tsk;
++
++ if (request == PTRACE_ATTACH) {
++ ret = ptrace_attach(child);
++ goto out_tsk;
++ }
++
++ ret = ptrace_check_attach(child, request == PTRACE_KILL);
++ if (ret < 0)
++ goto out_tsk;
++
++ switch (request) {
++ /* when I and D space are separate, these will need to be fixed. */
++ case PTRACE_PEEKTEXT: /* read word at location addr. */
++ case PTRACE_PEEKDATA: {
++ unsigned int tmp;
++ int copied;
++
++ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
++ ret = -EIO;
++ if (copied != sizeof(tmp))
++ break;
++ ret = put_user(tmp, (u32 __user *)data);
++ 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 PPC_PTRACE_PEEKTEXT_3264:
++ case PPC_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 *)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 *)data);
++ break;
++ }
++
++ /* Read a register (specified by ADDR) out of the "user area" */
++ case PTRACE_PEEKUSR: {
++ int index;
++ unsigned long tmp;
++
++ ret = -EIO;
++ /* convert to index and check */
++ index = (unsigned long) addr >> 2;
++ if ((addr & 3) || (index > PT_FPSCR32))
++ break;
++
++ if (index < PT_FPR0) {
++ tmp = get_reg(child, index);
++ } else {
++ flush_fp_to_thread(child);
++ /*
++ * the user space code considers the floating point
++ * to be an array of unsigned int (32 bits) - the
++ * index passed in is based on this assumption.
++ */
++ tmp = ((unsigned int *)child->thread.fpr)[index - PT_FPR0];
++ }
++ ret = put_user((unsigned int)tmp, (u32 __user *)data);
++ break;
++ }
++
++ /*
++ * Read 4 bytes out of the other process' pt_regs area
++ * data is a pointer specifying where the user wants the
++ * 4 bytes copied into
++ * addr is the offset into the other process' pt_regs structure
++ * that is to be read
++ * (this is run in a 32-bit process looking at a 64-bit process)
++ */
++ case PPC_PTRACE_PEEKUSR_3264: {
++ u32 index;
++ u32 reg32bits;
++ u64 tmp;
++ u32 numReg;
++ u32 part;
++
++ ret = -EIO;
++ /* Determine which register the user wants */
++ index = (u64)addr >> 2;
++ numReg = index / 2;
++ /* Determine which part of the register the user wants */
++ if (index % 2)
++ part = 1; /* want the 2nd half of the register (right-most). */
++ else
++ part = 0; /* want the 1st half of the register (left-most). */
++
++ /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
++ if ((addr & 3) || numReg > PT_FPSCR)
++ break;
++
++ if (numReg >= PT_FPR0) {
++ flush_fp_to_thread(child);
++ tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
++ } else { /* register within PT_REGS struct */
++ tmp = get_reg(child, numReg);
++ }
++ reg32bits = ((u32*)&tmp)[part];
++ ret = put_user(reg32bits, (u32 __user *)data);
++ break;
++ }
++
++ /* If I and D space are separate, this will have to be fixed. */
++ case PTRACE_POKETEXT: /* write the word at location addr. */
++ case PTRACE_POKEDATA: {
++ unsigned int tmp;
++ tmp = data;
++ ret = 0;
++ if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1)
++ == sizeof(tmp))
++ break;
++ 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 PPC_PTRACE_POKETEXT_3264:
++ case PPC_PTRACE_POKEDATA_3264: {
++ u32 tmp = data;
++ 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 *)addr) != 0)
++ break;
++ ret = 0;
++ if (access_process_vm(child, (u64)addrOthers, &tmp,
++ sizeof(tmp), 1) == sizeof(tmp))
++ break;
++ ret = -EIO;
++ break;
++ }
++
++ /* write the word at location addr in the USER area */
++ case PTRACE_POKEUSR: {
++ unsigned long index;
++
++ ret = -EIO;
++ /* convert to index and check */
++ index = (unsigned long) addr >> 2;
++ if ((addr & 3) || (index > PT_FPSCR32))
++ break;
++
++ if (index == PT_ORIG_R3)
++ break;
++ if (index < PT_FPR0) {
++ ret = put_reg(child, index, data);
++ } else {
++ flush_fp_to_thread(child);
++ /*
++ * the user space code considers the floating point
++ * to be an array of unsigned int (32 bits) - the
++ * index passed in is based on this assumption.
++ */
++ ((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data;
++ ret = 0;
++ }
++ break;
++ }
++
++ /*
++ * Write 4 bytes into the other process' pt_regs area
++ * data is the 4 bytes that the user wants written
++ * addr is the offset into the other process' pt_regs structure
++ * that is to be written into
++ * (this is run in a 32-bit process looking at a 64-bit process)
++ */
++ case PPC_PTRACE_POKEUSR_3264: {
++ u32 index;
++ u32 numReg;
++
++ ret = -EIO;
++ /* Determine which register the user wants */
++ index = (u64)addr >> 2;
++ numReg = index / 2;
++ /*
++ * Validate the input - check to see if address is on the
++ * wrong boundary or beyond the end of the user area
++ */
++ if ((addr & 3) || (numReg > PT_FPSCR))
++ break;
++ /* Insure it is a register we let them change */
++ if ((numReg == PT_ORIG_R3)
++ || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
++ break;
++ if (numReg >= PT_FPR0) {
++ flush_fp_to_thread(child);
++ }
++ if (numReg == PT_MSR)
++ data = (data & MSR_DEBUGCHANGE)
++ | (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
++ ((u32*)child->thread.regs)[index] = data;
++ ret = 0;
++ break;
++ }
++
++ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
++ case PTRACE_CONT: { /* restart after signal. */
++ ret = -EIO;
++ if (!valid_signal(data))
++ break;
++ if (request == PTRACE_SYSCALL)
++ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ else
++ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ child->exit_code = data;
++ /* make sure the single step bit is not set. */
++ clear_single_step(child);
++ wake_up_process(child);
++ ret = 0;
++ break;
++ }
++
++ /*
++ * make the child exit. Best I can do is send it a sigkill.
++ * perhaps it should be put in the status that it wants to
++ * exit.
++ */
++ case PTRACE_KILL: {
++ ret = 0;
++ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
++ break;
++ child->exit_code = SIGKILL;
++ /* make sure the single step bit is not set. */
++ clear_single_step(child);
++ wake_up_process(child);
++ break;
++ }
++
++ case PTRACE_SINGLESTEP: { /* set the trap flag. */
++ ret = -EIO;
++ if (!valid_signal(data))
++ break;
++ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
++ set_single_step(child);
++ child->exit_code = data;
++ /* give it a chance to run. */
++ wake_up_process(child);
++ ret = 0;
++ break;
++ }
++
++ case PTRACE_GET_DEBUGREG: {
++ ret = -EINVAL;
++ /* We only support one DABR and no IABRS at the moment */
++ if (addr > 0)
++ break;
++ ret = put_user(child->thread.dabr, (u32 __user *)data);
++ break;
++ }
++
++ case PTRACE_SET_DEBUGREG:
++ ret = ptrace_set_debugreg(child, addr, data);
++ break;
++
++ case PTRACE_DETACH:
++ ret = ptrace_detach(child, data);
++ break;
++
++ case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++ unsigned int __user *tmp = (unsigned int __user *)addr;
++
++ for (i = 0; i < 32; i++) {
++ ret = put_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++
++ case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
++ unsigned int __user *tmp = (unsigned int __user *)addr;
++
++ for (i = 0; i < 32; i++) {
++ ret = get_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++
++ case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++ unsigned int __user *tmp = (unsigned int __user *)addr;
++
++ flush_fp_to_thread(child);
++
++ for (i = 0; i < 32; i++) {
++ ret = put_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++
++ case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
++ int i;
++ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
++ unsigned int __user *tmp = (unsigned int __user *)addr;
++
++ flush_fp_to_thread(child);
++
++ for (i = 0; i < 32; i++) {
++ ret = get_user(*reg, tmp);
++ if (ret)
++ break;
++ reg++;
++ tmp++;
++ }
++ break;
++ }
++
++ case PTRACE_GETEVENTMSG:
++ ret = put_user(child->ptrace_message, (unsigned int __user *) data);
++ break;
++
++#ifdef CONFIG_ALTIVEC
++ case PTRACE_GETVRREGS:
++ /* Get the child altivec register state. */
++ flush_altivec_to_thread(child);
++ ret = get_vrregs((unsigned long __user *)data, child);
++ break;
++
++ case PTRACE_SETVRREGS:
++ /* Set the child altivec register state. */
++ flush_altivec_to_thread(child);
++ ret = set_vrregs(child, (unsigned long __user *)data);
++ break;
++#endif
++
++ default:
++ ret = ptrace_request(child, request, addr, data);
++ break;
++ }
++out_tsk:
++ put_task_struct(child);
++out:
++ unlock_kernel();
++ return ret;
++}
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/rtas.c
+@@ -0,0 +1,680 @@
++/*
++ *
++ * Procedures for interfacing to the RTAS on CHRP machines.
++ *
++ * Peter Bergner, IBM March 2001.
++ * Copyright (C) 2001 IBM.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <stdarg.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/spinlock.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/prom.h>
++#include <asm/rtas.h>
++#include <asm/semaphore.h>
++#include <asm/machdep.h>
++#include <asm/page.h>
++#include <asm/param.h>
++#include <asm/system.h>
++#include <asm/delay.h>
++#include <asm/uaccess.h>
++#include <asm/lmb.h>
++#ifdef CONFIG_PPC64
++#include <asm/systemcfg.h>
++#endif
++
++struct rtas_t rtas = {
++ .lock = SPIN_LOCK_UNLOCKED
++};
++
++EXPORT_SYMBOL(rtas);
++
++DEFINE_SPINLOCK(rtas_data_buf_lock);
++char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
++unsigned long rtas_rmo_buf;
++
++/*
++ * call_rtas_display_status and call_rtas_display_status_delay
++ * are designed only for very early low-level debugging, which
++ * is why the token is hard-coded to 10.
++ */
++void call_rtas_display_status(unsigned char c)
++{
++ struct rtas_args *args = &rtas.args;
++ unsigned long s;
++
++ if (!rtas.base)
++ return;
++ spin_lock_irqsave(&rtas.lock, s);
++
++ args->token = 10;
++ args->nargs = 1;
++ args->nret = 1;
++ args->rets = (rtas_arg_t *)&(args->args[1]);
++ args->args[0] = (int)c;
++
++ enter_rtas(__pa(args));
++
++ spin_unlock_irqrestore(&rtas.lock, s);
++}
++
++void call_rtas_display_status_delay(unsigned char c)
++{
++ static int pending_newline = 0; /* did last write end with unprinted newline? */
++ static int width = 16;
++
++ if (c == '\n') {
++ while (width-- > 0)
++ call_rtas_display_status(' ');
++ width = 16;
++ udelay(500000);
++ pending_newline = 1;
++ } else {
++ if (pending_newline) {
++ call_rtas_display_status('\r');
++ call_rtas_display_status('\n');
++ }
++ pending_newline = 0;
++ if (width--) {
++ call_rtas_display_status(c);
++ udelay(10000);
++ }
++ }
++}
++
++void rtas_progress(char *s, unsigned short hex)
++{
++ struct device_node *root;
++ int width, *p;
++ char *os;
++ static int display_character, set_indicator;
++ static int display_width, display_lines, *row_width, form_feed;
++ static DEFINE_SPINLOCK(progress_lock);
++ static int current_line;
++ static int pending_newline = 0; /* did last write end with unprinted newline? */
++
++ if (!rtas.base)
++ return;
++
++ if (display_width == 0) {
++ display_width = 0x10;
++ if ((root = find_path_device("/rtas"))) {
++ if ((p = (unsigned int *)get_property(root,
++ "ibm,display-line-length", NULL)))
++ display_width = *p;
++ if ((p = (unsigned int *)get_property(root,
++ "ibm,form-feed", NULL)))
++ form_feed = *p;
++ if ((p = (unsigned int *)get_property(root,
++ "ibm,display-number-of-lines", NULL)))
++ display_lines = *p;
++ row_width = (unsigned int *)get_property(root,
++ "ibm,display-truncation-length", NULL);
++ }
++ display_character = rtas_token("display-character");
++ set_indicator = rtas_token("set-indicator");
++ }
++
++ if (display_character == RTAS_UNKNOWN_SERVICE) {
++ /* use hex display if available */
++ if (set_indicator != RTAS_UNKNOWN_SERVICE)
++ rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
++ return;
++ }
++
++ spin_lock(&progress_lock);
++
++ /*
++ * Last write ended with newline, but we didn't print it since
++ * it would just clear the bottom line of output. Print it now
++ * instead.
++ *
++ * If no newline is pending and form feed is supported, clear the
++ * display with a form feed; otherwise, print a CR to start output
++ * at the beginning of the line.
++ */
++ if (pending_newline) {
++ rtas_call(display_character, 1, 1, NULL, '\r');
++ rtas_call(display_character, 1, 1, NULL, '\n');
++ pending_newline = 0;
++ } else {
++ current_line = 0;
++ if (form_feed)
++ rtas_call(display_character, 1, 1, NULL,
++ (char)form_feed);
++ else
++ rtas_call(display_character, 1, 1, NULL, '\r');
++ }
++
++ if (row_width)
++ width = row_width[current_line];
++ else
++ width = display_width;
++ os = s;
++ while (*os) {
++ if (*os == '\n' || *os == '\r') {
++ /* If newline is the last character, save it
++ * until next call to avoid bumping up the
++ * display output.
++ */
++ if (*os == '\n' && !os[1]) {
++ pending_newline = 1;
++ current_line++;
++ if (current_line > display_lines-1)
++ current_line = display_lines-1;
++ spin_unlock(&progress_lock);
++ return;
++ }
++
++ /* RTAS wants CR-LF, not just LF */
++
++ if (*os == '\n') {
++ rtas_call(display_character, 1, 1, NULL, '\r');
++ rtas_call(display_character, 1, 1, NULL, '\n');
++ } else {
++ /* CR might be used to re-draw a line, so we'll
++ * leave it alone and not add LF.
++ */
++ rtas_call(display_character, 1, 1, NULL, *os);
++ }
++
++ if (row_width)
++ width = row_width[current_line];
++ else
++ width = display_width;
++ } else {
++ width--;
++ rtas_call(display_character, 1, 1, NULL, *os);
++ }
++
++ os++;
++
++ /* if we overwrite the screen length */
++ if (width <= 0)
++ while ((*os != 0) && (*os != '\n') && (*os != '\r'))
++ os++;
++ }
++
++ spin_unlock(&progress_lock);
++}
++
++int rtas_token(const char *service)
++{
++ int *tokp;
++ if (rtas.dev == NULL)
++ return RTAS_UNKNOWN_SERVICE;
++ tokp = (int *) get_property(rtas.dev, service, NULL);
++ return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
++}
++
++#ifdef CONFIG_RTAS_ERROR_LOGGING
++/*
++ * Return the firmware-specified size of the error log buffer
++ * for all rtas calls that require an error buffer argument.
++ * This includes 'check-exception' and 'rtas-last-error'.
++ */
++int rtas_get_error_log_max(void)
++{
++ static int rtas_error_log_max;
++ if (rtas_error_log_max)
++ return rtas_error_log_max;
++
++ rtas_error_log_max = rtas_token ("rtas-error-log-max");
++ if ((rtas_error_log_max == RTAS_UNKNOWN_SERVICE) ||
++ (rtas_error_log_max > RTAS_ERROR_LOG_MAX)) {
++ printk (KERN_WARNING "RTAS: bad log buffer size %d\n",
++ rtas_error_log_max);
++ rtas_error_log_max = RTAS_ERROR_LOG_MAX;
++ }
++ return rtas_error_log_max;
++}
++EXPORT_SYMBOL(rtas_get_error_log_max);
++
++
++char rtas_err_buf[RTAS_ERROR_LOG_MAX];
++int rtas_last_error_token;
++
++/** Return a copy of the detailed error text associated with the
++ * most recent failed call to rtas. Because the error text
++ * might go stale if there are any other intervening rtas calls,
++ * this routine must be called atomically with whatever produced
++ * the error (i.e. with rtas.lock still held from the previous call).
++ */
++static char *__fetch_rtas_last_error(char *altbuf)
++{
++ struct rtas_args err_args, save_args;
++ u32 bufsz;
++ char *buf = NULL;
++
++ if (rtas_last_error_token == -1)
++ return NULL;
++
++ bufsz = rtas_get_error_log_max();
++
++ err_args.token = rtas_last_error_token;
++ err_args.nargs = 2;
++ err_args.nret = 1;
++ err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
++ err_args.args[1] = bufsz;
++ err_args.args[2] = 0;
++
++ save_args = rtas.args;
++ rtas.args = err_args;
++
++ enter_rtas(__pa(&rtas.args));
++
++ err_args = rtas.args;
++ rtas.args = save_args;
++
++ /* Log the error in the unlikely case that there was one. */
++ if (unlikely(err_args.args[2] == 0)) {
++ if (altbuf) {
++ buf = altbuf;
++ } else {
++ buf = rtas_err_buf;
++ if (mem_init_done)
++ buf = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
++ }
++ if (buf)
++ memcpy(buf, rtas_err_buf, RTAS_ERROR_LOG_MAX);
++ }
++
++ return buf;
++}
++
++#define get_errorlog_buffer() kmalloc(RTAS_ERROR_LOG_MAX, GFP_KERNEL)
++
++#else /* CONFIG_RTAS_ERROR_LOGGING */
++#define __fetch_rtas_last_error(x) NULL
++#define get_errorlog_buffer() NULL
++#endif
++
++int rtas_call(int token, int nargs, int nret, int *outputs, ...)
++{
++ va_list list;
++ int i;
++ unsigned long s;
++ struct rtas_args *rtas_args;
++ char *buff_copy = NULL;
++ int ret;
++
++ if (token == RTAS_UNKNOWN_SERVICE)
++ return -1;
++
++ /* Gotta do something different here, use global lock for now... */
++ spin_lock_irqsave(&rtas.lock, s);
++ rtas_args = &rtas.args;
++
++ rtas_args->token = token;
++ rtas_args->nargs = nargs;
++ rtas_args->nret = nret;
++ rtas_args->rets = (rtas_arg_t *)&(rtas_args->args[nargs]);
++ va_start(list, outputs);
++ for (i = 0; i < nargs; ++i)
++ rtas_args->args[i] = va_arg(list, rtas_arg_t);
++ va_end(list);
++
++ for (i = 0; i < nret; ++i)
++ rtas_args->rets[i] = 0;
++
++ enter_rtas(__pa(rtas_args));
++
++ /* A -1 return code indicates that the last command couldn't
++ be completed due to a hardware error. */
++ if (rtas_args->rets[0] == -1)
++ buff_copy = __fetch_rtas_last_error(NULL);
++
++ if (nret > 1 && outputs != NULL)
++ for (i = 0; i < nret-1; ++i)
++ outputs[i] = rtas_args->rets[i+1];
++ ret = (nret > 0)? rtas_args->rets[0]: 0;
++
++ /* Gotta do something different here, use global lock for now... */
++ spin_unlock_irqrestore(&rtas.lock, s);
++
++ if (buff_copy) {
++ log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
++ if (mem_init_done)
++ kfree(buff_copy);
++ }
++ return ret;
++}
++
++/* Given an RTAS status code of 990n compute the hinted delay of 10^n
++ * (last digit) milliseconds. For now we bound at n=5 (100 sec).
++ */
++unsigned int rtas_extended_busy_delay_time(int status)
++{
++ int order = status - 9900;
++ unsigned long ms;
++
++ if (order < 0)
++ order = 0; /* RTC depends on this for -2 clock busy */
++ else if (order > 5)
++ order = 5; /* bound */
++
++ /* Use microseconds for reasonable accuracy */
++ for (ms = 1; order > 0; order--)
++ ms *= 10;
++
++ return ms;
++}
++
++int rtas_error_rc(int rtas_rc)
++{
++ int rc;
++
++ switch (rtas_rc) {
++ case -1: /* Hardware Error */
++ rc = -EIO;
++ break;
++ case -3: /* Bad indicator/domain/etc */
++ rc = -EINVAL;
++ break;
++ case -9000: /* Isolation error */
++ rc = -EFAULT;
++ break;
++ case -9001: /* Outstanding TCE/PTE */
++ rc = -EEXIST;
++ break;
++ case -9002: /* No usable slot */
++ rc = -ENODEV;
++ break;
++ default:
++ printk(KERN_ERR "%s: unexpected RTAS error %d\n",
++ __FUNCTION__, rtas_rc);
++ rc = -ERANGE;
++ break;
++ }
++ return rc;
++}
++
++int rtas_get_power_level(int powerdomain, int *level)
++{
++ int token = rtas_token("get-power-level");
++ int rc;
++
++ if (token == RTAS_UNKNOWN_SERVICE)
++ return -ENOENT;
++
++ while ((rc = rtas_call(token, 1, 2, level, powerdomain)) == RTAS_BUSY)
++ udelay(1);
++
++ if (rc < 0)
++ return rtas_error_rc(rc);
++ return rc;
++}
++
++int rtas_set_power_level(int powerdomain, int level, int *setlevel)
++{
++ int token = rtas_token("set-power-level");
++ unsigned int wait_time;
++ int rc;
++
++ if (token == RTAS_UNKNOWN_SERVICE)
++ return -ENOENT;
++
++ while (1) {
++ rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
++ if (rc == RTAS_BUSY)
++ udelay(1);
++ else if (rtas_is_extended_busy(rc)) {
++ wait_time = rtas_extended_busy_delay_time(rc);
++ udelay(wait_time * 1000);
++ } else
++ break;
++ }
++
++ if (rc < 0)
++ return rtas_error_rc(rc);
++ return rc;
++}
++
++int rtas_get_sensor(int sensor, int index, int *state)
++{
++ int token = rtas_token("get-sensor-state");
++ unsigned int wait_time;
++ int rc;
++
++ if (token == RTAS_UNKNOWN_SERVICE)
++ return -ENOENT;
++
++ while (1) {
++ rc = rtas_call(token, 2, 2, state, sensor, index);
++ if (rc == RTAS_BUSY)
++ udelay(1);
++ else if (rtas_is_extended_busy(rc)) {
++ wait_time = rtas_extended_busy_delay_time(rc);
++ udelay(wait_time * 1000);
++ } else
++ break;
++ }
++
++ if (rc < 0)
++ return rtas_error_rc(rc);
++ return rc;
++}
++
++int rtas_set_indicator(int indicator, int index, int new_value)
++{
++ int token = rtas_token("set-indicator");
++ unsigned int wait_time;
++ int rc;
++
++ if (token == RTAS_UNKNOWN_SERVICE)
++ return -ENOENT;
++
++ while (1) {
++ rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
++ if (rc == RTAS_BUSY)
++ udelay(1);
++ else if (rtas_is_extended_busy(rc)) {
++ wait_time = rtas_extended_busy_delay_time(rc);
++ udelay(wait_time * 1000);
++ }
++ else
++ break;
++ }
++
++ if (rc < 0)
++ return rtas_error_rc(rc);
++ return rc;
++}
++
++void rtas_restart(char *cmd)
++{
++ printk("RTAS system-reboot returned %d\n",
++ rtas_call(rtas_token("system-reboot"), 0, 1, NULL));
++ for (;;);
++}
++
++void rtas_power_off(void)
++{
++ /* allow power on only with power button press */
++ printk("RTAS power-off returned %d\n",
++ rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
++ for (;;);
++}
++
++void rtas_halt(void)
++{
++ rtas_power_off();
++}
++
++/* Must be in the RMO region, so we place it here */
++static char rtas_os_term_buf[2048];
++
++void rtas_os_term(char *str)
++{
++ int status;
++
++ if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term"))
++ return;
++
++ snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);
++
++ do {
++ status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
++ __pa(rtas_os_term_buf));
++
++ if (status == RTAS_BUSY)
++ udelay(1);
++ else if (status != 0)
++ printk(KERN_EMERG "ibm,os-term call failed %d\n",
++ status);
++ } while (status == RTAS_BUSY);
++}
++
++
++asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
++{
++ struct rtas_args args;
++ unsigned long flags;
++ char *buff_copy, *errbuf = NULL;
++ int nargs;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
++ return -EFAULT;
++
++ nargs = args.nargs;
++ if (nargs > ARRAY_SIZE(args.args)
++ || args.nret > ARRAY_SIZE(args.args)
++ || nargs + args.nret > ARRAY_SIZE(args.args))
++ return -EINVAL;
++
++ /* Copy in args. */
++ if (copy_from_user(args.args, uargs->args,
++ nargs * sizeof(rtas_arg_t)) != 0)
++ return -EFAULT;
++
++ buff_copy = get_errorlog_buffer();
++
++ spin_lock_irqsave(&rtas.lock, flags);
++
++ rtas.args = args;
++ enter_rtas(__pa(&rtas.args));
++ args = rtas.args;
++
++ args.rets = &args.args[nargs];
++
++ /* A -1 return code indicates that the last command couldn't
++ be completed due to a hardware error. */
++ if (args.rets[0] == -1)
++ errbuf = __fetch_rtas_last_error(buff_copy);
++
++ spin_unlock_irqrestore(&rtas.lock, flags);
++
++ if (buff_copy) {
++ if (errbuf)
++ log_error(errbuf, ERR_TYPE_RTAS_LOG, 0);
++ kfree(buff_copy);
++ }
++
++ /* Copy out args. */
++ if (copy_to_user(uargs->args + nargs,
++ args.args + nargs,
++ args.nret * sizeof(rtas_arg_t)) != 0)
++ return -EFAULT;
++
++ return 0;
++}
++
++#ifdef CONFIG_SMP
++/* This version can't take the spinlock, because it never returns */
++
++struct rtas_args rtas_stop_self_args = {
++ /* The token is initialized for real in setup_system() */
++ .token = RTAS_UNKNOWN_SERVICE,
++ .nargs = 0,
++ .nret = 1,
++ .rets = &rtas_stop_self_args.args[0],
++};
++
++void rtas_stop_self(void)
++{
++ struct rtas_args *rtas_args = &rtas_stop_self_args;
++
++ local_irq_disable();
++
++ BUG_ON(rtas_args->token == RTAS_UNKNOWN_SERVICE);
++
++ printk("cpu %u (hwid %u) Ready to die...\n",
++ smp_processor_id(), hard_smp_processor_id());
++ enter_rtas(__pa(rtas_args));
++
++ panic("Alas, I survived.\n");
++}
++#endif
++
++/*
++ * Call early during boot, before mem init or bootmem, to retreive the RTAS
++ * informations from the device-tree and allocate the RMO buffer for userland
++ * accesses.
++ */
++void __init rtas_initialize(void)
++{
++ unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
++
++ /* Get RTAS dev node and fill up our "rtas" structure with infos
++ * about it.
++ */
++ rtas.dev = of_find_node_by_name(NULL, "rtas");
++ if (rtas.dev) {
++ u32 *basep, *entryp;
++ u32 *sizep;
++
++ basep = (u32 *)get_property(rtas.dev, "linux,rtas-base", NULL);
++ sizep = (u32 *)get_property(rtas.dev, "rtas-size", NULL);
++ if (basep != NULL && sizep != NULL) {
++ rtas.base = *basep;
++ rtas.size = *sizep;
++ entryp = (u32 *)get_property(rtas.dev, "linux,rtas-entry", NULL);
++ if (entryp == NULL) /* Ugh */
++ rtas.entry = rtas.base;
++ else
++ rtas.entry = *entryp;
++ } else
++ rtas.dev = NULL;
++ }
++ if (!rtas.dev)
++ return;
++
++ /* If RTAS was found, allocate the RMO buffer for it and look for
++ * the stop-self token if any
++ */
++#ifdef CONFIG_PPC64
++ if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
++ rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
++#endif
++ rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
++
++#ifdef CONFIG_HOTPLUG_CPU
++ rtas_stop_self_args.token = rtas_token("stop-self");
++#endif /* CONFIG_HOTPLUG_CPU */
++#ifdef CONFIG_RTAS_ERROR_LOGGING
++ rtas_last_error_token = rtas_token("rtas-last-error");
++#endif
++}
++
++
++EXPORT_SYMBOL(rtas_token);
++EXPORT_SYMBOL(rtas_call);
++EXPORT_SYMBOL(rtas_data_buf);
++EXPORT_SYMBOL(rtas_data_buf_lock);
++EXPORT_SYMBOL(rtas_extended_busy_delay_time);
++EXPORT_SYMBOL(rtas_get_sensor);
++EXPORT_SYMBOL(rtas_get_power_level);
++EXPORT_SYMBOL(rtas_set_power_level);
++EXPORT_SYMBOL(rtas_set_indicator);
+diff --git a/arch/powerpc/kernel/semaphore.c b/arch/powerpc/kernel/semaphore.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/semaphore.c
+@@ -0,0 +1,135 @@
++/*
++ * PowerPC-specific semaphore code.
++ *
++ * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
++ *
++ * 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.
++ *
++ * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
++ * to eliminate the SMP races in the old version between the updates
++ * of `count' and `waking'. Now we use negative `count' values to
++ * indicate that some process(es) are waiting for the semaphore.
++ */
++
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/module.h>
++
++#include <asm/atomic.h>
++#include <asm/semaphore.h>
++#include <asm/errno.h>
++
++/*
++ * Atomically update sem->count.
++ * This does the equivalent of the following:
++ *
++ * old_count = sem->count;
++ * tmp = MAX(old_count, 0) + incr;
++ * sem->count = tmp;
++ * return old_count;
++ */
++static inline int __sem_update_count(struct semaphore *sem, int incr)
++{
++ int old_count, tmp;
++
++ __asm__ __volatile__("\n"
++"1: lwarx %0,0,%3\n"
++" srawi %1,%0,31\n"
++" andc %1,%0,%1\n"
++" add %1,%1,%4\n"
++ PPC405_ERR77(0,%3)
++" stwcx. %1,0,%3\n"
++" bne 1b"
++ : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
++ : "r" (&sem->count), "r" (incr), "m" (sem->count)
++ : "cc");
++
++ return old_count;
++}
++
++void __up(struct semaphore *sem)
++{
++ /*
++ * Note that we incremented count in up() before we came here,
++ * but that was ineffective since the result was <= 0, and
++ * any negative value of count is equivalent to 0.
++ * This ends up setting count to 1, unless count is now > 0
++ * (i.e. because some other cpu has called up() in the meantime),
++ * in which case we just increment count.
++ */
++ __sem_update_count(sem, 1);
++ wake_up(&sem->wait);
++}
++EXPORT_SYMBOL(__up);
++
++/*
++ * Note that when we come in to __down or __down_interruptible,
++ * we have already decremented count, but that decrement was
++ * ineffective since the result was < 0, and any negative value
++ * of count is equivalent to 0.
++ * Thus it is only when we decrement count from some value > 0
++ * that we have actually got the semaphore.
++ */
++void __sched __down(struct semaphore *sem)
++{
++ struct task_struct *tsk = current;
++ DECLARE_WAITQUEUE(wait, tsk);
++
++ __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
++ add_wait_queue_exclusive(&sem->wait, &wait);
++
++ /*
++ * Try to get the semaphore. If the count is > 0, then we've
++ * got the semaphore; we decrement count and exit the loop.
++ * If the count is 0 or negative, we set it to -1, indicating
++ * that we are asleep, and then sleep.
++ */
++ while (__sem_update_count(sem, -1) <= 0) {
++ schedule();
++ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
++ }
++ remove_wait_queue(&sem->wait, &wait);
++ __set_task_state(tsk, TASK_RUNNING);
++
++ /*
++ * If there are any more sleepers, wake one of them up so
++ * that it can either get the semaphore, or set count to -1
++ * indicating that there are still processes sleeping.
++ */
++ wake_up(&sem->wait);
++}
++EXPORT_SYMBOL(__down);
++
++int __sched __down_interruptible(struct semaphore * sem)
++{
++ int retval = 0;
++ struct task_struct *tsk = current;
++ DECLARE_WAITQUEUE(wait, tsk);
++
++ __set_task_state(tsk, TASK_INTERRUPTIBLE);
++ add_wait_queue_exclusive(&sem->wait, &wait);
++
++ while (__sem_update_count(sem, -1) <= 0) {
++ if (signal_pending(current)) {
++ /*
++ * A signal is pending - give up trying.
++ * Set sem->count to 0 if it is negative,
++ * since we are no longer sleeping.
++ */
++ __sem_update_count(sem, 0);
++ retval = -EINTR;
++ break;
++ }
++ schedule();
++ set_task_state(tsk, TASK_INTERRUPTIBLE);
++ }
++ remove_wait_queue(&sem->wait, &wait);
++ __set_task_state(tsk, TASK_RUNNING);
++
++ wake_up(&sem->wait);
++ return retval;
++}
++EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/setup-common.c
+@@ -0,0 +1,410 @@
++/*
++ * Common boot and setup code for both 32-bit and 64-bit.
++ * Extracted from arch/powerpc/kernel/setup_64.c.
++ *
++ * Copyright (C) 2001 PPC64 Team, IBM Corp
++ *
++ * 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/string.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/reboot.h>
++#include <linux/delay.h>
++#include <linux/initrd.h>
++#include <linux/ide.h>
++#include <linux/seq_file.h>
++#include <linux/ioport.h>
++#include <linux/console.h>
++#include <linux/utsname.h>
++#include <linux/tty.h>
++#include <linux/root_dev.h>
++#include <linux/notifier.h>
++#include <linux/cpu.h>
++#include <linux/unistd.h>
++#include <linux/serial.h>
++#include <linux/serial_8250.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/processor.h>
++#include <asm/pgtable.h>
++#include <asm/smp.h>
++#include <asm/elf.h>
++#include <asm/machdep.h>
++#include <asm/time.h>
++#include <asm/cputable.h>
++#include <asm/sections.h>
++#include <asm/btext.h>
++#include <asm/nvram.h>
++#include <asm/setup.h>
++#include <asm/system.h>
++#include <asm/rtas.h>
++#include <asm/iommu.h>
++#include <asm/serial.h>
++#include <asm/cache.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/lmb.h>
++
++#undef DEBUG
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/*
++ * This still seems to be needed... -- paulus
++ */
++struct screen_info screen_info = {
++ .orig_x = 0,
++ .orig_y = 25,
++ .orig_video_cols = 80,
++ .orig_video_lines = 25,
++ .orig_video_isVGA = 1,
++ .orig_video_points = 16
++};
++
++#ifdef __DO_IRQ_CANON
++/* XXX should go elsewhere eventually */
++int ppc_do_canonicalize_irqs;
++EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
++#endif
++
++/* also used by kexec */
++void machine_shutdown(void)
++{
++ if (ppc_md.nvram_sync)
++ ppc_md.nvram_sync();
++}
++
++void machine_restart(char *cmd)
++{
++ machine_shutdown();
++ ppc_md.restart(cmd);
++#ifdef CONFIG_SMP
++ smp_send_stop();
++#endif
++ printk(KERN_EMERG "System Halted, OK to turn off power\n");
++ local_irq_disable();
++ while (1) ;
++}
++
++void machine_power_off(void)
++{
++ machine_shutdown();
++ ppc_md.power_off();
++#ifdef CONFIG_SMP
++ smp_send_stop();
++#endif
++ printk(KERN_EMERG "System Halted, OK to turn off power\n");
++ local_irq_disable();
++ while (1) ;
++}
++/* Used by the G5 thermal driver */
++EXPORT_SYMBOL_GPL(machine_power_off);
++
++void (*pm_power_off)(void) = machine_power_off;
++EXPORT_SYMBOL_GPL(pm_power_off);
++
++void machine_halt(void)
++{
++ machine_shutdown();
++ ppc_md.halt();
++#ifdef CONFIG_SMP
++ smp_send_stop();
++#endif
++ printk(KERN_EMERG "System Halted, OK to turn off power\n");
++ local_irq_disable();
++ while (1) ;
++}
++
++
++#ifdef CONFIG_TAU
++extern u32 cpu_temp(unsigned long cpu);
++extern u32 cpu_temp_both(unsigned long cpu);
++#endif /* CONFIG_TAU */
++
++#ifdef CONFIG_SMP
++DEFINE_PER_CPU(unsigned int, pvr);
++#endif
++
++static int show_cpuinfo(struct seq_file *m, void *v)
++{
++ unsigned long cpu_id = (unsigned long)v - 1;
++ unsigned int pvr;
++ unsigned short maj;
++ unsigned short min;
++
++ if (cpu_id == NR_CPUS) {
++#if defined(CONFIG_SMP) && defined(CONFIG_PPC32)
++ unsigned long bogosum = 0;
++ int i;
++ for (i = 0; i < NR_CPUS; ++i)
++ if (cpu_online(i))
++ bogosum += loops_per_jiffy;
++ seq_printf(m, "total bogomips\t: %lu.%02lu\n",
++ bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
++#endif /* CONFIG_SMP && CONFIG_PPC32 */
++ seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
++
++ if (ppc_md.show_cpuinfo != NULL)
++ ppc_md.show_cpuinfo(m);
++
++ return 0;
++ }
++
++ /* We only show online cpus: disable preempt (overzealous, I
++ * knew) to prevent cpu going down. */
++ preempt_disable();
++ if (!cpu_online(cpu_id)) {
++ preempt_enable();
++ return 0;
++ }
++
++#ifdef CONFIG_SMP
++#ifdef CONFIG_PPC64 /* XXX for now */
++ pvr = per_cpu(pvr, cpu_id);
++#else
++ pvr = cpu_data[cpu_id].pvr;
++#endif
++#else
++ pvr = mfspr(SPRN_PVR);
++#endif
++ maj = (pvr >> 8) & 0xFF;
++ min = pvr & 0xFF;
++
++ seq_printf(m, "processor\t: %lu\n", cpu_id);
++ seq_printf(m, "cpu\t\t: ");
++
++ if (cur_cpu_spec->pvr_mask)
++ seq_printf(m, "%s", cur_cpu_spec->cpu_name);
++ else
++ seq_printf(m, "unknown (%08x)", pvr);
++
++#ifdef CONFIG_ALTIVEC
++ if (cpu_has_feature(CPU_FTR_ALTIVEC))
++ seq_printf(m, ", altivec supported");
++#endif /* CONFIG_ALTIVEC */
++
++ seq_printf(m, "\n");
++
++#ifdef CONFIG_TAU
++ if (cur_cpu_spec->cpu_features & CPU_FTR_TAU) {
++#ifdef CONFIG_TAU_AVERAGE
++ /* more straightforward, but potentially misleading */
++ seq_printf(m, "temperature \t: %u C (uncalibrated)\n",
++ cpu_temp(i));
++#else
++ /* show the actual temp sensor range */
++ u32 temp;
++ temp = cpu_temp_both(i);
++ seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n",
++ temp & 0xff, temp >> 16);
++#endif
++ }
++#endif /* CONFIG_TAU */
++
++ /*
++ * Assume here that all clock rates are the same in a
++ * smp system. -- Cort
++ */
++ if (ppc_proc_freq)
++ seq_printf(m, "clock\t\t: %lu.%06luMHz\n",
++ ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
++
++ if (ppc_md.show_percpuinfo != NULL)
++ ppc_md.show_percpuinfo(m, cpu_id);
++
++ /* If we are a Freescale core do a simple check so
++ * we dont have to keep adding cases in the future */
++ if (PVR_VER(pvr) & 0x8000) {
++ maj = PVR_MAJ(pvr);
++ min = PVR_MIN(pvr);
++ } else {
++ switch (PVR_VER(pvr)) {
++ case 0x0020: /* 403 family */
++ maj = PVR_MAJ(pvr) + 1;
++ min = PVR_MIN(pvr);
++ break;
++ case 0x1008: /* 740P/750P ?? */
++ maj = ((pvr >> 8) & 0xFF) - 1;
++ min = pvr & 0xFF;
++ break;
++ default:
++ maj = (pvr >> 8) & 0xFF;
++ min = pvr & 0xFF;
++ break;
++ }
++ }
++
++ seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
++ maj, min, PVR_VER(pvr), PVR_REV(pvr));
++
++#ifdef CONFIG_PPC32
++ seq_printf(m, "bogomips\t: %lu.%02lu\n",
++ loops_per_jiffy / (500000/HZ),
++ (loops_per_jiffy / (5000/HZ)) % 100);
++#endif
++
++#ifdef CONFIG_SMP
++ seq_printf(m, "\n");
++#endif
++
++ preempt_enable();
++ return 0;
++}
++
++static void *c_start(struct seq_file *m, loff_t *pos)
++{
++ unsigned long i = *pos;
++
++ return i <= NR_CPUS ? (void *)(i + 1) : NULL;
++}
++
++static void *c_next(struct seq_file *m, void *v, loff_t *pos)
++{
++ ++*pos;
++ return c_start(m, pos);
++}
++
++static void c_stop(struct seq_file *m, void *v)
++{
++}
++
++struct seq_operations cpuinfo_op = {
++ .start =c_start,
++ .next = c_next,
++ .stop = c_stop,
++ .show = show_cpuinfo,
++};
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++static int __init set_preferred_console(void)
++{
++ struct device_node *prom_stdout = NULL;
++ char *name;
++ u32 *spd;
++ int offset = 0;
++
++ DBG(" -> set_preferred_console()\n");
++
++ /* The user has requested a console so this is already set up. */
++ if (strstr(saved_command_line, "console=")) {
++ DBG(" console was specified !\n");
++ return -EBUSY;
++ }
++
++ if (!of_chosen) {
++ DBG(" of_chosen is NULL !\n");
++ return -ENODEV;
++ }
++ /* We are getting a weird phandle from OF ... */
++ /* ... So use the full path instead */
++ name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
++ if (name == NULL) {
++ DBG(" no linux,stdout-path !\n");
++ return -ENODEV;
++ }
++ prom_stdout = of_find_node_by_path(name);
++ if (!prom_stdout) {
++ DBG(" can't find stdout package %s !\n", name);
++ return -ENODEV;
++ }
++ DBG("stdout is %s\n", prom_stdout->full_name);
++
++ name = (char *)get_property(prom_stdout, "name", NULL);
++ if (!name) {
++ DBG(" stdout package has no name !\n");
++ goto not_found;
++ }
++ spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
++
++ if (0)
++ ;
++#ifdef CONFIG_SERIAL_8250_CONSOLE
++ else if (strcmp(name, "serial") == 0) {
++ int i;
++ u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
++ if (i > 8) {
++ switch (reg[1]) {
++ case 0x3f8:
++ offset = 0;
++ break;
++ case 0x2f8:
++ offset = 1;
++ break;
++ case 0x898:
++ offset = 2;
++ break;
++ case 0x890:
++ offset = 3;
++ break;
++ default:
++ /* We dont recognise the serial port */
++ goto not_found;
++ }
++ }
++ }
++#endif /* CONFIG_SERIAL_8250_CONSOLE */
++#ifdef CONFIG_PPC_PSERIES
++ else if (strcmp(name, "vty") == 0) {
++ u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
++ char *compat = (char *)get_property(prom_stdout, "compatible", NULL);
++
++ if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) {
++ /* Host Virtual Serial Interface */
++ switch (reg[0]) {
++ case 0x30000000:
++ offset = 0;
++ break;
++ case 0x30000001:
++ offset = 1;
++ break;
++ default:
++ goto not_found;
++ }
++ of_node_put(prom_stdout);
++ DBG("Found hvsi console at offset %d\n", offset);
++ return add_preferred_console("hvsi", offset, NULL);
++ } else {
++ /* pSeries LPAR virtual console */
++ of_node_put(prom_stdout);
++ DBG("Found hvc console\n");
++ return add_preferred_console("hvc", 0, NULL);
++ }
++ }
++#endif /* CONFIG_PPC_PSERIES */
++#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
++ else if (strcmp(name, "ch-a") == 0)
++ offset = 0;
++ else if (strcmp(name, "ch-b") == 0)
++ offset = 1;
++#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
++ else
++ goto not_found;
++ of_node_put(prom_stdout);
++
++ DBG("Found serial console at ttyS%d\n", offset);
++
++ if (spd) {
++ static char __initdata opt[16];
++ sprintf(opt, "%d", *spd);
++ return add_preferred_console("ttyS", offset, opt);
++ } else
++ return add_preferred_console("ttyS", offset, NULL);
++
++ not_found:
++ DBG("No preferred console found !\n");
++ of_node_put(prom_stdout);
++ return -ENODEV;
++}
++console_initcall(set_preferred_console);
++#endif /* CONFIG_PPC_MULTIPLATFORM */
+diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/setup_32.c
+@@ -0,0 +1,372 @@
++/*
++ * Common prep/pmac/chrp boot and setup code.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/reboot.h>
++#include <linux/delay.h>
++#include <linux/initrd.h>
++#include <linux/ide.h>
++#include <linux/tty.h>
++#include <linux/bootmem.h>
++#include <linux/seq_file.h>
++#include <linux/root_dev.h>
++#include <linux/cpu.h>
++#include <linux/console.h>
++
++#include <asm/residual.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/processor.h>
++#include <asm/pgtable.h>
++#include <asm/setup.h>
++#include <asm/amigappc.h>
++#include <asm/smp.h>
++#include <asm/elf.h>
++#include <asm/cputable.h>
++#include <asm/bootx.h>
++#include <asm/btext.h>
++#include <asm/machdep.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/pmac_feature.h>
++#include <asm/sections.h>
++#include <asm/nvram.h>
++#include <asm/xmon.h>
++#include <asm/time.h>
++
++#define DBG(fmt...)
++
++#if defined CONFIG_KGDB
++#include <asm/kgdb.h>
++#endif
++
++extern void platform_init(void);
++extern void bootx_init(unsigned long r4, unsigned long phys);
++
++extern void ppc6xx_idle(void);
++extern void power4_idle(void);
++
++boot_infos_t *boot_infos;
++struct ide_machdep_calls ppc_ide_md;
++
++/* XXX should go elsewhere */
++int __irq_offset_value;
++EXPORT_SYMBOL(__irq_offset_value);
++
++int boot_cpuid;
++EXPORT_SYMBOL_GPL(boot_cpuid);
++int boot_cpuid_phys;
++
++unsigned long ISA_DMA_THRESHOLD;
++unsigned int DMA_MODE_READ;
++unsigned int DMA_MODE_WRITE;
++
++int have_of = 1;
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++int _machine = 0;
++
++extern void prep_init(void);
++extern void pmac_init(void);
++extern void chrp_init(void);
++
++dev_t boot_dev;
++#endif /* CONFIG_PPC_MULTIPLATFORM */
++
++#ifdef CONFIG_MAGIC_SYSRQ
++unsigned long SYSRQ_KEY = 0x54;
++#endif /* CONFIG_MAGIC_SYSRQ */
++
++#ifdef CONFIG_VGA_CONSOLE
++unsigned long vgacon_remap_base;
++#endif
++
++struct machdep_calls ppc_md;
++EXPORT_SYMBOL(ppc_md);
++
++/*
++ * These are used in binfmt_elf.c to put aux entries on the stack
++ * for each elf executable being started.
++ */
++int dcache_bsize;
++int icache_bsize;
++int ucache_bsize;
++
++/*
++ * We're called here very early in the boot. We determine the machine
++ * type and call the appropriate low-level setup functions.
++ * -- Cort <cort at fsmlabs.com>
++ *
++ * Note that the kernel may be running at an address which is different
++ * from the address that it was linked at, so we must use RELOC/PTRRELOC
++ * to access static data (including strings). -- paulus
++ */
++unsigned long __init early_init(unsigned long dt_ptr)
++{
++ unsigned long offset = reloc_offset();
++
++ /* First zero the BSS -- use memset_io, some platforms don't have
++ * caches on yet */
++ memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
++
++ /*
++ * Identify the CPU type and fix up code sections
++ * that depend on which cpu we have.
++ */
++ identify_cpu(offset, 0);
++ do_cpu_ftr_fixups(offset);
++
++ return KERNELBASE + offset;
++}
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++/*
++ * The PPC_MULTIPLATFORM version of platform_init...
++ */
++void __init platform_init(void)
++{
++ /* if we didn't get any bootinfo telling us what we are... */
++ if (_machine == 0) {
++ /* prep boot loader tells us if we're prep or not */
++ if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
++ _machine = _MACH_prep;
++ }
++
++#ifdef CONFIG_PPC_PREP
++ /* not much more to do here, if prep */
++ if (_machine == _MACH_prep) {
++ prep_init();
++ return;
++ }
++#endif
++
++#ifdef CONFIG_ADB
++ if (strstr(cmd_line, "adb_sync")) {
++ extern int __adb_probe_sync;
++ __adb_probe_sync = 1;
++ }
++#endif /* CONFIG_ADB */
++
++ switch (_machine) {
++#ifdef CONFIG_PPC_PMAC
++ case _MACH_Pmac:
++ pmac_init();
++ break;
++#endif
++#ifdef CONFIG_PPC_CHRP
++ case _MACH_chrp:
++ chrp_init();
++ break;
++#endif
++ }
++}
++#endif
++
++/*
++ * Find out what kind of machine we're on and save any data we need
++ * from the early boot process (devtree is copied on pmac by prom_init()).
++ * This is called very early on the boot process, after a minimal
++ * MMU environment has been set up but before MMU_init is called.
++ */
++void __init machine_init(unsigned long dt_ptr, unsigned long phys)
++{
++ early_init_devtree(__va(dt_ptr));
++
++#ifdef CONFIG_CMDLINE
++ strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
++#endif /* CONFIG_CMDLINE */
++
++ platform_init();
++
++#ifdef CONFIG_6xx
++ ppc_md.power_save = ppc6xx_idle;
++#endif
++
++ if (ppc_md.progress)
++ ppc_md.progress("id mach(): done", 0x200);
++}
++
++#ifdef CONFIG_BOOKE_WDT
++/* Checks wdt=x and wdt_period=xx command-line option */
++int __init early_parse_wdt(char *p)
++{
++ if (p && strncmp(p, "0", 1) != 0)
++ booke_wdt_enabled = 1;
++
++ return 0;
++}
++early_param("wdt", early_parse_wdt);
++
++int __init early_parse_wdt_period (char *p)
++{
++ if (p)
++ booke_wdt_period = simple_strtoul(p, NULL, 0);
++
++ return 0;
++}
++early_param("wdt_period", early_parse_wdt_period);
++#endif /* CONFIG_BOOKE_WDT */
++
++/* Checks "l2cr=xxxx" command-line option */
++int __init ppc_setup_l2cr(char *str)
++{
++ if (cpu_has_feature(CPU_FTR_L2CR)) {
++ unsigned long val = simple_strtoul(str, NULL, 0);
++ printk(KERN_INFO "l2cr set to %lx\n", val);
++ _set_L2CR(0); /* force invalidate by disable cache */
++ _set_L2CR(val); /* and enable it */
++ }
++ return 1;
++}
++__setup("l2cr=", ppc_setup_l2cr);
++
++#ifdef CONFIG_GENERIC_NVRAM
++
++/* Generic nvram hooks used by drivers/char/gen_nvram.c */
++unsigned char nvram_read_byte(int addr)
++{
++ if (ppc_md.nvram_read_val)
++ return ppc_md.nvram_read_val(addr);
++ return 0xff;
++}
++EXPORT_SYMBOL(nvram_read_byte);
++
++void nvram_write_byte(unsigned char val, int addr)
++{
++ if (ppc_md.nvram_write_val)
++ ppc_md.nvram_write_val(addr, val);
++}
++EXPORT_SYMBOL(nvram_write_byte);
++
++void nvram_sync(void)
++{
++ if (ppc_md.nvram_sync)
++ ppc_md.nvram_sync();
++}
++EXPORT_SYMBOL(nvram_sync);
++
++#endif /* CONFIG_NVRAM */
++
++static struct cpu cpu_devices[NR_CPUS];
++
++int __init ppc_init(void)
++{
++ int i;
++
++ /* clear the progress line */
++ if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
++
++ /* register CPU devices */
++ for (i = 0; i < NR_CPUS; i++)
++ if (cpu_possible(i))
++ register_cpu(&cpu_devices[i], i, NULL);
++
++ /* call platform init */
++ if (ppc_md.init != NULL) {
++ ppc_md.init();
++ }
++ return 0;
++}
++
++arch_initcall(ppc_init);
++
++/* Warning, IO base is not yet inited */
++void __init setup_arch(char **cmdline_p)
++{
++ extern char *klimit;
++ extern void do_init_bootmem(void);
++
++ /* so udelay does something sensible, assume <= 1000 bogomips */
++ loops_per_jiffy = 500000000 / HZ;
++
++ unflatten_device_tree();
++ finish_device_tree();
++
++#ifdef CONFIG_BOOTX_TEXT
++ init_boot_display();
++#endif
++
++#ifdef CONFIG_PPC_PMAC
++ /* This could be called "early setup arch", it must be done
++ * now because xmon need it
++ */
++ if (_machine == _MACH_Pmac)
++ pmac_feature_init(); /* New cool way */
++#endif
++
++#ifdef CONFIG_XMON
++ xmon_map_scc();
++ if (strstr(cmd_line, "xmon")) {
++ xmon_init(1);
++ debugger(NULL);
++ }
++#endif /* CONFIG_XMON */
++ if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
++
++#if defined(CONFIG_KGDB)
++ if (ppc_md.kgdb_map_scc)
++ ppc_md.kgdb_map_scc();
++ set_debug_traps();
++ if (strstr(cmd_line, "gdb")) {
++ if (ppc_md.progress)
++ ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
++ printk("kgdb breakpoint activated\n");
++ breakpoint();
++ }
++#endif
++
++ /*
++ * Set cache line size based on type of cpu as a default.
++ * Systems with OF can look in the properties on the cpu node(s)
++ * for a possibly more accurate value.
++ */
++ if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
++ dcache_bsize = cur_cpu_spec->dcache_bsize;
++ icache_bsize = cur_cpu_spec->icache_bsize;
++ ucache_bsize = 0;
++ } else
++ ucache_bsize = dcache_bsize = icache_bsize
++ = cur_cpu_spec->dcache_bsize;
++
++ /* reboot on panic */
++ panic_timeout = 180;
++
++ init_mm.start_code = PAGE_OFFSET;
++ init_mm.end_code = (unsigned long) _etext;
++ init_mm.end_data = (unsigned long) _edata;
++ init_mm.brk = (unsigned long) klimit;
++
++ /* Save unparsed command line copy for /proc/cmdline */
++ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
++ *cmdline_p = cmd_line;
++
++ parse_early_param();
++
++ /* set up the bootmem stuff with available memory */
++ do_init_bootmem();
++ if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
++
++#ifdef CONFIG_PPC_OCP
++ /* Initialize OCP device list */
++ ocp_early_init();
++ if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
++#endif
++
++#ifdef CONFIG_DUMMY_CONSOLE
++ conswitchp = &dummy_con;
++#endif
++
++ ppc_md.setup_arch();
++ if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
++
++ paging_init();
++
++ /* this is for modules since _machine can be a define -- Cort */
++ ppc_md.ppc_machine = _machine;
++}
+diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/setup_64.c
+@@ -0,0 +1,1028 @@
++/*
++ *
++ * Common boot and setup code.
++ *
++ * Copyright (C) 2001 PPC64 Team, IBM Corp
++ *
++ * 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.
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/reboot.h>
++#include <linux/delay.h>
++#include <linux/initrd.h>
++#include <linux/ide.h>
++#include <linux/seq_file.h>
++#include <linux/ioport.h>
++#include <linux/console.h>
++#include <linux/utsname.h>
++#include <linux/tty.h>
++#include <linux/root_dev.h>
++#include <linux/notifier.h>
++#include <linux/cpu.h>
++#include <linux/unistd.h>
++#include <linux/serial.h>
++#include <linux/serial_8250.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/processor.h>
++#include <asm/pgtable.h>
++#include <asm/smp.h>
++#include <asm/elf.h>
++#include <asm/machdep.h>
++#include <asm/paca.h>
++#include <asm/ppcdebug.h>
++#include <asm/time.h>
++#include <asm/cputable.h>
++#include <asm/sections.h>
++#include <asm/btext.h>
++#include <asm/nvram.h>
++#include <asm/setup.h>
++#include <asm/system.h>
++#include <asm/rtas.h>
++#include <asm/iommu.h>
++#include <asm/serial.h>
++#include <asm/cache.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/lmb.h>
++#include <asm/iSeries/ItLpNaca.h>
++#include <asm/firmware.h>
++#include <asm/systemcfg.h>
++#include <asm/xmon.h>
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/*
++ * Here are some early debugging facilities. You can enable one
++ * but your kernel will not boot on anything else if you do so
++ */
++
++/* This one is for use on LPAR machines that support an HVC console
++ * on vterm 0
++ */
++extern void udbg_init_debug_lpar(void);
++/* This one is for use on Apple G5 machines
++ */
++extern void udbg_init_pmac_realmode(void);
++/* That's RTAS panel debug */
++extern void call_rtas_display_status_delay(unsigned char c);
++/* Here's maple real mode debug */
++extern void udbg_init_maple_realmode(void);
++
++#define EARLY_DEBUG_INIT() do {} while(0)
++
++#if 0
++#define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
++#define EARLY_DEBUG_INIT() udbg_init_maple_realmode()
++#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
++#define EARLY_DEBUG_INIT() \
++ do { udbg_putc = call_rtas_display_status_delay; } while(0)
++#endif
++
++/* extern void *stab; */
++extern unsigned long klimit;
++
++extern void mm_init_ppc64(void);
++extern void stab_initialize(unsigned long stab);
++extern void htab_initialize(void);
++extern void early_init_devtree(void *flat_dt);
++extern void unflatten_device_tree(void);
++
++extern void smp_release_cpus(void);
++
++int have_of = 1;
++int boot_cpuid = 0;
++int boot_cpuid_phys = 0;
++dev_t boot_dev;
++u64 ppc64_pft_size;
++
++struct ppc64_caches ppc64_caches;
++EXPORT_SYMBOL_GPL(ppc64_caches);
++
++/*
++ * These are used in binfmt_elf.c to put aux entries on the stack
++ * for each elf executable being started.
++ */
++int dcache_bsize;
++int icache_bsize;
++int ucache_bsize;
++
++/* The main machine-dep calls structure
++ */
++struct machdep_calls ppc_md;
++EXPORT_SYMBOL(ppc_md);
++
++#ifdef CONFIG_MAGIC_SYSRQ
++unsigned long SYSRQ_KEY;
++#endif /* CONFIG_MAGIC_SYSRQ */
++
++
++static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
++static struct notifier_block ppc64_panic_block = {
++ .notifier_call = ppc64_panic_event,
++ .priority = INT_MIN /* may not return; must be done last */
++};
++
++#ifdef CONFIG_SMP
++
++static int smt_enabled_cmdline;
++
++/* Look for ibm,smt-enabled OF option */
++static void check_smt_enabled(void)
++{
++ struct device_node *dn;
++ char *smt_option;
++
++ /* Allow the command line to overrule the OF option */
++ if (smt_enabled_cmdline)
++ return;
++
++ dn = of_find_node_by_path("/options");
++
++ if (dn) {
++ smt_option = (char *)get_property(dn, "ibm,smt-enabled", NULL);
++
++ if (smt_option) {
++ if (!strcmp(smt_option, "on"))
++ smt_enabled_at_boot = 1;
++ else if (!strcmp(smt_option, "off"))
++ smt_enabled_at_boot = 0;
++ }
++ }
++}
++
++/* Look for smt-enabled= cmdline option */
++static int __init early_smt_enabled(char *p)
++{
++ smt_enabled_cmdline = 1;
++
++ if (!p)
++ return 0;
++
++ if (!strcmp(p, "on") || !strcmp(p, "1"))
++ smt_enabled_at_boot = 1;
++ else if (!strcmp(p, "off") || !strcmp(p, "0"))
++ smt_enabled_at_boot = 0;
++
++ return 0;
++}
++early_param("smt-enabled", early_smt_enabled);
++
++/**
++ * setup_cpu_maps - initialize the following cpu maps:
++ * cpu_possible_map
++ * cpu_present_map
++ * cpu_sibling_map
++ *
++ * Having the possible map set up early allows us to restrict allocations
++ * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
++ *
++ * We do not initialize the online map here; cpus set their own bits in
++ * cpu_online_map as they come up.
++ *
++ * This function is valid only for Open Firmware systems. finish_device_tree
++ * must be called before using this.
++ *
++ * While we're here, we may as well set the "physical" cpu ids in the paca.
++ */
++static void __init setup_cpu_maps(void)
++{
++ struct device_node *dn = NULL;
++ int cpu = 0;
++ int swap_cpuid = 0;
++
++ check_smt_enabled();
++
++ while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
++ u32 *intserv;
++ int j, len = sizeof(u32), nthreads;
++
++ intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s",
++ &len);
++ if (!intserv)
++ intserv = (u32 *)get_property(dn, "reg", NULL);
++
++ nthreads = len / sizeof(u32);
++
++ for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
++ cpu_set(cpu, cpu_present_map);
++ set_hard_smp_processor_id(cpu, intserv[j]);
++
++ if (intserv[j] == boot_cpuid_phys)
++ swap_cpuid = cpu;
++ cpu_set(cpu, cpu_possible_map);
++ cpu++;
++ }
++ }
++
++ /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
++ * boot cpu is logical 0.
++ */
++ if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
++ u32 tmp;
++ tmp = get_hard_smp_processor_id(0);
++ set_hard_smp_processor_id(0, boot_cpuid_phys);
++ set_hard_smp_processor_id(swap_cpuid, tmp);
++ }
++
++ /*
++ * On pSeries LPAR, we need to know how many cpus
++ * could possibly be added to this partition.
++ */
++ if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
++ (dn = of_find_node_by_path("/rtas"))) {
++ int num_addr_cell, num_size_cell, maxcpus;
++ unsigned int *ireg;
++
++ num_addr_cell = prom_n_addr_cells(dn);
++ num_size_cell = prom_n_size_cells(dn);
++
++ ireg = (unsigned int *)
++ get_property(dn, "ibm,lrdr-capacity", NULL);
++
++ if (!ireg)
++ goto out;
++
++ maxcpus = ireg[num_addr_cell + num_size_cell];
++
++ /* Double maxcpus for processors which have SMT capability */
++ if (cpu_has_feature(CPU_FTR_SMT))
++ maxcpus *= 2;
++
++ if (maxcpus > NR_CPUS) {
++ printk(KERN_WARNING
++ "Partition configured for %d cpus, "
++ "operating system maximum is %d.\n",
++ maxcpus, NR_CPUS);
++ maxcpus = NR_CPUS;
++ } else
++ printk(KERN_INFO "Partition configured for %d cpus.\n",
++ maxcpus);
++
++ for (cpu = 0; cpu < maxcpus; cpu++)
++ cpu_set(cpu, cpu_possible_map);
++ out:
++ of_node_put(dn);
++ }
++
++ /*
++ * Do the sibling map; assume only two threads per processor.
++ */
++ for_each_cpu(cpu) {
++ cpu_set(cpu, cpu_sibling_map[cpu]);
++ if (cpu_has_feature(CPU_FTR_SMT))
++ cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
++ }
++
++ systemcfg->processorCount = num_present_cpus();
++}
++#endif /* CONFIG_SMP */
++
++extern struct machdep_calls pSeries_md;
++extern struct machdep_calls pmac_md;
++extern struct machdep_calls maple_md;
++extern struct machdep_calls bpa_md;
++extern struct machdep_calls iseries_md;
++
++/* Ultimately, stuff them in an elf section like initcalls... */
++static struct machdep_calls __initdata *machines[] = {
++#ifdef CONFIG_PPC_PSERIES
++ &pSeries_md,
++#endif /* CONFIG_PPC_PSERIES */
++#ifdef CONFIG_PPC_PMAC
++ &pmac_md,
++#endif /* CONFIG_PPC_PMAC */
++#ifdef CONFIG_PPC_MAPLE
++ &maple_md,
++#endif /* CONFIG_PPC_MAPLE */
++#ifdef CONFIG_PPC_BPA
++ &bpa_md,
++#endif
++#ifdef CONFIG_PPC_ISERIES
++ &iseries_md,
++#endif
++ NULL
++};
++
++/*
++ * Early initialization entry point. This is called by head.S
++ * with MMU translation disabled. We rely on the "feature" of
++ * the CPU that ignores the top 2 bits of the address in real
++ * mode so we can access kernel globals normally provided we
++ * only toy with things in the RMO region. From here, we do
++ * some early parsing of the device-tree to setup out LMB
++ * data structures, and allocate & initialize the hash table
++ * and segment tables so we can start running with translation
++ * enabled.
++ *
++ * It is this function which will call the probe() callback of
++ * the various platform types and copy the matching one to the
++ * global ppc_md structure. Your platform can eventually do
++ * some very early initializations from the probe() routine, but
++ * this is not recommended, be very careful as, for example, the
++ * device-tree is not accessible via normal means at this point.
++ */
++
++void __init early_setup(unsigned long dt_ptr)
++{
++ struct paca_struct *lpaca = get_paca();
++ static struct machdep_calls **mach;
++
++ /*
++ * Enable early debugging if any specified (see top of
++ * this file)
++ */
++ EARLY_DEBUG_INIT();
++
++ DBG(" -> early_setup()\n");
++
++ /*
++ * Fill the default DBG level (do we want to keep
++ * that old mecanism around forever ?)
++ */
++ ppcdbg_initialize();
++
++ /*
++ * Do early initializations using the flattened device
++ * tree, like retreiving the physical memory map or
++ * calculating/retreiving the hash table size
++ */
++ early_init_devtree(__va(dt_ptr));
++
++ /*
++ * Iterate all ppc_md structures until we find the proper
++ * one for the current machine type
++ */
++ DBG("Probing machine type for platform %x...\n",
++ systemcfg->platform);
++
++ for (mach = machines; *mach; mach++) {
++ if ((*mach)->probe(systemcfg->platform))
++ break;
++ }
++ /* What can we do if we didn't find ? */
++ if (*mach == NULL) {
++ DBG("No suitable machine found !\n");
++ for (;;);
++ }
++ ppc_md = **mach;
++
++ DBG("Found, Initializing memory management...\n");
++
++ /*
++ * Initialize stab / SLB management
++ */
++ if (!firmware_has_feature(FW_FEATURE_ISERIES))
++ stab_initialize(lpaca->stab_real);
++
++ /*
++ * Initialize the MMU Hash table and create the linear mapping
++ * of memory
++ */
++ htab_initialize();
++
++ DBG(" <- early_setup()\n");
++}
++
++
++/*
++ * Initialize some remaining members of the ppc64_caches and systemcfg structures
++ * (at least until we get rid of them completely). This is mostly some
++ * cache informations about the CPU that will be used by cache flush
++ * routines and/or provided to userland
++ */
++static void __init initialize_cache_info(void)
++{
++ struct device_node *np;
++ unsigned long num_cpus = 0;
++
++ DBG(" -> initialize_cache_info()\n");
++
++ for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
++ num_cpus += 1;
++
++ /* We're assuming *all* of the CPUs have the same
++ * d-cache and i-cache sizes... -Peter
++ */
++
++ if ( num_cpus == 1 ) {
++ u32 *sizep, *lsizep;
++ u32 size, lsize;
++ const char *dc, *ic;
++
++ /* Then read cache informations */
++ if (systemcfg->platform == PLATFORM_POWERMAC) {
++ dc = "d-cache-block-size";
++ ic = "i-cache-block-size";
++ } else {
++ dc = "d-cache-line-size";
++ ic = "i-cache-line-size";
++ }
++
++ size = 0;
++ lsize = cur_cpu_spec->dcache_bsize;
++ sizep = (u32 *)get_property(np, "d-cache-size", NULL);
++ if (sizep != NULL)
++ size = *sizep;
++ lsizep = (u32 *) get_property(np, dc, NULL);
++ if (lsizep != NULL)
++ lsize = *lsizep;
++ if (sizep == 0 || lsizep == 0)
++ DBG("Argh, can't find dcache properties ! "
++ "sizep: %p, lsizep: %p\n", sizep, lsizep);
++
++ systemcfg->dcache_size = ppc64_caches.dsize = size;
++ systemcfg->dcache_line_size =
++ ppc64_caches.dline_size = lsize;
++ ppc64_caches.log_dline_size = __ilog2(lsize);
++ ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
++
++ size = 0;
++ lsize = cur_cpu_spec->icache_bsize;
++ sizep = (u32 *)get_property(np, "i-cache-size", NULL);
++ if (sizep != NULL)
++ size = *sizep;
++ lsizep = (u32 *)get_property(np, ic, NULL);
++ if (lsizep != NULL)
++ lsize = *lsizep;
++ if (sizep == 0 || lsizep == 0)
++ DBG("Argh, can't find icache properties ! "
++ "sizep: %p, lsizep: %p\n", sizep, lsizep);
++
++ systemcfg->icache_size = ppc64_caches.isize = size;
++ systemcfg->icache_line_size =
++ ppc64_caches.iline_size = lsize;
++ ppc64_caches.log_iline_size = __ilog2(lsize);
++ ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
++ }
++ }
++
++ /* Add an eye catcher and the systemcfg layout version number */
++ strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
++ systemcfg->version.major = SYSTEMCFG_MAJOR;
++ systemcfg->version.minor = SYSTEMCFG_MINOR;
++ systemcfg->processor = mfspr(SPRN_PVR);
++
++ DBG(" <- initialize_cache_info()\n");
++}
++
++static void __init check_for_initrd(void)
++{
++#ifdef CONFIG_BLK_DEV_INITRD
++ u64 *prop;
++
++ DBG(" -> check_for_initrd()\n");
++
++ if (of_chosen) {
++ prop = (u64 *)get_property(of_chosen,
++ "linux,initrd-start", NULL);
++ if (prop != NULL) {
++ initrd_start = (unsigned long)__va(*prop);
++ prop = (u64 *)get_property(of_chosen,
++ "linux,initrd-end", NULL);
++ if (prop != NULL) {
++ initrd_end = (unsigned long)__va(*prop);
++ initrd_below_start_ok = 1;
++ } else
++ initrd_start = 0;
++ }
++ }
++
++ /* If we were passed an initrd, set the ROOT_DEV properly if the values
++ * look sensible. If not, clear initrd reference.
++ */
++ if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
++ initrd_end > initrd_start)
++ ROOT_DEV = Root_RAM0;
++ else
++ initrd_start = initrd_end = 0;
++
++ if (initrd_start)
++ printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end);
++
++ DBG(" <- check_for_initrd()\n");
++#endif /* CONFIG_BLK_DEV_INITRD */
++}
++
++/*
++ * Do some initial setup of the system. The parameters are those which
++ * were passed in from the bootloader.
++ */
++void __init setup_system(void)
++{
++ DBG(" -> setup_system()\n");
++
++ /*
++ * Unflatten the device-tree passed by prom_init or kexec
++ */
++ unflatten_device_tree();
++
++ /*
++ * Fill the ppc64_caches & systemcfg structures with informations
++ * retreived from the device-tree. Need to be called before
++ * finish_device_tree() since the later requires some of the
++ * informations filled up here to properly parse the interrupt
++ * tree.
++ * It also sets up the cache line sizes which allows to call
++ * routines like flush_icache_range (used by the hash init
++ * later on).
++ */
++ initialize_cache_info();
++
++#ifdef CONFIG_PPC_RTAS
++ /*
++ * Initialize RTAS if available
++ */
++ rtas_initialize();
++#endif /* CONFIG_PPC_RTAS */
++
++ /*
++ * Check if we have an initrd provided via the device-tree
++ */
++ check_for_initrd();
++
++ /*
++ * Do some platform specific early initializations, that includes
++ * setting up the hash table pointers. It also sets up some interrupt-mapping
++ * related options that will be used by finish_device_tree()
++ */
++ ppc_md.init_early();
++
++ /*
++ * "Finish" the device-tree, that is do the actual parsing of
++ * some of the properties like the interrupt map
++ */
++ finish_device_tree();
++
++#ifdef CONFIG_BOOTX_TEXT
++ init_boot_display();
++#endif
++
++ /*
++ * Initialize xmon
++ */
++#ifdef CONFIG_XMON_DEFAULT
++ xmon_init(1);
++#endif
++ /*
++ * Register early console
++ */
++ register_early_udbg_console();
++
++ /* Save unparsed command line copy for /proc/cmdline */
++ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
++
++ parse_early_param();
++
++#ifdef CONFIG_SMP
++ /*
++ * iSeries has already initialized the cpu maps at this point.
++ */
++ setup_cpu_maps();
++
++ /* Release secondary cpus out of their spinloops at 0x60 now that
++ * we can map physical -> logical CPU ids
++ */
++ smp_release_cpus();
++#endif
++
++ printk("Starting Linux PPC64 %s\n", system_utsname.version);
++
++ printk("-----------------------------------------------------\n");
++ printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
++ printk("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch);
++ printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller);
++ printk("systemcfg = 0x%p\n", systemcfg);
++ printk("systemcfg->platform = 0x%x\n", systemcfg->platform);
++ printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount);
++ printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
++ printk("ppc64_caches.dcache_line_size = 0x%x\n",
++ ppc64_caches.dline_size);
++ printk("ppc64_caches.icache_line_size = 0x%x\n",
++ ppc64_caches.iline_size);
++ printk("htab_address = 0x%p\n", htab_address);
++ printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
++ printk("-----------------------------------------------------\n");
++
++ mm_init_ppc64();
++
++ DBG(" <- setup_system()\n");
++}
++
++static int ppc64_panic_event(struct notifier_block *this,
++ unsigned long event, void *ptr)
++{
++ ppc_md.panic((char *)ptr); /* May not return */
++ return NOTIFY_DONE;
++}
++
++#ifdef CONFIG_PPC_ISERIES
++/*
++ * On iSeries we just parse the mem=X option from the command line.
++ * On pSeries it's a bit more complicated, see prom_init_mem()
++ */
++static int __init early_parsemem(char *p)
++{
++ if (!p)
++ return 0;
++
++ memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
++
++ return 0;
++}
++early_param("mem", early_parsemem);
++#endif /* CONFIG_PPC_ISERIES */
++
++#ifdef CONFIG_IRQSTACKS
++static void __init irqstack_early_init(void)
++{
++ unsigned int i;
++
++ /*
++ * interrupt stacks must be under 256MB, we cannot afford to take
++ * SLB misses on them.
++ */
++ for_each_cpu(i) {
++ softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
++ THREAD_SIZE, 0x10000000));
++ hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
++ THREAD_SIZE, 0x10000000));
++ }
++}
++#else
++#define irqstack_early_init()
++#endif
++
++/*
++ * Stack space used when we detect a bad kernel stack pointer, and
++ * early in SMP boots before relocation is enabled.
++ */
++static void __init emergency_stack_init(void)
++{
++ unsigned long limit;
++ unsigned int i;
++
++ /*
++ * Emergency stacks must be under 256MB, we cannot afford to take
++ * SLB misses on them. The ABI also requires them to be 128-byte
++ * aligned.
++ *
++ * Since we use these as temporary stacks during secondary CPU
++ * bringup, we need to get at them in real mode. This means they
++ * must also be within the RMO region.
++ */
++ limit = min(0x10000000UL, lmb.rmo_size);
++
++ for_each_cpu(i)
++ paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128,
++ limit)) + PAGE_SIZE;
++}
++
++/*
++ * Called from setup_arch to initialize the bitmap of available
++ * syscalls in the systemcfg page
++ */
++void __init setup_syscall_map(void)
++{
++ unsigned int i, count64 = 0, count32 = 0;
++ extern unsigned long *sys_call_table;
++ extern unsigned long sys_ni_syscall;
++
++
++ for (i = 0; i < __NR_syscalls; i++) {
++ if (sys_call_table[i*2] != sys_ni_syscall) {
++ count64++;
++ systemcfg->syscall_map_64[i >> 5] |=
++ 0x80000000UL >> (i & 0x1f);
++ }
++ if (sys_call_table[i*2+1] != sys_ni_syscall) {
++ count32++;
++ systemcfg->syscall_map_32[i >> 5] |=
++ 0x80000000UL >> (i & 0x1f);
++ }
++ }
++ printk(KERN_INFO "Syscall map setup, %d 32-bit and %d 64-bit syscalls\n",
++ count32, count64);
++}
++
++/*
++ * Called into from start_kernel, after lock_kernel has been called.
++ * Initializes bootmem, which is unsed to manage page allocation until
++ * mem_init is called.
++ */
++void __init setup_arch(char **cmdline_p)
++{
++ extern void do_init_bootmem(void);
++
++ ppc64_boot_msg(0x12, "Setup Arch");
++
++ *cmdline_p = cmd_line;
++
++ /*
++ * Set cache line size based on type of cpu as a default.
++ * Systems with OF can look in the properties on the cpu node(s)
++ * for a possibly more accurate value.
++ */
++ dcache_bsize = ppc64_caches.dline_size;
++ icache_bsize = ppc64_caches.iline_size;
++
++ /* reboot on panic */
++ panic_timeout = 180;
++
++ if (ppc_md.panic)
++ notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
++
++ init_mm.start_code = PAGE_OFFSET;
++ init_mm.end_code = (unsigned long) _etext;
++ init_mm.end_data = (unsigned long) _edata;
++ init_mm.brk = klimit;
++
++ irqstack_early_init();
++ emergency_stack_init();
++
++ stabs_alloc();
++
++ /* set up the bootmem stuff with available memory */
++ do_init_bootmem();
++ sparse_init();
++
++ /* initialize the syscall map in systemcfg */
++ setup_syscall_map();
++
++#ifdef CONFIG_DUMMY_CONSOLE
++ conswitchp = &dummy_con;
++#endif
++
++ ppc_md.setup_arch();
++
++ /* Use the default idle loop if the platform hasn't provided one. */
++ if (NULL == ppc_md.idle_loop) {
++ ppc_md.idle_loop = default_idle;
++ printk(KERN_INFO "Using default idle loop\n");
++ }
++
++ paging_init();
++ ppc64_boot_msg(0x15, "Setup Done");
++}
++
++
++/* ToDo: do something useful if ppc_md is not yet setup. */
++#define PPC64_LINUX_FUNCTION 0x0f000000
++#define PPC64_IPL_MESSAGE 0xc0000000
++#define PPC64_TERM_MESSAGE 0xb0000000
++
++static void ppc64_do_msg(unsigned int src, const char *msg)
++{
++ if (ppc_md.progress) {
++ char buf[128];
++
++ sprintf(buf, "%08X\n", src);
++ ppc_md.progress(buf, 0);
++ snprintf(buf, 128, "%s", msg);
++ ppc_md.progress(buf, 0);
++ }
++}
++
++/* Print a boot progress message. */
++void ppc64_boot_msg(unsigned int src, const char *msg)
++{
++ ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
++ printk("[boot]%04x %s\n", src, msg);
++}
++
++/* Print a termination message (print only -- does not stop the kernel) */
++void ppc64_terminate_msg(unsigned int src, const char *msg)
++{
++ ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
++ printk("[terminate]%04x %s\n", src, msg);
++}
++
++#ifndef CONFIG_PPC_ISERIES
++/*
++ * This function can be used by platforms to "find" legacy serial ports.
++ * It works for "serial" nodes under an "isa" node, and will try to
++ * respect the "ibm,aix-loc" property if any. It works with up to 8
++ * ports.
++ */
++
++#define MAX_LEGACY_SERIAL_PORTS 8
++static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
++static unsigned int old_serial_count;
++
++void __init generic_find_legacy_serial_ports(u64 *physport,
++ unsigned int *default_speed)
++{
++ struct device_node *np;
++ u32 *sizeprop;
++
++ struct isa_reg_property {
++ u32 space;
++ u32 address;
++ u32 size;
++ };
++ struct pci_reg_property {
++ struct pci_address addr;
++ u32 size_hi;
++ u32 size_lo;
++ };
++
++ DBG(" -> generic_find_legacy_serial_port()\n");
++
++ *physport = 0;
++ if (default_speed)
++ *default_speed = 0;
++
++ np = of_find_node_by_path("/");
++ if (!np)
++ return;
++
++ /* First fill our array */
++ for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
++ struct device_node *isa, *pci;
++ struct isa_reg_property *reg;
++ unsigned long phys_size, addr_size, io_base;
++ u32 *rangesp;
++ u32 *interrupts, *clk, *spd;
++ char *typep;
++ int index, rlen, rentsize;
++
++ /* Ok, first check if it's under an "isa" parent */
++ isa = of_get_parent(np);
++ if (!isa || strcmp(isa->name, "isa")) {
++ DBG("%s: no isa parent found\n", np->full_name);
++ continue;
++ }
++
++ /* Now look for an "ibm,aix-loc" property that gives us ordering
++ * if any...
++ */
++ typep = (char *)get_property(np, "ibm,aix-loc", NULL);
++
++ /* Get the ISA port number */
++ reg = (struct isa_reg_property *)get_property(np, "reg", NULL);
++ if (reg == NULL)
++ goto next_port;
++ /* We assume the interrupt number isn't translated ... */
++ interrupts = (u32 *)get_property(np, "interrupts", NULL);
++ /* get clock freq. if present */
++ clk = (u32 *)get_property(np, "clock-frequency", NULL);
++ /* get default speed if present */
++ spd = (u32 *)get_property(np, "current-speed", NULL);
++ /* Default to locate at end of array */
++ index = old_serial_count; /* end of the array by default */
++
++ /* If we have a location index, then use it */
++ if (typep && *typep == 'S') {
++ index = simple_strtol(typep+1, NULL, 0) - 1;
++ /* if index is out of range, use end of array instead */
++ if (index >= MAX_LEGACY_SERIAL_PORTS)
++ index = old_serial_count;
++ /* if our index is still out of range, that mean that
++ * array is full, we could scan for a free slot but that
++ * make little sense to bother, just skip the port
++ */
++ if (index >= MAX_LEGACY_SERIAL_PORTS)
++ goto next_port;
++ if (index >= old_serial_count)
++ old_serial_count = index + 1;
++ /* Check if there is a port who already claimed our slot */
++ if (serial_ports[index].iobase != 0) {
++ /* if we still have some room, move it, else override */
++ if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
++ DBG("Moved legacy port %d -> %d\n", index,
++ old_serial_count);
++ serial_ports[old_serial_count++] =
++ serial_ports[index];
++ } else {
++ DBG("Replacing legacy port %d\n", index);
++ }
++ }
++ }
++ if (index >= MAX_LEGACY_SERIAL_PORTS)
++ goto next_port;
++ if (index >= old_serial_count)
++ old_serial_count = index + 1;
++
++ /* Now fill the entry */
++ memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port));
++ serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16;
++ serial_ports[index].iobase = reg->address;
++ serial_ports[index].irq = interrupts ? interrupts[0] : 0;
++ serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
++
++ DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
++ index,
++ serial_ports[index].iobase,
++ serial_ports[index].irq,
++ serial_ports[index].uartclk);
++
++ /* Get phys address of IO reg for port 1 */
++ if (index != 0)
++ goto next_port;
++
++ pci = of_get_parent(isa);
++ if (!pci) {
++ DBG("%s: no pci parent found\n", np->full_name);
++ goto next_port;
++ }
++
++ rangesp = (u32 *)get_property(pci, "ranges", &rlen);
++ if (rangesp == NULL) {
++ of_node_put(pci);
++ goto next_port;
++ }
++ rlen /= 4;
++
++ /* we need the #size-cells of the PCI bridge node itself */
++ phys_size = 1;
++ sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
++ if (sizeprop != NULL)
++ phys_size = *sizeprop;
++ /* we need the parent #addr-cells */
++ addr_size = prom_n_addr_cells(pci);
++ rentsize = 3 + addr_size + phys_size;
++ io_base = 0;
++ for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
++ if (((rangesp[0] >> 24) & 0x3) != 1)
++ continue; /* not IO space */
++ io_base = rangesp[3];
++ if (addr_size == 2)
++ io_base = (io_base << 32) | rangesp[4];
++ }
++ if (io_base != 0) {
++ *physport = io_base + reg->address;
++ if (default_speed && spd)
++ *default_speed = *spd;
++ }
++ of_node_put(pci);
++ next_port:
++ of_node_put(isa);
++ }
++
++ DBG(" <- generic_find_legacy_serial_port()\n");
++}
++
++static struct platform_device serial_device = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM,
++ .dev = {
++ .platform_data = serial_ports,
++ },
++};
++
++static int __init serial_dev_init(void)
++{
++ return platform_device_register(&serial_device);
++}
++arch_initcall(serial_dev_init);
++
++#endif /* CONFIG_PPC_ISERIES */
++
++int check_legacy_ioport(unsigned long base_port)
++{
++ if (ppc_md.check_legacy_ioport == NULL)
++ return 0;
++ return ppc_md.check_legacy_ioport(base_port);
++}
++EXPORT_SYMBOL(check_legacy_ioport);
++
++#ifdef CONFIG_XMON
++static int __init early_xmon(char *p)
++{
++ /* ensure xmon is enabled */
++ if (p) {
++ if (strncmp(p, "on", 2) == 0)
++ xmon_init(1);
++ if (strncmp(p, "off", 3) == 0)
++ xmon_init(0);
++ if (strncmp(p, "early", 5) != 0)
++ return 0;
++ }
++ xmon_init(1);
++ debugger(NULL);
++
++ return 0;
++}
++early_param("xmon", early_xmon);
++#endif
++
++void cpu_die(void)
++{
++ if (ppc_md.cpu_die)
++ ppc_md.cpu_die();
++}
+diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/signal_32.c
+@@ -0,0 +1,1269 @@
++/*
++ * Signal handling for 32bit PPC and 32bit tasks on 64bit PPC
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ * Copyright (C) 2001 IBM
++ * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
++ * Copyright (C) 1997 David S. Miller (davem at caip.rutgers.edu)
++ *
++ * Derived from "arch/i386/kernel/signal.c"
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
++ *
++ * 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/sched.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/errno.h>
++#include <linux/elf.h>
++#ifdef CONFIG_PPC64
++#include <linux/syscalls.h>
++#include <linux/compat.h>
++#include <linux/ptrace.h>
++#else
++#include <linux/wait.h>
++#include <linux/ptrace.h>
++#include <linux/unistd.h>
++#include <linux/stddef.h>
++#include <linux/tty.h>
++#include <linux/binfmts.h>
++#include <linux/suspend.h>
++#endif
++
++#include <asm/uaccess.h>
++#include <asm/cacheflush.h>
++#ifdef CONFIG_PPC64
++#include <asm/ppc32.h>
++#include <asm/ppcdebug.h>
++#include <asm/unistd.h>
++#include <asm/vdso.h>
++#else
++#include <asm/ucontext.h>
++#include <asm/pgtable.h>
++#endif
++
++#undef DEBUG_SIG
++
++#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
++
++#ifdef CONFIG_PPC64
++#define do_signal do_signal32
++#define sys_sigsuspend compat_sys_sigsuspend
++#define sys_rt_sigsuspend compat_sys_rt_sigsuspend
++#define sys_rt_sigreturn compat_sys_rt_sigreturn
++#define sys_sigaction compat_sys_sigaction
++#define sys_swapcontext compat_sys_swapcontext
++#define sys_sigreturn compat_sys_sigreturn
++
++#define old_sigaction old_sigaction32
++#define sigcontext sigcontext32
++#define mcontext mcontext32
++#define ucontext ucontext32
++
++/*
++ * Returning 0 means we return to userspace via
++ * ret_from_except and thus restore all user
++ * registers from *regs. This is what we need
++ * to do when a signal has been delivered.
++ */
++#define sigreturn_exit(regs) return 0
++
++#define GP_REGS_SIZE min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32))
++#undef __SIGNAL_FRAMESIZE
++#define __SIGNAL_FRAMESIZE __SIGNAL_FRAMESIZE32
++#undef ELF_NVRREG
++#define ELF_NVRREG ELF_NVRREG32
++
++/*
++ * Functions for flipping sigsets (thanks to brain dead generic
++ * implementation that makes things simple for little endian only)
++ */
++static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
++{
++ compat_sigset_t cset;
++
++ switch (_NSIG_WORDS) {
++ case 4: cset.sig[5] = set->sig[3] & 0xffffffffull;
++ cset.sig[7] = set->sig[3] >> 32;
++ case 3: cset.sig[4] = set->sig[2] & 0xffffffffull;
++ cset.sig[5] = set->sig[2] >> 32;
++ case 2: cset.sig[2] = set->sig[1] & 0xffffffffull;
++ cset.sig[3] = set->sig[1] >> 32;
++ case 1: cset.sig[0] = set->sig[0] & 0xffffffffull;
++ cset.sig[1] = set->sig[0] >> 32;
++ }
++ return copy_to_user(uset, &cset, sizeof(*uset));
++}
++
++static inline int get_sigset_t(sigset_t *set,
++ const compat_sigset_t __user *uset)
++{
++ compat_sigset_t s32;
++
++ if (copy_from_user(&s32, uset, sizeof(*uset)))
++ return -EFAULT;
++
++ /*
++ * Swap the 2 words of the 64-bit sigset_t (they are stored
++ * in the "wrong" endian in 32-bit user storage).
++ */
++ switch (_NSIG_WORDS) {
++ case 4: set->sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
++ case 3: set->sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
++ case 2: set->sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
++ case 1: set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
++ }
++ return 0;
++}
++
++static inline int get_old_sigaction(struct k_sigaction *new_ka,
++ struct old_sigaction __user *act)
++{
++ compat_old_sigset_t mask;
++ compat_uptr_t handler, restorer;
++
++ if (get_user(handler, &act->sa_handler) ||
++ __get_user(restorer, &act->sa_restorer) ||
++ __get_user(new_ka->sa.sa_flags, &act->sa_flags) ||
++ __get_user(mask, &act->sa_mask))
++ return -EFAULT;
++ new_ka->sa.sa_handler = compat_ptr(handler);
++ new_ka->sa.sa_restorer = compat_ptr(restorer);
++ siginitset(&new_ka->sa.sa_mask, mask);
++ return 0;
++}
++
++static inline compat_uptr_t to_user_ptr(void *kp)
++{
++ return (compat_uptr_t)(u64)kp;
++}
++
++#define from_user_ptr(p) compat_ptr(p)
++
++static inline int save_general_regs(struct pt_regs *regs,
++ struct mcontext __user *frame)
++{
++ elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
++ int i;
++
++ for (i = 0; i <= PT_RESULT; i ++)
++ if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i]))
++ return -EFAULT;
++ return 0;
++}
++
++static inline int restore_general_regs(struct pt_regs *regs,
++ struct mcontext __user *sr)
++{
++ elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
++ int i;
++
++ for (i = 0; i <= PT_RESULT; i++) {
++ if ((i == PT_MSR) || (i == PT_SOFTE))
++ continue;
++ if (__get_user(gregs[i], &sr->mc_gregs[i]))
++ return -EFAULT;
++ }
++ return 0;
++}
++
++#else /* CONFIG_PPC64 */
++
++extern void sigreturn_exit(struct pt_regs *);
++
++#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
++
++static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set)
++{
++ return copy_to_user(uset, set, sizeof(*uset));
++}
++
++static inline int get_sigset_t(sigset_t *set, const sigset_t __user *uset)
++{
++ return copy_from_user(set, uset, sizeof(*uset));
++}
++
++static inline int get_old_sigaction(struct k_sigaction *new_ka,
++ struct old_sigaction __user *act)
++{
++ old_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_restorer, &act->sa_restorer))
++ return -EFAULT;
++ __get_user(new_ka->sa.sa_flags, &act->sa_flags);
++ __get_user(mask, &act->sa_mask);
++ siginitset(&new_ka->sa.sa_mask, mask);
++ return 0;
++}
++
++#define to_user_ptr(p) (p)
++#define from_user_ptr(p) (p)
++
++static inline int save_general_regs(struct pt_regs *regs,
++ struct mcontext __user *frame)
++{
++ return __copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE);
++}
++
++static inline int restore_general_regs(struct pt_regs *regs,
++ struct mcontext __user *sr)
++{
++ /* copy up to but not including MSR */
++ if (__copy_from_user(regs, &sr->mc_gregs,
++ PT_MSR * sizeof(elf_greg_t)))
++ return -EFAULT;
++ /* copy from orig_r3 (the word after the MSR) up to the end */
++ if (__copy_from_user(®s->orig_gpr3, &sr->mc_gregs[PT_ORIG_R3],
++ GP_REGS_SIZE - PT_ORIG_R3 * sizeof(elf_greg_t)))
++ return -EFAULT;
++ return 0;
++}
++
++#endif /* CONFIG_PPC64 */
++
++int do_signal(sigset_t *oldset, struct pt_regs *regs);
++
++/*
++ * Atomically swap in the new signal mask, and wait for a signal.
++ */
++long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
++ struct pt_regs *regs)
++{
++ sigset_t saveset;
++
++ mask &= _BLOCKABLE;
++ spin_lock_irq(¤t->sighand->siglock);
++ saveset = current->blocked;
++ siginitset(¤t->blocked, mask);
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++
++ regs->result = -EINTR;
++ regs->gpr[3] = EINTR;
++ regs->ccr |= 0x10000000;
++ while (1) {
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ if (do_signal(&saveset, regs))
++ sigreturn_exit(regs);
++ }
++}
++
++long sys_rt_sigsuspend(
++#ifdef CONFIG_PPC64
++ compat_sigset_t __user *unewset,
++#else
++ sigset_t __user *unewset,
++#endif
++ size_t sigsetsize, int p3, int p4,
++ int p6, int p7, struct pt_regs *regs)
++{
++ sigset_t saveset, newset;
++
++ /* XXX: Don't preclude handling different sized sigset_t's. */
++ if (sigsetsize != sizeof(sigset_t))
++ return -EINVAL;
++
++ if (get_sigset_t(&newset, unewset))
++ return -EFAULT;
++ sigdelsetmask(&newset, ~_BLOCKABLE);
++
++ spin_lock_irq(¤t->sighand->siglock);
++ saveset = current->blocked;
++ current->blocked = newset;
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++
++ regs->result = -EINTR;
++ regs->gpr[3] = EINTR;
++ regs->ccr |= 0x10000000;
++ while (1) {
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ if (do_signal(&saveset, regs))
++ sigreturn_exit(regs);
++ }
++}
++
++#ifdef CONFIG_PPC32
++long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
++ int r6, int r7, int r8, struct pt_regs *regs)
++{
++ return do_sigaltstack(uss, uoss, regs->gpr[1]);
++}
++#endif
++
++long sys_sigaction(int sig, struct old_sigaction __user *act,
++ struct old_sigaction __user *oact)
++{
++ struct k_sigaction new_ka, old_ka;
++ int ret;
++
++#ifdef CONFIG_PPC64
++ if (sig < 0)
++ sig = -sig;
++#endif
++
++ if (act) {
++ if (get_old_sigaction(&new_ka, act))
++ return -EFAULT;
++ }
++
++ 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(to_user_ptr(old_ka.sa.sa_handler),
++ &oact->sa_handler) ||
++ __put_user(to_user_ptr(old_ka.sa.sa_restorer),
++ &oact->sa_restorer) ||
++ __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
++ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
++ return -EFAULT;
++ }
++
++ return ret;
++}
++
++/*
++ * When we have signals to deliver, we set up on the
++ * user stack, going down from the original stack pointer:
++ * a sigregs struct
++ * a sigcontext struct
++ * a gap of __SIGNAL_FRAMESIZE bytes
++ *
++ * Each of these things must be a multiple of 16 bytes in size.
++ *
++ */
++struct sigregs {
++ struct mcontext mctx; /* all the register values */
++ /*
++ * Programs using the rs6000/xcoff abi can save up to 19 gp
++ * regs and 18 fp regs below sp before decrementing it.
++ */
++ int abigap[56];
++};
++
++/* We use the mc_pad field for the signal return trampoline. */
++#define tramp mc_pad
++
++/*
++ * When we have rt signals to deliver, we set up on the
++ * user stack, going down from the original stack pointer:
++ * one rt_sigframe struct (siginfo + ucontext + ABI gap)
++ * a gap of __SIGNAL_FRAMESIZE+16 bytes
++ * (the +16 is to get the siginfo and ucontext in the same
++ * positions as in older kernels).
++ *
++ * Each of these things must be a multiple of 16 bytes in size.
++ *
++ */
++struct rt_sigframe {
++#ifdef CONFIG_PPC64
++ compat_siginfo_t info;
++#else
++ struct siginfo info;
++#endif
++ struct ucontext uc;
++ /*
++ * Programs using the rs6000/xcoff abi can save up to 19 gp
++ * regs and 18 fp regs below sp before decrementing it.
++ */
++ int abigap[56];
++};
++
++/*
++ * Save the current user registers on the user stack.
++ * We only save the altivec/spe registers if the process has used
++ * altivec/spe instructions at some point.
++ */
++static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
++ int sigret)
++{
++#ifdef CONFIG_PPC32
++ CHECK_FULL_REGS(regs);
++#endif
++ /* Make sure floating point registers are stored in regs */
++ flush_fp_to_thread(current);
++
++ /* save general and floating-point registers */
++ if (save_general_regs(regs, frame) ||
++ __copy_to_user(&frame->mc_fregs, current->thread.fpr,
++ ELF_NFPREG * sizeof(double)))
++ return 1;
++
++ current->thread.fpscr.val = 0; /* turn off all fp exceptions */
++
++#ifdef CONFIG_ALTIVEC
++ /* save altivec registers */
++ if (current->thread.used_vr) {
++ flush_altivec_to_thread(current);
++ if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
++ ELF_NVRREG * sizeof(vector128)))
++ return 1;
++ /* set MSR_VEC in the saved MSR value to indicate that
++ frame->mc_vregs contains valid data */
++ if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR]))
++ return 1;
++ }
++ /* else assert((regs->msr & MSR_VEC) == 0) */
++
++ /* We always copy to/from vrsave, it's 0 if we don't have or don't
++ * use altivec. Since VSCR only contains 32 bits saved in the least
++ * significant bits of a vector, we "cheat" and stuff VRSAVE in the
++ * most significant bits of that same vector. --BenH
++ */
++ if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))
++ return 1;
++#endif /* CONFIG_ALTIVEC */
++
++#ifdef CONFIG_SPE
++ /* save spe registers */
++ if (current->thread.used_spe) {
++ flush_spe_to_thread(current);
++ if (__copy_to_user(&frame->mc_vregs, current->thread.evr,
++ ELF_NEVRREG * sizeof(u32)))
++ return 1;
++ /* set MSR_SPE in the saved MSR value to indicate that
++ frame->mc_vregs contains valid data */
++ if (__put_user(regs->msr | MSR_SPE, &frame->mc_gregs[PT_MSR]))
++ return 1;
++ }
++ /* else assert((regs->msr & MSR_SPE) == 0) */
++
++ /* We always copy to/from spefscr */
++ if (__put_user(current->thread.spefscr, (u32 __user *)&frame->mc_vregs + ELF_NEVRREG))
++ return 1;
++#endif /* CONFIG_SPE */
++
++ if (sigret) {
++ /* Set up the sigreturn trampoline: li r0,sigret; sc */
++ if (__put_user(0x38000000UL + sigret, &frame->tramp[0])
++ || __put_user(0x44000002UL, &frame->tramp[1]))
++ return 1;
++ flush_icache_range((unsigned long) &frame->tramp[0],
++ (unsigned long) &frame->tramp[2]);
++ }
++
++ return 0;
++}
++
++/*
++ * Restore the current user register values from the user stack,
++ * (except for MSR).
++ */
++static long restore_user_regs(struct pt_regs *regs,
++ struct mcontext __user *sr, int sig)
++{
++ long err;
++ unsigned int save_r2 = 0;
++#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
++ unsigned long msr;
++#endif
++
++ /*
++ * restore general registers but not including MSR or SOFTE. Also
++ * take care of keeping r2 (TLS) intact if not a signal
++ */
++ if (!sig)
++ save_r2 = (unsigned int)regs->gpr[2];
++ err = restore_general_regs(regs, sr);
++ if (!sig)
++ regs->gpr[2] = (unsigned long) save_r2;
++ if (err)
++ return 1;
++
++ /* force the process to reload the FP registers from
++ current->thread when it next does FP instructions */
++ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
++ if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
++ sizeof(sr->mc_fregs)))
++ return 1;
++
++#ifdef CONFIG_ALTIVEC
++ /* force the process to reload the altivec registers from
++ current->thread when it next does altivec instructions */
++ regs->msr &= ~MSR_VEC;
++ if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
++ /* restore altivec registers from the stack */
++ if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
++ sizeof(sr->mc_vregs)))
++ return 1;
++ } else if (current->thread.used_vr)
++ memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
++
++ /* Always get VRSAVE back */
++ if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
++ return 1;
++#endif /* CONFIG_ALTIVEC */
++
++#ifdef CONFIG_SPE
++ /* force the process to reload the spe registers from
++ current->thread when it next does spe instructions */
++ regs->msr &= ~MSR_SPE;
++ if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
++ /* restore spe registers from the stack */
++ if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
++ ELF_NEVRREG * sizeof(u32)))
++ return 1;
++ } else if (current->thread.used_spe)
++ memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
++
++ /* Always get SPEFSCR back */
++ if (__get_user(current->thread.spefscr, (u32 __user *)&sr->mc_vregs + ELF_NEVRREG))
++ return 1;
++#endif /* CONFIG_SPE */
++
++#ifndef CONFIG_SMP
++ preempt_disable();
++ if (last_task_used_math == current)
++ last_task_used_math = NULL;
++ if (last_task_used_altivec == current)
++ last_task_used_altivec = NULL;
++#ifdef CONFIG_SPE
++ if (last_task_used_spe == current)
++ last_task_used_spe = NULL;
++#endif
++ preempt_enable();
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_PPC64
++long compat_sys_rt_sigaction(int sig, const struct sigaction32 __user *act,
++ struct sigaction32 __user *oact, size_t sigsetsize)
++{
++ struct k_sigaction new_ka, old_ka;
++ int ret;
++
++ /* XXX: Don't preclude handling different sized sigset_t's. */
++ if (sigsetsize != sizeof(compat_sigset_t))
++ return -EINVAL;
++
++ if (act) {
++ compat_uptr_t handler;
++
++ ret = get_user(handler, &act->sa_handler);
++ new_ka.sa.sa_handler = compat_ptr(handler);
++ ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask);
++ ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
++ if (ret)
++ return -EFAULT;
++ }
++
++ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
++ if (!ret && oact) {
++ ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
++ ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask);
++ ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
++ }
++ return ret;
++}
++
++/*
++ * Note: it is necessary to treat how as an unsigned int, with the
++ * corresponding cast to a signed int to insure that the proper
++ * conversion (sign extension) between the register representation
++ * of a signed int (msr in 32-bit mode) and the register representation
++ * of a signed int (msr in 64-bit mode) is performed.
++ */
++long compat_sys_rt_sigprocmask(u32 how, compat_sigset_t __user *set,
++ compat_sigset_t __user *oset, size_t sigsetsize)
++{
++ sigset_t s;
++ sigset_t __user *up;
++ int ret;
++ mm_segment_t old_fs = get_fs();
++
++ if (set) {
++ if (get_sigset_t(&s, set))
++ return -EFAULT;
++ }
++
++ set_fs(KERNEL_DS);
++ /* This is valid because of the set_fs() */
++ up = (sigset_t __user *) &s;
++ ret = sys_rt_sigprocmask((int)how, set ? up : NULL, oset ? up : NULL,
++ sigsetsize);
++ set_fs(old_fs);
++ if (ret)
++ return ret;
++ if (oset) {
++ if (put_sigset_t(oset, &s))
++ return -EFAULT;
++ }
++ return 0;
++}
++
++long compat_sys_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
++{
++ sigset_t s;
++ int ret;
++ mm_segment_t old_fs = get_fs();
++
++ set_fs(KERNEL_DS);
++ /* The __user pointer cast is valid because of the set_fs() */
++ ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
++ set_fs(old_fs);
++ if (!ret) {
++ if (put_sigset_t(set, &s))
++ return -EFAULT;
++ }
++ return ret;
++}
++
++
++int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
++{
++ int err;
++
++ if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
++ return -EFAULT;
++
++ /* If you change siginfo_t structure, please be sure
++ * this code is fixed accordingly.
++ * It should never copy any pad contained in the structure
++ * to avoid security leaks, but must copy the generic
++ * 3 ints plus the relevant union member.
++ * This routine must convert siginfo from 64bit to 32bit as well
++ * at the same time.
++ */
++ err = __put_user(s->si_signo, &d->si_signo);
++ err |= __put_user(s->si_errno, &d->si_errno);
++ err |= __put_user((short)s->si_code, &d->si_code);
++ if (s->si_code < 0)
++ err |= __copy_to_user(&d->_sifields._pad, &s->_sifields._pad,
++ SI_PAD_SIZE32);
++ else switch(s->si_code >> 16) {
++ case __SI_CHLD >> 16:
++ err |= __put_user(s->si_pid, &d->si_pid);
++ err |= __put_user(s->si_uid, &d->si_uid);
++ err |= __put_user(s->si_utime, &d->si_utime);
++ err |= __put_user(s->si_stime, &d->si_stime);
++ err |= __put_user(s->si_status, &d->si_status);
++ break;
++ case __SI_FAULT >> 16:
++ err |= __put_user((unsigned int)(unsigned long)s->si_addr,
++ &d->si_addr);
++ break;
++ case __SI_POLL >> 16:
++ err |= __put_user(s->si_band, &d->si_band);
++ err |= __put_user(s->si_fd, &d->si_fd);
++ break;
++ case __SI_TIMER >> 16:
++ err |= __put_user(s->si_tid, &d->si_tid);
++ err |= __put_user(s->si_overrun, &d->si_overrun);
++ err |= __put_user(s->si_int, &d->si_int);
++ break;
++ case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
++ case __SI_MESGQ >> 16:
++ err |= __put_user(s->si_int, &d->si_int);
++ /* fallthrough */
++ case __SI_KILL >> 16:
++ default:
++ err |= __put_user(s->si_pid, &d->si_pid);
++ err |= __put_user(s->si_uid, &d->si_uid);
++ break;
++ }
++ return err;
++}
++
++#define copy_siginfo_to_user copy_siginfo_to_user32
++
++/*
++ * Note: it is necessary to treat pid and sig as unsigned ints, with the
++ * corresponding cast to a signed int to insure that the proper conversion
++ * (sign extension) between the register representation of a signed int
++ * (msr in 32-bit mode) and the register representation of a signed int
++ * (msr in 64-bit mode) is performed.
++ */
++long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo)
++{
++ siginfo_t info;
++ int ret;
++ mm_segment_t old_fs = get_fs();
++
++ if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
++ copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
++ return -EFAULT;
++ set_fs (KERNEL_DS);
++ /* The __user pointer cast is valid becasuse of the set_fs() */
++ ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info);
++ set_fs (old_fs);
++ return ret;
++}
++/*
++ * Start Alternate signal stack support
++ *
++ * System Calls
++ * sigaltatck compat_sys_sigaltstack
++ */
++
++int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
++ int r6, int r7, int r8, struct pt_regs *regs)
++{
++ stack_32_t __user * newstack = (stack_32_t __user *)(long) __new;
++ stack_32_t __user * oldstack = (stack_32_t __user *)(long) __old;
++ stack_t uss, uoss;
++ int ret;
++ mm_segment_t old_fs;
++ unsigned long sp;
++ compat_uptr_t ss_sp;
++
++ /*
++ * set sp to the user stack on entry to the system call
++ * the system call router sets R9 to the saved registers
++ */
++ sp = regs->gpr[1];
++
++ /* Put new stack info in local 64 bit stack struct */
++ if (newstack) {
++ if (get_user(ss_sp, &newstack->ss_sp) ||
++ __get_user(uss.ss_flags, &newstack->ss_flags) ||
++ __get_user(uss.ss_size, &newstack->ss_size))
++ return -EFAULT;
++ uss.ss_sp = compat_ptr(ss_sp);
++ }
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ /* The __user pointer casts are valid because of the set_fs() */
++ ret = do_sigaltstack(
++ newstack ? (stack_t __user *) &uss : NULL,
++ oldstack ? (stack_t __user *) &uoss : NULL,
++ sp);
++ set_fs(old_fs);
++ /* Copy the stack information to the user output buffer */
++ if (!ret && oldstack &&
++ (put_user((long)uoss.ss_sp, &oldstack->ss_sp) ||
++ __put_user(uoss.ss_flags, &oldstack->ss_flags) ||
++ __put_user(uoss.ss_size, &oldstack->ss_size)))
++ return -EFAULT;
++ return ret;
++}
++#endif /* CONFIG_PPC64 */
++
++
++/*
++ * Restore the user process's signal mask
++ */
++#ifdef CONFIG_PPC64
++extern void restore_sigmask(sigset_t *set);
++#else /* CONFIG_PPC64 */
++static void restore_sigmask(sigset_t *set)
++{
++ sigdelsetmask(set, ~_BLOCKABLE);
++ spin_lock_irq(¤t->sighand->siglock);
++ current->blocked = *set;
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++}
++#endif
++
++/*
++ * Set up a signal frame for a "real-time" signal handler
++ * (one which gets siginfo).
++ */
++static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
++ siginfo_t *info, sigset_t *oldset,
++ struct pt_regs *regs, unsigned long newsp)
++{
++ struct rt_sigframe __user *rt_sf;
++ struct mcontext __user *frame;
++ unsigned long origsp = newsp;
++
++ /* Set up Signal Frame */
++ /* Put a Real Time Context onto stack */
++ newsp -= sizeof(*rt_sf);
++ rt_sf = (struct rt_sigframe __user *)newsp;
++
++ /* create a stack frame for the caller of the handler */
++ newsp -= __SIGNAL_FRAMESIZE + 16;
++
++ if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
++ goto badframe;
++
++ /* Put the siginfo & fill in most of the ucontext */
++ if (copy_siginfo_to_user(&rt_sf->info, info)
++ || __put_user(0, &rt_sf->uc.uc_flags)
++ || __put_user(0, &rt_sf->uc.uc_link)
++ || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
++ || __put_user(sas_ss_flags(regs->gpr[1]),
++ &rt_sf->uc.uc_stack.ss_flags)
++ || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
++ || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext),
++ &rt_sf->uc.uc_regs)
++ || put_sigset_t(&rt_sf->uc.uc_sigmask, oldset))
++ goto badframe;
++
++ /* Save user registers on the stack */
++ frame = &rt_sf->uc.uc_mcontext;
++#ifdef CONFIG_PPC64
++ if (vdso32_rt_sigtramp && current->thread.vdso_base) {
++ if (save_user_regs(regs, frame, 0))
++ goto badframe;
++ regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
++ } else
++#endif
++ {
++ if (save_user_regs(regs, frame, __NR_rt_sigreturn))
++ goto badframe;
++ regs->link = (unsigned long) frame->tramp;
++ }
++ if (put_user(regs->gpr[1], (u32 __user *)newsp))
++ goto badframe;
++ regs->gpr[1] = newsp;
++ regs->gpr[3] = sig;
++ regs->gpr[4] = (unsigned long) &rt_sf->info;
++ regs->gpr[5] = (unsigned long) &rt_sf->uc;
++ regs->gpr[6] = (unsigned long) rt_sf;
++ regs->nip = (unsigned long) ka->sa.sa_handler;
++ regs->trap = 0;
++#ifdef CONFIG_PPC64
++ regs->result = 0;
++
++ if (test_thread_flag(TIF_SINGLESTEP))
++ ptrace_notify(SIGTRAP);
++#endif
++ return 1;
++
++badframe:
++#ifdef DEBUG_SIG
++ printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
++ regs, frame, newsp);
++#endif
++ force_sigsegv(sig, current);
++ return 0;
++}
++
++static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
++{
++ sigset_t set;
++ struct mcontext __user *mcp;
++
++ if (get_sigset_t(&set, &ucp->uc_sigmask))
++ return -EFAULT;
++#ifdef CONFIG_PPC64
++ {
++ u32 cmcp;
++
++ if (__get_user(cmcp, &ucp->uc_regs))
++ return -EFAULT;
++ mcp = (struct mcontext __user *)(u64)cmcp;
++ }
++#else
++ if (__get_user(mcp, &ucp->uc_regs))
++ return -EFAULT;
++#endif
++ restore_sigmask(&set);
++ if (restore_user_regs(regs, mcp, sig))
++ return -EFAULT;
++
++ return 0;
++}
++
++long sys_swapcontext(struct ucontext __user *old_ctx,
++ struct ucontext __user *new_ctx,
++ int ctx_size, int r6, int r7, int r8, struct pt_regs *regs)
++{
++ unsigned char tmp;
++
++ /* Context size is for future use. Right now, we only make sure
++ * we are passed something we understand
++ */
++ if (ctx_size < sizeof(struct ucontext))
++ return -EINVAL;
++
++ if (old_ctx != NULL) {
++ if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
++ || save_user_regs(regs, &old_ctx->uc_mcontext, 0)
++ || put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked)
++ || __put_user(to_user_ptr(&old_ctx->uc_mcontext),
++ &old_ctx->uc_regs))
++ return -EFAULT;
++ }
++ if (new_ctx == NULL)
++ return 0;
++ if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
++ || __get_user(tmp, (u8 __user *) new_ctx)
++ || __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
++ return -EFAULT;
++
++ /*
++ * If we get a fault copying the context into the kernel's
++ * image of the user's registers, we can't just return -EFAULT
++ * because the user's registers will be corrupted. For instance
++ * the NIP value may have been updated but not some of the
++ * other registers. Given that we have done the access_ok
++ * and successfully read the first and last bytes of the region
++ * above, this should only happen in an out-of-memory situation
++ * or if another thread unmaps the region containing the context.
++ * We kill the task with a SIGSEGV in this situation.
++ */
++ if (do_setcontext(new_ctx, regs, 0))
++ do_exit(SIGSEGV);
++ sigreturn_exit(regs);
++ /* doesn't actually return back to here */
++ return 0;
++}
++
++long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
++ struct pt_regs *regs)
++{
++ struct rt_sigframe __user *rt_sf;
++
++ /* Always make any pending restarted system calls return -EINTR */
++ current_thread_info()->restart_block.fn = do_no_restart_syscall;
++
++ rt_sf = (struct rt_sigframe __user *)
++ (regs->gpr[1] + __SIGNAL_FRAMESIZE + 16);
++ if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf)))
++ goto bad;
++ if (do_setcontext(&rt_sf->uc, regs, 1))
++ goto bad;
++
++ /*
++ * It's not clear whether or why it is desirable to save the
++ * sigaltstack setting on signal delivery and restore it on
++ * signal return. But other architectures do this and we have
++ * always done it up until now so it is probably better not to
++ * change it. -- paulus
++ */
++#ifdef CONFIG_PPC64
++ /*
++ * We use the compat_sys_ version that does the 32/64 bits conversion
++ * and takes userland pointer directly. What about error checking ?
++ * nobody does any...
++ */
++ compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs);
++ return (int)regs->result;
++#else
++ do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]);
++ sigreturn_exit(regs); /* doesn't return here */
++ return 0;
++#endif
++
++ bad:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++#ifdef CONFIG_PPC32
++int sys_debug_setcontext(struct ucontext __user *ctx,
++ int ndbg, struct sig_dbg_op __user *dbg,
++ int r6, int r7, int r8,
++ struct pt_regs *regs)
++{
++ struct sig_dbg_op op;
++ int i;
++ unsigned long new_msr = regs->msr;
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ unsigned long new_dbcr0 = current->thread.dbcr0;
++#endif
++
++ for (i=0; i<ndbg; i++) {
++ if (__copy_from_user(&op, dbg, sizeof(op)))
++ return -EFAULT;
++ switch (op.dbg_type) {
++ case SIG_DBG_SINGLE_STEPPING:
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ if (op.dbg_value) {
++ new_msr |= MSR_DE;
++ new_dbcr0 |= (DBCR0_IDM | DBCR0_IC);
++ } else {
++ new_msr &= ~MSR_DE;
++ new_dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
++ }
++#else
++ if (op.dbg_value)
++ new_msr |= MSR_SE;
++ else
++ new_msr &= ~MSR_SE;
++#endif
++ break;
++ case SIG_DBG_BRANCH_TRACING:
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ return -EINVAL;
++#else
++ if (op.dbg_value)
++ new_msr |= MSR_BE;
++ else
++ new_msr &= ~MSR_BE;
++#endif
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ }
++
++ /* We wait until here to actually install the values in the
++ registers so if we fail in the above loop, it will not
++ affect the contents of these registers. After this point,
++ failure is a problem, anyway, and it's very unlikely unless
++ the user is really doing something wrong. */
++ regs->msr = new_msr;
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ current->thread.dbcr0 = new_dbcr0;
++#endif
++
++ /*
++ * If we get a fault copying the context into the kernel's
++ * image of the user's registers, we can't just return -EFAULT
++ * because the user's registers will be corrupted. For instance
++ * the NIP value may have been updated but not some of the
++ * other registers. Given that we have done the access_ok
++ * and successfully read the first and last bytes of the region
++ * above, this should only happen in an out-of-memory situation
++ * or if another thread unmaps the region containing the context.
++ * We kill the task with a SIGSEGV in this situation.
++ */
++ if (do_setcontext(ctx, regs, 1)) {
++ force_sig(SIGSEGV, current);
++ goto out;
++ }
++
++ /*
++ * It's not clear whether or why it is desirable to save the
++ * sigaltstack setting on signal delivery and restore it on
++ * signal return. But other architectures do this and we have
++ * always done it up until now so it is probably better not to
++ * change it. -- paulus
++ */
++ do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]);
++
++ sigreturn_exit(regs);
++ /* doesn't actually return back to here */
++
++ out:
++ return 0;
++}
++#endif
++
++/*
++ * OK, we're invoking a handler
++ */
++static int handle_signal(unsigned long sig, struct k_sigaction *ka,
++ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
++ unsigned long newsp)
++{
++ struct sigcontext __user *sc;
++ struct sigregs __user *frame;
++ unsigned long origsp = newsp;
++
++ /* Set up Signal Frame */
++ newsp -= sizeof(struct sigregs);
++ frame = (struct sigregs __user *) newsp;
++
++ /* Put a sigcontext on the stack */
++ newsp -= sizeof(*sc);
++ sc = (struct sigcontext __user *) newsp;
++
++ /* create a stack frame for the caller of the handler */
++ newsp -= __SIGNAL_FRAMESIZE;
++
++ if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
++ goto badframe;
++
++#if _NSIG != 64
++#error "Please adjust handle_signal()"
++#endif
++ if (__put_user(to_user_ptr(ka->sa.sa_handler), &sc->handler)
++ || __put_user(oldset->sig[0], &sc->oldmask)
++#ifdef CONFIG_PPC64
++ || __put_user((oldset->sig[0] >> 32), &sc->_unused[3])
++#else
++ || __put_user(oldset->sig[1], &sc->_unused[3])
++#endif
++ || __put_user(to_user_ptr(frame), &sc->regs)
++ || __put_user(sig, &sc->signal))
++ goto badframe;
++
++#ifdef CONFIG_PPC64
++ if (vdso32_sigtramp && current->thread.vdso_base) {
++ if (save_user_regs(regs, &frame->mctx, 0))
++ goto badframe;
++ regs->link = current->thread.vdso_base + vdso32_sigtramp;
++ } else
++#endif
++ {
++ if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
++ goto badframe;
++ regs->link = (unsigned long) frame->mctx.tramp;
++ }
++
++ if (put_user(regs->gpr[1], (u32 __user *)newsp))
++ goto badframe;
++ regs->gpr[1] = newsp;
++ regs->gpr[3] = sig;
++ regs->gpr[4] = (unsigned long) sc;
++ regs->nip = (unsigned long) ka->sa.sa_handler;
++ regs->trap = 0;
++#ifdef CONFIG_PPC64
++ regs->result = 0;
++
++ if (test_thread_flag(TIF_SINGLESTEP))
++ ptrace_notify(SIGTRAP);
++#endif
++
++ return 1;
++
++badframe:
++#ifdef DEBUG_SIG
++ printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
++ regs, frame, newsp);
++#endif
++ force_sigsegv(sig, current);
++ return 0;
++}
++
++/*
++ * Do a signal return; undo the signal stack.
++ */
++long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
++ struct pt_regs *regs)
++{
++ struct sigcontext __user *sc;
++ struct sigcontext sigctx;
++ struct mcontext __user *sr;
++ sigset_t set;
++
++ /* Always make any pending restarted system calls return -EINTR */
++ current_thread_info()->restart_block.fn = do_no_restart_syscall;
++
++ sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
++ if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
++ goto badframe;
++
++#ifdef CONFIG_PPC64
++ /*
++ * Note that PPC32 puts the upper 32 bits of the sigmask in the
++ * unused part of the signal stackframe
++ */
++ set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3]) << 32);
++#else
++ set.sig[0] = sigctx.oldmask;
++ set.sig[1] = sigctx._unused[3];
++#endif
++ restore_sigmask(&set);
++
++ sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
++ if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
++ || restore_user_regs(regs, sr, 1))
++ goto badframe;
++
++#ifdef CONFIG_PPC64
++ return (int)regs->result;
++#else
++ sigreturn_exit(regs); /* doesn't return */
++ return 0;
++#endif
++
++badframe:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++/*
++ * Note that 'init' is a special process: it doesn't get signals it doesn't
++ * want to handle. Thus you cannot kill init even with a SIGKILL even by
++ * mistake.
++ */
++int do_signal(sigset_t *oldset, struct pt_regs *regs)
++{
++ siginfo_t info;
++ struct k_sigaction ka;
++ unsigned int frame, newsp;
++ int signr, ret;
++
++#ifdef CONFIG_PPC32
++ if (try_to_freeze()) {
++ signr = 0;
++ if (!signal_pending(current))
++ goto no_signal;
++ }
++#endif
++
++ if (!oldset)
++ oldset = ¤t->blocked;
++
++ newsp = frame = 0;
++
++ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
++#ifdef CONFIG_PPC32
++no_signal:
++#endif
++ if (TRAP(regs) == 0x0C00 /* System Call! */
++ && regs->ccr & 0x10000000 /* error signalled */
++ && ((ret = regs->gpr[3]) == ERESTARTSYS
++ || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
++ || ret == ERESTART_RESTARTBLOCK)) {
++
++ if (signr > 0
++ && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
++ || (ret == ERESTARTSYS
++ && !(ka.sa.sa_flags & SA_RESTART)))) {
++ /* make the system call return an EINTR error */
++ regs->result = -EINTR;
++ regs->gpr[3] = EINTR;
++ /* note that the cr0.SO bit is already set */
++ } else {
++ regs->nip -= 4; /* Back up & retry system call */
++ regs->result = 0;
++ regs->trap = 0;
++ if (ret == ERESTART_RESTARTBLOCK)
++ regs->gpr[0] = __NR_restart_syscall;
++ else
++ regs->gpr[3] = regs->orig_gpr3;
++ }
++ }
++
++ if (signr == 0)
++ return 0; /* no signals delivered */
++
++ if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
++ && !on_sig_stack(regs->gpr[1]))
++ newsp = current->sas_ss_sp + current->sas_ss_size;
++ else
++ newsp = regs->gpr[1];
++ newsp &= ~0xfUL;
++
++#ifdef CONFIG_PPC64
++ /*
++ * Reenable the DABR before delivering the signal to
++ * user space. The DABR will have been cleared if it
++ * triggered inside the kernel.
++ */
++ if (current->thread.dabr)
++ set_dabr(current->thread.dabr);
++#endif
++
++ /* Whee! Actually deliver the signal. */
++ if (ka.sa.sa_flags & SA_SIGINFO)
++ ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
++ else
++ ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
++
++ if (ret) {
++ spin_lock_irq(¤t->sighand->siglock);
++ sigorsets(¤t->blocked, ¤t->blocked,
++ &ka.sa.sa_mask);
++ if (!(ka.sa.sa_flags & SA_NODEFER))
++ sigaddset(¤t->blocked, signr);
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++ }
++
++ return ret;
++}
+diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/sys_ppc32.c
+@@ -0,0 +1,1008 @@
++/*
++ * sys_ppc32.c: Conversion between 32bit and 64bit native syscalls.
++ *
++ * Copyright (C) 2001 IBM
++ * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
++ * Copyright (C) 1997 David S. Miller (davem at caip.rutgers.edu)
++ *
++ * These routines maintain argument size conversion between 32bit and 64bit
++ * environment.
++ *
++ * 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/fs.h>
++#include <linux/mm.h>
++#include <linux/file.h>
++#include <linux/signal.h>
++#include <linux/resource.h>
++#include <linux/times.h>
++#include <linux/utsname.h>
++#include <linux/timex.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/sem.h>
++#include <linux/msg.h>
++#include <linux/shm.h>
++#include <linux/poll.h>
++#include <linux/personality.h>
++#include <linux/stat.h>
++#include <linux/mman.h>
++#include <linux/in.h>
++#include <linux/syscalls.h>
++#include <linux/unistd.h>
++#include <linux/sysctl.h>
++#include <linux/binfmts.h>
++#include <linux/security.h>
++#include <linux/compat.h>
++#include <linux/ptrace.h>
++#include <linux/elf.h>
++
++#include <asm/ptrace.h>
++#include <asm/types.h>
++#include <asm/ipc.h>
++#include <asm/uaccess.h>
++#include <asm/unistd.h>
++#include <asm/semaphore.h>
++#include <asm/time.h>
++#include <asm/mmu_context.h>
++#include <asm/systemcfg.h>
++#include <asm/ppc-pci.h>
++
++/* readdir & getdents */
++#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
++#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
++
++struct old_linux_dirent32 {
++ u32 d_ino;
++ u32 d_offset;
++ unsigned short d_namlen;
++ char d_name[1];
++};
++
++struct readdir_callback32 {
++ struct old_linux_dirent32 __user * dirent;
++ int count;
++};
++
++static int fillonedir(void * __buf, const char * name, int namlen,
++ off_t offset, ino_t ino, unsigned int d_type)
++{
++ struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
++ struct old_linux_dirent32 __user * dirent;
++
++ if (buf->count)
++ return -EINVAL;
++ buf->count++;
++ dirent = buf->dirent;
++ put_user(ino, &dirent->d_ino);
++ put_user(offset, &dirent->d_offset);
++ put_user(namlen, &dirent->d_namlen);
++ copy_to_user(dirent->d_name, name, namlen);
++ put_user(0, dirent->d_name + namlen);
++ return 0;
++}
++
++asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 __user *dirent, unsigned int count)
++{
++ int error = -EBADF;
++ struct file * file;
++ struct readdir_callback32 buf;
++
++ file = fget(fd);
++ if (!file)
++ goto out;
++
++ buf.count = 0;
++ buf.dirent = dirent;
++
++ error = vfs_readdir(file, (filldir_t)fillonedir, &buf);
++ if (error < 0)
++ goto out_putf;
++ error = buf.count;
++
++out_putf:
++ fput(file);
++out:
++ return error;
++}
++
++asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
++ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
++ compat_uptr_t tvp_x)
++{
++ /* sign extend n */
++ return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
++}
++
++int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
++{
++ long err;
++
++ if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
++ !new_valid_dev(stat->rdev))
++ return -EOVERFLOW;
++
++ err = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
++ err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
++ err |= __put_user(stat->ino, &statbuf->st_ino);
++ err |= __put_user(stat->mode, &statbuf->st_mode);
++ err |= __put_user(stat->nlink, &statbuf->st_nlink);
++ err |= __put_user(stat->uid, &statbuf->st_uid);
++ err |= __put_user(stat->gid, &statbuf->st_gid);
++ err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
++ err |= __put_user(stat->size, &statbuf->st_size);
++ err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime);
++ err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
++ err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
++ err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
++ err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
++ err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
++ err |= __put_user(stat->blksize, &statbuf->st_blksize);
++ err |= __put_user(stat->blocks, &statbuf->st_blocks);
++ err |= __put_user(0, &statbuf->__unused4[0]);
++ err |= __put_user(0, &statbuf->__unused4[1]);
++
++ return err;
++}
++
++/* Note: it is necessary to treat option as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
++{
++ return sys_sysfs((int)option, arg1, arg2);
++}
++
++/* Handle adjtimex compatibility. */
++struct timex32 {
++ u32 modes;
++ s32 offset, freq, maxerror, esterror;
++ s32 status, constant, precision, tolerance;
++ struct compat_timeval time;
++ s32 tick;
++ s32 ppsfreq, jitter, shift, stabil;
++ s32 jitcnt, calcnt, errcnt, stbcnt;
++ s32 :32; s32 :32; s32 :32; s32 :32;
++ s32 :32; s32 :32; s32 :32; s32 :32;
++ s32 :32; s32 :32; s32 :32; s32 :32;
++};
++
++extern int do_adjtimex(struct timex *);
++extern void ppc_adjtimex(void);
++
++asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp)
++{
++ struct timex txc;
++ int ret;
++
++ memset(&txc, 0, sizeof(struct timex));
++
++ if(get_user(txc.modes, &utp->modes) ||
++ __get_user(txc.offset, &utp->offset) ||
++ __get_user(txc.freq, &utp->freq) ||
++ __get_user(txc.maxerror, &utp->maxerror) ||
++ __get_user(txc.esterror, &utp->esterror) ||
++ __get_user(txc.status, &utp->status) ||
++ __get_user(txc.constant, &utp->constant) ||
++ __get_user(txc.precision, &utp->precision) ||
++ __get_user(txc.tolerance, &utp->tolerance) ||
++ __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
++ __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
++ __get_user(txc.tick, &utp->tick) ||
++ __get_user(txc.ppsfreq, &utp->ppsfreq) ||
++ __get_user(txc.jitter, &utp->jitter) ||
++ __get_user(txc.shift, &utp->shift) ||
++ __get_user(txc.stabil, &utp->stabil) ||
++ __get_user(txc.jitcnt, &utp->jitcnt) ||
++ __get_user(txc.calcnt, &utp->calcnt) ||
++ __get_user(txc.errcnt, &utp->errcnt) ||
++ __get_user(txc.stbcnt, &utp->stbcnt))
++ return -EFAULT;
++
++ ret = do_adjtimex(&txc);
++
++ /* adjust the conversion of TB to time of day to track adjtimex */
++ ppc_adjtimex();
++
++ if(put_user(txc.modes, &utp->modes) ||
++ __put_user(txc.offset, &utp->offset) ||
++ __put_user(txc.freq, &utp->freq) ||
++ __put_user(txc.maxerror, &utp->maxerror) ||
++ __put_user(txc.esterror, &utp->esterror) ||
++ __put_user(txc.status, &utp->status) ||
++ __put_user(txc.constant, &utp->constant) ||
++ __put_user(txc.precision, &utp->precision) ||
++ __put_user(txc.tolerance, &utp->tolerance) ||
++ __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
++ __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
++ __put_user(txc.tick, &utp->tick) ||
++ __put_user(txc.ppsfreq, &utp->ppsfreq) ||
++ __put_user(txc.jitter, &utp->jitter) ||
++ __put_user(txc.shift, &utp->shift) ||
++ __put_user(txc.stabil, &utp->stabil) ||
++ __put_user(txc.jitcnt, &utp->jitcnt) ||
++ __put_user(txc.calcnt, &utp->calcnt) ||
++ __put_user(txc.errcnt, &utp->errcnt) ||
++ __put_user(txc.stbcnt, &utp->stbcnt))
++ ret = -EFAULT;
++
++ return ret;
++}
++
++asmlinkage long compat_sys_pause(void)
++{
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++
++ return -ERESTARTNOHAND;
++}
++
++static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
++{
++ long usec;
++
++ if (!access_ok(VERIFY_READ, i, sizeof(*i)))
++ return -EFAULT;
++ if (__get_user(o->tv_sec, &i->tv_sec))
++ return -EFAULT;
++ if (__get_user(usec, &i->tv_usec))
++ return -EFAULT;
++ o->tv_nsec = usec * 1000;
++ return 0;
++}
++
++static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
++{
++ return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
++ (__put_user(i->tv_sec, &o->tv_sec) |
++ __put_user(i->tv_usec, &o->tv_usec)));
++}
++
++struct sysinfo32 {
++ s32 uptime;
++ u32 loads[3];
++ u32 totalram;
++ u32 freeram;
++ u32 sharedram;
++ u32 bufferram;
++ u32 totalswap;
++ u32 freeswap;
++ unsigned short procs;
++ unsigned short pad;
++ u32 totalhigh;
++ u32 freehigh;
++ u32 mem_unit;
++ char _f[20-2*sizeof(int)-sizeof(int)];
++};
++
++asmlinkage long compat_sys_sysinfo(struct sysinfo32 __user *info)
++{
++ struct sysinfo s;
++ int ret, err;
++ int bitcount=0;
++ mm_segment_t old_fs = get_fs ();
++
++ /* The __user cast is valid due to set_fs() */
++ set_fs (KERNEL_DS);
++ ret = sys_sysinfo((struct sysinfo __user *)&s);
++ set_fs (old_fs);
++
++ /* Check to see if any memory value is too large for 32-bit and
++ * scale down if needed.
++ */
++ if ((s.totalram >> 32) || (s.totalswap >> 32)) {
++ while (s.mem_unit < PAGE_SIZE) {
++ s.mem_unit <<= 1;
++ bitcount++;
++ }
++ s.totalram >>=bitcount;
++ s.freeram >>= bitcount;
++ s.sharedram >>= bitcount;
++ s.bufferram >>= bitcount;
++ s.totalswap >>= bitcount;
++ s.freeswap >>= bitcount;
++ s.totalhigh >>= bitcount;
++ s.freehigh >>= bitcount;
++ }
++
++ err = put_user (s.uptime, &info->uptime);
++ err |= __put_user (s.loads[0], &info->loads[0]);
++ err |= __put_user (s.loads[1], &info->loads[1]);
++ err |= __put_user (s.loads[2], &info->loads[2]);
++ err |= __put_user (s.totalram, &info->totalram);
++ err |= __put_user (s.freeram, &info->freeram);
++ err |= __put_user (s.sharedram, &info->sharedram);
++ err |= __put_user (s.bufferram, &info->bufferram);
++ err |= __put_user (s.totalswap, &info->totalswap);
++ err |= __put_user (s.freeswap, &info->freeswap);
++ err |= __put_user (s.procs, &info->procs);
++ err |= __put_user (s.totalhigh, &info->totalhigh);
++ err |= __put_user (s.freehigh, &info->freehigh);
++ err |= __put_user (s.mem_unit, &info->mem_unit);
++ if (err)
++ return -EFAULT;
++
++ return ret;
++}
++
++
++
++
++/* Translations due to time_t size differences. Which affects all
++ sorts of things, like timeval and itimerval. */
++extern struct timezone sys_tz;
++
++asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
++{
++ if (tv) {
++ struct timeval ktv;
++ do_gettimeofday(&ktv);
++ if (put_tv32(tv, &ktv))
++ return -EFAULT;
++ }
++ if (tz) {
++ if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
++ return -EFAULT;
++ }
++
++ return 0;
++}
++
++
++
++asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
++{
++ struct timespec kts;
++ struct timezone ktz;
++
++ if (tv) {
++ if (get_ts32(&kts, tv))
++ return -EFAULT;
++ }
++ if (tz) {
++ if (copy_from_user(&ktz, tz, sizeof(ktz)))
++ return -EFAULT;
++ }
++
++ return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
++}
++
++#ifdef CONFIG_SYSVIPC
++long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
++ u32 fifth)
++{
++ int version;
++
++ version = call >> 16; /* hack for backward compatibility */
++ call &= 0xffff;
++
++ switch (call) {
++
++ case SEMTIMEDOP:
++ if (fifth)
++ /* sign extend semid */
++ return compat_sys_semtimedop((int)first,
++ compat_ptr(ptr), second,
++ compat_ptr(fifth));
++ /* else fall through for normal semop() */
++ case SEMOP:
++ /* struct sembuf is the same on 32 and 64bit :)) */
++ /* sign extend semid */
++ return sys_semtimedop((int)first, compat_ptr(ptr), second,
++ NULL);
++ case SEMGET:
++ /* sign extend key, nsems */
++ return sys_semget((int)first, (int)second, third);
++ case SEMCTL:
++ /* sign extend semid, semnum */
++ return compat_sys_semctl((int)first, (int)second, third,
++ compat_ptr(ptr));
++
++ case MSGSND:
++ /* sign extend msqid */
++ return compat_sys_msgsnd((int)first, (int)second, third,
++ compat_ptr(ptr));
++ case MSGRCV:
++ /* sign extend msqid, msgtyp */
++ return compat_sys_msgrcv((int)first, second, (int)fifth,
++ third, version, compat_ptr(ptr));
++ case MSGGET:
++ /* sign extend key */
++ return sys_msgget((int)first, second);
++ case MSGCTL:
++ /* sign extend msqid */
++ return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
++
++ case SHMAT:
++ /* sign extend shmid */
++ return compat_sys_shmat((int)first, second, third, version,
++ compat_ptr(ptr));
++ case SHMDT:
++ return sys_shmdt(compat_ptr(ptr));
++ case SHMGET:
++ /* sign extend key_t */
++ return sys_shmget((int)first, second, third);
++ case SHMCTL:
++ /* sign extend shmid */
++ return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
++
++ default:
++ return -ENOSYS;
++ }
++
++ return -ENOSYS;
++}
++#endif
++
++/* Note: it is necessary to treat out_fd and in_fd as unsigned ints,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sendfile(u32 out_fd, u32 in_fd, compat_off_t __user * offset, u32 count)
++{
++ mm_segment_t old_fs = get_fs();
++ int ret;
++ off_t of;
++ off_t __user *up;
++
++ if (offset && get_user(of, offset))
++ return -EFAULT;
++
++ /* The __user pointer cast is valid because of the set_fs() */
++ set_fs(KERNEL_DS);
++ up = offset ? (off_t __user *) &of : NULL;
++ ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
++ set_fs(old_fs);
++
++ if (offset && put_user(of, offset))
++ return -EFAULT;
++
++ return ret;
++}
++
++asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
++{
++ mm_segment_t old_fs = get_fs();
++ int ret;
++ loff_t lof;
++ loff_t __user *up;
++
++ if (offset && get_user(lof, offset))
++ return -EFAULT;
++
++ /* The __user pointer cast is valid because of the set_fs() */
++ set_fs(KERNEL_DS);
++ up = offset ? (loff_t __user *) &lof : NULL;
++ ret = sys_sendfile64(out_fd, in_fd, up, count);
++ set_fs(old_fs);
++
++ if (offset && put_user(lof, offset))
++ return -EFAULT;
++
++ return ret;
++}
++
++long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
++ unsigned long a3, unsigned long a4, unsigned long a5,
++ struct pt_regs *regs)
++{
++ int error;
++ char * filename;
++
++ filename = getname((char __user *) a0);
++ error = PTR_ERR(filename);
++ if (IS_ERR(filename))
++ goto out;
++ flush_fp_to_thread(current);
++ flush_altivec_to_thread(current);
++
++ error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
++
++ if (error == 0) {
++ task_lock(current);
++ current->ptrace &= ~PT_DTRACE;
++ task_unlock(current);
++ }
++ putname(filename);
++
++out:
++ return error;
++}
++
++/* Note: it is necessary to treat option as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
++{
++ return sys_prctl((int)option,
++ (unsigned long) arg2,
++ (unsigned long) arg3,
++ (unsigned long) arg4,
++ (unsigned long) arg5);
++}
++
++/* Note: it is necessary to treat pid as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
++{
++ struct timespec t;
++ int ret;
++ mm_segment_t old_fs = get_fs ();
++
++ /* The __user pointer cast is valid because of the set_fs() */
++ set_fs (KERNEL_DS);
++ ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
++ set_fs (old_fs);
++ if (put_compat_timespec(&t, interval))
++ return -EFAULT;
++ return ret;
++}
++
++asmlinkage int compat_sys_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
++{
++ return sys_pciconfig_read((unsigned long) bus,
++ (unsigned long) dfn,
++ (unsigned long) off,
++ (unsigned long) len,
++ compat_ptr(ubuf));
++}
++
++asmlinkage int compat_sys_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
++{
++ return sys_pciconfig_write((unsigned long) bus,
++ (unsigned long) dfn,
++ (unsigned long) off,
++ (unsigned long) len,
++ compat_ptr(ubuf));
++}
++
++asmlinkage int compat_sys_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
++{
++ return sys_pciconfig_iobase(which, in_bus, in_devfn);
++}
++
++
++/* Note: it is necessary to treat mode as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_access(const char __user * filename, u32 mode)
++{
++ return sys_access(filename, (int)mode);
++}
++
++
++/* Note: it is necessary to treat mode as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_creat(const char __user * pathname, u32 mode)
++{
++ return sys_creat(pathname, (int)mode);
++}
++
++
++/* Note: it is necessary to treat pid and options as unsigned ints,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_waitpid(u32 pid, unsigned int __user * stat_addr, u32 options)
++{
++ return sys_waitpid((int)pid, stat_addr, (int)options);
++}
++
++
++/* Note: it is necessary to treat gidsetsize as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_getgroups(u32 gidsetsize, gid_t __user *grouplist)
++{
++ return sys_getgroups((int)gidsetsize, grouplist);
++}
++
++
++/* Note: it is necessary to treat pid as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_getpgid(u32 pid)
++{
++ return sys_getpgid((int)pid);
++}
++
++
++
++/* Note: it is necessary to treat pid as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_getsid(u32 pid)
++{
++ return sys_getsid((int)pid);
++}
++
++
++/* Note: it is necessary to treat pid and sig as unsigned ints,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_kill(u32 pid, u32 sig)
++{
++ return sys_kill((int)pid, (int)sig);
++}
++
++
++/* Note: it is necessary to treat mode as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_mkdir(const char __user * pathname, u32 mode)
++{
++ return sys_mkdir(pathname, (int)mode);
++}
++
++long compat_sys_nice(u32 increment)
++{
++ /* sign extend increment */
++ return sys_nice((int)increment);
++}
++
++off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
++{
++ /* sign extend n */
++ return sys_lseek(fd, (int)offset, origin);
++}
++
++/* Note: it is necessary to treat bufsiz as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_readlink(const char __user * path, char __user * buf, u32 bufsiz)
++{
++ return sys_readlink(path, buf, (int)bufsiz);
++}
++
++/* Note: it is necessary to treat option as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sched_get_priority_max(u32 policy)
++{
++ return sys_sched_get_priority_max((int)policy);
++}
++
++
++/* Note: it is necessary to treat policy as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sched_get_priority_min(u32 policy)
++{
++ return sys_sched_get_priority_min((int)policy);
++}
++
++
++/* Note: it is necessary to treat pid as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sched_getparam(u32 pid, struct sched_param __user *param)
++{
++ return sys_sched_getparam((int)pid, param);
++}
++
++
++/* Note: it is necessary to treat pid as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sched_getscheduler(u32 pid)
++{
++ return sys_sched_getscheduler((int)pid);
++}
++
++
++/* Note: it is necessary to treat pid as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sched_setparam(u32 pid, struct sched_param __user *param)
++{
++ return sys_sched_setparam((int)pid, param);
++}
++
++
++/* Note: it is necessary to treat pid and policy as unsigned ints,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_sched_setscheduler(u32 pid, u32 policy, struct sched_param __user *param)
++{
++ return sys_sched_setscheduler((int)pid, (int)policy, param);
++}
++
++
++/* Note: it is necessary to treat len as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_setdomainname(char __user *name, u32 len)
++{
++ return sys_setdomainname(name, (int)len);
++}
++
++
++/* Note: it is necessary to treat gidsetsize as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_setgroups(u32 gidsetsize, gid_t __user *grouplist)
++{
++ return sys_setgroups((int)gidsetsize, grouplist);
++}
++
++
++asmlinkage long compat_sys_sethostname(char __user *name, u32 len)
++{
++ /* sign extend len */
++ return sys_sethostname(name, (int)len);
++}
++
++
++/* Note: it is necessary to treat pid and pgid as unsigned ints,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_setpgid(u32 pid, u32 pgid)
++{
++ return sys_setpgid((int)pid, (int)pgid);
++}
++
++long compat_sys_getpriority(u32 which, u32 who)
++{
++ /* sign extend which and who */
++ return sys_getpriority((int)which, (int)who);
++}
++
++long compat_sys_setpriority(u32 which, u32 who, u32 niceval)
++{
++ /* sign extend which, who and niceval */
++ return sys_setpriority((int)which, (int)who, (int)niceval);
++}
++
++long compat_sys_ioprio_get(u32 which, u32 who)
++{
++ /* sign extend which and who */
++ return sys_ioprio_get((int)which, (int)who);
++}
++
++long compat_sys_ioprio_set(u32 which, u32 who, u32 ioprio)
++{
++ /* sign extend which, who and ioprio */
++ return sys_ioprio_set((int)which, (int)who, (int)ioprio);
++}
++
++/* Note: it is necessary to treat newmask as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_ssetmask(u32 newmask)
++{
++ return sys_ssetmask((int) newmask);
++}
++
++asmlinkage long compat_sys_syslog(u32 type, char __user * buf, u32 len)
++{
++ /* sign extend len */
++ return sys_syslog(type, buf, (int)len);
++}
++
++
++/* Note: it is necessary to treat mask as an unsigned int,
++ * with the corresponding cast to a signed int to insure that the
++ * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
++ * and the register representation of a signed int (msr in 64-bit mode) is performed.
++ */
++asmlinkage long compat_sys_umask(u32 mask)
++{
++ return sys_umask((int)mask);
++}
++
++#ifdef CONFIG_SYSCTL
++struct __sysctl_args32 {
++ u32 name;
++ int nlen;
++ u32 oldval;
++ u32 oldlenp;
++ u32 newval;
++ u32 newlen;
++ u32 __unused[4];
++};
++
++asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args)
++{
++ struct __sysctl_args32 tmp;
++ int error;
++ size_t oldlen;
++ size_t __user *oldlenp = NULL;
++ unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
++
++ if (copy_from_user(&tmp, args, sizeof(tmp)))
++ return -EFAULT;
++
++ if (tmp.oldval && tmp.oldlenp) {
++ /* Duh, this is ugly and might not work if sysctl_args
++ is in read-only memory, but do_sysctl does indirectly
++ a lot of uaccess in both directions and we'd have to
++ basically copy the whole sysctl.c here, and
++ glibc's __sysctl uses rw memory for the structure
++ anyway. */
++ oldlenp = (size_t __user *)addr;
++ if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
++ put_user(oldlen, oldlenp))
++ return -EFAULT;
++ }
++
++ lock_kernel();
++ error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
++ compat_ptr(tmp.oldval), oldlenp,
++ compat_ptr(tmp.newval), tmp.newlen);
++ unlock_kernel();
++ if (oldlenp) {
++ if (!error) {
++ if (get_user(oldlen, oldlenp) ||
++ put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
++ error = -EFAULT;
++ }
++ copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
++ }
++ return error;
++}
++#endif
++
++unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, unsigned long pgoff)
++{
++ /* This should remain 12 even if PAGE_SIZE changes */
++ return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
++}
++
++long compat_sys_tgkill(u32 tgid, u32 pid, int sig)
++{
++ /* sign extend tgid, pid */
++ return sys_tgkill((int)tgid, (int)pid, sig);
++}
++
++/*
++ * long long munging:
++ * The 32 bit ABI passes long longs in an odd even register pair.
++ */
++
++compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
++ u32 reg6, u32 poshi, u32 poslo)
++{
++ return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
++}
++
++compat_ssize_t compat_sys_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count,
++ u32 reg6, u32 poshi, u32 poslo)
++{
++ return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
++}
++
++compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
++{
++ return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
++}
++
++asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4,
++ unsigned long high, unsigned long low)
++{
++ return sys_truncate(path, (high << 32) | low);
++}
++
++asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
++ unsigned long low)
++{
++ return sys_ftruncate(fd, (high << 32) | low);
++}
++
++long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
++ size_t len)
++{
++ return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
++ buf, len);
++}
++
++long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
++ size_t len, int advice)
++{
++ return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len,
++ advice);
++}
++
++long ppc32_timer_create(clockid_t clock,
++ struct compat_sigevent __user *ev32,
++ timer_t __user *timer_id)
++{
++ sigevent_t event;
++ timer_t t;
++ long err;
++ mm_segment_t savefs;
++
++ if (ev32 == NULL)
++ return sys_timer_create(clock, NULL, timer_id);
++
++ if (get_compat_sigevent(&event, ev32))
++ return -EFAULT;
++
++ if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
++ return -EFAULT;
++
++ savefs = get_fs();
++ set_fs(KERNEL_DS);
++ /* The __user pointer casts are valid due to the set_fs() */
++ err = sys_timer_create(clock,
++ (sigevent_t __user *) &event,
++ (timer_t __user *) &t);
++ set_fs(savefs);
++
++ if (err == 0)
++ err = __put_user(t, timer_id);
++
++ return err;
++}
++
++asmlinkage long compat_sys_add_key(const char __user *_type,
++ const char __user *_description,
++ const void __user *_payload,
++ u32 plen,
++ u32 ringid)
++{
++ return sys_add_key(_type, _description, _payload, plen, ringid);
++}
++
++asmlinkage long compat_sys_request_key(const char __user *_type,
++ const char __user *_description,
++ const char __user *_callout_info,
++ u32 destringid)
++{
++ return sys_request_key(_type, _description, _callout_info, destringid);
++}
++
+diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/syscalls.c
+@@ -0,0 +1,358 @@
++/*
++ * Implementation of various system calls for Linux/PowerPC
++ *
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Derived from "arch/i386/kernel/sys_i386.c"
++ * Adapted from the i386 version by Gary Thomas
++ * Modified by Cort Dougan (cort at cs.nmt.edu)
++ * and Paul Mackerras (paulus at cs.anu.edu.au).
++ *
++ * This file contains various random system calls that
++ * have a non-standard calling sequence on the Linux/PPC
++ * platform.
++ *
++ * 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/errno.h>
++#include <linux/sched.h>
++#include <linux/syscalls.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/sem.h>
++#include <linux/msg.h>
++#include <linux/shm.h>
++#include <linux/stat.h>
++#include <linux/mman.h>
++#include <linux/sys.h>
++#include <linux/ipc.h>
++#include <linux/utsname.h>
++#include <linux/file.h>
++#include <linux/init.h>
++#include <linux/personality.h>
++
++#include <asm/uaccess.h>
++#include <asm/ipc.h>
++#include <asm/semaphore.h>
++#include <asm/time.h>
++#include <asm/unistd.h>
++
++extern unsigned long wall_jiffies;
++
++
++/*
++ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
++ *
++ * This is really horribly ugly.
++ */
++int sys_ipc(uint call, int first, unsigned long second, long third,
++ void __user *ptr, long fifth)
++{
++ int version, ret;
++
++ version = call >> 16; /* hack for backward compatibility */
++ call &= 0xffff;
++
++ ret = -ENOSYS;
++ switch (call) {
++ case SEMOP:
++ ret = sys_semtimedop(first, (struct sembuf __user *)ptr,
++ (unsigned)second, NULL);
++ break;
++ case SEMTIMEDOP:
++ ret = sys_semtimedop(first, (struct sembuf __user *)ptr,
++ (unsigned)second,
++ (const struct timespec __user *) fifth);
++ break;
++ case SEMGET:
++ ret = sys_semget (first, (int)second, third);
++ break;
++ case SEMCTL: {
++ union semun fourth;
++
++ ret = -EINVAL;
++ if (!ptr)
++ break;
++ if ((ret = get_user(fourth.__pad, (void __user * __user *)ptr)))
++ break;
++ ret = sys_semctl(first, (int)second, third, fourth);
++ break;
++ }
++ case MSGSND:
++ ret = sys_msgsnd(first, (struct msgbuf __user *)ptr,
++ (size_t)second, third);
++ break;
++ case MSGRCV:
++ switch (version) {
++ case 0: {
++ struct ipc_kludge tmp;
++
++ ret = -EINVAL;
++ if (!ptr)
++ break;
++ if ((ret = copy_from_user(&tmp,
++ (struct ipc_kludge __user *) ptr,
++ sizeof (tmp)) ? -EFAULT : 0))
++ break;
++ ret = sys_msgrcv(first, tmp.msgp, (size_t) second,
++ tmp.msgtyp, third);
++ break;
++ }
++ default:
++ ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
++ (size_t)second, fifth, third);
++ break;
++ }
++ break;
++ case MSGGET:
++ ret = sys_msgget((key_t)first, (int)second);
++ break;
++ case MSGCTL:
++ ret = sys_msgctl(first, (int)second,
++ (struct msqid_ds __user *)ptr);
++ break;
++ case SHMAT: {
++ ulong raddr;
++ ret = do_shmat(first, (char __user *)ptr, (int)second, &raddr);
++ if (ret)
++ break;
++ ret = put_user(raddr, (ulong __user *) third);
++ break;
++ }
++ case SHMDT:
++ ret = sys_shmdt((char __user *)ptr);
++ break;
++ case SHMGET:
++ ret = sys_shmget(first, (size_t)second, third);
++ break;
++ case SHMCTL:
++ ret = sys_shmctl(first, (int)second,
++ (struct shmid_ds __user *)ptr);
++ break;
++ }
++
++ return ret;
++}
++
++/*
++ * sys_pipe() is the normal C calling standard for creating
++ * a pipe. It's not the way unix traditionally does this, though.
++ */
++int sys_pipe(int __user *fildes)
++{
++ int fd[2];
++ int error;
++
++ error = do_pipe(fd);
++ if (!error) {
++ if (copy_to_user(fildes, fd, 2*sizeof(int)))
++ error = -EFAULT;
++ }
++ return error;
++}
++
++static inline unsigned long do_mmap2(unsigned long addr, size_t len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, unsigned long off, int shift)
++{
++ struct file * file = NULL;
++ unsigned long ret = -EINVAL;
++
++ if (shift) {
++ if (off & ((1 << shift) - 1))
++ goto out;
++ off >>= shift;
++ }
++
++ ret = -EBADF;
++ if (!(flags & MAP_ANONYMOUS)) {
++ if (!(file = fget(fd)))
++ goto out;
++ }
++
++ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
++
++ down_write(¤t->mm->mmap_sem);
++ ret = do_mmap_pgoff(file, addr, len, prot, flags, off);
++ up_write(¤t->mm->mmap_sem);
++ if (file)
++ fput(file);
++out:
++ return ret;
++}
++
++unsigned long sys_mmap2(unsigned long addr, size_t len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, unsigned long pgoff)
++{
++ return do_mmap2(addr, len, prot, flags, fd, pgoff, PAGE_SHIFT-12);
++}
++
++unsigned long sys_mmap(unsigned long addr, size_t len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, off_t offset)
++{
++ return do_mmap2(addr, len, prot, flags, fd, offset, PAGE_SHIFT);
++}
++
++#ifdef CONFIG_PPC32
++/*
++ * Due to some executables calling the wrong select we sometimes
++ * get wrong args. This determines how the args are being passed
++ * (a single ptr to them all args passed) then calls
++ * sys_select() with the appropriate args. -- Cort
++ */
++int
++ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
++{
++ if ( (unsigned long)n >= 4096 )
++ {
++ unsigned long __user *buffer = (unsigned long __user *)n;
++ if (!access_ok(VERIFY_READ, buffer, 5*sizeof(unsigned long))
++ || __get_user(n, buffer)
++ || __get_user(inp, ((fd_set __user * __user *)(buffer+1)))
++ || __get_user(outp, ((fd_set __user * __user *)(buffer+2)))
++ || __get_user(exp, ((fd_set __user * __user *)(buffer+3)))
++ || __get_user(tvp, ((struct timeval __user * __user *)(buffer+4))))
++ return -EFAULT;
++ }
++ return sys_select(n, inp, outp, exp, tvp);
++}
++#endif
++
++#ifdef CONFIG_PPC64
++long ppc64_personality(unsigned long personality)
++{
++ long ret;
++
++ if (personality(current->personality) == PER_LINUX32
++ && personality == PER_LINUX)
++ personality = PER_LINUX32;
++ ret = sys_personality(personality);
++ if (ret == PER_LINUX32)
++ ret = PER_LINUX;
++ return ret;
++}
++#endif
++
++#ifdef CONFIG_PPC64
++#define OVERRIDE_MACHINE (personality(current->personality) == PER_LINUX32)
++#else
++#define OVERRIDE_MACHINE 0
++#endif
++
++static inline int override_machine(char *mach)
++{
++ if (OVERRIDE_MACHINE) {
++ /* change ppc64 to ppc */
++ if (__put_user(0, mach+3) || __put_user(0, mach+4))
++ return -EFAULT;
++ }
++ return 0;
++}
++
++long ppc_newuname(struct new_utsname __user * name)
++{
++ int err = 0;
++
++ down_read(&uts_sem);
++ if (copy_to_user(name, &system_utsname, sizeof(*name)))
++ err = -EFAULT;
++ up_read(&uts_sem);
++ if (!err)
++ err = override_machine(name->machine);
++ return err;
++}
++
++int sys_uname(struct old_utsname __user *name)
++{
++ int err = 0;
++
++ down_read(&uts_sem);
++ if (copy_to_user(name, &system_utsname, sizeof(*name)))
++ err = -EFAULT;
++ up_read(&uts_sem);
++ if (!err)
++ err = override_machine(name->machine);
++ return err;
++}
++
++int sys_olduname(struct oldold_utsname __user *name)
++{
++ int error;
++
++ if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
++ return -EFAULT;
++
++ down_read(&uts_sem);
++ error = __copy_to_user(&name->sysname, &system_utsname.sysname,
++ __OLD_UTS_LEN);
++ error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
++ error |= __copy_to_user(&name->nodename, &system_utsname.nodename,
++ __OLD_UTS_LEN);
++ error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
++ error |= __copy_to_user(&name->release, &system_utsname.release,
++ __OLD_UTS_LEN);
++ error |= __put_user(0, name->release + __OLD_UTS_LEN);
++ error |= __copy_to_user(&name->version, &system_utsname.version,
++ __OLD_UTS_LEN);
++ error |= __put_user(0, name->version + __OLD_UTS_LEN);
++ error |= __copy_to_user(&name->machine, &system_utsname.machine,
++ __OLD_UTS_LEN);
++ error |= override_machine(name->machine);
++ up_read(&uts_sem);
++
++ return error? -EFAULT: 0;
++}
++
++#ifdef CONFIG_PPC64
++time_t sys64_time(time_t __user * tloc)
++{
++ time_t secs;
++ time_t usecs;
++
++ long tb_delta = tb_ticks_since(tb_last_stamp);
++ tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
++
++ secs = xtime.tv_sec;
++ usecs = (xtime.tv_nsec/1000) + tb_delta / tb_ticks_per_usec;
++ while (usecs >= USEC_PER_SEC) {
++ ++secs;
++ usecs -= USEC_PER_SEC;
++ }
++
++ if (tloc) {
++ if (put_user(secs,tloc))
++ secs = -EFAULT;
++ }
++
++ return secs;
++}
++#endif
++
++long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
++ u32 len_high, u32 len_low)
++{
++ return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low,
++ (u64)len_high << 32 | len_low, advice);
++}
++
++void do_show_syscall(unsigned long r3, unsigned long r4, unsigned long r5,
++ unsigned long r6, unsigned long r7, unsigned long r8,
++ struct pt_regs *regs)
++{
++ printk("syscall %ld(%lx, %lx, %lx, %lx, %lx, %lx) regs=%p current=%p"
++ " cpu=%d\n", regs->gpr[0], r3, r4, r5, r6, r7, r8, regs,
++ current, smp_processor_id());
++}
++
++void do_show_syscall_exit(unsigned long r3)
++{
++ printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id());
++}
+diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/systbl.S
+@@ -0,0 +1,321 @@
++/*
++ * This file contains the table of syscall-handling functions.
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Largely rewritten by Cort Dougan (cort at cs.nmt.edu)
++ * and Paul Mackerras.
++ *
++ * Adapted for iSeries by Mike Corrigan (mikejc at us.ibm.com)
++ * PPC64 updates by Dave Engebretsen (engebret at us.ibm.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/config.h>
++#include <asm/ppc_asm.h>
++
++#ifdef CONFIG_PPC64
++#define SYSCALL(func) .llong .sys_##func,.sys_##func
++#define COMPAT_SYS(func) .llong .sys_##func,.compat_sys_##func
++#define PPC_SYS(func) .llong .ppc_##func,.ppc_##func
++#define OLDSYS(func) .llong .sys_ni_syscall,.sys_ni_syscall
++#define SYS32ONLY(func) .llong .sys_ni_syscall,.compat_sys_##func
++#define SYSX(f, f3264, f32) .llong .f,.f3264
++#else
++#define SYSCALL(func) .long sys_##func
++#define COMPAT_SYS(func) .long sys_##func
++#define PPC_SYS(func) .long ppc_##func
++#define OLDSYS(func) .long sys_##func
++#define SYS32ONLY(func) .long sys_##func
++#define SYSX(f, f3264, f32) .long f32
++#endif
++
++#ifdef CONFIG_PPC64
++#define sys_sigpending sys_ni_syscall
++#define sys_old_getrlimit sys_ni_syscall
++#else
++#define ppc_rtas sys_ni_syscall
++#endif
++
++_GLOBAL(sys_call_table)
++SYSCALL(restart_syscall)
++SYSCALL(exit)
++PPC_SYS(fork)
++SYSCALL(read)
++SYSCALL(write)
++COMPAT_SYS(open)
++SYSCALL(close)
++COMPAT_SYS(waitpid)
++COMPAT_SYS(creat)
++SYSCALL(link)
++SYSCALL(unlink)
++COMPAT_SYS(execve)
++SYSCALL(chdir)
++SYSX(sys64_time,compat_sys_time,sys_time)
++SYSCALL(mknod)
++SYSCALL(chmod)
++SYSCALL(lchown)
++SYSCALL(ni_syscall)
++OLDSYS(stat)
++SYSX(sys_lseek,ppc32_lseek,sys_lseek)
++SYSCALL(getpid)
++COMPAT_SYS(mount)
++SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount)
++SYSCALL(setuid)
++SYSCALL(getuid)
++COMPAT_SYS(stime)
++COMPAT_SYS(ptrace)
++SYSCALL(alarm)
++OLDSYS(fstat)
++COMPAT_SYS(pause)
++COMPAT_SYS(utime)
++SYSCALL(ni_syscall)
++SYSCALL(ni_syscall)
++COMPAT_SYS(access)
++COMPAT_SYS(nice)
++SYSCALL(ni_syscall)
++SYSCALL(sync)
++COMPAT_SYS(kill)
++SYSCALL(rename)
++COMPAT_SYS(mkdir)
++SYSCALL(rmdir)
++SYSCALL(dup)
++SYSCALL(pipe)
++COMPAT_SYS(times)
++SYSCALL(ni_syscall)
++SYSCALL(brk)
++SYSCALL(setgid)
++SYSCALL(getgid)
++SYSCALL(signal)
++SYSCALL(geteuid)
++SYSCALL(getegid)
++SYSCALL(acct)
++SYSCALL(umount)
++SYSCALL(ni_syscall)
++COMPAT_SYS(ioctl)
++COMPAT_SYS(fcntl)
++SYSCALL(ni_syscall)
++COMPAT_SYS(setpgid)
++SYSCALL(ni_syscall)
++SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
++COMPAT_SYS(umask)
++SYSCALL(chroot)
++SYSCALL(ustat)
++SYSCALL(dup2)
++SYSCALL(getppid)
++SYSCALL(getpgrp)
++SYSCALL(setsid)
++SYS32ONLY(sigaction)
++SYSCALL(sgetmask)
++COMPAT_SYS(ssetmask)
++SYSCALL(setreuid)
++SYSCALL(setregid)
++SYSX(sys_ni_syscall,ppc32_sigsuspend,ppc_sigsuspend)
++COMPAT_SYS(sigpending)
++COMPAT_SYS(sethostname)
++COMPAT_SYS(setrlimit)
++COMPAT_SYS(old_getrlimit)
++COMPAT_SYS(getrusage)
++COMPAT_SYS(gettimeofday)
++COMPAT_SYS(settimeofday)
++COMPAT_SYS(getgroups)
++COMPAT_SYS(setgroups)
++SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select)
++SYSCALL(symlink)
++OLDSYS(lstat)
++COMPAT_SYS(readlink)
++SYSCALL(uselib)
++SYSCALL(swapon)
++SYSCALL(reboot)
++SYSX(sys_ni_syscall,old32_readdir,old_readdir)
++SYSCALL(mmap)
++SYSCALL(munmap)
++SYSCALL(truncate)
++SYSCALL(ftruncate)
++SYSCALL(fchmod)
++SYSCALL(fchown)
++COMPAT_SYS(getpriority)
++COMPAT_SYS(setpriority)
++SYSCALL(ni_syscall)
++COMPAT_SYS(statfs)
++COMPAT_SYS(fstatfs)
++SYSCALL(ni_syscall)
++COMPAT_SYS(socketcall)
++COMPAT_SYS(syslog)
++COMPAT_SYS(setitimer)
++COMPAT_SYS(getitimer)
++COMPAT_SYS(newstat)
++COMPAT_SYS(newlstat)
++COMPAT_SYS(newfstat)
++SYSX(sys_ni_syscall,sys_uname,sys_uname)
++SYSCALL(ni_syscall)
++SYSCALL(vhangup)
++SYSCALL(ni_syscall)
++SYSCALL(ni_syscall)
++COMPAT_SYS(wait4)
++SYSCALL(swapoff)
++COMPAT_SYS(sysinfo)
++COMPAT_SYS(ipc)
++SYSCALL(fsync)
++SYSX(sys_ni_syscall,ppc32_sigreturn,sys_sigreturn)
++PPC_SYS(clone)
++COMPAT_SYS(setdomainname)
++PPC_SYS(newuname)
++SYSCALL(ni_syscall)
++COMPAT_SYS(adjtimex)
++SYSCALL(mprotect)
++SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask)
++SYSCALL(ni_syscall)
++SYSCALL(init_module)
++SYSCALL(delete_module)
++SYSCALL(ni_syscall)
++SYSCALL(quotactl)
++COMPAT_SYS(getpgid)
++SYSCALL(fchdir)
++SYSCALL(bdflush)
++COMPAT_SYS(sysfs)
++SYSX(ppc64_personality,ppc64_personality,sys_personality)
++SYSCALL(ni_syscall)
++SYSCALL(setfsuid)
++SYSCALL(setfsgid)
++SYSCALL(llseek)
++COMPAT_SYS(getdents)
++SYSX(sys_select,ppc32_select,ppc_select)
++SYSCALL(flock)
++SYSCALL(msync)
++COMPAT_SYS(readv)
++COMPAT_SYS(writev)
++COMPAT_SYS(getsid)
++SYSCALL(fdatasync)
++COMPAT_SYS(sysctl)
++SYSCALL(mlock)
++SYSCALL(munlock)
++SYSCALL(mlockall)
++SYSCALL(munlockall)
++COMPAT_SYS(sched_setparam)
++COMPAT_SYS(sched_getparam)
++COMPAT_SYS(sched_setscheduler)
++COMPAT_SYS(sched_getscheduler)
++SYSCALL(sched_yield)
++COMPAT_SYS(sched_get_priority_max)
++COMPAT_SYS(sched_get_priority_min)
++COMPAT_SYS(sched_rr_get_interval)
++COMPAT_SYS(nanosleep)
++SYSCALL(mremap)
++SYSCALL(setresuid)
++SYSCALL(getresuid)
++SYSCALL(ni_syscall)
++SYSCALL(poll)
++COMPAT_SYS(nfsservctl)
++SYSCALL(setresgid)
++SYSCALL(getresgid)
++COMPAT_SYS(prctl)
++SYSX(ppc64_rt_sigreturn,ppc32_rt_sigreturn,sys_rt_sigreturn)
++COMPAT_SYS(rt_sigaction)
++COMPAT_SYS(rt_sigprocmask)
++COMPAT_SYS(rt_sigpending)
++COMPAT_SYS(rt_sigtimedwait)
++COMPAT_SYS(rt_sigqueueinfo)
++SYSX(ppc64_rt_sigsuspend,ppc32_rt_sigsuspend,ppc_rt_sigsuspend)
++COMPAT_SYS(pread64)
++COMPAT_SYS(pwrite64)
++SYSCALL(chown)
++SYSCALL(getcwd)
++SYSCALL(capget)
++SYSCALL(capset)
++COMPAT_SYS(sigaltstack)
++SYSX(sys_sendfile64,compat_sys_sendfile,sys_sendfile)
++SYSCALL(ni_syscall)
++SYSCALL(ni_syscall)
++PPC_SYS(vfork)
++COMPAT_SYS(getrlimit)
++COMPAT_SYS(readahead)
++SYS32ONLY(mmap2)
++SYS32ONLY(truncate64)
++SYS32ONLY(ftruncate64)
++SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
++SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
++SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
++COMPAT_SYS(pciconfig_read)
++COMPAT_SYS(pciconfig_write)
++COMPAT_SYS(pciconfig_iobase)
++SYSCALL(ni_syscall)
++SYSCALL(getdents64)
++SYSCALL(pivot_root)
++SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64)
++SYSCALL(madvise)
++SYSCALL(mincore)
++SYSCALL(gettid)
++SYSCALL(tkill)
++SYSCALL(setxattr)
++SYSCALL(lsetxattr)
++SYSCALL(fsetxattr)
++SYSCALL(getxattr)
++SYSCALL(lgetxattr)
++SYSCALL(fgetxattr)
++SYSCALL(listxattr)
++SYSCALL(llistxattr)
++SYSCALL(flistxattr)
++SYSCALL(removexattr)
++SYSCALL(lremovexattr)
++SYSCALL(fremovexattr)
++COMPAT_SYS(futex)
++COMPAT_SYS(sched_setaffinity)
++COMPAT_SYS(sched_getaffinity)
++SYSCALL(ni_syscall)
++SYSCALL(ni_syscall)
++SYS32ONLY(sendfile64)
++COMPAT_SYS(io_setup)
++SYSCALL(io_destroy)
++COMPAT_SYS(io_getevents)
++COMPAT_SYS(io_submit)
++SYSCALL(io_cancel)
++SYSCALL(set_tid_address)
++SYSX(sys_fadvise64,ppc32_fadvise64,sys_fadvise64)
++SYSCALL(exit_group)
++SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie)
++SYSCALL(epoll_create)
++SYSCALL(epoll_ctl)
++SYSCALL(epoll_wait)
++SYSCALL(remap_file_pages)
++SYSX(sys_timer_create,ppc32_timer_create,sys_timer_create)
++COMPAT_SYS(timer_settime)
++COMPAT_SYS(timer_gettime)
++SYSCALL(timer_getoverrun)
++SYSCALL(timer_delete)
++COMPAT_SYS(clock_settime)
++COMPAT_SYS(clock_gettime)
++COMPAT_SYS(clock_getres)
++COMPAT_SYS(clock_nanosleep)
++SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
++COMPAT_SYS(tgkill)
++COMPAT_SYS(utimes)
++COMPAT_SYS(statfs64)
++COMPAT_SYS(fstatfs64)
++SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
++PPC_SYS(rtas)
++OLDSYS(debug_setcontext)
++SYSCALL(ni_syscall)
++SYSCALL(ni_syscall)
++COMPAT_SYS(mbind)
++COMPAT_SYS(get_mempolicy)
++COMPAT_SYS(set_mempolicy)
++COMPAT_SYS(mq_open)
++SYSCALL(mq_unlink)
++COMPAT_SYS(mq_timedsend)
++COMPAT_SYS(mq_timedreceive)
++COMPAT_SYS(mq_notify)
++COMPAT_SYS(mq_getsetattr)
++COMPAT_SYS(kexec_load)
++COMPAT_SYS(add_key)
++COMPAT_SYS(request_key)
++COMPAT_SYS(keyctl)
++COMPAT_SYS(waitid)
++COMPAT_SYS(ioprio_set)
++COMPAT_SYS(ioprio_get)
++SYSCALL(inotify_init)
++SYSCALL(inotify_add_watch)
++SYSCALL(inotify_rm_watch)
+diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/time.c
+@@ -0,0 +1,1005 @@
++/*
++ * Common time routines among all ppc machines.
++ *
++ * Written by Cort Dougan (cort at cs.nmt.edu) to merge
++ * Paul Mackerras' version and mine for PReP and Pmac.
++ * MPC8xx/MBX changes by Dan Malek (dmalek at jlc.net).
++ * Converted for 64-bit by Mike Corrigan (mikejc at us.ibm.com)
++ *
++ * First round of bugfixes by Gabriel Paubert (paubert at iram.es)
++ * to make clock more stable (2.4.0-test5). The only thing
++ * that this code assumes is that the timebases have been synchronized
++ * by firmware on SMP and are never stopped (never do sleep
++ * on SMP then, nap and doze are OK).
++ *
++ * Speeded up do_gettimeofday by getting rid of references to
++ * xtime (which required locks for consistency). (mikejc at us.ibm.com)
++ *
++ * TODO (not necessarily in this file):
++ * - improve precision and reproducibility of timebase frequency
++ * measurement at boot time. (for iSeries, we calibrate the timebase
++ * against the Titan chip's clock.)
++ * - for astronomical applications: add a new function to get
++ * non ambiguous timestamps even around leap seconds. This needs
++ * a new timestamp format and a good name.
++ *
++ * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
++ * "A Kernel Model for Precision Timekeeping" by Dave Mills
++ *
++ * 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/errno.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/timex.h>
++#include <linux/kernel_stat.h>
++#include <linux/time.h>
++#include <linux/init.h>
++#include <linux/profile.h>
++#include <linux/cpu.h>
++#include <linux/security.h>
++#include <linux/percpu.h>
++#include <linux/rtc.h>
++
++#include <asm/io.h>
++#include <asm/processor.h>
++#include <asm/nvram.h>
++#include <asm/cache.h>
++#include <asm/machdep.h>
++#include <asm/uaccess.h>
++#include <asm/time.h>
++#include <asm/prom.h>
++#include <asm/irq.h>
++#include <asm/div64.h>
++#ifdef CONFIG_PPC64
++#include <asm/systemcfg.h>
++#include <asm/firmware.h>
++#endif
++#ifdef CONFIG_PPC_ISERIES
++#include <asm/iSeries/ItLpQueue.h>
++#include <asm/iSeries/HvCallXm.h>
++#endif
++
++/* keep track of when we need to update the rtc */
++time_t last_rtc_update;
++extern int piranha_simulator;
++#ifdef CONFIG_PPC_ISERIES
++unsigned long iSeries_recal_titan = 0;
++unsigned long iSeries_recal_tb = 0;
++static unsigned long first_settimeofday = 1;
++#endif
++
++/* The decrementer counts down by 128 every 128ns on a 601. */
++#define DECREMENTER_COUNT_601 (1000000000 / HZ)
++
++#define XSEC_PER_SEC (1024*1024)
++
++#ifdef CONFIG_PPC64
++#define SCALE_XSEC(xsec, max) (((xsec) * max) / XSEC_PER_SEC)
++#else
++/* compute ((xsec << 12) * max) >> 32 */
++#define SCALE_XSEC(xsec, max) mulhwu((xsec) << 12, max)
++#endif
++
++unsigned long tb_ticks_per_jiffy;
++unsigned long tb_ticks_per_usec = 100; /* sane default */
++EXPORT_SYMBOL(tb_ticks_per_usec);
++unsigned long tb_ticks_per_sec;
++u64 tb_to_xs;
++unsigned tb_to_us;
++unsigned long processor_freq;
++DEFINE_SPINLOCK(rtc_lock);
++EXPORT_SYMBOL_GPL(rtc_lock);
++
++u64 tb_to_ns_scale;
++unsigned tb_to_ns_shift;
++
++struct gettimeofday_struct do_gtod;
++
++extern unsigned long wall_jiffies;
++
++extern struct timezone sys_tz;
++static long timezone_offset;
++
++void ppc_adjtimex(void);
++
++static unsigned adjusting_time = 0;
++
++unsigned long ppc_proc_freq;
++unsigned long ppc_tb_freq;
++
++#ifdef CONFIG_PPC32 /* XXX for now */
++#define boot_cpuid 0
++#endif
++
++u64 tb_last_jiffy __cacheline_aligned_in_smp;
++unsigned long tb_last_stamp;
++
++/*
++ * Note that on ppc32 this only stores the bottom 32 bits of
++ * the timebase value, but that's enough to tell when a jiffy
++ * has passed.
++ */
++DEFINE_PER_CPU(unsigned long, last_jiffy);
++
++static __inline__ void timer_check_rtc(void)
++{
++ /*
++ * update the rtc when needed, this should be performed on the
++ * right fraction of a second. Half or full second ?
++ * Full second works on mk48t59 clocks, others need testing.
++ * Note that this update is basically only used through
++ * the adjtimex system calls. Setting the HW clock in
++ * any other way is a /dev/rtc and userland business.
++ * This is still wrong by -0.5/+1.5 jiffies because of the
++ * timer interrupt resolution and possible delay, but here we
++ * hit a quantization limit which can only be solved by higher
++ * resolution timers and decoupling time management from timer
++ * interrupts. This is also wrong on the clocks
++ * which require being written at the half second boundary.
++ * We should have an rtc call that only sets the minutes and
++ * seconds like on Intel to avoid problems with non UTC clocks.
++ */
++ if (ppc_md.set_rtc_time && ntp_synced() &&
++ xtime.tv_sec - last_rtc_update >= 659 &&
++ abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ &&
++ jiffies - wall_jiffies == 1) {
++ struct rtc_time tm;
++ to_tm(xtime.tv_sec + 1 + timezone_offset, &tm);
++ tm.tm_year -= 1900;
++ tm.tm_mon -= 1;
++ if (ppc_md.set_rtc_time(&tm) == 0)
++ last_rtc_update = xtime.tv_sec + 1;
++ else
++ /* Try again one minute later */
++ last_rtc_update += 60;
++ }
++}
++
++/*
++ * This version of gettimeofday has microsecond resolution.
++ */
++static inline void __do_gettimeofday(struct timeval *tv, u64 tb_val)
++{
++ unsigned long sec, usec;
++ u64 tb_ticks, xsec;
++ struct gettimeofday_vars *temp_varp;
++ u64 temp_tb_to_xs, temp_stamp_xsec;
++
++ /*
++ * These calculations are faster (gets rid of divides)
++ * if done in units of 1/2^20 rather than microseconds.
++ * The conversion to microseconds at the end is done
++ * without a divide (and in fact, without a multiply)
++ */
++ temp_varp = do_gtod.varp;
++ tb_ticks = tb_val - temp_varp->tb_orig_stamp;
++ temp_tb_to_xs = temp_varp->tb_to_xs;
++ temp_stamp_xsec = temp_varp->stamp_xsec;
++ xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
++ sec = xsec / XSEC_PER_SEC;
++ usec = (unsigned long)xsec & (XSEC_PER_SEC - 1);
++ usec = SCALE_XSEC(usec, 1000000);
++
++ tv->tv_sec = sec;
++ tv->tv_usec = usec;
++}
++
++void do_gettimeofday(struct timeval *tv)
++{
++ if (__USE_RTC()) {
++ /* do this the old way */
++ unsigned long flags, seq;
++ unsigned int sec, nsec, usec, lost;
++
++ do {
++ seq = read_seqbegin_irqsave(&xtime_lock, flags);
++ sec = xtime.tv_sec;
++ nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp);
++ lost = jiffies - wall_jiffies;
++ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
++ usec = nsec / 1000 + lost * (1000000 / HZ);
++ while (usec >= 1000000) {
++ usec -= 1000000;
++ ++sec;
++ }
++ tv->tv_sec = sec;
++ tv->tv_usec = usec;
++ return;
++ }
++ __do_gettimeofday(tv, get_tb());
++}
++
++EXPORT_SYMBOL(do_gettimeofday);
++
++/* Synchronize xtime with do_gettimeofday */
++
++static inline void timer_sync_xtime(unsigned long cur_tb)
++{
++#ifdef CONFIG_PPC64
++ /* why do we do this? */
++ struct timeval my_tv;
++
++ __do_gettimeofday(&my_tv, cur_tb);
++
++ if (xtime.tv_sec <= my_tv.tv_sec) {
++ xtime.tv_sec = my_tv.tv_sec;
++ xtime.tv_nsec = my_tv.tv_usec * 1000;
++ }
++#endif
++}
++
++/*
++ * There are two copies of tb_to_xs and stamp_xsec so that no
++ * lock is needed to access and use these values in
++ * do_gettimeofday. We alternate the copies and as long as a
++ * reasonable time elapses between changes, there will never
++ * be inconsistent values. ntpd has a minimum of one minute
++ * between updates.
++ */
++static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
++ u64 new_tb_to_xs)
++{
++ unsigned temp_idx;
++ struct gettimeofday_vars *temp_varp;
++
++ temp_idx = (do_gtod.var_idx == 0);
++ temp_varp = &do_gtod.vars[temp_idx];
++
++ temp_varp->tb_to_xs = new_tb_to_xs;
++ temp_varp->tb_orig_stamp = new_tb_stamp;
++ temp_varp->stamp_xsec = new_stamp_xsec;
++ smp_mb();
++ do_gtod.varp = temp_varp;
++ do_gtod.var_idx = temp_idx;
++
++#ifdef CONFIG_PPC64
++ /*
++ * tb_update_count is used to allow the userspace gettimeofday code
++ * to assure itself that it sees a consistent view of the tb_to_xs and
++ * stamp_xsec variables. It reads the tb_update_count, then reads
++ * tb_to_xs and stamp_xsec and then reads tb_update_count again. If
++ * the two values of tb_update_count match and are even then the
++ * tb_to_xs and stamp_xsec values are consistent. If not, then it
++ * loops back and reads them again until this criteria is met.
++ */
++ ++(systemcfg->tb_update_count);
++ smp_wmb();
++ systemcfg->tb_orig_stamp = new_tb_stamp;
++ systemcfg->stamp_xsec = new_stamp_xsec;
++ systemcfg->tb_to_xs = new_tb_to_xs;
++ smp_wmb();
++ ++(systemcfg->tb_update_count);
++#endif
++}
++
++/*
++ * When the timebase - tb_orig_stamp gets too big, we do a manipulation
++ * between tb_orig_stamp and stamp_xsec. The goal here is to keep the
++ * difference tb - tb_orig_stamp small enough to always fit inside a
++ * 32 bits number. This is a requirement of our fast 32 bits userland
++ * implementation in the vdso. If we "miss" a call to this function
++ * (interrupt latency, CPU locked in a spinlock, ...) and we end up
++ * with a too big difference, then the vdso will fallback to calling
++ * the syscall
++ */
++static __inline__ void timer_recalc_offset(u64 cur_tb)
++{
++ unsigned long offset;
++ u64 new_stamp_xsec;
++
++ if (__USE_RTC())
++ return;
++ offset = cur_tb - do_gtod.varp->tb_orig_stamp;
++ if ((offset & 0x80000000u) == 0)
++ return;
++ new_stamp_xsec = do_gtod.varp->stamp_xsec
++ + mulhdu(offset, do_gtod.varp->tb_to_xs);
++ update_gtod(cur_tb, new_stamp_xsec, do_gtod.varp->tb_to_xs);
++}
++
++#ifdef CONFIG_SMP
++unsigned long profile_pc(struct pt_regs *regs)
++{
++ unsigned long pc = instruction_pointer(regs);
++
++ if (in_lock_functions(pc))
++ return regs->link;
++
++ return pc;
++}
++EXPORT_SYMBOL(profile_pc);
++#endif
++
++#ifdef CONFIG_PPC_ISERIES
++
++/*
++ * This function recalibrates the timebase based on the 49-bit time-of-day
++ * value in the Titan chip. The Titan is much more accurate than the value
++ * returned by the service processor for the timebase frequency.
++ */
++
++static void iSeries_tb_recal(void)
++{
++ struct div_result divres;
++ unsigned long titan, tb;
++ tb = get_tb();
++ titan = HvCallXm_loadTod();
++ if ( iSeries_recal_titan ) {
++ unsigned long tb_ticks = tb - iSeries_recal_tb;
++ unsigned long titan_usec = (titan - iSeries_recal_titan) >> 12;
++ unsigned long new_tb_ticks_per_sec = (tb_ticks * USEC_PER_SEC)/titan_usec;
++ unsigned long new_tb_ticks_per_jiffy = (new_tb_ticks_per_sec+(HZ/2))/HZ;
++ long tick_diff = new_tb_ticks_per_jiffy - tb_ticks_per_jiffy;
++ char sign = '+';
++ /* make sure tb_ticks_per_sec and tb_ticks_per_jiffy are consistent */
++ new_tb_ticks_per_sec = new_tb_ticks_per_jiffy * HZ;
++
++ if ( tick_diff < 0 ) {
++ tick_diff = -tick_diff;
++ sign = '-';
++ }
++ if ( tick_diff ) {
++ if ( tick_diff < tb_ticks_per_jiffy/25 ) {
++ printk( "Titan recalibrate: new tb_ticks_per_jiffy = %lu (%c%ld)\n",
++ new_tb_ticks_per_jiffy, sign, tick_diff );
++ tb_ticks_per_jiffy = new_tb_ticks_per_jiffy;
++ tb_ticks_per_sec = new_tb_ticks_per_sec;
++ div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres );
++ do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
++ tb_to_xs = divres.result_low;
++ do_gtod.varp->tb_to_xs = tb_to_xs;
++ systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
++ systemcfg->tb_to_xs = tb_to_xs;
++ }
++ else {
++ printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
++ " new tb_ticks_per_jiffy = %lu\n"
++ " old tb_ticks_per_jiffy = %lu\n",
++ new_tb_ticks_per_jiffy, tb_ticks_per_jiffy );
++ }
++ }
++ }
++ iSeries_recal_titan = titan;
++ iSeries_recal_tb = tb;
++}
++#endif
++
++/*
++ * For iSeries shared processors, we have to let the hypervisor
++ * set the hardware decrementer. We set a virtual decrementer
++ * in the lppaca and call the hypervisor if the virtual
++ * decrementer is less than the current value in the hardware
++ * decrementer. (almost always the new decrementer value will
++ * be greater than the current hardware decementer so the hypervisor
++ * call will not be needed)
++ */
++
++/*
++ * timer_interrupt - gets called when the decrementer overflows,
++ * with interrupts disabled.
++ */
++void timer_interrupt(struct pt_regs * regs)
++{
++ int next_dec;
++ int cpu = smp_processor_id();
++ unsigned long ticks;
++
++#ifdef CONFIG_PPC32
++ if (atomic_read(&ppc_n_lost_interrupts) != 0)
++ do_IRQ(regs);
++#endif
++
++ irq_enter();
++
++ profile_tick(CPU_PROFILING, regs);
++
++#ifdef CONFIG_PPC_ISERIES
++ get_paca()->lppaca.int_dword.fields.decr_int = 0;
++#endif
++
++ while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
++ >= tb_ticks_per_jiffy) {
++ /* Update last_jiffy */
++ per_cpu(last_jiffy, cpu) += tb_ticks_per_jiffy;
++ /* Handle RTCL overflow on 601 */
++ if (__USE_RTC() && per_cpu(last_jiffy, cpu) >= 1000000000)
++ per_cpu(last_jiffy, cpu) -= 1000000000;
++
++ /*
++ * We cannot disable the decrementer, so in the period
++ * between this cpu's being marked offline in cpu_online_map
++ * and calling stop-self, it is taking timer interrupts.
++ * Avoid calling into the scheduler rebalancing code if this
++ * is the case.
++ */
++ if (!cpu_is_offline(cpu))
++ update_process_times(user_mode(regs));
++
++ /*
++ * No need to check whether cpu is offline here; boot_cpuid
++ * should have been fixed up by now.
++ */
++ if (cpu != boot_cpuid)
++ continue;
++
++ write_seqlock(&xtime_lock);
++ tb_last_jiffy += tb_ticks_per_jiffy;
++ tb_last_stamp = per_cpu(last_jiffy, cpu);
++ timer_recalc_offset(tb_last_jiffy);
++ do_timer(regs);
++ timer_sync_xtime(tb_last_jiffy);
++ timer_check_rtc();
++ write_sequnlock(&xtime_lock);
++ if (adjusting_time && (time_adjust == 0))
++ ppc_adjtimex();
++ }
++
++ next_dec = tb_ticks_per_jiffy - ticks;
++ set_dec(next_dec);
++
++#ifdef CONFIG_PPC_ISERIES
++ if (hvlpevent_is_pending())
++ process_hvlpevents(regs);
++#endif
++
++#ifdef CONFIG_PPC64
++ /* collect purr register values often, for accurate calculations */
++ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
++ struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
++ cu->current_tb = mfspr(SPRN_PURR);
++ }
++#endif
++
++ irq_exit();
++}
++
++void wakeup_decrementer(void)
++{
++ int i;
++
++ set_dec(tb_ticks_per_jiffy);
++ /*
++ * We don't expect this to be called on a machine with a 601,
++ * so using get_tbl is fine.
++ */
++ tb_last_stamp = tb_last_jiffy = get_tb();
++ for_each_cpu(i)
++ per_cpu(last_jiffy, i) = tb_last_stamp;
++}
++
++#ifdef CONFIG_SMP
++void __init smp_space_timers(unsigned int max_cpus)
++{
++ int i;
++ unsigned long offset = tb_ticks_per_jiffy / max_cpus;
++ unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid);
++
++ for_each_cpu(i) {
++ if (i != boot_cpuid) {
++ previous_tb += offset;
++ per_cpu(last_jiffy, i) = previous_tb;
++ }
++ }
++}
++#endif
++
++/*
++ * Scheduler clock - returns current time in nanosec units.
++ *
++ * Note: mulhdu(a, b) (multiply high double unsigned) returns
++ * the high 64 bits of a * b, i.e. (a * b) >> 64, where a and b
++ * are 64-bit unsigned numbers.
++ */
++unsigned long long sched_clock(void)
++{
++ if (__USE_RTC())
++ return get_rtc();
++ return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
++}
++
++int do_settimeofday(struct timespec *tv)
++{
++ time_t wtm_sec, new_sec = tv->tv_sec;
++ long wtm_nsec, new_nsec = tv->tv_nsec;
++ unsigned long flags;
++ long int tb_delta;
++ u64 new_xsec, tb_delta_xs;
++
++ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
++ return -EINVAL;
++
++ write_seqlock_irqsave(&xtime_lock, flags);
++
++ /*
++ * Updating the RTC is not the job of this code. If the time is
++ * stepped under NTP, the RTC will be updated after STA_UNSYNC
++ * is cleared. Tools like clock/hwclock either copy the RTC
++ * to the system time, in which case there is no point in writing
++ * to the RTC again, or write to the RTC but then they don't call
++ * settimeofday to perform this operation.
++ */
++#ifdef CONFIG_PPC_ISERIES
++ if (first_settimeofday) {
++ iSeries_tb_recal();
++ first_settimeofday = 0;
++ }
++#endif
++ tb_delta = tb_ticks_since(tb_last_stamp);
++ tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
++ tb_delta_xs = mulhdu(tb_delta, do_gtod.varp->tb_to_xs);
++
++ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
++ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
++
++ set_normalized_timespec(&xtime, new_sec, new_nsec);
++ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
++
++ /* In case of a large backwards jump in time with NTP, we want the
++ * clock to be updated as soon as the PLL is again in lock.
++ */
++ last_rtc_update = new_sec - 658;
++
++ ntp_clear();
++
++ new_xsec = 0;
++ if (new_nsec != 0) {
++ new_xsec = (u64)new_nsec * XSEC_PER_SEC;
++ do_div(new_xsec, NSEC_PER_SEC);
++ }
++ new_xsec += (u64)new_sec * XSEC_PER_SEC - tb_delta_xs;
++ update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
++
++#ifdef CONFIG_PPC64
++ systemcfg->tz_minuteswest = sys_tz.tz_minuteswest;
++ systemcfg->tz_dsttime = sys_tz.tz_dsttime;
++#endif
++
++ write_sequnlock_irqrestore(&xtime_lock, flags);
++ clock_was_set();
++ return 0;
++}
++
++EXPORT_SYMBOL(do_settimeofday);
++
++void __init generic_calibrate_decr(void)
++{
++ struct device_node *cpu;
++ unsigned int *fp;
++ int node_found;
++
++ /*
++ * The cpu node should have a timebase-frequency property
++ * to tell us the rate at which the decrementer counts.
++ */
++ cpu = of_find_node_by_type(NULL, "cpu");
++
++ ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
++ node_found = 0;
++ if (cpu != 0) {
++ fp = (unsigned int *)get_property(cpu, "timebase-frequency",
++ NULL);
++ if (fp != 0) {
++ node_found = 1;
++ ppc_tb_freq = *fp;
++ }
++ }
++ if (!node_found)
++ printk(KERN_ERR "WARNING: Estimating decrementer frequency "
++ "(not found)\n");
++
++ ppc_proc_freq = DEFAULT_PROC_FREQ;
++ node_found = 0;
++ if (cpu != 0) {
++ fp = (unsigned int *)get_property(cpu, "clock-frequency",
++ NULL);
++ if (fp != 0) {
++ node_found = 1;
++ ppc_proc_freq = *fp;
++ }
++ }
++#ifdef CONFIG_BOOKE
++ /* Set the time base to zero */
++ mtspr(SPRN_TBWL, 0);
++ mtspr(SPRN_TBWU, 0);
++
++ /* Clear any pending timer interrupts */
++ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
++
++ /* Enable decrementer interrupt */
++ mtspr(SPRN_TCR, TCR_DIE);
++#endif
++ if (!node_found)
++ printk(KERN_ERR "WARNING: Estimating processor frequency "
++ "(not found)\n");
++
++ of_node_put(cpu);
++}
++
++unsigned long get_boot_time(void)
++{
++ struct rtc_time tm;
++
++ if (ppc_md.get_boot_time)
++ return ppc_md.get_boot_time();
++ if (!ppc_md.get_rtc_time)
++ return 0;
++ ppc_md.get_rtc_time(&tm);
++ return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
++ tm.tm_hour, tm.tm_min, tm.tm_sec);
++}
++
++/* This function is only called on the boot processor */
++void __init time_init(void)
++{
++ unsigned long flags;
++ unsigned long tm = 0;
++ struct div_result res;
++ u64 scale;
++ unsigned shift;
++
++ if (ppc_md.time_init != NULL)
++ timezone_offset = ppc_md.time_init();
++
++ if (__USE_RTC()) {
++ /* 601 processor: dec counts down by 128 every 128ns */
++ ppc_tb_freq = 1000000000;
++ tb_last_stamp = get_rtcl();
++ tb_last_jiffy = tb_last_stamp;
++ } else {
++ /* Normal PowerPC with timebase register */
++ ppc_md.calibrate_decr();
++ printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
++ ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
++ printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
++ ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
++ tb_last_stamp = tb_last_jiffy = get_tb();
++ }
++
++ tb_ticks_per_jiffy = ppc_tb_freq / HZ;
++ tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
++ tb_ticks_per_usec = ppc_tb_freq / 1000000;
++ tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
++ div128_by_32(1024*1024, 0, tb_ticks_per_sec, &res);
++ tb_to_xs = res.result_low;
++
++#ifdef CONFIG_PPC64
++ get_paca()->default_decr = tb_ticks_per_jiffy;
++#endif
++
++ /*
++ * Compute scale factor for sched_clock.
++ * The calibrate_decr() function has set tb_ticks_per_sec,
++ * which is the timebase frequency.
++ * We compute 1e9 * 2^64 / tb_ticks_per_sec and interpret
++ * the 128-bit result as a 64.64 fixed-point number.
++ * We then shift that number right until it is less than 1.0,
++ * giving us the scale factor and shift count to use in
++ * sched_clock().
++ */
++ div128_by_32(1000000000, 0, tb_ticks_per_sec, &res);
++ scale = res.result_low;
++ for (shift = 0; res.result_high != 0; ++shift) {
++ scale = (scale >> 1) | (res.result_high << 63);
++ res.result_high >>= 1;
++ }
++ tb_to_ns_scale = scale;
++ tb_to_ns_shift = shift;
++
++#ifdef CONFIG_PPC_ISERIES
++ if (!piranha_simulator)
++#endif
++ tm = get_boot_time();
++
++ write_seqlock_irqsave(&xtime_lock, flags);
++ xtime.tv_sec = tm;
++ xtime.tv_nsec = 0;
++ do_gtod.varp = &do_gtod.vars[0];
++ do_gtod.var_idx = 0;
++ do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
++ __get_cpu_var(last_jiffy) = tb_last_stamp;
++ do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
++ do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
++ do_gtod.varp->tb_to_xs = tb_to_xs;
++ do_gtod.tb_to_us = tb_to_us;
++#ifdef CONFIG_PPC64
++ systemcfg->tb_orig_stamp = tb_last_jiffy;
++ systemcfg->tb_update_count = 0;
++ systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
++ systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
++ systemcfg->tb_to_xs = tb_to_xs;
++#endif
++
++ time_freq = 0;
++
++ /* If platform provided a timezone (pmac), we correct the time */
++ if (timezone_offset) {
++ sys_tz.tz_minuteswest = -timezone_offset / 60;
++ sys_tz.tz_dsttime = 0;
++ xtime.tv_sec -= timezone_offset;
++ }
++
++ last_rtc_update = xtime.tv_sec;
++ set_normalized_timespec(&wall_to_monotonic,
++ -xtime.tv_sec, -xtime.tv_nsec);
++ write_sequnlock_irqrestore(&xtime_lock, flags);
++
++ /* Not exact, but the timer interrupt takes care of this */
++ set_dec(tb_ticks_per_jiffy);
++}
++
++/*
++ * After adjtimex is called, adjust the conversion of tb ticks
++ * to microseconds to keep do_gettimeofday synchronized
++ * with ntpd.
++ *
++ * Use the time_adjust, time_freq and time_offset computed by adjtimex to
++ * adjust the frequency.
++ */
++
++/* #define DEBUG_PPC_ADJTIMEX 1 */
++
++void ppc_adjtimex(void)
++{
++#ifdef CONFIG_PPC64
++ unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec,
++ new_tb_to_xs, new_xsec, new_stamp_xsec;
++ unsigned long tb_ticks_per_sec_delta;
++ long delta_freq, ltemp;
++ struct div_result divres;
++ unsigned long flags;
++ long singleshot_ppm = 0;
++
++ /*
++ * Compute parts per million frequency adjustment to
++ * accomplish the time adjustment implied by time_offset to be
++ * applied over the elapsed time indicated by time_constant.
++ * Use SHIFT_USEC to get it into the same units as
++ * time_freq.
++ */
++ if ( time_offset < 0 ) {
++ ltemp = -time_offset;
++ ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
++ ltemp >>= SHIFT_KG + time_constant;
++ ltemp = -ltemp;
++ } else {
++ ltemp = time_offset;
++ ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
++ ltemp >>= SHIFT_KG + time_constant;
++ }
++
++ /* If there is a single shot time adjustment in progress */
++ if ( time_adjust ) {
++#ifdef DEBUG_PPC_ADJTIMEX
++ printk("ppc_adjtimex: ");
++ if ( adjusting_time == 0 )
++ printk("starting ");
++ printk("single shot time_adjust = %ld\n", time_adjust);
++#endif
++
++ adjusting_time = 1;
++
++ /*
++ * Compute parts per million frequency adjustment
++ * to match time_adjust
++ */
++ singleshot_ppm = tickadj * HZ;
++ /*
++ * The adjustment should be tickadj*HZ to match the code in
++ * linux/kernel/timer.c, but experiments show that this is too
++ * large. 3/4 of tickadj*HZ seems about right
++ */
++ singleshot_ppm -= singleshot_ppm / 4;
++ /* Use SHIFT_USEC to get it into the same units as time_freq */
++ singleshot_ppm <<= SHIFT_USEC;
++ if ( time_adjust < 0 )
++ singleshot_ppm = -singleshot_ppm;
++ }
++ else {
++#ifdef DEBUG_PPC_ADJTIMEX
++ if ( adjusting_time )
++ printk("ppc_adjtimex: ending single shot time_adjust\n");
++#endif
++ adjusting_time = 0;
++ }
++
++ /* Add up all of the frequency adjustments */
++ delta_freq = time_freq + ltemp + singleshot_ppm;
++
++ /*
++ * Compute a new value for tb_ticks_per_sec based on
++ * the frequency adjustment
++ */
++ den = 1000000 * (1 << (SHIFT_USEC - 8));
++ if ( delta_freq < 0 ) {
++ tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den;
++ new_tb_ticks_per_sec = tb_ticks_per_sec + tb_ticks_per_sec_delta;
++ }
++ else {
++ tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den;
++ new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta;
++ }
++
++#ifdef DEBUG_PPC_ADJTIMEX
++ printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm);
++ printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);
++#endif
++
++ /*
++ * Compute a new value of tb_to_xs (used to convert tb to
++ * microseconds) and a new value of stamp_xsec which is the
++ * time (in 1/2^20 second units) corresponding to
++ * tb_orig_stamp. This new value of stamp_xsec compensates
++ * for the change in frequency (implied by the new tb_to_xs)
++ * which guarantees that the current time remains the same.
++ */
++ write_seqlock_irqsave( &xtime_lock, flags );
++ tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp;
++ div128_by_32(1024*1024, 0, new_tb_ticks_per_sec, &divres);
++ new_tb_to_xs = divres.result_low;
++ new_xsec = mulhdu(tb_ticks, new_tb_to_xs);
++
++ old_xsec = mulhdu(tb_ticks, do_gtod.varp->tb_to_xs);
++ new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
++
++ update_gtod(do_gtod.varp->tb_orig_stamp, new_stamp_xsec, new_tb_to_xs);
++
++ write_sequnlock_irqrestore( &xtime_lock, flags );
++#endif /* CONFIG_PPC64 */
++}
++
++
++#define FEBRUARY 2
++#define STARTOFTIME 1970
++#define SECDAY 86400L
++#define SECYR (SECDAY * 365)
++#define leapyear(year) ((year) % 4 == 0 && \
++ ((year) % 100 != 0 || (year) % 400 == 0))
++#define days_in_year(a) (leapyear(a) ? 366 : 365)
++#define days_in_month(a) (month_days[(a) - 1])
++
++static int month_days[12] = {
++ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
++};
++
++/*
++ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
++ */
++void GregorianDay(struct rtc_time * tm)
++{
++ int leapsToDate;
++ int lastYear;
++ int day;
++ int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
++
++ lastYear = tm->tm_year - 1;
++
++ /*
++ * Number of leap corrections to apply up to end of last year
++ */
++ leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400;
++
++ /*
++ * This year is a leap year if it is divisible by 4 except when it is
++ * divisible by 100 unless it is divisible by 400
++ *
++ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was
++ */
++ day = tm->tm_mon > 2 && leapyear(tm->tm_year);
++
++ day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +
++ tm->tm_mday;
++
++ tm->tm_wday = day % 7;
++}
++
++void to_tm(int tim, struct rtc_time * tm)
++{
++ register int i;
++ register long hms, day;
++
++ day = tim / SECDAY;
++ hms = tim % SECDAY;
++
++ /* Hours, minutes, seconds are easy */
++ tm->tm_hour = hms / 3600;
++ tm->tm_min = (hms % 3600) / 60;
++ tm->tm_sec = (hms % 3600) % 60;
++
++ /* Number of years in days */
++ for (i = STARTOFTIME; day >= days_in_year(i); i++)
++ day -= days_in_year(i);
++ tm->tm_year = i;
++
++ /* Number of months in days left */
++ if (leapyear(tm->tm_year))
++ days_in_month(FEBRUARY) = 29;
++ for (i = 1; day >= days_in_month(i); i++)
++ day -= days_in_month(i);
++ days_in_month(FEBRUARY) = 28;
++ tm->tm_mon = i;
++
++ /* Days are what is left over (+1) from all that. */
++ tm->tm_mday = day + 1;
++
++ /*
++ * Determine the day of week
++ */
++ GregorianDay(tm);
++}
++
++/* Auxiliary function to compute scaling factors */
++/* Actually the choice of a timebase running at 1/4 the of the bus
++ * frequency giving resolution of a few tens of nanoseconds is quite nice.
++ * It makes this computation very precise (27-28 bits typically) which
++ * is optimistic considering the stability of most processor clock
++ * oscillators and the precision with which the timebase frequency
++ * is measured but does not harm.
++ */
++unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale)
++{
++ unsigned mlt=0, tmp, err;
++ /* No concern for performance, it's done once: use a stupid
++ * but safe and compact method to find the multiplier.
++ */
++
++ for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {
++ if (mulhwu(inscale, mlt|tmp) < outscale)
++ mlt |= tmp;
++ }
++
++ /* We might still be off by 1 for the best approximation.
++ * A side effect of this is that if outscale is too large
++ * the returned value will be zero.
++ * Many corner cases have been checked and seem to work,
++ * some might have been forgotten in the test however.
++ */
++
++ err = inscale * (mlt+1);
++ if (err <= inscale/2)
++ mlt++;
++ return mlt;
++}
++
++/*
++ * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit
++ * result.
++ */
++void div128_by_32(u64 dividend_high, u64 dividend_low,
++ unsigned divisor, struct div_result *dr)
++{
++ unsigned long a, b, c, d;
++ unsigned long w, x, y, z;
++ u64 ra, rb, rc;
++
++ a = dividend_high >> 32;
++ b = dividend_high & 0xffffffff;
++ c = dividend_low >> 32;
++ d = dividend_low & 0xffffffff;
++
++ w = a / divisor;
++ ra = ((u64)(a - (w * divisor)) << 32) + b;
++
++ rb = ((u64) do_div(ra, divisor) << 32) + c;
++ x = ra;
++
++ rc = ((u64) do_div(rb, divisor) << 32) + d;
++ y = rb;
++
++ do_div(rc, divisor);
++ z = rc;
++
++ dr->result_high = ((u64)w << 32) + x;
++ dr->result_low = ((u64)y << 32) + z;
++
++}
+diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/traps.c
+@@ -0,0 +1,1101 @@
++/*
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.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.
++ *
++ * Modified by Cort Dougan (cort at cs.nmt.edu)
++ * and Paul Mackerras (paulus at samba.org)
++ */
++
++/*
++ * This file handles the architecture-dependent parts of hardware exceptions
++ */
++
++#include <linux/config.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/prctl.h>
++#include <linux/delay.h>
++#include <linux/kprobes.h>
++
++#include <asm/kdebug.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/machdep.h>
++#include <asm/rtas.h>
++#include <asm/xmon.h>
++#include <asm/pmc.h>
++#ifdef CONFIG_PPC32
++#include <asm/reg.h>
++#endif
++#ifdef CONFIG_PMAC_BACKLIGHT
++#include <asm/backlight.h>
++#endif
++#ifdef CONFIG_PPC64
++#include <asm/firmware.h>
++#include <asm/processor.h>
++#include <asm/systemcfg.h>
++#endif
++
++#ifdef CONFIG_PPC64 /* XXX */
++#define _IO_BASE pci_io_base
++#endif
++
++#ifdef CONFIG_DEBUGGER
++int (*__debugger)(struct pt_regs *regs);
++int (*__debugger_ipi)(struct pt_regs *regs);
++int (*__debugger_bpt)(struct pt_regs *regs);
++int (*__debugger_sstep)(struct pt_regs *regs);
++int (*__debugger_iabr_match)(struct pt_regs *regs);
++int (*__debugger_dabr_match)(struct pt_regs *regs);
++int (*__debugger_fault_handler)(struct pt_regs *regs);
++
++EXPORT_SYMBOL(__debugger);
++EXPORT_SYMBOL(__debugger_ipi);
++EXPORT_SYMBOL(__debugger_bpt);
++EXPORT_SYMBOL(__debugger_sstep);
++EXPORT_SYMBOL(__debugger_iabr_match);
++EXPORT_SYMBOL(__debugger_dabr_match);
++EXPORT_SYMBOL(__debugger_fault_handler);
++#endif
++
++struct notifier_block *powerpc_die_chain;
++static DEFINE_SPINLOCK(die_notifier_lock);
++
++int register_die_notifier(struct notifier_block *nb)
++{
++ int err = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&die_notifier_lock, flags);
++ err = notifier_chain_register(&powerpc_die_chain, nb);
++ spin_unlock_irqrestore(&die_notifier_lock, flags);
++ return err;
++}
++
++/*
++ * Trap & Exception support
++ */
++
++static DEFINE_SPINLOCK(die_lock);
++
++int die(const char *str, struct pt_regs *regs, long err)
++{
++ static int die_counter;
++ int nl = 0;
++
++ if (debugger(regs))
++ return 1;
++
++ console_verbose();
++ spin_lock_irq(&die_lock);
++ bust_spinlocks(1);
++#ifdef CONFIG_PMAC_BACKLIGHT
++ if (_machine == _MACH_Pmac) {
++ set_backlight_enable(1);
++ set_backlight_level(BACKLIGHT_MAX);
++ }
++#endif
++ printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
++#ifdef CONFIG_PREEMPT
++ printk("PREEMPT ");
++ nl = 1;
++#endif
++#ifdef CONFIG_SMP
++ printk("SMP NR_CPUS=%d ", NR_CPUS);
++ nl = 1;
++#endif
++#ifdef CONFIG_DEBUG_PAGEALLOC
++ printk("DEBUG_PAGEALLOC ");
++ nl = 1;
++#endif
++#ifdef CONFIG_NUMA
++ printk("NUMA ");
++ nl = 1;
++#endif
++#ifdef CONFIG_PPC64
++ switch (systemcfg->platform) {
++ case PLATFORM_PSERIES:
++ printk("PSERIES ");
++ nl = 1;
++ break;
++ case PLATFORM_PSERIES_LPAR:
++ printk("PSERIES LPAR ");
++ nl = 1;
++ break;
++ case PLATFORM_ISERIES_LPAR:
++ printk("ISERIES LPAR ");
++ nl = 1;
++ break;
++ case PLATFORM_POWERMAC:
++ printk("POWERMAC ");
++ nl = 1;
++ break;
++ case PLATFORM_BPA:
++ printk("BPA ");
++ nl = 1;
++ break;
++ }
++#endif
++ if (nl)
++ printk("\n");
++ print_modules();
++ show_regs(regs);
++ bust_spinlocks(0);
++ spin_unlock_irq(&die_lock);
++
++ if (in_interrupt())
++ panic("Fatal exception in interrupt");
++
++ if (panic_on_oops) {
++#ifdef CONFIG_PPC64
++ printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
++ ssleep(5);
++#endif
++ panic("Fatal exception");
++ }
++ do_exit(err);
++
++ return 0;
++}
++
++void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
++{
++ siginfo_t info;
++
++ if (!user_mode(regs)) {
++ if (die("Exception in kernel mode", regs, signr))
++ return;
++ }
++
++ memset(&info, 0, sizeof(info));
++ info.si_signo = signr;
++ info.si_code = code;
++ info.si_addr = (void __user *) addr;
++ force_sig_info(signr, &info, current);
++
++ /*
++ * Init gets no signals that it doesn't have a handler for.
++ * That's all very well, but if it has caused a synchronous
++ * exception and we ignore the resulting signal, it will just
++ * generate the same exception over and over again and we get
++ * nowhere. Better to kill it and let the kernel panic.
++ */
++ if (current->pid == 1) {
++ __sighandler_t handler;
++
++ spin_lock_irq(¤t->sighand->siglock);
++ handler = current->sighand->action[signr-1].sa.sa_handler;
++ spin_unlock_irq(¤t->sighand->siglock);
++ if (handler == SIG_DFL) {
++ /* init has generated a synchronous exception
++ and it doesn't have a handler for the signal */
++ printk(KERN_CRIT "init has generated signal %d "
++ "but has no handler for it\n", signr);
++ do_exit(signr);
++ }
++ }
++}
++
++#ifdef CONFIG_PPC64
++void system_reset_exception(struct pt_regs *regs)
++{
++ /* See if any machine dependent calls */
++ if (ppc_md.system_reset_exception)
++ ppc_md.system_reset_exception(regs);
++
++ die("System Reset", regs, SIGABRT);
++
++ /* Must die if the interrupt is not recoverable */
++ if (!(regs->msr & MSR_RI))
++ panic("Unrecoverable System Reset");
++
++ /* What should we do here? We could issue a shutdown or hard reset. */
++}
++#endif
++
++/*
++ * I/O accesses can cause machine checks on powermacs.
++ * Check if the NIP corresponds to the address of a sync
++ * instruction for which there is an entry in the exception
++ * table.
++ * Note that the 601 only takes a machine check on TEA
++ * (transfer error ack) signal assertion, and does not
++ * set any of the top 16 bits of SRR1.
++ * -- paulus.
++ */
++static inline int check_io_access(struct pt_regs *regs)
++{
++#ifdef CONFIG_PPC_PMAC
++ unsigned long msr = regs->msr;
++ const struct exception_table_entry *entry;
++ unsigned int *nip = (unsigned int *)regs->nip;
++
++ if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000)))
++ && (entry = search_exception_tables(regs->nip)) != NULL) {
++ /*
++ * Check that it's a sync instruction, or somewhere
++ * in the twi; isync; nop sequence that inb/inw/inl uses.
++ * As the address is in the exception table
++ * we should be able to read the instr there.
++ * For the debug message, we look at the preceding
++ * load or store.
++ */
++ if (*nip == 0x60000000) /* nop */
++ nip -= 2;
++ else if (*nip == 0x4c00012c) /* isync */
++ --nip;
++ if (*nip == 0x7c0004ac || (*nip >> 26) == 3) {
++ /* sync or twi */
++ unsigned int rb;
++
++ --nip;
++ rb = (*nip >> 11) & 0x1f;
++ printk(KERN_DEBUG "%s bad port %lx at %p\n",
++ (*nip & 0x100)? "OUT to": "IN from",
++ regs->gpr[rb] - _IO_BASE, nip);
++ regs->msr |= MSR_RI;
++ regs->nip = entry->fixup;
++ return 1;
++ }
++ }
++#endif /* CONFIG_PPC_PMAC */
++ return 0;
++}
++
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++/* On 4xx, the reason for the machine check or program exception
++ is in the ESR. */
++#define get_reason(regs) ((regs)->dsisr)
++#ifndef CONFIG_FSL_BOOKE
++#define get_mc_reason(regs) ((regs)->dsisr)
++#else
++#define get_mc_reason(regs) (mfspr(SPRN_MCSR))
++#endif
++#define REASON_FP ESR_FP
++#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
++#define REASON_PRIVILEGED ESR_PPR
++#define REASON_TRAP ESR_PTR
++
++/* single-step stuff */
++#define single_stepping(regs) (current->thread.dbcr0 & DBCR0_IC)
++#define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC)
++
++#else
++/* On non-4xx, the reason for the machine check or program
++ exception is in the MSR. */
++#define get_reason(regs) ((regs)->msr)
++#define get_mc_reason(regs) ((regs)->msr)
++#define REASON_FP 0x100000
++#define REASON_ILLEGAL 0x80000
++#define REASON_PRIVILEGED 0x40000
++#define REASON_TRAP 0x20000
++
++#define single_stepping(regs) ((regs)->msr & MSR_SE)
++#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
++#endif
++
++/*
++ * This is "fall-back" implementation for configurations
++ * which don't provide platform-specific machine check info
++ */
++void __attribute__ ((weak))
++platform_machine_check(struct pt_regs *regs)
++{
++}
++
++void machine_check_exception(struct pt_regs *regs)
++{
++#ifdef CONFIG_PPC64
++ int recover = 0;
++
++ /* See if any machine dependent calls */
++ if (ppc_md.machine_check_exception)
++ recover = ppc_md.machine_check_exception(regs);
++
++ if (recover)
++ return;
++#else
++ unsigned long reason = get_mc_reason(regs);
++
++ if (user_mode(regs)) {
++ regs->msr |= MSR_RI;
++ _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
++ return;
++ }
++
++#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
++ /* the qspan pci read routines can cause machine checks -- Cort */
++ bad_page_fault(regs, regs->dar, SIGBUS);
++ return;
++#endif
++
++ if (debugger_fault_handler(regs)) {
++ regs->msr |= MSR_RI;
++ return;
++ }
++
++ if (check_io_access(regs))
++ return;
++
++#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
++ if (reason & ESR_IMCP) {
++ printk("Instruction");
++ mtspr(SPRN_ESR, reason & ~ESR_IMCP);
++ } else
++ printk("Data");
++ printk(" machine check in kernel mode.\n");
++#elif defined(CONFIG_440A)
++ printk("Machine check in kernel mode.\n");
++ if (reason & ESR_IMCP){
++ printk("Instruction Synchronous Machine Check exception\n");
++ mtspr(SPRN_ESR, reason & ~ESR_IMCP);
++ }
++ else {
++ u32 mcsr = mfspr(SPRN_MCSR);
++ if (mcsr & MCSR_IB)
++ printk("Instruction Read PLB Error\n");
++ if (mcsr & MCSR_DRB)
++ printk("Data Read PLB Error\n");
++ if (mcsr & MCSR_DWB)
++ printk("Data Write PLB Error\n");
++ if (mcsr & MCSR_TLBP)
++ printk("TLB Parity Error\n");
++ if (mcsr & MCSR_ICP){
++ flush_instruction_cache();
++ printk("I-Cache Parity Error\n");
++ }
++ if (mcsr & MCSR_DCSP)
++ printk("D-Cache Search Parity Error\n");
++ if (mcsr & MCSR_DCFP)
++ printk("D-Cache Flush Parity Error\n");
++ if (mcsr & MCSR_IMPE)
++ printk("Machine Check exception is imprecise\n");
++
++ /* Clear MCSR */
++ mtspr(SPRN_MCSR, mcsr);
++ }
++#elif defined (CONFIG_E500)
++ printk("Machine check in kernel mode.\n");
++ printk("Caused by (from MCSR=%lx): ", reason);
++
++ if (reason & MCSR_MCP)
++ printk("Machine Check Signal\n");
++ if (reason & MCSR_ICPERR)
++ printk("Instruction Cache Parity Error\n");
++ if (reason & MCSR_DCP_PERR)
++ printk("Data Cache Push Parity Error\n");
++ if (reason & MCSR_DCPERR)
++ printk("Data Cache Parity Error\n");
++ if (reason & MCSR_GL_CI)
++ printk("Guarded Load or Cache-Inhibited stwcx.\n");
++ if (reason & MCSR_BUS_IAERR)
++ printk("Bus - Instruction Address Error\n");
++ if (reason & MCSR_BUS_RAERR)
++ printk("Bus - Read Address Error\n");
++ if (reason & MCSR_BUS_WAERR)
++ printk("Bus - Write Address Error\n");
++ if (reason & MCSR_BUS_IBERR)
++ printk("Bus - Instruction Data Error\n");
++ if (reason & MCSR_BUS_RBERR)
++ printk("Bus - Read Data Bus Error\n");
++ if (reason & MCSR_BUS_WBERR)
++ printk("Bus - Read Data Bus Error\n");
++ if (reason & MCSR_BUS_IPERR)
++ printk("Bus - Instruction Parity Error\n");
++ if (reason & MCSR_BUS_RPERR)
++ printk("Bus - Read Parity Error\n");
++#elif defined (CONFIG_E200)
++ printk("Machine check in kernel mode.\n");
++ printk("Caused by (from MCSR=%lx): ", reason);
++
++ if (reason & MCSR_MCP)
++ printk("Machine Check Signal\n");
++ if (reason & MCSR_CP_PERR)
++ printk("Cache Push Parity Error\n");
++ if (reason & MCSR_CPERR)
++ printk("Cache Parity Error\n");
++ if (reason & MCSR_EXCP_ERR)
++ printk("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n");
++ if (reason & MCSR_BUS_IRERR)
++ printk("Bus - Read Bus Error on instruction fetch\n");
++ if (reason & MCSR_BUS_DRERR)
++ printk("Bus - Read Bus Error on data load\n");
++ if (reason & MCSR_BUS_WRERR)
++ printk("Bus - Write Bus Error on buffered store or cache line push\n");
++#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */
++ printk("Machine check in kernel mode.\n");
++ printk("Caused by (from SRR1=%lx): ", reason);
++ switch (reason & 0x601F0000) {
++ case 0x80000:
++ printk("Machine check signal\n");
++ break;
++ case 0: /* for 601 */
++ case 0x40000:
++ case 0x140000: /* 7450 MSS error and TEA */
++ printk("Transfer error ack signal\n");
++ break;
++ case 0x20000:
++ printk("Data parity error signal\n");
++ break;
++ case 0x10000:
++ printk("Address parity error signal\n");
++ break;
++ case 0x20000000:
++ printk("L1 Data Cache error\n");
++ break;
++ case 0x40000000:
++ printk("L1 Instruction Cache error\n");
++ break;
++ case 0x00100000:
++ printk("L2 data cache parity error\n");
++ break;
++ default:
++ printk("Unknown values in msr\n");
++ }
++#endif /* CONFIG_4xx */
++
++ /*
++ * Optional platform-provided routine to print out
++ * additional info, e.g. bus error registers.
++ */
++ platform_machine_check(regs);
++#endif /* CONFIG_PPC64 */
++
++ if (debugger_fault_handler(regs))
++ return;
++ die("Machine check", regs, SIGBUS);
++
++ /* Must die if the interrupt is not recoverable */
++ if (!(regs->msr & MSR_RI))
++ panic("Unrecoverable Machine check");
++}
++
++void SMIException(struct pt_regs *regs)
++{
++ die("System Management Interrupt", regs, SIGABRT);
++}
++
++void unknown_exception(struct pt_regs *regs)
++{
++ printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
++ regs->nip, regs->msr, regs->trap);
++
++ _exception(SIGTRAP, regs, 0, 0);
++}
++
++void instruction_breakpoint_exception(struct pt_regs *regs)
++{
++ if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5,
++ 5, SIGTRAP) == NOTIFY_STOP)
++ return;
++ if (debugger_iabr_match(regs))
++ return;
++ _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
++}
++
++void RunModeException(struct pt_regs *regs)
++{
++ _exception(SIGTRAP, regs, 0, 0);
++}
++
++void __kprobes single_step_exception(struct pt_regs *regs)
++{
++ regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */
++
++ if (notify_die(DIE_SSTEP, "single_step", regs, 5,
++ 5, SIGTRAP) == NOTIFY_STOP)
++ return;
++ if (debugger_sstep(regs))
++ return;
++
++ _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
++}
++
++/*
++ * After we have successfully emulated an instruction, we have to
++ * check if the instruction was being single-stepped, and if so,
++ * pretend we got a single-step exception. This was pointed out
++ * by Kumar Gala. -- paulus
++ */
++static void emulate_single_step(struct pt_regs *regs)
++{
++ if (single_stepping(regs)) {
++ clear_single_step(regs);
++ _exception(SIGTRAP, regs, TRAP_TRACE, 0);
++ }
++}
++
++static void parse_fpe(struct pt_regs *regs)
++{
++ int code = 0;
++ unsigned long fpscr;
++
++ flush_fp_to_thread(current);
++
++ fpscr = current->thread.fpscr.val;
++
++ /* Invalid operation */
++ if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
++ code = FPE_FLTINV;
++
++ /* Overflow */
++ else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX))
++ code = FPE_FLTOVF;
++
++ /* Underflow */
++ else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX))
++ code = FPE_FLTUND;
++
++ /* Divide by zero */
++ else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX))
++ code = FPE_FLTDIV;
++
++ /* Inexact result */
++ else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX))
++ code = FPE_FLTRES;
++
++ _exception(SIGFPE, regs, code, regs->nip);
++}
++
++/*
++ * Illegal instruction emulation support. Originally written to
++ * provide the PVR to user applications using the mfspr rd, PVR.
++ * Return non-zero if we can't emulate, or -EFAULT if the associated
++ * memory access caused an access fault. Return zero on success.
++ *
++ * There are a couple of ways to do this, either "decode" the instruction
++ * or directly match lots of bits. In this case, matching lots of
++ * bits is faster and easier.
++ *
++ */
++#define INST_MFSPR_PVR 0x7c1f42a6
++#define INST_MFSPR_PVR_MASK 0xfc1fffff
++
++#define INST_DCBA 0x7c0005ec
++#define INST_DCBA_MASK 0x7c0007fe
++
++#define INST_MCRXR 0x7c000400
++#define INST_MCRXR_MASK 0x7c0007fe
++
++#define INST_STRING 0x7c00042a
++#define INST_STRING_MASK 0x7c0007fe
++#define INST_STRING_GEN_MASK 0x7c00067e
++#define INST_LSWI 0x7c0004aa
++#define INST_LSWX 0x7c00042a
++#define INST_STSWI 0x7c0005aa
++#define INST_STSWX 0x7c00052a
++
++static int emulate_string_inst(struct pt_regs *regs, u32 instword)
++{
++ u8 rT = (instword >> 21) & 0x1f;
++ u8 rA = (instword >> 16) & 0x1f;
++ u8 NB_RB = (instword >> 11) & 0x1f;
++ u32 num_bytes;
++ unsigned long EA;
++ int pos = 0;
++
++ /* Early out if we are an invalid form of lswx */
++ if ((instword & INST_STRING_MASK) == INST_LSWX)
++ if ((rT == rA) || (rT == NB_RB))
++ return -EINVAL;
++
++ EA = (rA == 0) ? 0 : regs->gpr[rA];
++
++ switch (instword & INST_STRING_MASK) {
++ case INST_LSWX:
++ case INST_STSWX:
++ EA += NB_RB;
++ num_bytes = regs->xer & 0x7f;
++ break;
++ case INST_LSWI:
++ case INST_STSWI:
++ num_bytes = (NB_RB == 0) ? 32 : NB_RB;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ while (num_bytes != 0)
++ {
++ u8 val;
++ u32 shift = 8 * (3 - (pos & 0x3));
++
++ switch ((instword & INST_STRING_MASK)) {
++ case INST_LSWX:
++ case INST_LSWI:
++ if (get_user(val, (u8 __user *)EA))
++ return -EFAULT;
++ /* first time updating this reg,
++ * zero it out */
++ if (pos == 0)
++ regs->gpr[rT] = 0;
++ regs->gpr[rT] |= val << shift;
++ break;
++ case INST_STSWI:
++ case INST_STSWX:
++ val = regs->gpr[rT] >> shift;
++ if (put_user(val, (u8 __user *)EA))
++ return -EFAULT;
++ break;
++ }
++ /* move EA to next address */
++ EA += 1;
++ num_bytes--;
++
++ /* manage our position within the register */
++ if (++pos == 4) {
++ pos = 0;
++ if (++rT == 32)
++ rT = 0;
++ }
++ }
++
++ return 0;
++}
++
++static int emulate_instruction(struct pt_regs *regs)
++{
++ u32 instword;
++ u32 rd;
++
++ if (!user_mode(regs))
++ return -EINVAL;
++ CHECK_FULL_REGS(regs);
++
++ if (get_user(instword, (u32 __user *)(regs->nip)))
++ return -EFAULT;
++
++ /* Emulate the mfspr rD, PVR. */
++ if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
++ rd = (instword >> 21) & 0x1f;
++ regs->gpr[rd] = mfspr(SPRN_PVR);
++ return 0;
++ }
++
++ /* Emulating the dcba insn is just a no-op. */
++ if ((instword & INST_DCBA_MASK) == INST_DCBA)
++ return 0;
++
++ /* Emulate the mcrxr insn. */
++ if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
++ int shift = (instword >> 21) & 0x1c;
++ unsigned long msk = 0xf0000000UL >> shift;
++
++ regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
++ regs->xer &= ~0xf0000000UL;
++ return 0;
++ }
++
++ /* Emulate load/store string insn. */
++ if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
++ return emulate_string_inst(regs, instword);
++
++ return -EINVAL;
++}
++
++/*
++ * Look through the list of trap instructions that are used for BUG(),
++ * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
++ * that the exception was caused by a trap instruction of some kind.
++ * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
++ * otherwise.
++ */
++extern struct bug_entry __start___bug_table[], __stop___bug_table[];
++
++#ifndef CONFIG_MODULES
++#define module_find_bug(x) NULL
++#endif
++
++struct bug_entry *find_bug(unsigned long bugaddr)
++{
++ struct bug_entry *bug;
++
++ for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
++ if (bugaddr == bug->bug_addr)
++ return bug;
++ return module_find_bug(bugaddr);
++}
++
++static int check_bug_trap(struct pt_regs *regs)
++{
++ struct bug_entry *bug;
++ unsigned long addr;
++
++ if (regs->msr & MSR_PR)
++ return 0; /* not in kernel */
++ addr = regs->nip; /* address of trap instruction */
++ if (addr < PAGE_OFFSET)
++ return 0;
++ bug = find_bug(regs->nip);
++ if (bug == NULL)
++ return 0;
++ if (bug->line & BUG_WARNING_TRAP) {
++ /* this is a WARN_ON rather than BUG/BUG_ON */
++#ifdef CONFIG_XMON
++ xmon_printf(KERN_ERR "Badness in %s at %s:%d\n",
++ bug->function, bug->file,
++ bug->line & ~BUG_WARNING_TRAP);
++#endif /* CONFIG_XMON */
++ printk(KERN_ERR "Badness in %s at %s:%d\n",
++ bug->function, bug->file,
++ bug->line & ~BUG_WARNING_TRAP);
++ dump_stack();
++ return 1;
++ }
++#ifdef CONFIG_XMON
++ xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
++ bug->function, bug->file, bug->line);
++ xmon(regs);
++#endif /* CONFIG_XMON */
++ printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
++ bug->function, bug->file, bug->line);
++
++ return 0;
++}
++
++void __kprobes program_check_exception(struct pt_regs *regs)
++{
++ unsigned int reason = get_reason(regs);
++ extern int do_mathemu(struct pt_regs *regs);
++
++#ifdef CONFIG_MATH_EMULATION
++ /* (reason & REASON_ILLEGAL) would be the obvious thing here,
++ * but there seems to be a hardware bug on the 405GP (RevD)
++ * that means ESR is sometimes set incorrectly - either to
++ * ESR_DST (!?) or 0. In the process of chasing this with the
++ * hardware people - not sure if it can happen on any illegal
++ * instruction or only on FP instructions, whether there is a
++ * pattern to occurences etc. -dgibson 31/Mar/2003 */
++ if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) {
++ emulate_single_step(regs);
++ return;
++ }
++#endif /* CONFIG_MATH_EMULATION */
++
++ if (reason & REASON_FP) {
++ /* IEEE FP exception */
++ parse_fpe(regs);
++ return;
++ }
++ if (reason & REASON_TRAP) {
++ /* trap exception */
++ if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
++ == NOTIFY_STOP)
++ return;
++ if (debugger_bpt(regs))
++ return;
++ if (check_bug_trap(regs)) {
++ regs->nip += 4;
++ return;
++ }
++ _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
++ return;
++ }
++
++ /* Try to emulate it if we should. */
++ if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
++ switch (emulate_instruction(regs)) {
++ case 0:
++ regs->nip += 4;
++ emulate_single_step(regs);
++ return;
++ case -EFAULT:
++ _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
++ return;
++ }
++ }
++
++ if (reason & REASON_PRIVILEGED)
++ _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
++ else
++ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
++}
++
++void alignment_exception(struct pt_regs *regs)
++{
++ int fixed;
++
++ fixed = fix_alignment(regs);
++
++ if (fixed == 1) {
++ regs->nip += 4; /* skip over emulated instruction */
++ emulate_single_step(regs);
++ return;
++ }
++
++ /* Operand address was bad */
++ if (fixed == -EFAULT) {
++ if (user_mode(regs))
++ _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
++ else
++ /* Search exception table */
++ bad_page_fault(regs, regs->dar, SIGSEGV);
++ return;
++ }
++ _exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
++}
++
++void StackOverflow(struct pt_regs *regs)
++{
++ printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
++ current, regs->gpr[1]);
++ debugger(regs);
++ show_regs(regs);
++ panic("kernel stack overflow");
++}
++
++void nonrecoverable_exception(struct pt_regs *regs)
++{
++ printk(KERN_ERR "Non-recoverable exception at PC=%lx MSR=%lx\n",
++ regs->nip, regs->msr);
++ debugger(regs);
++ die("nonrecoverable exception", regs, SIGKILL);
++}
++
++void trace_syscall(struct pt_regs *regs)
++{
++ printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n",
++ current, current->pid, regs->nip, regs->link, regs->gpr[0],
++ regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted());
++}
++
++void kernel_fp_unavailable_exception(struct pt_regs *regs)
++{
++ printk(KERN_EMERG "Unrecoverable FP Unavailable Exception "
++ "%lx at %lx\n", regs->trap, regs->nip);
++ die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
++}
++
++void altivec_unavailable_exception(struct pt_regs *regs)
++{
++#if !defined(CONFIG_ALTIVEC)
++ if (user_mode(regs)) {
++ /* A user program has executed an altivec instruction,
++ but this kernel doesn't support altivec. */
++ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
++ return;
++ }
++#endif
++ printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
++ "%lx at %lx\n", regs->trap, regs->nip);
++ die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
++}
++
++#ifdef CONFIG_PPC64
++extern perf_irq_t perf_irq;
++#endif
++
++#if defined(CONFIG_PPC64) || defined(CONFIG_E500)
++void performance_monitor_exception(struct pt_regs *regs)
++{
++ perf_irq(regs);
++}
++#endif
++
++#ifdef CONFIG_8xx
++void SoftwareEmulation(struct pt_regs *regs)
++{
++ extern int do_mathemu(struct pt_regs *);
++ extern int Soft_emulate_8xx(struct pt_regs *);
++ int errcode;
++
++ CHECK_FULL_REGS(regs);
++
++ if (!user_mode(regs)) {
++ debugger(regs);
++ die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
++ }
++
++#ifdef CONFIG_MATH_EMULATION
++ errcode = do_mathemu(regs);
++#else
++ errcode = Soft_emulate_8xx(regs);
++#endif
++ if (errcode) {
++ if (errcode > 0)
++ _exception(SIGFPE, regs, 0, 0);
++ else if (errcode == -EFAULT)
++ _exception(SIGSEGV, regs, 0, 0);
++ else
++ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
++ } else
++ emulate_single_step(regs);
++}
++#endif /* CONFIG_8xx */
++
++#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
++
++void DebugException(struct pt_regs *regs, unsigned long debug_status)
++{
++ if (debug_status & DBSR_IC) { /* instruction completion */
++ regs->msr &= ~MSR_DE;
++ if (user_mode(regs)) {
++ current->thread.dbcr0 &= ~DBCR0_IC;
++ } else {
++ /* Disable instruction completion */
++ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
++ /* Clear the instruction completion event */
++ mtspr(SPRN_DBSR, DBSR_IC);
++ if (debugger_sstep(regs))
++ return;
++ }
++ _exception(SIGTRAP, regs, TRAP_TRACE, 0);
++ }
++}
++#endif /* CONFIG_4xx || CONFIG_BOOKE */
++
++#if !defined(CONFIG_TAU_INT)
++void TAUException(struct pt_regs *regs)
++{
++ printk("TAU trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
++ regs->nip, regs->msr, regs->trap, print_tainted());
++}
++#endif /* CONFIG_INT_TAU */
++
++#ifdef CONFIG_ALTIVEC
++void altivec_assist_exception(struct pt_regs *regs)
++{
++ int err;
++
++ if (!user_mode(regs)) {
++ printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode"
++ " at %lx\n", regs->nip);
++ die("Kernel VMX/Altivec assist exception", regs, SIGILL);
++ }
++
++ flush_altivec_to_thread(current);
++
++ err = emulate_altivec(regs);
++ if (err == 0) {
++ regs->nip += 4; /* skip emulated instruction */
++ emulate_single_step(regs);
++ return;
++ }
++
++ if (err == -EFAULT) {
++ /* got an error reading the instruction */
++ _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
++ } else {
++ /* didn't recognize the instruction */
++ /* XXX quick hack for now: set the non-Java bit in the VSCR */
++ if (printk_ratelimit())
++ printk(KERN_ERR "Unrecognized altivec instruction "
++ "in %s at %lx\n", current->comm, regs->nip);
++ current->thread.vscr.u[3] |= 0x10000;
++ }
++}
++#endif /* CONFIG_ALTIVEC */
++
++#ifdef CONFIG_FSL_BOOKE
++void CacheLockingException(struct pt_regs *regs, unsigned long address,
++ unsigned long error_code)
++{
++ /* We treat cache locking instructions from the user
++ * as priv ops, in the future we could try to do
++ * something smarter
++ */
++ if (error_code & (ESR_DLK|ESR_ILK))
++ _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
++ return;
++}
++#endif /* CONFIG_FSL_BOOKE */
++
++#ifdef CONFIG_SPE
++void SPEFloatingPointException(struct pt_regs *regs)
++{
++ unsigned long spefscr;
++ int fpexc_mode;
++ int code = 0;
++
++ spefscr = current->thread.spefscr;
++ fpexc_mode = current->thread.fpexc_mode;
++
++ /* Hardware does not neccessarily set sticky
++ * underflow/overflow/invalid flags */
++ if ((spefscr & SPEFSCR_FOVF) && (fpexc_mode & PR_FP_EXC_OVF)) {
++ code = FPE_FLTOVF;
++ spefscr |= SPEFSCR_FOVFS;
++ }
++ else if ((spefscr & SPEFSCR_FUNF) && (fpexc_mode & PR_FP_EXC_UND)) {
++ code = FPE_FLTUND;
++ spefscr |= SPEFSCR_FUNFS;
++ }
++ else if ((spefscr & SPEFSCR_FDBZ) && (fpexc_mode & PR_FP_EXC_DIV))
++ code = FPE_FLTDIV;
++ else if ((spefscr & SPEFSCR_FINV) && (fpexc_mode & PR_FP_EXC_INV)) {
++ code = FPE_FLTINV;
++ spefscr |= SPEFSCR_FINVS;
++ }
++ else if ((spefscr & (SPEFSCR_FG | SPEFSCR_FX)) && (fpexc_mode & PR_FP_EXC_RES))
++ code = FPE_FLTRES;
++
++ current->thread.spefscr = spefscr;
++
++ _exception(SIGFPE, regs, code, regs->nip);
++ return;
++}
++#endif
++
++/*
++ * We enter here if we get an unrecoverable exception, that is, one
++ * that happened at a point where the RI (recoverable interrupt) bit
++ * in the MSR is 0. This indicates that SRR0/1 are live, and that
++ * we therefore lost state by taking this exception.
++ */
++void unrecoverable_exception(struct pt_regs *regs)
++{
++ printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n",
++ regs->trap, regs->nip);
++ die("Unrecoverable exception", regs, SIGABRT);
++}
++
++#ifdef CONFIG_BOOKE_WDT
++/*
++ * Default handler for a Watchdog exception,
++ * spins until a reboot occurs
++ */
++void __attribute__ ((weak)) WatchdogHandler(struct pt_regs *regs)
++{
++ /* Generic WatchdogHandler, implement your own */
++ mtspr(SPRN_TCR, mfspr(SPRN_TCR)&(~TCR_WIE));
++ return;
++}
++
++void WatchdogException(struct pt_regs *regs)
++{
++ printk (KERN_EMERG "PowerPC Book-E Watchdog Exception\n");
++ WatchdogHandler(regs);
++}
++#endif
++
++/*
++ * We enter here if we discover during exception entry that we are
++ * running in supervisor mode with a userspace value in the stack pointer.
++ */
++void kernel_bad_stack(struct pt_regs *regs)
++{
++ printk(KERN_EMERG "Bad kernel stack pointer %lx at %lx\n",
++ regs->gpr[1], regs->nip);
++ die("Bad kernel stack pointer", regs, SIGABRT);
++}
++
++void __init trap_init(void)
++{
++}
+diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/vecemu.c
+@@ -0,0 +1,345 @@
++/*
++ * Routines to emulate some Altivec/VMX instructions, specifically
++ * those that can trap when given denormalized operands in Java mode.
++ */
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <asm/ptrace.h>
++#include <asm/processor.h>
++#include <asm/uaccess.h>
++
++/* Functions in vector.S */
++extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
++extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b);
++extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
++extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
++extern void vrefp(vector128 *dst, vector128 *src);
++extern void vrsqrtefp(vector128 *dst, vector128 *src);
++extern void vexptep(vector128 *dst, vector128 *src);
++
++static unsigned int exp2s[8] = {
++ 0x800000,
++ 0x8b95c2,
++ 0x9837f0,
++ 0xa5fed7,
++ 0xb504f3,
++ 0xc5672a,
++ 0xd744fd,
++ 0xeac0c7
++};
++
++/*
++ * Computes an estimate of 2^x. The `s' argument is the 32-bit
++ * single-precision floating-point representation of x.
++ */
++static unsigned int eexp2(unsigned int s)
++{
++ int exp, pwr;
++ unsigned int mant, frac;
++
++ /* extract exponent field from input */
++ exp = ((s >> 23) & 0xff) - 127;
++ if (exp > 7) {
++ /* check for NaN input */
++ if (exp == 128 && (s & 0x7fffff) != 0)
++ return s | 0x400000; /* return QNaN */
++ /* 2^-big = 0, 2^+big = +Inf */
++ return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */
++ }
++ if (exp < -23)
++ return 0x3f800000; /* 1.0 */
++
++ /* convert to fixed point integer in 9.23 representation */
++ pwr = (s & 0x7fffff) | 0x800000;
++ if (exp > 0)
++ pwr <<= exp;
++ else
++ pwr >>= -exp;
++ if (s & 0x80000000)
++ pwr = -pwr;
++
++ /* extract integer part, which becomes exponent part of result */
++ exp = (pwr >> 23) + 126;
++ if (exp >= 254)
++ return 0x7f800000;
++ if (exp < -23)
++ return 0;
++
++ /* table lookup on top 3 bits of fraction to get mantissa */
++ mant = exp2s[(pwr >> 20) & 7];
++
++ /* linear interpolation using remaining 20 bits of fraction */
++ asm("mulhwu %0,%1,%2" : "=r" (frac)
++ : "r" (pwr << 12), "r" (0x172b83ff));
++ asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant));
++ mant += frac;
++
++ if (exp >= 0)
++ return mant + (exp << 23);
++
++ /* denormalized result */
++ exp = -exp;
++ mant += 1 << (exp - 1);
++ return mant >> exp;
++}
++
++/*
++ * Computes an estimate of log_2(x). The `s' argument is the 32-bit
++ * single-precision floating-point representation of x.
++ */
++static unsigned int elog2(unsigned int s)
++{
++ int exp, mant, lz, frac;
++
++ exp = s & 0x7f800000;
++ mant = s & 0x7fffff;
++ if (exp == 0x7f800000) { /* Inf or NaN */
++ if (mant != 0)
++ s |= 0x400000; /* turn NaN into QNaN */
++ return s;
++ }
++ if ((exp | mant) == 0) /* +0 or -0 */
++ return 0xff800000; /* return -Inf */
++
++ if (exp == 0) {
++ /* denormalized */
++ asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant));
++ mant <<= lz - 8;
++ exp = (-118 - lz) << 23;
++ } else {
++ mant |= 0x800000;
++ exp -= 127 << 23;
++ }
++
++ if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */
++ exp |= 0x400000; /* 0.5 * 2^23 */
++ asm("mulhwu %0,%1,%2" : "=r" (mant)
++ : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */
++ }
++ if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */
++ exp |= 0x200000; /* 0.25 * 2^23 */
++ asm("mulhwu %0,%1,%2" : "=r" (mant)
++ : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */
++ }
++ if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */
++ exp |= 0x100000; /* 0.125 * 2^23 */
++ asm("mulhwu %0,%1,%2" : "=r" (mant)
++ : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */
++ }
++ if (mant > 0x800000) { /* 1.0 * 2^23 */
++ /* calculate (mant - 1) * 1.381097463 */
++ /* 1.381097463 == 0.125 / (2^0.125 - 1) */
++ asm("mulhwu %0,%1,%2" : "=r" (frac)
++ : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a));
++ exp += frac;
++ }
++ s = exp & 0x80000000;
++ if (exp != 0) {
++ if (s)
++ exp = -exp;
++ asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp));
++ lz = 8 - lz;
++ if (lz > 0)
++ exp >>= lz;
++ else if (lz < 0)
++ exp <<= -lz;
++ s += ((lz + 126) << 23) + exp;
++ }
++ return s;
++}
++
++#define VSCR_SAT 1
++
++static int ctsxs(unsigned int x, int scale, unsigned int *vscrp)
++{
++ int exp, mant;
++
++ exp = (x >> 23) & 0xff;
++ mant = x & 0x7fffff;
++ if (exp == 255 && mant != 0)
++ return 0; /* NaN -> 0 */
++ exp = exp - 127 + scale;
++ if (exp < 0)
++ return 0; /* round towards zero */
++ if (exp >= 31) {
++ /* saturate, unless the result would be -2^31 */
++ if (x + (scale << 23) != 0xcf000000)
++ *vscrp |= VSCR_SAT;
++ return (x & 0x80000000)? 0x80000000: 0x7fffffff;
++ }
++ mant |= 0x800000;
++ mant = (mant << 7) >> (30 - exp);
++ return (x & 0x80000000)? -mant: mant;
++}
++
++static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp)
++{
++ int exp;
++ unsigned int mant;
++
++ exp = (x >> 23) & 0xff;
++ mant = x & 0x7fffff;
++ if (exp == 255 && mant != 0)
++ return 0; /* NaN -> 0 */
++ exp = exp - 127 + scale;
++ if (exp < 0)
++ return 0; /* round towards zero */
++ if (x & 0x80000000) {
++ /* negative => saturate to 0 */
++ *vscrp |= VSCR_SAT;
++ return 0;
++ }
++ if (exp >= 32) {
++ /* saturate */
++ *vscrp |= VSCR_SAT;
++ return 0xffffffff;
++ }
++ mant |= 0x800000;
++ mant = (mant << 8) >> (31 - exp);
++ return mant;
++}
++
++/* Round to floating integer, towards 0 */
++static unsigned int rfiz(unsigned int x)
++{
++ int exp;
++
++ exp = ((x >> 23) & 0xff) - 127;
++ if (exp == 128 && (x & 0x7fffff) != 0)
++ return x | 0x400000; /* NaN -> make it a QNaN */
++ if (exp >= 23)
++ return x; /* it's an integer already (or Inf) */
++ if (exp < 0)
++ return x & 0x80000000; /* |x| < 1.0 rounds to 0 */
++ return x & ~(0x7fffff >> exp);
++}
++
++/* Round to floating integer, towards +/- Inf */
++static unsigned int rfii(unsigned int x)
++{
++ int exp, mask;
++
++ exp = ((x >> 23) & 0xff) - 127;
++ if (exp == 128 && (x & 0x7fffff) != 0)
++ return x | 0x400000; /* NaN -> make it a QNaN */
++ if (exp >= 23)
++ return x; /* it's an integer already (or Inf) */
++ if ((x & 0x7fffffff) == 0)
++ return x; /* +/-0 -> +/-0 */
++ if (exp < 0)
++ /* 0 < |x| < 1.0 rounds to +/- 1.0 */
++ return (x & 0x80000000) | 0x3f800000;
++ mask = 0x7fffff >> exp;
++ /* mantissa overflows into exponent - that's OK,
++ it can't overflow into the sign bit */
++ return (x + mask) & ~mask;
++}
++
++/* Round to floating integer, to nearest */
++static unsigned int rfin(unsigned int x)
++{
++ int exp, half;
++
++ exp = ((x >> 23) & 0xff) - 127;
++ if (exp == 128 && (x & 0x7fffff) != 0)
++ return x | 0x400000; /* NaN -> make it a QNaN */
++ if (exp >= 23)
++ return x; /* it's an integer already (or Inf) */
++ if (exp < -1)
++ return x & 0x80000000; /* |x| < 0.5 -> +/-0 */
++ if (exp == -1)
++ /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */
++ return (x & 0x80000000) | 0x3f800000;
++ half = 0x400000 >> exp;
++ /* add 0.5 to the magnitude and chop off the fraction bits */
++ return (x + half) & ~(0x7fffff >> exp);
++}
++
++int emulate_altivec(struct pt_regs *regs)
++{
++ unsigned int instr, i;
++ unsigned int va, vb, vc, vd;
++ vector128 *vrs;
++
++ if (get_user(instr, (unsigned int __user *) regs->nip))
++ return -EFAULT;
++ if ((instr >> 26) != 4)
++ return -EINVAL; /* not an altivec instruction */
++ vd = (instr >> 21) & 0x1f;
++ va = (instr >> 16) & 0x1f;
++ vb = (instr >> 11) & 0x1f;
++ vc = (instr >> 6) & 0x1f;
++
++ vrs = current->thread.vr;
++ switch (instr & 0x3f) {
++ case 10:
++ switch (vc) {
++ case 0: /* vaddfp */
++ vaddfp(&vrs[vd], &vrs[va], &vrs[vb]);
++ break;
++ case 1: /* vsubfp */
++ vsubfp(&vrs[vd], &vrs[va], &vrs[vb]);
++ break;
++ case 4: /* vrefp */
++ vrefp(&vrs[vd], &vrs[vb]);
++ break;
++ case 5: /* vrsqrtefp */
++ vrsqrtefp(&vrs[vd], &vrs[vb]);
++ break;
++ case 6: /* vexptefp */
++ for (i = 0; i < 4; ++i)
++ vrs[vd].u[i] = eexp2(vrs[vb].u[i]);
++ break;
++ case 7: /* vlogefp */
++ for (i = 0; i < 4; ++i)
++ vrs[vd].u[i] = elog2(vrs[vb].u[i]);
++ break;
++ case 8: /* vrfin */
++ for (i = 0; i < 4; ++i)
++ vrs[vd].u[i] = rfin(vrs[vb].u[i]);
++ break;
++ case 9: /* vrfiz */
++ for (i = 0; i < 4; ++i)
++ vrs[vd].u[i] = rfiz(vrs[vb].u[i]);
++ break;
++ case 10: /* vrfip */
++ for (i = 0; i < 4; ++i) {
++ u32 x = vrs[vb].u[i];
++ x = (x & 0x80000000)? rfiz(x): rfii(x);
++ vrs[vd].u[i] = x;
++ }
++ break;
++ case 11: /* vrfim */
++ for (i = 0; i < 4; ++i) {
++ u32 x = vrs[vb].u[i];
++ x = (x & 0x80000000)? rfii(x): rfiz(x);
++ vrs[vd].u[i] = x;
++ }
++ break;
++ case 14: /* vctuxs */
++ for (i = 0; i < 4; ++i)
++ vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
++ ¤t->thread.vscr.u[3]);
++ break;
++ case 15: /* vctsxs */
++ for (i = 0; i < 4; ++i)
++ vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
++ ¤t->thread.vscr.u[3]);
++ break;
++ default:
++ return -EINVAL;
++ }
++ break;
++ case 46: /* vmaddfp */
++ vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
++ break;
++ case 47: /* vnmsubfp */
++ vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
+diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/vector.S
+@@ -0,0 +1,197 @@
++#include <linux/config.h>
++#include <asm/ppc_asm.h>
++#include <asm/reg.h>
++
++/*
++ * The routines below are in assembler so we can closely control the
++ * usage of floating-point registers. These routines must be called
++ * with preempt disabled.
++ */
++#ifdef CONFIG_PPC32
++ .data
++fpzero:
++ .long 0
++fpone:
++ .long 0x3f800000 /* 1.0 in single-precision FP */
++fphalf:
++ .long 0x3f000000 /* 0.5 in single-precision FP */
++
++#define LDCONST(fr, name) \
++ lis r11,name at ha; \
++ lfs fr,name at l(r11)
++#else
++
++ .section ".toc","aw"
++fpzero:
++ .tc FD_0_0[TC],0
++fpone:
++ .tc FD_3ff00000_0[TC],0x3ff0000000000000 /* 1.0 */
++fphalf:
++ .tc FD_3fe00000_0[TC],0x3fe0000000000000 /* 0.5 */
++
++#define LDCONST(fr, name) \
++ lfd fr,name at toc(r2)
++#endif
++
++ .text
++/*
++ * Internal routine to enable floating point and set FPSCR to 0.
++ * Don't call it from C; it doesn't use the normal calling convention.
++ */
++fpenable:
++#ifdef CONFIG_PPC32
++ stwu r1,-64(r1)
++#else
++ stdu r1,-64(r1)
++#endif
++ mfmsr r10
++ ori r11,r10,MSR_FP
++ mtmsr r11
++ isync
++ stfd fr0,24(r1)
++ stfd fr1,16(r1)
++ stfd fr31,8(r1)
++ LDCONST(fr1, fpzero)
++ mffs fr31
++ mtfsf 0xff,fr1
++ blr
++
++fpdisable:
++ mtlr r12
++ mtfsf 0xff,fr31
++ lfd fr31,8(r1)
++ lfd fr1,16(r1)
++ lfd fr0,24(r1)
++ mtmsr r10
++ isync
++ addi r1,r1,64
++ blr
++
++/*
++ * Vector add, floating point.
++ */
++_GLOBAL(vaddfp)
++ mflr r12
++ bl fpenable
++ li r0,4
++ mtctr r0
++ li r6,0
++1: lfsx fr0,r4,r6
++ lfsx fr1,r5,r6
++ fadds fr0,fr0,fr1
++ stfsx fr0,r3,r6
++ addi r6,r6,4
++ bdnz 1b
++ b fpdisable
++
++/*
++ * Vector subtract, floating point.
++ */
++_GLOBAL(vsubfp)
++ mflr r12
++ bl fpenable
++ li r0,4
++ mtctr r0
++ li r6,0
++1: lfsx fr0,r4,r6
++ lfsx fr1,r5,r6
++ fsubs fr0,fr0,fr1
++ stfsx fr0,r3,r6
++ addi r6,r6,4
++ bdnz 1b
++ b fpdisable
++
++/*
++ * Vector multiply and add, floating point.
++ */
++_GLOBAL(vmaddfp)
++ mflr r12
++ bl fpenable
++ stfd fr2,32(r1)
++ li r0,4
++ mtctr r0
++ li r7,0
++1: lfsx fr0,r4,r7
++ lfsx fr1,r5,r7
++ lfsx fr2,r6,r7
++ fmadds fr0,fr0,fr2,fr1
++ stfsx fr0,r3,r7
++ addi r7,r7,4
++ bdnz 1b
++ lfd fr2,32(r1)
++ b fpdisable
++
++/*
++ * Vector negative multiply and subtract, floating point.
++ */
++_GLOBAL(vnmsubfp)
++ mflr r12
++ bl fpenable
++ stfd fr2,32(r1)
++ li r0,4
++ mtctr r0
++ li r7,0
++1: lfsx fr0,r4,r7
++ lfsx fr1,r5,r7
++ lfsx fr2,r6,r7
++ fnmsubs fr0,fr0,fr2,fr1
++ stfsx fr0,r3,r7
++ addi r7,r7,4
++ bdnz 1b
++ lfd fr2,32(r1)
++ b fpdisable
++
++/*
++ * Vector reciprocal estimate. We just compute 1.0/x.
++ * r3 -> destination, r4 -> source.
++ */
++_GLOBAL(vrefp)
++ mflr r12
++ bl fpenable
++ li r0,4
++ LDCONST(fr1, fpone)
++ mtctr r0
++ li r6,0
++1: lfsx fr0,r4,r6
++ fdivs fr0,fr1,fr0
++ stfsx fr0,r3,r6
++ addi r6,r6,4
++ bdnz 1b
++ b fpdisable
++
++/*
++ * Vector reciprocal square-root estimate, floating point.
++ * We use the frsqrte instruction for the initial estimate followed
++ * by 2 iterations of Newton-Raphson to get sufficient accuracy.
++ * r3 -> destination, r4 -> source.
++ */
++_GLOBAL(vrsqrtefp)
++ mflr r12
++ bl fpenable
++ stfd fr2,32(r1)
++ stfd fr3,40(r1)
++ stfd fr4,48(r1)
++ stfd fr5,56(r1)
++ li r0,4
++ LDCONST(fr4, fpone)
++ LDCONST(fr5, fphalf)
++ mtctr r0
++ li r6,0
++1: lfsx fr0,r4,r6
++ frsqrte fr1,fr0 /* r = frsqrte(s) */
++ fmuls fr3,fr1,fr0 /* r * s */
++ fmuls fr2,fr1,fr5 /* r * 0.5 */
++ fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
++ fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
++ fmuls fr3,fr1,fr0 /* r * s */
++ fmuls fr2,fr1,fr5 /* r * 0.5 */
++ fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
++ fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
++ stfsx fr1,r3,r6
++ addi r6,r6,4
++ bdnz 1b
++ lfd fr5,56(r1)
++ lfd fr4,48(r1)
++ lfd fr3,40(r1)
++ lfd fr2,32(r1)
++ b fpdisable
+diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/vio.c
+@@ -0,0 +1,271 @@
++/*
++ * IBM PowerPC Virtual I/O Infrastructure Support.
++ *
++ * Copyright (c) 2003-2005 IBM Corp.
++ * Dave Engebretsen engebret at us.ibm.com
++ * Santiago Leon santil at us.ibm.com
++ * Hollis Blanchard <hollisb at us.ibm.com>
++ * Stephen Rothwell
++ *
++ * 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/console.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/dma-mapping.h>
++#include <asm/iommu.h>
++#include <asm/dma.h>
++#include <asm/vio.h>
++
++static const struct vio_device_id *vio_match_device(
++ const struct vio_device_id *, const struct vio_dev *);
++
++struct vio_dev vio_bus_device = { /* fake "parent" device */
++ .name = vio_bus_device.dev.bus_id,
++ .type = "",
++ .dev.bus_id = "vio",
++ .dev.bus = &vio_bus_type,
++};
++
++static struct vio_bus_ops vio_bus_ops;
++
++/*
++ * Convert from struct device to struct vio_dev and pass to driver.
++ * dev->driver has already been set by generic code because vio_bus_match
++ * succeeded.
++ */
++static int vio_bus_probe(struct device *dev)
++{
++ struct vio_dev *viodev = to_vio_dev(dev);
++ struct vio_driver *viodrv = to_vio_driver(dev->driver);
++ const struct vio_device_id *id;
++ int error = -ENODEV;
++
++ if (!viodrv->probe)
++ return error;
++
++ id = vio_match_device(viodrv->id_table, viodev);
++ if (id)
++ error = viodrv->probe(viodev, id);
++
++ return error;
++}
++
++/* convert from struct device to struct vio_dev and pass to driver. */
++static int vio_bus_remove(struct device *dev)
++{
++ struct vio_dev *viodev = to_vio_dev(dev);
++ struct vio_driver *viodrv = to_vio_driver(dev->driver);
++
++ if (viodrv->remove)
++ return viodrv->remove(viodev);
++
++ /* driver can't remove */
++ return 1;
++}
++
++/* convert from struct device to struct vio_dev and pass to driver. */
++static void vio_bus_shutdown(struct device *dev)
++{
++ struct vio_dev *viodev = to_vio_dev(dev);
++ struct vio_driver *viodrv = to_vio_driver(dev->driver);
++
++ if (viodrv->shutdown)
++ viodrv->shutdown(viodev);
++}
++
++/**
++ * vio_register_driver: - Register a new vio driver
++ * @drv: The vio_driver structure to be registered.
++ */
++int vio_register_driver(struct vio_driver *viodrv)
++{
++ printk(KERN_DEBUG "%s: driver %s registering\n", __FUNCTION__,
++ viodrv->driver.name);
++
++ /* fill in 'struct driver' fields */
++ viodrv->driver.bus = &vio_bus_type;
++ viodrv->driver.probe = vio_bus_probe;
++ viodrv->driver.remove = vio_bus_remove;
++ viodrv->driver.shutdown = vio_bus_shutdown;
++
++ return driver_register(&viodrv->driver);
++}
++EXPORT_SYMBOL(vio_register_driver);
++
++/**
++ * vio_unregister_driver - Remove registration of vio driver.
++ * @driver: The vio_driver struct to be removed form registration
++ */
++void vio_unregister_driver(struct vio_driver *viodrv)
++{
++ driver_unregister(&viodrv->driver);
++}
++EXPORT_SYMBOL(vio_unregister_driver);
++
++/**
++ * vio_match_device: - Tell if a VIO device has a matching
++ * VIO device id structure.
++ * @ids: array of VIO device id structures to search in
++ * @dev: the VIO device structure to match against
++ *
++ * Used by a driver to check whether a VIO device present in the
++ * system is in its list of supported devices. Returns the matching
++ * vio_device_id structure or NULL if there is no match.
++ */
++static const struct vio_device_id *vio_match_device(
++ const struct vio_device_id *ids, const struct vio_dev *dev)
++{
++ while (ids->type[0] != '\0') {
++ if (vio_bus_ops.match(ids, dev))
++ return ids;
++ ids++;
++ }
++ return NULL;
++}
++
++/**
++ * vio_bus_init: - Initialize the virtual IO bus
++ */
++int __init vio_bus_init(struct vio_bus_ops *ops)
++{
++ int err;
++
++ vio_bus_ops = *ops;
++
++ err = bus_register(&vio_bus_type);
++ if (err) {
++ printk(KERN_ERR "failed to register VIO bus\n");
++ return err;
++ }
++
++ /*
++ * The fake parent of all vio devices, just to give us
++ * a nice directory
++ */
++ err = device_register(&vio_bus_device.dev);
++ if (err) {
++ printk(KERN_WARNING "%s: device_register returned %i\n",
++ __FUNCTION__, err);
++ return err;
++ }
++
++ return 0;
++}
++
++/* vio_dev refcount hit 0 */
++static void __devinit vio_dev_release(struct device *dev)
++{
++ if (vio_bus_ops.release_device)
++ vio_bus_ops.release_device(dev);
++ kfree(to_vio_dev(dev));
++}
++
++static ssize_t viodev_show_name(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
++}
++DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
++
++struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
++{
++ /* init generic 'struct device' fields: */
++ viodev->dev.parent = &vio_bus_device.dev;
++ viodev->dev.bus = &vio_bus_type;
++ viodev->dev.release = vio_dev_release;
++
++ /* register with generic device framework */
++ if (device_register(&viodev->dev)) {
++ printk(KERN_ERR "%s: failed to register device %s\n",
++ __FUNCTION__, viodev->dev.bus_id);
++ return NULL;
++ }
++ device_create_file(&viodev->dev, &dev_attr_name);
++
++ return viodev;
++}
++
++void __devinit vio_unregister_device(struct vio_dev *viodev)
++{
++ if (vio_bus_ops.unregister_device)
++ vio_bus_ops.unregister_device(viodev);
++ device_remove_file(&viodev->dev, &dev_attr_name);
++ device_unregister(&viodev->dev);
++}
++EXPORT_SYMBOL(vio_unregister_device);
++
++static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
++ size_t size, enum dma_data_direction direction)
++{
++ return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
++ direction);
++}
++
++static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
++ size_t size, enum dma_data_direction direction)
++{
++ iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
++ direction);
++}
++
++static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
++ int nelems, enum dma_data_direction direction)
++{
++ return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
++ nelems, direction);
++}
++
++static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
++ int nelems, enum dma_data_direction direction)
++{
++ iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
++}
++
++static void *vio_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t *dma_handle, gfp_t flag)
++{
++ return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
++ dma_handle, flag);
++}
++
++static void vio_free_coherent(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t dma_handle)
++{
++ iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
++ dma_handle);
++}
++
++static int vio_dma_supported(struct device *dev, u64 mask)
++{
++ return 1;
++}
++
++struct dma_mapping_ops vio_dma_ops = {
++ .alloc_coherent = vio_alloc_coherent,
++ .free_coherent = vio_free_coherent,
++ .map_single = vio_map_single,
++ .unmap_single = vio_unmap_single,
++ .map_sg = vio_map_sg,
++ .unmap_sg = vio_unmap_sg,
++ .dma_supported = vio_dma_supported,
++};
++
++static int vio_bus_match(struct device *dev, struct device_driver *drv)
++{
++ const struct vio_dev *vio_dev = to_vio_dev(dev);
++ struct vio_driver *vio_drv = to_vio_driver(drv);
++ const struct vio_device_id *ids = vio_drv->id_table;
++
++ return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
++}
++
++struct bus_type vio_bus_type = {
++ .name = "vio",
++ .match = vio_bus_match,
++};
+diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/kernel/vmlinux.lds.S
+@@ -0,0 +1,279 @@
++#include <linux/config.h>
++#ifdef CONFIG_PPC64
++#include <asm/page.h>
++#else
++#define PAGE_SIZE 4096
++#endif
++#include <asm-generic/vmlinux.lds.h>
++
++#ifdef CONFIG_PPC64
++OUTPUT_ARCH(powerpc:common64)
++jiffies = jiffies_64;
++#else
++OUTPUT_ARCH(powerpc:common)
++jiffies = jiffies_64 + 4;
++#endif
++SECTIONS
++{
++ /* Sections to be discarded. */
++ /DISCARD/ : {
++ *(.exitcall.exit)
++ *(.exit.data)
++ }
++
++
++ /* Read-only sections, merged into text segment: */
++#ifdef CONFIG_PPC32
++ . = + SIZEOF_HEADERS;
++ .interp : { *(.interp) }
++ .hash : { *(.hash) }
++ .dynsym : { *(.dynsym) }
++ .dynstr : { *(.dynstr) }
++ .rel.text : { *(.rel.text) }
++ .rela.text : { *(.rela.text) }
++ .rel.data : { *(.rel.data) }
++ .rela.data : { *(.rela.data) }
++ .rel.rodata : { *(.rel.rodata) }
++ .rela.rodata : { *(.rela.rodata) }
++ .rel.got : { *(.rel.got) }
++ .rela.got : { *(.rela.got) }
++ .rel.ctors : { *(.rel.ctors) }
++ .rela.ctors : { *(.rela.ctors) }
++ .rel.dtors : { *(.rel.dtors) }
++ .rela.dtors : { *(.rela.dtors) }
++ .rel.bss : { *(.rel.bss) }
++ .rela.bss : { *(.rela.bss) }
++ .rel.plt : { *(.rel.plt) }
++ .rela.plt : { *(.rela.plt) }
++/* .init : { *(.init) } =0*/
++ .plt : { *(.plt) }
++#endif
++ .text : {
++ *(.text .text.*)
++ SCHED_TEXT
++ LOCK_TEXT
++ KPROBES_TEXT
++ *(.fixup)
++#ifdef CONFIG_PPC32
++ *(.got1)
++ __got2_start = .;
++ *(.got2)
++ __got2_end = .;
++#else
++ . = ALIGN(PAGE_SIZE);
++ _etext = .;
++#endif
++ }
++#ifdef CONFIG_PPC32
++ _etext = .;
++ PROVIDE (etext = .);
++
++ RODATA
++ .fini : { *(.fini) } =0
++ .ctors : { *(.ctors) }
++ .dtors : { *(.dtors) }
++
++ .fixup : { *(.fixup) }
++#endif
++
++ __ex_table : {
++ __start___ex_table = .;
++ *(__ex_table)
++ __stop___ex_table = .;
++ }
++
++ __bug_table : {
++ __start___bug_table = .;
++ *(__bug_table)
++ __stop___bug_table = .;
++ }
++
++#ifdef CONFIG_PPC64
++ __ftr_fixup : {
++ __start___ftr_fixup = .;
++ *(__ftr_fixup)
++ __stop___ftr_fixup = .;
++ }
++
++ RODATA
++#endif
++
++#ifdef CONFIG_PPC32
++ /* Read-write section, merged into data segment: */
++ . = ALIGN(PAGE_SIZE);
++ _sdata = .;
++ .data :
++ {
++ *(.data)
++ *(.data1)
++ *(.sdata)
++ *(.sdata2)
++ *(.got.plt) *(.got)
++ *(.dynamic)
++ CONSTRUCTORS
++ }
++
++ . = ALIGN(PAGE_SIZE);
++ __nosave_begin = .;
++ .data_nosave : { *(.data.nosave) }
++ . = ALIGN(PAGE_SIZE);
++ __nosave_end = .;
++
++ . = ALIGN(32);
++ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
++
++ _edata = .;
++ PROVIDE (edata = .);
++
++ . = ALIGN(8192);
++ .data.init_task : { *(.data.init_task) }
++#endif
++
++ /* will be freed after init */
++ . = ALIGN(PAGE_SIZE);
++ __init_begin = .;
++ .init.text : {
++ _sinittext = .;
++ *(.init.text)
++ _einittext = .;
++ }
++#ifdef CONFIG_PPC32
++ /* .exit.text is discarded at runtime, not link time,
++ to deal with references from __bug_table */
++ .exit.text : { *(.exit.text) }
++#endif
++ .init.data : {
++ *(.init.data);
++ __vtop_table_begin = .;
++ *(.vtop_fixup);
++ __vtop_table_end = .;
++ __ptov_table_begin = .;
++ *(.ptov_fixup);
++ __ptov_table_end = .;
++ }
++
++ . = ALIGN(16);
++ .init.setup : {
++ __setup_start = .;
++ *(.init.setup)
++ __setup_end = .;
++ }
++
++ .initcall.init : {
++ __initcall_start = .;
++ *(.initcall1.init)
++ *(.initcall2.init)
++ *(.initcall3.init)
++ *(.initcall4.init)
++ *(.initcall5.init)
++ *(.initcall6.init)
++ *(.initcall7.init)
++ __initcall_end = .;
++ }
++
++ .con_initcall.init : {
++ __con_initcall_start = .;
++ *(.con_initcall.init)
++ __con_initcall_end = .;
++ }
++
++ SECURITY_INIT
++
++#ifdef CONFIG_PPC32
++ __start___ftr_fixup = .;
++ __ftr_fixup : { *(__ftr_fixup) }
++ __stop___ftr_fixup = .;
++#else
++ . = ALIGN(PAGE_SIZE);
++ .init.ramfs : {
++ __initramfs_start = .;
++ *(.init.ramfs)
++ __initramfs_end = .;
++ }
++#endif
++
++#ifdef CONFIG_PPC32
++ . = ALIGN(32);
++#endif
++ .data.percpu : {
++ __per_cpu_start = .;
++ *(.data.percpu)
++ __per_cpu_end = .;
++ }
++
++ . = ALIGN(PAGE_SIZE);
++#ifdef CONFIG_PPC64
++ . = ALIGN(16384);
++ __init_end = .;
++ /* freed after init ends here */
++
++ /* Read/write sections */
++ . = ALIGN(PAGE_SIZE);
++ . = ALIGN(16384);
++ _sdata = .;
++ /* The initial task and kernel stack */
++ .data.init_task : {
++ *(.data.init_task)
++ }
++
++ . = ALIGN(PAGE_SIZE);
++ .data.page_aligned : {
++ *(.data.page_aligned)
++ }
++
++ .data.cacheline_aligned : {
++ *(.data.cacheline_aligned)
++ }
++
++ .data : {
++ *(.data .data.rel* .toc1)
++ *(.branch_lt)
++ }
++
++ .opd : {
++ *(.opd)
++ }
++
++ .got : {
++ __toc_start = .;
++ *(.got)
++ *(.toc)
++ . = ALIGN(PAGE_SIZE);
++ _edata = .;
++ }
++
++ . = ALIGN(PAGE_SIZE);
++#else
++ __initramfs_start = .;
++ .init.ramfs : {
++ *(.init.ramfs)
++ }
++ __initramfs_end = .;
++
++ . = ALIGN(4096);
++ __init_end = .;
++
++ . = ALIGN(4096);
++ _sextratext = .;
++ _eextratext = .;
++
++ __bss_start = .;
++#endif
++
++ .bss : {
++ __bss_start = .;
++ *(.sbss) *(.scommon)
++ *(.dynbss)
++ *(.bss)
++ *(COMMON)
++ __bss_stop = .;
++ }
++
++#ifdef CONFIG_PPC64
++ . = ALIGN(PAGE_SIZE);
++#endif
++ _end = . ;
++#ifdef CONFIG_PPC32
++ PROVIDE (end = .);
++#endif
++}
+diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/Makefile
+@@ -0,0 +1,19 @@
++#
++# Makefile for ppc-specific library files..
++#
++
++ifeq ($(CONFIG_PPC_MERGE),y)
++obj-y := string.o
++endif
++
++obj-y += strcase.o
++obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
++obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
++ memcpy_64.o usercopy_64.o mem_64.o
++obj-$(CONFIG_PPC_ISERIES) += e2a.o
++obj-$(CONFIG_XMON) += sstep.o
++
++ifeq ($(CONFIG_PPC64),y)
++obj-$(CONFIG_SMP) += locks.o
++obj-$(CONFIG_DEBUG_KERNEL) += sstep.o
++endif
+diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/checksum_32.S
+@@ -0,0 +1,225 @@
++/*
++ * This file contains assembly-language implementations
++ * of IP-style 1's complement checksum routines.
++ *
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.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.
++ *
++ * Severely hacked about by Paul Mackerras (paulus at cs.anu.edu.au).
++ */
++
++#include <linux/sys.h>
++#include <asm/processor.h>
++#include <asm/errno.h>
++#include <asm/ppc_asm.h>
++
++ .text
++
++/*
++ * ip_fast_csum(buf, len) -- Optimized for IP header
++ * len is in words and is always >= 5.
++ */
++_GLOBAL(ip_fast_csum)
++ lwz r0,0(r3)
++ lwzu r5,4(r3)
++ addic. r4,r4,-2
++ addc r0,r0,r5
++ mtctr r4
++ blelr-
++1: lwzu r4,4(r3)
++ adde r0,r0,r4
++ bdnz 1b
++ addze r0,r0 /* add in final carry */
++ rlwinm r3,r0,16,0,31 /* fold two halves together */
++ add r3,r0,r3
++ not r3,r3
++ srwi r3,r3,16
++ blr
++
++/*
++ * Compute checksum of TCP or UDP pseudo-header:
++ * csum_tcpudp_magic(saddr, daddr, len, proto, sum)
++ */
++_GLOBAL(csum_tcpudp_magic)
++ rlwimi r5,r6,16,0,15 /* put proto in upper half of len */
++ addc r0,r3,r4 /* add 4 32-bit words together */
++ adde r0,r0,r5
++ adde r0,r0,r7
++ addze r0,r0 /* add in final carry */
++ rlwinm r3,r0,16,0,31 /* fold two halves together */
++ add r3,r0,r3
++ not r3,r3
++ srwi r3,r3,16
++ blr
++
++/*
++ * computes the checksum of a memory block at buff, length len,
++ * and adds in "sum" (32-bit)
++ *
++ * csum_partial(buff, len, sum)
++ */
++_GLOBAL(csum_partial)
++ addic r0,r5,0
++ subi r3,r3,4
++ srwi. r6,r4,2
++ beq 3f /* if we're doing < 4 bytes */
++ andi. r5,r3,2 /* Align buffer to longword boundary */
++ beq+ 1f
++ lhz r5,4(r3) /* do 2 bytes to get aligned */
++ addi r3,r3,2
++ subi r4,r4,2
++ addc r0,r0,r5
++ srwi. r6,r4,2 /* # words to do */
++ beq 3f
++1: mtctr r6
++2: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */
++ adde r0,r0,r5 /* be unnecessary to unroll this loop */
++ bdnz 2b
++ andi. r4,r4,3
++3: cmpwi 0,r4,2
++ blt+ 4f
++ lhz r5,4(r3)
++ addi r3,r3,2
++ subi r4,r4,2
++ adde r0,r0,r5
++4: cmpwi 0,r4,1
++ bne+ 5f
++ lbz r5,4(r3)
++ slwi r5,r5,8 /* Upper byte of word */
++ adde r0,r0,r5
++5: addze r3,r0 /* add in final carry */
++ blr
++
++/*
++ * Computes the checksum of a memory block at src, length len,
++ * and adds in "sum" (32-bit), while copying the block to dst.
++ * If an access exception occurs on src or dst, it stores -EFAULT
++ * to *src_err or *dst_err respectively, and (for an error on
++ * src) zeroes the rest of dst.
++ *
++ * csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err)
++ */
++_GLOBAL(csum_partial_copy_generic)
++ addic r0,r6,0
++ subi r3,r3,4
++ subi r4,r4,4
++ srwi. r6,r5,2
++ beq 3f /* if we're doing < 4 bytes */
++ andi. r9,r4,2 /* Align dst to longword boundary */
++ beq+ 1f
++81: lhz r6,4(r3) /* do 2 bytes to get aligned */
++ addi r3,r3,2
++ subi r5,r5,2
++91: sth r6,4(r4)
++ addi r4,r4,2
++ addc r0,r0,r6
++ srwi. r6,r5,2 /* # words to do */
++ beq 3f
++1: srwi. r6,r5,4 /* # groups of 4 words to do */
++ beq 10f
++ mtctr r6
++71: lwz r6,4(r3)
++72: lwz r9,8(r3)
++73: lwz r10,12(r3)
++74: lwzu r11,16(r3)
++ adde r0,r0,r6
++75: stw r6,4(r4)
++ adde r0,r0,r9
++76: stw r9,8(r4)
++ adde r0,r0,r10
++77: stw r10,12(r4)
++ adde r0,r0,r11
++78: stwu r11,16(r4)
++ bdnz 71b
++10: rlwinm. r6,r5,30,30,31 /* # words left to do */
++ beq 13f
++ mtctr r6
++82: lwzu r9,4(r3)
++92: stwu r9,4(r4)
++ adde r0,r0,r9
++ bdnz 82b
++13: andi. r5,r5,3
++3: cmpwi 0,r5,2
++ blt+ 4f
++83: lhz r6,4(r3)
++ addi r3,r3,2
++ subi r5,r5,2
++93: sth r6,4(r4)
++ addi r4,r4,2
++ adde r0,r0,r6
++4: cmpwi 0,r5,1
++ bne+ 5f
++84: lbz r6,4(r3)
++94: stb r6,4(r4)
++ slwi r6,r6,8 /* Upper byte of word */
++ adde r0,r0,r6
++5: addze r3,r0 /* add in final carry */
++ blr
++
++/* These shouldn't go in the fixup section, since that would
++ cause the ex_table addresses to get out of order. */
++
++src_error_4:
++ mfctr r6 /* update # bytes remaining from ctr */
++ rlwimi r5,r6,4,0,27
++ b 79f
++src_error_1:
++ li r6,0
++ subi r5,r5,2
++95: sth r6,4(r4)
++ addi r4,r4,2
++79: srwi. r6,r5,2
++ beq 3f
++ mtctr r6
++src_error_2:
++ li r6,0
++96: stwu r6,4(r4)
++ bdnz 96b
++3: andi. r5,r5,3
++ beq src_error
++src_error_3:
++ li r6,0
++ mtctr r5
++ addi r4,r4,3
++97: stbu r6,1(r4)
++ bdnz 97b
++src_error:
++ cmpwi 0,r7,0
++ beq 1f
++ li r6,-EFAULT
++ stw r6,0(r7)
++1: addze r3,r0
++ blr
++
++dst_error:
++ cmpwi 0,r8,0
++ beq 1f
++ li r6,-EFAULT
++ stw r6,0(r8)
++1: addze r3,r0
++ blr
++
++.section __ex_table,"a"
++ .long 81b,src_error_1
++ .long 91b,dst_error
++ .long 71b,src_error_4
++ .long 72b,src_error_4
++ .long 73b,src_error_4
++ .long 74b,src_error_4
++ .long 75b,dst_error
++ .long 76b,dst_error
++ .long 77b,dst_error
++ .long 78b,dst_error
++ .long 82b,src_error_2
++ .long 92b,dst_error
++ .long 83b,src_error_3
++ .long 93b,dst_error
++ .long 84b,src_error_3
++ .long 94b,dst_error
++ .long 95b,dst_error
++ .long 96b,dst_error
++ .long 97b,dst_error
+diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/checksum_64.S
+@@ -0,0 +1,229 @@
++/*
++ * This file contains assembly-language implementations
++ * of IP-style 1's complement checksum routines.
++ *
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.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.
++ *
++ * Severely hacked about by Paul Mackerras (paulus at cs.anu.edu.au).
++ */
++
++#include <linux/sys.h>
++#include <asm/processor.h>
++#include <asm/errno.h>
++#include <asm/ppc_asm.h>
++
++/*
++ * ip_fast_csum(r3=buf, r4=len) -- Optimized for IP header
++ * len is in words and is always >= 5.
++ *
++ * In practice len == 5, but this is not guaranteed. So this code does not
++ * attempt to use doubleword instructions.
++ */
++_GLOBAL(ip_fast_csum)
++ lwz r0,0(r3)
++ lwzu r5,4(r3)
++ addic. r4,r4,-2
++ addc r0,r0,r5
++ mtctr r4
++ blelr-
++1: lwzu r4,4(r3)
++ adde r0,r0,r4
++ bdnz 1b
++ addze r0,r0 /* add in final carry */
++ rldicl r4,r0,32,0 /* fold two 32-bit halves together */
++ add r0,r0,r4
++ srdi r0,r0,32
++ rlwinm r3,r0,16,0,31 /* fold two halves together */
++ add r3,r0,r3
++ not r3,r3
++ srwi r3,r3,16
++ blr
++
++/*
++ * Compute checksum of TCP or UDP pseudo-header:
++ * csum_tcpudp_magic(r3=saddr, r4=daddr, r5=len, r6=proto, r7=sum)
++ * No real gain trying to do this specially for 64 bit, but
++ * the 32 bit addition may spill into the upper bits of
++ * the doubleword so we still must fold it down from 64.
++ */
++_GLOBAL(csum_tcpudp_magic)
++ rlwimi r5,r6,16,0,15 /* put proto in upper half of len */
++ addc r0,r3,r4 /* add 4 32-bit words together */
++ adde r0,r0,r5
++ adde r0,r0,r7
++ rldicl r4,r0,32,0 /* fold 64 bit value */
++ add r0,r4,r0
++ srdi r0,r0,32
++ rlwinm r3,r0,16,0,31 /* fold two halves together */
++ add r3,r0,r3
++ not r3,r3
++ srwi r3,r3,16
++ blr
++
++/*
++ * Computes the checksum of a memory block at buff, length len,
++ * and adds in "sum" (32-bit).
++ *
++ * This code assumes at least halfword alignment, though the length
++ * can be any number of bytes. The sum is accumulated in r5.
++ *
++ * csum_partial(r3=buff, r4=len, r5=sum)
++ */
++_GLOBAL(csum_partial)
++ subi r3,r3,8 /* we'll offset by 8 for the loads */
++ srdi. r6,r4,3 /* divide by 8 for doubleword count */
++ addic r5,r5,0 /* clear carry */
++ beq 3f /* if we're doing < 8 bytes */
++ andi. r0,r3,2 /* aligned on a word boundary already? */
++ beq+ 1f
++ lhz r6,8(r3) /* do 2 bytes to get aligned */
++ addi r3,r3,2
++ subi r4,r4,2
++ addc r5,r5,r6
++ srdi. r6,r4,3 /* recompute number of doublewords */
++ beq 3f /* any left? */
++1: mtctr r6
++2: ldu r6,8(r3) /* main sum loop */
++ adde r5,r5,r6
++ bdnz 2b
++ andi. r4,r4,7 /* compute bytes left to sum after doublewords */
++3: cmpwi 0,r4,4 /* is at least a full word left? */
++ blt 4f
++ lwz r6,8(r3) /* sum this word */
++ addi r3,r3,4
++ subi r4,r4,4
++ adde r5,r5,r6
++4: cmpwi 0,r4,2 /* is at least a halfword left? */
++ blt+ 5f
++ lhz r6,8(r3) /* sum this halfword */
++ addi r3,r3,2
++ subi r4,r4,2
++ adde r5,r5,r6
++5: cmpwi 0,r4,1 /* is at least a byte left? */
++ bne+ 6f
++ lbz r6,8(r3) /* sum this byte */
++ slwi r6,r6,8 /* this byte is assumed to be the upper byte of a halfword */
++ adde r5,r5,r6
++6: addze r5,r5 /* add in final carry */
++ rldicl r4,r5,32,0 /* fold two 32-bit halves together */
++ add r3,r4,r5
++ srdi r3,r3,32
++ blr
++
++/*
++ * Computes the checksum of a memory block at src, length len,
++ * and adds in "sum" (32-bit), while copying the block to dst.
++ * If an access exception occurs on src or dst, it stores -EFAULT
++ * to *src_err or *dst_err respectively, and (for an error on
++ * src) zeroes the rest of dst.
++ *
++ * This code needs to be reworked to take advantage of 64 bit sum+copy.
++ * However, due to tokenring halfword alignment problems this will be very
++ * tricky. For now we'll leave it until we instrument it somehow.
++ *
++ * csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err)
++ */
++_GLOBAL(csum_partial_copy_generic)
++ addic r0,r6,0
++ subi r3,r3,4
++ subi r4,r4,4
++ srwi. r6,r5,2
++ beq 3f /* if we're doing < 4 bytes */
++ andi. r9,r4,2 /* Align dst to longword boundary */
++ beq+ 1f
++81: lhz r6,4(r3) /* do 2 bytes to get aligned */
++ addi r3,r3,2
++ subi r5,r5,2
++91: sth r6,4(r4)
++ addi r4,r4,2
++ addc r0,r0,r6
++ srwi. r6,r5,2 /* # words to do */
++ beq 3f
++1: mtctr r6
++82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */
++92: stwu r6,4(r4) /* be unnecessary to unroll this loop */
++ adde r0,r0,r6
++ bdnz 82b
++ andi. r5,r5,3
++3: cmpwi 0,r5,2
++ blt+ 4f
++83: lhz r6,4(r3)
++ addi r3,r3,2
++ subi r5,r5,2
++93: sth r6,4(r4)
++ addi r4,r4,2
++ adde r0,r0,r6
++4: cmpwi 0,r5,1
++ bne+ 5f
++84: lbz r6,4(r3)
++94: stb r6,4(r4)
++ slwi r6,r6,8 /* Upper byte of word */
++ adde r0,r0,r6
++5: addze r3,r0 /* add in final carry (unlikely with 64-bit regs) */
++ rldicl r4,r3,32,0 /* fold 64 bit value */
++ add r3,r4,r3
++ srdi r3,r3,32
++ blr
++
++/* These shouldn't go in the fixup section, since that would
++ cause the ex_table addresses to get out of order. */
++
++ .globl src_error_1
++src_error_1:
++ li r6,0
++ subi r5,r5,2
++95: sth r6,4(r4)
++ addi r4,r4,2
++ srwi. r6,r5,2
++ beq 3f
++ mtctr r6
++ .globl src_error_2
++src_error_2:
++ li r6,0
++96: stwu r6,4(r4)
++ bdnz 96b
++3: andi. r5,r5,3
++ beq src_error
++ .globl src_error_3
++src_error_3:
++ li r6,0
++ mtctr r5
++ addi r4,r4,3
++97: stbu r6,1(r4)
++ bdnz 97b
++ .globl src_error
++src_error:
++ cmpdi 0,r7,0
++ beq 1f
++ li r6,-EFAULT
++ stw r6,0(r7)
++1: addze r3,r0
++ blr
++
++ .globl dst_error
++dst_error:
++ cmpdi 0,r8,0
++ beq 1f
++ li r6,-EFAULT
++ stw r6,0(r8)
++1: addze r3,r0
++ blr
++
++.section __ex_table,"a"
++ .align 3
++ .llong 81b,src_error_1
++ .llong 91b,dst_error
++ .llong 82b,src_error_2
++ .llong 92b,dst_error
++ .llong 83b,src_error_3
++ .llong 93b,dst_error
++ .llong 84b,src_error_3
++ .llong 94b,dst_error
++ .llong 95b,dst_error
++ .llong 96b,dst_error
++ .llong 97b,dst_error
+diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/copy_32.S
+@@ -0,0 +1,543 @@
++/*
++ * Memory copy functions for 32-bit PowerPC.
++ *
++ * Copyright (C) 1996-2005 Paul Mackerras.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/cache.h>
++#include <asm/errno.h>
++#include <asm/ppc_asm.h>
++
++#define COPY_16_BYTES \
++ lwz r7,4(r4); \
++ lwz r8,8(r4); \
++ lwz r9,12(r4); \
++ lwzu r10,16(r4); \
++ stw r7,4(r6); \
++ stw r8,8(r6); \
++ stw r9,12(r6); \
++ stwu r10,16(r6)
++
++#define COPY_16_BYTES_WITHEX(n) \
++8 ## n ## 0: \
++ lwz r7,4(r4); \
++8 ## n ## 1: \
++ lwz r8,8(r4); \
++8 ## n ## 2: \
++ lwz r9,12(r4); \
++8 ## n ## 3: \
++ lwzu r10,16(r4); \
++8 ## n ## 4: \
++ stw r7,4(r6); \
++8 ## n ## 5: \
++ stw r8,8(r6); \
++8 ## n ## 6: \
++ stw r9,12(r6); \
++8 ## n ## 7: \
++ stwu r10,16(r6)
++
++#define COPY_16_BYTES_EXCODE(n) \
++9 ## n ## 0: \
++ addi r5,r5,-(16 * n); \
++ b 104f; \
++9 ## n ## 1: \
++ addi r5,r5,-(16 * n); \
++ b 105f; \
++.section __ex_table,"a"; \
++ .align 2; \
++ .long 8 ## n ## 0b,9 ## n ## 0b; \
++ .long 8 ## n ## 1b,9 ## n ## 0b; \
++ .long 8 ## n ## 2b,9 ## n ## 0b; \
++ .long 8 ## n ## 3b,9 ## n ## 0b; \
++ .long 8 ## n ## 4b,9 ## n ## 1b; \
++ .long 8 ## n ## 5b,9 ## n ## 1b; \
++ .long 8 ## n ## 6b,9 ## n ## 1b; \
++ .long 8 ## n ## 7b,9 ## n ## 1b; \
++ .text
++
++ .text
++ .stabs "arch/powerpc/lib/",N_SO,0,0,0f
++ .stabs "copy32.S",N_SO,0,0,0f
++0:
++
++CACHELINE_BYTES = L1_CACHE_BYTES
++LG_CACHELINE_BYTES = L1_CACHE_SHIFT
++CACHELINE_MASK = (L1_CACHE_BYTES-1)
++
++/*
++ * Use dcbz on the complete cache lines in the destination
++ * to set them to zero. This requires that the destination
++ * area is cacheable. -- paulus
++ */
++_GLOBAL(cacheable_memzero)
++ mr r5,r4
++ li r4,0
++ addi r6,r3,-4
++ cmplwi 0,r5,4
++ blt 7f
++ stwu r4,4(r6)
++ beqlr
++ andi. r0,r6,3
++ add r5,r0,r5
++ subf r6,r0,r6
++ clrlwi r7,r6,32-LG_CACHELINE_BYTES
++ add r8,r7,r5
++ srwi r9,r8,LG_CACHELINE_BYTES
++ addic. r9,r9,-1 /* total number of complete cachelines */
++ ble 2f
++ xori r0,r7,CACHELINE_MASK & ~3
++ srwi. r0,r0,2
++ beq 3f
++ mtctr r0
++4: stwu r4,4(r6)
++ bdnz 4b
++3: mtctr r9
++ li r7,4
++#if !defined(CONFIG_8xx)
++10: dcbz r7,r6
++#else
++10: stw r4, 4(r6)
++ stw r4, 8(r6)
++ stw r4, 12(r6)
++ stw r4, 16(r6)
++#if CACHE_LINE_SIZE >= 32
++ stw r4, 20(r6)
++ stw r4, 24(r6)
++ stw r4, 28(r6)
++ stw r4, 32(r6)
++#endif /* CACHE_LINE_SIZE */
++#endif
++ addi r6,r6,CACHELINE_BYTES
++ bdnz 10b
++ clrlwi r5,r8,32-LG_CACHELINE_BYTES
++ addi r5,r5,4
++2: srwi r0,r5,2
++ mtctr r0
++ bdz 6f
++1: stwu r4,4(r6)
++ bdnz 1b
++6: andi. r5,r5,3
++7: cmpwi 0,r5,0
++ beqlr
++ mtctr r5
++ addi r6,r6,3
++8: stbu r4,1(r6)
++ bdnz 8b
++ blr
++
++_GLOBAL(memset)
++ rlwimi r4,r4,8,16,23
++ rlwimi r4,r4,16,0,15
++ addi r6,r3,-4
++ cmplwi 0,r5,4
++ blt 7f
++ stwu r4,4(r6)
++ beqlr
++ andi. r0,r6,3
++ add r5,r0,r5
++ subf r6,r0,r6
++ srwi r0,r5,2
++ mtctr r0
++ bdz 6f
++1: stwu r4,4(r6)
++ bdnz 1b
++6: andi. r5,r5,3
++7: cmpwi 0,r5,0
++ beqlr
++ mtctr r5
++ addi r6,r6,3
++8: stbu r4,1(r6)
++ bdnz 8b
++ blr
++
++/*
++ * This version uses dcbz on the complete cache lines in the
++ * destination area to reduce memory traffic. This requires that
++ * the destination area is cacheable.
++ * We only use this version if the source and dest don't overlap.
++ * -- paulus.
++ */
++_GLOBAL(cacheable_memcpy)
++ add r7,r3,r5 /* test if the src & dst overlap */
++ add r8,r4,r5
++ cmplw 0,r4,r7
++ cmplw 1,r3,r8
++ crand 0,0,4 /* cr0.lt &= cr1.lt */
++ blt memcpy /* if regions overlap */
++
++ addi r4,r4,-4
++ addi r6,r3,-4
++ neg r0,r3
++ andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
++ beq 58f
++
++ cmplw 0,r5,r0 /* is this more than total to do? */
++ blt 63f /* if not much to do */
++ andi. r8,r0,3 /* get it word-aligned first */
++ subf r5,r0,r5
++ mtctr r8
++ beq+ 61f
++70: lbz r9,4(r4) /* do some bytes */
++ stb r9,4(r6)
++ addi r4,r4,1
++ addi r6,r6,1
++ bdnz 70b
++61: srwi. r0,r0,2
++ mtctr r0
++ beq 58f
++72: lwzu r9,4(r4) /* do some words */
++ stwu r9,4(r6)
++ bdnz 72b
++
++58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
++ clrlwi r5,r5,32-LG_CACHELINE_BYTES
++ li r11,4
++ mtctr r0
++ beq 63f
++53:
++#if !defined(CONFIG_8xx)
++ dcbz r11,r6
++#endif
++ COPY_16_BYTES
++#if L1_CACHE_BYTES >= 32
++ COPY_16_BYTES
++#if L1_CACHE_BYTES >= 64
++ COPY_16_BYTES
++ COPY_16_BYTES
++#if L1_CACHE_BYTES >= 128
++ COPY_16_BYTES
++ COPY_16_BYTES
++ COPY_16_BYTES
++ COPY_16_BYTES
++#endif
++#endif
++#endif
++ bdnz 53b
++
++63: srwi. r0,r5,2
++ mtctr r0
++ beq 64f
++30: lwzu r0,4(r4)
++ stwu r0,4(r6)
++ bdnz 30b
++
++64: andi. r0,r5,3
++ mtctr r0
++ beq+ 65f
++40: lbz r0,4(r4)
++ stb r0,4(r6)
++ addi r4,r4,1
++ addi r6,r6,1
++ bdnz 40b
++65: blr
++
++_GLOBAL(memmove)
++ cmplw 0,r3,r4
++ bgt backwards_memcpy
++ /* fall through */
++
++_GLOBAL(memcpy)
++ srwi. r7,r5,3
++ addi r6,r3,-4
++ addi r4,r4,-4
++ beq 2f /* if less than 8 bytes to do */
++ andi. r0,r6,3 /* get dest word aligned */
++ mtctr r7
++ bne 5f
++1: lwz r7,4(r4)
++ lwzu r8,8(r4)
++ stw r7,4(r6)
++ stwu r8,8(r6)
++ bdnz 1b
++ andi. r5,r5,7
++2: cmplwi 0,r5,4
++ blt 3f
++ lwzu r0,4(r4)
++ addi r5,r5,-4
++ stwu r0,4(r6)
++3: cmpwi 0,r5,0
++ beqlr
++ mtctr r5
++ addi r4,r4,3
++ addi r6,r6,3
++4: lbzu r0,1(r4)
++ stbu r0,1(r6)
++ bdnz 4b
++ blr
++5: subfic r0,r0,4
++ mtctr r0
++6: lbz r7,4(r4)
++ addi r4,r4,1
++ stb r7,4(r6)
++ addi r6,r6,1
++ bdnz 6b
++ subf r5,r0,r5
++ rlwinm. r7,r5,32-3,3,31
++ beq 2b
++ mtctr r7
++ b 1b
++
++_GLOBAL(backwards_memcpy)
++ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
++ add r6,r3,r5
++ add r4,r4,r5
++ beq 2f
++ andi. r0,r6,3
++ mtctr r7
++ bne 5f
++1: lwz r7,-4(r4)
++ lwzu r8,-8(r4)
++ stw r7,-4(r6)
++ stwu r8,-8(r6)
++ bdnz 1b
++ andi. r5,r5,7
++2: cmplwi 0,r5,4
++ blt 3f
++ lwzu r0,-4(r4)
++ subi r5,r5,4
++ stwu r0,-4(r6)
++3: cmpwi 0,r5,0
++ beqlr
++ mtctr r5
++4: lbzu r0,-1(r4)
++ stbu r0,-1(r6)
++ bdnz 4b
++ blr
++5: mtctr r0
++6: lbzu r7,-1(r4)
++ stbu r7,-1(r6)
++ bdnz 6b
++ subf r5,r0,r5
++ rlwinm. r7,r5,32-3,3,31
++ beq 2b
++ mtctr r7
++ b 1b
++
++_GLOBAL(__copy_tofrom_user)
++ addi r4,r4,-4
++ addi r6,r3,-4
++ neg r0,r3
++ andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
++ beq 58f
++
++ cmplw 0,r5,r0 /* is this more than total to do? */
++ blt 63f /* if not much to do */
++ andi. r8,r0,3 /* get it word-aligned first */
++ mtctr r8
++ beq+ 61f
++70: lbz r9,4(r4) /* do some bytes */
++71: stb r9,4(r6)
++ addi r4,r4,1
++ addi r6,r6,1
++ bdnz 70b
++61: subf r5,r0,r5
++ srwi. r0,r0,2
++ mtctr r0
++ beq 58f
++72: lwzu r9,4(r4) /* do some words */
++73: stwu r9,4(r6)
++ bdnz 72b
++
++ .section __ex_table,"a"
++ .align 2
++ .long 70b,100f
++ .long 71b,101f
++ .long 72b,102f
++ .long 73b,103f
++ .text
++
++58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
++ clrlwi r5,r5,32-LG_CACHELINE_BYTES
++ li r11,4
++ beq 63f
++
++#ifdef CONFIG_8xx
++ /* Don't use prefetch on 8xx */
++ mtctr r0
++ li r0,0
++53: COPY_16_BYTES_WITHEX(0)
++ bdnz 53b
++
++#else /* not CONFIG_8xx */
++ /* Here we decide how far ahead to prefetch the source */
++ li r3,4
++ cmpwi r0,1
++ li r7,0
++ ble 114f
++ li r7,1
++#if MAX_COPY_PREFETCH > 1
++ /* Heuristically, for large transfers we prefetch
++ MAX_COPY_PREFETCH cachelines ahead. For small transfers
++ we prefetch 1 cacheline ahead. */
++ cmpwi r0,MAX_COPY_PREFETCH
++ ble 112f
++ li r7,MAX_COPY_PREFETCH
++112: mtctr r7
++111: dcbt r3,r4
++ addi r3,r3,CACHELINE_BYTES
++ bdnz 111b
++#else
++ dcbt r3,r4
++ addi r3,r3,CACHELINE_BYTES
++#endif /* MAX_COPY_PREFETCH > 1 */
++
++114: subf r8,r7,r0
++ mr r0,r7
++ mtctr r8
++
++53: dcbt r3,r4
++54: dcbz r11,r6
++ .section __ex_table,"a"
++ .align 2
++ .long 54b,105f
++ .text
++/* the main body of the cacheline loop */
++ COPY_16_BYTES_WITHEX(0)
++#if L1_CACHE_BYTES >= 32
++ COPY_16_BYTES_WITHEX(1)
++#if L1_CACHE_BYTES >= 64
++ COPY_16_BYTES_WITHEX(2)
++ COPY_16_BYTES_WITHEX(3)
++#if L1_CACHE_BYTES >= 128
++ COPY_16_BYTES_WITHEX(4)
++ COPY_16_BYTES_WITHEX(5)
++ COPY_16_BYTES_WITHEX(6)
++ COPY_16_BYTES_WITHEX(7)
++#endif
++#endif
++#endif
++ bdnz 53b
++ cmpwi r0,0
++ li r3,4
++ li r7,0
++ bne 114b
++#endif /* CONFIG_8xx */
++
++63: srwi. r0,r5,2
++ mtctr r0
++ beq 64f
++30: lwzu r0,4(r4)
++31: stwu r0,4(r6)
++ bdnz 30b
++
++64: andi. r0,r5,3
++ mtctr r0
++ beq+ 65f
++40: lbz r0,4(r4)
++41: stb r0,4(r6)
++ addi r4,r4,1
++ addi r6,r6,1
++ bdnz 40b
++65: li r3,0
++ blr
++
++/* read fault, initial single-byte copy */
++100: li r9,0
++ b 90f
++/* write fault, initial single-byte copy */
++101: li r9,1
++90: subf r5,r8,r5
++ li r3,0
++ b 99f
++/* read fault, initial word copy */
++102: li r9,0
++ b 91f
++/* write fault, initial word copy */
++103: li r9,1
++91: li r3,2
++ b 99f
++
++/*
++ * this stuff handles faults in the cacheline loop and branches to either
++ * 104f (if in read part) or 105f (if in write part), after updating r5
++ */
++ COPY_16_BYTES_EXCODE(0)
++#if L1_CACHE_BYTES >= 32
++ COPY_16_BYTES_EXCODE(1)
++#if L1_CACHE_BYTES >= 64
++ COPY_16_BYTES_EXCODE(2)
++ COPY_16_BYTES_EXCODE(3)
++#if L1_CACHE_BYTES >= 128
++ COPY_16_BYTES_EXCODE(4)
++ COPY_16_BYTES_EXCODE(5)
++ COPY_16_BYTES_EXCODE(6)
++ COPY_16_BYTES_EXCODE(7)
++#endif
++#endif
++#endif
++
++/* read fault in cacheline loop */
++104: li r9,0
++ b 92f
++/* fault on dcbz (effectively a write fault) */
++/* or write fault in cacheline loop */
++105: li r9,1
++92: li r3,LG_CACHELINE_BYTES
++ mfctr r8
++ add r0,r0,r8
++ b 106f
++/* read fault in final word loop */
++108: li r9,0
++ b 93f
++/* write fault in final word loop */
++109: li r9,1
++93: andi. r5,r5,3
++ li r3,2
++ b 99f
++/* read fault in final byte loop */
++110: li r9,0
++ b 94f
++/* write fault in final byte loop */
++111: li r9,1
++94: li r5,0
++ li r3,0
++/*
++ * At this stage the number of bytes not copied is
++ * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
++ */
++99: mfctr r0
++106: slw r3,r0,r3
++ add. r3,r3,r5
++ beq 120f /* shouldn't happen */
++ cmpwi 0,r9,0
++ bne 120f
++/* for a read fault, first try to continue the copy one byte at a time */
++ mtctr r3
++130: lbz r0,4(r4)
++131: stb r0,4(r6)
++ addi r4,r4,1
++ addi r6,r6,1
++ bdnz 130b
++/* then clear out the destination: r3 bytes starting at 4(r6) */
++132: mfctr r3
++ srwi. r0,r3,2
++ li r9,0
++ mtctr r0
++ beq 113f
++112: stwu r9,4(r6)
++ bdnz 112b
++113: andi. r0,r3,3
++ mtctr r0
++ beq 120f
++114: stb r9,4(r6)
++ addi r6,r6,1
++ bdnz 114b
++120: blr
++
++ .section __ex_table,"a"
++ .align 2
++ .long 30b,108b
++ .long 31b,109b
++ .long 40b,110b
++ .long 41b,111b
++ .long 130b,132b
++ .long 131b,120b
++ .long 112b,120b
++ .long 114b,120b
++ .text
+diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/copypage_64.S
+@@ -0,0 +1,121 @@
++/*
++ * arch/ppc64/lib/copypage.S
++ *
++ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
++ *
++ * 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 <asm/processor.h>
++#include <asm/ppc_asm.h>
++
++_GLOBAL(copy_page)
++ std r31,-8(1)
++ std r30,-16(1)
++ std r29,-24(1)
++ std r28,-32(1)
++ std r27,-40(1)
++ std r26,-48(1)
++ std r25,-56(1)
++ std r24,-64(1)
++ std r23,-72(1)
++ std r22,-80(1)
++ std r21,-88(1)
++ std r20,-96(1)
++ li r5,4096/32 - 1
++ addi r3,r3,-8
++ li r12,5
++0: addi r5,r5,-24
++ mtctr r12
++ ld r22,640(4)
++ ld r21,512(4)
++ ld r20,384(4)
++ ld r11,256(4)
++ ld r9,128(4)
++ ld r7,0(4)
++ ld r25,648(4)
++ ld r24,520(4)
++ ld r23,392(4)
++ ld r10,264(4)
++ ld r8,136(4)
++ ldu r6,8(4)
++ cmpwi r5,24
++1: std r22,648(3)
++ std r21,520(3)
++ std r20,392(3)
++ std r11,264(3)
++ std r9,136(3)
++ std r7,8(3)
++ ld r28,648(4)
++ ld r27,520(4)
++ ld r26,392(4)
++ ld r31,264(4)
++ ld r30,136(4)
++ ld r29,8(4)
++ std r25,656(3)
++ std r24,528(3)
++ std r23,400(3)
++ std r10,272(3)
++ std r8,144(3)
++ std r6,16(3)
++ ld r22,656(4)
++ ld r21,528(4)
++ ld r20,400(4)
++ ld r11,272(4)
++ ld r9,144(4)
++ ld r7,16(4)
++ std r28,664(3)
++ std r27,536(3)
++ std r26,408(3)
++ std r31,280(3)
++ std r30,152(3)
++ stdu r29,24(3)
++ ld r25,664(4)
++ ld r24,536(4)
++ ld r23,408(4)
++ ld r10,280(4)
++ ld r8,152(4)
++ ldu r6,24(4)
++ bdnz 1b
++ std r22,648(3)
++ std r21,520(3)
++ std r20,392(3)
++ std r11,264(3)
++ std r9,136(3)
++ std r7,8(3)
++ addi r4,r4,640
++ addi r3,r3,648
++ bge 0b
++ mtctr r5
++ ld r7,0(4)
++ ld r8,8(4)
++ ldu r9,16(4)
++3: ld r10,8(4)
++ std r7,8(3)
++ ld r7,16(4)
++ std r8,16(3)
++ ld r8,24(4)
++ std r9,24(3)
++ ldu r9,32(4)
++ stdu r10,32(3)
++ bdnz 3b
++4: ld r10,8(4)
++ std r7,8(3)
++ std r8,16(3)
++ std r9,24(3)
++ std r10,32(3)
++9: ld r20,-96(1)
++ ld r21,-88(1)
++ ld r22,-80(1)
++ ld r23,-72(1)
++ ld r24,-64(1)
++ ld r25,-56(1)
++ ld r26,-48(1)
++ ld r27,-40(1)
++ ld r28,-32(1)
++ ld r29,-24(1)
++ ld r30,-16(1)
++ ld r31,-8(1)
++ blr
+diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/copyuser_64.S
+@@ -0,0 +1,576 @@
++/*
++ * arch/ppc64/lib/copyuser.S
++ *
++ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
++ *
++ * 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 <asm/processor.h>
++#include <asm/ppc_asm.h>
++
++ .align 7
++_GLOBAL(__copy_tofrom_user)
++ /* first check for a whole page copy on a page boundary */
++ cmpldi cr1,r5,16
++ cmpdi cr6,r5,4096
++ or r0,r3,r4
++ neg r6,r3 /* LS 3 bits = # bytes to 8-byte dest bdry */
++ andi. r0,r0,4095
++ std r3,-24(r1)
++ crand cr0*4+2,cr0*4+2,cr6*4+2
++ std r4,-16(r1)
++ std r5,-8(r1)
++ dcbt 0,r4
++ beq .Lcopy_page
++ andi. r6,r6,7
++ mtcrf 0x01,r5
++ blt cr1,.Lshort_copy
++ bne .Ldst_unaligned
++.Ldst_aligned:
++ andi. r0,r4,7
++ addi r3,r3,-16
++ bne .Lsrc_unaligned
++ srdi r7,r5,4
++20: ld r9,0(r4)
++ addi r4,r4,-8
++ mtctr r7
++ andi. r5,r5,7
++ bf cr7*4+0,22f
++ addi r3,r3,8
++ addi r4,r4,8
++ mr r8,r9
++ blt cr1,72f
++21: ld r9,8(r4)
++70: std r8,8(r3)
++22: ldu r8,16(r4)
++71: stdu r9,16(r3)
++ bdnz 21b
++72: std r8,8(r3)
++ beq+ 3f
++ addi r3,r3,16
++23: ld r9,8(r4)
++.Ldo_tail:
++ bf cr7*4+1,1f
++ rotldi r9,r9,32
++73: stw r9,0(r3)
++ addi r3,r3,4
++1: bf cr7*4+2,2f
++ rotldi r9,r9,16
++74: sth r9,0(r3)
++ addi r3,r3,2
++2: bf cr7*4+3,3f
++ rotldi r9,r9,8
++75: stb r9,0(r3)
++3: li r3,0
++ blr
++
++.Lsrc_unaligned:
++ srdi r6,r5,3
++ addi r5,r5,-16
++ subf r4,r0,r4
++ srdi r7,r5,4
++ sldi r10,r0,3
++ cmpldi cr6,r6,3
++ andi. r5,r5,7
++ mtctr r7
++ subfic r11,r10,64
++ add r5,r5,r0
++ bt cr7*4+0,28f
++
++24: ld r9,0(r4) /* 3+2n loads, 2+2n stores */
++25: ld r0,8(r4)
++ sld r6,r9,r10
++26: ldu r9,16(r4)
++ srd r7,r0,r11
++ sld r8,r0,r10
++ or r7,r7,r6
++ blt cr6,79f
++27: ld r0,8(r4)
++ b 2f
++
++28: ld r0,0(r4) /* 4+2n loads, 3+2n stores */
++29: ldu r9,8(r4)
++ sld r8,r0,r10
++ addi r3,r3,-8
++ blt cr6,5f
++30: ld r0,8(r4)
++ srd r12,r9,r11
++ sld r6,r9,r10
++31: ldu r9,16(r4)
++ or r12,r8,r12
++ srd r7,r0,r11
++ sld r8,r0,r10
++ addi r3,r3,16
++ beq cr6,78f
++
++1: or r7,r7,r6
++32: ld r0,8(r4)
++76: std r12,8(r3)
++2: srd r12,r9,r11
++ sld r6,r9,r10
++33: ldu r9,16(r4)
++ or r12,r8,r12
++77: stdu r7,16(r3)
++ srd r7,r0,r11
++ sld r8,r0,r10
++ bdnz 1b
++
++78: std r12,8(r3)
++ or r7,r7,r6
++79: std r7,16(r3)
++5: srd r12,r9,r11
++ or r12,r8,r12
++80: std r12,24(r3)
++ bne 6f
++ li r3,0
++ blr
++6: cmpwi cr1,r5,8
++ addi r3,r3,32
++ sld r9,r9,r10
++ ble cr1,.Ldo_tail
++34: ld r0,8(r4)
++ srd r7,r0,r11
++ or r9,r7,r9
++ b .Ldo_tail
++
++.Ldst_unaligned:
++ mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */
++ subf r5,r6,r5
++ li r7,0
++ cmpldi r1,r5,16
++ bf cr7*4+3,1f
++35: lbz r0,0(r4)
++81: stb r0,0(r3)
++ addi r7,r7,1
++1: bf cr7*4+2,2f
++36: lhzx r0,r7,r4
++82: sthx r0,r7,r3
++ addi r7,r7,2
++2: bf cr7*4+1,3f
++37: lwzx r0,r7,r4
++83: stwx r0,r7,r3
++3: mtcrf 0x01,r5
++ add r4,r6,r4
++ add r3,r6,r3
++ b .Ldst_aligned
++
++.Lshort_copy:
++ bf cr7*4+0,1f
++38: lwz r0,0(r4)
++39: lwz r9,4(r4)
++ addi r4,r4,8
++84: stw r0,0(r3)
++85: stw r9,4(r3)
++ addi r3,r3,8
++1: bf cr7*4+1,2f
++40: lwz r0,0(r4)
++ addi r4,r4,4
++86: stw r0,0(r3)
++ addi r3,r3,4
++2: bf cr7*4+2,3f
++41: lhz r0,0(r4)
++ addi r4,r4,2
++87: sth r0,0(r3)
++ addi r3,r3,2
++3: bf cr7*4+3,4f
++42: lbz r0,0(r4)
++88: stb r0,0(r3)
++4: li r3,0
++ blr
++
++/*
++ * exception handlers follow
++ * we have to return the number of bytes not copied
++ * for an exception on a load, we set the rest of the destination to 0
++ */
++
++136:
++137:
++ add r3,r3,r7
++ b 1f
++130:
++131:
++ addi r3,r3,8
++120:
++122:
++124:
++125:
++126:
++127:
++128:
++129:
++133:
++ addi r3,r3,8
++121:
++132:
++ addi r3,r3,8
++123:
++134:
++135:
++138:
++139:
++140:
++141:
++142:
++
++/*
++ * here we have had a fault on a load and r3 points to the first
++ * unmodified byte of the destination
++ */
++1: ld r6,-24(r1)
++ ld r4,-16(r1)
++ ld r5,-8(r1)
++ subf r6,r6,r3
++ add r4,r4,r6
++ subf r5,r6,r5 /* #bytes left to go */
++
++/*
++ * first see if we can copy any more bytes before hitting another exception
++ */
++ mtctr r5
++43: lbz r0,0(r4)
++ addi r4,r4,1
++89: stb r0,0(r3)
++ addi r3,r3,1
++ bdnz 43b
++ li r3,0 /* huh? all copied successfully this time? */
++ blr
++
++/*
++ * here we have trapped again, need to clear ctr bytes starting at r3
++ */
++143: mfctr r5
++ li r0,0
++ mr r4,r3
++ mr r3,r5 /* return the number of bytes not copied */
++1: andi. r9,r4,7
++ beq 3f
++90: stb r0,0(r4)
++ addic. r5,r5,-1
++ addi r4,r4,1
++ bne 1b
++ blr
++3: cmpldi cr1,r5,8
++ srdi r9,r5,3
++ andi. r5,r5,7
++ blt cr1,93f
++ mtctr r9
++91: std r0,0(r4)
++ addi r4,r4,8
++ bdnz 91b
++93: beqlr
++ mtctr r5
++92: stb r0,0(r4)
++ addi r4,r4,1
++ bdnz 92b
++ blr
++
++/*
++ * exception handlers for stores: we just need to work
++ * out how many bytes weren't copied
++ */
++182:
++183:
++ add r3,r3,r7
++ b 1f
++180:
++ addi r3,r3,8
++171:
++177:
++ addi r3,r3,8
++170:
++172:
++176:
++178:
++ addi r3,r3,4
++185:
++ addi r3,r3,4
++173:
++174:
++175:
++179:
++181:
++184:
++186:
++187:
++188:
++189:
++1:
++ ld r6,-24(r1)
++ ld r5,-8(r1)
++ add r6,r6,r5
++ subf r3,r3,r6 /* #bytes not copied */
++190:
++191:
++192:
++ blr /* #bytes not copied in r3 */
++
++ .section __ex_table,"a"
++ .align 3
++ .llong 20b,120b
++ .llong 21b,121b
++ .llong 70b,170b
++ .llong 22b,122b
++ .llong 71b,171b
++ .llong 72b,172b
++ .llong 23b,123b
++ .llong 73b,173b
++ .llong 74b,174b
++ .llong 75b,175b
++ .llong 24b,124b
++ .llong 25b,125b
++ .llong 26b,126b
++ .llong 27b,127b
++ .llong 28b,128b
++ .llong 29b,129b
++ .llong 30b,130b
++ .llong 31b,131b
++ .llong 32b,132b
++ .llong 76b,176b
++ .llong 33b,133b
++ .llong 77b,177b
++ .llong 78b,178b
++ .llong 79b,179b
++ .llong 80b,180b
++ .llong 34b,134b
++ .llong 35b,135b
++ .llong 81b,181b
++ .llong 36b,136b
++ .llong 82b,182b
++ .llong 37b,137b
++ .llong 83b,183b
++ .llong 38b,138b
++ .llong 39b,139b
++ .llong 84b,184b
++ .llong 85b,185b
++ .llong 40b,140b
++ .llong 86b,186b
++ .llong 41b,141b
++ .llong 87b,187b
++ .llong 42b,142b
++ .llong 88b,188b
++ .llong 43b,143b
++ .llong 89b,189b
++ .llong 90b,190b
++ .llong 91b,191b
++ .llong 92b,192b
++
++ .text
++
++/*
++ * Routine to copy a whole page of data, optimized for POWER4.
++ * On POWER4 it is more than 50% faster than the simple loop
++ * above (following the .Ldst_aligned label) but it runs slightly
++ * slower on POWER3.
++ */
++.Lcopy_page:
++ std r31,-32(1)
++ std r30,-40(1)
++ std r29,-48(1)
++ std r28,-56(1)
++ std r27,-64(1)
++ std r26,-72(1)
++ std r25,-80(1)
++ std r24,-88(1)
++ std r23,-96(1)
++ std r22,-104(1)
++ std r21,-112(1)
++ std r20,-120(1)
++ li r5,4096/32 - 1
++ addi r3,r3,-8
++ li r0,5
++0: addi r5,r5,-24
++ mtctr r0
++20: ld r22,640(4)
++21: ld r21,512(4)
++22: ld r20,384(4)
++23: ld r11,256(4)
++24: ld r9,128(4)
++25: ld r7,0(4)
++26: ld r25,648(4)
++27: ld r24,520(4)
++28: ld r23,392(4)
++29: ld r10,264(4)
++30: ld r8,136(4)
++31: ldu r6,8(4)
++ cmpwi r5,24
++1:
++32: std r22,648(3)
++33: std r21,520(3)
++34: std r20,392(3)
++35: std r11,264(3)
++36: std r9,136(3)
++37: std r7,8(3)
++38: ld r28,648(4)
++39: ld r27,520(4)
++40: ld r26,392(4)
++41: ld r31,264(4)
++42: ld r30,136(4)
++43: ld r29,8(4)
++44: std r25,656(3)
++45: std r24,528(3)
++46: std r23,400(3)
++47: std r10,272(3)
++48: std r8,144(3)
++49: std r6,16(3)
++50: ld r22,656(4)
++51: ld r21,528(4)
++52: ld r20,400(4)
++53: ld r11,272(4)
++54: ld r9,144(4)
++55: ld r7,16(4)
++56: std r28,664(3)
++57: std r27,536(3)
++58: std r26,408(3)
++59: std r31,280(3)
++60: std r30,152(3)
++61: stdu r29,24(3)
++62: ld r25,664(4)
++63: ld r24,536(4)
++64: ld r23,408(4)
++65: ld r10,280(4)
++66: ld r8,152(4)
++67: ldu r6,24(4)
++ bdnz 1b
++68: std r22,648(3)
++69: std r21,520(3)
++70: std r20,392(3)
++71: std r11,264(3)
++72: std r9,136(3)
++73: std r7,8(3)
++74: addi r4,r4,640
++75: addi r3,r3,648
++ bge 0b
++ mtctr r5
++76: ld r7,0(4)
++77: ld r8,8(4)
++78: ldu r9,16(4)
++3:
++79: ld r10,8(4)
++80: std r7,8(3)
++81: ld r7,16(4)
++82: std r8,16(3)
++83: ld r8,24(4)
++84: std r9,24(3)
++85: ldu r9,32(4)
++86: stdu r10,32(3)
++ bdnz 3b
++4:
++87: ld r10,8(4)
++88: std r7,8(3)
++89: std r8,16(3)
++90: std r9,24(3)
++91: std r10,32(3)
++9: ld r20,-120(1)
++ ld r21,-112(1)
++ ld r22,-104(1)
++ ld r23,-96(1)
++ ld r24,-88(1)
++ ld r25,-80(1)
++ ld r26,-72(1)
++ ld r27,-64(1)
++ ld r28,-56(1)
++ ld r29,-48(1)
++ ld r30,-40(1)
++ ld r31,-32(1)
++ li r3,0
++ blr
++
++/*
++ * on an exception, reset to the beginning and jump back into the
++ * standard __copy_tofrom_user
++ */
++100: ld r20,-120(1)
++ ld r21,-112(1)
++ ld r22,-104(1)
++ ld r23,-96(1)
++ ld r24,-88(1)
++ ld r25,-80(1)
++ ld r26,-72(1)
++ ld r27,-64(1)
++ ld r28,-56(1)
++ ld r29,-48(1)
++ ld r30,-40(1)
++ ld r31,-32(1)
++ ld r3,-24(r1)
++ ld r4,-16(r1)
++ li r5,4096
++ b .Ldst_aligned
++
++ .section __ex_table,"a"
++ .align 3
++ .llong 20b,100b
++ .llong 21b,100b
++ .llong 22b,100b
++ .llong 23b,100b
++ .llong 24b,100b
++ .llong 25b,100b
++ .llong 26b,100b
++ .llong 27b,100b
++ .llong 28b,100b
++ .llong 29b,100b
++ .llong 30b,100b
++ .llong 31b,100b
++ .llong 32b,100b
++ .llong 33b,100b
++ .llong 34b,100b
++ .llong 35b,100b
++ .llong 36b,100b
++ .llong 37b,100b
++ .llong 38b,100b
++ .llong 39b,100b
++ .llong 40b,100b
++ .llong 41b,100b
++ .llong 42b,100b
++ .llong 43b,100b
++ .llong 44b,100b
++ .llong 45b,100b
++ .llong 46b,100b
++ .llong 47b,100b
++ .llong 48b,100b
++ .llong 49b,100b
++ .llong 50b,100b
++ .llong 51b,100b
++ .llong 52b,100b
++ .llong 53b,100b
++ .llong 54b,100b
++ .llong 55b,100b
++ .llong 56b,100b
++ .llong 57b,100b
++ .llong 58b,100b
++ .llong 59b,100b
++ .llong 60b,100b
++ .llong 61b,100b
++ .llong 62b,100b
++ .llong 63b,100b
++ .llong 64b,100b
++ .llong 65b,100b
++ .llong 66b,100b
++ .llong 67b,100b
++ .llong 68b,100b
++ .llong 69b,100b
++ .llong 70b,100b
++ .llong 71b,100b
++ .llong 72b,100b
++ .llong 73b,100b
++ .llong 74b,100b
++ .llong 75b,100b
++ .llong 76b,100b
++ .llong 77b,100b
++ .llong 78b,100b
++ .llong 79b,100b
++ .llong 80b,100b
++ .llong 81b,100b
++ .llong 82b,100b
++ .llong 83b,100b
++ .llong 84b,100b
++ .llong 85b,100b
++ .llong 86b,100b
++ .llong 87b,100b
++ .llong 88b,100b
++ .llong 89b,100b
++ .llong 90b,100b
++ .llong 91b,100b
+diff --git a/arch/powerpc/lib/div64.S b/arch/powerpc/lib/div64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/div64.S
+@@ -0,0 +1,59 @@
++/*
++ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
++ * This routine assumes that the top 32 bits of the dividend are
++ * non-zero to start with.
++ * On entry, r3 points to the dividend, which get overwritten with
++ * the 64-bit quotient, and r4 contains the divisor.
++ * On exit, r3 contains the remainder.
++ *
++ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
++ *
++ * 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 <asm/ppc_asm.h>
++#include <asm/processor.h>
++
++_GLOBAL(__div64_32)
++ lwz r5,0(r3) # get the dividend into r5/r6
++ lwz r6,4(r3)
++ cmplw r5,r4
++ li r7,0
++ li r8,0
++ blt 1f
++ divwu r7,r5,r4 # if dividend.hi >= divisor,
++ mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
++ subf. r5,r0,r5 # dividend.hi %= divisor
++ beq 3f
++1: mr r11,r5 # here dividend.hi != 0
++ andis. r0,r5,0xc000
++ bne 2f
++ cntlzw r0,r5 # we are shifting the dividend right
++ li r10,-1 # to make it < 2^32, and shifting
++ srw r10,r10,r0 # the divisor right the same amount,
++ addc r9,r4,r10 # rounding up (so the estimate cannot
++ andc r11,r6,r10 # ever be too large, only too small)
++ andc r9,r9,r10
++ addze r9,r9
++ or r11,r5,r11
++ rotlw r9,r9,r0
++ rotlw r11,r11,r0
++ divwu r11,r11,r9 # then we divide the shifted quantities
++2: mullw r10,r11,r4 # to get an estimate of the quotient,
++ mulhwu r9,r11,r4 # multiply the estimate by the divisor,
++ subfc r6,r10,r6 # take the product from the divisor,
++ add r8,r8,r11 # and add the estimate to the accumulated
++ subfe. r5,r9,r5 # quotient
++ bne 1b
++3: cmplw r6,r4
++ blt 4f
++ divwu r0,r6,r4 # perform the remaining 32-bit division
++ mullw r10,r0,r4 # and get the remainder
++ add r8,r8,r0
++ subf r6,r10,r6
++4: stw r7,0(r3) # return the quotient in *r3
++ stw r8,4(r3)
++ mr r3,r6 # return the remainder in r3
++ blr
+diff --git a/arch/powerpc/lib/e2a.c b/arch/powerpc/lib/e2a.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/e2a.c
+@@ -0,0 +1,108 @@
++/*
++ * arch/ppc64/lib/e2a.c
++ *
++ * EBCDIC to ASCII conversion
++ *
++ * This function moved here from arch/ppc64/kernel/viopath.c
++ *
++ * (C) Copyright 2000-2004 IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) anyu 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/module.h>
++
++unsigned char e2a(unsigned char x)
++{
++ switch (x) {
++ case 0xF0:
++ return '0';
++ case 0xF1:
++ return '1';
++ case 0xF2:
++ return '2';
++ case 0xF3:
++ return '3';
++ case 0xF4:
++ return '4';
++ case 0xF5:
++ return '5';
++ case 0xF6:
++ return '6';
++ case 0xF7:
++ return '7';
++ case 0xF8:
++ return '8';
++ case 0xF9:
++ return '9';
++ case 0xC1:
++ return 'A';
++ case 0xC2:
++ return 'B';
++ case 0xC3:
++ return 'C';
++ case 0xC4:
++ return 'D';
++ case 0xC5:
++ return 'E';
++ case 0xC6:
++ return 'F';
++ case 0xC7:
++ return 'G';
++ case 0xC8:
++ return 'H';
++ case 0xC9:
++ return 'I';
++ case 0xD1:
++ return 'J';
++ case 0xD2:
++ return 'K';
++ case 0xD3:
++ return 'L';
++ case 0xD4:
++ return 'M';
++ case 0xD5:
++ return 'N';
++ case 0xD6:
++ return 'O';
++ case 0xD7:
++ return 'P';
++ case 0xD8:
++ return 'Q';
++ case 0xD9:
++ return 'R';
++ case 0xE2:
++ return 'S';
++ case 0xE3:
++ return 'T';
++ case 0xE4:
++ return 'U';
++ case 0xE5:
++ return 'V';
++ case 0xE6:
++ return 'W';
++ case 0xE7:
++ return 'X';
++ case 0xE8:
++ return 'Y';
++ case 0xE9:
++ return 'Z';
++ }
++ return ' ';
++}
++EXPORT_SYMBOL(e2a);
++
++
+diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/locks.c
+@@ -0,0 +1,96 @@
++/*
++ * Spin and read/write lock operations.
++ *
++ * Copyright (C) 2001-2004 Paul Mackerras <paulus at au.ibm.com>, IBM
++ * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
++ * Copyright (C) 2002 Dave Engebretsen <engebret at us.ibm.com>, IBM
++ * Rework to support virtual processors
++ *
++ * 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/spinlock.h>
++#include <linux/module.h>
++#include <linux/stringify.h>
++#include <linux/smp.h>
++
++/* waiting for a spinlock... */
++#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
++#include <asm/hvcall.h>
++#include <asm/iSeries/HvCall.h>
++
++void __spin_yield(raw_spinlock_t *lock)
++{
++ unsigned int lock_value, holder_cpu, yield_count;
++ struct paca_struct *holder_paca;
++
++ lock_value = lock->slock;
++ if (lock_value == 0)
++ return;
++ holder_cpu = lock_value & 0xffff;
++ BUG_ON(holder_cpu >= NR_CPUS);
++ holder_paca = &paca[holder_cpu];
++ yield_count = holder_paca->lppaca.yield_count;
++ if ((yield_count & 1) == 0)
++ return; /* virtual cpu is currently running */
++ rmb();
++ if (lock->slock != lock_value)
++ return; /* something has changed */
++#ifdef CONFIG_PPC_ISERIES
++ HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
++ ((u64)holder_cpu << 32) | yield_count);
++#else
++ plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
++ yield_count);
++#endif
++}
++
++/*
++ * Waiting for a read lock or a write lock on a rwlock...
++ * This turns out to be the same for read and write locks, since
++ * we only know the holder if it is write-locked.
++ */
++void __rw_yield(raw_rwlock_t *rw)
++{
++ int lock_value;
++ unsigned int holder_cpu, yield_count;
++ struct paca_struct *holder_paca;
++
++ lock_value = rw->lock;
++ if (lock_value >= 0)
++ return; /* no write lock at present */
++ holder_cpu = lock_value & 0xffff;
++ BUG_ON(holder_cpu >= NR_CPUS);
++ holder_paca = &paca[holder_cpu];
++ yield_count = holder_paca->lppaca.yield_count;
++ if ((yield_count & 1) == 0)
++ return; /* virtual cpu is currently running */
++ rmb();
++ if (rw->lock != lock_value)
++ return; /* something has changed */
++#ifdef CONFIG_PPC_ISERIES
++ HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
++ ((u64)holder_cpu << 32) | yield_count);
++#else
++ plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
++ yield_count);
++#endif
++}
++#endif
++
++void __raw_spin_unlock_wait(raw_spinlock_t *lock)
++{
++ while (lock->slock) {
++ HMT_low();
++ if (SHARED_PROCESSOR)
++ __spin_yield(lock);
++ }
++ HMT_medium();
++}
++
++EXPORT_SYMBOL(__raw_spin_unlock_wait);
+diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/mem_64.S
+@@ -0,0 +1,119 @@
++/*
++ * String handling functions for PowerPC.
++ *
++ * Copyright (C) 1996 Paul Mackerras.
++ *
++ * 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 <asm/processor.h>
++#include <asm/errno.h>
++#include <asm/ppc_asm.h>
++
++_GLOBAL(memset)
++ neg r0,r3
++ rlwimi r4,r4,8,16,23
++ andi. r0,r0,7 /* # bytes to be 8-byte aligned */
++ rlwimi r4,r4,16,0,15
++ cmplw cr1,r5,r0 /* do we get that far? */
++ rldimi r4,r4,32,0
++ mtcrf 1,r0
++ mr r6,r3
++ blt cr1,8f
++ beq+ 3f /* if already 8-byte aligned */
++ subf r5,r0,r5
++ bf 31,1f
++ stb r4,0(r6)
++ addi r6,r6,1
++1: bf 30,2f
++ sth r4,0(r6)
++ addi r6,r6,2
++2: bf 29,3f
++ stw r4,0(r6)
++ addi r6,r6,4
++3: srdi. r0,r5,6
++ clrldi r5,r5,58
++ mtctr r0
++ beq 5f
++4: std r4,0(r6)
++ std r4,8(r6)
++ std r4,16(r6)
++ std r4,24(r6)
++ std r4,32(r6)
++ std r4,40(r6)
++ std r4,48(r6)
++ std r4,56(r6)
++ addi r6,r6,64
++ bdnz 4b
++5: srwi. r0,r5,3
++ clrlwi r5,r5,29
++ mtcrf 1,r0
++ beq 8f
++ bf 29,6f
++ std r4,0(r6)
++ std r4,8(r6)
++ std r4,16(r6)
++ std r4,24(r6)
++ addi r6,r6,32
++6: bf 30,7f
++ std r4,0(r6)
++ std r4,8(r6)
++ addi r6,r6,16
++7: bf 31,8f
++ std r4,0(r6)
++ addi r6,r6,8
++8: cmpwi r5,0
++ mtcrf 1,r5
++ beqlr+
++ bf 29,9f
++ stw r4,0(r6)
++ addi r6,r6,4
++9: bf 30,10f
++ sth r4,0(r6)
++ addi r6,r6,2
++10: bflr 31
++ stb r4,0(r6)
++ blr
++
++_GLOBAL(memmove)
++ cmplw 0,r3,r4
++ bgt .backwards_memcpy
++ b .memcpy
++
++_GLOBAL(backwards_memcpy)
++ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
++ add r6,r3,r5
++ add r4,r4,r5
++ beq 2f
++ andi. r0,r6,3
++ mtctr r7
++ bne 5f
++1: lwz r7,-4(r4)
++ lwzu r8,-8(r4)
++ stw r7,-4(r6)
++ stwu r8,-8(r6)
++ bdnz 1b
++ andi. r5,r5,7
++2: cmplwi 0,r5,4
++ blt 3f
++ lwzu r0,-4(r4)
++ subi r5,r5,4
++ stwu r0,-4(r6)
++3: cmpwi 0,r5,0
++ beqlr
++ mtctr r5
++4: lbzu r0,-1(r4)
++ stbu r0,-1(r6)
++ bdnz 4b
++ blr
++5: mtctr r0
++6: lbzu r7,-1(r4)
++ stbu r7,-1(r6)
++ bdnz 6b
++ subf r5,r0,r5
++ rlwinm. r7,r5,32-3,3,31
++ beq 2b
++ mtctr r7
++ b 1b
+diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/memcpy_64.S
+@@ -0,0 +1,172 @@
++/*
++ * arch/ppc64/lib/memcpy.S
++ *
++ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
++ *
++ * 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 <asm/processor.h>
++#include <asm/ppc_asm.h>
++
++ .align 7
++_GLOBAL(memcpy)
++ mtcrf 0x01,r5
++ cmpldi cr1,r5,16
++ neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
++ andi. r6,r6,7
++ dcbt 0,r4
++ blt cr1,.Lshort_copy
++ bne .Ldst_unaligned
++.Ldst_aligned:
++ andi. r0,r4,7
++ addi r3,r3,-16
++ bne .Lsrc_unaligned
++ srdi r7,r5,4
++ ld r9,0(r4)
++ addi r4,r4,-8
++ mtctr r7
++ andi. r5,r5,7
++ bf cr7*4+0,2f
++ addi r3,r3,8
++ addi r4,r4,8
++ mr r8,r9
++ blt cr1,3f
++1: ld r9,8(r4)
++ std r8,8(r3)
++2: ldu r8,16(r4)
++ stdu r9,16(r3)
++ bdnz 1b
++3: std r8,8(r3)
++ beqlr
++ addi r3,r3,16
++ ld r9,8(r4)
++.Ldo_tail:
++ bf cr7*4+1,1f
++ rotldi r9,r9,32
++ stw r9,0(r3)
++ addi r3,r3,4
++1: bf cr7*4+2,2f
++ rotldi r9,r9,16
++ sth r9,0(r3)
++ addi r3,r3,2
++2: bf cr7*4+3,3f
++ rotldi r9,r9,8
++ stb r9,0(r3)
++3: blr
++
++.Lsrc_unaligned:
++ srdi r6,r5,3
++ addi r5,r5,-16
++ subf r4,r0,r4
++ srdi r7,r5,4
++ sldi r10,r0,3
++ cmpdi cr6,r6,3
++ andi. r5,r5,7
++ mtctr r7
++ subfic r11,r10,64
++ add r5,r5,r0
++
++ bt cr7*4+0,0f
++
++ ld r9,0(r4) # 3+2n loads, 2+2n stores
++ ld r0,8(r4)
++ sld r6,r9,r10
++ ldu r9,16(r4)
++ srd r7,r0,r11
++ sld r8,r0,r10
++ or r7,r7,r6
++ blt cr6,4f
++ ld r0,8(r4)
++ # s1<< in r8, d0=(s0<<|s1>>) in r7, s3 in r0, s2 in r9, nix in r6 & r12
++ b 2f
++
++0: ld r0,0(r4) # 4+2n loads, 3+2n stores
++ ldu r9,8(r4)
++ sld r8,r0,r10
++ addi r3,r3,-8
++ blt cr6,5f
++ ld r0,8(r4)
++ srd r12,r9,r11
++ sld r6,r9,r10
++ ldu r9,16(r4)
++ or r12,r8,r12
++ srd r7,r0,r11
++ sld r8,r0,r10
++ addi r3,r3,16
++ beq cr6,3f
++
++ # d0=(s0<<|s1>>) in r12, s1<< in r6, s2>> in r7, s2<< in r8, s3 in r9
++1: or r7,r7,r6
++ ld r0,8(r4)
++ std r12,8(r3)
++2: srd r12,r9,r11
++ sld r6,r9,r10
++ ldu r9,16(r4)
++ or r12,r8,r12
++ stdu r7,16(r3)
++ srd r7,r0,r11
++ sld r8,r0,r10
++ bdnz 1b
++
++3: std r12,8(r3)
++ or r7,r7,r6
++4: std r7,16(r3)
++5: srd r12,r9,r11
++ or r12,r8,r12
++ std r12,24(r3)
++ beqlr
++ cmpwi cr1,r5,8
++ addi r3,r3,32
++ sld r9,r9,r10
++ ble cr1,.Ldo_tail
++ ld r0,8(r4)
++ srd r7,r0,r11
++ or r9,r7,r9
++ b .Ldo_tail
++
++.Ldst_unaligned:
++ mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7
++ subf r5,r6,r5
++ li r7,0
++ cmpldi r1,r5,16
++ bf cr7*4+3,1f
++ lbz r0,0(r4)
++ stb r0,0(r3)
++ addi r7,r7,1
++1: bf cr7*4+2,2f
++ lhzx r0,r7,r4
++ sthx r0,r7,r3
++ addi r7,r7,2
++2: bf cr7*4+1,3f
++ lwzx r0,r7,r4
++ stwx r0,r7,r3
++3: mtcrf 0x01,r5
++ add r4,r6,r4
++ add r3,r6,r3
++ b .Ldst_aligned
++
++.Lshort_copy:
++ bf cr7*4+0,1f
++ lwz r0,0(r4)
++ lwz r9,4(r4)
++ addi r4,r4,8
++ stw r0,0(r3)
++ stw r9,4(r3)
++ addi r3,r3,8
++1: bf cr7*4+1,2f
++ lwz r0,0(r4)
++ addi r4,r4,4
++ stw r0,0(r3)
++ addi r3,r3,4
++2: bf cr7*4+2,3f
++ lhz r0,0(r4)
++ addi r4,r4,2
++ sth r0,0(r3)
++ addi r3,r3,2
++3: bf cr7*4+3,4f
++ lbz r0,0(r4)
++ stb r0,0(r3)
++4: blr
+diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/rheap.c
+@@ -0,0 +1,693 @@
++/*
++ * arch/ppc/syslib/rheap.c
++ *
++ * A Remote Heap. Remote means that we don't touch the memory that the
++ * heap points to. Normal heap implementations use the memory they manage
++ * to place their list. We cannot do that because the memory we manage may
++ * have special properties, for example it is uncachable or of different
++ * endianess.
++ *
++ * Author: Pantelis Antoniou <panto at intracom.gr>
++ *
++ * 2004 (c) INTRACOM S.A. Greece. 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/types.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++
++#include <asm/rheap.h>
++
++/*
++ * Fixup a list_head, needed when copying lists. If the pointers fall
++ * between s and e, apply the delta. This assumes that
++ * sizeof(struct list_head *) == sizeof(unsigned long *).
++ */
++static inline void fixup(unsigned long s, unsigned long e, int d,
++ struct list_head *l)
++{
++ unsigned long *pp;
++
++ pp = (unsigned long *)&l->next;
++ if (*pp >= s && *pp < e)
++ *pp += d;
++
++ pp = (unsigned long *)&l->prev;
++ if (*pp >= s && *pp < e)
++ *pp += d;
++}
++
++/* Grow the allocated blocks */
++static int grow(rh_info_t * info, int max_blocks)
++{
++ rh_block_t *block, *blk;
++ int i, new_blocks;
++ int delta;
++ unsigned long blks, blke;
++
++ if (max_blocks <= info->max_blocks)
++ return -EINVAL;
++
++ new_blocks = max_blocks - info->max_blocks;
++
++ block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
++ if (block == NULL)
++ return -ENOMEM;
++
++ if (info->max_blocks > 0) {
++
++ /* copy old block area */
++ memcpy(block, info->block,
++ sizeof(rh_block_t) * info->max_blocks);
++
++ delta = (char *)block - (char *)info->block;
++
++ /* and fixup list pointers */
++ blks = (unsigned long)info->block;
++ blke = (unsigned long)(info->block + info->max_blocks);
++
++ for (i = 0, blk = block; i < info->max_blocks; i++, blk++)
++ fixup(blks, blke, delta, &blk->list);
++
++ fixup(blks, blke, delta, &info->empty_list);
++ fixup(blks, blke, delta, &info->free_list);
++ fixup(blks, blke, delta, &info->taken_list);
++
++ /* free the old allocated memory */
++ if ((info->flags & RHIF_STATIC_BLOCK) == 0)
++ kfree(info->block);
++ }
++
++ info->block = block;
++ info->empty_slots += new_blocks;
++ info->max_blocks = max_blocks;
++ info->flags &= ~RHIF_STATIC_BLOCK;
++
++ /* add all new blocks to the free list */
++ for (i = 0, blk = block + info->max_blocks; i < new_blocks; i++, blk++)
++ list_add(&blk->list, &info->empty_list);
++
++ return 0;
++}
++
++/*
++ * Assure at least the required amount of empty slots. If this function
++ * causes a grow in the block area then all pointers kept to the block
++ * area are invalid!
++ */
++static int assure_empty(rh_info_t * info, int slots)
++{
++ int max_blocks;
++
++ /* This function is not meant to be used to grow uncontrollably */
++ if (slots >= 4)
++ return -EINVAL;
++
++ /* Enough space */
++ if (info->empty_slots >= slots)
++ return 0;
++
++ /* Next 16 sized block */
++ max_blocks = ((info->max_blocks + slots) + 15) & ~15;
++
++ return grow(info, max_blocks);
++}
++
++static rh_block_t *get_slot(rh_info_t * info)
++{
++ rh_block_t *blk;
++
++ /* If no more free slots, and failure to extend. */
++ /* XXX: You should have called assure_empty before */
++ if (info->empty_slots == 0) {
++ printk(KERN_ERR "rh: out of slots; crash is imminent.\n");
++ return NULL;
++ }
++
++ /* Get empty slot to use */
++ blk = list_entry(info->empty_list.next, rh_block_t, list);
++ list_del_init(&blk->list);
++ info->empty_slots--;
++
++ /* Initialize */
++ blk->start = NULL;
++ blk->size = 0;
++ blk->owner = NULL;
++
++ return blk;
++}
++
++static inline void release_slot(rh_info_t * info, rh_block_t * blk)
++{
++ list_add(&blk->list, &info->empty_list);
++ info->empty_slots++;
++}
++
++static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
++{
++ rh_block_t *blk;
++ rh_block_t *before;
++ rh_block_t *after;
++ rh_block_t *next;
++ int size;
++ unsigned long s, e, bs, be;
++ struct list_head *l;
++
++ /* We assume that they are aligned properly */
++ size = blkn->size;
++ s = (unsigned long)blkn->start;
++ e = s + size;
++
++ /* Find the blocks immediately before and after the given one
++ * (if any) */
++ before = NULL;
++ after = NULL;
++ next = NULL;
++
++ list_for_each(l, &info->free_list) {
++ blk = list_entry(l, rh_block_t, list);
++
++ bs = (unsigned long)blk->start;
++ be = bs + blk->size;
++
++ if (next == NULL && s >= bs)
++ next = blk;
++
++ if (be == s)
++ before = blk;
++
++ if (e == bs)
++ after = blk;
++
++ /* If both are not null, break now */
++ if (before != NULL && after != NULL)
++ break;
++ }
++
++ /* Now check if they are really adjacent */
++ if (before != NULL && s != (unsigned long)before->start + before->size)
++ before = NULL;
++
++ if (after != NULL && e != (unsigned long)after->start)
++ after = NULL;
++
++ /* No coalescing; list insert and return */
++ if (before == NULL && after == NULL) {
++
++ if (next != NULL)
++ list_add(&blkn->list, &next->list);
++ else
++ list_add(&blkn->list, &info->free_list);
++
++ return;
++ }
++
++ /* We don't need it anymore */
++ release_slot(info, blkn);
++
++ /* Grow the before block */
++ if (before != NULL && after == NULL) {
++ before->size += size;
++ return;
++ }
++
++ /* Grow the after block backwards */
++ if (before == NULL && after != NULL) {
++ after->start = (int8_t *)after->start - size;
++ after->size += size;
++ return;
++ }
++
++ /* Grow the before block, and release the after block */
++ before->size += size + after->size;
++ list_del(&after->list);
++ release_slot(info, after);
++}
++
++static void attach_taken_block(rh_info_t * info, rh_block_t * blkn)
++{
++ rh_block_t *blk;
++ struct list_head *l;
++
++ /* Find the block immediately before the given one (if any) */
++ list_for_each(l, &info->taken_list) {
++ blk = list_entry(l, rh_block_t, list);
++ if (blk->start > blkn->start) {
++ list_add_tail(&blkn->list, &blk->list);
++ return;
++ }
++ }
++
++ list_add_tail(&blkn->list, &info->taken_list);
++}
++
++/*
++ * Create a remote heap dynamically. Note that no memory for the blocks
++ * are allocated. It will upon the first allocation
++ */
++rh_info_t *rh_create(unsigned int alignment)
++{
++ rh_info_t *info;
++
++ /* Alignment must be a power of two */
++ if ((alignment & (alignment - 1)) != 0)
++ return ERR_PTR(-EINVAL);
++
++ info = kmalloc(sizeof(*info), GFP_KERNEL);
++ if (info == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ info->alignment = alignment;
++
++ /* Initially everything as empty */
++ info->block = NULL;
++ info->max_blocks = 0;
++ info->empty_slots = 0;
++ info->flags = 0;
++
++ INIT_LIST_HEAD(&info->empty_list);
++ INIT_LIST_HEAD(&info->free_list);
++ INIT_LIST_HEAD(&info->taken_list);
++
++ return info;
++}
++
++/*
++ * Destroy a dynamically created remote heap. Deallocate only if the areas
++ * are not static
++ */
++void rh_destroy(rh_info_t * info)
++{
++ if ((info->flags & RHIF_STATIC_BLOCK) == 0 && info->block != NULL)
++ kfree(info->block);
++
++ if ((info->flags & RHIF_STATIC_INFO) == 0)
++ kfree(info);
++}
++
++/*
++ * Initialize in place a remote heap info block. This is needed to support
++ * operation very early in the startup of the kernel, when it is not yet safe
++ * to call kmalloc.
++ */
++void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
++ rh_block_t * block)
++{
++ int i;
++ rh_block_t *blk;
++
++ /* Alignment must be a power of two */
++ if ((alignment & (alignment - 1)) != 0)
++ return;
++
++ info->alignment = alignment;
++
++ /* Initially everything as empty */
++ info->block = block;
++ info->max_blocks = max_blocks;
++ info->empty_slots = max_blocks;
++ info->flags = RHIF_STATIC_INFO | RHIF_STATIC_BLOCK;
++
++ INIT_LIST_HEAD(&info->empty_list);
++ INIT_LIST_HEAD(&info->free_list);
++ INIT_LIST_HEAD(&info->taken_list);
++
++ /* Add all new blocks to the free list */
++ for (i = 0, blk = block; i < max_blocks; i++, blk++)
++ list_add(&blk->list, &info->empty_list);
++}
++
++/* Attach a free memory region, coalesces regions if adjuscent */
++int rh_attach_region(rh_info_t * info, void *start, int size)
++{
++ rh_block_t *blk;
++ unsigned long s, e, m;
++ int r;
++
++ /* The region must be aligned */
++ s = (unsigned long)start;
++ e = s + size;
++ m = info->alignment - 1;
++
++ /* Round start up */
++ s = (s + m) & ~m;
++
++ /* Round end down */
++ e = e & ~m;
++
++ /* Take final values */
++ start = (void *)s;
++ size = (int)(e - s);
++
++ /* Grow the blocks, if needed */
++ r = assure_empty(info, 1);
++ if (r < 0)
++ return r;
++
++ blk = get_slot(info);
++ blk->start = start;
++ blk->size = size;
++ blk->owner = NULL;
++
++ attach_free_block(info, blk);
++
++ return 0;
++}
++
++/* Detatch given address range, splits free block if needed. */
++void *rh_detach_region(rh_info_t * info, void *start, int size)
++{
++ struct list_head *l;
++ rh_block_t *blk, *newblk;
++ unsigned long s, e, m, bs, be;
++
++ /* Validate size */
++ if (size <= 0)
++ return ERR_PTR(-EINVAL);
++
++ /* The region must be aligned */
++ s = (unsigned long)start;
++ e = s + size;
++ m = info->alignment - 1;
++
++ /* Round start up */
++ s = (s + m) & ~m;
++
++ /* Round end down */
++ e = e & ~m;
++
++ if (assure_empty(info, 1) < 0)
++ return ERR_PTR(-ENOMEM);
++
++ blk = NULL;
++ list_for_each(l, &info->free_list) {
++ blk = list_entry(l, rh_block_t, list);
++ /* The range must lie entirely inside one free block */
++ bs = (unsigned long)blk->start;
++ be = (unsigned long)blk->start + blk->size;
++ if (s >= bs && e <= be)
++ break;
++ blk = NULL;
++ }
++
++ if (blk == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ /* Perfect fit */
++ if (bs == s && be == e) {
++ /* Delete from free list, release slot */
++ list_del(&blk->list);
++ release_slot(info, blk);
++ return (void *)s;
++ }
++
++ /* blk still in free list, with updated start and/or size */
++ if (bs == s || be == e) {
++ if (bs == s)
++ blk->start = (int8_t *)blk->start + size;
++ blk->size -= size;
++
++ } else {
++ /* The front free fragment */
++ blk->size = s - bs;
++
++ /* the back free fragment */
++ newblk = get_slot(info);
++ newblk->start = (void *)e;
++ newblk->size = be - e;
++
++ list_add(&newblk->list, &blk->list);
++ }
++
++ return (void *)s;
++}
++
++void *rh_alloc(rh_info_t * info, int size, const char *owner)
++{
++ struct list_head *l;
++ rh_block_t *blk;
++ rh_block_t *newblk;
++ void *start;
++
++ /* Validate size */
++ if (size <= 0)
++ return ERR_PTR(-EINVAL);
++
++ /* Align to configured alignment */
++ size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
++
++ if (assure_empty(info, 1) < 0)
++ return ERR_PTR(-ENOMEM);
++
++ blk = NULL;
++ list_for_each(l, &info->free_list) {
++ blk = list_entry(l, rh_block_t, list);
++ if (size <= blk->size)
++ break;
++ blk = NULL;
++ }
++
++ if (blk == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ /* Just fits */
++ if (blk->size == size) {
++ /* Move from free list to taken list */
++ list_del(&blk->list);
++ blk->owner = owner;
++ start = blk->start;
++
++ attach_taken_block(info, blk);
++
++ return start;
++ }
++
++ newblk = get_slot(info);
++ newblk->start = blk->start;
++ newblk->size = size;
++ newblk->owner = owner;
++
++ /* blk still in free list, with updated start, size */
++ blk->start = (int8_t *)blk->start + size;
++ blk->size -= size;
++
++ start = newblk->start;
++
++ attach_taken_block(info, newblk);
++
++ return start;
++}
++
++/* allocate at precisely the given address */
++void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
++{
++ struct list_head *l;
++ rh_block_t *blk, *newblk1, *newblk2;
++ unsigned long s, e, m, bs, be;
++
++ /* Validate size */
++ if (size <= 0)
++ return ERR_PTR(-EINVAL);
++
++ /* The region must be aligned */
++ s = (unsigned long)start;
++ e = s + size;
++ m = info->alignment - 1;
++
++ /* Round start up */
++ s = (s + m) & ~m;
++
++ /* Round end down */
++ e = e & ~m;
++
++ if (assure_empty(info, 2) < 0)
++ return ERR_PTR(-ENOMEM);
++
++ blk = NULL;
++ list_for_each(l, &info->free_list) {
++ blk = list_entry(l, rh_block_t, list);
++ /* The range must lie entirely inside one free block */
++ bs = (unsigned long)blk->start;
++ be = (unsigned long)blk->start + blk->size;
++ if (s >= bs && e <= be)
++ break;
++ }
++
++ if (blk == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ /* Perfect fit */
++ if (bs == s && be == e) {
++ /* Move from free list to taken list */
++ list_del(&blk->list);
++ blk->owner = owner;
++
++ start = blk->start;
++ attach_taken_block(info, blk);
++
++ return start;
++
++ }
++
++ /* blk still in free list, with updated start and/or size */
++ if (bs == s || be == e) {
++ if (bs == s)
++ blk->start = (int8_t *)blk->start + size;
++ blk->size -= size;
++
++ } else {
++ /* The front free fragment */
++ blk->size = s - bs;
++
++ /* The back free fragment */
++ newblk2 = get_slot(info);
++ newblk2->start = (void *)e;
++ newblk2->size = be - e;
++
++ list_add(&newblk2->list, &blk->list);
++ }
++
++ newblk1 = get_slot(info);
++ newblk1->start = (void *)s;
++ newblk1->size = e - s;
++ newblk1->owner = owner;
++
++ start = newblk1->start;
++ attach_taken_block(info, newblk1);
++
++ return start;
++}
++
++int rh_free(rh_info_t * info, void *start)
++{
++ rh_block_t *blk, *blk2;
++ struct list_head *l;
++ int size;
++
++ /* Linear search for block */
++ blk = NULL;
++ list_for_each(l, &info->taken_list) {
++ blk2 = list_entry(l, rh_block_t, list);
++ if (start < blk2->start)
++ break;
++ blk = blk2;
++ }
++
++ if (blk == NULL || start > (blk->start + blk->size))
++ return -EINVAL;
++
++ /* Remove from taken list */
++ list_del(&blk->list);
++
++ /* Get size of freed block */
++ size = blk->size;
++ attach_free_block(info, blk);
++
++ return size;
++}
++
++int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
++{
++ rh_block_t *blk;
++ struct list_head *l;
++ struct list_head *h;
++ int nr;
++
++ switch (what) {
++
++ case RHGS_FREE:
++ h = &info->free_list;
++ break;
++
++ case RHGS_TAKEN:
++ h = &info->taken_list;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ /* Linear search for block */
++ nr = 0;
++ list_for_each(l, h) {
++ blk = list_entry(l, rh_block_t, list);
++ if (stats != NULL && nr < max_stats) {
++ stats->start = blk->start;
++ stats->size = blk->size;
++ stats->owner = blk->owner;
++ stats++;
++ }
++ nr++;
++ }
++
++ return nr;
++}
++
++int rh_set_owner(rh_info_t * info, void *start, const char *owner)
++{
++ rh_block_t *blk, *blk2;
++ struct list_head *l;
++ int size;
++
++ /* Linear search for block */
++ blk = NULL;
++ list_for_each(l, &info->taken_list) {
++ blk2 = list_entry(l, rh_block_t, list);
++ if (start < blk2->start)
++ break;
++ blk = blk2;
++ }
++
++ if (blk == NULL || start > (blk->start + blk->size))
++ return -EINVAL;
++
++ blk->owner = owner;
++ size = blk->size;
++
++ return size;
++}
++
++void rh_dump(rh_info_t * info)
++{
++ static rh_stats_t st[32]; /* XXX maximum 32 blocks */
++ int maxnr;
++ int i, nr;
++
++ maxnr = sizeof(st) / sizeof(st[0]);
++
++ printk(KERN_INFO
++ "info @0x%p (%d slots empty / %d max)\n",
++ info, info->empty_slots, info->max_blocks);
++
++ printk(KERN_INFO " Free:\n");
++ nr = rh_get_stats(info, RHGS_FREE, maxnr, st);
++ if (nr > maxnr)
++ nr = maxnr;
++ for (i = 0; i < nr; i++)
++ printk(KERN_INFO
++ " 0x%p-0x%p (%u)\n",
++ st[i].start, (int8_t *) st[i].start + st[i].size,
++ st[i].size);
++ printk(KERN_INFO "\n");
++
++ printk(KERN_INFO " Taken:\n");
++ nr = rh_get_stats(info, RHGS_TAKEN, maxnr, st);
++ if (nr > maxnr)
++ nr = maxnr;
++ for (i = 0; i < nr; i++)
++ printk(KERN_INFO
++ " 0x%p-0x%p (%u) %s\n",
++ st[i].start, (int8_t *) st[i].start + st[i].size,
++ st[i].size, st[i].owner != NULL ? st[i].owner : "");
++ printk(KERN_INFO "\n");
++}
++
++void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
++{
++ printk(KERN_INFO
++ "blk @0x%p: 0x%p-0x%p (%u)\n",
++ blk, blk->start, (int8_t *) blk->start + blk->size, blk->size);
++}
+diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/sstep.c
+@@ -0,0 +1,158 @@
++/*
++ * Single-step support.
++ *
++ * Copyright (C) 2004 Paul Mackerras <paulus at au.ibm.com>, IBM
++ *
++ * 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/kernel.h>
++#include <linux/ptrace.h>
++#include <linux/config.h>
++#include <asm/sstep.h>
++#include <asm/processor.h>
++
++extern char system_call_common[];
++
++#ifdef CONFIG_PPC64
++/* Bits in SRR1 that are copied from MSR */
++#define MSR_MASK 0xffffffff87c0ffff
++#else
++#define MSR_MASK 0x87c0ffff
++#endif
++
++/*
++ * Determine whether a conditional branch instruction would branch.
++ */
++static int branch_taken(unsigned int instr, struct pt_regs *regs)
++{
++ unsigned int bo = (instr >> 21) & 0x1f;
++ unsigned int bi;
++
++ if ((bo & 4) == 0) {
++ /* decrement counter */
++ --regs->ctr;
++ if (((bo >> 1) & 1) ^ (regs->ctr == 0))
++ return 0;
++ }
++ if ((bo & 0x10) == 0) {
++ /* check bit from CR */
++ bi = (instr >> 16) & 0x1f;
++ if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
++ return 0;
++ }
++ return 1;
++}
++
++/*
++ * Emulate instructions that cause a transfer of control.
++ * Returns 1 if the step was emulated, 0 if not,
++ * or -1 if the instruction is one that should not be stepped,
++ * such as an rfid, or a mtmsrd that would clear MSR_RI.
++ */
++int emulate_step(struct pt_regs *regs, unsigned int instr)
++{
++ unsigned int opcode, rd;
++ unsigned long int imm;
++
++ opcode = instr >> 26;
++ switch (opcode) {
++ case 16: /* bc */
++ imm = (signed short)(instr & 0xfffc);
++ if ((instr & 2) == 0)
++ imm += regs->nip;
++ regs->nip += 4;
++ if ((regs->msr & MSR_SF) == 0)
++ regs->nip &= 0xffffffffUL;
++ if (instr & 1)
++ regs->link = regs->nip;
++ if (branch_taken(instr, regs))
++ regs->nip = imm;
++ return 1;
++#ifdef CONFIG_PPC64
++ case 17: /* sc */
++ /*
++ * N.B. this uses knowledge about how the syscall
++ * entry code works. If that is changed, this will
++ * need to be changed also.
++ */
++ regs->gpr[9] = regs->gpr[13];
++ regs->gpr[11] = regs->nip + 4;
++ regs->gpr[12] = regs->msr & MSR_MASK;
++ regs->gpr[13] = (unsigned long) get_paca();
++ regs->nip = (unsigned long) &system_call_common;
++ regs->msr = MSR_KERNEL;
++ return 1;
++#endif
++ case 18: /* b */
++ imm = instr & 0x03fffffc;
++ if (imm & 0x02000000)
++ imm -= 0x04000000;
++ if ((instr & 2) == 0)
++ imm += regs->nip;
++ if (instr & 1) {
++ regs->link = regs->nip + 4;
++ if ((regs->msr & MSR_SF) == 0)
++ regs->link &= 0xffffffffUL;
++ }
++ if ((regs->msr & MSR_SF) == 0)
++ imm &= 0xffffffffUL;
++ regs->nip = imm;
++ return 1;
++ case 19:
++ switch (instr & 0x7fe) {
++ case 0x20: /* bclr */
++ case 0x420: /* bcctr */
++ imm = (instr & 0x400)? regs->ctr: regs->link;
++ regs->nip += 4;
++ if ((regs->msr & MSR_SF) == 0) {
++ regs->nip &= 0xffffffffUL;
++ imm &= 0xffffffffUL;
++ }
++ if (instr & 1)
++ regs->link = regs->nip;
++ if (branch_taken(instr, regs))
++ regs->nip = imm;
++ return 1;
++ case 0x24: /* rfid, scary */
++ return -1;
++ }
++ case 31:
++ rd = (instr >> 21) & 0x1f;
++ switch (instr & 0x7fe) {
++ case 0xa6: /* mfmsr */
++ regs->gpr[rd] = regs->msr & MSR_MASK;
++ regs->nip += 4;
++ if ((regs->msr & MSR_SF) == 0)
++ regs->nip &= 0xffffffffUL;
++ return 1;
++ case 0x124: /* mtmsr */
++ imm = regs->gpr[rd];
++ if ((imm & MSR_RI) == 0)
++ /* can't step mtmsr that would clear MSR_RI */
++ return -1;
++ regs->msr = imm;
++ regs->nip += 4;
++ return 1;
++#ifdef CONFIG_PPC64
++ case 0x164: /* mtmsrd */
++ /* only MSR_EE and MSR_RI get changed if bit 15 set */
++ /* mtmsrd doesn't change MSR_HV and MSR_ME */
++ imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
++ imm = (regs->msr & MSR_MASK & ~imm)
++ | (regs->gpr[rd] & imm);
++ if ((imm & MSR_RI) == 0)
++ /* can't step mtmsrd that would clear MSR_RI */
++ return -1;
++ regs->msr = imm;
++ regs->nip += 4;
++ if ((imm & MSR_SF) == 0)
++ regs->nip &= 0xffffffffUL;
++ return 1;
++#endif
++ }
++ }
++ return 0;
++}
+diff --git a/arch/powerpc/lib/strcase.c b/arch/powerpc/lib/strcase.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/strcase.c
+@@ -0,0 +1,23 @@
++#include <linux/ctype.h>
++
++int strcasecmp(const char *s1, const char *s2)
++{
++ int c1, c2;
++
++ do {
++ c1 = tolower(*s1++);
++ c2 = tolower(*s2++);
++ } while (c1 == c2 && c1 != 0);
++ return c1 - c2;
++}
++
++int strncasecmp(const char *s1, const char *s2, int n)
++{
++ int c1, c2;
++
++ do {
++ c1 = tolower(*s1++);
++ c2 = tolower(*s2++);
++ } while ((--n > 0) && c1 == c2 && c1 != 0);
++ return c1 - c2;
++}
+diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/string.S
+@@ -0,0 +1,198 @@
++/*
++ * String handling functions for PowerPC.
++ *
++ * Copyright (C) 1996 Paul Mackerras.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/errno.h>
++#include <asm/ppc_asm.h>
++
++ .section __ex_table,"a"
++#ifdef CONFIG_PPC64
++ .align 3
++#define EXTBL .llong
++#else
++ .align 2
++#define EXTBL .long
++#endif
++ .text
++
++_GLOBAL(strcpy)
++ addi r5,r3,-1
++ addi r4,r4,-1
++1: lbzu r0,1(r4)
++ cmpwi 0,r0,0
++ stbu r0,1(r5)
++ bne 1b
++ blr
++
++/* This clears out any unused part of the destination buffer,
++ just as the libc version does. -- paulus */
++_GLOBAL(strncpy)
++ cmpwi 0,r5,0
++ beqlr
++ mtctr r5
++ addi r6,r3,-1
++ addi r4,r4,-1
++1: lbzu r0,1(r4)
++ cmpwi 0,r0,0
++ stbu r0,1(r6)
++ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
++ bnelr /* if we didn't hit a null char, we're done */
++ mfctr r5
++ cmpwi 0,r5,0 /* any space left in destination buffer? */
++ beqlr /* we know r0 == 0 here */
++2: stbu r0,1(r6) /* clear it out if so */
++ bdnz 2b
++ blr
++
++_GLOBAL(strcat)
++ addi r5,r3,-1
++ addi r4,r4,-1
++1: lbzu r0,1(r5)
++ cmpwi 0,r0,0
++ bne 1b
++ addi r5,r5,-1
++1: lbzu r0,1(r4)
++ cmpwi 0,r0,0
++ stbu r0,1(r5)
++ bne 1b
++ blr
++
++_GLOBAL(strcmp)
++ addi r5,r3,-1
++ addi r4,r4,-1
++1: lbzu r3,1(r5)
++ cmpwi 1,r3,0
++ lbzu r0,1(r4)
++ subf. r3,r0,r3
++ beqlr 1
++ beq 1b
++ blr
++
++_GLOBAL(strlen)
++ addi r4,r3,-1
++1: lbzu r0,1(r4)
++ cmpwi 0,r0,0
++ bne 1b
++ subf r3,r3,r4
++ blr
++
++_GLOBAL(memcmp)
++ cmpwi 0,r5,0
++ ble- 2f
++ mtctr r5
++ addi r6,r3,-1
++ addi r4,r4,-1
++1: lbzu r3,1(r6)
++ lbzu r0,1(r4)
++ subf. r3,r0,r3
++ bdnzt 2,1b
++ blr
++2: li r3,0
++ blr
++
++_GLOBAL(memchr)
++ cmpwi 0,r5,0
++ ble- 2f
++ mtctr r5
++ addi r3,r3,-1
++1: lbzu r0,1(r3)
++ cmpw 0,r0,r4
++ bdnzf 2,1b
++ beqlr
++2: li r3,0
++ blr
++
++_GLOBAL(__clear_user)
++ addi r6,r3,-4
++ li r3,0
++ li r5,0
++ cmplwi 0,r4,4
++ blt 7f
++ /* clear a single word */
++11: stwu r5,4(r6)
++ beqlr
++ /* clear word sized chunks */
++ andi. r0,r6,3
++ add r4,r0,r4
++ subf r6,r0,r6
++ srwi r0,r4,2
++ andi. r4,r4,3
++ mtctr r0
++ bdz 7f
++1: stwu r5,4(r6)
++ bdnz 1b
++ /* clear byte sized chunks */
++7: cmpwi 0,r4,0
++ beqlr
++ mtctr r4
++ addi r6,r6,3
++8: stbu r5,1(r6)
++ bdnz 8b
++ blr
++90: mr r3,r4
++ blr
++91: mfctr r3
++ slwi r3,r3,2
++ add r3,r3,r4
++ blr
++92: mfctr r3
++ blr
++
++ .section __ex_table,"a"
++ EXTBL 11b,90b
++ EXTBL 1b,91b
++ EXTBL 8b,92b
++ .text
++
++_GLOBAL(__strncpy_from_user)
++ addi r6,r3,-1
++ addi r4,r4,-1
++ cmpwi 0,r5,0
++ beq 2f
++ mtctr r5
++1: lbzu r0,1(r4)
++ cmpwi 0,r0,0
++ stbu r0,1(r6)
++ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
++ beq 3f
++2: addi r6,r6,1
++3: subf r3,r3,r6
++ blr
++99: li r3,-EFAULT
++ blr
++
++ .section __ex_table,"a"
++ EXTBL 1b,99b
++ .text
++
++/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
++_GLOBAL(__strnlen_user)
++ addi r7,r3,-1
++ subf r6,r7,r5 /* top+1 - str */
++ cmplw 0,r4,r6
++ bge 0f
++ mr r6,r4
++0: mtctr r6 /* ctr = min(len, top - str) */
++1: lbzu r0,1(r7) /* get next byte */
++ cmpwi 0,r0,0
++ bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
++ addi r7,r7,1
++ subf r3,r3,r7 /* number of bytes we have looked at */
++ beqlr /* return if we found a 0 byte */
++ cmpw 0,r3,r4 /* did we look at all len bytes? */
++ blt 99f /* if not, must have hit top */
++ addi r3,r4,1 /* return len + 1 to indicate no null found */
++ blr
++99: li r3,0 /* bad address, return 0 */
++ blr
++
++ .section __ex_table,"a"
++ EXTBL 1b,99b
+diff --git a/arch/powerpc/lib/usercopy_64.c b/arch/powerpc/lib/usercopy_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/lib/usercopy_64.c
+@@ -0,0 +1,41 @@
++/*
++ * Functions which are too large to be inlined.
++ *
++ * 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 <asm/uaccess.h>
++
++unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
++{
++ if (likely(access_ok(VERIFY_READ, from, n)))
++ n = __copy_from_user(to, from, n);
++ else
++ memset(to, 0, n);
++ return n;
++}
++
++unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
++{
++ if (likely(access_ok(VERIFY_WRITE, to, n)))
++ n = __copy_to_user(to, from, n);
++ return n;
++}
++
++unsigned long copy_in_user(void __user *to, const void __user *from,
++ unsigned long n)
++{
++ might_sleep();
++ if (likely(access_ok(VERIFY_READ, from, n) &&
++ access_ok(VERIFY_WRITE, to, n)))
++ n =__copy_tofrom_user(to, from, n);
++ return n;
++}
++
++EXPORT_SYMBOL(copy_from_user);
++EXPORT_SYMBOL(copy_to_user);
++EXPORT_SYMBOL(copy_in_user);
++
+diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/44x_mmu.c
+@@ -0,0 +1,120 @@
++/*
++ * Modifications by Matt Porter (mporter at mvista.com) to support
++ * PPC44x Book E processors.
++ *
++ * This file contains the routines for initializing the MMU
++ * on the 4xx series of chips.
++ * -- paulus
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/stddef.h>
++#include <linux/vmalloc.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/highmem.h>
++
++#include <asm/pgalloc.h>
++#include <asm/prom.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/uaccess.h>
++#include <asm/smp.h>
++#include <asm/bootx.h>
++#include <asm/machdep.h>
++#include <asm/setup.h>
++
++#include "mmu_decl.h"
++
++extern char etext[], _stext[];
++
++/* Used by the 44x TLB replacement exception handler.
++ * Just needed it declared someplace.
++ */
++unsigned int tlb_44x_index = 0;
++unsigned int tlb_44x_hwater = 62;
++
++/*
++ * "Pins" a 256MB TLB entry in AS0 for kernel lowmem
++ */
++static void __init
++ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys)
++{
++ unsigned long attrib = 0;
++
++ __asm__ __volatile__("\
++ clrrwi %2,%2,10\n\
++ ori %2,%2,%4\n\
++ clrrwi %1,%1,10\n\
++ li %0,0\n\
++ ori %0,%0,%5\n\
++ tlbwe %2,%3,%6\n\
++ tlbwe %1,%3,%7\n\
++ tlbwe %0,%3,%8"
++ :
++ : "r" (attrib), "r" (phys), "r" (virt), "r" (slot),
++ "i" (PPC44x_TLB_VALID | PPC44x_TLB_256M),
++ "i" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
++ "i" (PPC44x_TLB_PAGEID),
++ "i" (PPC44x_TLB_XLAT),
++ "i" (PPC44x_TLB_ATTRIB));
++}
++
++/*
++ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
++ */
++void __init MMU_init_hw(void)
++{
++ flush_instruction_cache();
++}
++
++unsigned long __init mmu_mapin_ram(void)
++{
++ unsigned int pinned_tlbs = 1;
++ int i;
++
++ /* Determine number of entries necessary to cover lowmem */
++ pinned_tlbs = (unsigned int)
++ (_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT);
++
++ /* Write upper watermark to save location */
++ tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs;
++
++ /* If necessary, set additional pinned TLBs */
++ if (pinned_tlbs > 1)
++ for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) {
++ unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE;
++ ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr);
++ }
++
++ return total_lowmem;
++}
+diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/4xx_mmu.c
+@@ -0,0 +1,141 @@
++/*
++ * This file contains the routines for initializing the MMU
++ * on the 4xx series of chips.
++ * -- paulus
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/stddef.h>
++#include <linux/vmalloc.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/highmem.h>
++
++#include <asm/pgalloc.h>
++#include <asm/prom.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/uaccess.h>
++#include <asm/smp.h>
++#include <asm/bootx.h>
++#include <asm/machdep.h>
++#include <asm/setup.h>
++#include "mmu_decl.h"
++
++extern int __map_without_ltlbs;
++/*
++ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
++ */
++void __init MMU_init_hw(void)
++{
++ /*
++ * The Zone Protection Register (ZPR) defines how protection will
++ * be applied to every page which is a member of a given zone. At
++ * present, we utilize only two of the 4xx's zones.
++ * The zone index bits (of ZSEL) in the PTE are used for software
++ * indicators, except the LSB. For user access, zone 1 is used,
++ * for kernel access, zone 0 is used. We set all but zone 1
++ * to zero, allowing only kernel access as indicated in the PTE.
++ * For zone 1, we set a 01 binary (a value of 10 will not work)
++ * to allow user access as indicated in the PTE. This also allows
++ * kernel access as indicated in the PTE.
++ */
++
++ mtspr(SPRN_ZPR, 0x10000000);
++
++ flush_instruction_cache();
++
++ /*
++ * Set up the real-mode cache parameters for the exception vector
++ * handlers (which are run in real-mode).
++ */
++
++ mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */
++
++ /*
++ * Cache instruction and data space where the exception
++ * vectors and the kernel live in real-mode.
++ */
++
++ mtspr(SPRN_DCCR, 0xF0000000); /* 512 MB of data space at 0x0. */
++ mtspr(SPRN_ICCR, 0xF0000000); /* 512 MB of instr. space at 0x0. */
++}
++
++#define LARGE_PAGE_SIZE_16M (1<<24)
++#define LARGE_PAGE_SIZE_4M (1<<22)
++
++unsigned long __init mmu_mapin_ram(void)
++{
++ unsigned long v, s;
++ phys_addr_t p;
++
++ v = KERNELBASE;
++ p = PPC_MEMSTART;
++ s = 0;
++
++ if (__map_without_ltlbs) {
++ return s;
++ }
++
++ while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
++ 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;
++ s += LARGE_PAGE_SIZE_16M;
++ }
++
++ while (s <= (total_lowmem - LARGE_PAGE_SIZE_4M)) {
++ 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;
++ s += LARGE_PAGE_SIZE_4M;
++ }
++
++ return s;
++}
+diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/Makefile
+@@ -0,0 +1,21 @@
++#
++# Makefile for the linux ppc-specific parts of the memory manager.
++#
++
++ifeq ($(CONFIG_PPC64),y)
++EXTRA_CFLAGS += -mno-minimal-toc
++endif
++
++obj-y := fault.o mem.o lmb.o
++obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o
++hash-$(CONFIG_PPC_MULTIPLATFORM) := hash_native_64.o
++obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \
++ hash_utils_64.o hash_low_64.o tlb_64.o \
++ slb_low.o slb.o stab.o mmap.o imalloc.o \
++ $(hash-y)
++obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o
++obj-$(CONFIG_40x) += 4xx_mmu.o
++obj-$(CONFIG_44x) += 44x_mmu.o
++obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o
++obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
++obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/fault.c
+@@ -0,0 +1,393 @@
++/*
++ * arch/ppc/mm/fault.c
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Derived from "arch/i386/mm/fault.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * Modified by Cort Dougan and Paul Mackerras.
++ *
++ * Modified for PPC64 by Dave Engebretsen (engebret at ibm.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/config.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/highmem.h>
++#include <linux/module.h>
++#include <linux/kprobes.h>
++
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/mmu_context.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/tlbflush.h>
++#include <asm/kdebug.h>
++#include <asm/siginfo.h>
++
++/*
++ * Check whether the instruction at regs->nip is a store using
++ * an update addressing form which will update r1.
++ */
++static int store_updates_sp(struct pt_regs *regs)
++{
++ unsigned int inst;
++
++ if (get_user(inst, (unsigned int __user *)regs->nip))
++ return 0;
++ /* check for 1 in the rA field */
++ if (((inst >> 16) & 0x1f) != 1)
++ return 0;
++ /* check major opcode */
++ switch (inst >> 26) {
++ case 37: /* stwu */
++ case 39: /* stbu */
++ case 45: /* sthu */
++ case 53: /* stfsu */
++ case 55: /* stfdu */
++ return 1;
++ case 62: /* std or stdu */
++ return (inst & 3) == 1;
++ case 31:
++ /* check minor opcode */
++ switch ((inst >> 1) & 0x3ff) {
++ case 181: /* stdux */
++ case 183: /* stwux */
++ case 247: /* stbux */
++ case 439: /* sthux */
++ case 695: /* stfsux */
++ case 759: /* stfdux */
++ return 1;
++ }
++ }
++ return 0;
++}
++
++#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
++static void do_dabr(struct pt_regs *regs, unsigned long error_code)
++{
++ siginfo_t info;
++
++ if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
++ 11, SIGSEGV) == NOTIFY_STOP)
++ return;
++
++ if (debugger_dabr_match(regs))
++ return;
++
++ /* Clear the DABR */
++ set_dabr(0);
++
++ /* Deliver the signal to userspace */
++ info.si_signo = SIGTRAP;
++ info.si_errno = 0;
++ info.si_code = TRAP_HWBKPT;
++ info.si_addr = (void __user *)regs->nip;
++ force_sig_info(SIGTRAP, &info, current);
++}
++#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
++
++/*
++ * For 600- and 800-family processors, the error_code parameter is DSISR
++ * for a data fault, SRR1 for an instruction fault. For 400-family processors
++ * the error_code parameter is ESR for a data fault, 0 for an instruction
++ * fault.
++ * For 64-bit processors, the error_code parameter is
++ * - DSISR for a non-SLB data access fault,
++ * - SRR1 & 0x08000000 for a non-SLB instruction access fault
++ * - 0 any SLB fault.
++ *
++ * The return value is 0 if the fault was handled, or the signal
++ * number if this is a kernel fault that can't be handled here.
++ */
++int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
++ unsigned long error_code)
++{
++ struct vm_area_struct * vma;
++ struct mm_struct *mm = current->mm;
++ siginfo_t info;
++ int code = SEGV_MAPERR;
++ int is_write = 0;
++ int trap = TRAP(regs);
++ int is_exec = trap == 0x400;
++
++#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
++ /*
++ * Fortunately the bit assignments in SRR1 for an instruction
++ * fault and DSISR for a data fault are mostly the same for the
++ * bits we are interested in. But there are some bits which
++ * indicate errors in DSISR but can validly be set in SRR1.
++ */
++ if (trap == 0x400)
++ error_code &= 0x48200000;
++ else
++ is_write = error_code & DSISR_ISSTORE;
++#else
++ is_write = error_code & ESR_DST;
++#endif /* CONFIG_4xx || CONFIG_BOOKE */
++
++ if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, error_code,
++ 11, SIGSEGV) == NOTIFY_STOP)
++ return 0;
++
++ if (trap == 0x300) {
++ if (debugger_fault_handler(regs))
++ return 0;
++ }
++
++ /* On a kernel SLB miss we can only check for a valid exception entry */
++ if (!user_mode(regs) && (address >= TASK_SIZE))
++ return SIGSEGV;
++
++#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
++ if (error_code & DSISR_DABRMATCH) {
++ /* DABR match */
++ do_dabr(regs, error_code);
++ return 0;
++ }
++#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
++
++ if (in_atomic() || mm == NULL) {
++ if (!user_mode(regs))
++ return SIGSEGV;
++ /* in_atomic() in user mode is really bad,
++ as is current->mm == NULL. */
++ printk(KERN_EMERG "Page fault in user mode with"
++ "in_atomic() = %d mm = %p\n", in_atomic(), mm);
++ printk(KERN_EMERG "NIP = %lx MSR = %lx\n",
++ regs->nip, regs->msr);
++ die("Weird page fault", regs, SIGSEGV);
++ }
++
++ /* When running in the kernel we expect faults to occur only to
++ * addresses in user space. All other faults represent errors in the
++ * kernel and should generate an OOPS. Unfortunatly, in the case of an
++ * erroneous fault occuring in a code path which already holds mmap_sem
++ * we will deadlock attempting to validate the fault against the
++ * address space. Luckily the kernel only validly references user
++ * space from well defined areas of code, which are listed in the
++ * exceptions table.
++ *
++ * As the vast majority of faults will be valid we will only perform
++ * the source reference check when there is a possibilty of a deadlock.
++ * Attempt to lock the address space, if we cannot we then validate the
++ * source. If this is invalid we can skip the address space check,
++ * thus avoiding the deadlock.
++ */
++ if (!down_read_trylock(&mm->mmap_sem)) {
++ if (!user_mode(regs) && !search_exception_tables(regs->nip))
++ goto bad_area_nosemaphore;
++
++ down_read(&mm->mmap_sem);
++ }
++
++ vma = find_vma(mm, address);
++ if (!vma)
++ goto bad_area;
++ if (vma->vm_start <= address)
++ goto good_area;
++ if (!(vma->vm_flags & VM_GROWSDOWN))
++ goto bad_area;
++
++ /*
++ * N.B. The POWER/Open ABI allows programs to access up to
++ * 288 bytes below the stack pointer.
++ * The kernel signal delivery code writes up to about 1.5kB
++ * below the stack pointer (r1) before decrementing it.
++ * The exec code can write slightly over 640kB to the stack
++ * before setting the user r1. Thus we allow the stack to
++ * expand to 1MB without further checks.
++ */
++ if (address + 0x100000 < vma->vm_end) {
++ /* get user regs even if this fault is in kernel mode */
++ struct pt_regs *uregs = current->thread.regs;
++ if (uregs == NULL)
++ goto bad_area;
++
++ /*
++ * A user-mode access to an address a long way below
++ * the stack pointer is only valid if the instruction
++ * is one which would update the stack pointer to the
++ * address accessed if the instruction completed,
++ * i.e. either stwu rs,n(r1) or stwux rs,r1,rb
++ * (or the byte, halfword, float or double forms).
++ *
++ * If we don't check this then any write to the area
++ * between the last mapped region and the stack will
++ * expand the stack rather than segfaulting.
++ */
++ if (address + 2048 < uregs->gpr[1]
++ && (!user_mode(regs) || !store_updates_sp(regs)))
++ goto bad_area;
++ }
++ if (expand_stack(vma, address))
++ goto bad_area;
++
++good_area:
++ code = SEGV_ACCERR;
++#if defined(CONFIG_6xx)
++ if (error_code & 0x95700000)
++ /* an error such as lwarx to I/O controller space,
++ address matching DABR, eciwx, etc. */
++ goto bad_area;
++#endif /* CONFIG_6xx */
++#if defined(CONFIG_8xx)
++ /* The MPC8xx seems to always set 0x80000000, which is
++ * "undefined". Of those that can be set, this is the only
++ * one which seems bad.
++ */
++ if (error_code & 0x10000000)
++ /* Guarded storage error. */
++ goto bad_area;
++#endif /* CONFIG_8xx */
++
++ if (is_exec) {
++#ifdef CONFIG_PPC64
++ /* protection fault */
++ if (error_code & DSISR_PROTFAULT)
++ goto bad_area;
++ if (!(vma->vm_flags & VM_EXEC))
++ goto bad_area;
++#endif
++#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
++ pte_t *ptep;
++
++ /* Since 4xx/Book-E supports per-page execute permission,
++ * we lazily flush dcache to icache. */
++ ptep = NULL;
++ if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
++ struct page *page = pte_page(*ptep);
++
++ if (! test_bit(PG_arch_1, &page->flags)) {
++ flush_dcache_icache_page(page);
++ set_bit(PG_arch_1, &page->flags);
++ }
++ pte_update(ptep, 0, _PAGE_HWEXEC);
++ _tlbie(address);
++ pte_unmap(ptep);
++ up_read(&mm->mmap_sem);
++ return 0;
++ }
++ if (ptep != NULL)
++ pte_unmap(ptep);
++#endif
++ /* a write */
++ } else if (is_write) {
++ if (!(vma->vm_flags & VM_WRITE))
++ goto bad_area;
++ /* a read */
++ } else {
++ /* protection fault */
++ if (error_code & 0x08000000)
++ goto bad_area;
++ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
++ goto bad_area;
++ }
++
++ /*
++ * If for any reason at all we couldn't handle the fault,
++ * make sure we exit gracefully rather than endlessly redo
++ * the fault.
++ */
++ survive:
++ switch (handle_mm_fault(mm, vma, address, is_write)) {
++
++ case VM_FAULT_MINOR:
++ current->min_flt++;
++ break;
++ case VM_FAULT_MAJOR:
++ current->maj_flt++;
++ break;
++ case VM_FAULT_SIGBUS:
++ goto do_sigbus;
++ case VM_FAULT_OOM:
++ goto out_of_memory;
++ default:
++ BUG();
++ }
++
++ up_read(&mm->mmap_sem);
++ return 0;
++
++bad_area:
++ up_read(&mm->mmap_sem);
++
++bad_area_nosemaphore:
++ /* User mode accesses cause a SIGSEGV */
++ if (user_mode(regs)) {
++ _exception(SIGSEGV, regs, code, address);
++ return 0;
++ }
++
++ if (is_exec && (error_code & DSISR_PROTFAULT)
++ && printk_ratelimit())
++ printk(KERN_CRIT "kernel tried to execute NX-protected"
++ " page (%lx) - exploit attempt? (uid: %d)\n",
++ address, current->uid);
++
++ return SIGSEGV;
++
++/*
++ * We ran out of memory, or some other thing happened to us that made
++ * us unable to handle the page fault gracefully.
++ */
++out_of_memory:
++ up_read(&mm->mmap_sem);
++ if (current->pid == 1) {
++ yield();
++ down_read(&mm->mmap_sem);
++ goto survive;
++ }
++ printk("VM: killing process %s\n", current->comm);
++ if (user_mode(regs))
++ do_exit(SIGKILL);
++ return SIGKILL;
++
++do_sigbus:
++ up_read(&mm->mmap_sem);
++ if (user_mode(regs)) {
++ info.si_signo = SIGBUS;
++ info.si_errno = 0;
++ info.si_code = BUS_ADRERR;
++ info.si_addr = (void __user *)address;
++ force_sig_info(SIGBUS, &info, current);
++ return 0;
++ }
++ return SIGBUS;
++}
++
++/*
++ * bad_page_fault is called when we have a bad access from the kernel.
++ * It is called from the DSI and ISI handlers in head.S and from some
++ * of the procedures in traps.c.
++ */
++void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
++{
++ const struct exception_table_entry *entry;
++
++ /* Are we prepared to handle this fault? */
++ if ((entry = search_exception_tables(regs->nip)) != NULL) {
++ regs->nip = entry->fixup;
++ return;
++ }
++
++ /* kernel has accessed a bad area */
++ die("Kernel access of bad area", regs, sig);
++}
+diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/fsl_booke_mmu.c
+@@ -0,0 +1,237 @@
++/*
++ * Modifications by Kumar Gala (kumar.gala at freescale.com) to support
++ * E500 Book E processors.
++ *
++ * Copyright 2004 Freescale Semiconductor, Inc
++ *
++ * This file contains the routines for initializing the MMU
++ * on the 4xx series of chips.
++ * -- paulus
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/stddef.h>
++#include <linux/vmalloc.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/highmem.h>
++
++#include <asm/pgalloc.h>
++#include <asm/prom.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/uaccess.h>
++#include <asm/smp.h>
++#include <asm/bootx.h>
++#include <asm/machdep.h>
++#include <asm/setup.h>
++
++extern void loadcam_entry(unsigned int index);
++unsigned int tlbcam_index;
++unsigned int num_tlbcam_entries;
++static unsigned long __cam0, __cam1, __cam2;
++extern unsigned long total_lowmem;
++extern unsigned long __max_low_memory;
++#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE
++
++#define NUM_TLBCAMS (16)
++
++struct tlbcam {
++ u32 MAS0;
++ u32 MAS1;
++ u32 MAS2;
++ u32 MAS3;
++ u32 MAS7;
++} TLBCAM[NUM_TLBCAMS];
++
++struct tlbcamrange {
++ unsigned long start;
++ unsigned long limit;
++ phys_addr_t phys;
++} tlbcam_addrs[NUM_TLBCAMS];
++
++extern unsigned int tlbcam_index;
++
++/*
++ * Return PA for this VA if it is mapped by a CAM, or 0
++ */
++unsigned long v_mapped_by_tlbcam(unsigned long va)
++{
++ int b;
++ for (b = 0; b < tlbcam_index; ++b)
++ if (va >= tlbcam_addrs[b].start && va < tlbcam_addrs[b].limit)
++ return tlbcam_addrs[b].phys + (va - tlbcam_addrs[b].start);
++ return 0;
++}
++
++/*
++ * Return VA for a given PA or 0 if not mapped
++ */
++unsigned long p_mapped_by_tlbcam(unsigned long pa)
++{
++ int b;
++ for (b = 0; b < tlbcam_index; ++b)
++ if (pa >= tlbcam_addrs[b].phys
++ && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start)
++ +tlbcam_addrs[b].phys)
++ return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys);
++ return 0;
++}
++
++/*
++ * Set up one of the I/D BAT (block address translation) register pairs.
++ * The parameters are not checked; in particular size must be a power
++ * of 4 between 4k and 256M.
++ */
++void settlbcam(int index, unsigned long virt, phys_addr_t phys,
++ unsigned int size, int flags, unsigned int pid)
++{
++ unsigned int tsize, lz;
++
++ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size));
++ tsize = (21 - lz) / 2;
++
++#ifdef CONFIG_SMP
++ if ((flags & _PAGE_NO_CACHE) == 0)
++ flags |= _PAGE_COHERENT;
++#endif
++
++ TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index) | MAS0_NV(index+1);
++ TLBCAM[index].MAS1 = MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(tsize) | MAS1_TID(pid);
++ TLBCAM[index].MAS2 = virt & PAGE_MASK;
++
++ TLBCAM[index].MAS2 |= (flags & _PAGE_WRITETHRU) ? MAS2_W : 0;
++ TLBCAM[index].MAS2 |= (flags & _PAGE_NO_CACHE) ? MAS2_I : 0;
++ TLBCAM[index].MAS2 |= (flags & _PAGE_COHERENT) ? MAS2_M : 0;
++ TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0;
++ TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0;
++
++ TLBCAM[index].MAS3 = (phys & PAGE_MASK) | MAS3_SX | MAS3_SR;
++ TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0);
++
++#ifndef CONFIG_KGDB /* want user access for breakpoints */
++ if (flags & _PAGE_USER) {
++ TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
++ TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
++ }
++#else
++ TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
++ TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
++#endif
++
++ tlbcam_addrs[index].start = virt;
++ tlbcam_addrs[index].limit = virt + size - 1;
++ tlbcam_addrs[index].phys = phys;
++
++ loadcam_entry(index);
++}
++
++void invalidate_tlbcam_entry(int index)
++{
++ TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index);
++ TLBCAM[index].MAS1 = ~MAS1_VALID;
++
++ loadcam_entry(index);
++}
++
++void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1,
++ unsigned long cam2)
++{
++ settlbcam(0, KERNELBASE, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0);
++ tlbcam_index++;
++ if (cam1) {
++ tlbcam_index++;
++ settlbcam(1, KERNELBASE+cam0, PPC_MEMSTART+cam0, cam1, _PAGE_KERNEL, 0);
++ }
++ if (cam2) {
++ tlbcam_index++;
++ settlbcam(2, KERNELBASE+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2, _PAGE_KERNEL, 0);
++ }
++}
++
++/*
++ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
++ */
++void __init MMU_init_hw(void)
++{
++ flush_instruction_cache();
++}
++
++unsigned long __init mmu_mapin_ram(void)
++{
++ cam_mapin_ram(__cam0, __cam1, __cam2);
++
++ return __cam0 + __cam1 + __cam2;
++}
++
++
++void __init
++adjust_total_lowmem(void)
++{
++ unsigned long max_low_mem = MAX_LOW_MEM;
++ unsigned long cam_max = 0x10000000;
++ unsigned long ram;
++
++ /* adjust CAM size to max_low_mem */
++ if (max_low_mem < cam_max)
++ cam_max = max_low_mem;
++
++ /* adjust lowmem size to max_low_mem */
++ if (max_low_mem < total_lowmem)
++ ram = max_low_mem;
++ else
++ ram = total_lowmem;
++
++ /* Calculate CAM values */
++ __cam0 = 1UL << 2 * (__ilog2(ram) / 2);
++ if (__cam0 > cam_max)
++ __cam0 = cam_max;
++ ram -= __cam0;
++ if (ram) {
++ __cam1 = 1UL << 2 * (__ilog2(ram) / 2);
++ if (__cam1 > cam_max)
++ __cam1 = cam_max;
++ ram -= __cam1;
++ }
++ if (ram) {
++ __cam2 = 1UL << 2 * (__ilog2(ram) / 2);
++ if (__cam2 > cam_max)
++ __cam2 = cam_max;
++ ram -= __cam2;
++ }
++
++ printk(KERN_INFO "Memory CAM mapping: CAM0=%ldMb, CAM1=%ldMb,"
++ " CAM2=%ldMb residual: %ldMb\n",
++ __cam0 >> 20, __cam1 >> 20, __cam2 >> 20,
++ (total_lowmem - __cam0 - __cam1 - __cam2) >> 20);
++ __max_low_memory = max_low_mem = __cam0 + __cam1 + __cam2;
++}
+diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/hash_low_32.S
+@@ -0,0 +1,618 @@
++/*
++ * arch/ppc/kernel/hashtable.S
++ *
++ * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ * Rewritten by Cort Dougan (cort at cs.nmt.edu) for PReP
++ * Copyright (C) 1996 Cort Dougan <cort at cs.nmt.edu>
++ * Adapted for Power Macintosh by Paul Mackerras.
++ * Low-level exception handlers and MMU support
++ * rewritten by Paul Mackerras.
++ * Copyright (C) 1996 Paul Mackerras.
++ *
++ * This file contains low-level assembler routines for managing
++ * the PowerPC MMU hash table. (PPC 8xx processors don't use a
++ * hash table, so this file is not used on them.)
++ *
++ * 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/reg.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/cputable.h>
++#include <asm/ppc_asm.h>
++#include <asm/thread_info.h>
++#include <asm/asm-offsets.h>
++
++#ifdef CONFIG_SMP
++ .comm mmu_hash_lock,4
++#endif /* CONFIG_SMP */
++
++/*
++ * Sync CPUs with hash_page taking & releasing the hash
++ * table lock
++ */
++#ifdef CONFIG_SMP
++ .text
++_GLOBAL(hash_page_sync)
++ lis r8,mmu_hash_lock at h
++ ori r8,r8,mmu_hash_lock at l
++ lis r0,0x0fff
++ b 10f
++11: lwz r6,0(r8)
++ cmpwi 0,r6,0
++ bne 11b
++10: lwarx r6,0,r8
++ cmpwi 0,r6,0
++ bne- 11b
++ stwcx. r0,0,r8
++ bne- 10b
++ isync
++ eieio
++ li r0,0
++ stw r0,0(r8)
++ blr
++#endif
++
++/*
++ * Load a PTE into the hash table, if possible.
++ * The address is in r4, and r3 contains an access flag:
++ * _PAGE_RW (0x400) if a write.
++ * r9 contains the SRR1 value, from which we use the MSR_PR bit.
++ * SPRG3 contains the physical address of the current task's thread.
++ *
++ * Returns to the caller if the access is illegal or there is no
++ * mapping for the address. Otherwise it places an appropriate PTE
++ * in the hash table and returns from the exception.
++ * Uses r0, r3 - r8, ctr, lr.
++ */
++ .text
++_GLOBAL(hash_page)
++#ifdef CONFIG_PPC64BRIDGE
++ mfmsr r0
++ clrldi r0,r0,1 /* make sure it's in 32-bit mode */
++ MTMSRD(r0)
++ isync
++#endif
++ tophys(r7,0) /* gets -KERNELBASE into r7 */
++#ifdef CONFIG_SMP
++ addis r8,r7,mmu_hash_lock at h
++ ori r8,r8,mmu_hash_lock at l
++ lis r0,0x0fff
++ b 10f
++11: lwz r6,0(r8)
++ cmpwi 0,r6,0
++ bne 11b
++10: lwarx r6,0,r8
++ cmpwi 0,r6,0
++ bne- 11b
++ stwcx. r0,0,r8
++ bne- 10b
++ isync
++#endif
++ /* Get PTE (linux-style) and check access */
++ lis r0,KERNELBASE at h /* check if kernel address */
++ cmplw 0,r4,r0
++ mfspr r8,SPRN_SPRG3 /* current task's THREAD (phys) */
++ ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
++ lwz r5,PGDIR(r8) /* virt page-table root */
++ blt+ 112f /* assume user more likely */
++ lis r5,swapper_pg_dir at ha /* if kernel address, use */
++ addi r5,r5,swapper_pg_dir at l /* kernel page table */
++ rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */
++112: add r5,r5,r7 /* convert to phys addr */
++ rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */
++ lwz r8,0(r5) /* get pmd entry */
++ rlwinm. r8,r8,0,0,19 /* extract address of pte page */
++#ifdef CONFIG_SMP
++ beq- hash_page_out /* return if no mapping */
++#else
++ /* XXX it seems like the 601 will give a machine fault on the
++ rfi if its alignment is wrong (bottom 4 bits of address are
++ 8 or 0xc) and we have had a not-taken conditional branch
++ to the address following the rfi. */
++ beqlr-
++#endif
++ rlwimi r8,r4,22,20,29 /* insert next 10 bits of address */
++ rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
++ ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
++
++ /*
++ * Update the linux PTE atomically. We do the lwarx up-front
++ * because almost always, there won't be a permission violation
++ * and there won't already be an HPTE, and thus we will have
++ * to update the PTE to set _PAGE_HASHPTE. -- paulus.
++ */
++retry:
++ lwarx r6,0,r8 /* get linux-style pte */
++ andc. r5,r3,r6 /* check access & ~permission */
++#ifdef CONFIG_SMP
++ bne- hash_page_out /* return if access not permitted */
++#else
++ bnelr-
++#endif
++ or r5,r0,r6 /* set accessed/dirty bits */
++ stwcx. r5,0,r8 /* attempt to update PTE */
++ bne- retry /* retry if someone got there first */
++
++ mfsrin r3,r4 /* get segment reg for segment */
++ mfctr r0
++ stw r0,_CTR(r11)
++ bl create_hpte /* add the hash table entry */
++
++#ifdef CONFIG_SMP
++ eieio
++ addis r8,r7,mmu_hash_lock at ha
++ li r0,0
++ stw r0,mmu_hash_lock at l(r8)
++#endif
++
++ /* Return from the exception */
++ lwz r5,_CTR(r11)
++ mtctr r5
++ lwz r0,GPR0(r11)
++ lwz r7,GPR7(r11)
++ lwz r8,GPR8(r11)
++ b fast_exception_return
++
++#ifdef CONFIG_SMP
++hash_page_out:
++ eieio
++ addis r8,r7,mmu_hash_lock at ha
++ li r0,0
++ stw r0,mmu_hash_lock at l(r8)
++ blr
++#endif /* CONFIG_SMP */
++
++/*
++ * Add an entry for a particular page to the hash table.
++ *
++ * add_hash_page(unsigned context, unsigned long va, unsigned long pmdval)
++ *
++ * We assume any necessary modifications to the pte (e.g. setting
++ * the accessed bit) have already been done and that there is actually
++ * a hash table in use (i.e. we're not on a 603).
++ */
++_GLOBAL(add_hash_page)
++ mflr r0
++ stw r0,4(r1)
++
++ /* Convert context and va to VSID */
++ mulli r3,r3,897*16 /* multiply context by context skew */
++ rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
++ mulli r0,r0,0x111 /* multiply by ESID skew */
++ add r3,r3,r0 /* note create_hpte trims to 24 bits */
++
++#ifdef CONFIG_SMP
++ rlwinm r8,r1,0,0,18 /* use cpu number to make tag */
++ lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */
++ oris r8,r8,12
++#endif /* CONFIG_SMP */
++
++ /*
++ * We disable interrupts here, even on UP, because we don't
++ * want to race with hash_page, and because we want the
++ * _PAGE_HASHPTE bit to be a reliable indication of whether
++ * the HPTE exists (or at least whether one did once).
++ * We also turn off the MMU for data accesses so that we
++ * we can't take a hash table miss (assuming the code is
++ * covered by a BAT). -- paulus
++ */
++ mfmsr r10
++ SYNC
++ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
++ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
++ mtmsr r0
++ SYNC_601
++ isync
++
++ tophys(r7,0)
++
++#ifdef CONFIG_SMP
++ addis r9,r7,mmu_hash_lock at ha
++ addi r9,r9,mmu_hash_lock at l
++10: lwarx r0,0,r9 /* take the mmu_hash_lock */
++ cmpi 0,r0,0
++ bne- 11f
++ stwcx. r8,0,r9
++ beq+ 12f
++11: lwz r0,0(r9)
++ cmpi 0,r0,0
++ beq 10b
++ b 11b
++12: isync
++#endif
++
++ /*
++ * Fetch the linux pte and test and set _PAGE_HASHPTE atomically.
++ * If _PAGE_HASHPTE was already set, we don't replace the existing
++ * HPTE, so we just unlock and return.
++ */
++ mr r8,r5
++ rlwimi r8,r4,22,20,29
++1: lwarx r6,0,r8
++ andi. r0,r6,_PAGE_HASHPTE
++ bne 9f /* if HASHPTE already set, done */
++ ori r5,r6,_PAGE_HASHPTE
++ stwcx. r5,0,r8
++ bne- 1b
++
++ bl create_hpte
++
++9:
++#ifdef CONFIG_SMP
++ eieio
++ li r0,0
++ stw r0,0(r9) /* clear mmu_hash_lock */
++#endif
++
++ /* reenable interrupts and DR */
++ mtmsr r10
++ SYNC_601
++ isync
++
++ lwz r0,4(r1)
++ mtlr r0
++ blr
++
++/*
++ * This routine adds a hardware PTE to the hash table.
++ * It is designed to be called with the MMU either on or off.
++ * r3 contains the VSID, r4 contains the virtual address,
++ * r5 contains the linux PTE, r6 contains the old value of the
++ * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the
++ * offset to be added to addresses (0 if the MMU is on,
++ * -KERNELBASE if it is off).
++ * On SMP, the caller should have the mmu_hash_lock held.
++ * We assume that the caller has (or will) set the _PAGE_HASHPTE
++ * bit in the linux PTE in memory. The value passed in r6 should
++ * be the old linux PTE value; if it doesn't have _PAGE_HASHPTE set
++ * this routine will skip the search for an existing HPTE.
++ * This procedure modifies r0, r3 - r6, r8, cr0.
++ * -- paulus.
++ *
++ * For speed, 4 of the instructions get patched once the size and
++ * physical address of the hash table are known. These definitions
++ * of Hash_base and Hash_bits below are just an example.
++ */
++Hash_base = 0xc0180000
++Hash_bits = 12 /* e.g. 256kB hash table */
++Hash_msk = (((1 << Hash_bits) - 1) * 64)
++
++#ifndef CONFIG_PPC64BRIDGE
++/* defines for the PTE format for 32-bit PPCs */
++#define PTE_SIZE 8
++#define PTEG_SIZE 64
++#define LG_PTEG_SIZE 6
++#define LDPTEu lwzu
++#define STPTE stw
++#define CMPPTE cmpw
++#define PTE_H 0x40
++#define PTE_V 0x80000000
++#define TST_V(r) rlwinm. r,r,0,0,0
++#define SET_V(r) oris r,r,PTE_V at h
++#define CLR_V(r,t) rlwinm r,r,0,1,31
++
++#else
++/* defines for the PTE format for 64-bit PPCs */
++#define PTE_SIZE 16
++#define PTEG_SIZE 128
++#define LG_PTEG_SIZE 7
++#define LDPTEu ldu
++#define STPTE std
++#define CMPPTE cmpd
++#define PTE_H 2
++#define PTE_V 1
++#define TST_V(r) andi. r,r,PTE_V
++#define SET_V(r) ori r,r,PTE_V
++#define CLR_V(r,t) li t,PTE_V; andc r,r,t
++#endif /* CONFIG_PPC64BRIDGE */
++
++#define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1)
++#define HASH_RIGHT 31-LG_PTEG_SIZE
++
++_GLOBAL(create_hpte)
++ /* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */
++ rlwinm r8,r5,32-10,31,31 /* _PAGE_RW -> PP lsb */
++ rlwinm r0,r5,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
++ and r8,r8,r0 /* writable if _RW & _DIRTY */
++ rlwimi r5,r5,32-1,30,30 /* _PAGE_USER -> PP msb */
++ rlwimi r5,r5,32-2,31,31 /* _PAGE_USER -> PP lsb */
++ ori r8,r8,0xe14 /* clear out reserved bits and M */
++ andc r8,r5,r8 /* PP = user? (rw&dirty? 2: 3): 0 */
++BEGIN_FTR_SECTION
++ ori r8,r8,_PAGE_COHERENT /* set M (coherence required) */
++END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
++
++ /* Construct the high word of the PPC-style PTE (r5) */
++#ifndef CONFIG_PPC64BRIDGE
++ rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
++ rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */
++#else /* CONFIG_PPC64BRIDGE */
++ clrlwi r3,r3,8 /* reduce vsid to 24 bits */
++ sldi r5,r3,12 /* shift vsid into position */
++ rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */
++#endif /* CONFIG_PPC64BRIDGE */
++ SET_V(r5) /* set V (valid) bit */
++
++ /* Get the address of the primary PTE group in the hash table (r3) */
++_GLOBAL(hash_page_patch_A)
++ addis r0,r7,Hash_base at h /* base address of hash table */
++ rlwimi r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
++ rlwinm r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
++ xor r3,r3,r0 /* make primary hash */
++ li r0,8 /* PTEs/group */
++
++ /*
++ * Test the _PAGE_HASHPTE bit in the old linux PTE, and skip the search
++ * if it is clear, meaning that the HPTE isn't there already...
++ */
++ andi. r6,r6,_PAGE_HASHPTE
++ beq+ 10f /* no PTE: go look for an empty slot */
++ tlbie r4
++
++ addis r4,r7,htab_hash_searches at ha
++ lwz r6,htab_hash_searches at l(r4)
++ addi r6,r6,1 /* count how many searches we do */
++ stw r6,htab_hash_searches at l(r4)
++
++ /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
++ mtctr r0
++ addi r4,r3,-PTE_SIZE
++1: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */
++ CMPPTE 0,r6,r5
++ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
++ beq+ found_slot
++
++ /* Search the secondary PTEG for a matching PTE */
++ ori r5,r5,PTE_H /* set H (secondary hash) bit */
++_GLOBAL(hash_page_patch_B)
++ xoris r4,r3,Hash_msk>>16 /* compute secondary hash */
++ xori r4,r4,(-PTEG_SIZE & 0xffff)
++ addi r4,r4,-PTE_SIZE
++ mtctr r0
++2: LDPTEu r6,PTE_SIZE(r4)
++ CMPPTE 0,r6,r5
++ bdnzf 2,2b
++ beq+ found_slot
++ xori r5,r5,PTE_H /* clear H bit again */
++
++ /* Search the primary PTEG for an empty slot */
++10: mtctr r0
++ addi r4,r3,-PTE_SIZE /* search primary PTEG */
++1: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */
++ TST_V(r6) /* test valid bit */
++ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
++ beq+ found_empty
++
++ /* update counter of times that the primary PTEG is full */
++ addis r4,r7,primary_pteg_full at ha
++ lwz r6,primary_pteg_full at l(r4)
++ addi r6,r6,1
++ stw r6,primary_pteg_full at l(r4)
++
++ /* Search the secondary PTEG for an empty slot */
++ ori r5,r5,PTE_H /* set H (secondary hash) bit */
++_GLOBAL(hash_page_patch_C)
++ xoris r4,r3,Hash_msk>>16 /* compute secondary hash */
++ xori r4,r4,(-PTEG_SIZE & 0xffff)
++ addi r4,r4,-PTE_SIZE
++ mtctr r0
++2: LDPTEu r6,PTE_SIZE(r4)
++ TST_V(r6)
++ bdnzf 2,2b
++ beq+ found_empty
++ xori r5,r5,PTE_H /* clear H bit again */
++
++ /*
++ * Choose an arbitrary slot in the primary PTEG to overwrite.
++ * Since both the primary and secondary PTEGs are full, and we
++ * have no information that the PTEs in the primary PTEG are
++ * more important or useful than those in the secondary PTEG,
++ * and we know there is a definite (although small) speed
++ * advantage to putting the PTE in the primary PTEG, we always
++ * put the PTE in the primary PTEG.
++ */
++ addis r4,r7,next_slot at ha
++ lwz r6,next_slot at l(r4)
++ addi r6,r6,PTE_SIZE
++ andi. r6,r6,7*PTE_SIZE
++ stw r6,next_slot at l(r4)
++ add r4,r3,r6
++
++#ifndef CONFIG_SMP
++ /* Store PTE in PTEG */
++found_empty:
++ STPTE r5,0(r4)
++found_slot:
++ STPTE r8,PTE_SIZE/2(r4)
++
++#else /* CONFIG_SMP */
++/*
++ * Between the tlbie above and updating the hash table entry below,
++ * another CPU could read the hash table entry and put it in its TLB.
++ * There are 3 cases:
++ * 1. using an empty slot
++ * 2. updating an earlier entry to change permissions (i.e. enable write)
++ * 3. taking over the PTE for an unrelated address
++ *
++ * In each case it doesn't really matter if the other CPUs have the old
++ * PTE in their TLB. So we don't need to bother with another tlbie here,
++ * which is convenient as we've overwritten the register that had the
++ * address. :-) The tlbie above is mainly to make sure that this CPU comes
++ * and gets the new PTE from the hash table.
++ *
++ * We do however have to make sure that the PTE is never in an invalid
++ * state with the V bit set.
++ */
++found_empty:
++found_slot:
++ CLR_V(r5,r0) /* clear V (valid) bit in PTE */
++ STPTE r5,0(r4)
++ sync
++ TLBSYNC
++ STPTE r8,PTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */
++ sync
++ SET_V(r5)
++ STPTE r5,0(r4) /* finally set V bit in PTE */
++#endif /* CONFIG_SMP */
++
++ sync /* make sure pte updates get to memory */
++ blr
++
++ .comm next_slot,4
++ .comm primary_pteg_full,4
++ .comm htab_hash_searches,4
++
++/*
++ * Flush the entry for a particular page from the hash table.
++ *
++ * flush_hash_pages(unsigned context, unsigned long va, unsigned long pmdval,
++ * int count)
++ *
++ * We assume that there is a hash table in use (Hash != 0).
++ */
++_GLOBAL(flush_hash_pages)
++ tophys(r7,0)
++
++ /*
++ * We disable interrupts here, even on UP, because we want
++ * the _PAGE_HASHPTE bit to be a reliable indication of
++ * whether the HPTE exists (or at least whether one did once).
++ * We also turn off the MMU for data accesses so that we
++ * we can't take a hash table miss (assuming the code is
++ * covered by a BAT). -- paulus
++ */
++ mfmsr r10
++ SYNC
++ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
++ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
++ mtmsr r0
++ SYNC_601
++ isync
++
++ /* First find a PTE in the range that has _PAGE_HASHPTE set */
++ rlwimi r5,r4,22,20,29
++1: lwz r0,0(r5)
++ cmpwi cr1,r6,1
++ andi. r0,r0,_PAGE_HASHPTE
++ bne 2f
++ ble cr1,19f
++ addi r4,r4,0x1000
++ addi r5,r5,4
++ addi r6,r6,-1
++ b 1b
++
++ /* Convert context and va to VSID */
++2: mulli r3,r3,897*16 /* multiply context by context skew */
++ rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
++ mulli r0,r0,0x111 /* multiply by ESID skew */
++ add r3,r3,r0 /* note code below trims to 24 bits */
++
++ /* Construct the high word of the PPC-style PTE (r11) */
++#ifndef CONFIG_PPC64BRIDGE
++ rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
++ rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */
++#else /* CONFIG_PPC64BRIDGE */
++ clrlwi r3,r3,8 /* reduce vsid to 24 bits */
++ sldi r11,r3,12 /* shift vsid into position */
++ rlwimi r11,r4,16,20,24 /* put in API (abbrev page index) */
++#endif /* CONFIG_PPC64BRIDGE */
++ SET_V(r11) /* set V (valid) bit */
++
++#ifdef CONFIG_SMP
++ addis r9,r7,mmu_hash_lock at ha
++ addi r9,r9,mmu_hash_lock at l
++ rlwinm r8,r1,0,0,18
++ add r8,r8,r7
++ lwz r8,TI_CPU(r8)
++ oris r8,r8,9
++10: lwarx r0,0,r9
++ cmpi 0,r0,0
++ bne- 11f
++ stwcx. r8,0,r9
++ beq+ 12f
++11: lwz r0,0(r9)
++ cmpi 0,r0,0
++ beq 10b
++ b 11b
++12: isync
++#endif
++
++ /*
++ * Check the _PAGE_HASHPTE bit in the linux PTE. If it is
++ * already clear, we're done (for this pte). If not,
++ * clear it (atomically) and proceed. -- paulus.
++ */
++33: lwarx r8,0,r5 /* fetch the pte */
++ andi. r0,r8,_PAGE_HASHPTE
++ beq 8f /* done if HASHPTE is already clear */
++ rlwinm r8,r8,0,31,29 /* clear HASHPTE bit */
++ stwcx. r8,0,r5 /* update the pte */
++ bne- 33b
++
++ /* Get the address of the primary PTE group in the hash table (r3) */
++_GLOBAL(flush_hash_patch_A)
++ addis r8,r7,Hash_base at h /* base address of hash table */
++ rlwimi r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
++ rlwinm r0,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
++ xor r8,r0,r8 /* make primary hash */
++
++ /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
++ li r0,8 /* PTEs/group */
++ mtctr r0
++ addi r12,r8,-PTE_SIZE
++1: LDPTEu r0,PTE_SIZE(r12) /* get next PTE */
++ CMPPTE 0,r0,r11
++ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
++ beq+ 3f
++
++ /* Search the secondary PTEG for a matching PTE */
++ ori r11,r11,PTE_H /* set H (secondary hash) bit */
++ li r0,8 /* PTEs/group */
++_GLOBAL(flush_hash_patch_B)
++ xoris r12,r8,Hash_msk>>16 /* compute secondary hash */
++ xori r12,r12,(-PTEG_SIZE & 0xffff)
++ addi r12,r12,-PTE_SIZE
++ mtctr r0
++2: LDPTEu r0,PTE_SIZE(r12)
++ CMPPTE 0,r0,r11
++ bdnzf 2,2b
++ xori r11,r11,PTE_H /* clear H again */
++ bne- 4f /* should rarely fail to find it */
++
++3: li r0,0
++ STPTE r0,0(r12) /* invalidate entry */
++4: sync
++ tlbie r4 /* in hw tlb too */
++ sync
++
++8: ble cr1,9f /* if all ptes checked */
++81: addi r6,r6,-1
++ addi r5,r5,4 /* advance to next pte */
++ addi r4,r4,0x1000
++ lwz r0,0(r5) /* check next pte */
++ cmpwi cr1,r6,1
++ andi. r0,r0,_PAGE_HASHPTE
++ bne 33b
++ bgt cr1,81b
++
++9:
++#ifdef CONFIG_SMP
++ TLBSYNC
++ li r0,0
++ stw r0,0(r9) /* clear mmu_hash_lock */
++#endif
++
++19: mtmsr r10
++ SYNC_601
++ isync
++ blr
+diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/hash_low_64.S
+@@ -0,0 +1,288 @@
++/*
++ * ppc64 MMU hashtable management routines
++ *
++ * (c) Copyright IBM Corp. 2003
++ *
++ * Maintained by: Benjamin Herrenschmidt
++ * <benh at kernel.crashing.org>
++ *
++ * This file is covered by the GNU Public Licence v2 as
++ * described in the kernel's COPYING file.
++ */
++
++#include <asm/reg.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/page.h>
++#include <asm/types.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/cputable.h>
++
++ .text
++
++/*
++ * Stackframe:
++ *
++ * +-> Back chain (SP + 256)
++ * | General register save area (SP + 112)
++ * | Parameter save area (SP + 48)
++ * | TOC save area (SP + 40)
++ * | link editor doubleword (SP + 32)
++ * | compiler doubleword (SP + 24)
++ * | LR save area (SP + 16)
++ * | CR save area (SP + 8)
++ * SP ---> +-- Back chain (SP + 0)
++ */
++#define STACKFRAMESIZE 256
++
++/* Save parameters offsets */
++#define STK_PARM(i) (STACKFRAMESIZE + 48 + ((i)-3)*8)
++
++/* Save non-volatile offsets */
++#define STK_REG(i) (112 + ((i)-14)*8)
++
++/*
++ * _hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
++ * pte_t *ptep, unsigned long trap, int local)
++ *
++ * Adds a page to the hash table. This is the non-LPAR version for now
++ */
++
++_GLOBAL(__hash_page)
++ mflr r0
++ std r0,16(r1)
++ stdu r1,-STACKFRAMESIZE(r1)
++ /* Save all params that we need after a function call */
++ std r6,STK_PARM(r6)(r1)
++ std r8,STK_PARM(r8)(r1)
++
++ /* Add _PAGE_PRESENT to access */
++ ori r4,r4,_PAGE_PRESENT
++
++ /* Save non-volatile registers.
++ * r31 will hold "old PTE"
++ * r30 is "new PTE"
++ * r29 is "va"
++ * r28 is a hash value
++ * r27 is hashtab mask (maybe dynamic patched instead ?)
++ */
++ std r27,STK_REG(r27)(r1)
++ std r28,STK_REG(r28)(r1)
++ std r29,STK_REG(r29)(r1)
++ std r30,STK_REG(r30)(r1)
++ std r31,STK_REG(r31)(r1)
++
++ /* Step 1:
++ *
++ * Check permissions, atomically mark the linux PTE busy
++ * and hashed.
++ */
++1:
++ ldarx r31,0,r6
++ /* Check access rights (access & ~(pte_val(*ptep))) */
++ andc. r0,r4,r31
++ bne- htab_wrong_access
++ /* Check if PTE is busy */
++ andi. r0,r31,_PAGE_BUSY
++ /* If so, just bail out and refault if needed. Someone else
++ * is changing this PTE anyway and might hash it.
++ */
++ bne- bail_ok
++ /* Prepare new PTE value (turn access RW into DIRTY, then
++ * add BUSY,HASHPTE and ACCESSED)
++ */
++ rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
++ or r30,r30,r31
++ ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
++ /* Write the linux PTE atomically (setting busy) */
++ stdcx. r30,0,r6
++ bne- 1b
++ isync
++
++ /* Step 2:
++ *
++ * Insert/Update the HPTE in the hash table. At this point,
++ * r4 (access) is re-useable, we use it for the new HPTE flags
++ */
++
++ /* Calc va and put it in r29 */
++ rldicr r29,r5,28,63-28
++ rldicl r3,r3,0,36
++ or r29,r3,r29
++
++ /* Calculate hash value for primary slot and store it in r28 */
++ rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
++ rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */
++ xor r28,r5,r0
++
++ /* Convert linux PTE bits into HW equivalents */
++ andi. r3,r30,0x1fe /* Get basic set of flags */
++ xori r3,r3,HW_NO_EXEC /* _PAGE_EXEC -> NOEXEC */
++ rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
++ rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
++ and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY -> r0 bit 30 */
++ andc r0,r30,r0 /* r0 = pte & ~r0 */
++ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
++
++ /* We eventually do the icache sync here (maybe inline that
++ * code rather than call a C function...)
++ */
++BEGIN_FTR_SECTION
++ mr r4,r30
++ mr r5,r7
++ bl .hash_page_do_lazy_icache
++END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
++
++ /* At this point, r3 contains new PP bits, save them in
++ * place of "access" in the param area (sic)
++ */
++ std r3,STK_PARM(r4)(r1)
++
++ /* Get htab_hash_mask */
++ ld r4,htab_hash_mask at got(2)
++ ld r27,0(r4) /* htab_hash_mask -> r27 */
++
++ /* Check if we may already be in the hashtable, in this case, we
++ * go to out-of-line code to try to modify the HPTE
++ */
++ andi. r0,r31,_PAGE_HASHPTE
++ bne htab_modify_pte
++
++htab_insert_pte:
++ /* Clear hpte bits in new pte (we also clear BUSY btw) and
++ * add _PAGE_HASHPTE
++ */
++ lis r0,_PAGE_HPTEFLAGS at h
++ ori r0,r0,_PAGE_HPTEFLAGS at l
++ andc r30,r30,r0
++ ori r30,r30,_PAGE_HASHPTE
++
++ /* page number in r5 */
++ rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT
++
++ /* Calculate primary group hash */
++ and r0,r28,r27
++ rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
++
++ /* Call ppc_md.hpte_insert */
++ ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */
++ mr r4,r29 /* Retreive va */
++ li r6,0 /* no vflags */
++_GLOBAL(htab_call_hpte_insert1)
++ bl . /* Will be patched by htab_finish_init() */
++ cmpdi 0,r3,0
++ bge htab_pte_insert_ok /* Insertion successful */
++ cmpdi 0,r3,-2 /* Critical failure */
++ beq- htab_pte_insert_failure
++
++ /* Now try secondary slot */
++
++ /* page number in r5 */
++ rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT
++
++ /* Calculate secondary group hash */
++ andc r0,r27,r28
++ rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
++
++ /* Call ppc_md.hpte_insert */
++ ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */
++ mr r4,r29 /* Retreive va */
++ li r6,HPTE_V_SECONDARY at l /* secondary slot */
++_GLOBAL(htab_call_hpte_insert2)
++ bl . /* Will be patched by htab_finish_init() */
++ cmpdi 0,r3,0
++ bge+ htab_pte_insert_ok /* Insertion successful */
++ cmpdi 0,r3,-2 /* Critical failure */
++ beq- htab_pte_insert_failure
++
++ /* Both are full, we need to evict something */
++ mftb r0
++ /* Pick a random group based on TB */
++ andi. r0,r0,1
++ mr r5,r28
++ bne 2f
++ not r5,r5
++2: and r0,r5,r27
++ rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
++ /* Call ppc_md.hpte_remove */
++_GLOBAL(htab_call_hpte_remove)
++ bl . /* Will be patched by htab_finish_init() */
++
++ /* Try all again */
++ b htab_insert_pte
++
++bail_ok:
++ li r3,0
++ b bail
++
++htab_pte_insert_ok:
++ /* Insert slot number & secondary bit in PTE */
++ rldimi r30,r3,12,63-15
++
++ /* Write out the PTE with a normal write
++ * (maybe add eieio may be good still ?)
++ */
++htab_write_out_pte:
++ ld r6,STK_PARM(r6)(r1)
++ std r30,0(r6)
++ li r3, 0
++bail:
++ ld r27,STK_REG(r27)(r1)
++ ld r28,STK_REG(r28)(r1)
++ ld r29,STK_REG(r29)(r1)
++ ld r30,STK_REG(r30)(r1)
++ ld r31,STK_REG(r31)(r1)
++ addi r1,r1,STACKFRAMESIZE
++ ld r0,16(r1)
++ mtlr r0
++ blr
++
++htab_modify_pte:
++ /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
++ mr r4,r3
++ rlwinm r3,r31,32-12,29,31
++
++ /* Secondary group ? if yes, get a inverted hash value */
++ mr r5,r28
++ andi. r0,r31,_PAGE_SECONDARY
++ beq 1f
++ not r5,r5
++1:
++ /* Calculate proper slot value for ppc_md.hpte_updatepp */
++ and r0,r5,r27
++ rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
++ add r3,r0,r3 /* add slot idx */
++
++ /* Call ppc_md.hpte_updatepp */
++ mr r5,r29 /* va */
++ li r6,0 /* large is 0 */
++ ld r7,STK_PARM(r8)(r1) /* get "local" param */
++_GLOBAL(htab_call_hpte_updatepp)
++ bl . /* Will be patched by htab_finish_init() */
++
++ /* if we failed because typically the HPTE wasn't really here
++ * we try an insertion.
++ */
++ cmpdi 0,r3,-1
++ beq- htab_insert_pte
++
++ /* Clear the BUSY bit and Write out the PTE */
++ li r0,_PAGE_BUSY
++ andc r30,r30,r0
++ b htab_write_out_pte
++
++htab_wrong_access:
++ /* Bail out clearing reservation */
++ stdcx. r31,0,r6
++ li r3,1
++ b bail
++
++htab_pte_insert_failure:
++ /* Bail out restoring old PTE */
++ ld r6,STK_PARM(r6)(r1)
++ std r31,0(r6)
++ li r3,-1
++ b bail
++
++
+diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/hash_native_64.c
+@@ -0,0 +1,446 @@
++/*
++ * native hashtable management.
++ *
++ * SMP scalability work:
++ * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * 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/spinlock.h>
++#include <linux/bitops.h>
++#include <linux/threads.h>
++#include <linux/smp.h>
++
++#include <asm/abs_addr.h>
++#include <asm/machdep.h>
++#include <asm/mmu.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++#include <asm/tlb.h>
++#include <asm/cputable.h>
++
++#define HPTE_LOCK_BIT 3
++
++static DEFINE_SPINLOCK(native_tlbie_lock);
++
++static inline void native_lock_hpte(hpte_t *hptep)
++{
++ unsigned long *word = &hptep->v;
++
++ while (1) {
++ if (!test_and_set_bit(HPTE_LOCK_BIT, word))
++ break;
++ while(test_bit(HPTE_LOCK_BIT, word))
++ cpu_relax();
++ }
++}
++
++static inline void native_unlock_hpte(hpte_t *hptep)
++{
++ unsigned long *word = &hptep->v;
++
++ asm volatile("lwsync":::"memory");
++ clear_bit(HPTE_LOCK_BIT, word);
++}
++
++long native_hpte_insert(unsigned long hpte_group, unsigned long va,
++ unsigned long prpn, unsigned long vflags,
++ unsigned long rflags)
++{
++ hpte_t *hptep = htab_address + hpte_group;
++ unsigned long hpte_v, hpte_r;
++ int i;
++
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++ if (! (hptep->v & HPTE_V_VALID)) {
++ /* retry with lock held */
++ native_lock_hpte(hptep);
++ if (! (hptep->v & HPTE_V_VALID))
++ break;
++ native_unlock_hpte(hptep);
++ }
++
++ hptep++;
++ }
++
++ if (i == HPTES_PER_GROUP)
++ return -1;
++
++ hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
++ if (vflags & HPTE_V_LARGE)
++ va &= ~(1UL << HPTE_V_AVPN_SHIFT);
++ hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
++
++ hptep->r = hpte_r;
++ /* Guarantee the second dword is visible before the valid bit */
++ __asm__ __volatile__ ("eieio" : : : "memory");
++ /*
++ * Now set the first dword including the valid bit
++ * NOTE: this also unlocks the hpte
++ */
++ hptep->v = hpte_v;
++
++ __asm__ __volatile__ ("ptesync" : : : "memory");
++
++ return i | (!!(vflags & HPTE_V_SECONDARY) << 3);
++}
++
++static long native_hpte_remove(unsigned long hpte_group)
++{
++ hpte_t *hptep;
++ int i;
++ int slot_offset;
++ unsigned long hpte_v;
++
++ /* pick a random entry to start at */
++ slot_offset = mftb() & 0x7;
++
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++ hptep = htab_address + hpte_group + slot_offset;
++ hpte_v = hptep->v;
++
++ if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) {
++ /* retry with lock held */
++ native_lock_hpte(hptep);
++ hpte_v = hptep->v;
++ if ((hpte_v & HPTE_V_VALID)
++ && !(hpte_v & HPTE_V_BOLTED))
++ break;
++ native_unlock_hpte(hptep);
++ }
++
++ slot_offset++;
++ slot_offset &= 0x7;
++ }
++
++ if (i == HPTES_PER_GROUP)
++ return -1;
++
++ /* Invalidate the hpte. NOTE: this also unlocks it */
++ hptep->v = 0;
++
++ return i;
++}
++
++static inline void set_pp_bit(unsigned long pp, hpte_t *addr)
++{
++ unsigned long old;
++ unsigned long *p = &addr->r;
++
++ __asm__ __volatile__(
++ "1: ldarx %0,0,%3\n\
++ rldimi %0,%2,0,61\n\
++ stdcx. %0,0,%3\n\
++ bne 1b"
++ : "=&r" (old), "=m" (*p)
++ : "r" (pp), "r" (p), "m" (*p)
++ : "cc");
++}
++
++/*
++ * Only works on small pages. Yes its ugly to have to check each slot in
++ * the group but we only use this during bootup.
++ */
++static long native_hpte_find(unsigned long vpn)
++{
++ hpte_t *hptep;
++ unsigned long hash;
++ unsigned long i, j;
++ long slot;
++ unsigned long hpte_v;
++
++ hash = hpt_hash(vpn, 0);
++
++ for (j = 0; j < 2; j++) {
++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++ hptep = htab_address + slot;
++ hpte_v = hptep->v;
++
++ if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11))
++ && (hpte_v & HPTE_V_VALID)
++ && ( !!(hpte_v & HPTE_V_SECONDARY) == j)) {
++ /* HPTE matches */
++ if (j)
++ slot = -slot;
++ return slot;
++ }
++ ++slot;
++ }
++ hash = ~hash;
++ }
++
++ return -1;
++}
++
++static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
++ unsigned long va, int large, int local)
++{
++ hpte_t *hptep = htab_address + slot;
++ unsigned long hpte_v;
++ unsigned long avpn = va >> 23;
++ int ret = 0;
++
++ if (large)
++ avpn &= ~1;
++
++ native_lock_hpte(hptep);
++
++ hpte_v = hptep->v;
++
++ /* Even if we miss, we need to invalidate the TLB */
++ if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
++ || !(hpte_v & HPTE_V_VALID)) {
++ native_unlock_hpte(hptep);
++ ret = -1;
++ } else {
++ set_pp_bit(newpp, hptep);
++ native_unlock_hpte(hptep);
++ }
++
++ /* Ensure it is out of the tlb too */
++ if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
++ tlbiel(va);
++ } else {
++ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
++
++ if (lock_tlbie)
++ spin_lock(&native_tlbie_lock);
++ tlbie(va, large);
++ if (lock_tlbie)
++ spin_unlock(&native_tlbie_lock);
++ }
++
++ return ret;
++}
++
++/*
++ * Update the page protection bits. Intended to be used to create
++ * guard pages for kernel data structures on pages which are bolted
++ * in the HPT. Assumes pages being operated on will not be stolen.
++ * Does not work on large pages.
++ *
++ * No need to lock here because we should be the only user.
++ */
++static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
++{
++ unsigned long vsid, va, vpn, flags = 0;
++ long slot;
++ hpte_t *hptep;
++ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
++
++ vsid = get_kernel_vsid(ea);
++ va = (vsid << 28) | (ea & 0x0fffffff);
++ vpn = va >> PAGE_SHIFT;
++
++ slot = native_hpte_find(vpn);
++ if (slot == -1)
++ panic("could not find page to bolt\n");
++ hptep = htab_address + slot;
++
++ set_pp_bit(newpp, hptep);
++
++ /* Ensure it is out of the tlb too */
++ if (lock_tlbie)
++ spin_lock_irqsave(&native_tlbie_lock, flags);
++ tlbie(va, 0);
++ if (lock_tlbie)
++ spin_unlock_irqrestore(&native_tlbie_lock, flags);
++}
++
++static void native_hpte_invalidate(unsigned long slot, unsigned long va,
++ int large, int local)
++{
++ hpte_t *hptep = htab_address + slot;
++ unsigned long hpte_v;
++ unsigned long avpn = va >> 23;
++ unsigned long flags;
++ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
++
++ if (large)
++ avpn &= ~1;
++
++ local_irq_save(flags);
++ native_lock_hpte(hptep);
++
++ hpte_v = hptep->v;
++
++ /* Even if we miss, we need to invalidate the TLB */
++ if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
++ || !(hpte_v & HPTE_V_VALID)) {
++ native_unlock_hpte(hptep);
++ } else {
++ /* Invalidate the hpte. NOTE: this also unlocks it */
++ hptep->v = 0;
++ }
++
++ /* Invalidate the tlb */
++ if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
++ tlbiel(va);
++ } else {
++ if (lock_tlbie)
++ spin_lock(&native_tlbie_lock);
++ tlbie(va, large);
++ if (lock_tlbie)
++ spin_unlock(&native_tlbie_lock);
++ }
++ local_irq_restore(flags);
++}
++
++/*
++ * clear all mappings on kexec. All cpus are in real mode (or they will
++ * be when they isi), and we are the only one left. We rely on our kernel
++ * mapping being 0xC0's and the hardware ignoring those two real bits.
++ *
++ * TODO: add batching support when enabled. remember, no dynamic memory here,
++ * athough there is the control page available...
++ */
++static void native_hpte_clear(void)
++{
++ unsigned long slot, slots, flags;
++ hpte_t *hptep = htab_address;
++ unsigned long hpte_v;
++ unsigned long pteg_count;
++
++ pteg_count = htab_hash_mask + 1;
++
++ local_irq_save(flags);
++
++ /* we take the tlbie lock and hold it. Some hardware will
++ * deadlock if we try to tlbie from two processors at once.
++ */
++ spin_lock(&native_tlbie_lock);
++
++ slots = pteg_count * HPTES_PER_GROUP;
++
++ for (slot = 0; slot < slots; slot++, hptep++) {
++ /*
++ * we could lock the pte here, but we are the only cpu
++ * running, right? and for crash dump, we probably
++ * don't want to wait for a maybe bad cpu.
++ */
++ hpte_v = hptep->v;
++
++ if (hpte_v & HPTE_V_VALID) {
++ hptep->v = 0;
++ tlbie(slot2va(hpte_v, slot), hpte_v & HPTE_V_LARGE);
++ }
++ }
++
++ spin_unlock(&native_tlbie_lock);
++ local_irq_restore(flags);
++}
++
++static void native_flush_hash_range(unsigned long number, int local)
++{
++ unsigned long va, vpn, hash, secondary, slot, flags, avpn;
++ int i, j;
++ hpte_t *hptep;
++ unsigned long hpte_v;
++ struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
++ unsigned long large = batch->large;
++
++ local_irq_save(flags);
++
++ j = 0;
++ for (i = 0; i < number; i++) {
++ va = batch->vaddr[j];
++ if (large)
++ vpn = va >> HPAGE_SHIFT;
++ else
++ vpn = va >> PAGE_SHIFT;
++ hash = hpt_hash(vpn, large);
++ secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
++ if (secondary)
++ hash = ~hash;
++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
++
++ hptep = htab_address + slot;
++
++ avpn = va >> 23;
++ if (large)
++ avpn &= ~0x1UL;
++
++ native_lock_hpte(hptep);
++
++ hpte_v = hptep->v;
++
++ /* Even if we miss, we need to invalidate the TLB */
++ if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
++ || !(hpte_v & HPTE_V_VALID)) {
++ native_unlock_hpte(hptep);
++ } else {
++ /* Invalidate the hpte. NOTE: this also unlocks it */
++ hptep->v = 0;
++ }
++
++ j++;
++ }
++
++ if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
++ asm volatile("ptesync":::"memory");
++
++ for (i = 0; i < j; i++)
++ __tlbiel(batch->vaddr[i]);
++
++ asm volatile("ptesync":::"memory");
++ } else {
++ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
++
++ if (lock_tlbie)
++ spin_lock(&native_tlbie_lock);
++
++ asm volatile("ptesync":::"memory");
++
++ for (i = 0; i < j; i++)
++ __tlbie(batch->vaddr[i], large);
++
++ asm volatile("eieio; tlbsync; ptesync":::"memory");
++
++ if (lock_tlbie)
++ spin_unlock(&native_tlbie_lock);
++ }
++
++ local_irq_restore(flags);
++}
++
++#ifdef CONFIG_PPC_PSERIES
++/* Disable TLB batching on nighthawk */
++static inline int tlb_batching_enabled(void)
++{
++ struct device_node *root = of_find_node_by_path("/");
++ int enabled = 1;
++
++ if (root) {
++ const char *model = get_property(root, "model", NULL);
++ if (model && !strcmp(model, "IBM,9076-N81"))
++ enabled = 0;
++ of_node_put(root);
++ }
++
++ return enabled;
++}
++#else
++static inline int tlb_batching_enabled(void)
++{
++ return 1;
++}
++#endif
++
++void hpte_init_native(void)
++{
++ ppc_md.hpte_invalidate = native_hpte_invalidate;
++ ppc_md.hpte_updatepp = native_hpte_updatepp;
++ ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp;
++ ppc_md.hpte_insert = native_hpte_insert;
++ ppc_md.hpte_remove = native_hpte_remove;
++ ppc_md.hpte_clear_all = native_hpte_clear;
++ if (tlb_batching_enabled())
++ ppc_md.flush_hash_range = native_flush_hash_range;
++ htab_finish_init();
++}
+diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/hash_utils_64.c
+@@ -0,0 +1,459 @@
++/*
++ * PowerPC64 port by Mike Corrigan and Dave Engebretsen
++ * {mikejc|engebret}@us.ibm.com
++ *
++ * Copyright (c) 2000 Mike Corrigan <mikejc at us.ibm.com>
++ *
++ * SMP scalability work:
++ * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * Module name: htab.c
++ *
++ * Description:
++ * PowerPC Hashed Page Table functions
++ *
++ * 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.
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/spinlock.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/proc_fs.h>
++#include <linux/stat.h>
++#include <linux/sysctl.h>
++#include <linux/ctype.h>
++#include <linux/cache.h>
++#include <linux/init.h>
++#include <linux/signal.h>
++
++#include <asm/ppcdebug.h>
++#include <asm/processor.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/mmu_context.h>
++#include <asm/page.h>
++#include <asm/types.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/machdep.h>
++#include <asm/lmb.h>
++#include <asm/abs_addr.h>
++#include <asm/tlbflush.h>
++#include <asm/io.h>
++#include <asm/eeh.h>
++#include <asm/tlb.h>
++#include <asm/cacheflush.h>
++#include <asm/cputable.h>
++#include <asm/abs_addr.h>
++#include <asm/sections.h>
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/*
++ * Note: pte --> Linux PTE
++ * HPTE --> PowerPC Hashed Page Table Entry
++ *
++ * Execution context:
++ * htab_initialize is called with the MMU off (of course), but
++ * the kernel has been copied down to zero so it can directly
++ * reference global data. At this point it is very difficult
++ * to print debug info.
++ *
++ */
++
++#ifdef CONFIG_U3_DART
++extern unsigned long dart_tablebase;
++#endif /* CONFIG_U3_DART */
++
++hpte_t *htab_address;
++unsigned long htab_hash_mask;
++
++unsigned long _SDR1;
++
++#define KB (1024)
++#define MB (1024*KB)
++
++static inline void loop_forever(void)
++{
++ volatile unsigned long x = 1;
++ for(;x;x|=1)
++ ;
++}
++
++static inline void create_pte_mapping(unsigned long start, unsigned long end,
++ unsigned long mode, int large)
++{
++ unsigned long addr;
++ unsigned int step;
++ unsigned long tmp_mode;
++ unsigned long vflags;
++
++ if (large) {
++ step = 16*MB;
++ vflags = HPTE_V_BOLTED | HPTE_V_LARGE;
++ } else {
++ step = 4*KB;
++ vflags = HPTE_V_BOLTED;
++ }
++
++ for (addr = start; addr < end; addr += step) {
++ unsigned long vpn, hash, hpteg;
++ unsigned long vsid = get_kernel_vsid(addr);
++ unsigned long va = (vsid << 28) | (addr & 0xfffffff);
++ int ret = -1;
++
++ if (large)
++ vpn = va >> HPAGE_SHIFT;
++ else
++ vpn = va >> PAGE_SHIFT;
++
++
++ tmp_mode = mode;
++
++ /* Make non-kernel text non-executable */
++ if (!in_kernel_text(addr))
++ tmp_mode = mode | HW_NO_EXEC;
++
++ hash = hpt_hash(vpn, large);
++
++ hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
++
++#ifdef CONFIG_PPC_ISERIES
++ if (systemcfg->platform & PLATFORM_ISERIES_LPAR)
++ ret = iSeries_hpte_bolt_or_insert(hpteg, va,
++ virt_to_abs(addr) >> PAGE_SHIFT,
++ vflags, tmp_mode);
++ else
++#endif
++#ifdef CONFIG_PPC_PSERIES
++ if (systemcfg->platform & PLATFORM_LPAR)
++ ret = pSeries_lpar_hpte_insert(hpteg, va,
++ virt_to_abs(addr) >> PAGE_SHIFT,
++ vflags, tmp_mode);
++ else
++#endif
++#ifdef CONFIG_PPC_MULTIPLATFORM
++ ret = native_hpte_insert(hpteg, va,
++ virt_to_abs(addr) >> PAGE_SHIFT,
++ vflags, tmp_mode);
++#endif
++
++ if (ret == -1) {
++ ppc64_terminate_msg(0x20, "create_pte_mapping");
++ loop_forever();
++ }
++ }
++}
++
++static unsigned long get_hashtable_size(void)
++{
++ unsigned long rnd_mem_size, pteg_count;
++
++ /* If hash size wasn't obtained in prom.c, we calculate it now based on
++ * the total RAM size
++ */
++ if (ppc64_pft_size)
++ return 1UL << ppc64_pft_size;
++
++ /* round mem_size up to next power of 2 */
++ rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize);
++ if (rnd_mem_size < systemcfg->physicalMemorySize)
++ rnd_mem_size <<= 1;
++
++ /* # pages / 2 */
++ pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11);
++
++ return pteg_count << 7;
++}
++
++void __init htab_initialize(void)
++{
++ unsigned long table, htab_size_bytes;
++ unsigned long pteg_count;
++ unsigned long mode_rw;
++ int i, use_largepages = 0;
++ unsigned long base = 0, size = 0;
++ extern unsigned long tce_alloc_start, tce_alloc_end;
++
++ DBG(" -> htab_initialize()\n");
++
++ /*
++ * Calculate the required size of the htab. We want the number of
++ * PTEGs to equal one half the number of real pages.
++ */
++ htab_size_bytes = get_hashtable_size();
++ pteg_count = htab_size_bytes >> 7;
++
++ /* For debug, make the HTAB 1/8 as big as it normally would be. */
++ ifppcdebug(PPCDBG_HTABSIZE) {
++ pteg_count >>= 3;
++ htab_size_bytes = pteg_count << 7;
++ }
++
++ htab_hash_mask = pteg_count - 1;
++
++ if (systemcfg->platform & PLATFORM_LPAR) {
++ /* Using a hypervisor which owns the htab */
++ htab_address = NULL;
++ _SDR1 = 0;
++ } else {
++ /* Find storage for the HPT. Must be contiguous in
++ * the absolute address space.
++ */
++ table = lmb_alloc(htab_size_bytes, htab_size_bytes);
++
++ DBG("Hash table allocated at %lx, size: %lx\n", table,
++ htab_size_bytes);
++
++ if ( !table ) {
++ ppc64_terminate_msg(0x20, "hpt space");
++ loop_forever();
++ }
++ htab_address = abs_to_virt(table);
++
++ /* htab absolute addr + encoded htabsize */
++ _SDR1 = table + __ilog2(pteg_count) - 11;
++
++ /* Initialize the HPT with no entries */
++ memset((void *)table, 0, htab_size_bytes);
++ }
++
++ mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
++
++ /* On U3 based machines, we need to reserve the DART area and
++ * _NOT_ map it to avoid cache paradoxes as it's remapped non
++ * cacheable later on
++ */
++ if (cpu_has_feature(CPU_FTR_16M_PAGE))
++ use_largepages = 1;
++
++ /* create bolted the linear mapping in the hash table */
++ for (i=0; i < lmb.memory.cnt; i++) {
++ base = lmb.memory.region[i].base + KERNELBASE;
++ size = lmb.memory.region[i].size;
++
++ DBG("creating mapping for region: %lx : %lx\n", base, size);
++
++#ifdef CONFIG_U3_DART
++ /* Do not map the DART space. Fortunately, it will be aligned
++ * in such a way that it will not cross two lmb regions and will
++ * fit within a single 16Mb page.
++ * The DART space is assumed to be a full 16Mb region even if we
++ * only use 2Mb of that space. We will use more of it later for
++ * AGP GART. We have to use a full 16Mb large page.
++ */
++ DBG("DART base: %lx\n", dart_tablebase);
++
++ if (dart_tablebase != 0 && dart_tablebase >= base
++ && dart_tablebase < (base + size)) {
++ if (base != dart_tablebase)
++ create_pte_mapping(base, dart_tablebase, mode_rw,
++ use_largepages);
++ if ((base + size) > (dart_tablebase + 16*MB))
++ create_pte_mapping(dart_tablebase + 16*MB, base + size,
++ mode_rw, use_largepages);
++ continue;
++ }
++#endif /* CONFIG_U3_DART */
++ create_pte_mapping(base, base + size, mode_rw, use_largepages);
++ }
++
++ /*
++ * If we have a memory_limit and we've allocated TCEs then we need to
++ * explicitly map the TCE area at the top of RAM. We also cope with the
++ * case that the TCEs start below memory_limit.
++ * tce_alloc_start/end are 16MB aligned so the mapping should work
++ * for either 4K or 16MB pages.
++ */
++ if (tce_alloc_start) {
++ tce_alloc_start += KERNELBASE;
++ tce_alloc_end += KERNELBASE;
++
++ if (base + size >= tce_alloc_start)
++ tce_alloc_start = base + size + 1;
++
++ create_pte_mapping(tce_alloc_start, tce_alloc_end,
++ mode_rw, use_largepages);
++ }
++
++ DBG(" <- htab_initialize()\n");
++}
++#undef KB
++#undef MB
++
++/*
++ * Called by asm hashtable.S for doing lazy icache flush
++ */
++unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
++{
++ struct page *page;
++
++ if (!pfn_valid(pte_pfn(pte)))
++ return pp;
++
++ page = pte_page(pte);
++
++ /* page is dirty */
++ if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) {
++ if (trap == 0x400) {
++ __flush_dcache_icache(page_address(page));
++ set_bit(PG_arch_1, &page->flags);
++ } else
++ pp |= HW_NO_EXEC;
++ }
++ return pp;
++}
++
++/* Result code is:
++ * 0 - handled
++ * 1 - normal page fault
++ * -1 - critical hash insertion error
++ */
++int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
++{
++ void *pgdir;
++ unsigned long vsid;
++ struct mm_struct *mm;
++ pte_t *ptep;
++ int ret;
++ int user_region = 0;
++ int local = 0;
++ cpumask_t tmp;
++
++ if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
++ return 1;
++
++ switch (REGION_ID(ea)) {
++ case USER_REGION_ID:
++ user_region = 1;
++ mm = current->mm;
++ if (! mm)
++ return 1;
++
++ vsid = get_vsid(mm->context.id, ea);
++ break;
++ case VMALLOC_REGION_ID:
++ mm = &init_mm;
++ vsid = get_kernel_vsid(ea);
++ break;
++#if 0
++ case KERNEL_REGION_ID:
++ /*
++ * Should never get here - entire 0xC0... region is bolted.
++ * Send the problem up to do_page_fault
++ */
++#endif
++ default:
++ /* Not a valid range
++ * Send the problem up to do_page_fault
++ */
++ return 1;
++ break;
++ }
++
++ pgdir = mm->pgd;
++
++ if (pgdir == NULL)
++ return 1;
++
++ tmp = cpumask_of_cpu(smp_processor_id());
++ if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
++ local = 1;
++
++ /* Is this a huge page ? */
++ if (unlikely(in_hugepage_area(mm->context, ea)))
++ ret = hash_huge_page(mm, access, ea, vsid, local);
++ else {
++ ptep = find_linux_pte(pgdir, ea);
++ if (ptep == NULL)
++ return 1;
++ ret = __hash_page(ea, access, vsid, ptep, trap, local);
++ }
++
++ return ret;
++}
++
++void flush_hash_page(unsigned long va, pte_t pte, int local)
++{
++ unsigned long vpn, hash, secondary, slot;
++ unsigned long huge = pte_huge(pte);
++
++ if (huge)
++ vpn = va >> HPAGE_SHIFT;
++ else
++ vpn = va >> PAGE_SHIFT;
++ hash = hpt_hash(vpn, huge);
++ secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15;
++ if (secondary)
++ hash = ~hash;
++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12;
++
++ ppc_md.hpte_invalidate(slot, va, huge, local);
++}
++
++void flush_hash_range(unsigned long number, int local)
++{
++ if (ppc_md.flush_hash_range) {
++ ppc_md.flush_hash_range(number, local);
++ } else {
++ int i;
++ struct ppc64_tlb_batch *batch =
++ &__get_cpu_var(ppc64_tlb_batch);
++
++ for (i = 0; i < number; i++)
++ flush_hash_page(batch->vaddr[i], batch->pte[i], local);
++ }
++}
++
++static inline void make_bl(unsigned int *insn_addr, void *func)
++{
++ unsigned long funcp = *((unsigned long *)func);
++ int offset = funcp - (unsigned long)insn_addr;
++
++ *insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc));
++ flush_icache_range((unsigned long)insn_addr, 4+
++ (unsigned long)insn_addr);
++}
++
++/*
++ * low_hash_fault is called when we the low level hash code failed
++ * to instert a PTE due to an hypervisor error
++ */
++void low_hash_fault(struct pt_regs *regs, unsigned long address)
++{
++ if (user_mode(regs)) {
++ siginfo_t info;
++
++ info.si_signo = SIGBUS;
++ info.si_errno = 0;
++ info.si_code = BUS_ADRERR;
++ info.si_addr = (void __user *)address;
++ force_sig_info(SIGBUS, &info, current);
++ return;
++ }
++ bad_page_fault(regs, address, SIGBUS);
++}
++
++void __init htab_finish_init(void)
++{
++ extern unsigned int *htab_call_hpte_insert1;
++ extern unsigned int *htab_call_hpte_insert2;
++ extern unsigned int *htab_call_hpte_remove;
++ extern unsigned int *htab_call_hpte_updatepp;
++
++ make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
++ make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
++ make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);
++ make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp);
++}
+diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/hugetlbpage.c
+@@ -0,0 +1,745 @@
++/*
++ * PPC64 (POWER4) Huge TLB Page Support for Kernel.
++ *
++ * Copyright (C) 2003 David Gibson, IBM Corporation.
++ *
++ * Based on the IA-32 version:
++ * Copyright (C) 2002, Rohit Seth <rohit.seth at intel.com>
++ */
++
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/hugetlb.h>
++#include <linux/pagemap.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/sysctl.h>
++#include <asm/mman.h>
++#include <asm/pgalloc.h>
++#include <asm/tlb.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/machdep.h>
++#include <asm/cputable.h>
++#include <asm/tlb.h>
++
++#include <linux/sysctl.h>
++
++#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
++#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
++
++/* Modelled after find_linux_pte() */
++pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
++{
++ pgd_t *pg;
++ pud_t *pu;
++ pmd_t *pm;
++ pte_t *pt;
++
++ BUG_ON(! in_hugepage_area(mm->context, addr));
++
++ addr &= HPAGE_MASK;
++
++ pg = pgd_offset(mm, addr);
++ if (!pgd_none(*pg)) {
++ pu = pud_offset(pg, addr);
++ if (!pud_none(*pu)) {
++ pm = pmd_offset(pu, addr);
++ pt = (pte_t *)pm;
++ BUG_ON(!pmd_none(*pm)
++ && !(pte_present(*pt) && pte_huge(*pt)));
++ return pt;
++ }
++ }
++
++ return NULL;
++}
++
++pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
++{
++ pgd_t *pg;
++ pud_t *pu;
++ pmd_t *pm;
++ pte_t *pt;
++
++ BUG_ON(! in_hugepage_area(mm->context, addr));
++
++ addr &= HPAGE_MASK;
++
++ pg = pgd_offset(mm, addr);
++ pu = pud_alloc(mm, pg, addr);
++
++ if (pu) {
++ pm = pmd_alloc(mm, pu, addr);
++ if (pm) {
++ pt = (pte_t *)pm;
++ BUG_ON(!pmd_none(*pm)
++ && !(pte_present(*pt) && pte_huge(*pt)));
++ return pt;
++ }
++ }
++
++ return NULL;
++}
++
++#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE)
++
++void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t pte)
++{
++ int i;
++
++ if (pte_present(*ptep)) {
++ pte_clear(mm, addr, ptep);
++ flush_tlb_pending();
++ }
++
++ for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) {
++ *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
++ ptep++;
++ }
++}
++
++pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep)
++{
++ unsigned long old = pte_update(ptep, ~0UL);
++ int i;
++
++ if (old & _PAGE_HASHPTE)
++ hpte_update(mm, addr, old, 0);
++
++ for (i = 1; i < HUGEPTE_BATCH_SIZE; i++)
++ ptep[i] = __pte(0);
++
++ return __pte(old);
++}
++
++/*
++ * This function checks for proper alignment of input addr and len parameters.
++ */
++int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
++{
++ if (len & ~HPAGE_MASK)
++ return -EINVAL;
++ if (addr & ~HPAGE_MASK)
++ return -EINVAL;
++ if (! (within_hugepage_low_range(addr, len)
++ || within_hugepage_high_range(addr, len)) )
++ return -EINVAL;
++ return 0;
++}
++
++static void flush_low_segments(void *parm)
++{
++ u16 areas = (unsigned long) parm;
++ unsigned long i;
++
++ asm volatile("isync" : : : "memory");
++
++ BUILD_BUG_ON((sizeof(areas)*8) != NUM_LOW_AREAS);
++
++ for (i = 0; i < NUM_LOW_AREAS; i++) {
++ if (! (areas & (1U << i)))
++ continue;
++ asm volatile("slbie %0"
++ : : "r" ((i << SID_SHIFT) | SLBIE_C));
++ }
++
++ asm volatile("isync" : : : "memory");
++}
++
++static void flush_high_segments(void *parm)
++{
++ u16 areas = (unsigned long) parm;
++ unsigned long i, j;
++
++ asm volatile("isync" : : : "memory");
++
++ BUILD_BUG_ON((sizeof(areas)*8) != NUM_HIGH_AREAS);
++
++ for (i = 0; i < NUM_HIGH_AREAS; i++) {
++ if (! (areas & (1U << i)))
++ continue;
++ for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
++ asm volatile("slbie %0"
++ :: "r" (((i << HTLB_AREA_SHIFT)
++ + (j << SID_SHIFT)) | SLBIE_C));
++ }
++
++ asm volatile("isync" : : : "memory");
++}
++
++static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
++{
++ unsigned long start = area << SID_SHIFT;
++ unsigned long end = (area+1) << SID_SHIFT;
++ struct vm_area_struct *vma;
++
++ BUG_ON(area >= NUM_LOW_AREAS);
++
++ /* Check no VMAs are in the region */
++ vma = find_vma(mm, start);
++ if (vma && (vma->vm_start < end))
++ return -EBUSY;
++
++ return 0;
++}
++
++static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
++{
++ unsigned long start = area << HTLB_AREA_SHIFT;
++ unsigned long end = (area+1) << HTLB_AREA_SHIFT;
++ struct vm_area_struct *vma;
++
++ BUG_ON(area >= NUM_HIGH_AREAS);
++
++ /* Check no VMAs are in the region */
++ vma = find_vma(mm, start);
++ if (vma && (vma->vm_start < end))
++ return -EBUSY;
++
++ return 0;
++}
++
++static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
++{
++ unsigned long i;
++
++ BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
++ BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);
++
++ newareas &= ~(mm->context.low_htlb_areas);
++ if (! newareas)
++ return 0; /* The segments we want are already open */
++
++ for (i = 0; i < NUM_LOW_AREAS; i++)
++ if ((1 << i) & newareas)
++ if (prepare_low_area_for_htlb(mm, i) != 0)
++ return -EBUSY;
++
++ mm->context.low_htlb_areas |= newareas;
++
++ /* update the paca copy of the context struct */
++ get_paca()->context = mm->context;
++
++ /* the context change must make it to memory before the flush,
++ * so that further SLB misses do the right thing. */
++ mb();
++ on_each_cpu(flush_low_segments, (void *)(unsigned long)newareas, 0, 1);
++
++ return 0;
++}
++
++static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
++{
++ unsigned long i;
++
++ BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
++ BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
++ != NUM_HIGH_AREAS);
++
++ newareas &= ~(mm->context.high_htlb_areas);
++ if (! newareas)
++ return 0; /* The areas we want are already open */
++
++ for (i = 0; i < NUM_HIGH_AREAS; i++)
++ if ((1 << i) & newareas)
++ if (prepare_high_area_for_htlb(mm, i) != 0)
++ return -EBUSY;
++
++ mm->context.high_htlb_areas |= newareas;
++
++ /* update the paca copy of the context struct */
++ get_paca()->context = mm->context;
++
++ /* the context change must make it to memory before the flush,
++ * so that further SLB misses do the right thing. */
++ mb();
++ on_each_cpu(flush_high_segments, (void *)(unsigned long)newareas, 0, 1);
++
++ return 0;
++}
++
++int prepare_hugepage_range(unsigned long addr, unsigned long len)
++{
++ int err;
++
++ if ( (addr+len) < addr )
++ return -EINVAL;
++
++ if ((addr + len) < 0x100000000UL)
++ err = open_low_hpage_areas(current->mm,
++ LOW_ESID_MASK(addr, len));
++ else
++ err = open_high_hpage_areas(current->mm,
++ HTLB_AREA_MASK(addr, len));
++ if (err) {
++ printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
++ " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",
++ addr, len,
++ LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));
++ return err;
++ }
++
++ return 0;
++}
++
++struct page *
++follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
++{
++ pte_t *ptep;
++ struct page *page;
++
++ if (! in_hugepage_area(mm->context, address))
++ return ERR_PTR(-EINVAL);
++
++ ptep = huge_pte_offset(mm, address);
++ page = pte_page(*ptep);
++ if (page)
++ page += (address % HPAGE_SIZE) / PAGE_SIZE;
++
++ return page;
++}
++
++int pmd_huge(pmd_t pmd)
++{
++ return 0;
++}
++
++struct page *
++follow_huge_pmd(struct mm_struct *mm, unsigned long address,
++ pmd_t *pmd, int write)
++{
++ BUG();
++ return NULL;
++}
++
++/* Because we have an exclusive hugepage region which lies within the
++ * normal user address space, we have to take special measures to make
++ * non-huge mmap()s evade the hugepage reserved regions. */
++unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
++ unsigned long len, unsigned long pgoff,
++ unsigned long flags)
++{
++ struct mm_struct *mm = current->mm;
++ struct vm_area_struct *vma;
++ unsigned long start_addr;
++
++ if (len > TASK_SIZE)
++ return -ENOMEM;
++
++ if (addr) {
++ addr = PAGE_ALIGN(addr);
++ vma = find_vma(mm, addr);
++ if (((TASK_SIZE - len) >= addr)
++ && (!vma || (addr+len) <= vma->vm_start)
++ && !is_hugepage_only_range(mm, addr,len))
++ return addr;
++ }
++ if (len > mm->cached_hole_size) {
++ start_addr = addr = mm->free_area_cache;
++ } else {
++ start_addr = addr = TASK_UNMAPPED_BASE;
++ mm->cached_hole_size = 0;
++ }
++
++full_search:
++ vma = find_vma(mm, addr);
++ while (TASK_SIZE - len >= addr) {
++ BUG_ON(vma && (addr >= vma->vm_end));
++
++ if (touches_hugepage_low_range(mm, addr, len)) {
++ addr = ALIGN(addr+1, 1<<SID_SHIFT);
++ vma = find_vma(mm, addr);
++ continue;
++ }
++ if (touches_hugepage_high_range(mm, addr, len)) {
++ addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
++ vma = find_vma(mm, addr);
++ continue;
++ }
++ if (!vma || addr + len <= vma->vm_start) {
++ /*
++ * Remember the place where we stopped the search:
++ */
++ mm->free_area_cache = addr + len;
++ return addr;
++ }
++ if (addr + mm->cached_hole_size < vma->vm_start)
++ mm->cached_hole_size = vma->vm_start - addr;
++ addr = vma->vm_end;
++ vma = vma->vm_next;
++ }
++
++ /* Make sure we didn't miss any holes */
++ if (start_addr != TASK_UNMAPPED_BASE) {
++ start_addr = addr = TASK_UNMAPPED_BASE;
++ mm->cached_hole_size = 0;
++ goto full_search;
++ }
++ return -ENOMEM;
++}
++
++/*
++ * This mmap-allocator allocates new areas top-down from below the
++ * stack's low limit (the base):
++ *
++ * Because we have an exclusive hugepage region which lies within the
++ * normal user address space, we have to take special measures to make
++ * non-huge mmap()s evade the hugepage reserved regions.
++ */
++unsigned long
++arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
++ const unsigned long len, const unsigned long pgoff,
++ const unsigned long flags)
++{
++ struct vm_area_struct *vma, *prev_vma;
++ struct mm_struct *mm = current->mm;
++ unsigned long base = mm->mmap_base, addr = addr0;
++ unsigned long largest_hole = mm->cached_hole_size;
++ int first_time = 1;
++
++ /* requested length too big for entire address space */
++ if (len > TASK_SIZE)
++ return -ENOMEM;
++
++ /* dont allow allocations above current base */
++ if (mm->free_area_cache > base)
++ mm->free_area_cache = base;
++
++ /* requesting a specific address */
++ if (addr) {
++ addr = PAGE_ALIGN(addr);
++ vma = find_vma(mm, addr);
++ if (TASK_SIZE - len >= addr &&
++ (!vma || addr + len <= vma->vm_start)
++ && !is_hugepage_only_range(mm, addr,len))
++ return addr;
++ }
++
++ if (len <= largest_hole) {
++ largest_hole = 0;
++ mm->free_area_cache = base;
++ }
++try_again:
++ /* make sure it can fit in the remaining address space */
++ if (mm->free_area_cache < len)
++ goto fail;
++
++ /* either no address requested or cant fit in requested address hole */
++ addr = (mm->free_area_cache - len) & PAGE_MASK;
++ do {
++hugepage_recheck:
++ if (touches_hugepage_low_range(mm, addr, len)) {
++ addr = (addr & ((~0) << SID_SHIFT)) - len;
++ goto hugepage_recheck;
++ } else if (touches_hugepage_high_range(mm, addr, len)) {
++ addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;
++ goto hugepage_recheck;
++ }
++
++ /*
++ * Lookup failure means no vma is above this address,
++ * i.e. return with success:
++ */
++ if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
++ return addr;
++
++ /*
++ * new region fits between prev_vma->vm_end and
++ * vma->vm_start, use it:
++ */
++ if (addr+len <= vma->vm_start &&
++ (!prev_vma || (addr >= prev_vma->vm_end))) {
++ /* remember the address as a hint for next time */
++ mm->cached_hole_size = largest_hole;
++ return (mm->free_area_cache = addr);
++ } else {
++ /* pull free_area_cache down to the first hole */
++ if (mm->free_area_cache == vma->vm_end) {
++ mm->free_area_cache = vma->vm_start;
++ mm->cached_hole_size = largest_hole;
++ }
++ }
++
++ /* remember the largest hole we saw so far */
++ if (addr + largest_hole < vma->vm_start)
++ largest_hole = vma->vm_start - addr;
++
++ /* try just below the current vma->vm_start */
++ addr = vma->vm_start-len;
++ } while (len <= vma->vm_start);
++
++fail:
++ /*
++ * if hint left us with no space for the requested
++ * mapping then try again:
++ */
++ if (first_time) {
++ mm->free_area_cache = base;
++ largest_hole = 0;
++ first_time = 0;
++ goto try_again;
++ }
++ /*
++ * A failed mmap() very likely causes application failure,
++ * so fall back to the bottom-up function here. This scenario
++ * can happen with large stack limits and large mmap()
++ * allocations.
++ */
++ mm->free_area_cache = TASK_UNMAPPED_BASE;
++ mm->cached_hole_size = ~0UL;
++ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
++ /*
++ * Restore the topdown base:
++ */
++ mm->free_area_cache = base;
++ mm->cached_hole_size = ~0UL;
++
++ return addr;
++}
++
++static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
++{
++ unsigned long addr = 0;
++ struct vm_area_struct *vma;
++
++ vma = find_vma(current->mm, addr);
++ while (addr + len <= 0x100000000UL) {
++ BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
++
++ if (! __within_hugepage_low_range(addr, len, segmask)) {
++ addr = ALIGN(addr+1, 1<<SID_SHIFT);
++ vma = find_vma(current->mm, addr);
++ continue;
++ }
++
++ if (!vma || (addr + len) <= vma->vm_start)
++ return addr;
++ addr = ALIGN(vma->vm_end, HPAGE_SIZE);
++ /* Depending on segmask this might not be a confirmed
++ * hugepage region, so the ALIGN could have skipped
++ * some VMAs */
++ vma = find_vma(current->mm, addr);
++ }
++
++ return -ENOMEM;
++}
++
++static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)
++{
++ unsigned long addr = 0x100000000UL;
++ struct vm_area_struct *vma;
++
++ vma = find_vma(current->mm, addr);
++ while (addr + len <= TASK_SIZE_USER64) {
++ BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
++
++ if (! __within_hugepage_high_range(addr, len, areamask)) {
++ addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
++ vma = find_vma(current->mm, addr);
++ continue;
++ }
++
++ if (!vma || (addr + len) <= vma->vm_start)
++ return addr;
++ addr = ALIGN(vma->vm_end, HPAGE_SIZE);
++ /* Depending on segmask this might not be a confirmed
++ * hugepage region, so the ALIGN could have skipped
++ * some VMAs */
++ vma = find_vma(current->mm, addr);
++ }
++
++ return -ENOMEM;
++}
++
++unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
++ unsigned long len, unsigned long pgoff,
++ unsigned long flags)
++{
++ int lastshift;
++ u16 areamask, curareas;
++
++ if (len & ~HPAGE_MASK)
++ return -EINVAL;
++
++ if (!cpu_has_feature(CPU_FTR_16M_PAGE))
++ return -EINVAL;
++
++ if (test_thread_flag(TIF_32BIT)) {
++ curareas = current->mm->context.low_htlb_areas;
++
++ /* First see if we can do the mapping in the existing
++ * low areas */
++ addr = htlb_get_low_area(len, curareas);
++ if (addr != -ENOMEM)
++ return addr;
++
++ lastshift = 0;
++ for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
++ ! lastshift; areamask >>=1) {
++ if (areamask & 1)
++ lastshift = 1;
++
++ addr = htlb_get_low_area(len, curareas | areamask);
++ if ((addr != -ENOMEM)
++ && open_low_hpage_areas(current->mm, areamask) == 0)
++ return addr;
++ }
++ } else {
++ curareas = current->mm->context.high_htlb_areas;
++
++ /* First see if we can do the mapping in the existing
++ * high areas */
++ addr = htlb_get_high_area(len, curareas);
++ if (addr != -ENOMEM)
++ return addr;
++
++ lastshift = 0;
++ for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
++ ! lastshift; areamask >>=1) {
++ if (areamask & 1)
++ lastshift = 1;
++
++ addr = htlb_get_high_area(len, curareas | areamask);
++ if ((addr != -ENOMEM)
++ && open_high_hpage_areas(current->mm, areamask) == 0)
++ return addr;
++ }
++ }
++ printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
++ " enough areas\n");
++ return -ENOMEM;
++}
++
++int hash_huge_page(struct mm_struct *mm, unsigned long access,
++ unsigned long ea, unsigned long vsid, int local)
++{
++ pte_t *ptep;
++ unsigned long va, vpn;
++ pte_t old_pte, new_pte;
++ unsigned long rflags, prpn;
++ long slot;
++ int err = 1;
++
++ spin_lock(&mm->page_table_lock);
++
++ ptep = huge_pte_offset(mm, ea);
++
++ /* Search the Linux page table for a match with va */
++ va = (vsid << 28) | (ea & 0x0fffffff);
++ vpn = va >> HPAGE_SHIFT;
++
++ /*
++ * If no pte found or not present, send the problem up to
++ * do_page_fault
++ */
++ if (unlikely(!ptep || pte_none(*ptep)))
++ goto out;
++
++/* BUG_ON(pte_bad(*ptep)); */
++
++ /*
++ * Check the user's access rights to the page. If access should be
++ * prevented then send the problem up to do_page_fault.
++ */
++ if (unlikely(access & ~pte_val(*ptep)))
++ goto out;
++ /*
++ * At this point, we have a pte (old_pte) which can be used to build
++ * or update an HPTE. There are 2 cases:
++ *
++ * 1. There is a valid (present) pte with no associated HPTE (this is
++ * the most common case)
++ * 2. There is a valid (present) pte with an associated HPTE. The
++ * current values of the pp bits in the HPTE prevent access
++ * because we are doing software DIRTY bit management and the
++ * page is currently not DIRTY.
++ */
++
++
++ old_pte = *ptep;
++ new_pte = old_pte;
++
++ rflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW));
++ /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */
++ rflags |= ((pte_val(new_pte) & _PAGE_EXEC) ? 0 : HW_NO_EXEC);
++
++ /* Check if pte already has an hpte (case 2) */
++ if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) {
++ /* There MIGHT be an HPTE for this pte */
++ unsigned long hash, slot;
++
++ hash = hpt_hash(vpn, 1);
++ if (pte_val(old_pte) & _PAGE_SECONDARY)
++ hash = ~hash;
++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
++
++ if (ppc_md.hpte_updatepp(slot, rflags, va, 1, local) == -1)
++ pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
++ }
++
++ if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) {
++ unsigned long hash = hpt_hash(vpn, 1);
++ unsigned long hpte_group;
++
++ prpn = pte_pfn(old_pte);
++
++repeat:
++ hpte_group = ((hash & htab_hash_mask) *
++ HPTES_PER_GROUP) & ~0x7UL;
++
++ /* Update the linux pte with the HPTE slot */
++ pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;
++ pte_val(new_pte) |= _PAGE_HASHPTE;
++
++ /* Add in WIMG bits */
++ /* XXX We should store these in the pte */
++ rflags |= _PAGE_COHERENT;
++
++ slot = ppc_md.hpte_insert(hpte_group, va, prpn,
++ HPTE_V_LARGE, rflags);
++
++ /* Primary is full, try the secondary */
++ if (unlikely(slot == -1)) {
++ pte_val(new_pte) |= _PAGE_SECONDARY;
++ hpte_group = ((~hash & htab_hash_mask) *
++ HPTES_PER_GROUP) & ~0x7UL;
++ slot = ppc_md.hpte_insert(hpte_group, va, prpn,
++ HPTE_V_LARGE |
++ HPTE_V_SECONDARY,
++ rflags);
++ if (slot == -1) {
++ if (mftb() & 0x1)
++ hpte_group = ((hash & htab_hash_mask) *
++ HPTES_PER_GROUP)&~0x7UL;
++
++ ppc_md.hpte_remove(hpte_group);
++ goto repeat;
++ }
++ }
++
++ if (unlikely(slot == -2))
++ panic("hash_huge_page: pte_insert failed\n");
++
++ pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;
++
++ /*
++ * No need to use ldarx/stdcx here because all who
++ * might be updating the pte will hold the
++ * page_table_lock
++ */
++ *ptep = new_pte;
++ }
++
++ err = 0;
++
++ out:
++ spin_unlock(&mm->page_table_lock);
++
++ return err;
++}
+diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/imalloc.c
+@@ -0,0 +1,312 @@
++/*
++ * c 2001 PPC 64 Team, IBM Corp
++ *
++ * 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/slab.h>
++#include <linux/vmalloc.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/semaphore.h>
++#include <asm/imalloc.h>
++#include <asm/cacheflush.h>
++
++static DECLARE_MUTEX(imlist_sem);
++struct vm_struct * imlist = NULL;
++
++static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
++{
++ unsigned long addr;
++ struct vm_struct **p, *tmp;
++
++ addr = ioremap_bot;
++ for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
++ if (size + addr < (unsigned long) tmp->addr)
++ break;
++ if ((unsigned long)tmp->addr >= ioremap_bot)
++ addr = tmp->size + (unsigned long) tmp->addr;
++ if (addr >= IMALLOC_END-size)
++ return 1;
++ }
++ *im_addr = addr;
++
++ return 0;
++}
++
++/* Return whether the region described by v_addr and size is a subset
++ * of the region described by parent
++ */
++static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
++ struct vm_struct *parent)
++{
++ return (int) (v_addr >= (unsigned long) parent->addr &&
++ v_addr < (unsigned long) parent->addr + parent->size &&
++ size < parent->size);
++}
++
++/* Return whether the region described by v_addr and size is a superset
++ * of the region described by child
++ */
++static int im_region_is_superset(unsigned long v_addr, unsigned long size,
++ struct vm_struct *child)
++{
++ struct vm_struct parent;
++
++ parent.addr = (void *) v_addr;
++ parent.size = size;
++
++ return im_region_is_subset((unsigned long) child->addr, child->size,
++ &parent);
++}
++
++/* Return whether the region described by v_addr and size overlaps
++ * the region described by vm. Overlapping regions meet the
++ * following conditions:
++ * 1) The regions share some part of the address space
++ * 2) The regions aren't identical
++ * 3) Neither region is a subset of the other
++ */
++static int im_region_overlaps(unsigned long v_addr, unsigned long size,
++ struct vm_struct *vm)
++{
++ if (im_region_is_superset(v_addr, size, vm))
++ return 0;
++
++ return (v_addr + size > (unsigned long) vm->addr + vm->size &&
++ v_addr < (unsigned long) vm->addr + vm->size) ||
++ (v_addr < (unsigned long) vm->addr &&
++ v_addr + size > (unsigned long) vm->addr);
++}
++
++/* Determine imalloc status of region described by v_addr and size.
++ * Can return one of the following:
++ * IM_REGION_UNUSED - Entire region is unallocated in imalloc space.
++ * IM_REGION_SUBSET - Region is a subset of a region that is already
++ * allocated in imalloc space.
++ * vm will be assigned to a ptr to the parent region.
++ * IM_REGION_EXISTS - Exact region already allocated in imalloc space.
++ * vm will be assigned to a ptr to the existing imlist
++ * member.
++ * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space.
++ * IM_REGION_SUPERSET - Region is a superset of a region that is already
++ * allocated in imalloc space.
++ */
++static int im_region_status(unsigned long v_addr, unsigned long size,
++ struct vm_struct **vm)
++{
++ struct vm_struct *tmp;
++
++ for (tmp = imlist; tmp; tmp = tmp->next)
++ if (v_addr < (unsigned long) tmp->addr + tmp->size)
++ break;
++
++ if (tmp) {
++ if (im_region_overlaps(v_addr, size, tmp))
++ return IM_REGION_OVERLAP;
++
++ *vm = tmp;
++ if (im_region_is_subset(v_addr, size, tmp)) {
++ /* Return with tmp pointing to superset */
++ return IM_REGION_SUBSET;
++ }
++ if (im_region_is_superset(v_addr, size, tmp)) {
++ /* Return with tmp pointing to first subset */
++ return IM_REGION_SUPERSET;
++ }
++ else if (v_addr == (unsigned long) tmp->addr &&
++ size == tmp->size) {
++ /* Return with tmp pointing to exact region */
++ return IM_REGION_EXISTS;
++ }
++ }
++
++ *vm = NULL;
++ return IM_REGION_UNUSED;
++}
++
++static struct vm_struct * split_im_region(unsigned long v_addr,
++ unsigned long size, struct vm_struct *parent)
++{
++ struct vm_struct *vm1 = NULL;
++ struct vm_struct *vm2 = NULL;
++ struct vm_struct *new_vm = NULL;
++
++ vm1 = (struct vm_struct *) kmalloc(sizeof(*vm1), GFP_KERNEL);
++ if (vm1 == NULL) {
++ printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++
++ if (v_addr == (unsigned long) parent->addr) {
++ /* Use existing parent vm_struct to represent child, allocate
++ * new one for the remainder of parent range
++ */
++ vm1->size = parent->size - size;
++ vm1->addr = (void *) (v_addr + size);
++ vm1->next = parent->next;
++
++ parent->size = size;
++ parent->next = vm1;
++ new_vm = parent;
++ } else if (v_addr + size == (unsigned long) parent->addr +
++ parent->size) {
++ /* Allocate new vm_struct to represent child, use existing
++ * parent one for remainder of parent range
++ */
++ vm1->size = size;
++ vm1->addr = (void *) v_addr;
++ vm1->next = parent->next;
++ new_vm = vm1;
++
++ parent->size -= size;
++ parent->next = vm1;
++ } else {
++ /* Allocate two new vm_structs for the new child and
++ * uppermost remainder, and use existing parent one for the
++ * lower remainder of parent range
++ */
++ vm2 = (struct vm_struct *) kmalloc(sizeof(*vm2), GFP_KERNEL);
++ if (vm2 == NULL) {
++ printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
++ kfree(vm1);
++ return NULL;
++ }
++
++ vm1->size = size;
++ vm1->addr = (void *) v_addr;
++ vm1->next = vm2;
++ new_vm = vm1;
++
++ vm2->size = ((unsigned long) parent->addr + parent->size) -
++ (v_addr + size);
++ vm2->addr = (void *) v_addr + size;
++ vm2->next = parent->next;
++
++ parent->size = v_addr - (unsigned long) parent->addr;
++ parent->next = vm1;
++ }
++
++ return new_vm;
++}
++
++static struct vm_struct * __add_new_im_area(unsigned long req_addr,
++ unsigned long size)
++{
++ struct vm_struct **p, *tmp, *area;
++
++ for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
++ if (req_addr + size <= (unsigned long)tmp->addr)
++ break;
++ }
++
++ area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
++ if (!area)
++ return NULL;
++ area->flags = 0;
++ area->addr = (void *)req_addr;
++ area->size = size;
++ area->next = *p;
++ *p = area;
++
++ return area;
++}
++
++static struct vm_struct * __im_get_area(unsigned long req_addr,
++ unsigned long size,
++ int criteria)
++{
++ struct vm_struct *tmp;
++ int status;
++
++ status = im_region_status(req_addr, size, &tmp);
++ if ((criteria & status) == 0) {
++ return NULL;
++ }
++
++ switch (status) {
++ case IM_REGION_UNUSED:
++ tmp = __add_new_im_area(req_addr, size);
++ break;
++ case IM_REGION_SUBSET:
++ tmp = split_im_region(req_addr, size, tmp);
++ break;
++ case IM_REGION_EXISTS:
++ /* Return requested region */
++ break;
++ case IM_REGION_SUPERSET:
++ /* Return first existing subset of requested region */
++ break;
++ default:
++ printk(KERN_ERR "%s() unexpected imalloc region status\n",
++ __FUNCTION__);
++ tmp = NULL;
++ }
++
++ return tmp;
++}
++
++struct vm_struct * im_get_free_area(unsigned long size)
++{
++ struct vm_struct *area;
++ unsigned long addr;
++
++ down(&imlist_sem);
++ if (get_free_im_addr(size, &addr)) {
++ printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
++ __FUNCTION__, size);
++ area = NULL;
++ goto next_im_done;
++ }
++
++ area = __im_get_area(addr, size, IM_REGION_UNUSED);
++ if (area == NULL) {
++ printk(KERN_ERR
++ "%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
++ __FUNCTION__, addr, size);
++ }
++next_im_done:
++ up(&imlist_sem);
++ return area;
++}
++
++struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
++ int criteria)
++{
++ struct vm_struct *area;
++
++ down(&imlist_sem);
++ area = __im_get_area(v_addr, size, criteria);
++ up(&imlist_sem);
++ return area;
++}
++
++void im_free(void * addr)
++{
++ struct vm_struct **p, *tmp;
++
++ if (!addr)
++ return;
++ if ((unsigned long) addr & ~PAGE_MASK) {
++ printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr);
++ return;
++ }
++ down(&imlist_sem);
++ for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
++ if (tmp->addr == addr) {
++ *p = tmp->next;
++ unmap_vm_area(tmp);
++ kfree(tmp);
++ up(&imlist_sem);
++ return;
++ }
++ }
++ up(&imlist_sem);
++ printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
++ addr);
++}
+diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/init_32.c
+@@ -0,0 +1,254 @@
++/*
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ * PPC44x/36-bit changes by Matt Porter (mporter at mvista.com)
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/highmem.h>
++#include <linux/initrd.h>
++#include <linux/pagemap.h>
++
++#include <asm/pgalloc.h>
++#include <asm/prom.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/smp.h>
++#include <asm/machdep.h>
++#include <asm/btext.h>
++#include <asm/tlb.h>
++#include <asm/prom.h>
++#include <asm/lmb.h>
++#include <asm/sections.h>
++
++#include "mmu_decl.h"
++
++#if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL)
++/* The ammount of lowmem must be within 0xF0000000 - KERNELBASE. */
++#if (CONFIG_LOWMEM_SIZE > (0xF0000000 - KERNELBASE))
++#error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL"
++#endif
++#endif
++#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE
++
++DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
++
++unsigned long total_memory;
++unsigned long total_lowmem;
++
++unsigned long ppc_memstart;
++unsigned long ppc_memoffset = PAGE_OFFSET;
++
++int boot_mapsize;
++#ifdef CONFIG_PPC_PMAC
++unsigned long agp_special_page;
++EXPORT_SYMBOL(agp_special_page);
++#endif
++
++#ifdef CONFIG_HIGHMEM
++pte_t *kmap_pte;
++pgprot_t kmap_prot;
++
++EXPORT_SYMBOL(kmap_prot);
++EXPORT_SYMBOL(kmap_pte);
++#endif
++
++void MMU_init(void);
++
++/* XXX should be in current.h -- paulus */
++extern struct task_struct *current_set[NR_CPUS];
++
++char *klimit = _end;
++struct device_node *memory_node;
++
++extern int init_bootmem_done;
++
++/*
++ * this tells the system to map all of ram with the segregs
++ * (i.e. page tables) instead of the bats.
++ * -- Cort
++ */
++int __map_without_bats;
++int __map_without_ltlbs;
++
++/* max amount of low RAM to map in */
++unsigned long __max_low_memory = MAX_LOW_MEM;
++
++/*
++ * limit of what is accessible with initial MMU setup -
++ * 256MB usually, but only 16MB on 601.
++ */
++unsigned long __initial_memory_limit = 0x10000000;
++
++/*
++ * Check for command-line options that affect what MMU_init will do.
++ */
++void MMU_setup(void)
++{
++ /* Check for nobats option (used in mapin_ram). */
++ if (strstr(cmd_line, "nobats")) {
++ __map_without_bats = 1;
++ }
++
++ if (strstr(cmd_line, "noltlbs")) {
++ __map_without_ltlbs = 1;
++ }
++}
++
++/*
++ * MMU_init sets up the basic memory mappings for the kernel,
++ * including both RAM and possibly some I/O regions,
++ * and sets up the page tables and the MMU hardware ready to go.
++ */
++void __init MMU_init(void)
++{
++ if (ppc_md.progress)
++ ppc_md.progress("MMU:enter", 0x111);
++
++ /* 601 can only access 16MB at the moment */
++ if (PVR_VER(mfspr(SPRN_PVR)) == 1)
++ __initial_memory_limit = 0x01000000;
++
++ /* parse args from command line */
++ MMU_setup();
++
++ if (lmb.memory.cnt > 1) {
++ lmb.memory.cnt = 1;
++ lmb_analyze();
++ printk(KERN_WARNING "Only using first contiguous memory region");
++ }
++
++ total_memory = lmb_end_of_DRAM();
++ total_lowmem = total_memory;
++
++#ifdef CONFIG_FSL_BOOKE
++ /* Freescale Book-E parts expect lowmem to be mapped by fixed TLB
++ * entries, so we need to adjust lowmem to match the amount we can map
++ * in the fixed entries */
++ adjust_total_lowmem();
++#endif /* CONFIG_FSL_BOOKE */
++
++ if (total_lowmem > __max_low_memory) {
++ total_lowmem = __max_low_memory;
++#ifndef CONFIG_HIGHMEM
++ total_memory = total_lowmem;
++ lmb_enforce_memory_limit(total_lowmem);
++ lmb_analyze();
++#endif /* CONFIG_HIGHMEM */
++ }
++
++ /* Initialize the MMU hardware */
++ if (ppc_md.progress)
++ ppc_md.progress("MMU:hw init", 0x300);
++ MMU_init_hw();
++
++ /* Map in all of RAM starting at KERNELBASE */
++ if (ppc_md.progress)
++ ppc_md.progress("MMU:mapin", 0x301);
++ mapin_ram();
++
++#ifdef CONFIG_HIGHMEM
++ ioremap_base = PKMAP_BASE;
++#else
++ ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */
++#endif /* CONFIG_HIGHMEM */
++ ioremap_bot = ioremap_base;
++
++ /* Map in I/O resources */
++ if (ppc_md.progress)
++ ppc_md.progress("MMU:setio", 0x302);
++ if (ppc_md.setup_io_mappings)
++ ppc_md.setup_io_mappings();
++
++ /* Initialize the context management stuff */
++ mmu_context_init();
++
++ if (ppc_md.progress)
++ ppc_md.progress("MMU:exit", 0x211);
++}
++
++/* This is only called until mem_init is done. */
++void __init *early_get_page(void)
++{
++ void *p;
++
++ if (init_bootmem_done) {
++ p = alloc_bootmem_pages(PAGE_SIZE);
++ } else {
++ p = __va(lmb_alloc_base(PAGE_SIZE, PAGE_SIZE,
++ __initial_memory_limit));
++ }
++ return p;
++}
++
++/* Free up now-unused memory */
++static void free_sec(unsigned long start, unsigned long end, const char *name)
++{
++ unsigned long cnt = 0;
++
++ while (start < end) {
++ ClearPageReserved(virt_to_page(start));
++ set_page_count(virt_to_page(start), 1);
++ free_page(start);
++ cnt++;
++ start += PAGE_SIZE;
++ }
++ if (cnt) {
++ printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name);
++ totalram_pages += cnt;
++ }
++}
++
++void free_initmem(void)
++{
++#define FREESEC(TYPE) \
++ free_sec((unsigned long)(&__ ## TYPE ## _begin), \
++ (unsigned long)(&__ ## TYPE ## _end), \
++ #TYPE);
++
++ printk ("Freeing unused kernel memory:");
++ FREESEC(init);
++ printk("\n");
++ ppc_md.progress = NULL;
++#undef FREESEC
++}
++
++#ifdef CONFIG_BLK_DEV_INITRD
++void free_initrd_mem(unsigned long start, unsigned long end)
++{
++ if (start < end)
++ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
++ for (; start < end; start += PAGE_SIZE) {
++ ClearPageReserved(virt_to_page(start));
++ set_page_count(virt_to_page(start), 1);
++ free_page(start);
++ totalram_pages++;
++ }
++}
++#endif
+diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/init_64.c
+@@ -0,0 +1,223 @@
++/*
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * Dave Engebretsen <engebret at us.ibm.com>
++ * Rework for PPC64 port.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/stddef.h>
++#include <linux/vmalloc.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/highmem.h>
++#include <linux/idr.h>
++#include <linux/nodemask.h>
++#include <linux/module.h>
++
++#include <asm/pgalloc.h>
++#include <asm/page.h>
++#include <asm/prom.h>
++#include <asm/lmb.h>
++#include <asm/rtas.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/uaccess.h>
++#include <asm/smp.h>
++#include <asm/machdep.h>
++#include <asm/tlb.h>
++#include <asm/eeh.h>
++#include <asm/processor.h>
++#include <asm/mmzone.h>
++#include <asm/cputable.h>
++#include <asm/ppcdebug.h>
++#include <asm/sections.h>
++#include <asm/system.h>
++#include <asm/iommu.h>
++#include <asm/abs_addr.h>
++#include <asm/vdso.h>
++#include <asm/imalloc.h>
++
++#if PGTABLE_RANGE > USER_VSID_RANGE
++#warning Limited user VSID range means pagetable space is wasted
++#endif
++
++#if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
++#warning TASK_SIZE is smaller than it needs to be.
++#endif
++
++unsigned long klimit = (unsigned long)_end;
++
++/* max amount of RAM to use */
++unsigned long __max_memory;
++
++/* info on what we think the IO hole is */
++unsigned long io_hole_start;
++unsigned long io_hole_size;
++
++/*
++ * Do very early mm setup.
++ */
++void __init mm_init_ppc64(void)
++{
++#ifndef CONFIG_PPC_ISERIES
++ unsigned long i;
++#endif
++
++ ppc64_boot_msg(0x100, "MM Init");
++
++ /* This is the story of the IO hole... please, keep seated,
++ * unfortunately, we are out of oxygen masks at the moment.
++ * So we need some rough way to tell where your big IO hole
++ * is. On pmac, it's between 2G and 4G, on POWER3, it's around
++ * that area as well, on POWER4 we don't have one, etc...
++ * We need that as a "hint" when sizing the TCE table on POWER3
++ * So far, the simplest way that seem work well enough for us it
++ * to just assume that the first discontinuity in our physical
++ * RAM layout is the IO hole. That may not be correct in the future
++ * (and isn't on iSeries but then we don't care ;)
++ */
++
++#ifndef CONFIG_PPC_ISERIES
++ for (i = 1; i < lmb.memory.cnt; i++) {
++ unsigned long base, prevbase, prevsize;
++
++ prevbase = lmb.memory.region[i-1].base;
++ prevsize = lmb.memory.region[i-1].size;
++ base = lmb.memory.region[i].base;
++ if (base > (prevbase + prevsize)) {
++ io_hole_start = prevbase + prevsize;
++ io_hole_size = base - (prevbase + prevsize);
++ break;
++ }
++ }
++#endif /* CONFIG_PPC_ISERIES */
++ if (io_hole_start)
++ printk("IO Hole assumed to be %lx -> %lx\n",
++ io_hole_start, io_hole_start + io_hole_size - 1);
++
++ ppc64_boot_msg(0x100, "MM Init Done");
++}
++
++void free_initmem(void)
++{
++ unsigned long addr;
++
++ addr = (unsigned long)__init_begin;
++ for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
++ memset((void *)addr, 0xcc, PAGE_SIZE);
++ ClearPageReserved(virt_to_page(addr));
++ set_page_count(virt_to_page(addr), 1);
++ free_page(addr);
++ totalram_pages++;
++ }
++ printk ("Freeing unused kernel memory: %luk freed\n",
++ ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10);
++}
++
++#ifdef CONFIG_BLK_DEV_INITRD
++void free_initrd_mem(unsigned long start, unsigned long end)
++{
++ if (start < end)
++ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
++ for (; start < end; start += PAGE_SIZE) {
++ ClearPageReserved(virt_to_page(start));
++ set_page_count(virt_to_page(start), 1);
++ free_page(start);
++ totalram_pages++;
++ }
++}
++#endif
++
++static struct kcore_list kcore_vmem;
++
++static int __init setup_kcore(void)
++{
++ int i;
++
++ for (i=0; i < lmb.memory.cnt; i++) {
++ unsigned long base, size;
++ struct kcore_list *kcore_mem;
++
++ base = lmb.memory.region[i].base;
++ size = lmb.memory.region[i].size;
++
++ /* GFP_ATOMIC to avoid might_sleep warnings during boot */
++ kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
++ if (!kcore_mem)
++ panic("mem_init: kmalloc failed\n");
++
++ kclist_add(kcore_mem, __va(base), size);
++ }
++
++ kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);
++
++ return 0;
++}
++module_init(setup_kcore);
++
++static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
++{
++ memset(addr, 0, kmem_cache_size(cache));
++}
++
++static const int pgtable_cache_size[2] = {
++ PTE_TABLE_SIZE, PMD_TABLE_SIZE
++};
++static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
++ "pgd_pte_cache", "pud_pmd_cache",
++};
++
++kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
++
++void pgtable_cache_init(void)
++{
++ int i;
++
++ BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]);
++ BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]);
++ BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]);
++ BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]);
++
++ for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {
++ int size = pgtable_cache_size[i];
++ const char *name = pgtable_cache_name[i];
++
++ pgtable_cache[i] = kmem_cache_create(name,
++ size, size,
++ SLAB_HWCACHE_ALIGN
++ | SLAB_MUST_HWCACHE_ALIGN,
++ zero_ctor,
++ NULL);
++ if (! pgtable_cache[i])
++ panic("pgtable_cache_init(): could not create %s!\n",
++ name);
++ }
++}
+diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/lmb.c
+@@ -0,0 +1,296 @@
++/*
++ * Procedures for maintaining information about logical memory blocks.
++ *
++ * Peter Bergner, IBM Corp. June 2001.
++ * Copyright (C) 2001 Peter Bergner.
++ *
++ * 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/init.h>
++#include <linux/bitops.h>
++#include <asm/types.h>
++#include <asm/page.h>
++#include <asm/prom.h>
++#include <asm/lmb.h>
++#ifdef CONFIG_PPC32
++#include "mmu_decl.h" /* for __max_low_memory */
++#endif
++
++struct lmb lmb;
++
++#undef DEBUG
++
++void lmb_dump_all(void)
++{
++#ifdef DEBUG
++ unsigned long i;
++
++ udbg_printf("lmb_dump_all:\n");
++ udbg_printf(" memory.cnt = 0x%lx\n",
++ lmb.memory.cnt);
++ udbg_printf(" memory.size = 0x%lx\n",
++ lmb.memory.size);
++ for (i=0; i < lmb.memory.cnt ;i++) {
++ udbg_printf(" memory.region[0x%x].base = 0x%lx\n",
++ i, lmb.memory.region[i].base);
++ udbg_printf(" .size = 0x%lx\n",
++ lmb.memory.region[i].size);
++ }
++
++ udbg_printf("\n reserved.cnt = 0x%lx\n",
++ lmb.reserved.cnt);
++ udbg_printf(" reserved.size = 0x%lx\n",
++ lmb.reserved.size);
++ for (i=0; i < lmb.reserved.cnt ;i++) {
++ udbg_printf(" reserved.region[0x%x].base = 0x%lx\n",
++ i, lmb.reserved.region[i].base);
++ udbg_printf(" .size = 0x%lx\n",
++ lmb.reserved.region[i].size);
++ }
++#endif /* DEBUG */
++}
++
++static unsigned long __init lmb_addrs_overlap(unsigned long base1,
++ unsigned long size1, unsigned long base2, unsigned long size2)
++{
++ return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
++}
++
++static long __init lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
++ unsigned long base2, unsigned long size2)
++{
++ if (base2 == base1 + size1)
++ return 1;
++ else if (base1 == base2 + size2)
++ return -1;
++
++ return 0;
++}
++
++static long __init lmb_regions_adjacent(struct lmb_region *rgn,
++ unsigned long r1, unsigned long r2)
++{
++ unsigned long base1 = rgn->region[r1].base;
++ unsigned long size1 = rgn->region[r1].size;
++ unsigned long base2 = rgn->region[r2].base;
++ unsigned long size2 = rgn->region[r2].size;
++
++ return lmb_addrs_adjacent(base1, size1, base2, size2);
++}
++
++/* Assumption: base addr of region 1 < base addr of region 2 */
++static void __init lmb_coalesce_regions(struct lmb_region *rgn,
++ unsigned long r1, unsigned long r2)
++{
++ unsigned long i;
++
++ rgn->region[r1].size += rgn->region[r2].size;
++ for (i=r2; i < rgn->cnt-1; i++) {
++ rgn->region[i].base = rgn->region[i+1].base;
++ rgn->region[i].size = rgn->region[i+1].size;
++ }
++ rgn->cnt--;
++}
++
++/* This routine called with relocation disabled. */
++void __init lmb_init(void)
++{
++ /* Create a dummy zero size LMB which will get coalesced away later.
++ * This simplifies the lmb_add() code below...
++ */
++ lmb.memory.region[0].base = 0;
++ lmb.memory.region[0].size = 0;
++ lmb.memory.cnt = 1;
++
++ /* Ditto. */
++ lmb.reserved.region[0].base = 0;
++ lmb.reserved.region[0].size = 0;
++ lmb.reserved.cnt = 1;
++}
++
++/* This routine may be called with relocation disabled. */
++void __init lmb_analyze(void)
++{
++ int i;
++
++ lmb.memory.size = 0;
++
++ for (i = 0; i < lmb.memory.cnt; i++)
++ lmb.memory.size += lmb.memory.region[i].size;
++}
++
++/* This routine called with relocation disabled. */
++static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
++ unsigned long size)
++{
++ unsigned long i, coalesced = 0;
++ long adjacent;
++
++ /* First try and coalesce this LMB with another. */
++ for (i=0; i < rgn->cnt; i++) {
++ unsigned long rgnbase = rgn->region[i].base;
++ unsigned long rgnsize = rgn->region[i].size;
++
++ adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
++ if ( adjacent > 0 ) {
++ rgn->region[i].base -= size;
++ rgn->region[i].size += size;
++ coalesced++;
++ break;
++ }
++ else if ( adjacent < 0 ) {
++ rgn->region[i].size += size;
++ coalesced++;
++ break;
++ }
++ }
++
++ if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) {
++ lmb_coalesce_regions(rgn, i, i+1);
++ coalesced++;
++ }
++
++ if (coalesced)
++ return coalesced;
++ if (rgn->cnt >= MAX_LMB_REGIONS)
++ return -1;
++
++ /* Couldn't coalesce the LMB, so add it to the sorted table. */
++ for (i = rgn->cnt-1; i >= 0; i--) {
++ if (base < rgn->region[i].base) {
++ rgn->region[i+1].base = rgn->region[i].base;
++ rgn->region[i+1].size = rgn->region[i].size;
++ } else {
++ rgn->region[i+1].base = base;
++ rgn->region[i+1].size = size;
++ break;
++ }
++ }
++ rgn->cnt++;
++
++ return 0;
++}
++
++/* This routine may be called with relocation disabled. */
++long __init lmb_add(unsigned long base, unsigned long size)
++{
++ struct lmb_region *_rgn = &(lmb.memory);
++
++ /* On pSeries LPAR systems, the first LMB is our RMO region. */
++ if (base == 0)
++ lmb.rmo_size = size;
++
++ return lmb_add_region(_rgn, base, size);
++
++}
++
++long __init lmb_reserve(unsigned long base, unsigned long size)
++{
++ struct lmb_region *_rgn = &(lmb.reserved);
++
++ return lmb_add_region(_rgn, base, size);
++}
++
++long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base,
++ unsigned long size)
++{
++ unsigned long i;
++
++ for (i=0; i < rgn->cnt; i++) {
++ unsigned long rgnbase = rgn->region[i].base;
++ unsigned long rgnsize = rgn->region[i].size;
++ if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) {
++ break;
++ }
++ }
++
++ return (i < rgn->cnt) ? i : -1;
++}
++
++unsigned long __init lmb_alloc(unsigned long size, unsigned long align)
++{
++ return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
++}
++
++unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align,
++ unsigned long max_addr)
++{
++ long i, j;
++ unsigned long base = 0;
++
++#ifdef CONFIG_PPC32
++ /* On 32-bit, make sure we allocate lowmem */
++ if (max_addr == LMB_ALLOC_ANYWHERE)
++ max_addr = __max_low_memory;
++#endif
++ for (i = lmb.memory.cnt-1; i >= 0; i--) {
++ unsigned long lmbbase = lmb.memory.region[i].base;
++ unsigned long lmbsize = lmb.memory.region[i].size;
++
++ if (max_addr == LMB_ALLOC_ANYWHERE)
++ base = _ALIGN_DOWN(lmbbase + lmbsize - size, align);
++ else if (lmbbase < max_addr) {
++ base = min(lmbbase + lmbsize, max_addr);
++ base = _ALIGN_DOWN(base - size, align);
++ } else
++ continue;
++
++ while ((lmbbase <= base) &&
++ ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0) )
++ base = _ALIGN_DOWN(lmb.reserved.region[j].base - size,
++ align);
++
++ if ((base != 0) && (lmbbase <= base))
++ break;
++ }
++
++ if (i < 0)
++ return 0;
++
++ lmb_add_region(&lmb.reserved, base, size);
++
++ return base;
++}
++
++/* You must call lmb_analyze() before this. */
++unsigned long __init lmb_phys_mem_size(void)
++{
++ return lmb.memory.size;
++}
++
++unsigned long __init lmb_end_of_DRAM(void)
++{
++ int idx = lmb.memory.cnt - 1;
++
++ return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
++}
++
++/*
++ * Truncate the lmb list to memory_limit if it's set
++ * You must call lmb_analyze() after this.
++ */
++void __init lmb_enforce_memory_limit(unsigned long memory_limit)
++{
++ unsigned long i, limit;
++
++ if (! memory_limit)
++ return;
++
++ limit = memory_limit;
++ for (i = 0; i < lmb.memory.cnt; i++) {
++ if (limit > lmb.memory.region[i].size) {
++ limit -= lmb.memory.region[i].size;
++ continue;
++ }
++
++ lmb.memory.region[i].size = limit;
++ lmb.memory.cnt = i + 1;
++ break;
++ }
++}
+diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/mem.c
+@@ -0,0 +1,564 @@
++/*
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ * PPC44x/36-bit changes by Matt Porter (mporter at mvista.com)
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/highmem.h>
++#include <linux/initrd.h>
++#include <linux/pagemap.h>
++
++#include <asm/pgalloc.h>
++#include <asm/prom.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/smp.h>
++#include <asm/machdep.h>
++#include <asm/btext.h>
++#include <asm/tlb.h>
++#include <asm/prom.h>
++#include <asm/lmb.h>
++#include <asm/sections.h>
++#ifdef CONFIG_PPC64
++#include <asm/vdso.h>
++#endif
++
++#include "mmu_decl.h"
++
++#ifndef CPU_FTR_COHERENT_ICACHE
++#define CPU_FTR_COHERENT_ICACHE 0 /* XXX for now */
++#define CPU_FTR_NOEXECUTE 0
++#endif
++
++int init_bootmem_done;
++int mem_init_done;
++unsigned long memory_limit;
++
++/*
++ * This is called by /dev/mem to know if a given address has to
++ * be mapped non-cacheable or not
++ */
++int page_is_ram(unsigned long pfn)
++{
++ unsigned long paddr = (pfn << PAGE_SHIFT);
++
++#ifndef CONFIG_PPC64 /* XXX for now */
++ return paddr < __pa(high_memory);
++#else
++ int i;
++ for (i=0; i < lmb.memory.cnt; i++) {
++ unsigned long base;
++
++ base = lmb.memory.region[i].base;
++
++ if ((paddr >= base) &&
++ (paddr < (base + lmb.memory.region[i].size))) {
++ return 1;
++ }
++ }
++
++ return 0;
++#endif
++}
++EXPORT_SYMBOL(page_is_ram);
++
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
++ unsigned long size, pgprot_t vma_prot)
++{
++ if (ppc_md.phys_mem_access_prot)
++ return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
++
++ if (!page_is_ram(pfn))
++ vma_prot = __pgprot(pgprot_val(vma_prot)
++ | _PAGE_GUARDED | _PAGE_NO_CACHE);
++ return vma_prot;
++}
++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;
++ unsigned long shared = 0, cached = 0;
++ unsigned long highmem = 0;
++ struct page *page;
++ pg_data_t *pgdat;
++ unsigned long i;
++
++ printk("Mem-info:\n");
++ 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++;
++ if (PageHighMem(page))
++ highmem++;
++ if (PageReserved(page))
++ reserved++;
++ else if (PageSwapCache(page))
++ cached++;
++ 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
++ printk("%ld pages of HIGHMEM\n", highmem);
++#endif
++ printk("%ld reserved pages\n", reserved);
++ printk("%ld pages shared\n", shared);
++ printk("%ld pages swap cached\n", cached);
++}
++
++/*
++ * Initialize the bootmem system and give it all the memory we
++ * have available. If we are using highmem, we only put the
++ * lowmem into the bootmem system.
++ */
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++void __init do_init_bootmem(void)
++{
++ unsigned long i;
++ unsigned long start, bootmap_pages;
++ unsigned long total_pages;
++ int boot_mapsize;
++
++ max_pfn = total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT;
++#ifdef CONFIG_HIGHMEM
++ total_pages = total_lowmem >> PAGE_SHIFT;
++#endif
++
++ /*
++ * Find an area to use for the bootmem bitmap. Calculate the size of
++ * bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE.
++ * Add 1 additional page in case the address isn't page-aligned.
++ */
++ bootmap_pages = bootmem_bootmap_pages(total_pages);
++
++ start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
++ BUG_ON(!start);
++
++ boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
++
++ /* Add all physical memory to the bootmem map, mark each area
++ * present.
++ */
++ for (i = 0; i < lmb.memory.cnt; i++) {
++ unsigned long base = lmb.memory.region[i].base;
++ unsigned long size = lmb_size_bytes(&lmb.memory, i);
++#ifdef CONFIG_HIGHMEM
++ if (base >= total_lowmem)
++ continue;
++ if (base + size > total_lowmem)
++ size = total_lowmem - base;
++#endif
++ free_bootmem(base, size);
++ }
++
++ /* reserve the sections we're already using */
++ for (i = 0; i < lmb.reserved.cnt; i++)
++ reserve_bootmem(lmb.reserved.region[i].base,
++ lmb_size_bytes(&lmb.reserved, i));
++
++ /* XXX need to clip this if using highmem? */
++ for (i = 0; i < lmb.memory.cnt; i++)
++ memory_present(0, lmb_start_pfn(&lmb.memory, i),
++ lmb_end_pfn(&lmb.memory, i));
++ init_bootmem_done = 1;
++}
++
++/*
++ * paging_init() sets up the page tables - in fact we've already done this.
++ */
++void __init paging_init(void)
++{
++ unsigned long zones_size[MAX_NR_ZONES];
++ unsigned long zholes_size[MAX_NR_ZONES];
++ unsigned long total_ram = lmb_phys_mem_size();
++ unsigned long top_of_ram = lmb_end_of_DRAM();
++
++#ifdef CONFIG_HIGHMEM
++ map_page(PKMAP_BASE, 0, 0); /* XXX gross */
++ pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
++ (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
++ map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
++ kmap_pte = pte_offset_kernel(pmd_offset(pgd_offset_k
++ (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
++ kmap_prot = PAGE_KERNEL;
++#endif /* CONFIG_HIGHMEM */
++
++ printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
++ top_of_ram, total_ram);
++ printk(KERN_INFO "Memory hole size: %ldMB\n",
++ (top_of_ram - total_ram) >> 20);
++ /*
++ * All pages are DMA-able so we put them all in the DMA zone.
++ */
++ memset(zones_size, 0, sizeof(zones_size));
++ memset(zholes_size, 0, sizeof(zholes_size));
++
++ zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
++ zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
++
++#ifdef CONFIG_HIGHMEM
++ zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
++ zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
++ zholes_size[ZONE_HIGHMEM] = (top_of_ram - total_ram) >> PAGE_SHIFT;
++#else
++ zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
++ zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
++#endif /* CONFIG_HIGHMEM */
++
++ free_area_init_node(0, NODE_DATA(0), zones_size,
++ __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
++}
++#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
++
++void __init mem_init(void)
++{
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++ int nid;
++#endif
++ pg_data_t *pgdat;
++ unsigned long i;
++ struct page *page;
++ unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize;
++
++ num_physpages = max_pfn; /* RAM is assumed contiguous */
++ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++ for_each_online_node(nid) {
++ if (NODE_DATA(nid)->node_spanned_pages != 0) {
++ printk("freeing bootmem node %x\n", nid);
++ totalram_pages +=
++ free_all_bootmem_node(NODE_DATA(nid));
++ }
++ }
++#else
++ max_mapnr = num_physpages;
++ totalram_pages += free_all_bootmem();
++#endif
++ for_each_pgdat(pgdat) {
++ for (i = 0; i < pgdat->node_spanned_pages; i++) {
++ page = pgdat_page_nr(pgdat, i);
++ if (PageReserved(page))
++ reservedpages++;
++ }
++ }
++
++ codesize = (unsigned long)&_sdata - (unsigned long)&_stext;
++ datasize = (unsigned long)&__init_begin - (unsigned long)&_sdata;
++ initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
++ bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start;
++
++#ifdef CONFIG_HIGHMEM
++ {
++ unsigned long pfn, highmem_mapnr;
++
++ highmem_mapnr = total_lowmem >> PAGE_SHIFT;
++ for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
++ struct page *page = pfn_to_page(pfn);
++
++ ClearPageReserved(page);
++ set_page_count(page, 1);
++ __free_page(page);
++ totalhigh_pages++;
++ }
++ totalram_pages += totalhigh_pages;
++ printk(KERN_INFO "High memory: %luk\n",
++ totalhigh_pages << (PAGE_SHIFT-10));
++ }
++#endif /* CONFIG_HIGHMEM */
++
++ printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, "
++ "%luk reserved, %luk data, %luk bss, %luk init)\n",
++ (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
++ num_physpages << (PAGE_SHIFT-10),
++ codesize >> 10,
++ reservedpages << (PAGE_SHIFT-10),
++ datasize >> 10,
++ bsssize >> 10,
++ initsize >> 10);
++
++ mem_init_done = 1;
++
++#ifdef CONFIG_PPC64
++ /* Initialize the vDSO */
++ vdso_init();
++#endif
++}
++
++/*
++ * This is called when a page has been modified by the kernel.
++ * It just marks the page as not i-cache clean. We do the i-cache
++ * flush later when the page is given to a user process, if necessary.
++ */
++void flush_dcache_page(struct page *page)
++{
++ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
++ return;
++ /* avoid an atomic op if possible */
++ if (test_bit(PG_arch_1, &page->flags))
++ clear_bit(PG_arch_1, &page->flags);
++}
++EXPORT_SYMBOL(flush_dcache_page);
++
++void flush_dcache_icache_page(struct page *page)
++{
++#ifdef CONFIG_BOOKE
++ void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE);
++ __flush_dcache_icache(start);
++ kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
++#elif defined(CONFIG_8xx) || defined(CONFIG_PPC64)
++ /* On 8xx there is no need to kmap since highmem is not supported */
++ __flush_dcache_icache(page_address(page));
++#else
++ __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
++#endif
++
++}
++void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
++{
++ clear_page(page);
++
++ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
++ return;
++ /*
++ * We shouldnt have to do this, but some versions of glibc
++ * require it (ld.so assumes zero filled pages are icache clean)
++ * - Anton
++ */
++
++ /* avoid an atomic op if possible */
++ if (test_bit(PG_arch_1, &pg->flags))
++ clear_bit(PG_arch_1, &pg->flags);
++}
++EXPORT_SYMBOL(clear_user_page);
++
++void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
++ struct page *pg)
++{
++ copy_page(vto, vfrom);
++
++ /*
++ * We should be able to use the following optimisation, however
++ * there are two problems.
++ * Firstly a bug in some versions of binutils meant PLT sections
++ * were not marked executable.
++ * Secondly the first word in the GOT section is blrl, used
++ * to establish the GOT address. Until recently the GOT was
++ * not marked executable.
++ * - Anton
++ */
++#if 0
++ if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0))
++ return;
++#endif
++
++ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
++ return;
++
++ /* avoid an atomic op if possible */
++ if (test_bit(PG_arch_1, &pg->flags))
++ clear_bit(PG_arch_1, &pg->flags);
++}
++
++void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
++ unsigned long addr, int len)
++{
++ unsigned long maddr;
++
++ maddr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
++ flush_icache_range(maddr, maddr + len);
++ kunmap(page);
++}
++EXPORT_SYMBOL(flush_icache_user_range);
++
++/*
++ * This is called at the end of handling a user page fault, when the
++ * fault has been handled by updating a PTE in the linux page tables.
++ * We use it to preload an HPTE into the hash table corresponding to
++ * the updated linux PTE.
++ *
++ * This must always be called with the mm->page_table_lock held
++ */
++void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
++ pte_t pte)
++{
++ /* handle i-cache coherency */
++ unsigned long pfn = pte_pfn(pte);
++#ifdef CONFIG_PPC32
++ pmd_t *pmd;
++#else
++ unsigned long vsid;
++ void *pgdir;
++ pte_t *ptep;
++ int local = 0;
++ cpumask_t tmp;
++ unsigned long flags;
++#endif
++
++ /* handle i-cache coherency */
++ if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
++ !cpu_has_feature(CPU_FTR_NOEXECUTE) &&
++ pfn_valid(pfn)) {
++ struct page *page = pfn_to_page(pfn);
++ if (!PageReserved(page)
++ && !test_bit(PG_arch_1, &page->flags)) {
++ if (vma->vm_mm == current->active_mm) {
++#ifdef CONFIG_8xx
++ /* On 8xx, cache control instructions (particularly
++ * "dcbst" from flush_dcache_icache) fault as write
++ * operation if there is an unpopulated TLB entry
++ * for the address in question. To workaround that,
++ * we invalidate the TLB here, thus avoiding dcbst
++ * misbehaviour.
++ */
++ _tlbie(address);
++#endif
++ __flush_dcache_icache((void *) address);
++ } else
++ flush_dcache_icache_page(page);
++ set_bit(PG_arch_1, &page->flags);
++ }
++ }
++
++#ifdef CONFIG_PPC_STD_MMU
++ /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
++ if (!pte_young(pte) || address >= TASK_SIZE)
++ return;
++#ifdef CONFIG_PPC32
++ if (Hash == 0)
++ return;
++ pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address);
++ if (!pmd_none(*pmd))
++ add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd));
++#else
++ pgdir = vma->vm_mm->pgd;
++ if (pgdir == NULL)
++ return;
++
++ ptep = find_linux_pte(pgdir, address);
++ if (!ptep)
++ return;
++
++ vsid = get_vsid(vma->vm_mm->context.id, address);
++
++ local_irq_save(flags);
++ tmp = cpumask_of_cpu(smp_processor_id());
++ if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
++ local = 1;
++
++ __hash_page(address, 0, vsid, ptep, 0x300, local);
++ local_irq_restore(flags);
++#endif
++#endif
++}
+diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/mmap.c
+@@ -0,0 +1,86 @@
++/*
++ * linux/arch/ppc64/mm/mmap.c
++ *
++ * flexible mmap layout support
++ *
++ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
++ * 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
++ *
++ *
++ * Started by Ingo Molnar <mingo at elte.hu>
++ */
++
++#include <linux/personality.h>
++#include <linux/mm.h>
++
++/*
++ * Top of mmap area (just below the process stack).
++ *
++ * Leave an at least ~128 MB hole.
++ */
++#define MIN_GAP (128*1024*1024)
++#define MAX_GAP (TASK_SIZE/6*5)
++
++static inline unsigned long mmap_base(void)
++{
++ unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
++
++ if (gap < MIN_GAP)
++ gap = MIN_GAP;
++ else if (gap > MAX_GAP)
++ gap = MAX_GAP;
++
++ return TASK_SIZE - (gap & PAGE_MASK);
++}
++
++static inline int mmap_is_legacy(void)
++{
++ /*
++ * Force standard allocation for 64 bit programs.
++ */
++ if (!test_thread_flag(TIF_32BIT))
++ return 1;
++
++ if (current->personality & ADDR_COMPAT_LAYOUT)
++ return 1;
++
++ if (current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
++ return 1;
++
++ return sysctl_legacy_va_layout;
++}
++
++/*
++ * This function, called very early during the creation of a new
++ * process VM image, sets up which VM layout function to use:
++ */
++void arch_pick_mmap_layout(struct mm_struct *mm)
++{
++ /*
++ * Fall back to the standard layout if the personality
++ * bit is set, or if the expected stack growth is unlimited:
++ */
++ if (mmap_is_legacy()) {
++ mm->mmap_base = TASK_UNMAPPED_BASE;
++ mm->get_unmapped_area = arch_get_unmapped_area;
++ mm->unmap_area = arch_unmap_area;
++ } else {
++ mm->mmap_base = mmap_base();
++ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
++ mm->unmap_area = arch_unmap_area_topdown;
++ }
++}
+diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/mmu_context_32.c
+@@ -0,0 +1,86 @@
++/*
++ * This file contains the routines for handling the MMU on those
++ * PowerPC implementations where the MMU substantially follows the
++ * architecture specification. This includes the 6xx, 7xx, 7xxx,
++ * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
++ * -- paulus
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/mm.h>
++#include <linux/init.h>
++
++#include <asm/mmu_context.h>
++#include <asm/tlbflush.h>
++
++mm_context_t next_mmu_context;
++unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
++#ifdef FEW_CONTEXTS
++atomic_t nr_free_contexts;
++struct mm_struct *context_mm[LAST_CONTEXT+1];
++void steal_context(void);
++#endif /* FEW_CONTEXTS */
++
++/*
++ * Initialize the context management stuff.
++ */
++void __init
++mmu_context_init(void)
++{
++ /*
++ * Some processors have too few contexts to reserve one for
++ * init_mm, and require using context 0 for a normal task.
++ * Other processors reserve the use of context zero for the kernel.
++ * This code assumes FIRST_CONTEXT < 32.
++ */
++ context_map[0] = (1 << FIRST_CONTEXT) - 1;
++ next_mmu_context = FIRST_CONTEXT;
++#ifdef FEW_CONTEXTS
++ atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
++#endif /* FEW_CONTEXTS */
++}
++
++#ifdef FEW_CONTEXTS
++/*
++ * Steal a context from a task that has one at the moment.
++ * This is only used on 8xx and 4xx and we presently assume that
++ * they don't do SMP. If they do then this will have to check
++ * whether the MM we steal is in use.
++ * We also assume that this is only used on systems that don't
++ * use an MMU hash table - this is true for 8xx and 4xx.
++ * This isn't an LRU system, it just frees up each context in
++ * turn (sort-of pseudo-random replacement :). This would be the
++ * place to implement an LRU scheme if anyone was motivated to do it.
++ * -- paulus
++ */
++void
++steal_context(void)
++{
++ struct mm_struct *mm;
++
++ /* free up context `next_mmu_context' */
++ /* if we shouldn't free context 0, don't... */
++ if (next_mmu_context < FIRST_CONTEXT)
++ next_mmu_context = FIRST_CONTEXT;
++ mm = context_mm[next_mmu_context];
++ flush_tlb_mm(mm);
++ destroy_context(mm);
++}
++#endif /* FEW_CONTEXTS */
+diff --git a/arch/powerpc/mm/mmu_context_64.c b/arch/powerpc/mm/mmu_context_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/mmu_context_64.c
+@@ -0,0 +1,63 @@
++/*
++ * MMU context allocation for 64-bit kernels.
++ *
++ * Copyright (C) 2004 Anton Blanchard, IBM Corp. <anton at samba.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/config.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/spinlock.h>
++#include <linux/idr.h>
++
++#include <asm/mmu_context.h>
++
++static DEFINE_SPINLOCK(mmu_context_lock);
++static DEFINE_IDR(mmu_context_idr);
++
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++ int index;
++ int err;
++
++again:
++ if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
++ return -ENOMEM;
++
++ spin_lock(&mmu_context_lock);
++ err = idr_get_new_above(&mmu_context_idr, NULL, 1, &index);
++ spin_unlock(&mmu_context_lock);
++
++ if (err == -EAGAIN)
++ goto again;
++ else if (err)
++ return err;
++
++ if (index > MAX_CONTEXT) {
++ idr_remove(&mmu_context_idr, index);
++ return -ENOMEM;
++ }
++
++ mm->context.id = index;
++
++ return 0;
++}
++
++void destroy_context(struct mm_struct *mm)
++{
++ spin_lock(&mmu_context_lock);
++ idr_remove(&mmu_context_idr, mm->context.id);
++ spin_unlock(&mmu_context_lock);
++
++ mm->context.id = NO_CONTEXT;
++}
+diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/mmu_decl.h
+@@ -0,0 +1,87 @@
++/*
++ * Declarations of procedures and variables shared between files
++ * in arch/ppc/mm/.
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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 <asm/tlbflush.h>
++#include <asm/mmu.h>
++
++#ifdef CONFIG_PPC32
++extern void mapin_ram(void);
++extern int map_page(unsigned long va, phys_addr_t pa, int flags);
++extern void setbat(int index, unsigned long virt, unsigned long phys,
++ unsigned int size, int flags);
++extern void settlbcam(int index, unsigned long virt, phys_addr_t phys,
++ unsigned int size, int flags, unsigned int pid);
++extern void invalidate_tlbcam_entry(int index);
++
++extern int __map_without_bats;
++extern unsigned long ioremap_base;
++extern unsigned long ioremap_bot;
++extern unsigned int rtas_data, rtas_size;
++
++extern PTE *Hash, *Hash_end;
++extern unsigned long Hash_size, Hash_mask;
++
++extern unsigned int num_tlbcam_entries;
++#endif
++
++extern unsigned long __max_low_memory;
++extern unsigned long __initial_memory_limit;
++extern unsigned long total_memory;
++extern unsigned long total_lowmem;
++
++/* ...and now those things that may be slightly different between processor
++ * architectures. -- Dan
++ */
++#if defined(CONFIG_8xx)
++#define flush_HPTE(X, va, pg) _tlbie(va)
++#define MMU_init_hw() do { } while(0)
++#define mmu_mapin_ram() (0UL)
++
++#elif defined(CONFIG_4xx)
++#define flush_HPTE(X, va, pg) _tlbie(va)
++extern void MMU_init_hw(void);
++extern unsigned long mmu_mapin_ram(void);
++
++#elif defined(CONFIG_FSL_BOOKE)
++#define flush_HPTE(X, va, pg) _tlbie(va)
++extern void MMU_init_hw(void);
++extern unsigned long mmu_mapin_ram(void);
++extern void adjust_total_lowmem(void);
++
++#elif defined(CONFIG_PPC32)
++/* anything 32-bit except 4xx or 8xx */
++extern void MMU_init_hw(void);
++extern unsigned long mmu_mapin_ram(void);
++
++/* Be careful....this needs to be updated if we ever encounter 603 SMPs,
++ * which includes all new 82xx processors. We need tlbie/tlbsync here
++ * in that case (I think). -- Dan.
++ */
++static inline void flush_HPTE(unsigned context, unsigned long va,
++ unsigned long pdval)
++{
++ if ((Hash != 0) &&
++ cpu_has_feature(CPU_FTR_HPTE_TABLE))
++ flush_hash_pages(0, va, pdval, 1);
++ else
++ _tlbie(va);
++}
++#endif
+diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/numa.c
+@@ -0,0 +1,779 @@
++/*
++ * pSeries NUMA support
++ *
++ * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * 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/threads.h>
++#include <linux/bootmem.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/mmzone.h>
++#include <linux/module.h>
++#include <linux/nodemask.h>
++#include <linux/cpu.h>
++#include <linux/notifier.h>
++#include <asm/lmb.h>
++#include <asm/machdep.h>
++#include <asm/abs_addr.h>
++#include <asm/system.h>
++
++static int numa_enabled = 1;
++
++static int numa_debug;
++#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
++
++#ifdef DEBUG_NUMA
++#define ARRAY_INITIALISER -1
++#else
++#define ARRAY_INITIALISER 0
++#endif
++
++int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] =
++ ARRAY_INITIALISER};
++char *numa_memory_lookup_table;
++cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
++int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0};
++
++struct pglist_data *node_data[MAX_NUMNODES];
++bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
++static int min_common_depth;
++
++/*
++ * We need somewhere to store start/span for each node until we have
++ * allocated the real node_data structures.
++ */
++static struct {
++ unsigned long node_start_pfn;
++ unsigned long node_end_pfn;
++ unsigned long node_present_pages;
++} init_node_data[MAX_NUMNODES] __initdata;
++
++EXPORT_SYMBOL(node_data);
++EXPORT_SYMBOL(numa_cpu_lookup_table);
++EXPORT_SYMBOL(numa_memory_lookup_table);
++EXPORT_SYMBOL(numa_cpumask_lookup_table);
++EXPORT_SYMBOL(nr_cpus_in_node);
++
++static inline void map_cpu_to_node(int cpu, int node)
++{
++ numa_cpu_lookup_table[cpu] = node;
++ if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) {
++ cpu_set(cpu, numa_cpumask_lookup_table[node]);
++ nr_cpus_in_node[node]++;
++ }
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static void unmap_cpu_from_node(unsigned long cpu)
++{
++ int node = numa_cpu_lookup_table[cpu];
++
++ dbg("removing cpu %lu from node %d\n", cpu, node);
++
++ if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
++ cpu_clear(cpu, numa_cpumask_lookup_table[node]);
++ nr_cpus_in_node[node]--;
++ } else {
++ printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n",
++ cpu, node);
++ }
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++static struct device_node * __devinit find_cpu_node(unsigned int cpu)
++{
++ unsigned int hw_cpuid = get_hard_smp_processor_id(cpu);
++ struct device_node *cpu_node = NULL;
++ unsigned int *interrupt_server, *reg;
++ int len;
++
++ while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) {
++ /* Try interrupt server first */
++ interrupt_server = (unsigned int *)get_property(cpu_node,
++ "ibm,ppc-interrupt-server#s", &len);
++
++ len = len / sizeof(u32);
++
++ if (interrupt_server && (len > 0)) {
++ while (len--) {
++ if (interrupt_server[len] == hw_cpuid)
++ return cpu_node;
++ }
++ } else {
++ reg = (unsigned int *)get_property(cpu_node,
++ "reg", &len);
++ if (reg && (len > 0) && (reg[0] == hw_cpuid))
++ return cpu_node;
++ }
++ }
++
++ return NULL;
++}
++
++/* must hold reference to node during call */
++static int *of_get_associativity(struct device_node *dev)
++{
++ return (unsigned int *)get_property(dev, "ibm,associativity", NULL);
++}
++
++static int of_node_numa_domain(struct device_node *device)
++{
++ int numa_domain;
++ unsigned int *tmp;
++
++ if (min_common_depth == -1)
++ return 0;
++
++ tmp = of_get_associativity(device);
++ if (tmp && (tmp[0] >= min_common_depth)) {
++ numa_domain = tmp[min_common_depth];
++ } else {
++ dbg("WARNING: no NUMA information for %s\n",
++ device->full_name);
++ numa_domain = 0;
++ }
++ return numa_domain;
++}
++
++/*
++ * In theory, the "ibm,associativity" property may contain multiple
++ * associativity lists because a resource may be multiply connected
++ * into the machine. This resource then has different associativity
++ * characteristics relative to its multiple connections. We ignore
++ * this for now. We also assume that all cpu and memory sets have
++ * their distances represented at a common level. This won't be
++ * true for heirarchical NUMA.
++ *
++ * In any case the ibm,associativity-reference-points should give
++ * the correct depth for a normal NUMA system.
++ *
++ * - Dave Hansen <haveblue at us.ibm.com>
++ */
++static int __init find_min_common_depth(void)
++{
++ int depth;
++ unsigned int *ref_points;
++ struct device_node *rtas_root;
++ unsigned int len;
++
++ rtas_root = of_find_node_by_path("/rtas");
++
++ if (!rtas_root)
++ return -1;
++
++ /*
++ * this property is 2 32-bit integers, each representing a level of
++ * depth in the associativity nodes. The first is for an SMP
++ * configuration (should be all 0's) and the second is for a normal
++ * NUMA configuration.
++ */
++ ref_points = (unsigned int *)get_property(rtas_root,
++ "ibm,associativity-reference-points", &len);
++
++ if ((len >= 1) && ref_points) {
++ depth = ref_points[1];
++ } else {
++ dbg("WARNING: could not find NUMA "
++ "associativity reference point\n");
++ depth = -1;
++ }
++ of_node_put(rtas_root);
++
++ return depth;
++}
++
++static int __init get_mem_addr_cells(void)
++{
++ struct device_node *memory = NULL;
++ int rc;
++
++ memory = of_find_node_by_type(memory, "memory");
++ if (!memory)
++ return 0; /* it won't matter */
++
++ rc = prom_n_addr_cells(memory);
++ return rc;
++}
++
++static int __init get_mem_size_cells(void)
++{
++ struct device_node *memory = NULL;
++ int rc;
++
++ memory = of_find_node_by_type(memory, "memory");
++ if (!memory)
++ return 0; /* it won't matter */
++ rc = prom_n_size_cells(memory);
++ return rc;
++}
++
++static unsigned long read_n_cells(int n, unsigned int **buf)
++{
++ unsigned long result = 0;
++
++ while (n--) {
++ result = (result << 32) | **buf;
++ (*buf)++;
++ }
++ return result;
++}
++
++/*
++ * Figure out to which domain a cpu belongs and stick it there.
++ * Return the id of the domain used.
++ */
++static int numa_setup_cpu(unsigned long lcpu)
++{
++ int numa_domain = 0;
++ struct device_node *cpu = find_cpu_node(lcpu);
++
++ if (!cpu) {
++ WARN_ON(1);
++ goto out;
++ }
++
++ numa_domain = of_node_numa_domain(cpu);
++
++ if (numa_domain >= num_online_nodes()) {
++ /*
++ * POWER4 LPAR uses 0xffff as invalid node,
++ * dont warn in this case.
++ */
++ if (numa_domain != 0xffff)
++ printk(KERN_ERR "WARNING: cpu %ld "
++ "maps to invalid NUMA node %d\n",
++ lcpu, numa_domain);
++ numa_domain = 0;
++ }
++out:
++ node_set_online(numa_domain);
++
++ map_cpu_to_node(lcpu, numa_domain);
++
++ of_node_put(cpu);
++
++ return numa_domain;
++}
++
++static int cpu_numa_callback(struct notifier_block *nfb,
++ unsigned long action,
++ void *hcpu)
++{
++ unsigned long lcpu = (unsigned long)hcpu;
++ int ret = NOTIFY_DONE;
++
++ switch (action) {
++ case CPU_UP_PREPARE:
++ if (min_common_depth == -1 || !numa_enabled)
++ map_cpu_to_node(lcpu, 0);
++ else
++ numa_setup_cpu(lcpu);
++ ret = NOTIFY_OK;
++ break;
++#ifdef CONFIG_HOTPLUG_CPU
++ case CPU_DEAD:
++ case CPU_UP_CANCELED:
++ unmap_cpu_from_node(lcpu);
++ break;
++ ret = NOTIFY_OK;
++#endif
++ }
++ return ret;
++}
++
++/*
++ * Check and possibly modify a memory region to enforce the memory limit.
++ *
++ * Returns the size the region should have to enforce the memory limit.
++ * This will either be the original value of size, a truncated value,
++ * or zero. If the returned value of size is 0 the region should be
++ * discarded as it lies wholy above the memory limit.
++ */
++static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size)
++{
++ /*
++ * We use lmb_end_of_DRAM() in here instead of memory_limit because
++ * we've already adjusted it for the limit and it takes care of
++ * having memory holes below the limit.
++ */
++
++ if (! memory_limit)
++ return size;
++
++ if (start + size <= lmb_end_of_DRAM())
++ return size;
++
++ if (start >= lmb_end_of_DRAM())
++ return 0;
++
++ return lmb_end_of_DRAM() - start;
++}
++
++static int __init parse_numa_properties(void)
++{
++ struct device_node *cpu = NULL;
++ struct device_node *memory = NULL;
++ int addr_cells, size_cells;
++ int max_domain = 0;
++ long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT;
++ unsigned long i;
++
++ if (numa_enabled == 0) {
++ printk(KERN_WARNING "NUMA disabled by user\n");
++ return -1;
++ }
++
++ numa_memory_lookup_table =
++ (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
++ memset(numa_memory_lookup_table, 0, entries * sizeof(char));
++
++ for (i = 0; i < entries ; i++)
++ numa_memory_lookup_table[i] = ARRAY_INITIALISER;
++
++ min_common_depth = find_min_common_depth();
++
++ dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth);
++ if (min_common_depth < 0)
++ return min_common_depth;
++
++ max_domain = numa_setup_cpu(boot_cpuid);
++
++ /*
++ * Even though we connect cpus to numa domains later in SMP init,
++ * we need to know the maximum node id now. This is because each
++ * node id must have NODE_DATA etc backing it.
++ * As a result of hotplug we could still have cpus appear later on
++ * with larger node ids. In that case we force the cpu into node 0.
++ */
++ for_each_cpu(i) {
++ int numa_domain;
++
++ cpu = find_cpu_node(i);
++
++ if (cpu) {
++ numa_domain = of_node_numa_domain(cpu);
++ of_node_put(cpu);
++
++ if (numa_domain < MAX_NUMNODES &&
++ max_domain < numa_domain)
++ max_domain = numa_domain;
++ }
++ }
++
++ addr_cells = get_mem_addr_cells();
++ size_cells = get_mem_size_cells();
++ memory = NULL;
++ while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
++ unsigned long start;
++ unsigned long size;
++ int numa_domain;
++ int ranges;
++ unsigned int *memcell_buf;
++ unsigned int len;
++
++ memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
++ if (!memcell_buf || len <= 0)
++ continue;
++
++ ranges = memory->n_addrs;
++new_range:
++ /* these are order-sensitive, and modify the buffer pointer */
++ start = read_n_cells(addr_cells, &memcell_buf);
++ size = read_n_cells(size_cells, &memcell_buf);
++
++ start = _ALIGN_DOWN(start, MEMORY_INCREMENT);
++ size = _ALIGN_UP(size, MEMORY_INCREMENT);
++
++ numa_domain = of_node_numa_domain(memory);
++
++ if (numa_domain >= MAX_NUMNODES) {
++ if (numa_domain != 0xffff)
++ printk(KERN_ERR "WARNING: memory at %lx maps "
++ "to invalid NUMA node %d\n", start,
++ numa_domain);
++ numa_domain = 0;
++ }
++
++ if (max_domain < numa_domain)
++ max_domain = numa_domain;
++
++ if (! (size = numa_enforce_memory_limit(start, size))) {
++ if (--ranges)
++ goto new_range;
++ else
++ continue;
++ }
++
++ /*
++ * Initialize new node struct, or add to an existing one.
++ */
++ if (init_node_data[numa_domain].node_end_pfn) {
++ if ((start / PAGE_SIZE) <
++ init_node_data[numa_domain].node_start_pfn)
++ init_node_data[numa_domain].node_start_pfn =
++ start / PAGE_SIZE;
++ if (((start / PAGE_SIZE) + (size / PAGE_SIZE)) >
++ init_node_data[numa_domain].node_end_pfn)
++ init_node_data[numa_domain].node_end_pfn =
++ (start / PAGE_SIZE) +
++ (size / PAGE_SIZE);
++
++ init_node_data[numa_domain].node_present_pages +=
++ size / PAGE_SIZE;
++ } else {
++ node_set_online(numa_domain);
++
++ init_node_data[numa_domain].node_start_pfn =
++ start / PAGE_SIZE;
++ init_node_data[numa_domain].node_end_pfn =
++ init_node_data[numa_domain].node_start_pfn +
++ size / PAGE_SIZE;
++ init_node_data[numa_domain].node_present_pages =
++ size / PAGE_SIZE;
++ }
++
++ for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
++ numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
++ numa_domain;
++
++ if (--ranges)
++ goto new_range;
++ }
++
++ for (i = 0; i <= max_domain; i++)
++ node_set_online(i);
++
++ return 0;
++}
++
++static void __init setup_nonnuma(void)
++{
++ unsigned long top_of_ram = lmb_end_of_DRAM();
++ unsigned long total_ram = lmb_phys_mem_size();
++ unsigned long i;
++
++ printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
++ top_of_ram, total_ram);
++ printk(KERN_INFO "Memory hole size: %ldMB\n",
++ (top_of_ram - total_ram) >> 20);
++
++ if (!numa_memory_lookup_table) {
++ long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT;
++ numa_memory_lookup_table =
++ (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
++ memset(numa_memory_lookup_table, 0, entries * sizeof(char));
++ for (i = 0; i < entries ; i++)
++ numa_memory_lookup_table[i] = ARRAY_INITIALISER;
++ }
++
++ map_cpu_to_node(boot_cpuid, 0);
++
++ node_set_online(0);
++
++ init_node_data[0].node_start_pfn = 0;
++ init_node_data[0].node_end_pfn = lmb_end_of_DRAM() / PAGE_SIZE;
++ init_node_data[0].node_present_pages = total_ram / PAGE_SIZE;
++
++ for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
++ numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
++}
++
++static void __init dump_numa_topology(void)
++{
++ unsigned int node;
++ unsigned int count;
++
++ if (min_common_depth == -1 || !numa_enabled)
++ return;
++
++ for_each_online_node(node) {
++ unsigned long i;
++
++ printk(KERN_INFO "Node %d Memory:", node);
++
++ count = 0;
++
++ for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) {
++ if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) {
++ if (count == 0)
++ printk(" 0x%lx", i);
++ ++count;
++ } else {
++ if (count > 0)
++ printk("-0x%lx", i);
++ count = 0;
++ }
++ }
++
++ if (count > 0)
++ printk("-0x%lx", i);
++ printk("\n");
++ }
++ return;
++}
++
++/*
++ * Allocate some memory, satisfying the lmb or bootmem allocator where
++ * required. nid is the preferred node and end is the physical address of
++ * the highest address in the node.
++ *
++ * Returns the physical address of the memory.
++ */
++static unsigned long careful_allocation(int nid, unsigned long size,
++ unsigned long align, unsigned long end)
++{
++ unsigned long ret = lmb_alloc_base(size, align, end);
++
++ /* retry over all memory */
++ if (!ret)
++ ret = lmb_alloc_base(size, align, lmb_end_of_DRAM());
++
++ if (!ret)
++ panic("numa.c: cannot allocate %lu bytes on node %d",
++ size, nid);
++
++ /*
++ * If the memory came from a previously allocated node, we must
++ * retry with the bootmem allocator.
++ */
++ if (pa_to_nid(ret) < nid) {
++ nid = pa_to_nid(ret);
++ ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid),
++ size, align, 0);
++
++ if (!ret)
++ panic("numa.c: cannot allocate %lu bytes on node %d",
++ size, nid);
++
++ ret = virt_to_abs(ret);
++
++ dbg("alloc_bootmem %lx %lx\n", ret, size);
++ }
++
++ return ret;
++}
++
++void __init do_init_bootmem(void)
++{
++ int nid;
++ int addr_cells, size_cells;
++ struct device_node *memory = NULL;
++ static struct notifier_block ppc64_numa_nb = {
++ .notifier_call = cpu_numa_callback,
++ .priority = 1 /* Must run before sched domains notifier. */
++ };
++
++ min_low_pfn = 0;
++ max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
++ max_pfn = max_low_pfn;
++
++ if (parse_numa_properties())
++ setup_nonnuma();
++ else
++ dump_numa_topology();
++
++ register_cpu_notifier(&ppc64_numa_nb);
++
++ for_each_online_node(nid) {
++ unsigned long start_paddr, end_paddr;
++ int i;
++ unsigned long bootmem_paddr;
++ unsigned long bootmap_pages;
++
++ start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE;
++ end_paddr = init_node_data[nid].node_end_pfn * PAGE_SIZE;
++
++ /* Allocate the node structure node local if possible */
++ NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid,
++ sizeof(struct pglist_data),
++ SMP_CACHE_BYTES, end_paddr);
++ NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid));
++ memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
++
++ dbg("node %d\n", nid);
++ dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
++
++ NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
++ NODE_DATA(nid)->node_start_pfn =
++ init_node_data[nid].node_start_pfn;
++ NODE_DATA(nid)->node_spanned_pages =
++ end_paddr - start_paddr;
++
++ if (NODE_DATA(nid)->node_spanned_pages == 0)
++ continue;
++
++ dbg("start_paddr = %lx\n", start_paddr);
++ dbg("end_paddr = %lx\n", end_paddr);
++
++ bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT);
++
++ bootmem_paddr = careful_allocation(nid,
++ bootmap_pages << PAGE_SHIFT,
++ PAGE_SIZE, end_paddr);
++ memset(abs_to_virt(bootmem_paddr), 0,
++ bootmap_pages << PAGE_SHIFT);
++ dbg("bootmap_paddr = %lx\n", bootmem_paddr);
++
++ init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
++ start_paddr >> PAGE_SHIFT,
++ end_paddr >> PAGE_SHIFT);
++
++ /*
++ * We need to do another scan of all memory sections to
++ * associate memory with the correct node.
++ */
++ addr_cells = get_mem_addr_cells();
++ size_cells = get_mem_size_cells();
++ memory = NULL;
++ while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
++ unsigned long mem_start, mem_size;
++ int numa_domain, ranges;
++ unsigned int *memcell_buf;
++ unsigned int len;
++
++ memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
++ if (!memcell_buf || len <= 0)
++ continue;
++
++ ranges = memory->n_addrs; /* ranges in cell */
++new_range:
++ mem_start = read_n_cells(addr_cells, &memcell_buf);
++ mem_size = read_n_cells(size_cells, &memcell_buf);
++ if (numa_enabled) {
++ numa_domain = of_node_numa_domain(memory);
++ if (numa_domain >= MAX_NUMNODES)
++ numa_domain = 0;
++ } else
++ numa_domain = 0;
++
++ if (numa_domain != nid)
++ continue;
++
++ mem_size = numa_enforce_memory_limit(mem_start, mem_size);
++ if (mem_size) {
++ dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
++ free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
++ }
++
++ if (--ranges) /* process all ranges in cell */
++ goto new_range;
++ }
++
++ /*
++ * Mark reserved regions on this node
++ */
++ for (i = 0; i < lmb.reserved.cnt; i++) {
++ unsigned long physbase = lmb.reserved.region[i].base;
++ unsigned long size = lmb.reserved.region[i].size;
++
++ if (pa_to_nid(physbase) != nid &&
++ pa_to_nid(physbase+size-1) != nid)
++ continue;
++
++ if (physbase < end_paddr &&
++ (physbase+size) > start_paddr) {
++ /* overlaps */
++ if (physbase < start_paddr) {
++ size -= start_paddr - physbase;
++ physbase = start_paddr;
++ }
++
++ if (size > end_paddr - physbase)
++ size = end_paddr - physbase;
++
++ dbg("reserve_bootmem %lx %lx\n", physbase,
++ size);
++ reserve_bootmem_node(NODE_DATA(nid), physbase,
++ size);
++ }
++ }
++ /*
++ * This loop may look famaliar, but we have to do it again
++ * after marking our reserved memory to mark memory present
++ * for sparsemem.
++ */
++ addr_cells = get_mem_addr_cells();
++ size_cells = get_mem_size_cells();
++ memory = NULL;
++ while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
++ unsigned long mem_start, mem_size;
++ int numa_domain, ranges;
++ unsigned int *memcell_buf;
++ unsigned int len;
++
++ memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
++ if (!memcell_buf || len <= 0)
++ continue;
++
++ ranges = memory->n_addrs; /* ranges in cell */
++new_range2:
++ mem_start = read_n_cells(addr_cells, &memcell_buf);
++ mem_size = read_n_cells(size_cells, &memcell_buf);
++ if (numa_enabled) {
++ numa_domain = of_node_numa_domain(memory);
++ if (numa_domain >= MAX_NUMNODES)
++ numa_domain = 0;
++ } else
++ numa_domain = 0;
++
++ if (numa_domain != nid)
++ continue;
++
++ mem_size = numa_enforce_memory_limit(mem_start, mem_size);
++ memory_present(numa_domain, mem_start >> PAGE_SHIFT,
++ (mem_start + mem_size) >> PAGE_SHIFT);
++
++ if (--ranges) /* process all ranges in cell */
++ goto new_range2;
++ }
++
++ }
++}
++
++void __init paging_init(void)
++{
++ unsigned long zones_size[MAX_NR_ZONES];
++ unsigned long zholes_size[MAX_NR_ZONES];
++ int nid;
++
++ memset(zones_size, 0, sizeof(zones_size));
++ memset(zholes_size, 0, sizeof(zholes_size));
++
++ for_each_online_node(nid) {
++ unsigned long start_pfn;
++ unsigned long end_pfn;
++
++ start_pfn = init_node_data[nid].node_start_pfn;
++ end_pfn = init_node_data[nid].node_end_pfn;
++
++ zones_size[ZONE_DMA] = end_pfn - start_pfn;
++ zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] -
++ init_node_data[nid].node_present_pages;
++
++ dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
++ zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
++
++ free_area_init_node(nid, NODE_DATA(nid), zones_size,
++ start_pfn, zholes_size);
++ }
++}
++
++static int __init early_numa(char *p)
++{
++ if (!p)
++ return 0;
++
++ if (strstr(p, "off"))
++ numa_enabled = 0;
++
++ if (strstr(p, "debug"))
++ numa_debug = 1;
++
++ return 0;
++}
++early_param("numa", early_numa);
+diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/pgtable_32.c
+@@ -0,0 +1,467 @@
++/*
++ * This file contains the routines setting up the linux page tables.
++ * -- paulus
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/module.h>
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
++#include <linux/init.h>
++#include <linux/highmem.h>
++
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++#include <asm/io.h>
++
++#include "mmu_decl.h"
++
++unsigned long ioremap_base;
++unsigned long ioremap_bot;
++int io_bat_index;
++
++#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
++#define HAVE_BATS 1
++#endif
++
++#if defined(CONFIG_FSL_BOOKE)
++#define HAVE_TLBCAM 1
++#endif
++
++extern char etext[], _stext[];
++
++#ifdef CONFIG_SMP
++extern void hash_page_sync(void);
++#endif
++
++#ifdef HAVE_BATS
++extern unsigned long v_mapped_by_bats(unsigned long va);
++extern unsigned long p_mapped_by_bats(unsigned long pa);
++void setbat(int index, unsigned long virt, unsigned long phys,
++ unsigned int size, int flags);
++
++#else /* !HAVE_BATS */
++#define v_mapped_by_bats(x) (0UL)
++#define p_mapped_by_bats(x) (0UL)
++#endif /* HAVE_BATS */
++
++#ifdef HAVE_TLBCAM
++extern unsigned int tlbcam_index;
++extern unsigned long v_mapped_by_tlbcam(unsigned long va);
++extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
++#else /* !HAVE_TLBCAM */
++#define v_mapped_by_tlbcam(x) (0UL)
++#define p_mapped_by_tlbcam(x) (0UL)
++#endif /* HAVE_TLBCAM */
++
++#ifdef CONFIG_PTE_64BIT
++/* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
++#define PGDIR_ORDER 1
++#else
++#define PGDIR_ORDER 0
++#endif
++
++pgd_t *pgd_alloc(struct mm_struct *mm)
++{
++ pgd_t *ret;
++
++ ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, PGDIR_ORDER);
++ return ret;
++}
++
++void pgd_free(pgd_t *pgd)
++{
++ free_pages((unsigned long)pgd, PGDIR_ORDER);
++}
++
++pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
++{
++ pte_t *pte;
++ extern int mem_init_done;
++ extern void *early_get_page(void);
++
++ if (mem_init_done) {
++ pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
++ } else {
++ pte = (pte_t *)early_get_page();
++ if (pte)
++ clear_page(pte);
++ }
++ return pte;
++}
++
++struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++ struct page *ptepage;
++
++#ifdef CONFIG_HIGHPTE
++ gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
++#else
++ gfp_t flags = GFP_KERNEL | __GFP_REPEAT;
++#endif
++
++ ptepage = alloc_pages(flags, 0);
++ if (ptepage)
++ clear_highpage(ptepage);
++ return ptepage;
++}
++
++void pte_free_kernel(pte_t *pte)
++{
++#ifdef CONFIG_SMP
++ hash_page_sync();
++#endif
++ free_page((unsigned long)pte);
++}
++
++void pte_free(struct page *ptepage)
++{
++#ifdef CONFIG_SMP
++ hash_page_sync();
++#endif
++ __free_page(ptepage);
++}
++
++#ifndef CONFIG_PHYS_64BIT
++void __iomem *
++ioremap(phys_addr_t addr, unsigned long size)
++{
++ return __ioremap(addr, size, _PAGE_NO_CACHE);
++}
++#else /* CONFIG_PHYS_64BIT */
++void __iomem *
++ioremap64(unsigned long long addr, unsigned long size)
++{
++ return __ioremap(addr, size, _PAGE_NO_CACHE);
++}
++
++void __iomem *
++ioremap(phys_addr_t addr, unsigned long size)
++{
++ phys_addr_t addr64 = fixup_bigphys_addr(addr, size);
++
++ return ioremap64(addr64, size);
++}
++#endif /* CONFIG_PHYS_64BIT */
++
++void __iomem *
++__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
++{
++ unsigned long v, i;
++ phys_addr_t p;
++ int err;
++
++ /*
++ * Choose an address to map it to.
++ * Once the vmalloc system is running, we use it.
++ * Before then, we use space going down from ioremap_base
++ * (ioremap_bot records where we're up to).
++ */
++ p = addr & PAGE_MASK;
++ size = PAGE_ALIGN(addr + size) - p;
++
++ /*
++ * If the address lies within the first 16 MB, assume it's in ISA
++ * memory space
++ */
++ if (p < 16*1024*1024)
++ p += _ISA_MEM_BASE;
++
++ /*
++ * Don't allow anybody to remap normal RAM that we're using.
++ * mem_init() sets high_memory so only do the check after that.
++ */
++ if (mem_init_done && (p < virt_to_phys(high_memory))) {
++ printk("__ioremap(): phys addr "PHYS_FMT" is RAM lr %p\n", p,
++ __builtin_return_address(0));
++ return NULL;
++ }
++
++ if (size == 0)
++ return NULL;
++
++ /*
++ * Is it already mapped? Perhaps overlapped by a previous
++ * BAT mapping. If the whole area is mapped then we're done,
++ * otherwise remap it since we want to keep the virt addrs for
++ * each request contiguous.
++ *
++ * We make the assumption here that if the bottom and top
++ * of the range we want are mapped then it's mapped to the
++ * same virt address (and this is contiguous).
++ * -- Cort
++ */
++ if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
++ goto out;
++
++ if ((v = p_mapped_by_tlbcam(p)))
++ goto out;
++
++ if (mem_init_done) {
++ struct vm_struct *area;
++ area = get_vm_area(size, VM_IOREMAP);
++ if (area == 0)
++ return NULL;
++ v = (unsigned long) area->addr;
++ } else {
++ v = (ioremap_bot -= size);
++ }
++
++ if ((flags & _PAGE_PRESENT) == 0)
++ flags |= _PAGE_KERNEL;
++ if (flags & _PAGE_NO_CACHE)
++ flags |= _PAGE_GUARDED;
++
++ /*
++ * Should check if it is a candidate for a BAT mapping
++ */
++
++ err = 0;
++ for (i = 0; i < size && err == 0; i += PAGE_SIZE)
++ err = map_page(v+i, p+i, flags);
++ if (err) {
++ if (mem_init_done)
++ vunmap((void *)v);
++ return NULL;
++ }
++
++out:
++ return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK));
++}
++
++void iounmap(volatile void __iomem *addr)
++{
++ /*
++ * If mapped by BATs then there is nothing to do.
++ * Calling vfree() generates a benign warning.
++ */
++ if (v_mapped_by_bats((unsigned long)addr)) return;
++
++ if (addr > high_memory && (unsigned long) addr < ioremap_bot)
++ vunmap((void *) (PAGE_MASK & (unsigned long)addr));
++}
++
++void __iomem *ioport_map(unsigned long port, unsigned int len)
++{
++ return (void __iomem *) (port + _IO_BASE);
++}
++
++void ioport_unmap(void __iomem *addr)
++{
++ /* Nothing to do */
++}
++EXPORT_SYMBOL(ioport_map);
++EXPORT_SYMBOL(ioport_unmap);
++
++int
++map_page(unsigned long va, phys_addr_t pa, int flags)
++{
++ pmd_t *pd;
++ pte_t *pg;
++ int err = -ENOMEM;
++
++ /* 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(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));
++ }
++ return err;
++}
++
++/*
++ * Map in all of physical memory starting at KERNELBASE.
++ */
++void __init mapin_ram(void)
++{
++ unsigned long v, p, s, f;
++
++ s = mmu_mapin_ram();
++ v = KERNELBASE + s;
++ p = PPC_MEMSTART + s;
++ for (; s < total_lowmem; s += PAGE_SIZE) {
++ if ((char *) v >= _stext && (char *) v < etext)
++ f = _PAGE_RAM_TEXT;
++ else
++ f = _PAGE_RAM;
++ map_page(v, p, f);
++ v += PAGE_SIZE;
++ p += PAGE_SIZE;
++ }
++}
++
++/* is x a power of 2? */
++#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
++
++/* is x a power of 4? */
++#define is_power_of_4(x) ((x) != 0 && (((x) & (x-1)) == 0) && (ffs(x) & 1))
++
++/*
++ * Set up a mapping for a block of I/O.
++ * virt, phys, size must all be page-aligned.
++ * This should only be called before ioremap is called.
++ */
++void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
++ unsigned int size, int flags)
++{
++ int i;
++
++ if (virt > KERNELBASE && virt < ioremap_bot)
++ ioremap_bot = ioremap_base = virt;
++
++#ifdef HAVE_BATS
++ /*
++ * Use a BAT for this if possible...
++ */
++ if (io_bat_index < 2 && is_power_of_2(size)
++ && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
++ setbat(io_bat_index, virt, phys, size, flags);
++ ++io_bat_index;
++ return;
++ }
++#endif /* HAVE_BATS */
++
++#ifdef HAVE_TLBCAM
++ /*
++ * Use a CAM for this if possible...
++ */
++ if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
++ && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
++ settlbcam(tlbcam_index, virt, phys, size, flags, 0);
++ ++tlbcam_index;
++ return;
++ }
++#endif /* HAVE_TLBCAM */
++
++ /* No BATs available, put it in the page tables. */
++ for (i = 0; i < size; i += PAGE_SIZE)
++ map_page(virt + i, phys + i, flags);
++}
++
++/* Scan the real Linux page tables and return a PTE pointer for
++ * a virtual address in a context.
++ * Returns true (1) if PTE was found, zero otherwise. The pointer to
++ * the PTE pointer is unmodified if PTE is not found.
++ */
++int
++get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
++{
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *pte;
++ int retval = 0;
++
++ pgd = pgd_offset(mm, addr & PAGE_MASK);
++ if (pgd) {
++ pmd = pmd_offset(pgd, addr & PAGE_MASK);
++ if (pmd_present(*pmd)) {
++ pte = pte_offset_map(pmd, addr & PAGE_MASK);
++ if (pte) {
++ retval = 1;
++ *ptep = pte;
++ /* XXX caller needs to do pte_unmap, yuck */
++ }
++ }
++ }
++ return(retval);
++}
++
++/* Find physical address for this virtual address. Normally used by
++ * I/O functions, but anyone can call it.
++ */
++unsigned long iopa(unsigned long addr)
++{
++ unsigned long pa;
++
++ /* I don't know why this won't work on PMacs or CHRP. It
++ * appears there is some bug, or there is some implicit
++ * mapping done not properly represented by BATs or in page
++ * tables.......I am actively working on resolving this, but
++ * can't hold up other stuff. -- Dan
++ */
++ pte_t *pte;
++ struct mm_struct *mm;
++
++ /* Check the BATs */
++ pa = v_mapped_by_bats(addr);
++ if (pa)
++ return pa;
++
++ /* Allow mapping of user addresses (within the thread)
++ * for DMA if necessary.
++ */
++ if (addr < TASK_SIZE)
++ mm = current->mm;
++ else
++ mm = &init_mm;
++
++ pa = 0;
++ if (get_pteptr(mm, addr, &pte)) {
++ pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
++ pte_unmap(pte);
++ }
++
++ return(pa);
++}
++
++/* This is will find the virtual address for a physical one....
++ * Swiped from APUS, could be dangerous :-).
++ * This is only a placeholder until I really find a way to make this
++ * work. -- Dan
++ */
++unsigned long
++mm_ptov (unsigned long paddr)
++{
++ unsigned long ret;
++#if 0
++ if (paddr < 16*1024*1024)
++ ret = ZTWO_VADDR(paddr);
++ else {
++ int i;
++
++ for (i = 0; i < kmap_chunk_count;){
++ unsigned long phys = kmap_chunks[i++];
++ unsigned long size = kmap_chunks[i++];
++ unsigned long virt = kmap_chunks[i++];
++ if (paddr >= phys
++ && paddr < (phys + size)){
++ ret = virt + paddr - phys;
++ goto exit;
++ }
++ }
++
++ ret = (unsigned long) __va(paddr);
++ }
++exit:
++#ifdef DEBUGPV
++ printk ("PTOV(%lx)=%lx\n", paddr, ret);
++#endif
++#else
++ ret = (unsigned long)paddr + KERNELBASE;
++#endif
++ return ret;
++}
++
+diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/pgtable_64.c
+@@ -0,0 +1,347 @@
++/*
++ * This file contains ioremap and related functions for 64-bit machines.
++ *
++ * Derived from arch/ppc64/mm/init.c
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at samba.org)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * Dave Engebretsen <engebret at us.ibm.com>
++ * Rework for PPC64 port.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/stddef.h>
++#include <linux/vmalloc.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/highmem.h>
++#include <linux/idr.h>
++#include <linux/nodemask.h>
++#include <linux/module.h>
++
++#include <asm/pgalloc.h>
++#include <asm/page.h>
++#include <asm/prom.h>
++#include <asm/lmb.h>
++#include <asm/rtas.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/uaccess.h>
++#include <asm/smp.h>
++#include <asm/machdep.h>
++#include <asm/tlb.h>
++#include <asm/eeh.h>
++#include <asm/processor.h>
++#include <asm/mmzone.h>
++#include <asm/cputable.h>
++#include <asm/ppcdebug.h>
++#include <asm/sections.h>
++#include <asm/system.h>
++#include <asm/iommu.h>
++#include <asm/abs_addr.h>
++#include <asm/vdso.h>
++#include <asm/imalloc.h>
++
++unsigned long ioremap_bot = IMALLOC_BASE;
++static unsigned long phbs_io_bot = PHBS_IO_BASE;
++
++#ifdef CONFIG_PPC_ISERIES
++
++void __iomem *ioremap(unsigned long addr, unsigned long size)
++{
++ return (void __iomem *)addr;
++}
++
++extern void __iomem *__ioremap(unsigned long addr, unsigned long size,
++ unsigned long flags)
++{
++ return (void __iomem *)addr;
++}
++
++void iounmap(volatile void __iomem *addr)
++{
++ return;
++}
++
++#else
++
++/*
++ * map_io_page currently only called by __ioremap
++ * map_io_page adds an entry to the ioremap page table
++ * and adds an entry to the HPT, possibly bolting it
++ */
++static int map_io_page(unsigned long ea, unsigned long pa, int flags)
++{
++ pgd_t *pgdp;
++ pud_t *pudp;
++ pmd_t *pmdp;
++ pte_t *ptep;
++ unsigned long vsid;
++
++ if (mem_init_done) {
++ pgdp = pgd_offset_k(ea);
++ pudp = pud_alloc(&init_mm, pgdp, ea);
++ if (!pudp)
++ return -ENOMEM;
++ pmdp = pmd_alloc(&init_mm, pudp, ea);
++ if (!pmdp)
++ return -ENOMEM;
++ ptep = pte_alloc_kernel(pmdp, ea);
++ if (!ptep)
++ return -ENOMEM;
++ set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
++ __pgprot(flags)));
++ } else {
++ unsigned long va, vpn, hash, hpteg;
++
++ /*
++ * If the mm subsystem is not fully up, we cannot create a
++ * linux page table entry for this mapping. Simply bolt an
++ * entry in the hardware page table.
++ */
++ vsid = get_kernel_vsid(ea);
++ va = (vsid << 28) | (ea & 0xFFFFFFF);
++ vpn = va >> PAGE_SHIFT;
++
++ hash = hpt_hash(vpn, 0);
++
++ hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
++
++ /* Panic if a pte grpup is full */
++ if (ppc_md.hpte_insert(hpteg, va, pa >> PAGE_SHIFT,
++ HPTE_V_BOLTED,
++ _PAGE_NO_CACHE|_PAGE_GUARDED|PP_RWXX)
++ == -1) {
++ panic("map_io_page: could not insert mapping");
++ }
++ }
++ return 0;
++}
++
++
++static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
++ unsigned long ea, unsigned long size,
++ unsigned long flags)
++{
++ unsigned long i;
++
++ if ((flags & _PAGE_PRESENT) == 0)
++ flags |= pgprot_val(PAGE_KERNEL);
++
++ for (i = 0; i < size; i += PAGE_SIZE)
++ if (map_io_page(ea+i, pa+i, flags))
++ return NULL;
++
++ return (void __iomem *) (ea + (addr & ~PAGE_MASK));
++}
++
++
++void __iomem *
++ioremap(unsigned long addr, unsigned long size)
++{
++ return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
++}
++
++void __iomem * __ioremap(unsigned long addr, unsigned long size,
++ unsigned long flags)
++{
++ unsigned long pa, ea;
++ void __iomem *ret;
++
++ /*
++ * Choose an address to map it to.
++ * Once the imalloc system is running, we use it.
++ * Before that, we map using addresses going
++ * up from ioremap_bot. imalloc will use
++ * the addresses from ioremap_bot through
++ * IMALLOC_END
++ *
++ */
++ pa = addr & PAGE_MASK;
++ size = PAGE_ALIGN(addr + size) - pa;
++
++ if (size == 0)
++ return NULL;
++
++ if (mem_init_done) {
++ struct vm_struct *area;
++ area = im_get_free_area(size);
++ if (area == NULL)
++ return NULL;
++ ea = (unsigned long)(area->addr);
++ ret = __ioremap_com(addr, pa, ea, size, flags);
++ if (!ret)
++ im_free(area->addr);
++ } else {
++ ea = ioremap_bot;
++ ret = __ioremap_com(addr, pa, ea, size, flags);
++ if (ret)
++ ioremap_bot += size;
++ }
++ return ret;
++}
++
++#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
++
++int __ioremap_explicit(unsigned long pa, unsigned long ea,
++ unsigned long size, unsigned long flags)
++{
++ struct vm_struct *area;
++ void __iomem *ret;
++
++ /* For now, require page-aligned values for pa, ea, and size */
++ if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
++ !IS_PAGE_ALIGNED(size)) {
++ printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__);
++ return 1;
++ }
++
++ if (!mem_init_done) {
++ /* Two things to consider in this case:
++ * 1) No records will be kept (imalloc, etc) that the region
++ * has been remapped
++ * 2) It won't be easy to iounmap() the region later (because
++ * of 1)
++ */
++ ;
++ } else {
++ area = im_get_area(ea, size,
++ IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
++ if (area == NULL) {
++ /* Expected when PHB-dlpar is in play */
++ return 1;
++ }
++ if (ea != (unsigned long) area->addr) {
++ printk(KERN_ERR "unexpected addr return from "
++ "im_get_area\n");
++ return 1;
++ }
++ }
++
++ ret = __ioremap_com(pa, pa, ea, size, flags);
++ if (ret == NULL) {
++ printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
++ return 1;
++ }
++ if (ret != (void *) ea) {
++ printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
++ return 1;
++ }
++
++ return 0;
++}
++
++/*
++ * Unmap an IO region and remove it from imalloc'd list.
++ * Access to IO memory should be serialized by driver.
++ * This code is modeled after vmalloc code - unmap_vm_area()
++ *
++ * XXX what about calls before mem_init_done (ie python_countermeasures())
++ */
++void iounmap(volatile void __iomem *token)
++{
++ void *addr;
++
++ if (!mem_init_done)
++ return;
++
++ addr = (void *) ((unsigned long __force) token & PAGE_MASK);
++
++ im_free(addr);
++}
++
++static int iounmap_subset_regions(unsigned long addr, unsigned long size)
++{
++ struct vm_struct *area;
++
++ /* Check whether subsets of this region exist */
++ area = im_get_area(addr, size, IM_REGION_SUPERSET);
++ if (area == NULL)
++ return 1;
++
++ while (area) {
++ iounmap((void __iomem *) area->addr);
++ area = im_get_area(addr, size,
++ IM_REGION_SUPERSET);
++ }
++
++ return 0;
++}
++
++int iounmap_explicit(volatile void __iomem *start, unsigned long size)
++{
++ struct vm_struct *area;
++ unsigned long addr;
++ int rc;
++
++ addr = (unsigned long __force) start & PAGE_MASK;
++
++ /* Verify that the region either exists or is a subset of an existing
++ * region. In the latter case, split the parent region to create
++ * the exact region
++ */
++ area = im_get_area(addr, size,
++ IM_REGION_EXISTS | IM_REGION_SUBSET);
++ if (area == NULL) {
++ /* Determine whether subset regions exist. If so, unmap */
++ rc = iounmap_subset_regions(addr, size);
++ if (rc) {
++ printk(KERN_ERR
++ "%s() cannot unmap nonexistent range 0x%lx\n",
++ __FUNCTION__, addr);
++ return 1;
++ }
++ } else {
++ iounmap((void __iomem *) area->addr);
++ }
++ /*
++ * FIXME! This can't be right:
++ iounmap(area->addr);
++ * Maybe it should be "iounmap(area);"
++ */
++ return 0;
++}
++
++#endif
++
++EXPORT_SYMBOL(ioremap);
++EXPORT_SYMBOL(__ioremap);
++EXPORT_SYMBOL(iounmap);
++
++void __iomem * reserve_phb_iospace(unsigned long size)
++{
++ void __iomem *virt_addr;
++
++ if (phbs_io_bot >= IMALLOC_BASE)
++ panic("reserve_phb_iospace(): phb io space overflow\n");
++
++ virt_addr = (void __iomem *) phbs_io_bot;
++ phbs_io_bot += size;
++
++ return virt_addr;
++}
+diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/ppc_mmu_32.c
+@@ -0,0 +1,285 @@
++/*
++ * This file contains the routines for handling the MMU on those
++ * PowerPC implementations where the MMU substantially follows the
++ * architecture specification. This includes the 6xx, 7xx, 7xxx,
++ * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
++ * -- paulus
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/mm.h>
++#include <linux/init.h>
++#include <linux/highmem.h>
++
++#include <asm/prom.h>
++#include <asm/mmu.h>
++#include <asm/machdep.h>
++#include <asm/lmb.h>
++
++#include "mmu_decl.h"
++
++PTE *Hash, *Hash_end;
++unsigned long Hash_size, Hash_mask;
++unsigned long _SDR1;
++
++union ubat { /* BAT register values to be loaded */
++ BAT bat;
++#ifdef CONFIG_PPC64BRIDGE
++ u64 word[2];
++#else
++ u32 word[2];
++#endif
++} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
++
++struct batrange { /* stores address ranges mapped by BATs */
++ unsigned long start;
++ unsigned long limit;
++ unsigned long phys;
++} bat_addrs[4];
++
++/*
++ * Return PA for this VA if it is mapped by a BAT, or 0
++ */
++unsigned long v_mapped_by_bats(unsigned long va)
++{
++ int b;
++ for (b = 0; b < 4; ++b)
++ if (va >= bat_addrs[b].start && va < bat_addrs[b].limit)
++ return bat_addrs[b].phys + (va - bat_addrs[b].start);
++ return 0;
++}
++
++/*
++ * Return VA for a given PA or 0 if not mapped
++ */
++unsigned long p_mapped_by_bats(unsigned long pa)
++{
++ int b;
++ for (b = 0; b < 4; ++b)
++ if (pa >= bat_addrs[b].phys
++ && pa < (bat_addrs[b].limit-bat_addrs[b].start)
++ +bat_addrs[b].phys)
++ return bat_addrs[b].start+(pa-bat_addrs[b].phys);
++ return 0;
++}
++
++unsigned long __init mmu_mapin_ram(void)
++{
++#ifdef CONFIG_POWER4
++ return 0;
++#else
++ unsigned long tot, bl, done;
++ unsigned long max_size = (256<<20);
++ unsigned long align;
++
++ if (__map_without_bats)
++ return 0;
++
++ /* Set up BAT2 and if necessary BAT3 to cover RAM. */
++
++ /* Make sure we don't map a block larger than the
++ smallest alignment of the physical address. */
++ /* alignment of PPC_MEMSTART */
++ align = ~(PPC_MEMSTART-1) & PPC_MEMSTART;
++ /* set BAT block size to MIN(max_size, align) */
++ if (align && align < max_size)
++ max_size = align;
++
++ tot = total_lowmem;
++ for (bl = 128<<10; bl < max_size; bl <<= 1) {
++ if (bl * 2 > tot)
++ break;
++ }
++
++ setbat(2, KERNELBASE, PPC_MEMSTART, bl, _PAGE_RAM);
++ done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
++ if ((done < tot) && !bat_addrs[3].limit) {
++ /* use BAT3 to cover a bit more */
++ tot -= done;
++ for (bl = 128<<10; bl < max_size; bl <<= 1)
++ if (bl * 2 > tot)
++ break;
++ setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_RAM);
++ done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1;
++ }
++
++ return done;
++#endif
++}
++
++/*
++ * Set up one of the I/D BAT (block address translation) register pairs.
++ * The parameters are not checked; in particular size must be a power
++ * of 2 between 128k and 256M.
++ */
++void __init setbat(int index, unsigned long virt, unsigned long phys,
++ unsigned int size, int flags)
++{
++ unsigned int bl;
++ int wimgxpp;
++ union ubat *bat = BATS[index];
++
++ if (((flags & _PAGE_NO_CACHE) == 0) &&
++ cpu_has_feature(CPU_FTR_NEED_COHERENT))
++ flags |= _PAGE_COHERENT;
++
++ bl = (size >> 17) - 1;
++ if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
++ /* 603, 604, etc. */
++ /* Do DBAT first */
++ wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
++ | _PAGE_COHERENT | _PAGE_GUARDED);
++ wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX;
++ bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
++ bat[1].word[1] = phys | wimgxpp;
++#ifndef CONFIG_KGDB /* want user access for breakpoints */
++ if (flags & _PAGE_USER)
++#endif
++ bat[1].bat.batu.vp = 1;
++ if (flags & _PAGE_GUARDED) {
++ /* G bit must be zero in IBATs */
++ bat[0].word[0] = bat[0].word[1] = 0;
++ } else {
++ /* make IBAT same as DBAT */
++ bat[0] = bat[1];
++ }
++ } else {
++ /* 601 cpu */
++ if (bl > BL_8M)
++ bl = BL_8M;
++ wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
++ | _PAGE_COHERENT);
++ wimgxpp |= (flags & _PAGE_RW)?
++ ((flags & _PAGE_USER)? PP_RWRW: PP_RWXX): PP_RXRX;
++ bat->word[0] = virt | wimgxpp | 4; /* Ks=0, Ku=1 */
++ bat->word[1] = phys | bl | 0x40; /* V=1 */
++ }
++
++ bat_addrs[index].start = virt;
++ bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1;
++ bat_addrs[index].phys = phys;
++}
++
++/*
++ * Initialize the hash table and patch the instructions in hashtable.S.
++ */
++void __init MMU_init_hw(void)
++{
++ unsigned int hmask, mb, mb2;
++ unsigned int n_hpteg, lg_n_hpteg;
++
++ extern unsigned int hash_page_patch_A[];
++ extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
++ extern unsigned int hash_page[];
++ extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
++
++ if (!cpu_has_feature(CPU_FTR_HPTE_TABLE)) {
++ /*
++ * Put a blr (procedure return) instruction at the
++ * start of hash_page, since we can still get DSI
++ * exceptions on a 603.
++ */
++ hash_page[0] = 0x4e800020;
++ flush_icache_range((unsigned long) &hash_page[0],
++ (unsigned long) &hash_page[1]);
++ return;
++ }
++
++ if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
++
++#ifdef CONFIG_PPC64BRIDGE
++#define LG_HPTEG_SIZE 7 /* 128 bytes per HPTEG */
++#define SDR1_LOW_BITS (lg_n_hpteg - 11)
++#define MIN_N_HPTEG 2048 /* min 256kB hash table */
++#else
++#define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */
++#define SDR1_LOW_BITS ((n_hpteg - 1) >> 10)
++#define MIN_N_HPTEG 1024 /* min 64kB hash table */
++#endif
++
++ /*
++ * Allow 1 HPTE (1/8 HPTEG) for each page of memory.
++ * This is less than the recommended amount, but then
++ * Linux ain't AIX.
++ */
++ n_hpteg = total_memory / (PAGE_SIZE * 8);
++ if (n_hpteg < MIN_N_HPTEG)
++ n_hpteg = MIN_N_HPTEG;
++ lg_n_hpteg = __ilog2(n_hpteg);
++ if (n_hpteg & (n_hpteg - 1)) {
++ ++lg_n_hpteg; /* round up if not power of 2 */
++ n_hpteg = 1 << lg_n_hpteg;
++ }
++ Hash_size = n_hpteg << LG_HPTEG_SIZE;
++
++ /*
++ * Find some memory for the hash table.
++ */
++ if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
++ Hash = __va(lmb_alloc_base(Hash_size, Hash_size,
++ __initial_memory_limit));
++ cacheable_memzero(Hash, Hash_size);
++ _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
++
++ Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
++
++ printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
++ total_memory >> 20, Hash_size >> 10, Hash);
++
++
++ /*
++ * Patch up the instructions in hashtable.S:create_hpte
++ */
++ if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
++ Hash_mask = n_hpteg - 1;
++ hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
++ mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg;
++ if (lg_n_hpteg > 16)
++ mb2 = 16 - LG_HPTEG_SIZE;
++
++ hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
++ | ((unsigned int)(Hash) >> 16);
++ hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6);
++ hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) | (mb2 << 6);
++ hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) | hmask;
++ hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) | hmask;
++
++ /*
++ * Ensure that the locations we've patched have been written
++ * out from the data cache and invalidated in the instruction
++ * cache, on those machines with split caches.
++ */
++ flush_icache_range((unsigned long) &hash_page_patch_A[0],
++ (unsigned long) &hash_page_patch_C[1]);
++
++ /*
++ * Patch up the instructions in hashtable.S:flush_hash_page
++ */
++ flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
++ | ((unsigned int)(Hash) >> 16);
++ flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) | (mb << 6);
++ flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) | (mb2 << 6);
++ flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) | hmask;
++ flush_icache_range((unsigned long) &flush_hash_patch_A[0],
++ (unsigned long) &flush_hash_patch_B[1]);
++
++ if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
++}
+diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/slb.c
+@@ -0,0 +1,158 @@
++/*
++ * PowerPC64 SLB support.
++ *
++ * Copyright (C) 2004 David Gibson <dwg at au.ibm.com>, IBM
++ * Based on earlier code writteh by:
++ * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
++ * Copyright (c) 2001 Dave Engebretsen
++ * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ *
++ * 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/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/mmu_context.h>
++#include <asm/paca.h>
++#include <asm/cputable.h>
++
++extern void slb_allocate(unsigned long ea);
++
++static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot)
++{
++ return (ea & ESID_MASK) | SLB_ESID_V | slot;
++}
++
++static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags)
++{
++ return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
++}
++
++static inline void create_slbe(unsigned long ea, unsigned long flags,
++ unsigned long entry)
++{
++ asm volatile("slbmte %0,%1" :
++ : "r" (mk_vsid_data(ea, flags)),
++ "r" (mk_esid_data(ea, entry))
++ : "memory" );
++}
++
++static void slb_flush_and_rebolt(void)
++{
++ /* If you change this make sure you change SLB_NUM_BOLTED
++ * appropriately too. */
++ unsigned long ksp_flags = SLB_VSID_KERNEL;
++ unsigned long ksp_esid_data;
++
++ WARN_ON(!irqs_disabled());
++
++ if (cpu_has_feature(CPU_FTR_16M_PAGE))
++ ksp_flags |= SLB_VSID_L;
++
++ ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
++ if ((ksp_esid_data & ESID_MASK) == KERNELBASE)
++ ksp_esid_data &= ~SLB_ESID_V;
++
++ /* We need to do this all in asm, so we're sure we don't touch
++ * the stack between the slbia and rebolting it. */
++ asm volatile("isync\n"
++ "slbia\n"
++ /* Slot 1 - first VMALLOC segment */
++ "slbmte %0,%1\n"
++ /* Slot 2 - kernel stack */
++ "slbmte %2,%3\n"
++ "isync"
++ :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)),
++ "r"(mk_esid_data(VMALLOCBASE, 1)),
++ "r"(mk_vsid_data(ksp_esid_data, ksp_flags)),
++ "r"(ksp_esid_data)
++ : "memory");
++}
++
++/* Flush all user entries from the segment table of the current processor. */
++void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
++{
++ unsigned long offset = get_paca()->slb_cache_ptr;
++ unsigned long esid_data = 0;
++ unsigned long pc = KSTK_EIP(tsk);
++ unsigned long stack = KSTK_ESP(tsk);
++ unsigned long unmapped_base;
++
++ if (offset <= SLB_CACHE_ENTRIES) {
++ int i;
++ asm volatile("isync" : : : "memory");
++ for (i = 0; i < offset; i++) {
++ esid_data = ((unsigned long)get_paca()->slb_cache[i]
++ << SID_SHIFT) | SLBIE_C;
++ asm volatile("slbie %0" : : "r" (esid_data));
++ }
++ asm volatile("isync" : : : "memory");
++ } else {
++ slb_flush_and_rebolt();
++ }
++
++ /* Workaround POWER5 < DD2.1 issue */
++ if (offset == 1 || offset > SLB_CACHE_ENTRIES)
++ asm volatile("slbie %0" : : "r" (esid_data));
++
++ get_paca()->slb_cache_ptr = 0;
++ get_paca()->context = mm->context;
++
++ /*
++ * preload some userspace segments into the SLB.
++ */
++ if (test_tsk_thread_flag(tsk, TIF_32BIT))
++ unmapped_base = TASK_UNMAPPED_BASE_USER32;
++ else
++ unmapped_base = TASK_UNMAPPED_BASE_USER64;
++
++ if (pc >= KERNELBASE)
++ return;
++ slb_allocate(pc);
++
++ if (GET_ESID(pc) == GET_ESID(stack))
++ return;
++
++ if (stack >= KERNELBASE)
++ return;
++ slb_allocate(stack);
++
++ if ((GET_ESID(pc) == GET_ESID(unmapped_base))
++ || (GET_ESID(stack) == GET_ESID(unmapped_base)))
++ return;
++
++ if (unmapped_base >= KERNELBASE)
++ return;
++ slb_allocate(unmapped_base);
++}
++
++void slb_initialize(void)
++{
++ /* On iSeries the bolted entries have already been set up by
++ * the hypervisor from the lparMap data in head.S */
++#ifndef CONFIG_PPC_ISERIES
++ unsigned long flags = SLB_VSID_KERNEL;
++
++ /* Invalidate the entire SLB (even slot 0) & all the ERATS */
++ if (cpu_has_feature(CPU_FTR_16M_PAGE))
++ flags |= SLB_VSID_L;
++
++ asm volatile("isync":::"memory");
++ asm volatile("slbmte %0,%0"::"r" (0) : "memory");
++ asm volatile("isync; slbia; isync":::"memory");
++ create_slbe(KERNELBASE, flags, 0);
++ create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1);
++ /* We don't bolt the stack for the time being - we're in boot,
++ * so the stack is in the bolted segment. By the time it goes
++ * elsewhere, we'll call _switch() which will bolt in the new
++ * one. */
++ asm volatile("isync":::"memory");
++#endif
++
++ get_paca()->stab_rr = SLB_NUM_BOLTED;
++}
+diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/slb_low.S
+@@ -0,0 +1,151 @@
++/*
++ * arch/ppc64/mm/slb_low.S
++ *
++ * Low-level SLB routines
++ *
++ * Copyright (C) 2004 David Gibson <dwg at au.ibm.com>, IBM
++ *
++ * Based on earlier C version:
++ * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
++ * Copyright (c) 2001 Dave Engebretsen
++ * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/cputable.h>
++
++/* void slb_allocate(unsigned long ea);
++ *
++ * Create an SLB entry for the given EA (user or kernel).
++ * r3 = faulting address, r13 = PACA
++ * r9, r10, r11 are clobbered by this function
++ * No other registers are examined or changed.
++ */
++_GLOBAL(slb_allocate)
++ /*
++ * First find a slot, round robin. Previously we tried to find
++ * a free slot first but that took too long. Unfortunately we
++ * dont have any LRU information to help us choose a slot.
++ */
++#ifdef CONFIG_PPC_ISERIES
++ /*
++ * On iSeries, the "bolted" stack segment can be cast out on
++ * shared processor switch so we need to check for a miss on
++ * it and restore it to the right slot.
++ */
++ ld r9,PACAKSAVE(r13)
++ clrrdi r9,r9,28
++ clrrdi r11,r3,28
++ li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */
++ cmpld r9,r11
++ beq 3f
++#endif /* CONFIG_PPC_ISERIES */
++
++ ld r10,PACASTABRR(r13)
++ addi r10,r10,1
++ /* use a cpu feature mask if we ever change our slb size */
++ cmpldi r10,SLB_NUM_ENTRIES
++
++ blt+ 4f
++ li r10,SLB_NUM_BOLTED
++
++4:
++ std r10,PACASTABRR(r13)
++3:
++ /* r3 = faulting address, r10 = entry */
++
++ srdi r9,r3,60 /* get region */
++ srdi r3,r3,28 /* get esid */
++ cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */
++
++ rldimi r10,r3,28,0 /* r10= ESID<<28 | entry */
++ oris r10,r10,SLB_ESID_V at h /* r10 |= SLB_ESID_V */
++
++ /* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */
++
++ blt cr7,0f /* user or kernel? */
++
++ /* kernel address: proto-VSID = ESID */
++ /* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
++ * this code will generate the protoVSID 0xfffffffff for the
++ * top segment. That's ok, the scramble below will translate
++ * it to VSID 0, which is reserved as a bad VSID - one which
++ * will never have any pages in it. */
++ li r11,SLB_VSID_KERNEL
++BEGIN_FTR_SECTION
++ bne cr7,9f
++ li r11,(SLB_VSID_KERNEL|SLB_VSID_L)
++END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
++ b 9f
++
++0: /* user address: proto-VSID = context<<15 | ESID */
++ srdi. r9,r3,USER_ESID_BITS
++ bne- 8f /* invalid ea bits set */
++
++#ifdef CONFIG_HUGETLB_PAGE
++BEGIN_FTR_SECTION
++ lhz r9,PACAHIGHHTLBAREAS(r13)
++ srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT)
++ srd r9,r9,r11
++ lhz r11,PACALOWHTLBAREAS(r13)
++ srd r11,r11,r3
++ or r9,r9,r11
++END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
++#endif /* CONFIG_HUGETLB_PAGE */
++
++ li r11,SLB_VSID_USER
++
++#ifdef CONFIG_HUGETLB_PAGE
++BEGIN_FTR_SECTION
++ rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */
++END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
++#endif /* CONFIG_HUGETLB_PAGE */
++
++ ld r9,PACACONTEXTID(r13)
++ rldimi r3,r9,USER_ESID_BITS,0
++
++9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
++ ASM_VSID_SCRAMBLE(r3,r9)
++
++ rldimi r11,r3,SLB_VSID_SHIFT,16 /* combine VSID and flags */
++
++ /*
++ * No need for an isync before or after this slbmte. The exception
++ * we enter with and the rfid we exit with are context synchronizing.
++ */
++ slbmte r11,r10
++
++ bgelr cr7 /* we're done for kernel addresses */
++
++ /* Update the slb cache */
++ lhz r3,PACASLBCACHEPTR(r13) /* offset = paca->slb_cache_ptr */
++ cmpldi r3,SLB_CACHE_ENTRIES
++ bge 1f
++
++ /* still room in the slb cache */
++ sldi r11,r3,1 /* r11 = offset * sizeof(u16) */
++ rldicl r10,r10,36,28 /* get low 16 bits of the ESID */
++ add r11,r11,r13 /* r11 = (u16 *)paca + offset */
++ sth r10,PACASLBCACHE(r11) /* paca->slb_cache[offset] = esid */
++ addi r3,r3,1 /* offset++ */
++ b 2f
++1: /* offset >= SLB_CACHE_ENTRIES */
++ li r3,SLB_CACHE_ENTRIES+1
++2:
++ sth r3,PACASLBCACHEPTR(r13) /* paca->slb_cache_ptr = offset */
++ blr
++
++8: /* invalid EA */
++ li r3,0 /* BAD_VSID */
++ li r11,SLB_VSID_USER /* flags don't much matter */
++ b 9b
+diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/stab.c
+@@ -0,0 +1,279 @@
++/*
++ * PowerPC64 Segment Translation Support.
++ *
++ * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
++ * Copyright (c) 2001 Dave Engebretsen
++ *
++ * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * 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/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/mmu_context.h>
++#include <asm/paca.h>
++#include <asm/cputable.h>
++#include <asm/lmb.h>
++#include <asm/abs_addr.h>
++
++struct stab_entry {
++ unsigned long esid_data;
++ unsigned long vsid_data;
++};
++
++/* Both the segment table and SLB code uses the following cache */
++#define NR_STAB_CACHE_ENTRIES 8
++DEFINE_PER_CPU(long, stab_cache_ptr);
++DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]);
++
++/*
++ * Create a segment table entry for the given esid/vsid pair.
++ */
++static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
++{
++ unsigned long esid_data, vsid_data;
++ unsigned long entry, group, old_esid, castout_entry, i;
++ unsigned int global_entry;
++ struct stab_entry *ste, *castout_ste;
++ unsigned long kernel_segment = (esid << SID_SHIFT) >= KERNELBASE;
++
++ vsid_data = vsid << STE_VSID_SHIFT;
++ esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V;
++ if (! kernel_segment)
++ esid_data |= STE_ESID_KS;
++
++ /* Search the primary group first. */
++ global_entry = (esid & 0x1f) << 3;
++ ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
++
++ /* Find an empty entry, if one exists. */
++ for (group = 0; group < 2; group++) {
++ for (entry = 0; entry < 8; entry++, ste++) {
++ if (!(ste->esid_data & STE_ESID_V)) {
++ ste->vsid_data = vsid_data;
++ asm volatile("eieio":::"memory");
++ ste->esid_data = esid_data;
++ return (global_entry | entry);
++ }
++ }
++ /* Now search the secondary group. */
++ global_entry = ((~esid) & 0x1f) << 3;
++ ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
++ }
++
++ /*
++ * Could not find empty entry, pick one with a round robin selection.
++ * Search all entries in the two groups.
++ */
++ castout_entry = get_paca()->stab_rr;
++ for (i = 0; i < 16; i++) {
++ if (castout_entry < 8) {
++ global_entry = (esid & 0x1f) << 3;
++ ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
++ castout_ste = ste + castout_entry;
++ } else {
++ global_entry = ((~esid) & 0x1f) << 3;
++ ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
++ castout_ste = ste + (castout_entry - 8);
++ }
++
++ /* Dont cast out the first kernel segment */
++ if ((castout_ste->esid_data & ESID_MASK) != KERNELBASE)
++ break;
++
++ castout_entry = (castout_entry + 1) & 0xf;
++ }
++
++ get_paca()->stab_rr = (castout_entry + 1) & 0xf;
++
++ /* Modify the old entry to the new value. */
++
++ /* Force previous translations to complete. DRENG */
++ asm volatile("isync" : : : "memory");
++
++ old_esid = castout_ste->esid_data >> SID_SHIFT;
++ castout_ste->esid_data = 0; /* Invalidate old entry */
++
++ asm volatile("sync" : : : "memory"); /* Order update */
++
++ castout_ste->vsid_data = vsid_data;
++ asm volatile("eieio" : : : "memory"); /* Order update */
++ castout_ste->esid_data = esid_data;
++
++ asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT));
++ /* Ensure completion of slbie */
++ asm volatile("sync" : : : "memory");
++
++ return (global_entry | (castout_entry & 0x7));
++}
++
++/*
++ * Allocate a segment table entry for the given ea and mm
++ */
++static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
++{
++ unsigned long vsid;
++ unsigned char stab_entry;
++ unsigned long offset;
++
++ /* Kernel or user address? */
++ if (ea >= KERNELBASE) {
++ vsid = get_kernel_vsid(ea);
++ } else {
++ if ((ea >= TASK_SIZE_USER64) || (! mm))
++ return 1;
++
++ vsid = get_vsid(mm->context.id, ea);
++ }
++
++ stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid);
++
++ if (ea < KERNELBASE) {
++ offset = __get_cpu_var(stab_cache_ptr);
++ if (offset < NR_STAB_CACHE_ENTRIES)
++ __get_cpu_var(stab_cache[offset++]) = stab_entry;
++ else
++ offset = NR_STAB_CACHE_ENTRIES+1;
++ __get_cpu_var(stab_cache_ptr) = offset;
++
++ /* Order update */
++ asm volatile("sync":::"memory");
++ }
++
++ return 0;
++}
++
++int ste_allocate(unsigned long ea)
++{
++ return __ste_allocate(ea, current->mm);
++}
++
++/*
++ * Do the segment table work for a context switch: flush all user
++ * entries from the table, then preload some probably useful entries
++ * for the new task
++ */
++void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
++{
++ struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr;
++ struct stab_entry *ste;
++ unsigned long offset = __get_cpu_var(stab_cache_ptr);
++ unsigned long pc = KSTK_EIP(tsk);
++ unsigned long stack = KSTK_ESP(tsk);
++ unsigned long unmapped_base;
++
++ /* Force previous translations to complete. DRENG */
++ asm volatile("isync" : : : "memory");
++
++ if (offset <= NR_STAB_CACHE_ENTRIES) {
++ int i;
++
++ for (i = 0; i < offset; i++) {
++ ste = stab + __get_cpu_var(stab_cache[i]);
++ ste->esid_data = 0; /* invalidate entry */
++ }
++ } else {
++ unsigned long entry;
++
++ /* Invalidate all entries. */
++ ste = stab;
++
++ /* Never flush the first entry. */
++ ste += 1;
++ for (entry = 1;
++ entry < (PAGE_SIZE / sizeof(struct stab_entry));
++ entry++, ste++) {
++ unsigned long ea;
++ ea = ste->esid_data & ESID_MASK;
++ if (ea < KERNELBASE) {
++ ste->esid_data = 0;
++ }
++ }
++ }
++
++ asm volatile("sync; slbia; sync":::"memory");
++
++ __get_cpu_var(stab_cache_ptr) = 0;
++
++ /* Now preload some entries for the new task */
++ if (test_tsk_thread_flag(tsk, TIF_32BIT))
++ unmapped_base = TASK_UNMAPPED_BASE_USER32;
++ else
++ unmapped_base = TASK_UNMAPPED_BASE_USER64;
++
++ __ste_allocate(pc, mm);
++
++ if (GET_ESID(pc) == GET_ESID(stack))
++ return;
++
++ __ste_allocate(stack, mm);
++
++ if ((GET_ESID(pc) == GET_ESID(unmapped_base))
++ || (GET_ESID(stack) == GET_ESID(unmapped_base)))
++ return;
++
++ __ste_allocate(unmapped_base, mm);
++
++ /* Order update */
++ asm volatile("sync" : : : "memory");
++}
++
++extern void slb_initialize(void);
++
++/*
++ * Allocate segment tables for secondary CPUs. These must all go in
++ * the first (bolted) segment, so that do_stab_bolted won't get a
++ * recursive segment miss on the segment table itself.
++ */
++void stabs_alloc(void)
++{
++ int cpu;
++
++ if (cpu_has_feature(CPU_FTR_SLB))
++ return;
++
++ for_each_cpu(cpu) {
++ unsigned long newstab;
++
++ if (cpu == 0)
++ continue; /* stab for CPU 0 is statically allocated */
++
++ newstab = lmb_alloc_base(PAGE_SIZE, PAGE_SIZE, 1<<SID_SHIFT);
++ if (! newstab)
++ panic("Unable to allocate segment table for CPU %d.\n",
++ cpu);
++
++ newstab += KERNELBASE;
++
++ memset((void *)newstab, 0, PAGE_SIZE);
++
++ paca[cpu].stab_addr = newstab;
++ paca[cpu].stab_real = virt_to_abs(newstab);
++ printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx virtual, 0x%lx absolute\n", cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
++ }
++}
++
++/*
++ * Build an entry for the base kernel segment and put it into
++ * the segment table or SLB. All other segment table or SLB
++ * entries are faulted in.
++ */
++void stab_initialize(unsigned long stab)
++{
++ unsigned long vsid = get_kernel_vsid(KERNELBASE);
++
++ if (cpu_has_feature(CPU_FTR_SLB)) {
++ slb_initialize();
++ } else {
++ asm volatile("isync; slbia; isync":::"memory");
++ make_ste(stab, GET_ESID(KERNELBASE), vsid);
++
++ /* Order update */
++ asm volatile("sync":::"memory");
++ }
++}
+diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/tlb_32.c
+@@ -0,0 +1,183 @@
++/*
++ * This file contains the routines for TLB flushing.
++ * On machines where the MMU uses a hash table to store virtual to
++ * physical translations, these routines flush entries from the
++ * hash table also.
++ * -- paulus
++ *
++ * Derived from arch/ppc/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * 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/mm.h>
++#include <linux/init.h>
++#include <linux/highmem.h>
++#include <asm/tlbflush.h>
++#include <asm/tlb.h>
++
++#include "mmu_decl.h"
++
++/*
++ * Called when unmapping pages to flush entries from the TLB/hash table.
++ */
++void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
++{
++ unsigned long ptephys;
++
++ if (Hash != 0) {
++ ptephys = __pa(ptep) & PAGE_MASK;
++ flush_hash_pages(mm->context, addr, ptephys, 1);
++ }
++}
++
++/*
++ * Called by ptep_set_access_flags, must flush on CPUs for which the
++ * DSI handler can't just "fixup" the TLB on a write fault
++ */
++void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr)
++{
++ if (Hash != 0)
++ return;
++ _tlbie(addr);
++}
++
++/*
++ * Called at the end of a mmu_gather operation to make sure the
++ * TLB flush is completely done.
++ */
++void tlb_flush(struct mmu_gather *tlb)
++{
++ if (Hash == 0) {
++ /*
++ * 603 needs to flush the whole TLB here since
++ * it doesn't use a hash table.
++ */
++ _tlbia();
++ }
++}
++
++/*
++ * TLB flushing:
++ *
++ * - flush_tlb_mm(mm) flushes the specified mm context TLB's
++ * - flush_tlb_page(vma, vmaddr) flushes one page
++ * - flush_tlb_range(vma, start, end) flushes a range of pages
++ * - flush_tlb_kernel_range(start, end) flushes kernel pages
++ *
++ * since the hardware hash table functions as an extension of the
++ * tlb as far as the linux tables are concerned, flush it too.
++ * -- Cort
++ */
++
++/*
++ * 750 SMP is a Bad Idea because the 750 doesn't broadcast all
++ * the cache operations on the bus. Hence we need to use an IPI
++ * to get the other CPU(s) to invalidate their TLBs.
++ */
++#ifdef CONFIG_SMP_750
++#define FINISH_FLUSH smp_send_tlb_invalidate(0)
++#else
++#define FINISH_FLUSH do { } while (0)
++#endif
++
++static void flush_range(struct mm_struct *mm, unsigned long start,
++ unsigned long end)
++{
++ pmd_t *pmd;
++ unsigned long pmd_end;
++ int count;
++ unsigned int ctx = mm->context;
++
++ if (Hash == 0) {
++ _tlbia();
++ return;
++ }
++ start &= PAGE_MASK;
++ if (start >= end)
++ return;
++ end = (end - 1) | ~PAGE_MASK;
++ pmd = pmd_offset(pgd_offset(mm, start), start);
++ for (;;) {
++ pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
++ if (pmd_end > end)
++ pmd_end = end;
++ if (!pmd_none(*pmd)) {
++ count = ((pmd_end - start) >> PAGE_SHIFT) + 1;
++ flush_hash_pages(ctx, start, pmd_val(*pmd), count);
++ }
++ if (pmd_end == end)
++ break;
++ start = pmd_end + 1;
++ ++pmd;
++ }
++}
++
++/*
++ * Flush kernel TLB entries in the given range
++ */
++void flush_tlb_kernel_range(unsigned long start, unsigned long end)
++{
++ flush_range(&init_mm, start, end);
++ FINISH_FLUSH;
++}
++
++/*
++ * Flush all the (user) entries for the address space described by mm.
++ */
++void flush_tlb_mm(struct mm_struct *mm)
++{
++ struct vm_area_struct *mp;
++
++ if (Hash == 0) {
++ _tlbia();
++ return;
++ }
++
++ for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
++ flush_range(mp->vm_mm, mp->vm_start, mp->vm_end);
++ FINISH_FLUSH;
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
++{
++ struct mm_struct *mm;
++ pmd_t *pmd;
++
++ if (Hash == 0) {
++ _tlbie(vmaddr);
++ return;
++ }
++ mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
++ pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
++ if (!pmd_none(*pmd))
++ flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
++ FINISH_FLUSH;
++}
++
++/*
++ * For each address in the range, find the pte for the address
++ * and check _PAGE_HASHPTE bit; if it is set, find and destroy
++ * the corresponding HPTE.
++ */
++void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
++ unsigned long end)
++{
++ flush_range(vma->vm_mm, start, end);
++ FINISH_FLUSH;
++}
+diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/mm/tlb_64.c
+@@ -0,0 +1,196 @@
++/*
++ * This file contains the routines for flushing entries from the
++ * TLB and MMU hash table.
++ *
++ * Derived from arch/ppc64/mm/init.c:
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
++ * and Cort Dougan (PReP) (cort at cs.nmt.edu)
++ * Copyright (C) 1996 Paul Mackerras
++ * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
++ *
++ * Derived from "arch/i386/mm/init.c"
++ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
++ *
++ * Dave Engebretsen <engebret at us.ibm.com>
++ * Rework for PPC64 port.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/percpu.h>
++#include <linux/hardirq.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++#include <asm/tlb.h>
++#include <linux/highmem.h>
++
++DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
++
++/* This is declared as we are using the more or less generic
++ * include/asm-ppc64/tlb.h file -- tgall
++ */
++DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
++DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
++unsigned long pte_freelist_forced_free;
++
++struct pte_freelist_batch
++{
++ struct rcu_head rcu;
++ unsigned int index;
++ pgtable_free_t tables[0];
++};
++
++DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
++unsigned long pte_freelist_forced_free;
++
++#define PTE_FREELIST_SIZE \
++ ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
++ / sizeof(pgtable_free_t))
++
++#ifdef CONFIG_SMP
++static void pte_free_smp_sync(void *arg)
++{
++ /* Do nothing, just ensure we sync with all CPUs */
++}
++#endif
++
++/* This is only called when we are critically out of memory
++ * (and fail to get a page in pte_free_tlb).
++ */
++static void pgtable_free_now(pgtable_free_t pgf)
++{
++ pte_freelist_forced_free++;
++
++ smp_call_function(pte_free_smp_sync, NULL, 0, 1);
++
++ pgtable_free(pgf);
++}
++
++static void pte_free_rcu_callback(struct rcu_head *head)
++{
++ struct pte_freelist_batch *batch =
++ container_of(head, struct pte_freelist_batch, rcu);
++ unsigned int i;
++
++ for (i = 0; i < batch->index; i++)
++ pgtable_free(batch->tables[i]);
++
++ free_page((unsigned long)batch);
++}
++
++static void pte_free_submit(struct pte_freelist_batch *batch)
++{
++ INIT_RCU_HEAD(&batch->rcu);
++ call_rcu(&batch->rcu, pte_free_rcu_callback);
++}
++
++void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
++{
++ /* This is safe as we are holding page_table_lock */
++ cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
++ struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
++
++ if (atomic_read(&tlb->mm->mm_users) < 2 ||
++ cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
++ pgtable_free(pgf);
++ return;
++ }
++
++ if (*batchp == NULL) {
++ *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
++ if (*batchp == NULL) {
++ pgtable_free_now(pgf);
++ return;
++ }
++ (*batchp)->index = 0;
++ }
++ (*batchp)->tables[(*batchp)->index++] = pgf;
++ if ((*batchp)->index == PTE_FREELIST_SIZE) {
++ pte_free_submit(*batchp);
++ *batchp = NULL;
++ }
++}
++
++/*
++ * Update the MMU hash table to correspond with a change to
++ * a Linux PTE. If wrprot is true, it is permissible to
++ * change the existing HPTE to read-only rather than removing it
++ * (if we remove it we should clear the _PTE_HPTEFLAGS bits).
++ */
++void hpte_update(struct mm_struct *mm, unsigned long addr,
++ unsigned long pte, int wrprot)
++{
++ struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
++ unsigned long vsid;
++ int i;
++
++ i = batch->index;
++
++ /*
++ * This can happen when we are in the middle of a TLB batch and
++ * we encounter memory pressure (eg copy_page_range when it tries
++ * to allocate a new pte). If we have to reclaim memory and end
++ * up scanning and resetting referenced bits then our batch context
++ * will change mid stream.
++ */
++ if (i != 0 && (mm != batch->mm || batch->large != pte_huge(pte))) {
++ flush_tlb_pending();
++ i = 0;
++ }
++ if (i == 0) {
++ batch->mm = mm;
++ batch->large = pte_huge(pte);
++ }
++ if (addr < KERNELBASE) {
++ vsid = get_vsid(mm->context.id, addr);
++ WARN_ON(vsid == 0);
++ } else
++ vsid = get_kernel_vsid(addr);
++ batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff);
++ batch->pte[i] = __pte(pte);
++ batch->index = ++i;
++ if (i >= PPC64_TLB_BATCH_NR)
++ flush_tlb_pending();
++}
++
++void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
++{
++ int i;
++ int cpu;
++ cpumask_t tmp;
++ int local = 0;
++
++ BUG_ON(in_interrupt());
++
++ cpu = get_cpu();
++ i = batch->index;
++ tmp = cpumask_of_cpu(cpu);
++ if (cpus_equal(batch->mm->cpu_vm_mask, tmp))
++ local = 1;
++
++ if (i == 1)
++ flush_hash_page(batch->vaddr[0], batch->pte[0], local);
++ else
++ flush_hash_range(i, local);
++ batch->index = 0;
++ put_cpu();
++}
++
++void pte_free_finish(void)
++{
++ /* This is safe as we are holding page_table_lock */
++ struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
++
++ if (*batchp == NULL)
++ return;
++ pte_free_submit(*batchp);
++ *batchp = NULL;
++}
+diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/oprofile/Kconfig
+@@ -0,0 +1,23 @@
++
++menu "Profiling support"
++ depends on EXPERIMENTAL
++
++config PROFILING
++ bool "Profiling support (EXPERIMENTAL)"
++ help
++ Say Y here to enable the extended profiling support mechanisms used
++ by profilers such as OProfile.
++
++
++config OPROFILE
++ tristate "OProfile system profiling (EXPERIMENTAL)"
++ depends on PROFILING
++ help
++ OProfile is a profiling system capable of profiling the
++ whole system, include the kernel, kernel modules, libraries,
++ and applications.
++
++ If unsure, say N.
++
++endmenu
++
+diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/oprofile/Makefile
+@@ -0,0 +1,11 @@
++obj-$(CONFIG_OPROFILE) += oprofile.o
++
++DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
++ oprof.o cpu_buffer.o buffer_sync.o \
++ event_buffer.o oprofile_files.o \
++ oprofilefs.o oprofile_stats.o \
++ timer_int.o )
++
++oprofile-y := $(DRIVER_OBJS) common.o
++oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
++oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
+diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/oprofile/common.c
+@@ -0,0 +1,195 @@
++/*
++ * PPC 64 oprofile support:
++ * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
++ * PPC 32 oprofile support: (based on PPC 64 support)
++ * Copyright (C) Freescale Semiconductor, Inc 2004
++ * Author: Andy Fleming
++ *
++ * Based on alpha version.
++ *
++ * 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/oprofile.h>
++#ifndef __powerpc64__
++#include <linux/slab.h>
++#endif /* ! __powerpc64__ */
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/errno.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++#include <asm/pmc.h>
++#include <asm/cputable.h>
++#include <asm/oprofile_impl.h>
++
++static struct op_powerpc_model *model;
++
++static struct op_counter_config ctr[OP_MAX_COUNTER];
++static struct op_system_config sys;
++
++#ifndef __powerpc64__
++static char *cpu_type;
++#endif /* ! __powerpc64__ */
++
++static void op_handle_interrupt(struct pt_regs *regs)
++{
++ model->handle_interrupt(regs, ctr);
++}
++
++static int op_powerpc_setup(void)
++{
++ int err;
++
++ /* Grab the hardware */
++ err = reserve_pmc_hardware(op_handle_interrupt);
++ if (err)
++ return err;
++
++ /* Pre-compute the values to stuff in the hardware registers. */
++ model->reg_setup(ctr, &sys, model->num_counters);
++
++ /* Configure the registers on all cpus. */
++#ifdef __powerpc64__
++ on_each_cpu(model->cpu_setup, NULL, 0, 1);
++#else /* __powerpc64__ */
++#if 0
++ /* FIXME: Make multi-cpu work */
++ on_each_cpu(model->reg_setup, NULL, 0, 1);
++#endif
++#endif /* __powerpc64__ */
++
++ return 0;
++}
++
++static void op_powerpc_shutdown(void)
++{
++ release_pmc_hardware();
++}
++
++static void op_powerpc_cpu_start(void *dummy)
++{
++ model->start(ctr);
++}
++
++static int op_powerpc_start(void)
++{
++ on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1);
++ return 0;
++}
++
++static inline void op_powerpc_cpu_stop(void *dummy)
++{
++ model->stop();
++}
++
++static void op_powerpc_stop(void)
++{
++ on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1);
++}
++
++static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
++{
++ int i;
++
++#ifdef __powerpc64__
++ /*
++ * There is one mmcr0, mmcr1 and mmcra for setting the events for
++ * all of the counters.
++ */
++ oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
++ oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
++ oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
++#endif /* __powerpc64__ */
++
++ for (i = 0; i < model->num_counters; ++i) {
++ struct dentry *dir;
++ char buf[3];
++
++ snprintf(buf, sizeof buf, "%d", i);
++ dir = oprofilefs_mkdir(sb, root, buf);
++
++ 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);
++#ifdef __powerpc64__
++ /*
++ * We dont support per counter user/kernel selection, but
++ * we leave the entries because userspace expects them
++ */
++#endif /* __powerpc64__ */
++ oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
++ oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
++
++#ifndef __powerpc64__
++ /* FIXME: Not sure if this is used */
++#endif /* ! __powerpc64__ */
++ oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
++ }
++
++ oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
++ oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
++#ifdef __powerpc64__
++ oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
++ &sys.backtrace_spinlocks);
++#endif /* __powerpc64__ */
++
++ /* Default to tracing both kernel and user */
++ sys.enable_kernel = 1;
++ sys.enable_user = 1;
++#ifdef __powerpc64__
++ /* Turn on backtracing through spinlocks by default */
++ sys.backtrace_spinlocks = 1;
++#endif /* __powerpc64__ */
++
++ return 0;
++}
++
++int __init oprofile_arch_init(struct oprofile_operations *ops)
++{
++#ifndef __powerpc64__
++#ifdef CONFIG_FSL_BOOKE
++ model = &op_model_fsl_booke;
++#else
++ return -ENODEV;
++#endif
++
++ cpu_type = kmalloc(32, GFP_KERNEL);
++ if (NULL == cpu_type)
++ return -ENOMEM;
++
++ sprintf(cpu_type, "ppc/%s", cur_cpu_spec->cpu_name);
++
++ model->num_counters = cur_cpu_spec->num_pmcs;
++
++ ops->cpu_type = cpu_type;
++#else /* __powerpc64__ */
++ if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type)
++ return -ENODEV;
++ model = cur_cpu_spec->oprofile_model;
++ model->num_counters = cur_cpu_spec->num_pmcs;
++
++ ops->cpu_type = cur_cpu_spec->oprofile_cpu_type;
++#endif /* __powerpc64__ */
++ ops->create_files = op_powerpc_create_files;
++ ops->setup = op_powerpc_setup;
++ ops->shutdown = op_powerpc_shutdown;
++ ops->start = op_powerpc_start;
++ ops->stop = op_powerpc_stop;
++
++ printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
++ ops->cpu_type);
++
++ return 0;
++}
++
++void oprofile_arch_exit(void)
++{
++#ifndef __powerpc64__
++ kfree(cpu_type);
++ cpu_type = NULL;
++#endif /* ! __powerpc64__ */
++}
+diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/oprofile/op_model_fsl_booke.c
+@@ -0,0 +1,183 @@
++/*
++ * oprofile/op_model_e500.c
++ *
++ * Freescale Book-E oprofile support, based on ppc64 oprofile support
++ * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * Copyright (c) 2004 Freescale Semiconductor, Inc
++ *
++ * Author: Andy Fleming
++ * Maintainer: Kumar Gala <Kumar.Gala at freescale.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/oprofile.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++#include <asm/processor.h>
++#include <asm/cputable.h>
++#include <asm/reg_booke.h>
++#include <asm/page.h>
++#include <asm/pmc.h>
++#include <asm/oprofile_impl.h>
++
++static unsigned long reset_value[OP_MAX_COUNTER];
++
++static int num_counters;
++static int oprofile_running;
++
++static inline unsigned int ctr_read(unsigned int i)
++{
++ switch(i) {
++ case 0:
++ return mfpmr(PMRN_PMC0);
++ case 1:
++ return mfpmr(PMRN_PMC1);
++ case 2:
++ return mfpmr(PMRN_PMC2);
++ case 3:
++ return mfpmr(PMRN_PMC3);
++ default:
++ return 0;
++ }
++}
++
++static inline void ctr_write(unsigned int i, unsigned int val)
++{
++ switch(i) {
++ case 0:
++ mtpmr(PMRN_PMC0, val);
++ break;
++ case 1:
++ mtpmr(PMRN_PMC1, val);
++ break;
++ case 2:
++ mtpmr(PMRN_PMC2, val);
++ break;
++ case 3:
++ mtpmr(PMRN_PMC3, val);
++ break;
++ default:
++ break;
++ }
++}
++
++
++static void fsl_booke_reg_setup(struct op_counter_config *ctr,
++ struct op_system_config *sys,
++ int num_ctrs)
++{
++ int i;
++
++ num_counters = num_ctrs;
++
++ /* freeze all counters */
++ pmc_stop_ctrs();
++
++ /* Our counters count up, and "count" refers to
++ * how much before the next interrupt, and we interrupt
++ * on overflow. So we calculate the starting value
++ * which will give us "count" until overflow.
++ * Then we set the events on the enabled counters */
++ for (i = 0; i < num_counters; ++i) {
++ reset_value[i] = 0x80000000UL - ctr[i].count;
++
++ init_pmc_stop(i);
++
++ set_pmc_event(i, ctr[i].event);
++
++ set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel);
++ }
++}
++
++static void fsl_booke_start(struct op_counter_config *ctr)
++{
++ int i;
++
++ mtmsr(mfmsr() | MSR_PMM);
++
++ for (i = 0; i < num_counters; ++i) {
++ if (ctr[i].enabled) {
++ ctr_write(i, reset_value[i]);
++ /* Set Each enabled counterd to only
++ * count when the Mark bit is not set */
++ set_pmc_marked(i, 1, 0);
++ pmc_start_ctr(i, 1);
++ } else {
++ ctr_write(i, 0);
++
++ /* Set the ctr to be stopped */
++ pmc_start_ctr(i, 0);
++ }
++ }
++
++ /* Clear the freeze bit, and enable the interrupt.
++ * The counters won't actually start until the rfi clears
++ * the PMM bit */
++ pmc_start_ctrs(1);
++
++ oprofile_running = 1;
++
++ pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(),
++ mfpmr(PMRN_PMGC0));
++}
++
++static void fsl_booke_stop(void)
++{
++ /* freeze counters */
++ pmc_stop_ctrs();
++
++ oprofile_running = 0;
++
++ pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(),
++ mfpmr(PMRN_PMGC0));
++
++ mb();
++}
++
++
++static void fsl_booke_handle_interrupt(struct pt_regs *regs,
++ struct op_counter_config *ctr)
++{
++ unsigned long pc;
++ int is_kernel;
++ int val;
++ int i;
++
++ /* set the PMM bit (see comment below) */
++ mtmsr(mfmsr() | MSR_PMM);
++
++ pc = regs->nip;
++ is_kernel = (pc >= KERNELBASE);
++
++ for (i = 0; i < num_counters; ++i) {
++ val = ctr_read(i);
++ if (val < 0) {
++ if (oprofile_running && ctr[i].enabled) {
++ oprofile_add_pc(pc, is_kernel, i);
++ ctr_write(i, reset_value[i]);
++ } else {
++ ctr_write(i, 0);
++ }
++ }
++ }
++
++ /* The freeze bit was set by the interrupt. */
++ /* Clear the freeze bit, and reenable the interrupt.
++ * The counters won't actually start until the rfi clears
++ * the PMM bit */
++ pmc_start_ctrs(1);
++}
++
++struct op_powerpc_model op_model_fsl_booke = {
++ .reg_setup = fsl_booke_reg_setup,
++ .start = fsl_booke_start,
++ .stop = fsl_booke_stop,
++ .handle_interrupt = fsl_booke_handle_interrupt,
++};
+diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/oprofile/op_model_power4.c
+@@ -0,0 +1,309 @@
++/*
++ * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * 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/oprofile.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++#include <asm/processor.h>
++#include <asm/cputable.h>
++#include <asm/systemcfg.h>
++#include <asm/rtas.h>
++#include <asm/oprofile_impl.h>
++
++#define dbg(args...)
++
++static unsigned long reset_value[OP_MAX_COUNTER];
++
++static int oprofile_running;
++static int mmcra_has_sihv;
++
++/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
++static u32 mmcr0_val;
++static u64 mmcr1_val;
++static u32 mmcra_val;
++
++/*
++ * Since we do not have an NMI, backtracing through spinlocks is
++ * only a best guess. In light of this, allow it to be disabled at
++ * runtime.
++ */
++static int backtrace_spinlocks;
++
++static void power4_reg_setup(struct op_counter_config *ctr,
++ struct op_system_config *sys,
++ int num_ctrs)
++{
++ int i;
++
++ /*
++ * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above.
++ * However we disable it on all POWER4 until we verify it works
++ * (I was seeing some strange behaviour last time I tried).
++ *
++ * It has been verified to work on POWER5 so we enable it there.
++ */
++ if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
++ mmcra_has_sihv = 1;
++
++ /*
++ * The performance counter event settings are given in the mmcr0,
++ * mmcr1 and mmcra values passed from the user in the
++ * op_system_config structure (sys variable).
++ */
++ mmcr0_val = sys->mmcr0;
++ mmcr1_val = sys->mmcr1;
++ mmcra_val = sys->mmcra;
++
++ backtrace_spinlocks = sys->backtrace_spinlocks;
++
++ for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
++ reset_value[i] = 0x80000000UL - ctr[i].count;
++
++ /* setup user and kernel profiling */
++ if (sys->enable_kernel)
++ mmcr0_val &= ~MMCR0_KERNEL_DISABLE;
++ else
++ mmcr0_val |= MMCR0_KERNEL_DISABLE;
++
++ if (sys->enable_user)
++ mmcr0_val &= ~MMCR0_PROBLEM_DISABLE;
++ else
++ mmcr0_val |= MMCR0_PROBLEM_DISABLE;
++}
++
++extern void ppc64_enable_pmcs(void);
++
++static void power4_cpu_setup(void *unused)
++{
++ unsigned int mmcr0 = mmcr0_val;
++ unsigned long mmcra = mmcra_val;
++
++ ppc64_enable_pmcs();
++
++ /* set the freeze bit */
++ mmcr0 |= MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
++ mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ mtspr(SPRN_MMCR1, mmcr1_val);
++
++ mmcra |= MMCRA_SAMPLE_ENABLE;
++ mtspr(SPRN_MMCRA, mmcra);
++
++ dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),
++ mfspr(SPRN_MMCR0));
++ dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(),
++ mfspr(SPRN_MMCR1));
++ dbg("setup on cpu %d, mmcra %lx\n", smp_processor_id(),
++ mfspr(SPRN_MMCRA));
++}
++
++static void power4_start(struct op_counter_config *ctr)
++{
++ int i;
++ unsigned int mmcr0;
++
++ /* set the PMM bit (see comment below) */
++ mtmsrd(mfmsr() | MSR_PMM);
++
++ for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
++ if (ctr[i].enabled) {
++ ctr_write(i, reset_value[i]);
++ } else {
++ ctr_write(i, 0);
++ }
++ }
++
++ mmcr0 = mfspr(SPRN_MMCR0);
++
++ /*
++ * We must clear the PMAO bit on some (GQ) chips. Just do it
++ * all the time
++ */
++ mmcr0 &= ~MMCR0_PMAO;
++
++ /*
++ * now clear the freeze bit, counting will not start until we
++ * rfid from this excetion, because only at that point will
++ * the PMM bit be cleared
++ */
++ mmcr0 &= ~MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ oprofile_running = 1;
++
++ dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
++}
++
++static void power4_stop(void)
++{
++ unsigned int mmcr0;
++
++ /* freeze counters */
++ mmcr0 = mfspr(SPRN_MMCR0);
++ mmcr0 |= MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ oprofile_running = 0;
++
++ dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
++
++ mb();
++}
++
++/* Fake functions used by canonicalize_pc */
++static void __attribute_used__ hypervisor_bucket(void)
++{
++}
++
++static void __attribute_used__ rtas_bucket(void)
++{
++}
++
++static void __attribute_used__ kernel_unknown_bucket(void)
++{
++}
++
++static unsigned long check_spinlock_pc(struct pt_regs *regs,
++ unsigned long profile_pc)
++{
++ unsigned long pc = instruction_pointer(regs);
++
++ /*
++ * If both the SIAR (sampled instruction) and the perfmon exception
++ * occurred in a spinlock region then we account the sample to the
++ * calling function. This isnt 100% correct, we really need soft
++ * IRQ disable so we always get the perfmon exception at the
++ * point at which the SIAR is set.
++ */
++ if (backtrace_spinlocks && in_lock_functions(pc) &&
++ in_lock_functions(profile_pc))
++ return regs->link;
++ else
++ return profile_pc;
++}
++
++/*
++ * On GQ and newer the MMCRA stores the HV and PR bits at the time
++ * the SIAR was sampled. We use that to work out if the SIAR was sampled in
++ * the hypervisor, our exception vectors or RTAS.
++ */
++static unsigned long get_pc(struct pt_regs *regs)
++{
++ unsigned long pc = mfspr(SPRN_SIAR);
++ unsigned long mmcra;
++
++ /* Cant do much about it */
++ if (!mmcra_has_sihv)
++ return check_spinlock_pc(regs, pc);
++
++ mmcra = mfspr(SPRN_MMCRA);
++
++ /* Were we in the hypervisor? */
++ if ((systemcfg->platform == PLATFORM_PSERIES_LPAR) &&
++ (mmcra & MMCRA_SIHV))
++ /* function descriptor madness */
++ return *((unsigned long *)hypervisor_bucket);
++
++ /* We were in userspace, nothing to do */
++ if (mmcra & MMCRA_SIPR)
++ return pc;
++
++#ifdef CONFIG_PPC_RTAS
++ /* Were we in RTAS? */
++ if (pc >= rtas.base && pc < (rtas.base + rtas.size))
++ /* function descriptor madness */
++ return *((unsigned long *)rtas_bucket);
++#endif
++
++ /* Were we in our exception vectors or SLB real mode miss handler? */
++ if (pc < 0x1000000UL)
++ return (unsigned long)__va(pc);
++
++ /* Not sure where we were */
++ if (pc < KERNELBASE)
++ /* function descriptor madness */
++ return *((unsigned long *)kernel_unknown_bucket);
++
++ return check_spinlock_pc(regs, pc);
++}
++
++static int get_kernel(unsigned long pc)
++{
++ int is_kernel;
++
++ if (!mmcra_has_sihv) {
++ is_kernel = (pc >= KERNELBASE);
++ } else {
++ unsigned long mmcra = mfspr(SPRN_MMCRA);
++ is_kernel = ((mmcra & MMCRA_SIPR) == 0);
++ }
++
++ return is_kernel;
++}
++
++static void power4_handle_interrupt(struct pt_regs *regs,
++ struct op_counter_config *ctr)
++{
++ unsigned long pc;
++ int is_kernel;
++ int val;
++ int i;
++ unsigned int mmcr0;
++
++ pc = get_pc(regs);
++ is_kernel = get_kernel(pc);
++
++ /* set the PMM bit (see comment below) */
++ mtmsrd(mfmsr() | MSR_PMM);
++
++ for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
++ val = ctr_read(i);
++ if (val < 0) {
++ if (oprofile_running && ctr[i].enabled) {
++ oprofile_add_pc(pc, is_kernel, i);
++ ctr_write(i, reset_value[i]);
++ } else {
++ ctr_write(i, 0);
++ }
++ }
++ }
++
++ mmcr0 = mfspr(SPRN_MMCR0);
++
++ /* reset the perfmon trigger */
++ mmcr0 |= MMCR0_PMXE;
++
++ /*
++ * We must clear the PMAO bit on some (GQ) chips. Just do it
++ * all the time
++ */
++ mmcr0 &= ~MMCR0_PMAO;
++
++ /*
++ * now clear the freeze bit, counting will not start until we
++ * rfid from this exception, because only at that point will
++ * the PMM bit be cleared
++ */
++ mmcr0 &= ~MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++}
++
++struct op_powerpc_model op_model_power4 = {
++ .reg_setup = power4_reg_setup,
++ .cpu_setup = power4_cpu_setup,
++ .start = power4_start,
++ .stop = power4_stop,
++ .handle_interrupt = power4_handle_interrupt,
++};
+diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/oprofile/op_model_rs64.c
+@@ -0,0 +1,218 @@
++/*
++ * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * 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/oprofile.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++#include <asm/processor.h>
++#include <asm/cputable.h>
++#include <asm/oprofile_impl.h>
++
++#define dbg(args...)
++
++static void ctrl_write(unsigned int i, unsigned int val)
++{
++ unsigned int tmp = 0;
++ unsigned long shift = 0, mask = 0;
++
++ dbg("ctrl_write %d %x\n", i, val);
++
++ switch(i) {
++ case 0:
++ tmp = mfspr(SPRN_MMCR0);
++ shift = 6;
++ mask = 0x7F;
++ break;
++ case 1:
++ tmp = mfspr(SPRN_MMCR0);
++ shift = 0;
++ mask = 0x3F;
++ break;
++ case 2:
++ tmp = mfspr(SPRN_MMCR1);
++ shift = 31 - 4;
++ mask = 0x1F;
++ break;
++ case 3:
++ tmp = mfspr(SPRN_MMCR1);
++ shift = 31 - 9;
++ mask = 0x1F;
++ break;
++ case 4:
++ tmp = mfspr(SPRN_MMCR1);
++ shift = 31 - 14;
++ mask = 0x1F;
++ break;
++ case 5:
++ tmp = mfspr(SPRN_MMCR1);
++ shift = 31 - 19;
++ mask = 0x1F;
++ break;
++ case 6:
++ tmp = mfspr(SPRN_MMCR1);
++ shift = 31 - 24;
++ mask = 0x1F;
++ break;
++ case 7:
++ tmp = mfspr(SPRN_MMCR1);
++ shift = 31 - 28;
++ mask = 0xF;
++ break;
++ }
++
++ tmp = tmp & ~(mask << shift);
++ tmp |= val << shift;
++
++ switch(i) {
++ case 0:
++ case 1:
++ mtspr(SPRN_MMCR0, tmp);
++ break;
++ default:
++ mtspr(SPRN_MMCR1, tmp);
++ }
++
++ dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0),
++ mfspr(SPRN_MMCR1));
++}
++
++static unsigned long reset_value[OP_MAX_COUNTER];
++
++static int num_counters;
++
++static void rs64_reg_setup(struct op_counter_config *ctr,
++ struct op_system_config *sys,
++ int num_ctrs)
++{
++ int i;
++
++ num_counters = num_ctrs;
++
++ for (i = 0; i < num_counters; ++i)
++ reset_value[i] = 0x80000000UL - ctr[i].count;
++
++ /* XXX setup user and kernel profiling */
++}
++
++static void rs64_cpu_setup(void *unused)
++{
++ unsigned int mmcr0;
++
++ /* reset MMCR0 and set the freeze bit */
++ mmcr0 = MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ /* reset MMCR1, MMCRA */
++ mtspr(SPRN_MMCR1, 0);
++
++ if (cpu_has_feature(CPU_FTR_MMCRA))
++ mtspr(SPRN_MMCRA, 0);
++
++ mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
++ /* Only applies to POWER3, but should be safe on RS64 */
++ mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),
++ mfspr(SPRN_MMCR0));
++ dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(),
++ mfspr(SPRN_MMCR1));
++}
++
++static void rs64_start(struct op_counter_config *ctr)
++{
++ int i;
++ unsigned int mmcr0;
++
++ /* set the PMM bit (see comment below) */
++ mtmsrd(mfmsr() | MSR_PMM);
++
++ for (i = 0; i < num_counters; ++i) {
++ if (ctr[i].enabled) {
++ ctr_write(i, reset_value[i]);
++ ctrl_write(i, ctr[i].event);
++ } else {
++ ctr_write(i, 0);
++ }
++ }
++
++ mmcr0 = mfspr(SPRN_MMCR0);
++
++ /*
++ * now clear the freeze bit, counting will not start until we
++ * rfid from this excetion, because only at that point will
++ * the PMM bit be cleared
++ */
++ mmcr0 &= ~MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
++}
++
++static void rs64_stop(void)
++{
++ unsigned int mmcr0;
++
++ /* freeze counters */
++ mmcr0 = mfspr(SPRN_MMCR0);
++ mmcr0 |= MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++
++ dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
++
++ mb();
++}
++
++static void rs64_handle_interrupt(struct pt_regs *regs,
++ struct op_counter_config *ctr)
++{
++ unsigned int mmcr0;
++ int val;
++ int i;
++ unsigned long pc = mfspr(SPRN_SIAR);
++ int is_kernel = (pc >= KERNELBASE);
++
++ /* set the PMM bit (see comment below) */
++ mtmsrd(mfmsr() | MSR_PMM);
++
++ for (i = 0; i < num_counters; ++i) {
++ val = ctr_read(i);
++ if (val < 0) {
++ if (ctr[i].enabled) {
++ oprofile_add_pc(pc, is_kernel, i);
++ ctr_write(i, reset_value[i]);
++ } else {
++ ctr_write(i, 0);
++ }
++ }
++ }
++
++ mmcr0 = mfspr(SPRN_MMCR0);
++
++ /* reset the perfmon trigger */
++ mmcr0 |= MMCR0_PMXE;
++
++ /*
++ * now clear the freeze bit, counting will not start until we
++ * rfid from this exception, because only at that point will
++ * the PMM bit be cleared
++ */
++ mmcr0 &= ~MMCR0_FC;
++ mtspr(SPRN_MMCR0, mmcr0);
++}
++
++struct op_powerpc_model op_model_rs64 = {
++ .reg_setup = rs64_reg_setup,
++ .cpu_setup = rs64_cpu_setup,
++ .start = rs64_start,
++ .stop = rs64_stop,
++ .handle_interrupt = rs64_handle_interrupt,
++};
+diff --git a/arch/powerpc/platforms/4xx/Kconfig b/arch/powerpc/platforms/4xx/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/4xx/Kconfig
+@@ -0,0 +1,280 @@
++config 4xx
++ bool
++ depends on 40x || 44x
++ default y
++
++config WANT_EARLY_SERIAL
++ bool
++ select SERIAL_8250
++ default n
++
++menu "AMCC 4xx options"
++ depends on 4xx
++
++choice
++ prompt "Machine Type"
++ depends on 40x
++ default WALNUT
++
++config BUBINGA
++ bool "Bubinga"
++ select WANT_EARLY_SERIAL
++ help
++ This option enables support for the IBM 405EP evaluation board.
++
++config CPCI405
++ bool "CPCI405"
++ help
++ This option enables support for the CPCI405 board.
++
++config EP405
++ bool "EP405/EP405PC"
++ help
++ This option enables support for the EP405/EP405PC boards.
++
++config REDWOOD_5
++ bool "Redwood-5"
++ help
++ This option enables support for the IBM STB04 evaluation board.
++
++config REDWOOD_6
++ bool "Redwood-6"
++ help
++ This option enables support for the IBM STBx25xx evaluation board.
++
++config SYCAMORE
++ bool "Sycamore"
++ help
++ This option enables support for the IBM PPC405GPr evaluation board.
++
++config WALNUT
++ bool "Walnut"
++ help
++ This option enables support for the IBM PPC405GP evaluation board.
++
++config XILINX_ML300
++ bool "Xilinx-ML300"
++ help
++ This option enables support for the Xilinx ML300 evaluation board.
++
++endchoice
++
++choice
++ prompt "Machine Type"
++ depends on 44x
++ default EBONY
++
++config BAMBOO
++ bool "Bamboo"
++ select WANT_EARLY_SERIAL
++ help
++ This option enables support for the IBM PPC440EP evaluation board.
++
++config EBONY
++ bool "Ebony"
++ select WANT_EARLY_SERIAL
++ help
++ This option enables support for the IBM PPC440GP evaluation board.
++
++config LUAN
++ bool "Luan"
++ select WANT_EARLY_SERIAL
++ help
++ This option enables support for the IBM PPC440SP evaluation board.
++
++config OCOTEA
++ bool "Ocotea"
++ select WANT_EARLY_SERIAL
++ help
++ This option enables support for the IBM PPC440GX evaluation board.
++
++endchoice
++
++config EP405PC
++ bool "EP405PC Support"
++ depends on EP405
++
++
++# It's often necessary to know the specific 4xx processor type.
++# Fortunately, it is impled (so far) from the board type, so we
++# don't need to ask more redundant questions.
++config NP405H
++ bool
++ depends on ASH
++ default y
++
++config 440EP
++ bool
++ depends on BAMBOO
++ select PPC_FPU
++ default y
++
++config 440GP
++ bool
++ depends on EBONY
++ default y
++
++config 440GX
++ bool
++ depends on OCOTEA
++ default y
++
++config 440SP
++ bool
++ depends on LUAN
++ default y
++
++config 440
++ bool
++ depends on 440GP || 440SP || 440EP
++ default y
++
++config 440A
++ bool
++ depends on 440GX
++ default y
++
++config IBM440EP_ERR42
++ bool
++ depends on 440EP
++ default y
++
++# All 405-based cores up until the 405GPR and 405EP have this errata.
++config IBM405_ERR77
++ bool
++ depends on 40x && !403GCX && !405GPR && !405EP
++ default y
++
++# All 40x-based cores, up until the 405GPR and 405EP have this errata.
++config IBM405_ERR51
++ bool
++ depends on 40x && !405GPR && !405EP
++ default y
++
++config BOOKE
++ bool
++ depends on 44x
++ default y
++
++config IBM_OCP
++ bool
++ depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
++ default y
++
++config XILINX_OCP
++ bool
++ depends on XILINX_ML300
++ default y
++
++config IBM_EMAC4
++ bool
++ depends on 440GX || 440SP
++ default y
++
++config BIOS_FIXUP
++ bool
++ depends on BUBINGA || EP405 || SYCAMORE || WALNUT
++ default y
++
++# OAK doesn't exist but wanted to keep this around for any future 403GCX boards
++config 403GCX
++ bool
++ depends OAK
++ default y
++
++config 405EP
++ bool
++ depends on BUBINGA
++ default y
++
++config 405GP
++ bool
++ depends on CPCI405 || EP405 || WALNUT
++ default y
++
++config 405GPR
++ bool
++ depends on SYCAMORE
++ default y
++
++config VIRTEX_II_PRO
++ bool
++ depends on XILINX_ML300
++ default y
++
++config STB03xxx
++ bool
++ depends on REDWOOD_5 || REDWOOD_6
++ default y
++
++config EMBEDDEDBOOT
++ bool
++ depends on EP405 || XILINX_ML300
++ default y
++
++config IBM_OPENBIOS
++ bool
++ depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
++ default y
++
++config PPC4xx_DMA
++ bool "PPC4xx DMA controller support"
++ depends on 4xx
++
++config PPC4xx_EDMA
++ bool
++ depends on !STB03xxx && PPC4xx_DMA
++ default y
++
++config PPC_GEN550
++ bool
++ depends on 4xx
++ default y
++
++choice
++ prompt "TTYS0 device and default console"
++ depends on 40x
++ default UART0_TTYS0
++
++config UART0_TTYS0
++ bool "UART0"
++
++config UART0_TTYS1
++ bool "UART1"
++
++endchoice
++
++config SERIAL_SICC
++ bool "SICC Serial port support"
++ depends on STB03xxx
++
++config UART1_DFLT_CONSOLE
++ bool
++ depends on SERIAL_SICC && UART0_TTYS1
++ default y
++
++config SERIAL_SICC_CONSOLE
++ bool
++ depends on SERIAL_SICC && UART0_TTYS1
++ default y
++endmenu
++
++
++menu "IBM 40x options"
++ depends on 40x
++
++config SERIAL_SICC
++ bool "SICC Serial port"
++ depends on STB03xxx
++
++config UART1_DFLT_CONSOLE
++ bool
++ depends on SERIAL_SICC && UART0_TTYS1
++ default y
++
++config SERIAL_SICC_CONSOLE
++ bool
++ depends on SERIAL_SICC && UART0_TTYS1
++ default y
++
++endmenu
+diff --git a/arch/powerpc/platforms/4xx/Makefile b/arch/powerpc/platforms/4xx/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/4xx/Makefile
+@@ -0,0 +1 @@
++# empty makefile so make clean works
+\ No newline at end of file
+diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/85xx/Kconfig
+@@ -0,0 +1,86 @@
++config 85xx
++ bool
++ depends on E500
++ default y
++
++config PPC_INDIRECT_PCI_BE
++ bool
++ depends on 85xx
++ default y
++
++menu "Freescale 85xx options"
++ depends on E500
++
++choice
++ prompt "Machine Type"
++ depends on 85xx
++ default MPC8540_ADS
++
++config MPC8540_ADS
++ bool "Freescale MPC8540 ADS"
++ help
++ This option enables support for the MPC 8540 ADS evaluation board.
++
++config MPC8548_CDS
++ bool "Freescale MPC8548 CDS"
++ help
++ This option enablese support for the MPC8548 CDS evaluation board.
++
++config MPC8555_CDS
++ bool "Freescale MPC8555 CDS"
++ help
++ This option enablese support for the MPC8555 CDS evaluation board.
++
++config MPC8560_ADS
++ bool "Freescale MPC8560 ADS"
++ help
++ This option enables support for the MPC 8560 ADS evaluation board.
++
++config SBC8560
++ bool "WindRiver PowerQUICC III SBC8560"
++ help
++ This option enables support for the WindRiver PowerQUICC III
++ SBC8560 board.
++
++config STX_GP3
++ bool "Silicon Turnkey Express GP3"
++ help
++ This option enables support for the Silicon Turnkey Express GP3
++ board.
++
++endchoice
++
++# It's often necessary to know the specific 85xx processor type.
++# Fortunately, it is implied (so far) from the board type, so we
++# don't need to ask more redundant questions.
++config MPC8540
++ bool
++ depends on MPC8540_ADS
++ default y
++
++config MPC8548
++ bool
++ depends on MPC8548_CDS
++ default y
++
++config MPC8555
++ bool
++ depends on MPC8555_CDS
++ default y
++
++config MPC8560
++ bool
++ depends on SBC8560 || MPC8560_ADS || STX_GP3
++ default y
++
++config 85xx_PCI2
++ bool "Supprt for 2nd PCI host controller"
++ depends on MPC8555_CDS
++ default y
++
++config PPC_GEN550
++ bool
++ depends on MPC8540 || SBC8560 || MPC8555
++ default y
++
++endmenu
+diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/85xx/Makefile
+@@ -0,0 +1 @@
++# empty makefile so make clean works
+diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/8xx/Kconfig
+@@ -0,0 +1,352 @@
++config FADS
++ bool
++
++choice
++ prompt "8xx Machine Type"
++ depends on 8xx
++ default RPXLITE
++
++config RPXLITE
++ bool "RPX-Lite"
++ ---help---
++ Single-board computers based around the PowerPC MPC8xx chips and
++ intended for embedded applications. The following types are
++ supported:
++
++ RPX-Lite:
++ Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
++
++ RPX-Classic:
++ Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on
++ the MPC 860
++
++ BSE-IP:
++ Bright Star Engineering ip-Engine.
++
++ TQM823L:
++ TQM850L:
++ TQM855L:
++ TQM860L:
++ MPC8xx based family of mini modules, half credit card size,
++ up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
++ 2 x CAN bus interface, ...
++ Manufacturer: TQ Components, www.tq-group.de
++ Date of Release: October (?) 1999
++ End of Life: not yet :-)
++ URL:
++ - module: <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>
++ - starter kit: <http://www.denx.de/PDF/STK8xxLHWM201.pdf>
++ - images: <http://www.denx.de/embedded-ppc-en.html>
++
++ FPS850L:
++ FingerPrint Sensor System (based on TQM850L)
++ Manufacturer: IKENDI AG, <http://www.ikendi.com/>
++ Date of Release: November 1999
++ End of life: end 2000 ?
++ URL: see TQM850L
++
++ IVMS8:
++ MPC860 based board used in the "Integrated Voice Mail System",
++ Small Version (8 voice channels)
++ Manufacturer: Speech Design, <http://www.speech-design.de/>
++ Date of Release: December 2000 (?)
++ End of life: -
++ URL: <http://www.speech-design.de/>
++
++ IVML24:
++ MPC860 based board used in the "Integrated Voice Mail System",
++ Large Version (24 voice channels)
++ Manufacturer: Speech Design, <http://www.speech-design.de/>
++ Date of Release: March 2001 (?)
++ End of life: -
++ URL: <http://www.speech-design.de/>
++
++ HERMES:
++ Hermes-Pro ISDN/LAN router with integrated 8 x hub
++ Manufacturer: Multidata Gesellschaft fur Datentechnik und Informatik
++ <http://www.multidata.de/>
++ Date of Release: 2000 (?)
++ End of life: -
++ URL: <http://www.multidata.de/english/products/hpro.htm>
++
++ IP860:
++ VMEBus IP (Industry Pack) carrier board with MPC860
++ Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
++ Date of Release: ?
++ End of life: -
++ URL: <http://www.microsys.de/html/ip860.html>
++
++ PCU_E:
++ PCU = Peripheral Controller Unit, Extended
++ Manufacturer: Siemens AG, ICN (Information and Communication Networks)
++ <http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
++ Date of Release: April 2001
++ End of life: August 2001
++ URL: n. a.
++
++config RPXCLASSIC
++ bool "RPX-Classic"
++ help
++ The RPX-Classic is a single-board computer based on the Motorola
++ MPC860. It features 16MB of DRAM and a variable amount of flash,
++ I2C EEPROM, thermal monitoring, a PCMCIA slot, a DIP switch and two
++ LEDs. Variants with Ethernet ports exist. Say Y here to support it
++ directly.
++
++config BSEIP
++ bool "BSE-IP"
++ help
++ Say Y here to support the Bright Star Engineering ipEngine SBC.
++ This is a credit-card-sized device featuring a MPC823 processor,
++ 26MB DRAM, 4MB flash, Ethernet, a 16K-gate FPGA, USB, an LCD/video
++ controller, and two RS232 ports.
++
++config MPC8XXFADS
++ bool "FADS"
++ select FADS
++
++config MPC86XADS
++ bool "MPC86XADS"
++ help
++ MPC86x Application Development System by Freescale Semiconductor.
++ The MPC86xADS is meant to serve as a platform for s/w and h/w
++ development around the MPC86X processor families.
++ select FADS
++
++config MPC885ADS
++ bool "MPC885ADS"
++ help
++ Freescale Semiconductor MPC885 Application Development System (ADS).
++ Also known as DUET.
++ The MPC885ADS is meant to serve as a platform for s/w and h/w
++ development around the MPC885 processor family.
++
++config TQM823L
++ bool "TQM823L"
++ help
++ Say Y here to support the TQM823L, one of an MPC8xx-based family of
++ mini SBCs (half credit-card size) from TQ Components first released
++ in late 1999. Technical references are at
++ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
++ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
++ <http://www.denx.de/embedded-ppc-en.html>.
++
++config TQM850L
++ bool "TQM850L"
++ help
++ Say Y here to support the TQM850L, one of an MPC8xx-based family of
++ mini SBCs (half credit-card size) from TQ Components first released
++ in late 1999. Technical references are at
++ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
++ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
++ <http://www.denx.de/embedded-ppc-en.html>.
++
++config TQM855L
++ bool "TQM855L"
++ help
++ Say Y here to support the TQM855L, one of an MPC8xx-based family of
++ mini SBCs (half credit-card size) from TQ Components first released
++ in late 1999. Technical references are at
++ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
++ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
++ <http://www.denx.de/embedded-ppc-en.html>.
++
++config TQM860L
++ bool "TQM860L"
++ help
++ Say Y here to support the TQM860L, one of an MPC8xx-based family of
++ mini SBCs (half credit-card size) from TQ Components first released
++ in late 1999. Technical references are at
++ <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
++ <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
++ <http://www.denx.de/embedded-ppc-en.html>.
++
++config FPS850L
++ bool "FPS850L"
++
++config IVMS8
++ bool "IVMS8"
++ help
++ Say Y here to support the Integrated Voice-Mail Small 8-channel SBC
++ from Speech Design, released March 2001. The manufacturer's website
++ is at <http://www.speech-design.de/>.
++
++config IVML24
++ bool "IVML24"
++ help
++ Say Y here to support the Integrated Voice-Mail Large 24-channel SBC
++ from Speech Design, released March 2001. The manufacturer's website
++ is at <http://www.speech-design.de/>.
++
++config HERMES_PRO
++ bool "HERMES"
++
++config IP860
++ bool "IP860"
++
++config LWMON
++ bool "LWMON"
++
++config PCU_E
++ bool "PCU_E"
++
++config CCM
++ bool "CCM"
++
++config LANTEC
++ bool "LANTEC"
++
++config MBX
++ bool "MBX"
++ help
++ MBX is a line of Motorola single-board computer based around the
++ MPC821 and MPC860 processors, and intended for embedded-controller
++ applications. Say Y here to support these boards directly.
++
++config WINCEPT
++ bool "WinCept"
++ help
++ The Wincept 100/110 is a Motorola single-board computer based on the
++ MPC821 PowerPC, introduced in 1998 and designed to be used in
++ thin-client machines. Say Y to support it directly.
++
++endchoice
++
++#
++# MPC8xx Communication options
++#
++
++menu "MPC8xx CPM Options"
++ depends on 8xx
++
++config SCC_ENET
++ bool "CPM SCC Ethernet"
++ depends on NET_ETHERNET
++ help
++ Enable Ethernet support via the Motorola MPC8xx serial
++ communications controller.
++
++choice
++ prompt "SCC used for Ethernet"
++ depends on SCC_ENET
++ default SCC1_ENET
++
++config SCC1_ENET
++ bool "SCC1"
++ help
++ Use MPC8xx serial communications controller 1 to drive Ethernet
++ (default).
++
++config SCC2_ENET
++ bool "SCC2"
++ help
++ Use MPC8xx serial communications controller 2 to drive Ethernet.
++
++config SCC3_ENET
++ bool "SCC3"
++ help
++ Use MPC8xx serial communications controller 3 to drive Ethernet.
++
++endchoice
++
++config FEC_ENET
++ bool "860T FEC Ethernet"
++ depends on NET_ETHERNET
++ help
++ Enable Ethernet support via the Fast Ethernet Controller (FCC) on
++ the Motorola MPC8260.
++
++config USE_MDIO
++ bool "Use MDIO for PHY configuration"
++ depends on FEC_ENET
++ help
++ On some boards the hardware configuration of the ethernet PHY can be
++ used without any software interaction over the MDIO interface, so
++ all MII code can be omitted. Say N here if unsure or if you don't
++ need link status reports.
++
++config FEC_AM79C874
++ bool "Support AMD79C874 PHY"
++ depends on USE_MDIO
++
++config FEC_LXT970
++ bool "Support LXT970 PHY"
++ depends on USE_MDIO
++
++config FEC_LXT971
++ bool "Support LXT971 PHY"
++ depends on USE_MDIO
++
++config FEC_QS6612
++ bool "Support QS6612 PHY"
++ depends on USE_MDIO
++
++config ENET_BIG_BUFFERS
++ bool "Use Big CPM Ethernet Buffers"
++ depends on SCC_ENET || FEC_ENET
++ help
++ Allocate large buffers for MPC8xx Ethernet. Increases throughput
++ and decreases the likelihood of dropped packets, but costs memory.
++
++config HTDMSOUND
++ bool "Embedded Planet HIOX Audio"
++ depends on SOUND=y
++
++# This doesn't really belong here, but it is convenient to ask
++# 8xx specific questions.
++comment "Generic MPC8xx Options"
++
++config 8xx_COPYBACK
++ bool "Copy-Back Data Cache (else Writethrough)"
++ help
++ Saying Y here will cause the cache on an MPC8xx processor to be used
++ in Copy-Back mode. If you say N here, it is used in Writethrough
++ mode.
++
++ If in doubt, say Y here.
++
++config 8xx_CPU6
++ bool "CPU6 Silicon Errata (860 Pre Rev. C)"
++ help
++ MPC860 CPUs, prior to Rev C have some bugs in the silicon, which
++ require workarounds for Linux (and most other OSes to work). If you
++ get a BUG() very early in boot, this might fix the problem. For
++ more details read the document entitled "MPC860 Family Device Errata
++ Reference" on Motorola's website. This option also incurs a
++ performance hit.
++
++ If in doubt, say N here.
++
++choice
++ prompt "Microcode patch selection"
++ default NO_UCODE_PATCH
++ help
++ Help not implemented yet, coming soon.
++
++config NO_UCODE_PATCH
++ bool "None"
++
++config USB_SOF_UCODE_PATCH
++ bool "USB SOF patch"
++ help
++ Help not implemented yet, coming soon.
++
++config I2C_SPI_UCODE_PATCH
++ bool "I2C/SPI relocation patch"
++ help
++ Help not implemented yet, coming soon.
++
++config I2C_SPI_SMC1_UCODE_PATCH
++ bool "I2C/SPI/SMC1 relocation patch"
++ help
++ Help not implemented yet, coming soon.
++
++endchoice
++
++config UCODE_PATCH
++ bool
++ default y
++ depends on !NO_UCODE_PATCH
++
++endmenu
++
+diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/Makefile
+@@ -0,0 +1,13 @@
++ifeq ($(CONFIG_PPC_MERGE),y)
++obj-$(CONFIG_PPC_PMAC) += powermac/
++else
++ifeq ($(CONFIG_PPC64),y)
++obj-$(CONFIG_PPC_PMAC) += powermac/
++endif
++endif
++obj-$(CONFIG_PPC_CHRP) += chrp/
++obj-$(CONFIG_4xx) += 4xx/
++obj-$(CONFIG_85xx) += 85xx/
++obj-$(CONFIG_PPC_PSERIES) += pseries/
++obj-$(CONFIG_PPC_ISERIES) += iseries/
++obj-$(CONFIG_PPC_MAPLE) += maple/
+diff --git a/arch/powerpc/platforms/apus/Kconfig b/arch/powerpc/platforms/apus/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/apus/Kconfig
+@@ -0,0 +1,130 @@
++
++config AMIGA
++ bool
++ depends on APUS
++ default y
++ help
++ This option enables support for the Amiga series of computers.
++
++config ZORRO
++ bool
++ depends on APUS
++ default y
++ help
++ This enables support for the Zorro bus in the Amiga. If you have
++ expansion cards in your Amiga that conform to the Amiga
++ AutoConfig(tm) specification, say Y, otherwise N. Note that even
++ expansion cards that do not fit in the Zorro slots but fit in e.g.
++ the CPU slot may fall in this category, so you have to say Y to let
++ Linux use these.
++
++config ABSTRACT_CONSOLE
++ bool
++ depends on APUS
++ default y
++
++config APUS_FAST_EXCEPT
++ bool
++ depends on APUS
++ default y
++
++config AMIGA_PCMCIA
++ bool "Amiga 1200/600 PCMCIA support"
++ depends on APUS && EXPERIMENTAL
++ help
++ 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 AMIGA_BUILTIN_SERIAL
++ tristate "Amiga builtin serial support"
++ depends on APUS
++ help
++ If you want to use your Amiga's built-in serial port in Linux,
++ answer Y.
++
++ To compile this driver as a module, choose M here.
++
++config GVPIOEXT
++ tristate "GVP IO-Extender support"
++ depends on APUS
++ help
++ If you want to use a GVP IO-Extender serial card in Linux, say Y.
++ Otherwise, say N.
++
++config GVPIOEXT_LP
++ tristate "GVP IO-Extender parallel printer support"
++ depends on GVPIOEXT
++ help
++ Say Y to enable driving a printer from the parallel port on your
++ GVP IO-Extender card, N otherwise.
++
++config GVPIOEXT_PLIP
++ tristate "GVP IO-Extender PLIP support"
++ depends on GVPIOEXT
++ help
++ Say Y to enable doing IP over the parallel port on your GVP
++ IO-Extender card, N otherwise.
++
++config MULTIFACE_III_TTY
++ tristate "Multiface Card III serial support"
++ depends on APUS
++ help
++ If you want to use a Multiface III card's serial port in Linux,
++ answer Y.
++
++ To compile this driver as a module, choose M here.
++
++config A2232
++ tristate "Commodore A2232 serial support (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && APUS
++ ---help---
++ This option supports the 2232 7-port serial card shipped with the
++ Amiga 2000 and other Zorro-bus machines, dating from 1989. At
++ a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
++ each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
++ ports were connected with 8 pin DIN connectors on the card bracket,
++ for which 8 pin to DB25 adapters were supplied. The card also had
++ jumpers internally to toggle various pinning configurations.
++
++ This driver can be built as a module; but then "generic_serial"
++ will also be built as a module. This has to be loaded before
++ "ser_a2232". If you want to do this, answer M here.
++
++config WHIPPET_SERIAL
++ tristate "Hisoft Whippet PCMCIA serial support"
++ depends on AMIGA_PCMCIA
++ help
++ HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
++ is no listing for the Whippet in their Amiga section.
++
++config APNE
++ tristate "PCMCIA NE2000 support"
++ depends on AMIGA_PCMCIA
++ help
++ If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
++ say N.
++
++ To compile this driver as a module, choose M here: the
++ module will be called apne.
++
++config SERIAL_CONSOLE
++ bool "Support for serial port console"
++ depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y)
++
++config HEARTBEAT
++ bool "Use power LED as a heartbeat"
++ depends on APUS
++ help
++ Use the power-on LED on your machine as a load meter. The exact
++ behavior is platform-dependent, but normally the flash frequency is
++ a hyperbolic function of the 5-minute load average.
++
++config PROC_HARDWARE
++ bool "/proc/hardware support"
++ depends on APUS
++
++source "drivers/zorro/Kconfig"
++
++config PCI_PERMEDIA
++ bool "PCI for Permedia2"
++ depends on !4xx && !8xx && APUS
+diff --git a/arch/powerpc/platforms/chrp/Makefile b/arch/powerpc/platforms/chrp/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/Makefile
+@@ -0,0 +1,4 @@
++obj-y += setup.o time.o pegasos_eth.o
++obj-$(CONFIG_PCI) += pci.o
++obj-$(CONFIG_SMP) += smp.o
++obj-$(CONFIG_NVRAM) += nvram.o
+diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/chrp.h
+@@ -0,0 +1,12 @@
++/*
++ * Declarations of CHRP platform-specific things.
++ */
++
++extern void chrp_nvram_init(void);
++extern void chrp_get_rtc_time(struct rtc_time *);
++extern int chrp_set_rtc_time(struct rtc_time *);
++extern void chrp_calibrate_decr(void);
++extern long chrp_time_init(void);
++
++extern void chrp_find_bridges(void);
++extern void chrp_event_scan(void);
+diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/nvram.c
+@@ -0,0 +1,84 @@
++/*
++ * c 2001 PPC 64 Team, IBM Corp
++ *
++ * 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.
++ *
++ * /dev/nvram driver for PPC
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <asm/uaccess.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include "chrp.h"
++
++static unsigned int nvram_size;
++static unsigned char nvram_buf[4];
++static DEFINE_SPINLOCK(nvram_lock);
++
++static unsigned char chrp_nvram_read(int addr)
++{
++ unsigned long done, flags;
++ unsigned char ret;
++
++ if (addr >= nvram_size) {
++ printk(KERN_DEBUG "%s: read addr %d > nvram_size %u\n",
++ current->comm, addr, nvram_size);
++ return 0xff;
++ }
++ spin_lock_irqsave(&nvram_lock, flags);
++ if ((call_rtas("nvram-fetch", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
++ ret = 0xff;
++ else
++ ret = nvram_buf[0];
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ return ret;
++}
++
++static void chrp_nvram_write(int addr, unsigned char val)
++{
++ unsigned long done, flags;
++
++ if (addr >= nvram_size) {
++ printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n",
++ current->comm, addr, nvram_size);
++ return;
++ }
++ spin_lock_irqsave(&nvram_lock, flags);
++ nvram_buf[0] = val;
++ if ((call_rtas("nvram-store", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
++ printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr);
++ spin_unlock_irqrestore(&nvram_lock, flags);
++}
++
++void __init chrp_nvram_init(void)
++{
++ struct device_node *nvram;
++ unsigned int *nbytes_p, proplen;
++
++ nvram = of_find_node_by_type(NULL, "nvram");
++ if (nvram == NULL)
++ return;
++
++ nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
++ if (nbytes_p == NULL || proplen != sizeof(unsigned int))
++ return;
++
++ nvram_size = *nbytes_p;
++
++ printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size);
++ of_node_put(nvram);
++
++ ppc_md.nvram_read_val = chrp_nvram_read;
++ ppc_md.nvram_write_val = chrp_nvram_write;
++
++ return;
++}
+diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/pci.c
+@@ -0,0 +1,310 @@
++/*
++ * CHRP pci routines.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/ide.h>
++
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/irq.h>
++#include <asm/hydra.h>
++#include <asm/prom.h>
++#include <asm/gg2.h>
++#include <asm/machdep.h>
++#include <asm/sections.h>
++#include <asm/pci-bridge.h>
++#include <asm/open_pic.h>
++#include <asm/grackle.h>
++#include <asm/rtas.h>
++
++/* LongTrail */
++void __iomem *gg2_pci_config_base;
++
++/*
++ * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
++ * limit the bus number to 3 bits
++ */
++
++int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
++ int len, u32 *val)
++{
++ volatile void __iomem *cfg_data;
++ struct pci_controller *hose = bus->sysdata;
++
++ if (bus->number > 7)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ /*
++ * Note: the caller has already checked that off is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
++ switch (len) {
++ case 1:
++ *val = in_8(cfg_data);
++ break;
++ case 2:
++ *val = in_le16(cfg_data);
++ break;
++ default:
++ *val = in_le32(cfg_data);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
++ int len, u32 val)
++{
++ volatile void __iomem *cfg_data;
++ struct pci_controller *hose = bus->sysdata;
++
++ if (bus->number > 7)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ /*
++ * Note: the caller has already checked that off is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
++ switch (len) {
++ case 1:
++ out_8(cfg_data, val);
++ break;
++ case 2:
++ out_le16(cfg_data, val);
++ break;
++ default:
++ out_le32(cfg_data, val);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops gg2_pci_ops =
++{
++ gg2_read_config,
++ gg2_write_config
++};
++
++/*
++ * Access functions for PCI config space using RTAS calls.
++ */
++int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
++ int len, u32 *val)
++{
++ struct pci_controller *hose = bus->sysdata;
++ unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
++ | (((bus->number - hose->first_busno) & 0xff) << 16)
++ | (hose->index << 24);
++ int ret = -1;
++ int rval;
++
++ rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
++ *val = ret;
++ return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
++}
++
++int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
++ int len, u32 val)
++{
++ struct pci_controller *hose = bus->sysdata;
++ unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
++ | (((bus->number - hose->first_busno) & 0xff) << 16)
++ | (hose->index << 24);
++ int rval;
++
++ rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
++ addr, len, val);
++ return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops rtas_pci_ops =
++{
++ rtas_read_config,
++ rtas_write_config
++};
++
++volatile struct Hydra __iomem *Hydra = NULL;
++
++int __init
++hydra_init(void)
++{
++ struct device_node *np;
++
++ np = find_devices("mac-io");
++ if (np == NULL || np->n_addrs == 0)
++ return 0;
++ Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
++ printk("Hydra Mac I/O at %lx\n", np->addrs[0].address);
++ printk("Hydra Feature_Control was %x",
++ in_le32(&Hydra->Feature_Control));
++ out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
++ HYDRA_FC_SCSI_CELL_EN |
++ HYDRA_FC_SCCA_ENABLE |
++ HYDRA_FC_SCCB_ENABLE |
++ HYDRA_FC_ARB_BYPASS |
++ HYDRA_FC_MPIC_ENABLE |
++ HYDRA_FC_SLOW_SCC_PCLK |
++ HYDRA_FC_MPIC_IS_MASTER));
++ printk(", now %x\n", in_le32(&Hydra->Feature_Control));
++ return 1;
++}
++
++void __init
++chrp_pcibios_fixup(void)
++{
++ struct pci_dev *dev = NULL;
++ struct device_node *np;
++
++ /* PCI interrupts are controlled by the OpenPIC */
++ for_each_pci_dev(dev) {
++ np = pci_device_to_OF_node(dev);
++ if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
++ dev->irq = np->intrs[0].line;
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++ }
++}
++
++#define PRG_CL_RESET_VALID 0x00010000
++
++static void __init
++setup_python(struct pci_controller *hose, struct device_node *dev)
++{
++ u32 __iomem *reg;
++ u32 val;
++ unsigned long addr = dev->addrs[0].address;
++
++ setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
++
++ /* Clear the magic go-slow bit */
++ reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
++ val = in_be32(®[12]);
++ if (val & PRG_CL_RESET_VALID) {
++ out_be32(®[12], val & ~PRG_CL_RESET_VALID);
++ in_be32(®[12]);
++ }
++ iounmap(reg);
++}
++
++/* Marvell Discovery II based Pegasos 2 */
++static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
++{
++ struct device_node *root = find_path_device("/");
++ struct device_node *rtas;
++
++ rtas = of_find_node_by_name (root, "rtas");
++ if (rtas) {
++ hose->ops = &rtas_pci_ops;
++ } else {
++ printk ("RTAS supporting Pegasos OF not found, please upgrade"
++ " your firmware\n");
++ }
++ pci_assign_all_buses = 1;
++}
++
++void __init
++chrp_find_bridges(void)
++{
++ struct device_node *dev;
++ int *bus_range;
++ int len, index = -1;
++ struct pci_controller *hose;
++ unsigned int *dma;
++ char *model, *machine;
++ int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
++ struct device_node *root = find_path_device("/");
++
++ /*
++ * The PCI host bridge nodes on some machines don't have
++ * properties to adequately identify them, so we have to
++ * look at what sort of machine this is as well.
++ */
++ machine = get_property(root, "model", NULL);
++ if (machine != NULL) {
++ is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
++ is_mot = strncmp(machine, "MOT", 3) == 0;
++ if (strncmp(machine, "Pegasos2", 8) == 0)
++ is_pegasos = 2;
++ else if (strncmp(machine, "Pegasos", 7) == 0)
++ is_pegasos = 1;
++ }
++ for (dev = root->child; dev != NULL; dev = dev->sibling) {
++ if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
++ continue;
++ ++index;
++ /* The GG2 bridge on the LongTrail doesn't have an address */
++ if (dev->n_addrs < 1 && !is_longtrail) {
++ printk(KERN_WARNING "Can't use %s: no address\n",
++ dev->full_name);
++ continue;
++ }
++ bus_range = (int *) get_property(dev, "bus-range", &len);
++ if (bus_range == NULL || len < 2 * sizeof(int)) {
++ printk(KERN_WARNING "Can't get bus-range for %s\n",
++ dev->full_name);
++ continue;
++ }
++ if (bus_range[1] == bus_range[0])
++ printk(KERN_INFO "PCI bus %d", bus_range[0]);
++ else
++ printk(KERN_INFO "PCI buses %d..%d",
++ bus_range[0], bus_range[1]);
++ printk(" controlled by %s", dev->type);
++ if (dev->n_addrs > 0)
++ printk(" at %lx", dev->addrs[0].address);
++ printk("\n");
++
++ hose = pcibios_alloc_controller();
++ if (!hose) {
++ printk("Can't allocate PCI controller structure for %s\n",
++ dev->full_name);
++ continue;
++ }
++ hose->arch_data = dev;
++ hose->first_busno = bus_range[0];
++ hose->last_busno = bus_range[1];
++
++ model = get_property(dev, "model", NULL);
++ if (model == NULL)
++ model = "<none>";
++ if (device_is_compatible(dev, "IBM,python")) {
++ setup_python(hose, dev);
++ } else if (is_mot
++ || strncmp(model, "Motorola, Grackle", 17) == 0) {
++ setup_grackle(hose);
++ } else if (is_longtrail) {
++ void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
++ hose->ops = &gg2_pci_ops;
++ hose->cfg_data = p;
++ gg2_pci_config_base = p;
++ } else if (is_pegasos == 1) {
++ setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc);
++ } else if (is_pegasos == 2) {
++ setup_peg2(hose, dev);
++ } else {
++ printk("No methods for %s (model %s), using RTAS\n",
++ dev->full_name, model);
++ hose->ops = &rtas_pci_ops;
++ }
++
++ pci_process_bridge_OF_ranges(hose, dev, index == 0);
++
++ /* check the first bridge for a property that we can
++ use to set pci_dram_offset */
++ dma = (unsigned int *)
++ get_property(dev, "ibm,dma-ranges", &len);
++ if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
++ pci_dram_offset = dma[2] - dma[3];
++ printk("pci_dram_offset = %lx\n", pci_dram_offset);
++ }
++ }
++
++ /* Do not fixup interrupts from OF tree on pegasos */
++ if (is_pegasos == 0)
++ ppc_md.pcibios_fixup = chrp_pcibios_fixup;
++}
+diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
+@@ -0,0 +1,213 @@
++/*
++ * arch/ppc/platforms/chrp_pegasos_eth.c
++ *
++ * Copyright (C) 2005 Sven Luther <sl at bplan-gmbh.de>
++ * Thanks to :
++ * Dale Farnsworth <dale at farnsworth.org>
++ * Mark A. Greer <mgreer at mvista.com>
++ * Nicolas DET <nd at bplan-gmbh.de>
++ * Benjamin Herrenschmidt <benh at kernel.crashing.org>
++ * And anyone else who helped me on this.
++ */
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mv643xx.h>
++#include <linux/pci.h>
++
++#define PEGASOS2_MARVELL_REGBASE (0xf1000000)
++#define PEGASOS2_MARVELL_REGSIZE (0x00004000)
++#define PEGASOS2_SRAM_BASE (0xf2000000)
++#define PEGASOS2_SRAM_SIZE (256*1024)
++
++#define PEGASOS2_SRAM_BASE_ETH0 (PEGASOS2_SRAM_BASE)
++#define PEGASOS2_SRAM_BASE_ETH1 (PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) )
++
++
++#define PEGASOS2_SRAM_RXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
++#define PEGASOS2_SRAM_TXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
++
++#undef BE_VERBOSE
++
++static struct resource mv643xx_eth_shared_resources[] = {
++ [0] = {
++ .name = "ethernet shared base",
++ .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
++ .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
++ MV643XX_ETH_SHARED_REGS_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device mv643xx_eth_shared_device = {
++ .name = MV643XX_ETH_SHARED_NAME,
++ .id = 0,
++ .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
++ .resource = mv643xx_eth_shared_resources,
++};
++
++static struct resource mv643xx_eth0_resources[] = {
++ [0] = {
++ .name = "eth0 irq",
++ .start = 9,
++ .end = 9,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++
++static struct mv643xx_eth_platform_data eth0_pd = {
++ .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
++ .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
++ .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
++
++ .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH0 + PEGASOS2_SRAM_TXRING_SIZE,
++ .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
++ .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
++};
++
++static struct platform_device eth0_device = {
++ .name = MV643XX_ETH_NAME,
++ .id = 0,
++ .num_resources = ARRAY_SIZE(mv643xx_eth0_resources),
++ .resource = mv643xx_eth0_resources,
++ .dev = {
++ .platform_data = ð0_pd,
++ },
++};
++
++static struct resource mv643xx_eth1_resources[] = {
++ [0] = {
++ .name = "eth1 irq",
++ .start = 9,
++ .end = 9,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct mv643xx_eth_platform_data eth1_pd = {
++ .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
++ .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
++ .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
++
++ .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH1 + PEGASOS2_SRAM_TXRING_SIZE,
++ .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
++ .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
++};
++
++static struct platform_device eth1_device = {
++ .name = MV643XX_ETH_NAME,
++ .id = 1,
++ .num_resources = ARRAY_SIZE(mv643xx_eth1_resources),
++ .resource = mv643xx_eth1_resources,
++ .dev = {
++ .platform_data = ð1_pd,
++ },
++};
++
++static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
++ &mv643xx_eth_shared_device,
++ ð0_device,
++ ð1_device,
++};
++
++/***********/
++/***********/
++#define MV_READ(offset,val) { val = readl(mv643xx_reg_base + offset); }
++#define MV_WRITE(offset,data) writel(data, mv643xx_reg_base + offset)
++
++static void __iomem *mv643xx_reg_base;
++
++static int Enable_SRAM(void)
++{
++ u32 ALong;
++
++ if (mv643xx_reg_base == NULL)
++ mv643xx_reg_base = ioremap(PEGASOS2_MARVELL_REGBASE,
++ PEGASOS2_MARVELL_REGSIZE);
++
++ if (mv643xx_reg_base == NULL)
++ return -ENOMEM;
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: register remapped from %p to %p\n",
++ (void *)PEGASOS2_MARVELL_REGBASE, (void *)mv643xx_reg_base);
++#endif
++
++ MV_WRITE(MV64340_SRAM_CONFIG, 0);
++
++ MV_WRITE(MV64340_INTEGRATED_SRAM_BASE_ADDR, PEGASOS2_SRAM_BASE >> 16);
++
++ MV_READ(MV64340_BASE_ADDR_ENABLE, ALong);
++ ALong &= ~(1 << 19);
++ MV_WRITE(MV64340_BASE_ADDR_ENABLE, ALong);
++
++ ALong = 0x02;
++ ALong |= PEGASOS2_SRAM_BASE & 0xffff0000;
++ MV_WRITE(MV643XX_ETH_BAR_4, ALong);
++
++ MV_WRITE(MV643XX_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
++
++ MV_READ(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
++ ALong &= ~(1 << 4);
++ MV_WRITE(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: register unmapped\n");
++ printk("Pegasos II/Marvell MV64361: SRAM at %p, size=%x\n", (void*) PEGASOS2_SRAM_BASE, PEGASOS2_SRAM_SIZE);
++#endif
++
++ iounmap(mv643xx_reg_base);
++ mv643xx_reg_base = NULL;
++
++ return 1;
++}
++
++
++/***********/
++/***********/
++int mv643xx_eth_add_pds(void)
++{
++ int ret = 0;
++ static struct pci_device_id pci_marvell_mv64360[] = {
++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
++ { }
++ };
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: init\n");
++#endif
++
++ if (pci_dev_present(pci_marvell_mv64360)) {
++ ret = platform_add_devices(mv643xx_eth_pd_devs,
++ ARRAY_SIZE(mv643xx_eth_pd_devs));
++
++ if ( Enable_SRAM() < 0)
++ {
++ eth0_pd.tx_sram_addr = 0;
++ eth0_pd.tx_sram_size = 0;
++ eth0_pd.rx_sram_addr = 0;
++ eth0_pd.rx_sram_size = 0;
++
++ eth1_pd.tx_sram_addr = 0;
++ eth1_pd.tx_sram_size = 0;
++ eth1_pd.rx_sram_addr = 0;
++ eth1_pd.rx_sram_size = 0;
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: Can't enable the "
++ "SRAM\n");
++#endif
++ }
++ }
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: init is over\n");
++#endif
++
++ return ret;
++}
++
++device_initcall(mv643xx_eth_add_pds);
+diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/setup.c
+@@ -0,0 +1,522 @@
++/*
++ * arch/ppc/platforms/setup.c
++ *
++ * Copyright (C) 1995 Linus Torvalds
++ * Adapted from 'alpha' version by Gary Thomas
++ * Modified by Cort Dougan (cort at cs.nmt.edu)
++ */
++
++/*
++ * bootup setup stuff..
++ */
++
++#include <linux/config.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/tty.h>
++#include <linux/major.h>
++#include <linux/interrupt.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/version.h>
++#include <linux/adb.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/ide.h>
++#include <linux/console.h>
++#include <linux/seq_file.h>
++#include <linux/root_dev.h>
++#include <linux/initrd.h>
++#include <linux/module.h>
++
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/prom.h>
++#include <asm/gg2.h>
++#include <asm/pci-bridge.h>
++#include <asm/dma.h>
++#include <asm/machdep.h>
++#include <asm/irq.h>
++#include <asm/hydra.h>
++#include <asm/sections.h>
++#include <asm/time.h>
++#include <asm/btext.h>
++#include <asm/i8259.h>
++#include <asm/mpic.h>
++#include <asm/rtas.h>
++#include <asm/xmon.h>
++
++#include "chrp.h"
++
++void rtas_indicator_progress(char *, unsigned short);
++void btext_progress(char *, unsigned short);
++
++int _chrp_type;
++EXPORT_SYMBOL(_chrp_type);
++
++struct mpic *chrp_mpic;
++
++/*
++ * XXX this should be in xmon.h, but putting it there means xmon.h
++ * has to include <linux/interrupt.h> (to get irqreturn_t), which
++ * causes all sorts of problems. -- paulus
++ */
++extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
++
++extern unsigned long loops_per_jiffy;
++
++#ifdef CONFIG_SMP
++extern struct smp_ops_t chrp_smp_ops;
++#endif
++
++static const char *gg2_memtypes[4] = {
++ "FPM", "SDRAM", "EDO", "BEDO"
++};
++static const char *gg2_cachesizes[4] = {
++ "256 KB", "512 KB", "1 MB", "Reserved"
++};
++static const char *gg2_cachetypes[4] = {
++ "Asynchronous", "Reserved", "Flow-Through Synchronous",
++ "Pipelined Synchronous"
++};
++static const char *gg2_cachemodes[4] = {
++ "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
++};
++
++void chrp_show_cpuinfo(struct seq_file *m)
++{
++ int i, sdramen;
++ unsigned int t;
++ struct device_node *root;
++ const char *model = "";
++
++ root = find_path_device("/");
++ if (root)
++ model = get_property(root, "model", NULL);
++ seq_printf(m, "machine\t\t: CHRP %s\n", model);
++
++ /* longtrail (goldengate) stuff */
++ if (!strncmp(model, "IBM,LongTrail", 13)) {
++ /* VLSI VAS96011/12 `Golden Gate 2' */
++ /* Memory banks */
++ sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
++ >>31) & 1;
++ for (i = 0; i < (sdramen ? 4 : 6); i++) {
++ t = in_le32(gg2_pci_config_base+
++ GG2_PCI_DRAM_BANK0+
++ i*4);
++ if (!(t & 1))
++ continue;
++ switch ((t>>8) & 0x1f) {
++ case 0x1f:
++ model = "4 MB";
++ break;
++ case 0x1e:
++ model = "8 MB";
++ break;
++ case 0x1c:
++ model = "16 MB";
++ break;
++ case 0x18:
++ model = "32 MB";
++ break;
++ case 0x10:
++ model = "64 MB";
++ break;
++ case 0x00:
++ model = "128 MB";
++ break;
++ default:
++ model = "Reserved";
++ break;
++ }
++ seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
++ gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
++ }
++ /* L2 cache */
++ t = in_le32(gg2_pci_config_base+GG2_PCI_CC_CTRL);
++ seq_printf(m, "board l2\t: %s %s (%s)\n",
++ gg2_cachesizes[(t>>7) & 3],
++ gg2_cachetypes[(t>>2) & 3],
++ gg2_cachemodes[t & 3]);
++ }
++}
++
++/*
++ * Fixes for the National Semiconductor PC78308VUL SuperI/O
++ *
++ * Some versions of Open Firmware incorrectly initialize the IRQ settings
++ * for keyboard and mouse
++ */
++static inline void __init sio_write(u8 val, u8 index)
++{
++ outb(index, 0x15c);
++ outb(val, 0x15d);
++}
++
++static inline u8 __init sio_read(u8 index)
++{
++ outb(index, 0x15c);
++ return inb(0x15d);
++}
++
++static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
++ u8 type)
++{
++ u8 level0, type0, active;
++
++ /* select logical device */
++ sio_write(device, 0x07);
++ active = sio_read(0x30);
++ level0 = sio_read(0x70);
++ type0 = sio_read(0x71);
++ if (level0 != level || type0 != type || !active) {
++ printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
++ "remapping to level %d, type %d, active\n",
++ name, level0, type0, !active ? "in" : "", level, type);
++ sio_write(0x01, 0x30);
++ sio_write(level, 0x70);
++ sio_write(type, 0x71);
++ }
++}
++
++static void __init sio_init(void)
++{
++ struct device_node *root;
++
++ if ((root = find_path_device("/")) &&
++ !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
++ /* logical device 0 (KBC/Keyboard) */
++ sio_fixup_irq("keyboard", 0, 1, 2);
++ /* select logical device 1 (KBC/Mouse) */
++ sio_fixup_irq("mouse", 1, 12, 2);
++ }
++}
++
++
++static void __init pegasos_set_l2cr(void)
++{
++ struct device_node *np;
++
++ /* On Pegasos, enable the l2 cache if needed, as the OF forgets it */
++ if (_chrp_type != _CHRP_Pegasos)
++ return;
++
++ /* Enable L2 cache if needed */
++ np = find_type_devices("cpu");
++ if (np != NULL) {
++ unsigned int *l2cr = (unsigned int *)
++ get_property (np, "l2cr", NULL);
++ if (l2cr == NULL) {
++ printk ("Pegasos l2cr : no cpu l2cr property found\n");
++ return;
++ }
++ if (!((*l2cr) & 0x80000000)) {
++ printk ("Pegasos l2cr : L2 cache was not active, "
++ "activating\n");
++ _set_L2CR(0);
++ _set_L2CR((*l2cr) | 0x80000000);
++ }
++ }
++}
++
++void __init chrp_setup_arch(void)
++{
++ struct device_node *root = find_path_device ("/");
++ char *machine = NULL;
++ struct device_node *device;
++ unsigned int *p = NULL;
++
++ /* init to some ~sane value until calibrate_delay() runs */
++ loops_per_jiffy = 50000000/HZ;
++
++ if (root)
++ machine = get_property(root, "model", NULL);
++ if (machine && strncmp(machine, "Pegasos", 7) == 0) {
++ _chrp_type = _CHRP_Pegasos;
++ } else if (machine && strncmp(machine, "IBM", 3) == 0) {
++ _chrp_type = _CHRP_IBM;
++ } else if (machine && strncmp(machine, "MOT", 3) == 0) {
++ _chrp_type = _CHRP_Motorola;
++ } else {
++ /* Let's assume it is an IBM chrp if all else fails */
++ _chrp_type = _CHRP_IBM;
++ }
++ printk("chrp type = %x\n", _chrp_type);
++
++ rtas_initialize();
++ if (rtas_token("display-character") >= 0)
++ ppc_md.progress = rtas_progress;
++
++#ifdef CONFIG_BOOTX_TEXT
++ if (ppc_md.progress == NULL && boot_text_mapped)
++ ppc_md.progress = btext_progress;
++#endif
++
++#ifdef CONFIG_BLK_DEV_INITRD
++ /* this is fine for chrp */
++ initrd_below_start_ok = 1;
++
++ if (initrd_start)
++ ROOT_DEV = Root_RAM0;
++ else
++#endif
++ ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
++
++ /* On pegasos, enable the L2 cache if not already done by OF */
++ pegasos_set_l2cr();
++
++ /* Lookup PCI host bridges */
++ chrp_find_bridges();
++
++ /*
++ * Temporary fixes for PCI devices.
++ * -- Geert
++ */
++ hydra_init(); /* Mac I/O */
++
++ /*
++ * Fix the Super I/O configuration
++ */
++ sio_init();
++
++ /* Get the event scan rate for the rtas so we know how
++ * often it expects a heartbeat. -- Cort
++ */
++ device = find_devices("rtas");
++ if (device)
++ p = (unsigned int *) get_property
++ (device, "rtas-event-scan-rate", NULL);
++ if (p && *p) {
++ ppc_md.heartbeat = chrp_event_scan;
++ ppc_md.heartbeat_reset = HZ / (*p * 30) - 1;
++ ppc_md.heartbeat_count = 1;
++ printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
++ *p, ppc_md.heartbeat_reset);
++ }
++
++ pci_create_OF_bus_map();
++
++ /*
++ * Print the banner, then scroll down so boot progress
++ * can be printed. -- Cort
++ */
++ if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
++}
++
++void
++chrp_event_scan(void)
++{
++ unsigned char log[1024];
++ int ret = 0;
++
++ /* XXX: we should loop until the hardware says no more error logs -- Cort */
++ rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0,
++ __pa(log), 1024);
++ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
++}
++
++/*
++ * Finds the open-pic node and sets up the mpic driver.
++ */
++static void __init chrp_find_openpic(void)
++{
++ struct device_node *np, *root;
++ int len, i, j, irq_count;
++ int isu_size, idu_size;
++ unsigned int *iranges, *opprop = NULL;
++ int oplen = 0;
++ unsigned long opaddr;
++ int na = 1;
++ unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
++
++ np = find_type_devices("open-pic");
++ if (np == NULL)
++ return;
++ root = find_path_device("/");
++ if (root) {
++ opprop = (unsigned int *) get_property
++ (root, "platform-open-pic", &oplen);
++ na = prom_n_addr_cells(root);
++ }
++ if (opprop && oplen >= na * sizeof(unsigned int)) {
++ opaddr = opprop[na-1]; /* assume 32-bit */
++ oplen /= na * sizeof(unsigned int);
++ } else {
++ if (np->n_addrs == 0)
++ return;
++ opaddr = np->addrs[0].address;
++ oplen = 0;
++ }
++
++ printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
++
++ irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
++ prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4);
++
++ iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
++ if (iranges == NULL)
++ len = 0; /* non-distributed mpic */
++ else
++ len /= 2 * sizeof(unsigned int);
++
++ /*
++ * The first pair of cells in interrupt-ranges refers to the
++ * IDU; subsequent pairs refer to the ISUs.
++ */
++ if (oplen < len) {
++ printk(KERN_ERR "Insufficient addresses for distributed"
++ " OpenPIC (%d < %d)\n", np->n_addrs, len);
++ len = oplen;
++ }
++
++ isu_size = 0;
++ idu_size = 0;
++ if (len > 0 && iranges[1] != 0) {
++ printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n",
++ iranges[0], iranges[0] + iranges[1] - 1);
++ idu_size = iranges[1];
++ }
++ if (len > 1)
++ isu_size = iranges[3];
++
++ chrp_mpic = mpic_alloc(opaddr, MPIC_PRIMARY,
++ isu_size, NUM_ISA_INTERRUPTS, irq_count,
++ NR_IRQS - 4, init_senses, irq_count,
++ " MPIC ");
++ if (chrp_mpic == NULL) {
++ printk(KERN_ERR "Failed to allocate MPIC structure\n");
++ return;
++ }
++
++ j = na - 1;
++ for (i = 1; i < len; ++i) {
++ iranges += 2;
++ j += na;
++ printk(KERN_INFO "OpenPIC irqs %d..%d in ISU at %x\n",
++ iranges[0], iranges[0] + iranges[1] - 1,
++ opprop[j]);
++ mpic_assign_isu(chrp_mpic, i - 1, opprop[j]);
++ }
++
++ mpic_init(chrp_mpic);
++ mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL);
++}
++
++#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
++static struct irqaction xmon_irqaction = {
++ .handler = xmon_irq,
++ .mask = CPU_MASK_NONE,
++ .name = "XMON break",
++};
++#endif
++
++void __init chrp_init_IRQ(void)
++{
++ struct device_node *np;
++ unsigned long chrp_int_ack = 0;
++#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
++ struct device_node *kbd;
++#endif
++
++ for (np = find_devices("pci"); np != NULL; np = np->next) {
++ unsigned int *addrp = (unsigned int *)
++ get_property(np, "8259-interrupt-acknowledge", NULL);
++
++ if (addrp == NULL)
++ continue;
++ chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
++ break;
++ }
++ if (np == NULL)
++ printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
++
++ chrp_find_openpic();
++
++ i8259_init(chrp_int_ack, 0);
++
++ if (_chrp_type == _CHRP_Pegasos)
++ ppc_md.get_irq = i8259_irq;
++ else
++ ppc_md.get_irq = mpic_get_irq;
++
++#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
++ /* see if there is a keyboard in the device tree
++ with a parent of type "adb" */
++ for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
++ if (kbd->parent && kbd->parent->type
++ && strcmp(kbd->parent->type, "adb") == 0)
++ break;
++ if (kbd)
++ setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
++#endif
++}
++
++void __init
++chrp_init2(void)
++{
++#ifdef CONFIG_NVRAM
++ chrp_nvram_init();
++#endif
++
++ request_region(0x20,0x20,"pic1");
++ request_region(0xa0,0x20,"pic2");
++ request_region(0x00,0x20,"dma1");
++ request_region(0x40,0x20,"timer");
++ request_region(0x80,0x10,"dma page reg");
++ request_region(0xc0,0x20,"dma2");
++
++ if (ppc_md.progress)
++ ppc_md.progress(" Have fun! ", 0x7777);
++}
++
++void __init chrp_init(void)
++{
++ ISA_DMA_THRESHOLD = ~0L;
++ DMA_MODE_READ = 0x44;
++ DMA_MODE_WRITE = 0x48;
++ isa_io_base = CHRP_ISA_IO_BASE; /* default value */
++ ppc_do_canonicalize_irqs = 1;
++
++ /* Assume we have an 8259... */
++ __irq_offset_value = NUM_ISA_INTERRUPTS;
++
++ ppc_md.setup_arch = chrp_setup_arch;
++ ppc_md.show_cpuinfo = chrp_show_cpuinfo;
++
++ ppc_md.init_IRQ = chrp_init_IRQ;
++ ppc_md.init = chrp_init2;
++
++ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
++
++ ppc_md.restart = rtas_restart;
++ ppc_md.power_off = rtas_power_off;
++ ppc_md.halt = rtas_halt;
++
++ ppc_md.time_init = chrp_time_init;
++ ppc_md.set_rtc_time = chrp_set_rtc_time;
++ ppc_md.get_rtc_time = chrp_get_rtc_time;
++ ppc_md.calibrate_decr = chrp_calibrate_decr;
++
++#ifdef CONFIG_SMP
++ smp_ops = &chrp_smp_ops;
++#endif /* CONFIG_SMP */
++}
++
++#ifdef CONFIG_BOOTX_TEXT
++void
++btext_progress(char *s, unsigned short hex)
++{
++ btext_drawstring(s);
++ btext_drawstring("\n");
++}
++#endif /* CONFIG_BOOTX_TEXT */
+diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/smp.c
+@@ -0,0 +1,122 @@
++/*
++ * Smp support for CHRP machines.
++ *
++ * Written by Cort Dougan (cort at cs.nmt.edu) borrowing a great
++ * deal of code from the sparc and intel versions.
++ *
++ * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++
++#include <asm/ptrace.h>
++#include <asm/atomic.h>
++#include <asm/irq.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/sections.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/smp.h>
++#include <asm/residual.h>
++#include <asm/time.h>
++#include <asm/open_pic.h>
++#include <asm/machdep.h>
++#include <asm/smp.h>
++#include <asm/mpic.h>
++
++extern unsigned long smp_chrp_cpu_nr;
++
++static int __init smp_chrp_probe(void)
++{
++ struct device_node *cpus = NULL;
++ unsigned int *reg;
++ int reglen;
++ int ncpus = 0;
++ int cpuid;
++ unsigned int phys;
++
++ /* Count CPUs in the device-tree */
++ cpuid = 1; /* the boot cpu is logical cpu 0 */
++ while ((cpus = of_find_node_by_type(cpus, "cpu")) != NULL) {
++ phys = ncpus;
++ reg = (unsigned int *) get_property(cpus, "reg", ®len);
++ if (reg && reglen >= sizeof(unsigned int))
++ /* hmmm, not having a reg property would be bad */
++ phys = *reg;
++ if (phys != boot_cpuid_phys) {
++ set_hard_smp_processor_id(cpuid, phys);
++ ++cpuid;
++ }
++ ++ncpus;
++ }
++
++ printk(KERN_INFO "CHRP SMP probe found %d cpus\n", ncpus);
++
++ /* Nothing more to do if less than 2 of them */
++ if (ncpus <= 1)
++ return 1;
++
++ mpic_request_ipis();
++
++ return ncpus;
++}
++
++static void __devinit smp_chrp_kick_cpu(int nr)
++{
++ *(unsigned long *)KERNELBASE = nr;
++ asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
++}
++
++static void __devinit smp_chrp_setup_cpu(int cpu_nr)
++{
++ mpic_setup_this_cpu();
++}
++
++static DEFINE_SPINLOCK(timebase_lock);
++static unsigned int timebase_upper = 0, timebase_lower = 0;
++
++void __devinit smp_chrp_give_timebase(void)
++{
++ spin_lock(&timebase_lock);
++ rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
++ timebase_upper = get_tbu();
++ timebase_lower = get_tbl();
++ spin_unlock(&timebase_lock);
++
++ while (timebase_upper || timebase_lower)
++ barrier();
++ rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
++}
++
++void __devinit smp_chrp_take_timebase(void)
++{
++ while (!(timebase_upper || timebase_lower))
++ barrier();
++ spin_lock(&timebase_lock);
++ set_tb(timebase_upper, timebase_lower);
++ timebase_upper = 0;
++ timebase_lower = 0;
++ spin_unlock(&timebase_lock);
++ printk("CPU %i taken timebase\n", smp_processor_id());
++}
++
++/* CHRP with openpic */
++struct smp_ops_t chrp_smp_ops = {
++ .message_pass = smp_mpic_message_pass,
++ .probe = smp_chrp_probe,
++ .kick_cpu = smp_chrp_kick_cpu,
++ .setup_cpu = smp_chrp_setup_cpu,
++ .give_timebase = smp_chrp_give_timebase,
++ .take_timebase = smp_chrp_take_timebase,
++};
+diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/chrp/time.c
+@@ -0,0 +1,188 @@
++/*
++ * arch/ppc/platforms/chrp_time.c
++ *
++ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
++ *
++ * Adapted for PowerPC (PReP) by Gary Thomas
++ * Modified by Cort Dougan (cort at cs.nmt.edu).
++ * Copied and modified from arch/i386/kernel/time.c
++ *
++ */
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/timex.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/init.h>
++#include <linux/bcd.h>
++
++#include <asm/io.h>
++#include <asm/nvram.h>
++#include <asm/prom.h>
++#include <asm/sections.h>
++#include <asm/time.h>
++
++extern spinlock_t rtc_lock;
++
++static int nvram_as1 = NVRAM_AS1;
++static int nvram_as0 = NVRAM_AS0;
++static int nvram_data = NVRAM_DATA;
++
++long __init chrp_time_init(void)
++{
++ struct device_node *rtcs;
++ int base;
++
++ rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
++ if (rtcs == NULL)
++ rtcs = find_compatible_devices("rtc", "ds1385-rtc");
++ if (rtcs == NULL || rtcs->addrs == NULL)
++ return 0;
++ base = rtcs->addrs[0].address;
++ nvram_as1 = 0;
++ nvram_as0 = base;
++ nvram_data = base + 1;
++
++ return 0;
++}
++
++int chrp_cmos_clock_read(int addr)
++{
++ if (nvram_as1 != 0)
++ outb(addr>>8, nvram_as1);
++ outb(addr, nvram_as0);
++ return (inb(nvram_data));
++}
++
++void chrp_cmos_clock_write(unsigned long val, int addr)
++{
++ if (nvram_as1 != 0)
++ outb(addr>>8, nvram_as1);
++ outb(addr, nvram_as0);
++ outb(val, nvram_data);
++ return;
++}
++
++/*
++ * Set the hardware clock. -- Cort
++ */
++int chrp_set_rtc_time(struct rtc_time *tmarg)
++{
++ unsigned char save_control, save_freq_select;
++ struct rtc_time tm = *tmarg;
++
++ spin_lock(&rtc_lock);
++
++ save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
++
++ chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
++
++ save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
++
++ chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
++
++ tm.tm_year -= 1900;
++ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
++ BIN_TO_BCD(tm.tm_sec);
++ BIN_TO_BCD(tm.tm_min);
++ BIN_TO_BCD(tm.tm_hour);
++ BIN_TO_BCD(tm.tm_mon);
++ BIN_TO_BCD(tm.tm_mday);
++ BIN_TO_BCD(tm.tm_year);
++ }
++ chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
++ chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
++ chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
++ chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
++ chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
++ chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
++
++ /* The following flags have to be released exactly in this order,
++ * otherwise the DS12887 (popular MC146818A clone with integrated
++ * battery and quartz) will not reset the oscillator and will not
++ * update precisely 500 ms later. You won't find this mentioned in
++ * the Dallas Semiconductor data sheets, but who believes data
++ * sheets anyway ... -- Markus Kuhn
++ */
++ chrp_cmos_clock_write(save_control, RTC_CONTROL);
++ chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
++
++ spin_unlock(&rtc_lock);
++ return 0;
++}
++
++void chrp_get_rtc_time(struct rtc_time *tm)
++{
++ unsigned int year, mon, day, hour, min, sec;
++ int uip, i;
++
++ /* The Linux interpretation of the CMOS clock register contents:
++ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
++ * RTC registers show the second which has precisely just started.
++ * Let's hope other operating systems interpret the RTC the same way.
++ */
++
++ /* Since the UIP flag is set for about 2.2 ms and the clock
++ * is typically written with a precision of 1 jiffy, trying
++ * to obtain a precision better than a few milliseconds is
++ * an illusion. Only consistency is interesting, this also
++ * allows to use the routine for /dev/rtc without a potential
++ * 1 second kernel busy loop triggered by any reader of /dev/rtc.
++ */
++
++ for ( i = 0; i<1000000; i++) {
++ uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
++ sec = chrp_cmos_clock_read(RTC_SECONDS);
++ min = chrp_cmos_clock_read(RTC_MINUTES);
++ hour = chrp_cmos_clock_read(RTC_HOURS);
++ day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
++ mon = chrp_cmos_clock_read(RTC_MONTH);
++ year = chrp_cmos_clock_read(RTC_YEAR);
++ uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
++ if ((uip & RTC_UIP)==0) break;
++ }
++
++ if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
++ BCD_TO_BIN(sec);
++ BCD_TO_BIN(min);
++ BCD_TO_BIN(hour);
++ BCD_TO_BIN(day);
++ BCD_TO_BIN(mon);
++ BCD_TO_BIN(year);
++ }
++ if ((year += 1900) < 1970)
++ year += 100;
++ tm->tm_sec = sec;
++ tm->tm_min = min;
++ tm->tm_hour = hour;
++ tm->tm_mday = day;
++ tm->tm_mon = mon;
++ tm->tm_year = year;
++}
++
++
++void __init chrp_calibrate_decr(void)
++{
++ struct device_node *cpu;
++ unsigned int freq, *fp;
++
++ /*
++ * The cpu node should have a timebase-frequency property
++ * to tell us the rate at which the decrementer counts.
++ */
++ freq = 16666000; /* hardcoded default */
++ cpu = find_type_devices("cpu");
++ if (cpu != 0) {
++ fp = (unsigned int *)
++ get_property(cpu, "timebase-frequency", NULL);
++ if (fp != 0)
++ freq = *fp;
++ }
++ ppc_tb_freq = freq;
++}
+diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/embedded6xx/Kconfig
+@@ -0,0 +1,318 @@
++choice
++ prompt "Machine Type"
++ depends on EMBEDDED6xx
++
++config KATANA
++ bool "Artesyn-Katana"
++ help
++ Select KATANA if configuring an Artesyn KATANA 750i or 3750
++ cPCI board.
++
++config WILLOW
++ bool "Cogent-Willow"
++
++config CPCI690
++ bool "Force-CPCI690"
++ help
++ Select CPCI690 if configuring a Force CPCI690 cPCI board.
++
++config POWERPMC250
++ bool "Force-PowerPMC250"
++
++config CHESTNUT
++ bool "IBM 750FX Eval board or 750GX Eval board"
++ help
++ Select CHESTNUT if configuring an IBM 750FX Eval Board or a
++ IBM 750GX Eval board.
++
++config SPRUCE
++ bool "IBM-Spruce"
++ select PPC_INDIRECT_PCI
++
++config HDPU
++ bool "Sky-HDPU"
++ help
++ Select HDPU if configuring a Sky Computers Compute Blade.
++
++config HDPU_FEATURES
++ depends HDPU
++ tristate "HDPU-Features"
++ help
++ Select to enable HDPU enhanced features.
++
++config EV64260
++ bool "Marvell-EV64260BP"
++ help
++ Select EV64260 if configuring a Marvell (formerly Galileo)
++ EV64260BP Evaluation platform.
++
++config LOPEC
++ bool "Motorola-LoPEC"
++ select PPC_I8259
++
++config MVME5100
++ bool "Motorola-MVME5100"
++ select PPC_INDIRECT_PCI
++
++config PPLUS
++ bool "Motorola-PowerPlus"
++ select PPC_I8259
++ select PPC_INDIRECT_PCI
++
++config PRPMC750
++ bool "Motorola-PrPMC750"
++ select PPC_INDIRECT_PCI
++
++config PRPMC800
++ bool "Motorola-PrPMC800"
++ select PPC_INDIRECT_PCI
++
++config SANDPOINT
++ bool "Motorola-Sandpoint"
++ select PPC_I8259
++ help
++ Select SANDPOINT if configuring for a Motorola Sandpoint X3
++ (any flavor).
++
++config RADSTONE_PPC7D
++ bool "Radstone Technology PPC7D board"
++ select PPC_I8259
++
++config PAL4
++ bool "SBS-Palomar4"
++
++config GEMINI
++ bool "Synergy-Gemini"
++ select PPC_INDIRECT_PCI
++ depends on BROKEN
++ help
++ Select Gemini if configuring for a Synergy Microsystems' Gemini
++ series Single Board Computer. More information is available at:
++ <http://www.synergymicro.com/PressRel/97_10_15.html>.
++
++config EST8260
++ bool "EST8260"
++ ---help---
++ The EST8260 is a single-board computer manufactured by Wind River
++ Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
++ the MPC8260. Wind River Systems has a website at
++ <http://www.windriver.com/>, but the EST8260 cannot be found on it
++ and has probably been discontinued or rebadged.
++
++config SBC82xx
++ bool "SBC82xx"
++ ---help---
++ SBC PowerQUICC II, single-board computer with MPC82xx CPU
++ Manufacturer: Wind River Systems, Inc.
++ Date of Release: May 2003
++ End of Life: -
++ URL: <http://www.windriver.com/>
++
++config SBS8260
++ bool "SBS8260"
++
++config RPX8260
++ bool "RPXSUPER"
++
++config TQM8260
++ bool "TQM8260"
++ ---help---
++ MPC8260 based module, little larger than credit card,
++ up to 128 MB global + 64 MB local RAM, 32 MB Flash,
++ 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
++ 2 x serial ports, ...
++ Manufacturer: TQ Components, www.tq-group.de
++ Date of Release: June 2001
++ End of Life: not yet :-)
++ URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
++
++config ADS8272
++ bool "ADS8272"
++
++config PQ2FADS
++ bool "Freescale-PQ2FADS"
++ help
++ Select PQ2FADS if you wish to configure for a Freescale
++ PQ2FADS board (-VR or -ZU).
++
++config LITE5200
++ bool "Freescale LITE5200 / (IceCube)"
++ select PPC_MPC52xx
++ help
++ Support for the LITE5200 dev board for the MPC5200 from Freescale.
++ This is for the LITE5200 version 2.0 board. Don't know if it changes
++ much but it's only been tested on this board version. I think this
++ board is also known as IceCube.
++
++config MPC834x_SYS
++ bool "Freescale MPC834x SYS"
++ help
++ This option enables support for the MPC 834x SYS evaluation board.
++
++ Be aware that PCI buses can only function when SYS board is plugged
++ into the PIB (Platform IO Board) board from Freescale which provide
++ 3 PCI slots. The PIBs PCI initialization is the bootloader's
++ responsiblilty.
++
++config EV64360
++ bool "Marvell-EV64360BP"
++ help
++ Select EV64360 if configuring a Marvell EV64360BP Evaluation
++ platform.
++endchoice
++
++config PQ2ADS
++ bool
++ depends on ADS8272
++ default y
++
++config TQM8xxL
++ bool
++ depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L)
++ default y
++
++config PPC_MPC52xx
++ bool
++
++config 8260
++ bool "CPM2 Support" if WILLOW
++ depends on 6xx
++ default y if TQM8260 || RPX8260 || EST8260 || SBS8260 || SBC82xx || PQ2FADS
++ help
++ The MPC8260 is a typical embedded CPU made by Motorola. Selecting
++ this option means that you wish to build a kernel for a machine with
++ an 8260 class CPU.
++
++config 8272
++ bool
++ depends on 6xx
++ default y if ADS8272
++ select 8260
++ help
++ The MPC8272 CPM has a different internal dpram setup than other CPM2
++ devices
++
++config 83xx
++ bool
++ default y if MPC834x_SYS
++
++config MPC834x
++ bool
++ default y if MPC834x_SYS
++
++config CPM2
++ bool
++ depends on 8260 || MPC8560 || MPC8555
++ default y
++ help
++ The CPM2 (Communications Processor Module) is a coprocessor on
++ embedded CPUs made by Motorola. Selecting this option means that
++ you wish to build a kernel for a machine with a CPM2 coprocessor
++ on it (826x, 827x, 8560).
++
++config PPC_GEN550
++ bool
++ depends on SANDPOINT || SPRUCE || PPLUS || \
++ PRPMC750 || PRPMC800 || LOPEC || \
++ (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \
++ 83xx
++ default y
++
++config FORCE
++ bool
++ depends on 6xx && POWERPMC250
++ default y
++
++config GT64260
++ bool
++ depends on EV64260 || CPCI690
++ default y
++
++config MV64360 # Really MV64360 & MV64460
++ bool
++ depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU || EV64360
++ default y
++
++config MV64X60
++ bool
++ depends on (GT64260 || MV64360)
++ select PPC_INDIRECT_PCI
++ default y
++
++menu "Set bridge options"
++ depends on MV64X60
++
++config NOT_COHERENT_CACHE
++ bool "Turn off Cache Coherency"
++ default n
++ help
++ Some 64x60 bridges lock up when trying to enforce cache coherency.
++ When this option is selected, cache coherency will be turned off.
++ Note that this can cause other problems (e.g., stale data being
++ speculatively loaded via a cached mapping). Use at your own risk.
++
++config MV64X60_BASE
++ hex "Set bridge base used by firmware"
++ default "0xf1000000"
++ help
++ A firmware can leave the base address of the bridge's registers at
++ a non-standard location. If so, set this value to reflect the
++ address of that non-standard location.
++
++config MV64X60_NEW_BASE
++ hex "Set bridge base used by kernel"
++ default "0xf1000000"
++ help
++ If the current base address of the bridge's registers is not where
++ you want it, set this value to the address that you want it moved to.
++
++endmenu
++
++config NONMONARCH_SUPPORT
++ bool "Enable Non-Monarch Support"
++ depends on PRPMC800
++
++config HARRIER
++ bool
++ depends on PRPMC800
++ default y
++
++config EPIC_SERIAL_MODE
++ bool
++ depends on 6xx && (LOPEC || SANDPOINT)
++ default y
++
++config MPC10X_BRIDGE
++ bool
++ depends on POWERPMC250 || LOPEC || SANDPOINT
++ select PPC_INDIRECT_PCI
++ default y
++
++config MPC10X_OPENPIC
++ bool
++ depends on POWERPMC250 || LOPEC || SANDPOINT
++ default y
++
++config MPC10X_STORE_GATHERING
++ bool "Enable MPC10x store gathering"
++ depends on MPC10X_BRIDGE
++
++config SANDPOINT_ENABLE_UART1
++ bool "Enable DUART mode on Sandpoint"
++ depends on SANDPOINT
++ help
++ If this option is enabled then the MPC824x processor will run
++ in DUART mode instead of UART mode.
++
++config HARRIER_STORE_GATHERING
++ bool "Enable Harrier store gathering"
++ depends on HARRIER
++
++config MVME5100_IPMC761_PRESENT
++ bool "MVME5100 configured with an IPMC761"
++ depends on MVME5100
++ select PPC_I8259
++
++config SPRUCE_BAUD_33M
++ bool "Spruce baud clock support"
++ depends on SPRUCE
+diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/Kconfig
+@@ -0,0 +1,31 @@
++
++menu "iSeries device drivers"
++ depends on PPC_ISERIES
++
++config VIOCONS
++ tristate "iSeries Virtual Console Support"
++
++config VIODASD
++ tristate "iSeries Virtual I/O disk support"
++ help
++ If you are running on an iSeries system and you want to use
++ virtual disks created and managed by OS/400, say Y.
++
++config VIOCD
++ tristate "iSeries Virtual I/O CD support"
++ help
++ If you are running Linux on an IBM iSeries system and you want to
++ read a CD drive owned by OS/400, say Y here.
++
++config VIOTAPE
++ tristate "iSeries Virtual Tape Support"
++ help
++ If you are running Linux on an iSeries system and you want Linux
++ to read and/or write a tape drive owned by OS/400, say Y here.
++
++endmenu
++
++config VIOPATH
++ bool
++ depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH
++ default y
+diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/Makefile
+@@ -0,0 +1,9 @@
++EXTRA_CFLAGS += -mno-minimal-toc
++
++obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \
++ hvcall.o proc.o htab.o iommu.o misc.o
++obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o
++obj-$(CONFIG_IBMVIO) += vio.o
++obj-$(CONFIG_SMP) += smp.o
++obj-$(CONFIG_VIOPATH) += viopath.o
++obj-$(CONFIG_MODULES) += ksyms.o
+diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/call_hpt.h
+@@ -0,0 +1,101 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _PLATFORMS_ISERIES_CALL_HPT_H
++#define _PLATFORMS_ISERIES_CALL_HPT_H
++
++/*
++ * This file contains the "hypervisor call" interface which is used to
++ * drive the hypervisor from the OS.
++ */
++
++#include <asm/iSeries/HvCallSc.h>
++#include <asm/iSeries/HvTypes.h>
++#include <asm/mmu.h>
++
++#define HvCallHptGetHptAddress HvCallHpt + 0
++#define HvCallHptGetHptPages HvCallHpt + 1
++#define HvCallHptSetPp HvCallHpt + 5
++#define HvCallHptSetSwBits HvCallHpt + 6
++#define HvCallHptUpdate HvCallHpt + 7
++#define HvCallHptInvalidateNoSyncICache HvCallHpt + 8
++#define HvCallHptGet HvCallHpt + 11
++#define HvCallHptFindNextValid HvCallHpt + 12
++#define HvCallHptFindValid HvCallHpt + 13
++#define HvCallHptAddValidate HvCallHpt + 16
++#define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18
++
++
++static inline u64 HvCallHpt_getHptAddress(void)
++{
++ return HvCall0(HvCallHptGetHptAddress);
++}
++
++static inline u64 HvCallHpt_getHptPages(void)
++{
++ return HvCall0(HvCallHptGetHptPages);
++}
++
++static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
++{
++ HvCall2(HvCallHptSetPp, hpteIndex, value);
++}
++
++static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff)
++{
++ HvCall3(HvCallHptSetSwBits, hpteIndex, bitson, bitsoff);
++}
++
++static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
++{
++ HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
++}
++
++static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
++ u8 bitsoff)
++{
++ u64 compressedStatus;
++
++ compressedStatus = HvCall4(HvCallHptInvalidateSetSwBitsGet,
++ hpteIndex, bitson, bitsoff, 1);
++ HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
++ return compressedStatus;
++}
++
++static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
++{
++ return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
++}
++
++static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
++ u8 bitson, u8 bitsoff)
++{
++ return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
++ bitson, bitsoff);
++}
++
++static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
++{
++ HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
++}
++
++static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
++{
++ HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
++}
++
++#endif /* _PLATFORMS_ISERIES_CALL_HPT_H */
+diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/call_pci.h
+@@ -0,0 +1,290 @@
++/*
++ * Provides the Hypervisor PCI calls for iSeries Linux Parition.
++ * Copyright (C) 2001 <Wayne G Holm> <IBM Corporation>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the:
++ * Free Software Foundation, Inc.,
++ * 59 Temple Place, Suite 330,
++ * Boston, MA 02111-1307 USA
++ *
++ * Change Activity:
++ * Created, Jan 9, 2001
++ */
++
++#ifndef _PLATFORMS_ISERIES_CALL_PCI_H
++#define _PLATFORMS_ISERIES_CALL_PCI_H
++
++#include <asm/iSeries/HvCallSc.h>
++#include <asm/iSeries/HvTypes.h>
++
++/*
++ * DSA == Direct Select Address
++ * this struct must be 64 bits in total
++ */
++struct HvCallPci_DsaAddr {
++ u16 busNumber; /* PHB index? */
++ u8 subBusNumber; /* PCI bus number? */
++ u8 deviceId; /* device and function? */
++ u8 barNumber;
++ u8 reserved[3];
++};
++
++union HvDsaMap {
++ u64 DsaAddr;
++ struct HvCallPci_DsaAddr Dsa;
++};
++
++struct HvCallPci_LoadReturn {
++ u64 rc;
++ u64 value;
++};
++
++enum HvCallPci_DeviceType {
++ HvCallPci_NodeDevice = 1,
++ HvCallPci_SpDevice = 2,
++ HvCallPci_IopDevice = 3,
++ HvCallPci_BridgeDevice = 4,
++ HvCallPci_MultiFunctionDevice = 5,
++ HvCallPci_IoaDevice = 6
++};
++
++
++struct HvCallPci_DeviceInfo {
++ u32 deviceType; /* See DeviceType enum for values */
++};
++
++struct HvCallPci_BusUnitInfo {
++ u32 sizeReturned; /* length of data returned */
++ u32 deviceType; /* see DeviceType enum for values */
++};
++
++struct HvCallPci_BridgeInfo {
++ struct HvCallPci_BusUnitInfo busUnitInfo; /* Generic bus unit info */
++ u8 subBusNumber; /* Bus number of secondary bus */
++ u8 maxAgents; /* Max idsels on secondary bus */
++ u8 maxSubBusNumber; /* Max Sub Bus */
++ u8 logicalSlotNumber; /* Logical Slot Number for IOA */
++};
++
++
++/*
++ * Maximum BusUnitInfo buffer size. Provided for clients so
++ * they can allocate a buffer big enough for any type of bus
++ * unit. Increase as needed.
++ */
++enum {HvCallPci_MaxBusUnitInfoSize = 128};
++
++struct HvCallPci_BarParms {
++ u64 vaddr;
++ u64 raddr;
++ u64 size;
++ u64 protectStart;
++ u64 protectEnd;
++ u64 relocationOffset;
++ u64 pciAddress;
++ u64 reserved[3];
++};
++
++enum HvCallPci_VpdType {
++ HvCallPci_BusVpd = 1,
++ HvCallPci_BusAdapterVpd = 2
++};
++
++#define HvCallPciConfigLoad8 HvCallPci + 0
++#define HvCallPciConfigLoad16 HvCallPci + 1
++#define HvCallPciConfigLoad32 HvCallPci + 2
++#define HvCallPciConfigStore8 HvCallPci + 3
++#define HvCallPciConfigStore16 HvCallPci + 4
++#define HvCallPciConfigStore32 HvCallPci + 5
++#define HvCallPciEoi HvCallPci + 16
++#define HvCallPciGetBarParms HvCallPci + 18
++#define HvCallPciMaskFisr HvCallPci + 20
++#define HvCallPciUnmaskFisr HvCallPci + 21
++#define HvCallPciSetSlotReset HvCallPci + 25
++#define HvCallPciGetDeviceInfo HvCallPci + 27
++#define HvCallPciGetCardVpd HvCallPci + 28
++#define HvCallPciBarLoad8 HvCallPci + 40
++#define HvCallPciBarLoad16 HvCallPci + 41
++#define HvCallPciBarLoad32 HvCallPci + 42
++#define HvCallPciBarLoad64 HvCallPci + 43
++#define HvCallPciBarStore8 HvCallPci + 44
++#define HvCallPciBarStore16 HvCallPci + 45
++#define HvCallPciBarStore32 HvCallPci + 46
++#define HvCallPciBarStore64 HvCallPci + 47
++#define HvCallPciMaskInterrupts HvCallPci + 48
++#define HvCallPciUnmaskInterrupts HvCallPci + 49
++#define HvCallPciGetBusUnitInfo HvCallPci + 50
++
++static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
++ u8 deviceId, u32 offset, u16 *value)
++{
++ struct HvCallPci_DsaAddr dsa;
++ struct HvCallPci_LoadReturn retVal;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumber;
++ dsa.subBusNumber = subBusNumber;
++ dsa.deviceId = deviceId;
++
++ HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0);
++
++ *value = retVal.value;
++
++ return retVal.rc;
++}
++
++static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
++ u8 deviceId, u32 offset, u8 value)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumber;
++ dsa.subBusNumber = subBusNumber;
++ dsa.deviceId = deviceId;
++
++ return HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
++}
++
++static inline u64 HvCallPci_eoi(u16 busNumberParm, u8 subBusParm,
++ u8 deviceIdParm)
++{
++ struct HvCallPci_DsaAddr dsa;
++ struct HvCallPci_LoadReturn retVal;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceIdParm;
++
++ HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa);
++
++ return retVal.rc;
++}
++
++static inline u64 HvCallPci_getBarParms(u16 busNumberParm, u8 subBusParm,
++ u8 deviceIdParm, u8 barNumberParm, u64 parms, u32 sizeofParms)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceIdParm;
++ dsa.barNumber = barNumberParm;
++
++ return HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
++}
++
++static inline u64 HvCallPci_maskFisr(u16 busNumberParm, u8 subBusParm,
++ u8 deviceIdParm, u64 fisrMask)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceIdParm;
++
++ return HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
++}
++
++static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, u8 subBusParm,
++ u8 deviceIdParm, u64 fisrMask)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceIdParm;
++
++ return HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
++}
++
++static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, u8 subBusParm,
++ u8 deviceNumberParm, u64 parms, u32 sizeofParms)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceNumberParm << 4;
++
++ return HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
++}
++
++static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, u8 subBusParm,
++ u8 deviceIdParm, u64 interruptMask)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceIdParm;
++
++ return HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
++}
++
++static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, u8 subBusParm,
++ u8 deviceIdParm, u64 interruptMask)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceIdParm;
++
++ return HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
++}
++
++static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, u8 subBusParm,
++ u8 deviceIdParm, u64 parms, u32 sizeofParms)
++{
++ struct HvCallPci_DsaAddr dsa;
++
++ *((u64*)&dsa) = 0;
++
++ dsa.busNumber = busNumberParm;
++ dsa.subBusNumber = subBusParm;
++ dsa.deviceId = deviceIdParm;
++
++ return HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms,
++ sizeofParms);
++}
++
++static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm,
++ u16 sizeParm)
++{
++ u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
++ sizeParm, HvCallPci_BusVpd);
++ if (xRc == -1)
++ return -1;
++ else
++ return xRc & 0xFFFF;
++}
++
++#endif /* _PLATFORMS_ISERIES_CALL_PCI_H */
+diff --git a/arch/powerpc/platforms/iseries/call_sm.h b/arch/powerpc/platforms/iseries/call_sm.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/call_sm.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _ISERIES_CALL_SM_H
++#define _ISERIES_CALL_SM_H
++
++/*
++ * This file contains the "hypervisor call" interface which is used to
++ * drive the hypervisor from the OS.
++ */
++
++#include <asm/iSeries/HvCallSc.h>
++#include <asm/iSeries/HvTypes.h>
++
++#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11
++
++static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex,
++ u64 indexIntoBitMap)
++{
++ return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap);
++}
++
++#endif /* _ISERIES_CALL_SM_H */
+diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/htab.c
+@@ -0,0 +1,257 @@
++/*
++ * iSeries hashtable management.
++ * Derived from pSeries_htab.c
++ *
++ * SMP scalability work:
++ * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * 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 <asm/machdep.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/mmu_context.h>
++#include <asm/abs_addr.h>
++#include <linux/spinlock.h>
++
++#include "call_hpt.h"
++
++static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp =
++ { [0 ... 63] = SPIN_LOCK_UNLOCKED};
++
++/*
++ * Very primitive algorithm for picking up a lock
++ */
++static inline void iSeries_hlock(unsigned long slot)
++{
++ if (slot & 0x8)
++ slot = ~slot;
++ spin_lock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
++}
++
++static inline void iSeries_hunlock(unsigned long slot)
++{
++ if (slot & 0x8)
++ slot = ~slot;
++ spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
++}
++
++static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
++ unsigned long prpn, unsigned long vflags,
++ unsigned long rflags)
++{
++ unsigned long arpn;
++ long slot;
++ hpte_t lhpte;
++ int secondary = 0;
++
++ /*
++ * The hypervisor tries both primary and secondary.
++ * If we are being called to insert in the secondary,
++ * it means we have already tried both primary and secondary,
++ * so we return failure immediately.
++ */
++ if (vflags & HPTE_V_SECONDARY)
++ return -1;
++
++ iSeries_hlock(hpte_group);
++
++ slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
++ BUG_ON(lhpte.v & HPTE_V_VALID);
++
++ if (slot == -1) { /* No available entry found in either group */
++ iSeries_hunlock(hpte_group);
++ return -1;
++ }
++
++ if (slot < 0) { /* MSB set means secondary group */
++ vflags |= HPTE_V_SECONDARY;
++ secondary = 1;
++ slot &= 0x7fffffffffffffff;
++ }
++
++ arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT;
++
++ lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
++ lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
++
++ /* Now fill in the actual HPTE */
++ HvCallHpt_addValidate(slot, secondary, &lhpte);
++
++ iSeries_hunlock(hpte_group);
++
++ return (secondary << 3) | (slot & 7);
++}
++
++long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
++ unsigned long va, unsigned long prpn, unsigned long vflags,
++ unsigned long rflags)
++{
++ long slot;
++ hpte_t lhpte;
++
++ slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
++
++ if (lhpte.v & HPTE_V_VALID) {
++ /* Bolt the existing HPTE */
++ HvCallHpt_setSwBits(slot, 0x10, 0);
++ HvCallHpt_setPp(slot, PP_RWXX);
++ return 0;
++ }
++
++ return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags);
++}
++
++static unsigned long iSeries_hpte_getword0(unsigned long slot)
++{
++ hpte_t hpte;
++
++ HvCallHpt_get(&hpte, slot);
++ return hpte.v;
++}
++
++static long iSeries_hpte_remove(unsigned long hpte_group)
++{
++ unsigned long slot_offset;
++ int i;
++ unsigned long hpte_v;
++
++ /* Pick a random slot to start at */
++ slot_offset = mftb() & 0x7;
++
++ iSeries_hlock(hpte_group);
++
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++ hpte_v = iSeries_hpte_getword0(hpte_group + slot_offset);
++
++ if (! (hpte_v & HPTE_V_BOLTED)) {
++ HvCallHpt_invalidateSetSwBitsGet(hpte_group +
++ slot_offset, 0, 0);
++ iSeries_hunlock(hpte_group);
++ return i;
++ }
++
++ slot_offset++;
++ slot_offset &= 0x7;
++ }
++
++ iSeries_hunlock(hpte_group);
++
++ return -1;
++}
++
++/*
++ * The HyperVisor expects the "flags" argument in this form:
++ * bits 0..59 : reserved
++ * bit 60 : N
++ * bits 61..63 : PP2,PP1,PP0
++ */
++static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
++ unsigned long va, int large, int local)
++{
++ hpte_t hpte;
++ unsigned long avpn = va >> 23;
++
++ iSeries_hlock(slot);
++
++ HvCallHpt_get(&hpte, slot);
++ if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) {
++ /*
++ * Hypervisor expects bits as NPPP, which is
++ * different from how they are mapped in our PP.
++ */
++ HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1));
++ iSeries_hunlock(slot);
++ return 0;
++ }
++ iSeries_hunlock(slot);
++
++ return -1;
++}
++
++/*
++ * Functions used to find the PTE for a particular virtual address.
++ * Only used during boot when bolting pages.
++ *
++ * Input : vpn : virtual page number
++ * Output: PTE index within the page table of the entry
++ * -1 on failure
++ */
++static long iSeries_hpte_find(unsigned long vpn)
++{
++ hpte_t hpte;
++ long slot;
++
++ /*
++ * The HvCallHpt_findValid interface is as follows:
++ * 0xffffffffffffffff : No entry found.
++ * 0x00000000xxxxxxxx : Entry found in primary group, slot x
++ * 0x80000000xxxxxxxx : Entry found in secondary group, slot x
++ */
++ slot = HvCallHpt_findValid(&hpte, vpn);
++ if (hpte.v & HPTE_V_VALID) {
++ if (slot < 0) {
++ slot &= 0x7fffffffffffffff;
++ slot = -slot;
++ }
++ } else
++ slot = -1;
++ return slot;
++}
++
++/*
++ * Update the page protection bits. Intended to be used to create
++ * guard pages for kernel data structures on pages which are bolted
++ * in the HPT. Assumes pages being operated on will not be stolen.
++ * Does not work on large pages.
++ *
++ * No need to lock here because we should be the only user.
++ */
++static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
++{
++ unsigned long vsid,va,vpn;
++ long slot;
++
++ vsid = get_kernel_vsid(ea);
++ va = (vsid << 28) | (ea & 0x0fffffff);
++ vpn = va >> PAGE_SHIFT;
++ slot = iSeries_hpte_find(vpn);
++ if (slot == -1)
++ panic("updateboltedpp: Could not find page to bolt\n");
++ HvCallHpt_setPp(slot, newpp);
++}
++
++static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
++ int large, int local)
++{
++ unsigned long hpte_v;
++ unsigned long avpn = va >> 23;
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ iSeries_hlock(slot);
++
++ hpte_v = iSeries_hpte_getword0(slot);
++
++ if ((HPTE_V_AVPN_VAL(hpte_v) == avpn) && (hpte_v & HPTE_V_VALID))
++ HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0);
++
++ iSeries_hunlock(slot);
++
++ local_irq_restore(flags);
++}
++
++void hpte_init_iSeries(void)
++{
++ ppc_md.hpte_invalidate = iSeries_hpte_invalidate;
++ ppc_md.hpte_updatepp = iSeries_hpte_updatepp;
++ ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
++ ppc_md.hpte_insert = iSeries_hpte_insert;
++ ppc_md.hpte_remove = iSeries_hpte_remove;
++
++ htab_finish_init();
++}
+diff --git a/arch/powerpc/platforms/iseries/hvcall.S b/arch/powerpc/platforms/iseries/hvcall.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/hvcall.S
+@@ -0,0 +1,94 @@
++/*
++ * This file contains the code to perform calls to the
++ * iSeries LPAR hypervisor
++ *
++ * 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 <asm/ppc_asm.h>
++#include <asm/processor.h>
++#include <asm/ptrace.h> /* XXX for STACK_FRAME_OVERHEAD */
++
++ .text
++
++/*
++ * Hypervisor call
++ *
++ * Invoke the iSeries hypervisor via the System Call instruction
++ * Parameters are passed to this routine in registers r3 - r10
++ *
++ * r3 contains the HV function to be called
++ * r4-r10 contain the operands to the hypervisor function
++ *
++ */
++
++_GLOBAL(HvCall)
++_GLOBAL(HvCall0)
++_GLOBAL(HvCall1)
++_GLOBAL(HvCall2)
++_GLOBAL(HvCall3)
++_GLOBAL(HvCall4)
++_GLOBAL(HvCall5)
++_GLOBAL(HvCall6)
++_GLOBAL(HvCall7)
++
++
++ mfcr r0
++ std r0,-8(r1)
++ stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1)
++
++ /* r0 = 0xffffffffffffffff indicates a hypervisor call */
++
++ li r0,-1
++
++ /* Invoke the hypervisor */
++
++ sc
++
++ ld r1,0(r1)
++ ld r0,-8(r1)
++ mtcrf 0xff,r0
++
++ /* return to caller, return value in r3 */
++
++ blr
++
++_GLOBAL(HvCall0Ret16)
++_GLOBAL(HvCall1Ret16)
++_GLOBAL(HvCall2Ret16)
++_GLOBAL(HvCall3Ret16)
++_GLOBAL(HvCall4Ret16)
++_GLOBAL(HvCall5Ret16)
++_GLOBAL(HvCall6Ret16)
++_GLOBAL(HvCall7Ret16)
++
++ mfcr r0
++ std r0,-8(r1)
++ std r31,-16(r1)
++ stdu r1,-(STACK_FRAME_OVERHEAD+32)(r1)
++
++ mr r31,r4
++ li r0,-1
++ mr r4,r5
++ mr r5,r6
++ mr r6,r7
++ mr r7,r8
++ mr r8,r9
++ mr r9,r10
++
++ sc
++
++ std r3,0(r31)
++ std r4,8(r31)
++
++ mr r3,r5
++
++ ld r1,0(r1)
++ ld r0,-8(r1)
++ mtcrf 0xff,r0
++ ld r31,-16(r1)
++
++ blr
+diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/hvlog.c
+@@ -0,0 +1,35 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <asm/page.h>
++#include <asm/abs_addr.h>
++#include <asm/iSeries/HvCall.h>
++#include <asm/iSeries/HvCallSc.h>
++#include <asm/iSeries/HvTypes.h>
++
++
++void HvCall_writeLogBuffer(const void *buffer, u64 len)
++{
++ struct HvLpBufferList hv_buf;
++ u64 left_this_page;
++ u64 cur = virt_to_abs(buffer);
++
++ while (len) {
++ hv_buf.addr = cur;
++ left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur;
++ if (left_this_page > len)
++ left_this_page = len;
++ hv_buf.len = left_this_page;
++ len -= left_this_page;
++ HvCall2(HvCallBaseWriteLogBuffer,
++ virt_to_abs(&hv_buf),
++ left_this_page);
++ cur = (cur & PAGE_MASK) + PAGE_SIZE;
++ }
++}
+diff --git a/arch/powerpc/platforms/iseries/hvlpconfig.c b/arch/powerpc/platforms/iseries/hvlpconfig.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/hvlpconfig.c
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (C) 2001 Kyle A. Lucke, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/module.h>
++#include <asm/iSeries/HvLpConfig.h>
++
++HvLpIndex HvLpConfig_getLpIndex_outline(void)
++{
++ return HvLpConfig_getLpIndex();
++}
++EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline);
+diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/iommu.c
+@@ -0,0 +1,178 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
++ *
++ * Rewrite, cleanup:
++ *
++ * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
++ *
++ * Dynamic DMA mapping support, iSeries-specific parts.
++ *
++ *
++ * 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/types.h>
++#include <linux/dma-mapping.h>
++#include <linux/list.h>
++
++#include <asm/iommu.h>
++#include <asm/tce.h>
++#include <asm/machdep.h>
++#include <asm/abs_addr.h>
++#include <asm/pci-bridge.h>
++#include <asm/iSeries/HvCallXm.h>
++
++extern struct list_head iSeries_Global_Device_List;
++
++
++static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
++ unsigned long uaddr, enum dma_data_direction direction)
++{
++ u64 rc;
++ union tce_entry tce;
++
++ while (npages--) {
++ tce.te_word = 0;
++ tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
++
++ if (tbl->it_type == TCE_VB) {
++ /* Virtual Bus */
++ tce.te_bits.tb_valid = 1;
++ tce.te_bits.tb_allio = 1;
++ if (direction != DMA_TO_DEVICE)
++ tce.te_bits.tb_rdwr = 1;
++ } else {
++ /* PCI Bus */
++ tce.te_bits.tb_rdwr = 1; /* Read allowed */
++ if (direction != DMA_TO_DEVICE)
++ tce.te_bits.tb_pciwr = 1;
++ }
++
++ rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
++ tce.te_word);
++ if (rc)
++ panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
++ rc);
++ index++;
++ uaddr += PAGE_SIZE;
++ }
++}
++
++static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
++{
++ u64 rc;
++
++ while (npages--) {
++ rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0);
++ if (rc)
++ panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
++ rc);
++ index++;
++ }
++}
++
++#ifdef CONFIG_PCI
++/*
++ * This function compares the known tables to find an iommu_table
++ * that has already been built for hardware TCEs.
++ */
++static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
++{
++ struct pci_dn *pdn;
++
++ list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
++ struct iommu_table *it = pdn->iommu_table;
++ if ((it != NULL) &&
++ (it->it_type == TCE_PCI) &&
++ (it->it_offset == tbl->it_offset) &&
++ (it->it_index == tbl->it_index) &&
++ (it->it_size == tbl->it_size))
++ return it;
++ }
++ return NULL;
++}
++
++/*
++ * Call Hv with the architected data structure to get TCE table info.
++ * info. Put the returned data into the Linux representation of the
++ * TCE table data.
++ * The Hardware Tce table comes in three flavors.
++ * 1. TCE table shared between Buses.
++ * 2. TCE table per Bus.
++ * 3. TCE Table per IOA.
++ */
++static void iommu_table_getparms(struct pci_dn *pdn,
++ struct iommu_table* tbl)
++{
++ struct iommu_table_cb *parms;
++
++ parms = kmalloc(sizeof(*parms), GFP_KERNEL);
++ if (parms == NULL)
++ panic("PCI_DMA: TCE Table Allocation failed.");
++
++ memset(parms, 0, sizeof(*parms));
++
++ parms->itc_busno = pdn->busno;
++ parms->itc_slotno = pdn->LogicalSlot;
++ parms->itc_virtbus = 0;
++
++ HvCallXm_getTceTableParms(iseries_hv_addr(parms));
++
++ if (parms->itc_size == 0)
++ panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms);
++
++ /* itc_size is in pages worth of table, it_size is in # of entries */
++ tbl->it_size = (parms->itc_size * PAGE_SIZE) / sizeof(union tce_entry);
++ tbl->it_busno = parms->itc_busno;
++ tbl->it_offset = parms->itc_offset;
++ tbl->it_index = parms->itc_index;
++ tbl->it_blocksize = 1;
++ tbl->it_type = TCE_PCI;
++
++ kfree(parms);
++}
++
++
++void iommu_devnode_init_iSeries(struct device_node *dn)
++{
++ struct iommu_table *tbl;
++ struct pci_dn *pdn = PCI_DN(dn);
++
++ tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
++
++ iommu_table_getparms(pdn, tbl);
++
++ /* Look for existing tce table */
++ pdn->iommu_table = iommu_table_find(tbl);
++ if (pdn->iommu_table == NULL)
++ pdn->iommu_table = iommu_init_table(tbl);
++ else
++ kfree(tbl);
++}
++#endif
++
++static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
++static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
++
++void iommu_init_early_iSeries(void)
++{
++ ppc_md.tce_build = tce_build_iSeries;
++ ppc_md.tce_free = tce_free_iSeries;
++
++ ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries;
++ ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries;
++
++ pci_iommu_init();
++}
+diff --git a/arch/powerpc/platforms/iseries/ipl_parms.h b/arch/powerpc/platforms/iseries/ipl_parms.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/ipl_parms.h
+@@ -0,0 +1,70 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _ISERIES_IPL_PARMS_H
++#define _ISERIES_IPL_PARMS_H
++
++/*
++ * This struct maps the IPL Parameters DMA'd from the SP.
++ *
++ * Warning:
++ * This data must map in exactly 64 bytes and match the architecture for
++ * the IPL parms
++ */
++
++#include <asm/types.h>
++
++struct ItIplParmsReal {
++ u8 xFormat; // Defines format of IplParms x00-x00
++ u8 xRsvd01:6; // Reserved x01-x01
++ u8 xAlternateSearch:1; // Alternate search indicator ...
++ u8 xUaSupplied:1; // UA Supplied on programmed IPL...
++ u8 xLsUaFormat; // Format byte for UA x02-x02
++ u8 xRsvd02; // Reserved x03-x03
++ u32 xLsUa; // LS UA x04-x07
++ u32 xUnusedLsLid; // First OS LID to load x08-x0B
++ u16 xLsBusNumber; // LS Bus Number x0C-x0D
++ u8 xLsCardAdr; // LS Card Address x0E-x0E
++ u8 xLsBoardAdr; // LS Board Address x0F-x0F
++ u32 xRsvd03; // Reserved x10-x13
++ u8 xSpcnPresent:1; // SPCN present x14-x14
++ u8 xCpmPresent:1; // CPM present ...
++ u8 xRsvd04:6; // Reserved ...
++ u8 xRsvd05:4; // Reserved x15-x15
++ u8 xKeyLock:4; // Keylock setting ...
++ u8 xRsvd06:6; // Reserved x16-x16
++ u8 xIplMode:2; // Ipl mode (A|B|C|D) ...
++ u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17
++ u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19
++ u16 xPowerOnResetIpl:1; // Indicate POR condition ...
++ u16 xMainStorePreserved:1; // Main Storage is preserved ...
++ u16 xRsvd07:13; // Reserved ...
++ u16 xIplSource:16; // Ipl source x1A-x1B
++ u8 xIplReason:8; // Reason for this IPL x1C-x1C
++ u8 xRsvd08; // Reserved x1D-x1D
++ u16 xRsvd09; // Reserved x1E-x1F
++ u16 xSysBoxType; // System Box Type x20-x21
++ u16 xSysProcType; // System Processor Type x22-x23
++ u32 xRsvd10; // Reserved x24-x27
++ u64 xRsvd11; // Reserved x28-x2F
++ u64 xRsvd12; // Reserved x30-x37
++ u64 xRsvd13; // Reserved x38-x3F
++};
++
++extern struct ItIplParmsReal xItIplParmsReal;
++
++#endif /* _ISERIES_IPL_PARMS_H */
+diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/irq.c
+@@ -0,0 +1,366 @@
++/*
++ * This module supports the iSeries PCI bus interrupt handling
++ * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
++ * Copyright (C) 2004-2005 IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the:
++ * Free Software Foundation, Inc.,
++ * 59 Temple Place, Suite 330,
++ * Boston, MA 02111-1307 USA
++ *
++ * Change Activity:
++ * Created, December 13, 2000 by Wayne Holm
++ * End Change Activity
++ */
++#include <linux/config.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/threads.h>
++#include <linux/smp.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/bootmem.h>
++#include <linux/ide.h>
++#include <linux/irq.h>
++#include <linux/spinlock.h>
++
++#include <asm/ppcdebug.h>
++#include <asm/iSeries/HvTypes.h>
++#include <asm/iSeries/HvLpEvent.h>
++#include <asm/iSeries/HvCallXm.h>
++
++#include "irq.h"
++#include "call_pci.h"
++
++/* This maps virtual irq numbers to real irqs */
++unsigned int virt_irq_to_real_map[NR_IRQS];
++
++/* The next available virtual irq number */
++/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */
++static int next_virtual_irq = 2;
++
++static long Pci_Interrupt_Count;
++static long Pci_Event_Count;
++
++enum XmPciLpEvent_Subtype {
++ XmPciLpEvent_BusCreated = 0, // PHB has been created
++ XmPciLpEvent_BusError = 1, // PHB has failed
++ XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
++ XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
++ XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
++ XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
++ XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
++ XmPciLpEvent_BridgeError = 21, // Bridge Error
++ XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
++};
++
++struct XmPciLpEvent_BusInterrupt {
++ HvBusNumber busNumber;
++ HvSubBusNumber subBusNumber;
++};
++
++struct XmPciLpEvent_NodeInterrupt {
++ HvBusNumber busNumber;
++ HvSubBusNumber subBusNumber;
++ HvAgentId deviceId;
++};
++
++struct XmPciLpEvent {
++ struct HvLpEvent hvLpEvent;
++
++ union {
++ u64 alignData; // Align on an 8-byte boundary
++
++ struct {
++ u32 fisr;
++ HvBusNumber busNumber;
++ HvSubBusNumber subBusNumber;
++ HvAgentId deviceId;
++ } slotInterrupt;
++
++ struct XmPciLpEvent_BusInterrupt busFailed;
++ struct XmPciLpEvent_BusInterrupt busRecovered;
++ struct XmPciLpEvent_BusInterrupt busCreated;
++
++ struct XmPciLpEvent_NodeInterrupt nodeFailed;
++ struct XmPciLpEvent_NodeInterrupt nodeRecovered;
++
++ } eventData;
++
++};
++
++static void intReceived(struct XmPciLpEvent *eventParm,
++ struct pt_regs *regsParm)
++{
++ int irq;
++
++ ++Pci_Interrupt_Count;
++
++ switch (eventParm->hvLpEvent.xSubtype) {
++ case XmPciLpEvent_SlotInterrupt:
++ irq = eventParm->hvLpEvent.xCorrelationToken;
++ /* Dispatch the interrupt handlers for this irq */
++ ppc_irq_dispatch_handler(regsParm, irq);
++ HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
++ eventParm->eventData.slotInterrupt.subBusNumber,
++ eventParm->eventData.slotInterrupt.deviceId);
++ break;
++ /* Ignore error recovery events for now */
++ case XmPciLpEvent_BusCreated:
++ printk(KERN_INFO "intReceived: system bus %d created\n",
++ eventParm->eventData.busCreated.busNumber);
++ break;
++ case XmPciLpEvent_BusError:
++ case XmPciLpEvent_BusFailed:
++ printk(KERN_INFO "intReceived: system bus %d failed\n",
++ eventParm->eventData.busFailed.busNumber);
++ break;
++ case XmPciLpEvent_BusRecovered:
++ case XmPciLpEvent_UnQuiesceBus:
++ printk(KERN_INFO "intReceived: system bus %d recovered\n",
++ eventParm->eventData.busRecovered.busNumber);
++ break;
++ case XmPciLpEvent_NodeFailed:
++ case XmPciLpEvent_BridgeError:
++ printk(KERN_INFO
++ "intReceived: multi-adapter bridge %d/%d/%d failed\n",
++ eventParm->eventData.nodeFailed.busNumber,
++ eventParm->eventData.nodeFailed.subBusNumber,
++ eventParm->eventData.nodeFailed.deviceId);
++ break;
++ case XmPciLpEvent_NodeRecovered:
++ printk(KERN_INFO
++ "intReceived: multi-adapter bridge %d/%d/%d recovered\n",
++ eventParm->eventData.nodeRecovered.busNumber,
++ eventParm->eventData.nodeRecovered.subBusNumber,
++ eventParm->eventData.nodeRecovered.deviceId);
++ break;
++ default:
++ printk(KERN_ERR
++ "intReceived: unrecognized event subtype 0x%x\n",
++ eventParm->hvLpEvent.xSubtype);
++ break;
++ }
++}
++
++static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
++ struct pt_regs *regsParm)
++{
++#ifdef CONFIG_PCI
++ ++Pci_Event_Count;
++
++ if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
++ switch (eventParm->xFlags.xFunction) {
++ case HvLpEvent_Function_Int:
++ intReceived((struct XmPciLpEvent *)eventParm, regsParm);
++ break;
++ case HvLpEvent_Function_Ack:
++ printk(KERN_ERR
++ "XmPciLpEvent_handler: unexpected ack received\n");
++ break;
++ default:
++ printk(KERN_ERR
++ "XmPciLpEvent_handler: unexpected event function %d\n",
++ (int)eventParm->xFlags.xFunction);
++ break;
++ }
++ } else if (eventParm)
++ printk(KERN_ERR
++ "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n",
++ (int)eventParm->xType);
++ else
++ printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n");
++#endif
++}
++
++/*
++ * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
++ * It must be called before the bus walk.
++ */
++void __init iSeries_init_IRQ(void)
++{
++ /* Register PCI event handler and open an event path */
++ int xRc;
++
++ xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
++ &XmPciLpEvent_handler);
++ if (xRc == 0) {
++ xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
++ if (xRc != 0)
++ printk(KERN_ERR "iSeries_init_IRQ: open event path "
++ "failed with rc 0x%x\n", xRc);
++ } else
++ printk(KERN_ERR "iSeries_init_IRQ: register handler "
++ "failed with rc 0x%x\n", xRc);
++}
++
++#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
++#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
++#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
++
++/*
++ * This will be called by device drivers (via enable_IRQ)
++ * to enable INTA in the bridge interrupt status register.
++ */
++static void iSeries_enable_IRQ(unsigned int irq)
++{
++ u32 bus, deviceId, function, mask;
++ const u32 subBus = 0;
++ unsigned int rirq = virt_irq_to_real_map[irq];
++
++ /* The IRQ has already been locked by the caller */
++ bus = REAL_IRQ_TO_BUS(rirq);
++ function = REAL_IRQ_TO_FUNC(rirq);
++ deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
++
++ /* Unmask secondary INTA */
++ mask = 0x80000000;
++ HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
++ PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
++ bus, subBus, deviceId, irq);
++}
++
++/* This is called by iSeries_activate_IRQs */
++static unsigned int iSeries_startup_IRQ(unsigned int irq)
++{
++ u32 bus, deviceId, function, mask;
++ const u32 subBus = 0;
++ unsigned int rirq = virt_irq_to_real_map[irq];
++
++ bus = REAL_IRQ_TO_BUS(rirq);
++ function = REAL_IRQ_TO_FUNC(rirq);
++ deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
++
++ /* Link the IRQ number to the bridge */
++ HvCallXm_connectBusUnit(bus, subBus, deviceId, irq);
++
++ /* Unmask bridge interrupts in the FISR */
++ mask = 0x01010000 << function;
++ HvCallPci_unmaskFisr(bus, subBus, deviceId, mask);
++ iSeries_enable_IRQ(irq);
++ return 0;
++}
++
++/*
++ * This is called out of iSeries_fixup to activate interrupt
++ * generation for usable slots
++ */
++void __init iSeries_activate_IRQs()
++{
++ int irq;
++ unsigned long flags;
++
++ for_each_irq (irq) {
++ irq_desc_t *desc = get_irq_desc(irq);
++
++ if (desc && desc->handler && desc->handler->startup) {
++ spin_lock_irqsave(&desc->lock, flags);
++ desc->handler->startup(irq);
++ spin_unlock_irqrestore(&desc->lock, flags);
++ }
++ }
++}
++
++/* this is not called anywhere currently */
++static void iSeries_shutdown_IRQ(unsigned int irq)
++{
++ u32 bus, deviceId, function, mask;
++ const u32 subBus = 0;
++ unsigned int rirq = virt_irq_to_real_map[irq];
++
++ /* irq should be locked by the caller */
++ bus = REAL_IRQ_TO_BUS(rirq);
++ function = REAL_IRQ_TO_FUNC(rirq);
++ deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
++
++ /* Invalidate the IRQ number in the bridge */
++ HvCallXm_connectBusUnit(bus, subBus, deviceId, 0);
++
++ /* Mask bridge interrupts in the FISR */
++ mask = 0x01010000 << function;
++ HvCallPci_maskFisr(bus, subBus, deviceId, mask);
++}
++
++/*
++ * This will be called by device drivers (via disable_IRQ)
++ * to disable INTA in the bridge interrupt status register.
++ */
++static void iSeries_disable_IRQ(unsigned int irq)
++{
++ u32 bus, deviceId, function, mask;
++ const u32 subBus = 0;
++ unsigned int rirq = virt_irq_to_real_map[irq];
++
++ /* The IRQ has already been locked by the caller */
++ bus = REAL_IRQ_TO_BUS(rirq);
++ function = REAL_IRQ_TO_FUNC(rirq);
++ deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
++
++ /* Mask secondary INTA */
++ mask = 0x80000000;
++ HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
++ PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
++ bus, subBus, deviceId, irq);
++}
++
++/*
++ * Need to define this so ppc_irq_dispatch_handler will NOT call
++ * enable_IRQ at the end of interrupt handling. However, this does
++ * nothing because there is not enough information provided to do
++ * the EOI HvCall. This is done by XmPciLpEvent.c
++ */
++static void iSeries_end_IRQ(unsigned int irq)
++{
++}
++
++static hw_irq_controller iSeries_IRQ_handler = {
++ .typename = "iSeries irq controller",
++ .startup = iSeries_startup_IRQ,
++ .shutdown = iSeries_shutdown_IRQ,
++ .enable = iSeries_enable_IRQ,
++ .disable = iSeries_disable_IRQ,
++ .end = iSeries_end_IRQ
++};
++
++/*
++ * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
++ * It calculates the irq value for the slot.
++ * Note that subBusNumber is always 0 (at the moment at least).
++ */
++int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
++ HvSubBusNumber subBusNumber, HvAgentId deviceId)
++{
++ unsigned int realirq, virtirq;
++ u8 idsel = (deviceId >> 4);
++ u8 function = deviceId & 7;
++
++ virtirq = next_virtual_irq++;
++ realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
++ virt_irq_to_real_map[virtirq] = realirq;
++
++ irq_desc[virtirq].handler = &iSeries_IRQ_handler;
++ return virtirq;
++}
++
++int virt_irq_create_mapping(unsigned int real_irq)
++{
++ BUG(); /* Don't call this on iSeries, yet */
++
++ return 0;
++}
++
++void virt_irq_init(void)
++{
++ return;
++}
+diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/irq.h
+@@ -0,0 +1,8 @@
++#ifndef _ISERIES_IRQ_H
++#define _ISERIES_IRQ_H
++
++extern void iSeries_init_IRQ(void);
++extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
++extern void iSeries_activate_IRQs(void);
++
++#endif /* _ISERIES_IRQ_H */
+diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/ksyms.c
+@@ -0,0 +1,27 @@
++/*
++ * (C) 2001-2005 PPC 64 Team, IBM Corp
++ *
++ * 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 <asm/hw_irq.h>
++#include <asm/iSeries/HvCallSc.h>
++
++EXPORT_SYMBOL(HvCall0);
++EXPORT_SYMBOL(HvCall1);
++EXPORT_SYMBOL(HvCall2);
++EXPORT_SYMBOL(HvCall3);
++EXPORT_SYMBOL(HvCall4);
++EXPORT_SYMBOL(HvCall5);
++EXPORT_SYMBOL(HvCall6);
++EXPORT_SYMBOL(HvCall7);
++
++#ifdef CONFIG_SMP
++EXPORT_SYMBOL(local_get_flags);
++EXPORT_SYMBOL(local_irq_disable);
++EXPORT_SYMBOL(local_irq_restore);
++#endif
+diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/lpardata.c
+@@ -0,0 +1,227 @@
++/*
++ * Copyright 2001 Mike Corrigan, IBM Corp
++ *
++ * 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/types.h>
++#include <linux/threads.h>
++#include <linux/module.h>
++#include <linux/bitops.h>
++#include <asm/processor.h>
++#include <asm/ptrace.h>
++#include <asm/naca.h>
++#include <asm/abs_addr.h>
++#include <asm/iSeries/ItLpNaca.h>
++#include <asm/lppaca.h>
++#include <asm/iSeries/ItLpRegSave.h>
++#include <asm/paca.h>
++#include <asm/iSeries/LparMap.h>
++#include <asm/iSeries/ItExtVpdPanel.h>
++#include <asm/iSeries/ItLpQueue.h>
++
++#include "vpd_areas.h"
++#include "spcomm_area.h"
++#include "ipl_parms.h"
++#include "processor_vpd.h"
++#include "release_data.h"
++
++/* The HvReleaseData is the root of the information shared between
++ * the hypervisor and Linux.
++ */
++struct HvReleaseData hvReleaseData = {
++ .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */
++ .xSize = sizeof(struct HvReleaseData),
++ .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
++ .xSlicNacaAddr = &naca, /* 64-bit Naca address */
++ .xMsNucDataOffset = LPARMAP_PHYS,
++ .xFlags = HVREL_TAGSINACTIVE /* tags inactive */
++ /* 64 bit */
++ /* shared processors */
++ /* HMT allowed */
++ | 6, /* TEMP: This allows non-GA driver */
++ .xVrmIndex = 4, /* We are v5r2m0 */
++ .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */
++ .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */
++ .xVrmName = { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4.64" ebcdic */
++ 0xa7, 0x40, 0xf2, 0x4b,
++ 0xf4, 0x4b, 0xf6, 0xf4 },
++};
++
++/*
++ * The NACA. The first dword of the naca is required by the iSeries
++ * hypervisor to point to itVpdAreas. The hypervisor finds the NACA
++ * through the pointer in hvReleaseData.
++ */
++struct naca_struct naca = {
++ .xItVpdAreas = &itVpdAreas,
++ .xRamDisk = 0,
++ .xRamDiskSize = 0,
++};
++
++extern void system_reset_iSeries(void);
++extern void machine_check_iSeries(void);
++extern void data_access_iSeries(void);
++extern void instruction_access_iSeries(void);
++extern void hardware_interrupt_iSeries(void);
++extern void alignment_iSeries(void);
++extern void program_check_iSeries(void);
++extern void fp_unavailable_iSeries(void);
++extern void decrementer_iSeries(void);
++extern void trap_0a_iSeries(void);
++extern void trap_0b_iSeries(void);
++extern void system_call_iSeries(void);
++extern void single_step_iSeries(void);
++extern void trap_0e_iSeries(void);
++extern void performance_monitor_iSeries(void);
++extern void data_access_slb_iSeries(void);
++extern void instruction_access_slb_iSeries(void);
++
++struct ItLpNaca itLpNaca = {
++ .xDesc = 0xd397d581, /* "LpNa" ebcdic */
++ .xSize = 0x0400, /* size of ItLpNaca */
++ .xIntHdlrOffset = 0x0300, /* offset to int array */
++ .xMaxIntHdlrEntries = 19, /* # ents */
++ .xPrimaryLpIndex = 0, /* Part # of primary */
++ .xServiceLpIndex = 0, /* Part # of serv */
++ .xLpIndex = 0, /* Part # of me */
++ .xMaxLpQueues = 0, /* # of LP queues */
++ .xLpQueueOffset = 0x100, /* offset of start of LP queues */
++ .xPirEnvironMode = 0, /* Piranha stuff */
++ .xPirConsoleMode = 0,
++ .xPirDasdMode = 0,
++ .xLparInstalled = 0,
++ .xSysPartitioned = 0,
++ .xHwSyncedTBs = 0,
++ .xIntProcUtilHmt = 0,
++ .xSpVpdFormat = 0,
++ .xIntProcRatio = 0,
++ .xPlicVrmIndex = 0, /* VRM index of PLIC */
++ .xMinSupportedSlicVrmInd = 0, /* min supported SLIC */
++ .xMinCompatableSlicVrmInd = 0, /* min compat SLIC */
++ .xLoadAreaAddr = 0, /* 64-bit addr of load area */
++ .xLoadAreaChunks = 0, /* chunks for load area */
++ .xPaseSysCallCRMask = 0, /* PASE mask */
++ .xSlicSegmentTablePtr = 0, /* seg table */
++ .xOldLpQueue = { 0 }, /* Old LP Queue */
++ .xInterruptHdlr = {
++ (u64)system_reset_iSeries, /* 0x100 System Reset */
++ (u64)machine_check_iSeries, /* 0x200 Machine Check */
++ (u64)data_access_iSeries, /* 0x300 Data Access */
++ (u64)instruction_access_iSeries, /* 0x400 Instruction Access */
++ (u64)hardware_interrupt_iSeries, /* 0x500 External */
++ (u64)alignment_iSeries, /* 0x600 Alignment */
++ (u64)program_check_iSeries, /* 0x700 Program Check */
++ (u64)fp_unavailable_iSeries, /* 0x800 FP Unavailable */
++ (u64)decrementer_iSeries, /* 0x900 Decrementer */
++ (u64)trap_0a_iSeries, /* 0xa00 Trap 0A */
++ (u64)trap_0b_iSeries, /* 0xb00 Trap 0B */
++ (u64)system_call_iSeries, /* 0xc00 System Call */
++ (u64)single_step_iSeries, /* 0xd00 Single Step */
++ (u64)trap_0e_iSeries, /* 0xe00 Trap 0E */
++ (u64)performance_monitor_iSeries,/* 0xf00 Performance Monitor */
++ 0, /* int 0x1000 */
++ 0, /* int 0x1010 */
++ 0, /* int 0x1020 CPU ctls */
++ (u64)hardware_interrupt_iSeries, /* SC Ret Hdlr */
++ (u64)data_access_slb_iSeries, /* 0x380 D-SLB */
++ (u64)instruction_access_slb_iSeries /* 0x480 I-SLB */
++ }
++};
++EXPORT_SYMBOL(itLpNaca);
++
++/* May be filled in by the hypervisor so cannot end up in the BSS */
++struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
++
++/* May be filled in by the hypervisor so cannot end up in the BSS */
++struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data")));
++EXPORT_SYMBOL(xItExtVpdPanel);
++
++#define maxPhysicalProcessors 32
++
++struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
++ {
++ .xInstCacheOperandSize = 32,
++ .xDataCacheOperandSize = 32,
++ .xProcFreq = 50000000,
++ .xTimeBaseFreq = 50000000,
++ .xPVR = 0x3600
++ }
++};
++
++/* Space for Main Store Vpd 27,200 bytes */
++/* May be filled in by the hypervisor so cannot end up in the BSS */
++u64 xMsVpd[3400] __attribute__((__section__(".data")));
++
++/* Space for Recovery Log Buffer */
++/* May be filled in by the hypervisor so cannot end up in the BSS */
++u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
++
++struct SpCommArea xSpCommArea = {
++ .xDesc = 0xE2D7C3C2,
++ .xFormat = 1,
++};
++
++/* The LparMap data is now located at offset 0x6000 in head.S
++ * It was put there so that the HvReleaseData could address it
++ * with a 32-bit offset as required by the iSeries hypervisor
++ *
++ * The Naca has a pointer to the ItVpdAreas. The hypervisor finds
++ * the Naca via the HvReleaseData area. The HvReleaseData has the
++ * offset into the Naca of the pointer to the ItVpdAreas.
++ */
++struct ItVpdAreas itVpdAreas = {
++ .xSlicDesc = 0xc9a3e5c1, /* "ItVA" */
++ .xSlicSize = sizeof(struct ItVpdAreas),
++ .xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */
++ .xSlicDmaEntries = ItDmaMaxEntries, /* # DMA array entries */
++ .xSlicMaxLogicalProcs = NR_CPUS * 2, /* Max logical procs */
++ .xSlicMaxPhysicalProcs = maxPhysicalProcessors, /* Max physical procs */
++ .xSlicDmaToksOffset = offsetof(struct ItVpdAreas, xPlicDmaToks),
++ .xSlicVpdAdrsOffset = offsetof(struct ItVpdAreas, xSlicVpdAdrs),
++ .xSlicDmaLensOffset = offsetof(struct ItVpdAreas, xPlicDmaLens),
++ .xSlicVpdLensOffset = offsetof(struct ItVpdAreas, xSlicVpdLens),
++ .xSlicMaxSlotLabels = 0, /* max slot labels */
++ .xSlicMaxLpQueues = 1, /* max LP queues */
++ .xPlicDmaLens = { 0 }, /* DMA lengths */
++ .xPlicDmaToks = { 0 }, /* DMA tokens */
++ .xSlicVpdLens = { /* VPD lengths */
++ 0,0,0, /* 0 - 2 */
++ sizeof(xItExtVpdPanel), /* 3 Extended VPD */
++ sizeof(struct paca_struct), /* 4 length of Paca */
++ 0, /* 5 */
++ sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
++ 26992, /* 7 length of MS VPD */
++ 0, /* 8 */
++ sizeof(struct ItLpNaca),/* 9 length of LP Naca */
++ 0, /* 10 */
++ 256, /* 11 length of Recovery Log Buf */
++ sizeof(struct SpCommArea), /* 12 length of SP Comm Area */
++ 0,0,0, /* 13 - 15 */
++ sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */
++ 0,0,0,0,0,0, /* 17 - 22 */
++ sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */
++ 0,0 /* 24 - 25 */
++ },
++ .xSlicVpdAdrs = { /* VPD addresses */
++ 0,0,0, /* 0 - 2 */
++ &xItExtVpdPanel, /* 3 Extended VPD */
++ &paca[0], /* 4 first Paca */
++ 0, /* 5 */
++ &xItIplParmsReal, /* 6 IPL parms */
++ &xMsVpd, /* 7 MS Vpd */
++ 0, /* 8 */
++ &itLpNaca, /* 9 LpNaca */
++ 0, /* 10 */
++ &xRecoveryLogBuffer, /* 11 Recovery Log Buffer */
++ &xSpCommArea, /* 12 SP Comm Area */
++ 0,0,0, /* 13 - 15 */
++ &xIoHriProcessorVpd, /* 16 Proc Vpd */
++ 0,0,0,0,0,0, /* 17 - 22 */
++ &hvlpevent_queue, /* 23 Lp Queue */
++ 0,0
++ }
++};
+diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/lpevents.c
+@@ -0,0 +1,325 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <linux/seq_file.h>
++#include <linux/proc_fs.h>
++#include <linux/module.h>
++
++#include <asm/system.h>
++#include <asm/paca.h>
++#include <asm/iSeries/ItLpQueue.h>
++#include <asm/iSeries/HvLpEvent.h>
++#include <asm/iSeries/HvCallEvent.h>
++#include <asm/iSeries/ItLpNaca.h>
++
++/*
++ * The LpQueue is used to pass event data from the hypervisor to
++ * the partition. This is where I/O interrupt events are communicated.
++ *
++ * It is written to by the hypervisor so cannot end up in the BSS.
++ */
++struct hvlpevent_queue hvlpevent_queue __attribute__((__section__(".data")));
++
++DEFINE_PER_CPU(unsigned long[HvLpEvent_Type_NumTypes], hvlpevent_counts);
++
++static char *event_types[HvLpEvent_Type_NumTypes] = {
++ "Hypervisor",
++ "Machine Facilities",
++ "Session Manager",
++ "SPD I/O",
++ "Virtual Bus",
++ "PCI I/O",
++ "RIO I/O",
++ "Virtual Lan",
++ "Virtual I/O"
++};
++
++/* Array of LpEvent handler functions */
++static LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
++static unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes];
++
++static struct HvLpEvent * get_next_hvlpevent(void)
++{
++ struct HvLpEvent * event;
++ event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
++
++ if (event->xFlags.xValid) {
++ /* rmb() needed only for weakly consistent machines (regatta) */
++ rmb();
++ /* Set pointer to next potential event */
++ hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 +
++ LpEventAlign) / LpEventAlign) * LpEventAlign;
++
++ /* Wrap to beginning if no room at end */
++ if (hvlpevent_queue.xSlicCurEventPtr >
++ hvlpevent_queue.xSlicLastValidEventPtr) {
++ hvlpevent_queue.xSlicCurEventPtr =
++ hvlpevent_queue.xSlicEventStackPtr;
++ }
++ } else {
++ event = NULL;
++ }
++
++ return event;
++}
++
++static unsigned long spread_lpevents = NR_CPUS;
++
++int hvlpevent_is_pending(void)
++{
++ struct HvLpEvent *next_event;
++
++ if (smp_processor_id() >= spread_lpevents)
++ return 0;
++
++ next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
++
++ return next_event->xFlags.xValid |
++ hvlpevent_queue.xPlicOverflowIntPending;
++}
++
++static void hvlpevent_clear_valid(struct HvLpEvent * event)
++{
++ /* Tell the Hypervisor that we're done with this event.
++ * Also clear bits within this event that might look like valid bits.
++ * ie. on 64-byte boundaries.
++ */
++ struct HvLpEvent *tmp;
++ unsigned extra = ((event->xSizeMinus1 + LpEventAlign) /
++ LpEventAlign) - 1;
++
++ switch (extra) {
++ case 3:
++ tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);
++ tmp->xFlags.xValid = 0;
++ case 2:
++ tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);
++ tmp->xFlags.xValid = 0;
++ case 1:
++ tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);
++ tmp->xFlags.xValid = 0;
++ }
++
++ mb();
++
++ event->xFlags.xValid = 0;
++}
++
++void process_hvlpevents(struct pt_regs *regs)
++{
++ struct HvLpEvent * event;
++
++ /* If we have recursed, just return */
++ if (!spin_trylock(&hvlpevent_queue.lock))
++ return;
++
++ for (;;) {
++ event = get_next_hvlpevent();
++ if (event) {
++ /* Call appropriate handler here, passing
++ * a pointer to the LpEvent. The handler
++ * must make a copy of the LpEvent if it
++ * needs it in a bottom half. (perhaps for
++ * an ACK)
++ *
++ * Handlers are responsible for ACK processing
++ *
++ * The Hypervisor guarantees that LpEvents will
++ * only be delivered with types that we have
++ * registered for, so no type check is necessary
++ * here!
++ */
++ if (event->xType < HvLpEvent_Type_NumTypes)
++ __get_cpu_var(hvlpevent_counts)[event->xType]++;
++ if (event->xType < HvLpEvent_Type_NumTypes &&
++ lpEventHandler[event->xType])
++ lpEventHandler[event->xType](event, regs);
++ else
++ printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
++
++ hvlpevent_clear_valid(event);
++ } else if (hvlpevent_queue.xPlicOverflowIntPending)
++ /*
++ * No more valid events. If overflow events are
++ * pending process them
++ */
++ HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex);
++ else
++ break;
++ }
++
++ spin_unlock(&hvlpevent_queue.lock);
++}
++
++static int set_spread_lpevents(char *str)
++{
++ unsigned long val = simple_strtoul(str, NULL, 0);
++
++ /*
++ * The parameter is the number of processors to share in processing
++ * lp events.
++ */
++ if (( val > 0) && (val <= NR_CPUS)) {
++ spread_lpevents = val;
++ printk("lpevent processing spread over %ld processors\n", val);
++ } else {
++ printk("invalid spread_lpevents %ld\n", val);
++ }
++
++ return 1;
++}
++__setup("spread_lpevents=", set_spread_lpevents);
++
++void setup_hvlpevent_queue(void)
++{
++ void *eventStack;
++
++ /* Allocate a page for the Event Stack. */
++ eventStack = alloc_bootmem_pages(LpEventStackSize);
++ memset(eventStack, 0, LpEventStackSize);
++
++ /* Invoke the hypervisor to initialize the event stack */
++ HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);
++
++ hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack;
++ hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack;
++ hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack +
++ (LpEventStackSize - LpEventMaxSize);
++ hvlpevent_queue.xIndex = 0;
++}
++
++/* Register a handler for an LpEvent type */
++int HvLpEvent_registerHandler(HvLpEvent_Type eventType, LpEventHandler handler)
++{
++ if (eventType < HvLpEvent_Type_NumTypes) {
++ lpEventHandler[eventType] = handler;
++ return 0;
++ }
++ return 1;
++}
++EXPORT_SYMBOL(HvLpEvent_registerHandler);
++
++int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType)
++{
++ might_sleep();
++
++ if (eventType < HvLpEvent_Type_NumTypes) {
++ if (!lpEventHandlerPaths[eventType]) {
++ lpEventHandler[eventType] = NULL;
++ /*
++ * We now sleep until all other CPUs have scheduled.
++ * This ensures that the deletion is seen by all
++ * other CPUs, and that the deleted handler isn't
++ * still running on another CPU when we return.
++ */
++ synchronize_rcu();
++ return 0;
++ }
++ }
++ return 1;
++}
++EXPORT_SYMBOL(HvLpEvent_unregisterHandler);
++
++/*
++ * lpIndex is the partition index of the target partition.
++ * needed only for VirtualIo, VirtualLan and SessionMgr. Zero
++ * indicates to use our partition index - for the other types.
++ */
++int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex)
++{
++ if ((eventType < HvLpEvent_Type_NumTypes) &&
++ lpEventHandler[eventType]) {
++ if (lpIndex == 0)
++ lpIndex = itLpNaca.xLpIndex;
++ HvCallEvent_openLpEventPath(lpIndex, eventType);
++ ++lpEventHandlerPaths[eventType];
++ return 0;
++ }
++ return 1;
++}
++
++int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex)
++{
++ if ((eventType < HvLpEvent_Type_NumTypes) &&
++ lpEventHandler[eventType] &&
++ lpEventHandlerPaths[eventType]) {
++ if (lpIndex == 0)
++ lpIndex = itLpNaca.xLpIndex;
++ HvCallEvent_closeLpEventPath(lpIndex, eventType);
++ --lpEventHandlerPaths[eventType];
++ return 0;
++ }
++ return 1;
++}
++
++static int proc_lpevents_show(struct seq_file *m, void *v)
++{
++ int cpu, i;
++ unsigned long sum;
++ static unsigned long cpu_totals[NR_CPUS];
++
++ /* FIXME: do we care that there's no locking here? */
++ sum = 0;
++ for_each_online_cpu(cpu) {
++ cpu_totals[cpu] = 0;
++ for (i = 0; i < HvLpEvent_Type_NumTypes; i++) {
++ cpu_totals[cpu] += per_cpu(hvlpevent_counts, cpu)[i];
++ }
++ sum += cpu_totals[cpu];
++ }
++
++ seq_printf(m, "LpEventQueue 0\n");
++ seq_printf(m, " events processed:\t%lu\n", sum);
++
++ for (i = 0; i < HvLpEvent_Type_NumTypes; ++i) {
++ sum = 0;
++ for_each_online_cpu(cpu) {
++ sum += per_cpu(hvlpevent_counts, cpu)[i];
++ }
++
++ seq_printf(m, " %-20s %10lu\n", event_types[i], sum);
++ }
++
++ seq_printf(m, "\n events processed by processor:\n");
++
++ for_each_online_cpu(cpu) {
++ seq_printf(m, " CPU%02d %10lu\n", cpu, cpu_totals[cpu]);
++ }
++
++ return 0;
++}
++
++static int proc_lpevents_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, proc_lpevents_show, NULL);
++}
++
++static struct file_operations proc_lpevents_operations = {
++ .open = proc_lpevents_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init proc_lpevents_init(void)
++{
++ struct proc_dir_entry *e;
++
++ e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
++ if (e)
++ e->proc_fops = &proc_lpevents_operations;
++
++ return 0;
++}
++__initcall(proc_lpevents_init);
++
+diff --git a/arch/powerpc/platforms/iseries/main_store.h b/arch/powerpc/platforms/iseries/main_store.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/main_store.h
+@@ -0,0 +1,165 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _ISERIES_MAIN_STORE_H
++#define _ISERIES_MAIN_STORE_H
++
++/* Main Store Vpd for Condor,iStar,sStar */
++struct IoHriMainStoreSegment4 {
++ u8 msArea0Exists:1;
++ u8 msArea1Exists:1;
++ u8 msArea2Exists:1;
++ u8 msArea3Exists:1;
++ u8 reserved1:4;
++ u8 reserved2;
++
++ u8 msArea0Functional:1;
++ u8 msArea1Functional:1;
++ u8 msArea2Functional:1;
++ u8 msArea3Functional:1;
++ u8 reserved3:4;
++ u8 reserved4;
++
++ u32 totalMainStore;
++
++ u64 msArea0Ptr;
++ u64 msArea1Ptr;
++ u64 msArea2Ptr;
++ u64 msArea3Ptr;
++
++ u32 cardProductionLevel;
++
++ u32 msAdrHole;
++
++ u8 msArea0HasRiserVpd:1;
++ u8 msArea1HasRiserVpd:1;
++ u8 msArea2HasRiserVpd:1;
++ u8 msArea3HasRiserVpd:1;
++ u8 reserved5:4;
++ u8 reserved6;
++ u16 reserved7;
++
++ u8 reserved8[28];
++
++ u64 nonInterleavedBlocksStartAdr;
++ u64 nonInterleavedBlocksEndAdr;
++};
++
++/* Main Store VPD for Power4 */
++struct IoHriMainStoreChipInfo1 {
++ u32 chipMfgID __attribute((packed));
++ char chipECLevel[4] __attribute((packed));
++};
++
++struct IoHriMainStoreVpdIdData {
++ char typeNumber[4];
++ char modelNumber[4];
++ char partNumber[12];
++ char serialNumber[12];
++};
++
++struct IoHriMainStoreVpdFruData {
++ char fruLabel[8] __attribute((packed));
++ u8 numberOfSlots __attribute((packed));
++ u8 pluggingType __attribute((packed));
++ u16 slotMapIndex __attribute((packed));
++};
++
++struct IoHriMainStoreAdrRangeBlock {
++ void *blockStart __attribute((packed));
++ void *blockEnd __attribute((packed));
++ u32 blockProcChipId __attribute((packed));
++};
++
++#define MaxAreaAdrRangeBlocks 4
++
++struct IoHriMainStoreArea4 {
++ u32 msVpdFormat __attribute((packed));
++ u8 containedVpdType __attribute((packed));
++ u8 reserved1 __attribute((packed));
++ u16 reserved2 __attribute((packed));
++
++ u64 msExists __attribute((packed));
++ u64 msFunctional __attribute((packed));
++
++ u32 memorySize __attribute((packed));
++ u32 procNodeId __attribute((packed));
++
++ u32 numAdrRangeBlocks __attribute((packed));
++ struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed));
++
++ struct IoHriMainStoreChipInfo1 chipInfo0 __attribute((packed));
++ struct IoHriMainStoreChipInfo1 chipInfo1 __attribute((packed));
++ struct IoHriMainStoreChipInfo1 chipInfo2 __attribute((packed));
++ struct IoHriMainStoreChipInfo1 chipInfo3 __attribute((packed));
++ struct IoHriMainStoreChipInfo1 chipInfo4 __attribute((packed));
++ struct IoHriMainStoreChipInfo1 chipInfo5 __attribute((packed));
++ struct IoHriMainStoreChipInfo1 chipInfo6 __attribute((packed));
++ struct IoHriMainStoreChipInfo1 chipInfo7 __attribute((packed));
++
++ void *msRamAreaArray __attribute((packed));
++ u32 msRamAreaArrayNumEntries __attribute((packed));
++ u32 msRamAreaArrayEntrySize __attribute((packed));
++
++ u32 numaDimmExists __attribute((packed));
++ u32 numaDimmFunctional __attribute((packed));
++ void *numaDimmArray __attribute((packed));
++ u32 numaDimmArrayNumEntries __attribute((packed));
++ u32 numaDimmArrayEntrySize __attribute((packed));
++
++ struct IoHriMainStoreVpdIdData idData __attribute((packed));
++
++ u64 powerData __attribute((packed));
++ u64 cardAssemblyPartNum __attribute((packed));
++ u64 chipSerialNum __attribute((packed));
++
++ u64 reserved3 __attribute((packed));
++ char reserved4[16] __attribute((packed));
++
++ struct IoHriMainStoreVpdFruData fruData __attribute((packed));
++
++ u8 vpdPortNum __attribute((packed));
++ u8 reserved5 __attribute((packed));
++ u8 frameId __attribute((packed));
++ u8 rackUnit __attribute((packed));
++ char asciiKeywordVpd[256] __attribute((packed));
++ u32 reserved6 __attribute((packed));
++};
++
++
++struct IoHriMainStoreSegment5 {
++ u16 reserved1;
++ u8 reserved2;
++ u8 msVpdFormat;
++
++ u32 totalMainStore;
++ u64 maxConfiguredMsAdr;
++
++ struct IoHriMainStoreArea4 *msAreaArray;
++ u32 msAreaArrayNumEntries;
++ u32 msAreaArrayEntrySize;
++
++ u32 msAreaExists;
++ u32 msAreaFunctional;
++
++ u64 reserved3;
++};
++
++extern u64 xMsVpd[];
++
++#endif /* _ISERIES_MAIN_STORE_H */
+diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/mf.c
+@@ -0,0 +1,1321 @@
++/*
++ * Copyright (C) 2001 Troy D. Armstrong IBM Corporation
++ * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation
++ *
++ * This modules exists as an interface between a Linux secondary partition
++ * running on an iSeries and the primary partition's Virtual Service
++ * Processor (VSP) object. The VSP has final authority over powering on/off
++ * all partitions in the iSeries. It also provides miscellaneous low-level
++ * machine facility type operations.
++ *
++ *
++ * 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/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/bcd.h>
++#include <linux/rtc.h>
++
++#include <asm/time.h>
++#include <asm/uaccess.h>
++#include <asm/paca.h>
++#include <asm/abs_addr.h>
++#include <asm/iSeries/vio.h>
++#include <asm/iSeries/mf.h>
++#include <asm/iSeries/HvLpConfig.h>
++#include <asm/iSeries/ItLpQueue.h>
++
++#include "setup.h"
++
++extern int piranha_simulator;
++
++/*
++ * This is the structure layout for the Machine Facilites LPAR event
++ * flows.
++ */
++struct vsp_cmd_data {
++ u64 token;
++ u16 cmd;
++ HvLpIndex lp_index;
++ u8 result_code;
++ u32 reserved;
++ union {
++ u64 state; /* GetStateOut */
++ u64 ipl_type; /* GetIplTypeOut, Function02SelectIplTypeIn */
++ u64 ipl_mode; /* GetIplModeOut, Function02SelectIplModeIn */
++ u64 page[4]; /* GetSrcHistoryIn */
++ u64 flag; /* GetAutoIplWhenPrimaryIplsOut,
++ SetAutoIplWhenPrimaryIplsIn,
++ WhiteButtonPowerOffIn,
++ Function08FastPowerOffIn,
++ IsSpcnRackPowerIncompleteOut */
++ struct {
++ u64 token;
++ u64 address_type;
++ u64 side;
++ u32 length;
++ u32 offset;
++ } kern; /* SetKernelImageIn, GetKernelImageIn,
++ SetKernelCmdLineIn, GetKernelCmdLineIn */
++ u32 length_out; /* GetKernelImageOut, GetKernelCmdLineOut */
++ u8 reserved[80];
++ } sub_data;
++};
++
++struct vsp_rsp_data {
++ struct completion com;
++ struct vsp_cmd_data *response;
++};
++
++struct alloc_data {
++ u16 size;
++ u16 type;
++ u32 count;
++ u16 reserved1;
++ u8 reserved2;
++ HvLpIndex target_lp;
++};
++
++struct ce_msg_data;
++
++typedef void (*ce_msg_comp_hdlr)(void *token, struct ce_msg_data *vsp_cmd_rsp);
++
++struct ce_msg_comp_data {
++ ce_msg_comp_hdlr handler;
++ void *token;
++};
++
++struct ce_msg_data {
++ u8 ce_msg[12];
++ char reserved[4];
++ struct ce_msg_comp_data *completion;
++};
++
++struct io_mf_lp_event {
++ struct HvLpEvent hp_lp_event;
++ u16 subtype_result_code;
++ u16 reserved1;
++ u32 reserved2;
++ union {
++ struct alloc_data alloc;
++ struct ce_msg_data ce_msg;
++ struct vsp_cmd_data vsp_cmd;
++ } data;
++};
++
++#define subtype_data(a, b, c, d) \
++ (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
++
++/*
++ * All outgoing event traffic is kept on a FIFO queue. The first
++ * pointer points to the one that is outstanding, and all new
++ * requests get stuck on the end. Also, we keep a certain number of
++ * preallocated pending events so that we can operate very early in
++ * the boot up sequence (before kmalloc is ready).
++ */
++struct pending_event {
++ struct pending_event *next;
++ struct io_mf_lp_event event;
++ MFCompleteHandler hdlr;
++ char dma_data[72];
++ unsigned dma_data_length;
++ unsigned remote_address;
++};
++static spinlock_t pending_event_spinlock;
++static struct pending_event *pending_event_head;
++static struct pending_event *pending_event_tail;
++static struct pending_event *pending_event_avail;
++static struct pending_event pending_event_prealloc[16];
++
++/*
++ * Put a pending event onto the available queue, so it can get reused.
++ * Attention! You must have the pending_event_spinlock before calling!
++ */
++static void free_pending_event(struct pending_event *ev)
++{
++ if (ev != NULL) {
++ ev->next = pending_event_avail;
++ pending_event_avail = ev;
++ }
++}
++
++/*
++ * Enqueue the outbound event onto the stack. If the queue was
++ * empty to begin with, we must also issue it via the Hypervisor
++ * interface. There is a section of code below that will touch
++ * the first stack pointer without the protection of the pending_event_spinlock.
++ * This is OK, because we know that nobody else will be modifying
++ * the first pointer when we do this.
++ */
++static int signal_event(struct pending_event *ev)
++{
++ int rc = 0;
++ unsigned long flags;
++ int go = 1;
++ struct pending_event *ev1;
++ HvLpEvent_Rc hv_rc;
++
++ /* enqueue the event */
++ if (ev != NULL) {
++ ev->next = NULL;
++ spin_lock_irqsave(&pending_event_spinlock, flags);
++ if (pending_event_head == NULL)
++ pending_event_head = ev;
++ else {
++ go = 0;
++ pending_event_tail->next = ev;
++ }
++ pending_event_tail = ev;
++ spin_unlock_irqrestore(&pending_event_spinlock, flags);
++ }
++
++ /* send the event */
++ while (go) {
++ go = 0;
++
++ /* any DMA data to send beforehand? */
++ if (pending_event_head->dma_data_length > 0)
++ HvCallEvent_dmaToSp(pending_event_head->dma_data,
++ pending_event_head->remote_address,
++ pending_event_head->dma_data_length,
++ HvLpDma_Direction_LocalToRemote);
++
++ hv_rc = HvCallEvent_signalLpEvent(
++ &pending_event_head->event.hp_lp_event);
++ if (hv_rc != HvLpEvent_Rc_Good) {
++ printk(KERN_ERR "mf.c: HvCallEvent_signalLpEvent() "
++ "failed with %d\n", (int)hv_rc);
++
++ spin_lock_irqsave(&pending_event_spinlock, flags);
++ ev1 = pending_event_head;
++ pending_event_head = pending_event_head->next;
++ if (pending_event_head != NULL)
++ go = 1;
++ spin_unlock_irqrestore(&pending_event_spinlock, flags);
++
++ if (ev1 == ev)
++ rc = -EIO;
++ else if (ev1->hdlr != NULL)
++ (*ev1->hdlr)((void *)ev1->event.hp_lp_event.xCorrelationToken, -EIO);
++
++ spin_lock_irqsave(&pending_event_spinlock, flags);
++ free_pending_event(ev1);
++ spin_unlock_irqrestore(&pending_event_spinlock, flags);
++ }
++ }
++
++ return rc;
++}
++
++/*
++ * Allocate a new pending_event structure, and initialize it.
++ */
++static struct pending_event *new_pending_event(void)
++{
++ struct pending_event *ev = NULL;
++ HvLpIndex primary_lp = HvLpConfig_getPrimaryLpIndex();
++ unsigned long flags;
++ struct HvLpEvent *hev;
++
++ spin_lock_irqsave(&pending_event_spinlock, flags);
++ if (pending_event_avail != NULL) {
++ ev = pending_event_avail;
++ pending_event_avail = pending_event_avail->next;
++ }
++ spin_unlock_irqrestore(&pending_event_spinlock, flags);
++ if (ev == NULL) {
++ ev = kmalloc(sizeof(struct pending_event), GFP_ATOMIC);
++ if (ev == NULL) {
++ printk(KERN_ERR "mf.c: unable to kmalloc %ld bytes\n",
++ sizeof(struct pending_event));
++ return NULL;
++ }
++ }
++ memset(ev, 0, sizeof(struct pending_event));
++ hev = &ev->event.hp_lp_event;
++ hev->xFlags.xValid = 1;
++ hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck;
++ hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck;
++ hev->xFlags.xFunction = HvLpEvent_Function_Int;
++ hev->xType = HvLpEvent_Type_MachineFac;
++ hev->xSourceLp = HvLpConfig_getLpIndex();
++ hev->xTargetLp = primary_lp;
++ hev->xSizeMinus1 = sizeof(ev->event) - 1;
++ hev->xRc = HvLpEvent_Rc_Good;
++ hev->xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primary_lp,
++ HvLpEvent_Type_MachineFac);
++ hev->xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primary_lp,
++ HvLpEvent_Type_MachineFac);
++
++ return ev;
++}
++
++static int signal_vsp_instruction(struct vsp_cmd_data *vsp_cmd)
++{
++ struct pending_event *ev = new_pending_event();
++ int rc;
++ struct vsp_rsp_data response;
++
++ if (ev == NULL)
++ return -ENOMEM;
++
++ init_completion(&response.com);
++ response.response = vsp_cmd;
++ ev->event.hp_lp_event.xSubtype = 6;
++ ev->event.hp_lp_event.x.xSubtypeData =
++ subtype_data('M', 'F', 'V', 'I');
++ ev->event.data.vsp_cmd.token = (u64)&response;
++ ev->event.data.vsp_cmd.cmd = vsp_cmd->cmd;
++ ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
++ ev->event.data.vsp_cmd.result_code = 0xFF;
++ ev->event.data.vsp_cmd.reserved = 0;
++ memcpy(&(ev->event.data.vsp_cmd.sub_data),
++ &(vsp_cmd->sub_data), sizeof(vsp_cmd->sub_data));
++ mb();
++
++ rc = signal_event(ev);
++ if (rc == 0)
++ wait_for_completion(&response.com);
++ return rc;
++}
++
++
++/*
++ * Send a 12-byte CE message to the primary partition VSP object
++ */
++static int signal_ce_msg(char *ce_msg, struct ce_msg_comp_data *completion)
++{
++ struct pending_event *ev = new_pending_event();
++
++ if (ev == NULL)
++ return -ENOMEM;
++
++ ev->event.hp_lp_event.xSubtype = 0;
++ ev->event.hp_lp_event.x.xSubtypeData =
++ subtype_data('M', 'F', 'C', 'E');
++ memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
++ ev->event.data.ce_msg.completion = completion;
++ return signal_event(ev);
++}
++
++/*
++ * Send a 12-byte CE message (with no data) to the primary partition VSP object
++ */
++static int signal_ce_msg_simple(u8 ce_op, struct ce_msg_comp_data *completion)
++{
++ u8 ce_msg[12];
++
++ memset(ce_msg, 0, sizeof(ce_msg));
++ ce_msg[3] = ce_op;
++ return signal_ce_msg(ce_msg, completion);
++}
++
++/*
++ * Send a 12-byte CE message and DMA data to the primary partition VSP object
++ */
++static int dma_and_signal_ce_msg(char *ce_msg,
++ struct ce_msg_comp_data *completion, void *dma_data,
++ unsigned dma_data_length, unsigned remote_address)
++{
++ struct pending_event *ev = new_pending_event();
++
++ if (ev == NULL)
++ return -ENOMEM;
++
++ ev->event.hp_lp_event.xSubtype = 0;
++ ev->event.hp_lp_event.x.xSubtypeData =
++ subtype_data('M', 'F', 'C', 'E');
++ memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
++ ev->event.data.ce_msg.completion = completion;
++ memcpy(ev->dma_data, dma_data, dma_data_length);
++ ev->dma_data_length = dma_data_length;
++ ev->remote_address = remote_address;
++ return signal_event(ev);
++}
++
++/*
++ * Initiate a nice (hopefully) shutdown of Linux. We simply are
++ * going to try and send the init process a SIGINT signal. If
++ * this fails (why?), we'll simply force it off in a not-so-nice
++ * manner.
++ */
++static int shutdown(void)
++{
++ int rc = kill_proc(1, SIGINT, 1);
++
++ if (rc) {
++ printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), "
++ "hard shutdown commencing\n", rc);
++ mf_power_off();
++ } else
++ printk(KERN_INFO "mf.c: init has been successfully notified "
++ "to proceed with shutdown\n");
++ return rc;
++}
++
++/*
++ * The primary partition VSP object is sending us a new
++ * event flow. Handle it...
++ */
++static void handle_int(struct io_mf_lp_event *event)
++{
++ struct ce_msg_data *ce_msg_data;
++ struct ce_msg_data *pce_msg_data;
++ unsigned long flags;
++ struct pending_event *pev;
++
++ /* ack the interrupt */
++ event->hp_lp_event.xRc = HvLpEvent_Rc_Good;
++ HvCallEvent_ackLpEvent(&event->hp_lp_event);
++
++ /* process interrupt */
++ switch (event->hp_lp_event.xSubtype) {
++ case 0: /* CE message */
++ ce_msg_data = &event->data.ce_msg;
++ switch (ce_msg_data->ce_msg[3]) {
++ case 0x5B: /* power control notification */
++ if ((ce_msg_data->ce_msg[5] & 0x20) != 0) {
++ printk(KERN_INFO "mf.c: Commencing partition shutdown\n");
++ if (shutdown() == 0)
++ signal_ce_msg_simple(0xDB, NULL);
++ }
++ break;
++ case 0xC0: /* get time */
++ spin_lock_irqsave(&pending_event_spinlock, flags);
++ pev = pending_event_head;
++ if (pev != NULL)
++ pending_event_head = pending_event_head->next;
++ spin_unlock_irqrestore(&pending_event_spinlock, flags);
++ if (pev == NULL)
++ break;
++ pce_msg_data = &pev->event.data.ce_msg;
++ if (pce_msg_data->ce_msg[3] != 0x40)
++ break;
++ if (pce_msg_data->completion != NULL) {
++ ce_msg_comp_hdlr handler =
++ pce_msg_data->completion->handler;
++ void *token = pce_msg_data->completion->token;
++
++ if (handler != NULL)
++ (*handler)(token, ce_msg_data);
++ }
++ spin_lock_irqsave(&pending_event_spinlock, flags);
++ free_pending_event(pev);
++ spin_unlock_irqrestore(&pending_event_spinlock, flags);
++ /* send next waiting event */
++ if (pending_event_head != NULL)
++ signal_event(NULL);
++ break;
++ }
++ break;
++ case 1: /* IT sys shutdown */
++ printk(KERN_INFO "mf.c: Commencing system shutdown\n");
++ shutdown();
++ break;
++ }
++}
++
++/*
++ * The primary partition VSP object is acknowledging the receipt
++ * of a flow we sent to them. If there are other flows queued
++ * up, we must send another one now...
++ */
++static void handle_ack(struct io_mf_lp_event *event)
++{
++ unsigned long flags;
++ struct pending_event *two = NULL;
++ unsigned long free_it = 0;
++ struct ce_msg_data *ce_msg_data;
++ struct ce_msg_data *pce_msg_data;
++ struct vsp_rsp_data *rsp;
++
++ /* handle current event */
++ if (pending_event_head == NULL) {
++ printk(KERN_ERR "mf.c: stack empty for receiving ack\n");
++ return;
++ }
++
++ switch (event->hp_lp_event.xSubtype) {
++ case 0: /* CE msg */
++ ce_msg_data = &event->data.ce_msg;
++ if (ce_msg_data->ce_msg[3] != 0x40) {
++ free_it = 1;
++ break;
++ }
++ if (ce_msg_data->ce_msg[2] == 0)
++ break;
++ free_it = 1;
++ pce_msg_data = &pending_event_head->event.data.ce_msg;
++ if (pce_msg_data->completion != NULL) {
++ ce_msg_comp_hdlr handler =
++ pce_msg_data->completion->handler;
++ void *token = pce_msg_data->completion->token;
++
++ if (handler != NULL)
++ (*handler)(token, ce_msg_data);
++ }
++ break;
++ case 4: /* allocate */
++ case 5: /* deallocate */
++ if (pending_event_head->hdlr != NULL)
++ (*pending_event_head->hdlr)((void *)event->hp_lp_event.xCorrelationToken, event->data.alloc.count);
++ free_it = 1;
++ break;
++ case 6:
++ free_it = 1;
++ rsp = (struct vsp_rsp_data *)event->data.vsp_cmd.token;
++ if (rsp == NULL) {
++ printk(KERN_ERR "mf.c: no rsp\n");
++ break;
++ }
++ if (rsp->response != NULL)
++ memcpy(rsp->response, &event->data.vsp_cmd,
++ sizeof(event->data.vsp_cmd));
++ complete(&rsp->com);
++ break;
++ }
++
++ /* remove from queue */
++ spin_lock_irqsave(&pending_event_spinlock, flags);
++ if ((pending_event_head != NULL) && (free_it == 1)) {
++ struct pending_event *oldHead = pending_event_head;
++
++ pending_event_head = pending_event_head->next;
++ two = pending_event_head;
++ free_pending_event(oldHead);
++ }
++ spin_unlock_irqrestore(&pending_event_spinlock, flags);
++
++ /* send next waiting event */
++ if (two != NULL)
++ signal_event(NULL);
++}
++
++/*
++ * This is the generic event handler we are registering with
++ * the Hypervisor. Ensure the flows are for us, and then
++ * parse it enough to know if it is an interrupt or an
++ * acknowledge.
++ */
++static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs)
++{
++ if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {
++ switch(event->xFlags.xFunction) {
++ case HvLpEvent_Function_Ack:
++ handle_ack((struct io_mf_lp_event *)event);
++ break;
++ case HvLpEvent_Function_Int:
++ handle_int((struct io_mf_lp_event *)event);
++ break;
++ default:
++ printk(KERN_ERR "mf.c: non ack/int event received\n");
++ break;
++ }
++ } else
++ printk(KERN_ERR "mf.c: alien event received\n");
++}
++
++/*
++ * Global kernel interface to allocate and seed events into the
++ * Hypervisor.
++ */
++void mf_allocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
++ unsigned size, unsigned count, MFCompleteHandler hdlr,
++ void *user_token)
++{
++ struct pending_event *ev = new_pending_event();
++ int rc;
++
++ if (ev == NULL) {
++ rc = -ENOMEM;
++ } else {
++ ev->event.hp_lp_event.xSubtype = 4;
++ ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
++ ev->event.hp_lp_event.x.xSubtypeData =
++ subtype_data('M', 'F', 'M', 'A');
++ ev->event.data.alloc.target_lp = target_lp;
++ ev->event.data.alloc.type = type;
++ ev->event.data.alloc.size = size;
++ ev->event.data.alloc.count = count;
++ ev->hdlr = hdlr;
++ rc = signal_event(ev);
++ }
++ if ((rc != 0) && (hdlr != NULL))
++ (*hdlr)(user_token, rc);
++}
++EXPORT_SYMBOL(mf_allocate_lp_events);
++
++/*
++ * Global kernel interface to unseed and deallocate events already in
++ * Hypervisor.
++ */
++void mf_deallocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
++ unsigned count, MFCompleteHandler hdlr, void *user_token)
++{
++ struct pending_event *ev = new_pending_event();
++ int rc;
++
++ if (ev == NULL)
++ rc = -ENOMEM;
++ else {
++ ev->event.hp_lp_event.xSubtype = 5;
++ ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
++ ev->event.hp_lp_event.x.xSubtypeData =
++ subtype_data('M', 'F', 'M', 'D');
++ ev->event.data.alloc.target_lp = target_lp;
++ ev->event.data.alloc.type = type;
++ ev->event.data.alloc.count = count;
++ ev->hdlr = hdlr;
++ rc = signal_event(ev);
++ }
++ if ((rc != 0) && (hdlr != NULL))
++ (*hdlr)(user_token, rc);
++}
++EXPORT_SYMBOL(mf_deallocate_lp_events);
++
++/*
++ * Global kernel interface to tell the VSP object in the primary
++ * partition to power this partition off.
++ */
++void mf_power_off(void)
++{
++ printk(KERN_INFO "mf.c: Down it goes...\n");
++ signal_ce_msg_simple(0x4d, NULL);
++ for (;;)
++ ;
++}
++
++/*
++ * Global kernel interface to tell the VSP object in the primary
++ * partition to reboot this partition.
++ */
++void mf_reboot(void)
++{
++ printk(KERN_INFO "mf.c: Preparing to bounce...\n");
++ signal_ce_msg_simple(0x4e, NULL);
++ for (;;)
++ ;
++}
++
++/*
++ * Display a single word SRC onto the VSP control panel.
++ */
++void mf_display_src(u32 word)
++{
++ u8 ce[12];
++
++ memset(ce, 0, sizeof(ce));
++ ce[3] = 0x4a;
++ ce[7] = 0x01;
++ ce[8] = word >> 24;
++ ce[9] = word >> 16;
++ ce[10] = word >> 8;
++ ce[11] = word;
++ signal_ce_msg(ce, NULL);
++}
++
++/*
++ * Display a single word SRC of the form "PROGXXXX" on the VSP control panel.
++ */
++void mf_display_progress(u16 value)
++{
++ u8 ce[12];
++ u8 src[72];
++
++ memcpy(ce, "\x00\x00\x04\x4A\x00\x00\x00\x48\x00\x00\x00\x00", 12);
++ memcpy(src, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00PROGxxxx ",
++ 72);
++ src[6] = value >> 8;
++ src[7] = value & 255;
++ src[44] = "0123456789ABCDEF"[(value >> 12) & 15];
++ src[45] = "0123456789ABCDEF"[(value >> 8) & 15];
++ src[46] = "0123456789ABCDEF"[(value >> 4) & 15];
++ src[47] = "0123456789ABCDEF"[value & 15];
++ dma_and_signal_ce_msg(ce, NULL, src, sizeof(src), 9 * 64 * 1024);
++}
++
++/*
++ * Clear the VSP control panel. Used to "erase" an SRC that was
++ * previously displayed.
++ */
++void mf_clear_src(void)
++{
++ signal_ce_msg_simple(0x4b, NULL);
++}
++
++/*
++ * Initialization code here.
++ */
++void mf_init(void)
++{
++ int i;
++
++ /* initialize */
++ spin_lock_init(&pending_event_spinlock);
++ for (i = 0;
++ i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc);
++ ++i)
++ free_pending_event(&pending_event_prealloc[i]);
++ HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler);
++
++ /* virtual continue ack */
++ signal_ce_msg_simple(0x57, NULL);
++
++ /* initialization complete */
++ printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities "
++ "initialized\n");
++}
++
++struct rtc_time_data {
++ struct completion com;
++ struct ce_msg_data ce_msg;
++ int rc;
++};
++
++static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
++{
++ struct rtc_time_data *rtc = token;
++
++ memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
++ rtc->rc = 0;
++ complete(&rtc->com);
++}
++
++static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
++{
++ tm->tm_wday = 0;
++ tm->tm_yday = 0;
++ tm->tm_isdst = 0;
++ if (rc) {
++ tm->tm_sec = 0;
++ tm->tm_min = 0;
++ tm->tm_hour = 0;
++ tm->tm_mday = 15;
++ tm->tm_mon = 5;
++ tm->tm_year = 52;
++ return rc;
++ }
++
++ if ((ce_msg[2] == 0xa9) ||
++ (ce_msg[2] == 0xaf)) {
++ /* TOD clock is not set */
++ tm->tm_sec = 1;
++ tm->tm_min = 1;
++ tm->tm_hour = 1;
++ tm->tm_mday = 10;
++ tm->tm_mon = 8;
++ tm->tm_year = 71;
++ mf_set_rtc(tm);
++ }
++ {
++ u8 year = ce_msg[5];
++ u8 sec = ce_msg[6];
++ u8 min = ce_msg[7];
++ u8 hour = ce_msg[8];
++ u8 day = ce_msg[10];
++ u8 mon = ce_msg[11];
++
++ BCD_TO_BIN(sec);
++ BCD_TO_BIN(min);
++ BCD_TO_BIN(hour);
++ BCD_TO_BIN(day);
++ BCD_TO_BIN(mon);
++ BCD_TO_BIN(year);
++
++ if (year <= 69)
++ year += 100;
++
++ tm->tm_sec = sec;
++ tm->tm_min = min;
++ tm->tm_hour = hour;
++ tm->tm_mday = day;
++ tm->tm_mon = mon;
++ tm->tm_year = year;
++ }
++
++ return 0;
++}
++
++int mf_get_rtc(struct rtc_time *tm)
++{
++ struct ce_msg_comp_data ce_complete;
++ struct rtc_time_data rtc_data;
++ int rc;
++
++ memset(&ce_complete, 0, sizeof(ce_complete));
++ memset(&rtc_data, 0, sizeof(rtc_data));
++ init_completion(&rtc_data.com);
++ ce_complete.handler = &get_rtc_time_complete;
++ ce_complete.token = &rtc_data;
++ rc = signal_ce_msg_simple(0x40, &ce_complete);
++ if (rc)
++ return rc;
++ wait_for_completion(&rtc_data.com);
++ return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
++}
++
++struct boot_rtc_time_data {
++ int busy;
++ struct ce_msg_data ce_msg;
++ int rc;
++};
++
++static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
++{
++ struct boot_rtc_time_data *rtc = token;
++
++ memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
++ rtc->rc = 0;
++ rtc->busy = 0;
++}
++
++int mf_get_boot_rtc(struct rtc_time *tm)
++{
++ struct ce_msg_comp_data ce_complete;
++ struct boot_rtc_time_data rtc_data;
++ int rc;
++
++ memset(&ce_complete, 0, sizeof(ce_complete));
++ memset(&rtc_data, 0, sizeof(rtc_data));
++ rtc_data.busy = 1;
++ ce_complete.handler = &get_boot_rtc_time_complete;
++ ce_complete.token = &rtc_data;
++ rc = signal_ce_msg_simple(0x40, &ce_complete);
++ if (rc)
++ return rc;
++ /* We need to poll here as we are not yet taking interrupts */
++ while (rtc_data.busy) {
++ if (hvlpevent_is_pending())
++ process_hvlpevents(NULL);
++ }
++ return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
++}
++
++int mf_set_rtc(struct rtc_time *tm)
++{
++ char ce_time[12];
++ u8 day, mon, hour, min, sec, y1, y2;
++ unsigned year;
++
++ year = 1900 + tm->tm_year;
++ y1 = year / 100;
++ y2 = year % 100;
++
++ sec = tm->tm_sec;
++ min = tm->tm_min;
++ hour = tm->tm_hour;
++ day = tm->tm_mday;
++ mon = tm->tm_mon + 1;
++
++ BIN_TO_BCD(sec);
++ BIN_TO_BCD(min);
++ BIN_TO_BCD(hour);
++ BIN_TO_BCD(mon);
++ BIN_TO_BCD(day);
++ BIN_TO_BCD(y1);
++ BIN_TO_BCD(y2);
++
++ memset(ce_time, 0, sizeof(ce_time));
++ ce_time[3] = 0x41;
++ ce_time[4] = y1;
++ ce_time[5] = y2;
++ ce_time[6] = sec;
++ ce_time[7] = min;
++ ce_time[8] = hour;
++ ce_time[10] = day;
++ ce_time[11] = mon;
++
++ return signal_ce_msg(ce_time, NULL);
++}
++
++#ifdef CONFIG_PROC_FS
++
++static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++ char *p;
++ struct vsp_cmd_data vsp_cmd;
++ int rc;
++ dma_addr_t dma_addr;
++
++ /* The HV appears to return no more than 256 bytes of command line */
++ if (off >= 256)
++ return 0;
++ if ((off + count) > 256)
++ count = 256 - off;
++
++ dma_addr = dma_map_single(iSeries_vio_dev, page, off + count,
++ DMA_FROM_DEVICE);
++ if (dma_mapping_error(dma_addr))
++ return -ENOMEM;
++ memset(page, 0, off + count);
++ memset(&vsp_cmd, 0, sizeof(vsp_cmd));
++ vsp_cmd.cmd = 33;
++ vsp_cmd.sub_data.kern.token = dma_addr;
++ vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
++ vsp_cmd.sub_data.kern.side = (u64)data;
++ vsp_cmd.sub_data.kern.length = off + count;
++ mb();
++ rc = signal_vsp_instruction(&vsp_cmd);
++ dma_unmap_single(iSeries_vio_dev, dma_addr, off + count,
++ DMA_FROM_DEVICE);
++ if (rc)
++ return rc;
++ if (vsp_cmd.result_code != 0)
++ return -ENOMEM;
++ p = page;
++ len = 0;
++ while (len < (off + count)) {
++ if ((*p == '\0') || (*p == '\n')) {
++ if (*p == '\0')
++ *p = '\n';
++ p++;
++ len++;
++ *eof = 1;
++ break;
++ }
++ p++;
++ len++;
++ }
++
++ if (len < off) {
++ *eof = 1;
++ len = 0;
++ }
++ return len;
++}
++
++#if 0
++static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
++{
++ struct vsp_cmd_data vsp_cmd;
++ int rc;
++ int len = *size;
++ dma_addr_t dma_addr;
++
++ dma_addr = dma_map_single(iSeries_vio_dev, buffer, len,
++ DMA_FROM_DEVICE);
++ memset(buffer, 0, len);
++ memset(&vsp_cmd, 0, sizeof(vsp_cmd));
++ vsp_cmd.cmd = 32;
++ vsp_cmd.sub_data.kern.token = dma_addr;
++ vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
++ vsp_cmd.sub_data.kern.side = side;
++ vsp_cmd.sub_data.kern.offset = offset;
++ vsp_cmd.sub_data.kern.length = len;
++ mb();
++ rc = signal_vsp_instruction(&vsp_cmd);
++ if (rc == 0) {
++ if (vsp_cmd.result_code == 0)
++ *size = vsp_cmd.sub_data.length_out;
++ else
++ rc = -ENOMEM;
++ }
++
++ dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE);
++
++ return rc;
++}
++
++static int proc_mf_dump_vmlinux(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int sizeToGet = count;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
++ if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) {
++ if (sizeToGet != 0) {
++ *start = page + off;
++ return sizeToGet;
++ }
++ *eof = 1;
++ return 0;
++ }
++ *eof = 1;
++ return 0;
++}
++#endif
++
++static int proc_mf_dump_side(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++ char mf_current_side = ' ';
++ struct vsp_cmd_data vsp_cmd;
++
++ memset(&vsp_cmd, 0, sizeof(vsp_cmd));
++ vsp_cmd.cmd = 2;
++ vsp_cmd.sub_data.ipl_type = 0;
++ mb();
++
++ if (signal_vsp_instruction(&vsp_cmd) == 0) {
++ if (vsp_cmd.result_code == 0) {
++ switch (vsp_cmd.sub_data.ipl_type) {
++ case 0: mf_current_side = 'A';
++ break;
++ case 1: mf_current_side = 'B';
++ break;
++ case 2: mf_current_side = 'C';
++ break;
++ default: mf_current_side = 'D';
++ break;
++ }
++ }
++ }
++
++ len = sprintf(page, "%c\n", mf_current_side);
++
++ if (len <= (off + count))
++ *eof = 1;
++ *start = page + off;
++ len -= off;
++ if (len > count)
++ len = count;
++ if (len < 0)
++ len = 0;
++ return len;
++}
++
++static int proc_mf_change_side(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char side;
++ u64 newSide;
++ struct vsp_cmd_data vsp_cmd;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
++ if (count == 0)
++ return 0;
++
++ if (get_user(side, buffer))
++ return -EFAULT;
++
++ switch (side) {
++ case 'A': newSide = 0;
++ break;
++ case 'B': newSide = 1;
++ break;
++ case 'C': newSide = 2;
++ break;
++ case 'D': newSide = 3;
++ break;
++ default:
++ printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n");
++ return -EINVAL;
++ }
++
++ memset(&vsp_cmd, 0, sizeof(vsp_cmd));
++ vsp_cmd.sub_data.ipl_type = newSide;
++ vsp_cmd.cmd = 10;
++
++ (void)signal_vsp_instruction(&vsp_cmd);
++
++ return count;
++}
++
++#if 0
++static void mf_getSrcHistory(char *buffer, int size)
++{
++ struct IplTypeReturnStuff return_stuff;
++ struct pending_event *ev = new_pending_event();
++ int rc = 0;
++ char *pages[4];
++
++ pages[0] = kmalloc(4096, GFP_ATOMIC);
++ pages[1] = kmalloc(4096, GFP_ATOMIC);
++ pages[2] = kmalloc(4096, GFP_ATOMIC);
++ pages[3] = kmalloc(4096, GFP_ATOMIC);
++ if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL)
++ || (pages[2] == NULL) || (pages[3] == NULL))
++ return -ENOMEM;
++
++ return_stuff.xType = 0;
++ return_stuff.xRc = 0;
++ return_stuff.xDone = 0;
++ ev->event.hp_lp_event.xSubtype = 6;
++ ev->event.hp_lp_event.x.xSubtypeData =
++ subtype_data('M', 'F', 'V', 'I');
++ ev->event.data.vsp_cmd.xEvent = &return_stuff;
++ ev->event.data.vsp_cmd.cmd = 4;
++ ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
++ ev->event.data.vsp_cmd.result_code = 0xFF;
++ ev->event.data.vsp_cmd.reserved = 0;
++ ev->event.data.vsp_cmd.sub_data.page[0] = iseries_hv_addr(pages[0]);
++ ev->event.data.vsp_cmd.sub_data.page[1] = iseries_hv_addr(pages[1]);
++ ev->event.data.vsp_cmd.sub_data.page[2] = iseries_hv_addr(pages[2]);
++ ev->event.data.vsp_cmd.sub_data.page[3] = iseries_hv_addr(pages[3]);
++ mb();
++ if (signal_event(ev) != 0)
++ return;
++
++ while (return_stuff.xDone != 1)
++ udelay(10);
++ if (return_stuff.xRc == 0)
++ memcpy(buffer, pages[0], size);
++ kfree(pages[0]);
++ kfree(pages[1]);
++ kfree(pages[2]);
++ kfree(pages[3]);
++}
++#endif
++
++static int proc_mf_dump_src(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++#if 0
++ int len;
++
++ mf_getSrcHistory(page, count);
++ len = count;
++ len -= off;
++ if (len < count) {
++ *eof = 1;
++ if (len <= 0)
++ return 0;
++ } else
++ len = count;
++ *start = page + off;
++ return len;
++#else
++ return 0;
++#endif
++}
++
++static int proc_mf_change_src(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char stkbuf[10];
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
++ if ((count < 4) && (count != 1)) {
++ printk(KERN_ERR "mf_proc: invalid src\n");
++ return -EINVAL;
++ }
++
++ if (count > (sizeof(stkbuf) - 1))
++ count = sizeof(stkbuf) - 1;
++ if (copy_from_user(stkbuf, buffer, count))
++ return -EFAULT;
++
++ if ((count == 1) && (*stkbuf == '\0'))
++ mf_clear_src();
++ else
++ mf_display_src(*(u32 *)stkbuf);
++
++ return count;
++}
++
++static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ struct vsp_cmd_data vsp_cmd;
++ dma_addr_t dma_addr;
++ char *page;
++ int ret = -EACCES;
++
++ if (!capable(CAP_SYS_ADMIN))
++ goto out;
++
++ dma_addr = 0;
++ page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
++ GFP_ATOMIC);
++ ret = -ENOMEM;
++ if (page == NULL)
++ goto out;
++
++ ret = -EFAULT;
++ if (copy_from_user(page, buffer, count))
++ goto out_free;
++
++ memset(&vsp_cmd, 0, sizeof(vsp_cmd));
++ vsp_cmd.cmd = 31;
++ vsp_cmd.sub_data.kern.token = dma_addr;
++ vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
++ vsp_cmd.sub_data.kern.side = (u64)data;
++ vsp_cmd.sub_data.kern.length = count;
++ mb();
++ (void)signal_vsp_instruction(&vsp_cmd);
++ ret = count;
++
++out_free:
++ dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
++out:
++ return ret;
++}
++
++static ssize_t proc_mf_change_vmlinux(struct file *file,
++ const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
++ ssize_t rc;
++ dma_addr_t dma_addr;
++ char *page;
++ struct vsp_cmd_data vsp_cmd;
++
++ rc = -EACCES;
++ if (!capable(CAP_SYS_ADMIN))
++ goto out;
++
++ dma_addr = 0;
++ page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
++ GFP_ATOMIC);
++ rc = -ENOMEM;
++ if (page == NULL) {
++ printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");
++ goto out;
++ }
++ rc = -EFAULT;
++ if (copy_from_user(page, buf, count))
++ goto out_free;
++
++ memset(&vsp_cmd, 0, sizeof(vsp_cmd));
++ vsp_cmd.cmd = 30;
++ vsp_cmd.sub_data.kern.token = dma_addr;
++ vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
++ vsp_cmd.sub_data.kern.side = (u64)dp->data;
++ vsp_cmd.sub_data.kern.offset = *ppos;
++ vsp_cmd.sub_data.kern.length = count;
++ mb();
++ rc = signal_vsp_instruction(&vsp_cmd);
++ if (rc)
++ goto out_free;
++ rc = -ENOMEM;
++ if (vsp_cmd.result_code != 0)
++ goto out_free;
++
++ *ppos += count;
++ rc = count;
++out_free:
++ dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
++out:
++ return rc;
++}
++
++static struct file_operations proc_vmlinux_operations = {
++ .write = proc_mf_change_vmlinux,
++};
++
++static int __init mf_proc_init(void)
++{
++ struct proc_dir_entry *mf_proc_root;
++ struct proc_dir_entry *ent;
++ struct proc_dir_entry *mf;
++ char name[2];
++ int i;
++
++ mf_proc_root = proc_mkdir("iSeries/mf", NULL);
++ if (!mf_proc_root)
++ return 1;
++
++ name[1] = '\0';
++ for (i = 0; i < 4; i++) {
++ name[0] = 'A' + i;
++ mf = proc_mkdir(name, mf_proc_root);
++ if (!mf)
++ return 1;
++
++ ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf);
++ if (!ent)
++ return 1;
++ ent->nlink = 1;
++ ent->data = (void *)(long)i;
++ ent->read_proc = proc_mf_dump_cmdline;
++ ent->write_proc = proc_mf_change_cmdline;
++
++ if (i == 3) /* no vmlinux entry for 'D' */
++ continue;
++
++ ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);
++ if (!ent)
++ return 1;
++ ent->nlink = 1;
++ ent->data = (void *)(long)i;
++ ent->proc_fops = &proc_vmlinux_operations;
++ }
++
++ ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
++ if (!ent)
++ return 1;
++ ent->nlink = 1;
++ ent->data = (void *)0;
++ ent->read_proc = proc_mf_dump_side;
++ ent->write_proc = proc_mf_change_side;
++
++ ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
++ if (!ent)
++ return 1;
++ ent->nlink = 1;
++ ent->data = (void *)0;
++ ent->read_proc = proc_mf_dump_src;
++ ent->write_proc = proc_mf_change_src;
++
++ return 0;
++}
++
++__initcall(mf_proc_init);
++
++#endif /* CONFIG_PROC_FS */
++
++/*
++ * Get the RTC from the virtual service processor
++ * This requires flowing LpEvents to the primary partition
++ */
++void iSeries_get_rtc_time(struct rtc_time *rtc_tm)
++{
++ if (piranha_simulator)
++ return;
++
++ mf_get_rtc(rtc_tm);
++ rtc_tm->tm_mon--;
++}
++
++/*
++ * Set the RTC in the virtual service processor
++ * This requires flowing LpEvents to the primary partition
++ */
++int iSeries_set_rtc_time(struct rtc_time *tm)
++{
++ mf_set_rtc(tm);
++ return 0;
++}
++
++unsigned long iSeries_get_boot_time(void)
++{
++ struct rtc_time tm;
++
++ if (piranha_simulator)
++ return 0;
++
++ mf_get_boot_rtc(&tm);
++ return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday,
++ tm.tm_hour, tm.tm_min, tm.tm_sec);
++}
+diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/misc.S
+@@ -0,0 +1,55 @@
++/*
++ * This file contains miscellaneous low-level functions.
++ * Copyright (C) 1995-2005 IBM Corp
++ *
++ * Largely rewritten by Cort Dougan (cort at cs.nmt.edu)
++ * and Paul Mackerras.
++ * Adapted for iSeries by Mike Corrigan (mikejc at us.ibm.com)
++ * PPC64 updates by Dave Engebretsen (engebret at us.ibm.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <asm/processor.h>
++#include <asm/asm-offsets.h>
++
++ .text
++
++/* unsigned long local_save_flags(void) */
++_GLOBAL(local_get_flags)
++ lbz r3,PACAPROCENABLED(r13)
++ blr
++
++/* unsigned long local_irq_disable(void) */
++_GLOBAL(local_irq_disable)
++ lbz r3,PACAPROCENABLED(r13)
++ li r4,0
++ stb r4,PACAPROCENABLED(r13)
++ blr /* Done */
++
++/* void local_irq_restore(unsigned long flags) */
++_GLOBAL(local_irq_restore)
++ lbz r5,PACAPROCENABLED(r13)
++ /* Check if things are setup the way we want _already_. */
++ cmpw 0,r3,r5
++ beqlr
++ /* are we enabling interrupts? */
++ cmpdi 0,r3,0
++ stb r3,PACAPROCENABLED(r13)
++ beqlr
++ /* Check pending interrupts */
++ /* A decrementer, IPI or PMC interrupt may have occurred
++ * while we were in the hypervisor (which enables) */
++ ld r4,PACALPPACA+LPPACAANYINT(r13)
++ cmpdi r4,0
++ beqlr
++
++ /*
++ * Handle pending interrupts in interrupt context
++ */
++ li r0,0x5555
++ sc
++ blr
+diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/pci.c
+@@ -0,0 +1,906 @@
++/*
++ * Copyright (C) 2001 Allan Trautman, IBM Corporation
++ *
++ * iSeries specific routines for PCI.
++ *
++ * Based on code from pci.c and iSeries_pci.c 32bit
++ *
++ * 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/list.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/ide.h>
++#include <linux/pci.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/pci-bridge.h>
++#include <asm/ppcdebug.h>
++#include <asm/iommu.h>
++#include <asm/abs_addr.h>
++
++#include <asm/iSeries/HvCallXm.h>
++#include <asm/iSeries/mf.h>
++
++#include <asm/ppc-pci.h>
++
++#include "irq.h"
++#include "pci.h"
++#include "call_pci.h"
++
++extern unsigned long io_page_mask;
++
++/*
++ * Forward declares of prototypes.
++ */
++static struct device_node *find_Device_Node(int bus, int devfn);
++static void scan_PHB_slots(struct pci_controller *Phb);
++static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
++static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
++
++LIST_HEAD(iSeries_Global_Device_List);
++
++static int DeviceCount;
++
++/* Counters and control flags. */
++static long Pci_Io_Read_Count;
++static long Pci_Io_Write_Count;
++#if 0
++static long Pci_Cfg_Read_Count;
++static long Pci_Cfg_Write_Count;
++#endif
++static long Pci_Error_Count;
++
++static int Pci_Retry_Max = 3; /* Only retry 3 times */
++static int Pci_Error_Flag = 1; /* Set Retry Error on. */
++
++static struct pci_ops iSeries_pci_ops;
++
++/*
++ * Table defines
++ * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
++ */
++#define IOMM_TABLE_MAX_ENTRIES 1024
++#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL
++#define BASE_IO_MEMORY 0xE000000000000000UL
++
++static unsigned long max_io_memory = 0xE000000000000000UL;
++static long current_iomm_table_entry;
++
++/*
++ * Lookup Tables.
++ */
++static struct device_node **iomm_table;
++static u8 *iobar_table;
++
++/*
++ * Static and Global variables
++ */
++static char *pci_io_text = "iSeries PCI I/O";
++static DEFINE_SPINLOCK(iomm_table_lock);
++
++/*
++ * iomm_table_initialize
++ *
++ * Allocates and initalizes the Address Translation Table and Bar
++ * Tables to get them ready for use. Must be called before any
++ * I/O space is handed out to the device BARs.
++ */
++static void iomm_table_initialize(void)
++{
++ spin_lock(&iomm_table_lock);
++ iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
++ GFP_KERNEL);
++ iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
++ GFP_KERNEL);
++ spin_unlock(&iomm_table_lock);
++ if ((iomm_table == NULL) || (iobar_table == NULL))
++ panic("PCI: I/O tables allocation failed.\n");
++}
++
++/*
++ * iomm_table_allocate_entry
++ *
++ * Adds pci_dev entry in address translation table
++ *
++ * - Allocates the number of entries required in table base on BAR
++ * size.
++ * - Allocates starting at BASE_IO_MEMORY and increases.
++ * - The size is round up to be a multiple of entry size.
++ * - CurrentIndex is incremented to keep track of the last entry.
++ * - Builds the resource entry for allocated BARs.
++ */
++static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
++{
++ struct resource *bar_res = &dev->resource[bar_num];
++ long bar_size = pci_resource_len(dev, bar_num);
++
++ /*
++ * No space to allocate, quick exit, skip Allocation.
++ */
++ if (bar_size == 0)
++ return;
++ /*
++ * Set Resource values.
++ */
++ spin_lock(&iomm_table_lock);
++ bar_res->name = pci_io_text;
++ bar_res->start =
++ IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
++ bar_res->start += BASE_IO_MEMORY;
++ bar_res->end = bar_res->start + bar_size - 1;
++ /*
++ * Allocate the number of table entries needed for BAR.
++ */
++ while (bar_size > 0 ) {
++ iomm_table[current_iomm_table_entry] = dev->sysdata;
++ iobar_table[current_iomm_table_entry] = bar_num;
++ bar_size -= IOMM_TABLE_ENTRY_SIZE;
++ ++current_iomm_table_entry;
++ }
++ max_io_memory = BASE_IO_MEMORY +
++ (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry);
++ spin_unlock(&iomm_table_lock);
++}
++
++/*
++ * allocate_device_bars
++ *
++ * - Allocates ALL pci_dev BAR's and updates the resources with the
++ * BAR value. BARS with zero length will have the resources
++ * The HvCallPci_getBarParms is used to get the size of the BAR
++ * space. It calls iomm_table_allocate_entry to allocate
++ * each entry.
++ * - Loops through The Bar resources(0 - 5) including the ROM
++ * is resource(6).
++ */
++static void allocate_device_bars(struct pci_dev *dev)
++{
++ struct resource *bar_res;
++ int bar_num;
++
++ for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) {
++ bar_res = &dev->resource[bar_num];
++ iomm_table_allocate_entry(dev, bar_num);
++ }
++}
++
++/*
++ * Log error information to system console.
++ * Filter out the device not there errors.
++ * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx
++ * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
++ * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
++ */
++static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
++ int AgentId, int HvRc)
++{
++ if (HvRc == 0x0302)
++ return;
++ printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
++ Error_Text, Bus, SubBus, AgentId, HvRc);
++}
++
++/*
++ * build_device_node(u16 Bus, int SubBus, u8 DevFn)
++ */
++static struct device_node *build_device_node(HvBusNumber Bus,
++ HvSubBusNumber SubBus, int AgentId, int Function)
++{
++ struct device_node *node;
++ struct pci_dn *pdn;
++
++ PPCDBG(PPCDBG_BUSWALK,
++ "-build_device_node 0x%02X.%02X.%02X Function: %02X\n",
++ Bus, SubBus, AgentId, Function);
++
++ node = kmalloc(sizeof(struct device_node), GFP_KERNEL);
++ if (node == NULL)
++ return NULL;
++ memset(node, 0, sizeof(struct device_node));
++ pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
++ if (pdn == NULL) {
++ kfree(node);
++ return NULL;
++ }
++ node->data = pdn;
++ pdn->node = node;
++ list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List);
++ pdn->busno = Bus;
++ pdn->bussubno = SubBus;
++ pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
++ return node;
++}
++
++/*
++ * unsigned long __init find_and_init_phbs(void)
++ *
++ * Description:
++ * This function checks for all possible system PCI host bridges that connect
++ * PCI buses. The system hypervisor is queried as to the guest partition
++ * ownership status. A pci_controller is built for any bus which is partially
++ * owned or fully owned by this guest partition.
++ */
++unsigned long __init find_and_init_phbs(void)
++{
++ struct pci_controller *phb;
++ HvBusNumber bus;
++
++ PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n");
++
++ /* Check all possible buses. */
++ for (bus = 0; bus < 256; bus++) {
++ int ret = HvCallXm_testBus(bus);
++ if (ret == 0) {
++ printk("bus %d appears to exist\n", bus);
++
++ phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
++ if (phb == NULL)
++ return -ENOMEM;
++ pci_setup_pci_controller(phb);
++
++ phb->pci_mem_offset = phb->local_number = bus;
++ phb->first_busno = bus;
++ phb->last_busno = bus;
++ phb->ops = &iSeries_pci_ops;
++
++ PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",
++ phb, bus);
++
++ /* Find and connect the devices. */
++ scan_PHB_slots(phb);
++ }
++ /*
++ * Check for Unexpected Return code, a clue that something
++ * has gone wrong.
++ */
++ else if (ret != 0x0301)
++ printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
++ bus, ret);
++ }
++ return 0;
++}
++
++/*
++ * iSeries_pcibios_init
++ *
++ * Chance to initialize and structures or variable before PCI Bus walk.
++ */
++void iSeries_pcibios_init(void)
++{
++ PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n");
++ iomm_table_initialize();
++ find_and_init_phbs();
++ io_page_mask = -1;
++ PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n");
++}
++
++/*
++ * iSeries_pci_final_fixup(void)
++ */
++void __init iSeries_pci_final_fixup(void)
++{
++ struct pci_dev *pdev = NULL;
++ struct device_node *node;
++ int DeviceCount = 0;
++
++ PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n");
++
++ /* Fix up at the device node and pci_dev relationship */
++ mf_display_src(0xC9000100);
++
++ printk("pcibios_final_fixup\n");
++ for_each_pci_dev(pdev) {
++ node = find_Device_Node(pdev->bus->number, pdev->devfn);
++ printk("pci dev %p (%x.%x), node %p\n", pdev,
++ pdev->bus->number, pdev->devfn, node);
++
++ if (node != NULL) {
++ ++DeviceCount;
++ pdev->sysdata = (void *)node;
++ PCI_DN(node)->pcidev = pdev;
++ PPCDBG(PPCDBG_BUSWALK,
++ "pdev 0x%p <==> DevNode 0x%p\n",
++ pdev, node);
++ allocate_device_bars(pdev);
++ iSeries_Device_Information(pdev, DeviceCount);
++ iommu_devnode_init_iSeries(node);
++ } else
++ printk("PCI: Device Tree not found for 0x%016lX\n",
++ (unsigned long)pdev);
++ pdev->irq = PCI_DN(node)->Irq;
++ }
++ iSeries_activate_IRQs();
++ mf_display_src(0xC9000200);
++}
++
++void pcibios_fixup_bus(struct pci_bus *PciBus)
++{
++ PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",
++ PciBus->number);
++}
++
++void pcibios_fixup_resources(struct pci_dev *pdev)
++{
++ PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev);
++}
++
++/*
++ * Loop through each node function to find usable EADs bridges.
++ */
++static void scan_PHB_slots(struct pci_controller *Phb)
++{
++ struct HvCallPci_DeviceInfo *DevInfo;
++ HvBusNumber bus = Phb->local_number; /* System Bus */
++ const HvSubBusNumber SubBus = 0; /* EADs is always 0. */
++ int HvRc = 0;
++ int IdSel;
++ const int MaxAgents = 8;
++
++ DevInfo = (struct HvCallPci_DeviceInfo*)
++ kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
++ if (DevInfo == NULL)
++ return;
++
++ /*
++ * Probe for EADs Bridges
++ */
++ for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
++ HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
++ iseries_hv_addr(DevInfo),
++ sizeof(struct HvCallPci_DeviceInfo));
++ if (HvRc == 0) {
++ if (DevInfo->deviceType == HvCallPci_NodeDevice)
++ scan_EADS_bridge(bus, SubBus, IdSel);
++ else
++ printk("PCI: Invalid System Configuration(0x%02X)"
++ " for bus 0x%02x id 0x%02x.\n",
++ DevInfo->deviceType, bus, IdSel);
++ }
++ else
++ pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
++ }
++ kfree(DevInfo);
++}
++
++static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
++ int IdSel)
++{
++ struct HvCallPci_BridgeInfo *BridgeInfo;
++ HvAgentId AgentId;
++ int Function;
++ int HvRc;
++
++ BridgeInfo = (struct HvCallPci_BridgeInfo *)
++ kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
++ if (BridgeInfo == NULL)
++ return;
++
++ /* Note: hvSubBus and irq is always be 0 at this level! */
++ for (Function = 0; Function < 8; ++Function) {
++ AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
++ HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
++ if (HvRc == 0) {
++ printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
++ bus, IdSel, Function, AgentId);
++ /* Connect EADs: 0x18.00.12 = 0x00 */
++ PPCDBG(PPCDBG_BUSWALK,
++ "PCI:Connect EADs: 0x%02X.%02X.%02X\n",
++ bus, SubBus, AgentId);
++ HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
++ iseries_hv_addr(BridgeInfo),
++ sizeof(struct HvCallPci_BridgeInfo));
++ if (HvRc == 0) {
++ printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
++ BridgeInfo->busUnitInfo.deviceType,
++ BridgeInfo->subBusNumber,
++ BridgeInfo->maxAgents,
++ BridgeInfo->maxSubBusNumber,
++ BridgeInfo->logicalSlotNumber);
++ PPCDBG(PPCDBG_BUSWALK,
++ "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
++ BridgeInfo->busUnitInfo.deviceType,
++ BridgeInfo->subBusNumber,
++ BridgeInfo->maxAgents,
++ BridgeInfo->maxSubBusNumber,
++ BridgeInfo->logicalSlotNumber);
++
++ if (BridgeInfo->busUnitInfo.deviceType ==
++ HvCallPci_BridgeDevice) {
++ /* Scan_Bridge_Slot...: 0x18.00.12 */
++ scan_bridge_slot(bus, BridgeInfo);
++ } else
++ printk("PCI: Invalid Bridge Configuration(0x%02X)",
++ BridgeInfo->busUnitInfo.deviceType);
++ }
++ } else if (HvRc != 0x000B)
++ pci_Log_Error("EADs Connect",
++ bus, SubBus, AgentId, HvRc);
++ }
++ kfree(BridgeInfo);
++}
++
++/*
++ * This assumes that the node slot is always on the primary bus!
++ */
++static int scan_bridge_slot(HvBusNumber Bus,
++ struct HvCallPci_BridgeInfo *BridgeInfo)
++{
++ struct device_node *node;
++ HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
++ u16 VendorId = 0;
++ int HvRc = 0;
++ u8 Irq = 0;
++ int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
++ int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
++ HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
++
++ /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
++ Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
++ PPCDBG(PPCDBG_BUSWALK,
++ "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",
++ Bus, 0, EADsIdSel, Irq);
++
++ /*
++ * Connect all functions of any device found.
++ */
++ for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
++ for (Function = 0; Function < 8; ++Function) {
++ HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
++ HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
++ AgentId, Irq);
++ if (HvRc != 0) {
++ pci_Log_Error("Connect Bus Unit",
++ Bus, SubBus, AgentId, HvRc);
++ continue;
++ }
++
++ HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
++ PCI_VENDOR_ID, &VendorId);
++ if (HvRc != 0) {
++ pci_Log_Error("Read Vendor",
++ Bus, SubBus, AgentId, HvRc);
++ continue;
++ }
++ printk("read vendor ID: %x\n", VendorId);
++
++ /* FoundDevice: 0x18.28.10 = 0x12AE */
++ PPCDBG(PPCDBG_BUSWALK,
++ "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n",
++ Bus, SubBus, AgentId, VendorId, Irq);
++ HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
++ PCI_INTERRUPT_LINE, Irq);
++ if (HvRc != 0)
++ pci_Log_Error("PciCfgStore Irq Failed!",
++ Bus, SubBus, AgentId, HvRc);
++
++ ++DeviceCount;
++ node = build_device_node(Bus, SubBus, EADsIdSel, Function);
++ PCI_DN(node)->Irq = Irq;
++ PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber;
++
++ } /* for (Function = 0; Function < 8; ++Function) */
++ } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
++ return HvRc;
++}
++
++/*
++ * I/0 Memory copy MUST use mmio commands on iSeries
++ * To do; For performance, include the hv call directly
++ */
++void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
++{
++ u8 ByteValue = c;
++ long NumberOfBytes = Count;
++
++ while (NumberOfBytes > 0) {
++ iSeries_Write_Byte(ByteValue, dest++);
++ -- NumberOfBytes;
++ }
++}
++EXPORT_SYMBOL(iSeries_memset_io);
++
++void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
++{
++ char *src = source;
++ long NumberOfBytes = count;
++
++ while (NumberOfBytes > 0) {
++ iSeries_Write_Byte(*src++, dest++);
++ -- NumberOfBytes;
++ }
++}
++EXPORT_SYMBOL(iSeries_memcpy_toio);
++
++void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
++{
++ char *dst = dest;
++ long NumberOfBytes = count;
++
++ while (NumberOfBytes > 0) {
++ *dst++ = iSeries_Read_Byte(src++);
++ -- NumberOfBytes;
++ }
++}
++EXPORT_SYMBOL(iSeries_memcpy_fromio);
++
++/*
++ * Look down the chain to find the matching Device Device
++ */
++static struct device_node *find_Device_Node(int bus, int devfn)
++{
++ struct pci_dn *pdn;
++
++ list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
++ if ((bus == pdn->busno) && (devfn == pdn->devfn))
++ return pdn->node;
++ }
++ return NULL;
++}
++
++#if 0
++/*
++ * Returns the device node for the passed pci_dev
++ * Sanity Check Node PciDev to passed pci_dev
++ * If none is found, returns a NULL which the client must handle.
++ */
++static struct device_node *get_Device_Node(struct pci_dev *pdev)
++{
++ struct device_node *node;
++
++ node = pdev->sysdata;
++ if (node == NULL || PCI_DN(node)->pcidev != pdev)
++ node = find_Device_Node(pdev->bus->number, pdev->devfn);
++ return node;
++}
++#endif
++
++/*
++ * Config space read and write functions.
++ * For now at least, we look for the device node for the bus and devfn
++ * that we are asked to access. It may be possible to translate the devfn
++ * to a subbus and deviceid more directly.
++ */
++static u64 hv_cfg_read_func[4] = {
++ HvCallPciConfigLoad8, HvCallPciConfigLoad16,
++ HvCallPciConfigLoad32, HvCallPciConfigLoad32
++};
++
++static u64 hv_cfg_write_func[4] = {
++ HvCallPciConfigStore8, HvCallPciConfigStore16,
++ HvCallPciConfigStore32, HvCallPciConfigStore32
++};
++
++/*
++ * Read PCI config space
++ */
++static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int size, u32 *val)
++{
++ struct device_node *node = find_Device_Node(bus->number, devfn);
++ u64 fn;
++ struct HvCallPci_LoadReturn ret;
++
++ if (node == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ if (offset > 255) {
++ *val = ~0;
++ return PCIBIOS_BAD_REGISTER_NUMBER;
++ }
++
++ fn = hv_cfg_read_func[(size - 1) & 3];
++ HvCall3Ret16(fn, &ret, iseries_ds_addr(node), offset, 0);
++
++ if (ret.rc != 0) {
++ *val = ~0;
++ return PCIBIOS_DEVICE_NOT_FOUND; /* or something */
++ }
++
++ *val = ret.value;
++ return 0;
++}
++
++/*
++ * Write PCI config space
++ */
++
++static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int size, u32 val)
++{
++ struct device_node *node = find_Device_Node(bus->number, devfn);
++ u64 fn;
++ u64 ret;
++
++ if (node == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ if (offset > 255)
++ return PCIBIOS_BAD_REGISTER_NUMBER;
++
++ fn = hv_cfg_write_func[(size - 1) & 3];
++ ret = HvCall4(fn, iseries_ds_addr(node), offset, val, 0);
++
++ if (ret != 0)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ return 0;
++}
++
++static struct pci_ops iSeries_pci_ops = {
++ .read = iSeries_pci_read_config,
++ .write = iSeries_pci_write_config
++};
++
++/*
++ * Check Return Code
++ * -> On Failure, print and log information.
++ * Increment Retry Count, if exceeds max, panic partition.
++ *
++ * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
++ * PCI: Device 23.90 ReadL Retry( 1)
++ * PCI: Device 23.90 ReadL Retry Successful(1)
++ */
++static int CheckReturnCode(char *TextHdr, struct device_node *DevNode,
++ int *retry, u64 ret)
++{
++ if (ret != 0) {
++ struct pci_dn *pdn = PCI_DN(DevNode);
++
++ ++Pci_Error_Count;
++ (*retry)++;
++ printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
++ TextHdr, pdn->busno, pdn->devfn,
++ *retry, (int)ret);
++ /*
++ * Bump the retry and check for retry count exceeded.
++ * If, Exceeded, panic the system.
++ */
++ if (((*retry) > Pci_Retry_Max) &&
++ (Pci_Error_Flag > 0)) {
++ mf_display_src(0xB6000103);
++ panic_timeout = 0;
++ panic("PCI: Hardware I/O Error, SRC B6000103, "
++ "Automatic Reboot Disabled.\n");
++ }
++ return -1; /* Retry Try */
++ }
++ return 0;
++}
++
++/*
++ * Translate the I/O Address into a device node, bar, and bar offset.
++ * Note: Make sure the passed variable end up on the stack to avoid
++ * the exposure of being device global.
++ */
++static inline struct device_node *xlate_iomm_address(
++ const volatile void __iomem *IoAddress,
++ u64 *dsaptr, u64 *BarOffsetPtr)
++{
++ unsigned long OrigIoAddr;
++ unsigned long BaseIoAddr;
++ unsigned long TableIndex;
++ struct device_node *DevNode;
++
++ OrigIoAddr = (unsigned long __force)IoAddress;
++ if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory))
++ return NULL;
++ BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY;
++ TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE;
++ DevNode = iomm_table[TableIndex];
++
++ if (DevNode != NULL) {
++ int barnum = iobar_table[TableIndex];
++ *dsaptr = iseries_ds_addr(DevNode) | (barnum << 24);
++ *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE;
++ } else
++ panic("PCI: Invalid PCI IoAddress detected!\n");
++ return DevNode;
++}
++
++/*
++ * Read MM I/O Instructions for the iSeries
++ * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
++ * else, data is returned in big Endian format.
++ *
++ * iSeries_Read_Byte = Read Byte ( 8 bit)
++ * iSeries_Read_Word = Read Word (16 bit)
++ * iSeries_Read_Long = Read Long (32 bit)
++ */
++u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
++{
++ u64 BarOffset;
++ u64 dsa;
++ int retry = 0;
++ struct HvCallPci_LoadReturn ret;
++ struct device_node *DevNode =
++ xlate_iomm_address(IoAddress, &dsa, &BarOffset);
++
++ if (DevNode == NULL) {
++ static unsigned long last_jiffies;
++ static int num_printed;
++
++ if ((jiffies - last_jiffies) > 60 * HZ) {
++ last_jiffies = jiffies;
++ num_printed = 0;
++ }
++ if (num_printed++ < 10)
++ printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress);
++ return 0xff;
++ }
++ do {
++ ++Pci_Io_Read_Count;
++ HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
++ } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
++
++ return (u8)ret.value;
++}
++EXPORT_SYMBOL(iSeries_Read_Byte);
++
++u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
++{
++ u64 BarOffset;
++ u64 dsa;
++ int retry = 0;
++ struct HvCallPci_LoadReturn ret;
++ struct device_node *DevNode =
++ xlate_iomm_address(IoAddress, &dsa, &BarOffset);
++
++ if (DevNode == NULL) {
++ static unsigned long last_jiffies;
++ static int num_printed;
++
++ if ((jiffies - last_jiffies) > 60 * HZ) {
++ last_jiffies = jiffies;
++ num_printed = 0;
++ }
++ if (num_printed++ < 10)
++ printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress);
++ return 0xffff;
++ }
++ do {
++ ++Pci_Io_Read_Count;
++ HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
++ BarOffset, 0);
++ } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
++
++ return swab16((u16)ret.value);
++}
++EXPORT_SYMBOL(iSeries_Read_Word);
++
++u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
++{
++ u64 BarOffset;
++ u64 dsa;
++ int retry = 0;
++ struct HvCallPci_LoadReturn ret;
++ struct device_node *DevNode =
++ xlate_iomm_address(IoAddress, &dsa, &BarOffset);
++
++ if (DevNode == NULL) {
++ static unsigned long last_jiffies;
++ static int num_printed;
++
++ if ((jiffies - last_jiffies) > 60 * HZ) {
++ last_jiffies = jiffies;
++ num_printed = 0;
++ }
++ if (num_printed++ < 10)
++ printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress);
++ return 0xffffffff;
++ }
++ do {
++ ++Pci_Io_Read_Count;
++ HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
++ BarOffset, 0);
++ } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
++
++ return swab32((u32)ret.value);
++}
++EXPORT_SYMBOL(iSeries_Read_Long);
++
++/*
++ * Write MM I/O Instructions for the iSeries
++ *
++ * iSeries_Write_Byte = Write Byte (8 bit)
++ * iSeries_Write_Word = Write Word(16 bit)
++ * iSeries_Write_Long = Write Long(32 bit)
++ */
++void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
++{
++ u64 BarOffset;
++ u64 dsa;
++ int retry = 0;
++ u64 rc;
++ struct device_node *DevNode =
++ xlate_iomm_address(IoAddress, &dsa, &BarOffset);
++
++ if (DevNode == NULL) {
++ static unsigned long last_jiffies;
++ static int num_printed;
++
++ if ((jiffies - last_jiffies) > 60 * HZ) {
++ last_jiffies = jiffies;
++ num_printed = 0;
++ }
++ if (num_printed++ < 10)
++ printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress);
++ return;
++ }
++ do {
++ ++Pci_Io_Write_Count;
++ rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
++ } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
++}
++EXPORT_SYMBOL(iSeries_Write_Byte);
++
++void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
++{
++ u64 BarOffset;
++ u64 dsa;
++ int retry = 0;
++ u64 rc;
++ struct device_node *DevNode =
++ xlate_iomm_address(IoAddress, &dsa, &BarOffset);
++
++ if (DevNode == NULL) {
++ static unsigned long last_jiffies;
++ static int num_printed;
++
++ if ((jiffies - last_jiffies) > 60 * HZ) {
++ last_jiffies = jiffies;
++ num_printed = 0;
++ }
++ if (num_printed++ < 10)
++ printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress);
++ return;
++ }
++ do {
++ ++Pci_Io_Write_Count;
++ rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
++ } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
++}
++EXPORT_SYMBOL(iSeries_Write_Word);
++
++void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
++{
++ u64 BarOffset;
++ u64 dsa;
++ int retry = 0;
++ u64 rc;
++ struct device_node *DevNode =
++ xlate_iomm_address(IoAddress, &dsa, &BarOffset);
++
++ if (DevNode == NULL) {
++ static unsigned long last_jiffies;
++ static int num_printed;
++
++ if ((jiffies - last_jiffies) > 60 * HZ) {
++ last_jiffies = jiffies;
++ num_printed = 0;
++ }
++ if (num_printed++ < 10)
++ printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress);
++ return;
++ }
++ do {
++ ++Pci_Io_Write_Count;
++ rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
++ } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
++}
++EXPORT_SYMBOL(iSeries_Write_Long);
+diff --git a/arch/powerpc/platforms/iseries/pci.h b/arch/powerpc/platforms/iseries/pci.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/pci.h
+@@ -0,0 +1,63 @@
++#ifndef _PLATFORMS_ISERIES_PCI_H
++#define _PLATFORMS_ISERIES_PCI_H
++
++/*
++ * Created by Allan Trautman on Tue Feb 20, 2001.
++ *
++ * Define some useful macros for the iSeries pci routines.
++ * Copyright (C) 2001 Allan H Trautman, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the:
++ * Free Software Foundation, Inc.,
++ * 59 Temple Place, Suite 330,
++ * Boston, MA 02111-1307 USA
++ *
++ * Change Activity:
++ * Created Feb 20, 2001
++ * Added device reset, March 22, 2001
++ * Ported to ppc64, May 25, 2001
++ * End Change Activity
++ */
++
++#include <asm/pci-bridge.h>
++
++struct pci_dev; /* For Forward Reference */
++
++/*
++ * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
++ * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
++ */
++
++#define ISERIES_PCI_AGENTID(idsel, func) \
++ (((idsel & 0x0F) << 4) | (func & 0x07))
++#define ISERIES_ENCODE_DEVICE(agentid) \
++ ((0x10) | ((agentid & 0x20) >> 2) | (agentid & 0x07))
++
++#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
++#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
++
++/*
++ * Generate a Direct Select Address for the Hypervisor
++ */
++static inline u64 iseries_ds_addr(struct device_node *node)
++{
++ struct pci_dn *pdn = PCI_DN(node);
++
++ return ((u64)pdn->busno << 48) + ((u64)pdn->bussubno << 40)
++ + ((u64)0x10 << 32);
++}
++
++extern void iSeries_Device_Information(struct pci_dev*, int);
++
++#endif /* _PLATFORMS_ISERIES_PCI_H */
+diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/proc.c
+@@ -0,0 +1,116 @@
++/*
++ * Copyright (C) 2001 Kyle A. Lucke IBM Corporation
++ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/param.h> /* for HZ */
++#include <asm/paca.h>
++#include <asm/processor.h>
++#include <asm/time.h>
++#include <asm/lppaca.h>
++#include <asm/iSeries/ItLpQueue.h>
++#include <asm/iSeries/HvCallXm.h>
++
++#include "processor_vpd.h"
++#include "main_store.h"
++
++static int __init iseries_proc_create(void)
++{
++ struct proc_dir_entry *e = proc_mkdir("iSeries", 0);
++ if (!e)
++ return 1;
++
++ return 0;
++}
++core_initcall(iseries_proc_create);
++
++static unsigned long startTitan = 0;
++static unsigned long startTb = 0;
++
++static int proc_titantod_show(struct seq_file *m, void *v)
++{
++ unsigned long tb0, titan_tod;
++
++ tb0 = get_tb();
++ titan_tod = HvCallXm_loadTod();
++
++ seq_printf(m, "Titan\n" );
++ seq_printf(m, " time base = %016lx\n", tb0);
++ seq_printf(m, " titan tod = %016lx\n", titan_tod);
++ seq_printf(m, " xProcFreq = %016x\n",
++ xIoHriProcessorVpd[0].xProcFreq);
++ seq_printf(m, " xTimeBaseFreq = %016x\n",
++ xIoHriProcessorVpd[0].xTimeBaseFreq);
++ seq_printf(m, " tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy);
++ seq_printf(m, " tb_ticks_per_usec = %lu\n", tb_ticks_per_usec);
++
++ if (!startTitan) {
++ startTitan = titan_tod;
++ startTb = tb0;
++ } else {
++ unsigned long titan_usec = (titan_tod - startTitan) >> 12;
++ unsigned long tb_ticks = (tb0 - startTb);
++ unsigned long titan_jiffies = titan_usec / (1000000/HZ);
++ unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ);
++ unsigned long titan_jiff_rem_usec =
++ titan_usec - titan_jiff_usec;
++ unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy;
++ unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy;
++ unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks;
++ unsigned long tb_jiff_rem_usec =
++ tb_jiff_rem_ticks / tb_ticks_per_usec;
++ unsigned long new_tb_ticks_per_jiffy =
++ (tb_ticks * (1000000/HZ))/titan_usec;
++
++ seq_printf(m, " titan elapsed = %lu uSec\n", titan_usec);
++ seq_printf(m, " tb elapsed = %lu ticks\n", tb_ticks);
++ seq_printf(m, " titan jiffies = %lu.%04lu \n", titan_jiffies,
++ titan_jiff_rem_usec);
++ seq_printf(m, " tb jiffies = %lu.%04lu\n", tb_jiffies,
++ tb_jiff_rem_usec);
++ seq_printf(m, " new tb_ticks_per_jiffy = %lu\n",
++ new_tb_ticks_per_jiffy);
++ }
++
++ return 0;
++}
++
++static int proc_titantod_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, proc_titantod_show, NULL);
++}
++
++static struct file_operations proc_titantod_operations = {
++ .open = proc_titantod_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init iseries_proc_init(void)
++{
++ struct proc_dir_entry *e;
++
++ e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
++ if (e)
++ e->proc_fops = &proc_titantod_operations;
++
++ return 0;
++}
++__initcall(iseries_proc_init);
+diff --git a/arch/powerpc/platforms/iseries/processor_vpd.h b/arch/powerpc/platforms/iseries/processor_vpd.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/processor_vpd.h
+@@ -0,0 +1,85 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _ISERIES_PROCESSOR_VPD_H
++#define _ISERIES_PROCESSOR_VPD_H
++
++#include <asm/types.h>
++
++/*
++ * This struct maps Processor Vpd that is DMAd to SLIC by CSP
++ */
++struct IoHriProcessorVpd {
++ u8 xFormat; // VPD format indicator x00-x00
++ u8 xProcStatus:8; // Processor State x01-x01
++ u8 xSecondaryThreadCount; // Secondary thread cnt x02-x02
++ u8 xSrcType:1; // Src Type x03-x03
++ u8 xSrcSoft:1; // Src stay soft ...
++ u8 xSrcParable:1; // Src parable ...
++ u8 xRsvd1:5; // Reserved ...
++ u16 xHvPhysicalProcIndex; // Hypervisor physical proc index04-x05
++ u16 xRsvd2; // Reserved x06-x07
++ u32 xHwNodeId; // Hardware node id x08-x0B
++ u32 xHwProcId; // Hardware processor id x0C-x0F
++
++ u32 xTypeNum; // Card Type/CCIN number x10-x13
++ u32 xModelNum; // Model/Feature number x14-x17
++ u64 xSerialNum; // Serial number x18-x1F
++ char xPartNum[12]; // Book Part or FPU number x20-x2B
++ char xMfgID[4]; // Manufacturing ID x2C-x2F
++
++ u32 xProcFreq; // Processor Frequency x30-x33
++ u32 xTimeBaseFreq; // Time Base Frequency x34-x37
++
++ u32 xChipEcLevel; // Chip EC Levels x38-x3B
++ u32 xProcIdReg; // PIR SPR value x3C-x3F
++ u32 xPVR; // PVR value x40-x43
++ u8 xRsvd3[12]; // Reserved x44-x4F
++
++ u32 xInstCacheSize; // Instruction cache size in KB x50-x53
++ u32 xInstBlockSize; // Instruction cache block size x54-x57
++ u32 xDataCacheOperandSize; // Data cache operand size x58-x5B
++ u32 xInstCacheOperandSize; // Inst cache operand size x5C-x5F
++
++ u32 xDataL1CacheSizeKB; // L1 data cache size in KB x60-x63
++ u32 xDataL1CacheLineSize; // L1 data cache block size x64-x67
++ u64 xRsvd4; // Reserved x68-x6F
++
++ u32 xDataL2CacheSizeKB; // L2 data cache size in KB x70-x73
++ u32 xDataL2CacheLineSize; // L2 data cache block size x74-x77
++ u64 xRsvd5; // Reserved x78-x7F
++
++ u32 xDataL3CacheSizeKB; // L3 data cache size in KB x80-x83
++ u32 xDataL3CacheLineSize; // L3 data cache block size x84-x87
++ u64 xRsvd6; // Reserved x88-x8F
++
++ u64 xFruLabel; // Card Location Label x90-x97
++ u8 xSlotsOnCard; // Slots on card (0=no slots) x98-x98
++ u8 xPartLocFlag; // Location flag (0-pluggable 1-imbedded) x99-x99
++ u16 xSlotMapIndex; // Index in slot map table x9A-x9B
++ u8 xSmartCardPortNo; // Smart card port number x9C-x9C
++ u8 xRsvd7; // Reserved x9D-x9D
++ u16 xFrameIdAndRackUnit; // Frame ID and rack unit adr x9E-x9F
++
++ u8 xRsvd8[24]; // Reserved xA0-xB7
++
++ char xProcSrc[72]; // CSP format SRC xB8-xFF
++};
++
++extern struct IoHriProcessorVpd xIoHriProcessorVpd[];
++
++#endif /* _ISERIES_PROCESSOR_VPD_H */
+diff --git a/arch/powerpc/platforms/iseries/release_data.h b/arch/powerpc/platforms/iseries/release_data.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/release_data.h
+@@ -0,0 +1,63 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _ISERIES_RELEASE_DATA_H
++#define _ISERIES_RELEASE_DATA_H
++
++/*
++ * This control block contains the critical information about the
++ * release so that it can be changed in the future (ie, the virtual
++ * address of the OS's NACA).
++ */
++#include <asm/types.h>
++#include <asm/naca.h>
++
++/*
++ * When we IPL a secondary partition, we will check if if the
++ * secondary xMinPlicVrmIndex > the primary xVrmIndex.
++ * If it is then this tells PLIC that this secondary is not
++ * supported running on this "old" of a level of PLIC.
++ *
++ * Likewise, we will compare the primary xMinSlicVrmIndex to
++ * the secondary xVrmIndex.
++ * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we
++ * know that this PLIC does not support running an OS "that old".
++ */
++
++#define HVREL_TAGSINACTIVE 0x8000
++#define HVREL_32BIT 0x4000
++#define HVREL_NOSHAREDPROCS 0x2000
++#define HVREL_NOHMT 0x1000
++
++struct HvReleaseData {
++ u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */
++ u16 xSize; /* Size of this control block x04-x05 */
++ u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */
++ struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */
++ u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */
++ u32 xRsvd1; /* Reserved x14-x17 */
++ u16 xFlags;
++ u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */
++ u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */
++ u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */
++ char xVrmName[12]; /* Displayable name x20-x2B */
++ char xRsvd3[20]; /* Reserved x2C-x3F */
++};
++
++extern struct HvReleaseData hvReleaseData;
++
++#endif /* _ISERIES_RELEASE_DATA_H */
+diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/setup.c
+@@ -0,0 +1,996 @@
++/*
++ * Copyright (c) 2000 Mike Corrigan <mikejc at us.ibm.com>
++ * Copyright (c) 1999-2000 Grant Erickson <grant at lcse.umn.edu>
++ *
++ * Description:
++ * Architecture- / platform-specific boot-time initialization code for
++ * the IBM iSeries LPAR. Adapted from original code by Grant Erickson and
++ * code by Gary Thomas, Cort Dougan <cort at fsmlabs.com>, and Dan Malek
++ * <dan at net4x.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.
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/threads.h>
++#include <linux/smp.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/initrd.h>
++#include <linux/seq_file.h>
++#include <linux/kdev_t.h>
++#include <linux/major.h>
++#include <linux/root_dev.h>
++
++#include <asm/processor.h>
++#include <asm/machdep.h>
++#include <asm/page.h>
++#include <asm/mmu.h>
++#include <asm/pgtable.h>
++#include <asm/mmu_context.h>
++#include <asm/cputable.h>
++#include <asm/sections.h>
++#include <asm/iommu.h>
++#include <asm/firmware.h>
++
++#include <asm/time.h>
++#include <asm/naca.h>
++#include <asm/paca.h>
++#include <asm/cache.h>
++#include <asm/sections.h>
++#include <asm/abs_addr.h>
++#include <asm/iSeries/HvLpConfig.h>
++#include <asm/iSeries/HvCallEvent.h>
++#include <asm/iSeries/HvCallXm.h>
++#include <asm/iSeries/ItLpQueue.h>
++#include <asm/iSeries/mf.h>
++#include <asm/iSeries/HvLpEvent.h>
++#include <asm/iSeries/LparMap.h>
++
++#include "setup.h"
++#include "irq.h"
++#include "vpd_areas.h"
++#include "processor_vpd.h"
++#include "main_store.h"
++#include "call_sm.h"
++#include "call_hpt.h"
++
++extern void hvlog(char *fmt, ...);
++
++#ifdef DEBUG
++#define DBG(fmt...) hvlog(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/* Function Prototypes */
++extern void ppcdbg_initialize(void);
++
++static void build_iSeries_Memory_Map(void);
++static void iseries_shared_idle(void);
++static void iseries_dedicated_idle(void);
++#ifdef CONFIG_PCI
++extern void iSeries_pci_final_fixup(void);
++#else
++static void iSeries_pci_final_fixup(void) { }
++#endif
++
++/* Global Variables */
++int piranha_simulator;
++
++extern int rd_size; /* Defined in drivers/block/rd.c */
++extern unsigned long klimit;
++extern unsigned long embedded_sysmap_start;
++extern unsigned long embedded_sysmap_end;
++
++extern unsigned long iSeries_recal_tb;
++extern unsigned long iSeries_recal_titan;
++
++static int mf_initialized;
++
++struct MemoryBlock {
++ unsigned long absStart;
++ unsigned long absEnd;
++ unsigned long logicalStart;
++ unsigned long logicalEnd;
++};
++
++/*
++ * Process the main store vpd to determine where the holes in memory are
++ * and return the number of physical blocks and fill in the array of
++ * block data.
++ */
++static unsigned long iSeries_process_Condor_mainstore_vpd(
++ struct MemoryBlock *mb_array, unsigned long max_entries)
++{
++ unsigned long holeFirstChunk, holeSizeChunks;
++ unsigned long numMemoryBlocks = 1;
++ struct IoHriMainStoreSegment4 *msVpd =
++ (struct IoHriMainStoreSegment4 *)xMsVpd;
++ unsigned long holeStart = msVpd->nonInterleavedBlocksStartAdr;
++ unsigned long holeEnd = msVpd->nonInterleavedBlocksEndAdr;
++ unsigned long holeSize = holeEnd - holeStart;
++
++ printk("Mainstore_VPD: Condor\n");
++ /*
++ * Determine if absolute memory has any
++ * holes so that we can interpret the
++ * access map we get back from the hypervisor
++ * correctly.
++ */
++ mb_array[0].logicalStart = 0;
++ mb_array[0].logicalEnd = 0x100000000;
++ mb_array[0].absStart = 0;
++ mb_array[0].absEnd = 0x100000000;
++
++ if (holeSize) {
++ numMemoryBlocks = 2;
++ holeStart = holeStart & 0x000fffffffffffff;
++ holeStart = addr_to_chunk(holeStart);
++ holeFirstChunk = holeStart;
++ holeSize = addr_to_chunk(holeSize);
++ holeSizeChunks = holeSize;
++ printk( "Main store hole: start chunk = %0lx, size = %0lx chunks\n",
++ holeFirstChunk, holeSizeChunks );
++ mb_array[0].logicalEnd = holeFirstChunk;
++ mb_array[0].absEnd = holeFirstChunk;
++ mb_array[1].logicalStart = holeFirstChunk;
++ mb_array[1].logicalEnd = 0x100000000 - holeSizeChunks;
++ mb_array[1].absStart = holeFirstChunk + holeSizeChunks;
++ mb_array[1].absEnd = 0x100000000;
++ }
++ return numMemoryBlocks;
++}
++
++#define MaxSegmentAreas 32
++#define MaxSegmentAdrRangeBlocks 128
++#define MaxAreaRangeBlocks 4
++
++static unsigned long iSeries_process_Regatta_mainstore_vpd(
++ struct MemoryBlock *mb_array, unsigned long max_entries)
++{
++ struct IoHriMainStoreSegment5 *msVpdP =
++ (struct IoHriMainStoreSegment5 *)xMsVpd;
++ unsigned long numSegmentBlocks = 0;
++ u32 existsBits = msVpdP->msAreaExists;
++ unsigned long area_num;
++
++ printk("Mainstore_VPD: Regatta\n");
++
++ for (area_num = 0; area_num < MaxSegmentAreas; ++area_num ) {
++ unsigned long numAreaBlocks;
++ struct IoHriMainStoreArea4 *currentArea;
++
++ if (existsBits & 0x80000000) {
++ unsigned long block_num;
++
++ currentArea = &msVpdP->msAreaArray[area_num];
++ numAreaBlocks = currentArea->numAdrRangeBlocks;
++ printk("ms_vpd: processing area %2ld blocks=%ld",
++ area_num, numAreaBlocks);
++ for (block_num = 0; block_num < numAreaBlocks;
++ ++block_num ) {
++ /* Process an address range block */
++ struct MemoryBlock tempBlock;
++ unsigned long i;
++
++ tempBlock.absStart =
++ (unsigned long)currentArea->xAdrRangeBlock[block_num].blockStart;
++ tempBlock.absEnd =
++ (unsigned long)currentArea->xAdrRangeBlock[block_num].blockEnd;
++ tempBlock.logicalStart = 0;
++ tempBlock.logicalEnd = 0;
++ printk("\n block %ld absStart=%016lx absEnd=%016lx",
++ block_num, tempBlock.absStart,
++ tempBlock.absEnd);
++
++ for (i = 0; i < numSegmentBlocks; ++i) {
++ if (mb_array[i].absStart ==
++ tempBlock.absStart)
++ break;
++ }
++ if (i == numSegmentBlocks) {
++ if (numSegmentBlocks == max_entries)
++ panic("iSeries_process_mainstore_vpd: too many memory blocks");
++ mb_array[numSegmentBlocks] = tempBlock;
++ ++numSegmentBlocks;
++ } else
++ printk(" (duplicate)");
++ }
++ printk("\n");
++ }
++ existsBits <<= 1;
++ }
++ /* Now sort the blocks found into ascending sequence */
++ if (numSegmentBlocks > 1) {
++ unsigned long m, n;
++
++ for (m = 0; m < numSegmentBlocks - 1; ++m) {
++ for (n = numSegmentBlocks - 1; m < n; --n) {
++ if (mb_array[n].absStart <
++ mb_array[n-1].absStart) {
++ struct MemoryBlock tempBlock;
++
++ tempBlock = mb_array[n];
++ mb_array[n] = mb_array[n-1];
++ mb_array[n-1] = tempBlock;
++ }
++ }
++ }
++ }
++ /*
++ * Assign "logical" addresses to each block. These
++ * addresses correspond to the hypervisor "bitmap" space.
++ * Convert all addresses into units of 256K chunks.
++ */
++ {
++ unsigned long i, nextBitmapAddress;
++
++ printk("ms_vpd: %ld sorted memory blocks\n", numSegmentBlocks);
++ nextBitmapAddress = 0;
++ for (i = 0; i < numSegmentBlocks; ++i) {
++ unsigned long length = mb_array[i].absEnd -
++ mb_array[i].absStart;
++
++ mb_array[i].logicalStart = nextBitmapAddress;
++ mb_array[i].logicalEnd = nextBitmapAddress + length;
++ nextBitmapAddress += length;
++ printk(" Bitmap range: %016lx - %016lx\n"
++ " Absolute range: %016lx - %016lx\n",
++ mb_array[i].logicalStart,
++ mb_array[i].logicalEnd,
++ mb_array[i].absStart, mb_array[i].absEnd);
++ mb_array[i].absStart = addr_to_chunk(mb_array[i].absStart &
++ 0x000fffffffffffff);
++ mb_array[i].absEnd = addr_to_chunk(mb_array[i].absEnd &
++ 0x000fffffffffffff);
++ mb_array[i].logicalStart =
++ addr_to_chunk(mb_array[i].logicalStart);
++ mb_array[i].logicalEnd = addr_to_chunk(mb_array[i].logicalEnd);
++ }
++ }
++
++ return numSegmentBlocks;
++}
++
++static unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
++ unsigned long max_entries)
++{
++ unsigned long i;
++ unsigned long mem_blocks = 0;
++
++ if (cpu_has_feature(CPU_FTR_SLB))
++ mem_blocks = iSeries_process_Regatta_mainstore_vpd(mb_array,
++ max_entries);
++ else
++ mem_blocks = iSeries_process_Condor_mainstore_vpd(mb_array,
++ max_entries);
++
++ printk("Mainstore_VPD: numMemoryBlocks = %ld \n", mem_blocks);
++ for (i = 0; i < mem_blocks; ++i) {
++ printk("Mainstore_VPD: block %3ld logical chunks %016lx - %016lx\n"
++ " abs chunks %016lx - %016lx\n",
++ i, mb_array[i].logicalStart, mb_array[i].logicalEnd,
++ mb_array[i].absStart, mb_array[i].absEnd);
++ }
++ return mem_blocks;
++}
++
++static void __init iSeries_get_cmdline(void)
++{
++ char *p, *q;
++
++ /* copy the command line parameter from the primary VSP */
++ HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
++ HvLpDma_Direction_RemoteToLocal);
++
++ p = cmd_line;
++ q = cmd_line + 255;
++ while(p < q) {
++ if (!*p || *p == '\n')
++ break;
++ ++p;
++ }
++ *p = 0;
++}
++
++static void __init iSeries_init_early(void)
++{
++ DBG(" -> iSeries_init_early()\n");
++
++ ppc64_firmware_features = FW_FEATURE_ISERIES;
++
++ ppcdbg_initialize();
++
++ ppc64_interrupt_controller = IC_ISERIES;
++
++#if defined(CONFIG_BLK_DEV_INITRD)
++ /*
++ * If the init RAM disk has been configured and there is
++ * a non-zero starting address for it, set it up
++ */
++ if (naca.xRamDisk) {
++ initrd_start = (unsigned long)__va(naca.xRamDisk);
++ initrd_end = initrd_start + naca.xRamDiskSize * PAGE_SIZE;
++ initrd_below_start_ok = 1; // ramdisk in kernel space
++ ROOT_DEV = Root_RAM0;
++ if (((rd_size * 1024) / PAGE_SIZE) < naca.xRamDiskSize)
++ rd_size = (naca.xRamDiskSize * PAGE_SIZE) / 1024;
++ } else
++#endif /* CONFIG_BLK_DEV_INITRD */
++ {
++ /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */
++ }
++
++ iSeries_recal_tb = get_tb();
++ iSeries_recal_titan = HvCallXm_loadTod();
++
++ /*
++ * Initialize the hash table management pointers
++ */
++ hpte_init_iSeries();
++
++ /*
++ * Initialize the DMA/TCE management
++ */
++ iommu_init_early_iSeries();
++
++ iSeries_get_cmdline();
++
++ /* Save unparsed command line copy for /proc/cmdline */
++ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
++
++ /* Parse early parameters, in particular mem=x */
++ parse_early_param();
++
++ if (memory_limit) {
++ if (memory_limit < systemcfg->physicalMemorySize)
++ systemcfg->physicalMemorySize = memory_limit;
++ else {
++ printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
++ memory_limit = 0;
++ }
++ }
++
++ /* Initialize machine-dependency vectors */
++#ifdef CONFIG_SMP
++ smp_init_iSeries();
++#endif
++ if (itLpNaca.xPirEnvironMode == 0)
++ piranha_simulator = 1;
++
++ /* Associate Lp Event Queue 0 with processor 0 */
++ HvCallEvent_setLpEventQueueInterruptProc(0, 0);
++
++ mf_init();
++ mf_initialized = 1;
++ mb();
++
++ /* If we were passed an initrd, set the ROOT_DEV properly if the values
++ * look sensible. If not, clear initrd reference.
++ */
++#ifdef CONFIG_BLK_DEV_INITRD
++ if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
++ initrd_end > initrd_start)
++ ROOT_DEV = Root_RAM0;
++ else
++ initrd_start = initrd_end = 0;
++#endif /* CONFIG_BLK_DEV_INITRD */
++
++ DBG(" <- iSeries_init_early()\n");
++}
++
++struct mschunks_map mschunks_map = {
++ /* XXX We don't use these, but Piranha might need them. */
++ .chunk_size = MSCHUNKS_CHUNK_SIZE,
++ .chunk_shift = MSCHUNKS_CHUNK_SHIFT,
++ .chunk_mask = MSCHUNKS_OFFSET_MASK,
++};
++EXPORT_SYMBOL(mschunks_map);
++
++void mschunks_alloc(unsigned long num_chunks)
++{
++ klimit = _ALIGN(klimit, sizeof(u32));
++ mschunks_map.mapping = (u32 *)klimit;
++ klimit += num_chunks * sizeof(u32);
++ mschunks_map.num_chunks = num_chunks;
++}
++
++/*
++ * The iSeries may have very large memories ( > 128 GB ) and a partition
++ * may get memory in "chunks" that may be anywhere in the 2**52 real
++ * address space. The chunks are 256K in size. To map this to the
++ * memory model Linux expects, the AS/400 specific code builds a
++ * translation table to translate what Linux thinks are "physical"
++ * addresses to the actual real addresses. This allows us to make
++ * it appear to Linux that we have contiguous memory starting at
++ * physical address zero while in fact this could be far from the truth.
++ * To avoid confusion, I'll let the words physical and/or real address
++ * apply to the Linux addresses while I'll use "absolute address" to
++ * refer to the actual hardware real address.
++ *
++ * build_iSeries_Memory_Map gets information from the Hypervisor and
++ * looks at the Main Store VPD to determine the absolute addresses
++ * of the memory that has been assigned to our partition and builds
++ * a table used to translate Linux's physical addresses to these
++ * absolute addresses. Absolute addresses are needed when
++ * communicating with the hypervisor (e.g. to build HPT entries)
++ */
++
++static void __init build_iSeries_Memory_Map(void)
++{
++ u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize;
++ u32 nextPhysChunk;
++ u32 hptFirstChunk, hptLastChunk, hptSizeChunks, hptSizePages;
++ u32 totalChunks,moreChunks;
++ u32 currChunk, thisChunk, absChunk;
++ u32 currDword;
++ u32 chunkBit;
++ u64 map;
++ struct MemoryBlock mb[32];
++ unsigned long numMemoryBlocks, curBlock;
++
++ /* Chunk size on iSeries is 256K bytes */
++ totalChunks = (u32)HvLpConfig_getMsChunks();
++ mschunks_alloc(totalChunks);
++
++ /*
++ * Get absolute address of our load area
++ * and map it to physical address 0
++ * This guarantees that the loadarea ends up at physical 0
++ * otherwise, it might not be returned by PLIC as the first
++ * chunks
++ */
++
++ loadAreaFirstChunk = (u32)addr_to_chunk(itLpNaca.xLoadAreaAddr);
++ loadAreaSize = itLpNaca.xLoadAreaChunks;
++
++ /*
++ * Only add the pages already mapped here.
++ * Otherwise we might add the hpt pages
++ * The rest of the pages of the load area
++ * aren't in the HPT yet and can still
++ * be assigned an arbitrary physical address
++ */
++ if ((loadAreaSize * 64) > HvPagesToMap)
++ loadAreaSize = HvPagesToMap / 64;
++
++ loadAreaLastChunk = loadAreaFirstChunk + loadAreaSize - 1;
++
++ /*
++ * TODO Do we need to do something if the HPT is in the 64MB load area?
++ * This would be required if the itLpNaca.xLoadAreaChunks includes
++ * the HPT size
++ */
++
++ printk("Mapping load area - physical addr = 0000000000000000\n"
++ " absolute addr = %016lx\n",
++ chunk_to_addr(loadAreaFirstChunk));
++ printk("Load area size %dK\n", loadAreaSize * 256);
++
++ for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)
++ mschunks_map.mapping[nextPhysChunk] =
++ loadAreaFirstChunk + nextPhysChunk;
++
++ /*
++ * Get absolute address of our HPT and remember it so
++ * we won't map it to any physical address
++ */
++ hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
++ hptSizePages = (u32)HvCallHpt_getHptPages();
++ hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT);
++ hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
++
++ printk("HPT absolute addr = %016lx, size = %dK\n",
++ chunk_to_addr(hptFirstChunk), hptSizeChunks * 256);
++
++ ppc64_pft_size = __ilog2(hptSizePages * PAGE_SIZE);
++
++ /*
++ * The actual hashed page table is in the hypervisor,
++ * we have no direct access
++ */
++ htab_address = NULL;
++
++ /*
++ * Determine if absolute memory has any
++ * holes so that we can interpret the
++ * access map we get back from the hypervisor
++ * correctly.
++ */
++ numMemoryBlocks = iSeries_process_mainstore_vpd(mb, 32);
++
++ /*
++ * Process the main store access map from the hypervisor
++ * to build up our physical -> absolute translation table
++ */
++ curBlock = 0;
++ currChunk = 0;
++ currDword = 0;
++ moreChunks = totalChunks;
++
++ while (moreChunks) {
++ map = HvCallSm_get64BitsOfAccessMap(itLpNaca.xLpIndex,
++ currDword);
++ thisChunk = currChunk;
++ while (map) {
++ chunkBit = map >> 63;
++ map <<= 1;
++ if (chunkBit) {
++ --moreChunks;
++ while (thisChunk >= mb[curBlock].logicalEnd) {
++ ++curBlock;
++ if (curBlock >= numMemoryBlocks)
++ panic("out of memory blocks");
++ }
++ if (thisChunk < mb[curBlock].logicalStart)
++ panic("memory block error");
++
++ absChunk = mb[curBlock].absStart +
++ (thisChunk - mb[curBlock].logicalStart);
++ if (((absChunk < hptFirstChunk) ||
++ (absChunk > hptLastChunk)) &&
++ ((absChunk < loadAreaFirstChunk) ||
++ (absChunk > loadAreaLastChunk))) {
++ mschunks_map.mapping[nextPhysChunk] =
++ absChunk;
++ ++nextPhysChunk;
++ }
++ }
++ ++thisChunk;
++ }
++ ++currDword;
++ currChunk += 64;
++ }
++
++ /*
++ * main store size (in chunks) is
++ * totalChunks - hptSizeChunks
++ * which should be equal to
++ * nextPhysChunk
++ */
++ systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
++}
++
++/*
++ * Document me.
++ */
++static void __init iSeries_setup_arch(void)
++{
++ unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
++
++ if (get_paca()->lppaca.shared_proc) {
++ ppc_md.idle_loop = iseries_shared_idle;
++ printk(KERN_INFO "Using shared processor idle loop\n");
++ } else {
++ ppc_md.idle_loop = iseries_dedicated_idle;
++ printk(KERN_INFO "Using dedicated idle loop\n");
++ }
++
++ /* Setup the Lp Event Queue */
++ setup_hvlpevent_queue();
++
++ printk("Max logical processors = %d\n",
++ itVpdAreas.xSlicMaxLogicalProcs);
++ printk("Max physical processors = %d\n",
++ itVpdAreas.xSlicMaxPhysicalProcs);
++
++ systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
++ printk("Processor version = %x\n", systemcfg->processor);
++}
++
++static void iSeries_show_cpuinfo(struct seq_file *m)
++{
++ seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
++}
++
++/*
++ * Document me.
++ * and Implement me.
++ */
++static int iSeries_get_irq(struct pt_regs *regs)
++{
++ /* -2 means ignore this interrupt */
++ return -2;
++}
++
++/*
++ * Document me.
++ */
++static void iSeries_restart(char *cmd)
++{
++ mf_reboot();
++}
++
++/*
++ * Document me.
++ */
++static void iSeries_power_off(void)
++{
++ mf_power_off();
++}
++
++/*
++ * Document me.
++ */
++static void iSeries_halt(void)
++{
++ mf_power_off();
++}
++
++static void __init iSeries_progress(char * st, unsigned short code)
++{
++ printk("Progress: [%04x] - %s\n", (unsigned)code, st);
++ if (!piranha_simulator && mf_initialized) {
++ if (code != 0xffff)
++ mf_display_progress(code);
++ else
++ mf_clear_src();
++ }
++}
++
++static void __init iSeries_fixup_klimit(void)
++{
++ /*
++ * Change klimit to take into account any ram disk
++ * that may be included
++ */
++ if (naca.xRamDisk)
++ klimit = KERNELBASE + (u64)naca.xRamDisk +
++ (naca.xRamDiskSize * PAGE_SIZE);
++ else {
++ /*
++ * No ram disk was included - check and see if there
++ * was an embedded system map. Change klimit to take
++ * into account any embedded system map
++ */
++ if (embedded_sysmap_end)
++ klimit = KERNELBASE + ((embedded_sysmap_end + 4095) &
++ 0xfffffffffffff000);
++ }
++}
++
++static int __init iSeries_src_init(void)
++{
++ /* clear the progress line */
++ ppc_md.progress(" ", 0xffff);
++ return 0;
++}
++
++late_initcall(iSeries_src_init);
++
++static inline void process_iSeries_events(void)
++{
++ asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
++}
++
++static void yield_shared_processor(void)
++{
++ unsigned long tb;
++
++ HvCall_setEnabledInterrupts(HvCall_MaskIPI |
++ HvCall_MaskLpEvent |
++ HvCall_MaskLpProd |
++ HvCall_MaskTimeout);
++
++ tb = get_tb();
++ /* Compute future tb value when yield should expire */
++ HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
++
++ /*
++ * The decrementer stops during the yield. Force a fake decrementer
++ * here and let the timer_interrupt code sort out the actual time.
++ */
++ get_paca()->lppaca.int_dword.fields.decr_int = 1;
++ process_iSeries_events();
++}
++
++static void iseries_shared_idle(void)
++{
++ while (1) {
++ while (!need_resched() && !hvlpevent_is_pending()) {
++ local_irq_disable();
++ ppc64_runlatch_off();
++
++ /* Recheck with irqs off */
++ if (!need_resched() && !hvlpevent_is_pending())
++ yield_shared_processor();
++
++ HMT_medium();
++ local_irq_enable();
++ }
++
++ ppc64_runlatch_on();
++
++ if (hvlpevent_is_pending())
++ process_iSeries_events();
++
++ schedule();
++ }
++}
++
++static void iseries_dedicated_idle(void)
++{
++ long oldval;
++
++ while (1) {
++ oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
++
++ if (!oldval) {
++ set_thread_flag(TIF_POLLING_NRFLAG);
++
++ while (!need_resched()) {
++ ppc64_runlatch_off();
++ HMT_low();
++
++ if (hvlpevent_is_pending()) {
++ HMT_medium();
++ ppc64_runlatch_on();
++ process_iSeries_events();
++ }
++ }
++
++ HMT_medium();
++ clear_thread_flag(TIF_POLLING_NRFLAG);
++ } else {
++ set_need_resched();
++ }
++
++ ppc64_runlatch_on();
++ schedule();
++ }
++}
++
++#ifndef CONFIG_PCI
++void __init iSeries_init_IRQ(void) { }
++#endif
++
++static int __init iseries_probe(int platform)
++{
++ return PLATFORM_ISERIES_LPAR == platform;
++}
++
++struct machdep_calls __initdata iseries_md = {
++ .setup_arch = iSeries_setup_arch,
++ .show_cpuinfo = iSeries_show_cpuinfo,
++ .init_IRQ = iSeries_init_IRQ,
++ .get_irq = iSeries_get_irq,
++ .init_early = iSeries_init_early,
++ .pcibios_fixup = iSeries_pci_final_fixup,
++ .restart = iSeries_restart,
++ .power_off = iSeries_power_off,
++ .halt = iSeries_halt,
++ .get_boot_time = iSeries_get_boot_time,
++ .set_rtc_time = iSeries_set_rtc_time,
++ .get_rtc_time = iSeries_get_rtc_time,
++ .calibrate_decr = generic_calibrate_decr,
++ .progress = iSeries_progress,
++ .probe = iseries_probe,
++ /* XXX Implement enable_pmcs for iSeries */
++};
++
++struct blob {
++ unsigned char data[PAGE_SIZE];
++ unsigned long next;
++};
++
++struct iseries_flat_dt {
++ struct boot_param_header header;
++ u64 reserve_map[2];
++ struct blob dt;
++ struct blob strings;
++};
++
++struct iseries_flat_dt iseries_dt;
++
++void dt_init(struct iseries_flat_dt *dt)
++{
++ dt->header.off_mem_rsvmap =
++ offsetof(struct iseries_flat_dt, reserve_map);
++ dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
++ dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
++ dt->header.totalsize = sizeof(struct iseries_flat_dt);
++ dt->header.dt_strings_size = sizeof(struct blob);
++
++ /* There is no notion of hardware cpu id on iSeries */
++ dt->header.boot_cpuid_phys = smp_processor_id();
++
++ dt->dt.next = (unsigned long)&dt->dt.data;
++ dt->strings.next = (unsigned long)&dt->strings.data;
++
++ dt->header.magic = OF_DT_HEADER;
++ dt->header.version = 0x10;
++ dt->header.last_comp_version = 0x10;
++
++ dt->reserve_map[0] = 0;
++ dt->reserve_map[1] = 0;
++}
++
++void dt_check_blob(struct blob *b)
++{
++ if (b->next >= (unsigned long)&b->next) {
++ DBG("Ran out of space in flat device tree blob!\n");
++ BUG();
++ }
++}
++
++void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
++{
++ *((u32*)dt->dt.next) = value;
++ dt->dt.next += sizeof(u32);
++
++ dt_check_blob(&dt->dt);
++}
++
++void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
++{
++ *((u64*)dt->dt.next) = value;
++ dt->dt.next += sizeof(u64);
++
++ dt_check_blob(&dt->dt);
++}
++
++unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
++{
++ unsigned long start = blob->next - (unsigned long)blob->data;
++
++ memcpy((char *)blob->next, data, len);
++ blob->next = _ALIGN(blob->next + len, 4);
++
++ dt_check_blob(blob);
++
++ return start;
++}
++
++void dt_start_node(struct iseries_flat_dt *dt, char *name)
++{
++ dt_push_u32(dt, OF_DT_BEGIN_NODE);
++ dt_push_bytes(&dt->dt, name, strlen(name) + 1);
++}
++
++#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
++
++void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
++{
++ unsigned long offset;
++
++ dt_push_u32(dt, OF_DT_PROP);
++
++ /* Length of the data */
++ dt_push_u32(dt, len);
++
++ /* Put the property name in the string blob. */
++ offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
++
++ /* The offset of the properties name in the string blob. */
++ dt_push_u32(dt, (u32)offset);
++
++ /* The actual data. */
++ dt_push_bytes(&dt->dt, data, len);
++}
++
++void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
++{
++ dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
++}
++
++void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
++{
++ dt_prop(dt, name, (char *)&data, sizeof(u32));
++}
++
++void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
++{
++ dt_prop(dt, name, (char *)&data, sizeof(u64));
++}
++
++void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
++{
++ dt_prop(dt, name, (char *)data, sizeof(u64) * n);
++}
++
++void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
++{
++ dt_prop(dt, name, NULL, 0);
++}
++
++void dt_cpus(struct iseries_flat_dt *dt)
++{
++ unsigned char buf[32];
++ unsigned char *p;
++ unsigned int i, index;
++ struct IoHriProcessorVpd *d;
++
++ /* yuck */
++ snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
++ p = strchr(buf, ' ');
++ if (!p) p = buf + strlen(buf);
++
++ dt_start_node(dt, "cpus");
++ dt_prop_u32(dt, "#address-cells", 1);
++ dt_prop_u32(dt, "#size-cells", 0);
++
++ for (i = 0; i < NR_CPUS; i++) {
++ if (paca[i].lppaca.dyn_proc_status >= 2)
++ continue;
++
++ snprintf(p, 32 - (p - buf), "@%d", i);
++ dt_start_node(dt, buf);
++
++ dt_prop_str(dt, "device_type", "cpu");
++
++ index = paca[i].lppaca.dyn_hv_phys_proc_index;
++ d = &xIoHriProcessorVpd[index];
++
++ dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
++ dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
++
++ dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
++ dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
++
++ /* magic conversions to Hz copied from old code */
++ dt_prop_u32(dt, "clock-frequency",
++ ((1UL << 34) * 1000000) / d->xProcFreq);
++ dt_prop_u32(dt, "timebase-frequency",
++ ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
++
++ dt_prop_u32(dt, "reg", i);
++
++ dt_end_node(dt);
++ }
++
++ dt_end_node(dt);
++}
++
++void build_flat_dt(struct iseries_flat_dt *dt)
++{
++ u64 tmp[2];
++
++ dt_init(dt);
++
++ dt_start_node(dt, "");
++
++ dt_prop_u32(dt, "#address-cells", 2);
++ dt_prop_u32(dt, "#size-cells", 2);
++
++ /* /memory */
++ dt_start_node(dt, "memory at 0");
++ dt_prop_str(dt, "name", "memory");
++ dt_prop_str(dt, "device_type", "memory");
++ tmp[0] = 0;
++ tmp[1] = systemcfg->physicalMemorySize;
++ dt_prop_u64_list(dt, "reg", tmp, 2);
++ dt_end_node(dt);
++
++ /* /chosen */
++ dt_start_node(dt, "chosen");
++ dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
++ dt_end_node(dt);
++
++ dt_cpus(dt);
++
++ dt_end_node(dt);
++
++ dt_push_u32(dt, OF_DT_END);
++}
++
++void * __init iSeries_early_setup(void)
++{
++ iSeries_fixup_klimit();
++
++ /*
++ * Initialize the table which translate Linux physical addresses to
++ * AS/400 absolute addresses
++ */
++ build_iSeries_Memory_Map();
++
++ build_flat_dt(&iseries_dt);
++
++ return (void *) __pa(&iseries_dt);
++}
+diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/setup.h
+@@ -0,0 +1,24 @@
++/*
++ * Copyright (c) 2000 Mike Corrigan <mikejc at us.ibm.com>
++ * Copyright (c) 1999-2000 Grant Erickson <grant at lcse.umn.edu>
++ *
++ * Description:
++ * Architecture- / platform-specific boot-time initialization code for
++ * the IBM AS/400 LPAR. Adapted from original code by Grant Erickson and
++ * code by Gary Thomas, Cort Dougan <cort at cs.nmt.edu>, and Dan Malek
++ * <dan at netx4.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 __ISERIES_SETUP_H__
++#define __ISERIES_SETUP_H__
++
++extern unsigned long iSeries_get_boot_time(void);
++extern int iSeries_set_rtc_time(struct rtc_time *tm);
++extern void iSeries_get_rtc_time(struct rtc_time *tm);
++
++#endif /* __ISERIES_SETUP_H__ */
+diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/smp.c
+@@ -0,0 +1,121 @@
++/*
++ * SMP support for iSeries machines.
++ *
++ * Dave Engebretsen, Peter Bergner, and
++ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
++ *
++ * Plus various changes from other IBM teams...
++ *
++ * 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.
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/cache.h>
++#include <linux/err.h>
++#include <linux/sysdev.h>
++#include <linux/cpu.h>
++
++#include <asm/ptrace.h>
++#include <asm/atomic.h>
++#include <asm/irq.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/paca.h>
++#include <asm/iSeries/HvCall.h>
++#include <asm/time.h>
++#include <asm/ppcdebug.h>
++#include <asm/machdep.h>
++#include <asm/cputable.h>
++#include <asm/system.h>
++
++static unsigned long iSeries_smp_message[NR_CPUS];
++
++void iSeries_smp_message_recv(struct pt_regs *regs)
++{
++ int cpu = smp_processor_id();
++ int msg;
++
++ if (num_online_cpus() < 2)
++ return;
++
++ for (msg = 0; msg < 4; msg++)
++ if (test_and_clear_bit(msg, &iSeries_smp_message[cpu]))
++ smp_message_recv(msg, regs);
++}
++
++static inline void smp_iSeries_do_message(int cpu, int msg)
++{
++ set_bit(msg, &iSeries_smp_message[cpu]);
++ HvCall_sendIPI(&(paca[cpu]));
++}
++
++static void smp_iSeries_message_pass(int target, int msg)
++{
++ int i;
++
++ if (target < NR_CPUS)
++ smp_iSeries_do_message(target, msg);
++ else {
++ for_each_online_cpu(i) {
++ if ((target == MSG_ALL_BUT_SELF) &&
++ (i == smp_processor_id()))
++ continue;
++ smp_iSeries_do_message(i, msg);
++ }
++ }
++}
++
++static int smp_iSeries_probe(void)
++{
++ return cpus_weight(cpu_possible_map);
++}
++
++static void smp_iSeries_kick_cpu(int nr)
++{
++ BUG_ON((nr < 0) || (nr >= NR_CPUS));
++
++ /* Verify that our partition has a processor nr */
++ if (paca[nr].lppaca.dyn_proc_status >= 2)
++ return;
++
++ /* The processor is currently spinning, waiting
++ * for the cpu_start field to become non-zero
++ * After we set cpu_start, the processor will
++ * continue on to secondary_start in iSeries_head.S
++ */
++ paca[nr].cpu_start = 1;
++}
++
++static void __devinit smp_iSeries_setup_cpu(int nr)
++{
++}
++
++static struct smp_ops_t iSeries_smp_ops = {
++ .message_pass = smp_iSeries_message_pass,
++ .probe = smp_iSeries_probe,
++ .kick_cpu = smp_iSeries_kick_cpu,
++ .setup_cpu = smp_iSeries_setup_cpu,
++};
++
++/* This is called very early. */
++void __init smp_init_iSeries(void)
++{
++ smp_ops = &iSeries_smp_ops;
++}
+diff --git a/arch/powerpc/platforms/iseries/spcomm_area.h b/arch/powerpc/platforms/iseries/spcomm_area.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/spcomm_area.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _ISERIES_SPCOMM_AREA_H
++#define _ISERIES_SPCOMM_AREA_H
++
++
++struct SpCommArea {
++ u32 xDesc; // Descriptor (only in new formats) 000-003
++ u8 xFormat; // Format (only in new formats) 004-004
++ u8 xRsvd1[11]; // Reserved 005-00F
++ u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017
++ u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F
++ u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027
++ u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F
++ u8 xRsvd2[80]; // Reserved 030-07F
++};
++
++extern struct SpCommArea xSpCommArea;
++
++#endif /* _ISERIES_SPCOMM_AREA_H */
+diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/vio.c
+@@ -0,0 +1,156 @@
++/*
++ * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
++ *
++ * Copyright (c) 2005 Stephen Rothwell, IBM Corp.
++ *
++ * 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/device.h>
++#include <linux/init.h>
++
++#include <asm/vio.h>
++#include <asm/iommu.h>
++#include <asm/tce.h>
++#include <asm/abs_addr.h>
++#include <asm/page.h>
++#include <asm/iSeries/vio.h>
++#include <asm/iSeries/HvTypes.h>
++#include <asm/iSeries/HvLpConfig.h>
++#include <asm/iSeries/HvCallXm.h>
++
++struct device *iSeries_vio_dev = &vio_bus_device.dev;
++EXPORT_SYMBOL(iSeries_vio_dev);
++
++static struct iommu_table veth_iommu_table;
++static struct iommu_table vio_iommu_table;
++
++static void __init iommu_vio_init(void)
++{
++ struct iommu_table *t;
++ struct iommu_table_cb cb;
++ unsigned long cbp;
++ unsigned long itc_entries;
++
++ cb.itc_busno = 255; /* Bus 255 is the virtual bus */
++ cb.itc_virtbus = 0xff; /* Ask for virtual bus */
++
++ cbp = virt_to_abs(&cb);
++ HvCallXm_getTceTableParms(cbp);
++
++ itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
++ veth_iommu_table.it_size = itc_entries / 2;
++ veth_iommu_table.it_busno = cb.itc_busno;
++ veth_iommu_table.it_offset = cb.itc_offset;
++ veth_iommu_table.it_index = cb.itc_index;
++ veth_iommu_table.it_type = TCE_VB;
++ veth_iommu_table.it_blocksize = 1;
++
++ t = iommu_init_table(&veth_iommu_table);
++
++ if (!t)
++ printk("Virtual Bus VETH TCE table failed.\n");
++
++ vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
++ vio_iommu_table.it_busno = cb.itc_busno;
++ vio_iommu_table.it_offset = cb.itc_offset +
++ veth_iommu_table.it_size;
++ vio_iommu_table.it_index = cb.itc_index;
++ vio_iommu_table.it_type = TCE_VB;
++ vio_iommu_table.it_blocksize = 1;
++
++ t = iommu_init_table(&vio_iommu_table);
++
++ if (!t)
++ printk("Virtual Bus VIO TCE table failed.\n");
++}
++
++/**
++ * vio_register_device_iseries: - Register a new iSeries vio device.
++ * @voidev: The device to register.
++ */
++static struct vio_dev *__init vio_register_device_iseries(char *type,
++ uint32_t unit_num)
++{
++ struct vio_dev *viodev;
++
++ /* allocate a vio_dev for this device */
++ viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
++ if (!viodev)
++ return NULL;
++ memset(viodev, 0, sizeof(struct vio_dev));
++
++ snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
++
++ viodev->name = viodev->dev.bus_id;
++ viodev->type = type;
++ viodev->unit_address = unit_num;
++ viodev->iommu_table = &vio_iommu_table;
++ if (vio_register_device(viodev) == NULL) {
++ kfree(viodev);
++ return NULL;
++ }
++ return viodev;
++}
++
++void __init probe_bus_iseries(void)
++{
++ HvLpIndexMap vlan_map;
++ struct vio_dev *viodev;
++ int i;
++
++ /* there is only one of each of these */
++ vio_register_device_iseries("viocons", 0);
++ vio_register_device_iseries("vscsi", 0);
++
++ vlan_map = HvLpConfig_getVirtualLanIndexMap();
++ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
++ if ((vlan_map & (0x8000 >> i)) == 0)
++ continue;
++ viodev = vio_register_device_iseries("vlan", i);
++ /* veth is special and has it own iommu_table */
++ viodev->iommu_table = &veth_iommu_table;
++ }
++ for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
++ vio_register_device_iseries("viodasd", i);
++ for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
++ vio_register_device_iseries("viocd", i);
++ for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
++ vio_register_device_iseries("viotape", i);
++}
++
++/**
++ * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
++ * vio_device_id
++ */
++static int vio_match_device_iseries(const struct vio_device_id *id,
++ const struct vio_dev *dev)
++{
++ return strncmp(dev->type, id->type, strlen(id->type)) == 0;
++}
++
++static struct vio_bus_ops vio_bus_ops_iseries = {
++ .match = vio_match_device_iseries,
++};
++
++/**
++ * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
++ */
++static int __init vio_bus_init_iseries(void)
++{
++ int err;
++
++ err = vio_bus_init(&vio_bus_ops_iseries);
++ if (err == 0) {
++ iommu_vio_init();
++ vio_bus_device.iommu_table = &vio_iommu_table;
++ iSeries_vio_dev = &vio_bus_device.dev;
++ probe_bus_iseries();
++ }
++ return err;
++}
++
++__initcall(vio_bus_init_iseries);
+diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/viopath.c
+@@ -0,0 +1,672 @@
++/* -*- linux-c -*-
++ *
++ * iSeries Virtual I/O Message Path code
++ *
++ * Authors: Dave Boutcher <boutcher at us.ibm.com>
++ * Ryan Arnold <ryanarn at us.ibm.com>
++ * Colin Devilbiss <devilbis at us.ibm.com>
++ *
++ * (C) Copyright 2000-2005 IBM Corporation
++ *
++ * This code is used by the iSeries virtual disk, cd,
++ * tape, and console to communicate with OS/400 in another
++ * partition.
++ *
++ * 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) anyu 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/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/vmalloc.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <linux/dma-mapping.h>
++#include <linux/wait.h>
++#include <linux/seq_file.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/iSeries/HvTypes.h>
++#include <asm/iSeries/ItExtVpdPanel.h>
++#include <asm/iSeries/HvLpEvent.h>
++#include <asm/iSeries/HvLpConfig.h>
++#include <asm/iSeries/mf.h>
++#include <asm/iSeries/vio.h>
++
++/* Status of the path to each other partition in the system.
++ * This is overkill, since we will only ever establish connections
++ * to our hosting partition and the primary partition on the system.
++ * But this allows for other support in the future.
++ */
++static struct viopathStatus {
++ int isOpen; /* Did we open the path? */
++ int isActive; /* Do we have a mon msg outstanding */
++ int users[VIO_MAX_SUBTYPES];
++ HvLpInstanceId mSourceInst;
++ HvLpInstanceId mTargetInst;
++ int numberAllocated;
++} viopathStatus[HVMAXARCHITECTEDLPS];
++
++static DEFINE_SPINLOCK(statuslock);
++
++/*
++ * For each kind of event we allocate a buffer that is
++ * guaranteed not to cross a page boundary
++ */
++static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] __page_aligned;
++static atomic_t event_buffer_available[VIO_MAX_SUBTYPES];
++static int event_buffer_initialised;
++
++static void handleMonitorEvent(struct HvLpEvent *event);
++
++/*
++ * We use this structure to handle asynchronous responses. The caller
++ * blocks on the semaphore and the handler posts the semaphore. However,
++ * if system_state is not SYSTEM_RUNNING, then wait_atomic is used ...
++ */
++struct alloc_parms {
++ struct semaphore sem;
++ int number;
++ atomic_t wait_atomic;
++ int used_wait_atomic;
++};
++
++/* Put a sequence number in each mon msg. The value is not
++ * important. Start at something other than 0 just for
++ * readability. wrapping this is ok.
++ */
++static u8 viomonseq = 22;
++
++/* Our hosting logical partition. We get this at startup
++ * time, and different modules access this variable directly.
++ */
++HvLpIndex viopath_hostLp = HvLpIndexInvalid;
++EXPORT_SYMBOL(viopath_hostLp);
++HvLpIndex viopath_ourLp = HvLpIndexInvalid;
++EXPORT_SYMBOL(viopath_ourLp);
++
++/* For each kind of incoming event we set a pointer to a
++ * routine to call.
++ */
++static vio_event_handler_t *vio_handler[VIO_MAX_SUBTYPES];
++
++#define VIOPATH_KERN_WARN KERN_WARNING "viopath: "
++#define VIOPATH_KERN_INFO KERN_INFO "viopath: "
++
++static int proc_viopath_show(struct seq_file *m, void *v)
++{
++ char *buf;
++ u16 vlanMap;
++ dma_addr_t handle;
++ HvLpEvent_Rc hvrc;
++ DECLARE_MUTEX_LOCKED(Semaphore);
++
++ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (!buf)
++ return 0;
++ memset(buf, 0, PAGE_SIZE);
++
++ handle = dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE,
++ DMA_FROM_DEVICE);
++
++ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
++ HvLpEvent_Type_VirtualIo,
++ viomajorsubtype_config | vioconfigget,
++ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
++ viopath_sourceinst(viopath_hostLp),
++ viopath_targetinst(viopath_hostLp),
++ (u64)(unsigned long)&Semaphore, VIOVERSION << 16,
++ ((u64)handle) << 32, PAGE_SIZE, 0, 0);
++
++ if (hvrc != HvLpEvent_Rc_Good)
++ printk(VIOPATH_KERN_WARN "hv error on op %d\n", (int)hvrc);
++
++ down(&Semaphore);
++
++ vlanMap = HvLpConfig_getVirtualLanIndexMap();
++
++ buf[PAGE_SIZE-1] = '\0';
++ seq_printf(m, "%s", buf);
++ seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap);
++ seq_printf(m, "SRLNBR=%c%c%c%c%c%c%c\n",
++ e2a(xItExtVpdPanel.mfgID[2]),
++ e2a(xItExtVpdPanel.mfgID[3]),
++ e2a(xItExtVpdPanel.systemSerial[1]),
++ e2a(xItExtVpdPanel.systemSerial[2]),
++ e2a(xItExtVpdPanel.systemSerial[3]),
++ e2a(xItExtVpdPanel.systemSerial[4]),
++ e2a(xItExtVpdPanel.systemSerial[5]));
++
++ dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE);
++ kfree(buf);
++
++ return 0;
++}
++
++static int proc_viopath_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, proc_viopath_show, NULL);
++}
++
++static struct file_operations proc_viopath_operations = {
++ .open = proc_viopath_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init vio_proc_init(void)
++{
++ struct proc_dir_entry *e;
++
++ e = create_proc_entry("iSeries/config", 0, NULL);
++ if (e)
++ e->proc_fops = &proc_viopath_operations;
++
++ return 0;
++}
++__initcall(vio_proc_init);
++
++/* See if a given LP is active. Allow for invalid lps to be passed in
++ * and just return invalid
++ */
++int viopath_isactive(HvLpIndex lp)
++{
++ if (lp == HvLpIndexInvalid)
++ return 0;
++ if (lp < HVMAXARCHITECTEDLPS)
++ return viopathStatus[lp].isActive;
++ else
++ return 0;
++}
++EXPORT_SYMBOL(viopath_isactive);
++
++/*
++ * We cache the source and target instance ids for each
++ * partition.
++ */
++HvLpInstanceId viopath_sourceinst(HvLpIndex lp)
++{
++ return viopathStatus[lp].mSourceInst;
++}
++EXPORT_SYMBOL(viopath_sourceinst);
++
++HvLpInstanceId viopath_targetinst(HvLpIndex lp)
++{
++ return viopathStatus[lp].mTargetInst;
++}
++EXPORT_SYMBOL(viopath_targetinst);
++
++/*
++ * Send a monitor message. This is a message with the acknowledge
++ * bit on that the other side will NOT explicitly acknowledge. When
++ * the other side goes down, the hypervisor will acknowledge any
++ * outstanding messages....so we will know when the other side dies.
++ */
++static void sendMonMsg(HvLpIndex remoteLp)
++{
++ HvLpEvent_Rc hvrc;
++
++ viopathStatus[remoteLp].mSourceInst =
++ HvCallEvent_getSourceLpInstanceId(remoteLp,
++ HvLpEvent_Type_VirtualIo);
++ viopathStatus[remoteLp].mTargetInst =
++ HvCallEvent_getTargetLpInstanceId(remoteLp,
++ HvLpEvent_Type_VirtualIo);
++
++ /*
++ * Deliberately ignore the return code here. if we call this
++ * more than once, we don't care.
++ */
++ vio_setHandler(viomajorsubtype_monitor, handleMonitorEvent);
++
++ hvrc = HvCallEvent_signalLpEventFast(remoteLp, HvLpEvent_Type_VirtualIo,
++ viomajorsubtype_monitor, HvLpEvent_AckInd_DoAck,
++ HvLpEvent_AckType_DeferredAck,
++ viopathStatus[remoteLp].mSourceInst,
++ viopathStatus[remoteLp].mTargetInst,
++ viomonseq++, 0, 0, 0, 0, 0);
++
++ if (hvrc == HvLpEvent_Rc_Good)
++ viopathStatus[remoteLp].isActive = 1;
++ else {
++ printk(VIOPATH_KERN_WARN "could not connect to partition %d\n",
++ remoteLp);
++ viopathStatus[remoteLp].isActive = 0;
++ }
++}
++
++static void handleMonitorEvent(struct HvLpEvent *event)
++{
++ HvLpIndex remoteLp;
++ int i;
++
++ /*
++ * This handler is _also_ called as part of the loop
++ * at the end of this routine, so it must be able to
++ * ignore NULL events...
++ */
++ if (!event)
++ return;
++
++ /*
++ * First see if this is just a normal monitor message from the
++ * other partition
++ */
++ if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
++ remoteLp = event->xSourceLp;
++ if (!viopathStatus[remoteLp].isActive)
++ sendMonMsg(remoteLp);
++ return;
++ }
++
++ /*
++ * This path is for an acknowledgement; the other partition
++ * died
++ */
++ remoteLp = event->xTargetLp;
++ if ((event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst) ||
++ (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst)) {
++ printk(VIOPATH_KERN_WARN "ignoring ack....mismatched instances\n");
++ return;
++ }
++
++ printk(VIOPATH_KERN_WARN "partition %d ended\n", remoteLp);
++
++ viopathStatus[remoteLp].isActive = 0;
++
++ /*
++ * For each active handler, pass them a NULL
++ * message to indicate that the other partition
++ * died
++ */
++ for (i = 0; i < VIO_MAX_SUBTYPES; i++) {
++ if (vio_handler[i] != NULL)
++ (*vio_handler[i])(NULL);
++ }
++}
++
++int vio_setHandler(int subtype, vio_event_handler_t *beh)
++{
++ subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
++ if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
++ return -EINVAL;
++ if (vio_handler[subtype] != NULL)
++ return -EBUSY;
++ vio_handler[subtype] = beh;
++ return 0;
++}
++EXPORT_SYMBOL(vio_setHandler);
++
++int vio_clearHandler(int subtype)
++{
++ subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
++ if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
++ return -EINVAL;
++ if (vio_handler[subtype] == NULL)
++ return -EAGAIN;
++ vio_handler[subtype] = NULL;
++ return 0;
++}
++EXPORT_SYMBOL(vio_clearHandler);
++
++static void handleConfig(struct HvLpEvent *event)
++{
++ if (!event)
++ return;
++ if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
++ printk(VIOPATH_KERN_WARN
++ "unexpected config request from partition %d",
++ event->xSourceLp);
++
++ if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
++ (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
++ event->xRc = HvLpEvent_Rc_InvalidSubtype;
++ HvCallEvent_ackLpEvent(event);
++ }
++ return;
++ }
++
++ up((struct semaphore *)event->xCorrelationToken);
++}
++
++/*
++ * Initialization of the hosting partition
++ */
++void vio_set_hostlp(void)
++{
++ /*
++ * If this has already been set then we DON'T want to either change
++ * it or re-register the proc file system
++ */
++ if (viopath_hostLp != HvLpIndexInvalid)
++ return;
++
++ /*
++ * Figure out our hosting partition. This isn't allowed to change
++ * while we're active
++ */
++ viopath_ourLp = HvLpConfig_getLpIndex();
++ viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);
++
++ if (viopath_hostLp != HvLpIndexInvalid)
++ vio_setHandler(viomajorsubtype_config, handleConfig);
++}
++EXPORT_SYMBOL(vio_set_hostlp);
++
++static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
++{
++ HvLpIndex remoteLp;
++ int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK)
++ >> VIOMAJOR_SUBTYPE_SHIFT;
++
++ if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
++ remoteLp = event->xSourceLp;
++ /*
++ * The isActive is checked because if the hosting partition
++ * went down and came back up it would not be active but it
++ * would have different source and target instances, in which
++ * case we'd want to reset them. This case really protects
++ * against an unauthorized active partition sending interrupts
++ * or acks to this linux partition.
++ */
++ if (viopathStatus[remoteLp].isActive
++ && (event->xSourceInstanceId !=
++ viopathStatus[remoteLp].mTargetInst)) {
++ printk(VIOPATH_KERN_WARN
++ "message from invalid partition. "
++ "int msg rcvd, source inst (%d) doesnt match (%d)\n",
++ viopathStatus[remoteLp].mTargetInst,
++ event->xSourceInstanceId);
++ return;
++ }
++
++ if (viopathStatus[remoteLp].isActive
++ && (event->xTargetInstanceId !=
++ viopathStatus[remoteLp].mSourceInst)) {
++ printk(VIOPATH_KERN_WARN
++ "message from invalid partition. "
++ "int msg rcvd, target inst (%d) doesnt match (%d)\n",
++ viopathStatus[remoteLp].mSourceInst,
++ event->xTargetInstanceId);
++ return;
++ }
++ } else {
++ remoteLp = event->xTargetLp;
++ if (event->xSourceInstanceId !=
++ viopathStatus[remoteLp].mSourceInst) {
++ printk(VIOPATH_KERN_WARN
++ "message from invalid partition. "
++ "ack msg rcvd, source inst (%d) doesnt match (%d)\n",
++ viopathStatus[remoteLp].mSourceInst,
++ event->xSourceInstanceId);
++ return;
++ }
++
++ if (event->xTargetInstanceId !=
++ viopathStatus[remoteLp].mTargetInst) {
++ printk(VIOPATH_KERN_WARN
++ "message from invalid partition. "
++ "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n",
++ viopathStatus[remoteLp].mTargetInst,
++ event->xTargetInstanceId);
++ return;
++ }
++ }
++
++ if (vio_handler[subtype] == NULL) {
++ printk(VIOPATH_KERN_WARN
++ "unexpected virtual io event subtype %d from partition %d\n",
++ event->xSubtype, remoteLp);
++ /* No handler. Ack if necessary */
++ if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
++ (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
++ event->xRc = HvLpEvent_Rc_InvalidSubtype;
++ HvCallEvent_ackLpEvent(event);
++ }
++ return;
++ }
++
++ /* This innocuous little line is where all the real work happens */
++ (*vio_handler[subtype])(event);
++}
++
++static void viopath_donealloc(void *parm, int number)
++{
++ struct alloc_parms *parmsp = parm;
++
++ parmsp->number = number;
++ if (parmsp->used_wait_atomic)
++ atomic_set(&parmsp->wait_atomic, 0);
++ else
++ up(&parmsp->sem);
++}
++
++static int allocateEvents(HvLpIndex remoteLp, int numEvents)
++{
++ struct alloc_parms parms;
++
++ if (system_state != SYSTEM_RUNNING) {
++ parms.used_wait_atomic = 1;
++ atomic_set(&parms.wait_atomic, 1);
++ } else {
++ parms.used_wait_atomic = 0;
++ init_MUTEX_LOCKED(&parms.sem);
++ }
++ mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */
++ numEvents, &viopath_donealloc, &parms);
++ if (system_state != SYSTEM_RUNNING) {
++ while (atomic_read(&parms.wait_atomic))
++ mb();
++ } else
++ down(&parms.sem);
++ return parms.number;
++}
++
++int viopath_open(HvLpIndex remoteLp, int subtype, int numReq)
++{
++ int i;
++ unsigned long flags;
++ int tempNumAllocated;
++
++ if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
++ return -EINVAL;
++
++ subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
++ if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
++ return -EINVAL;
++
++ spin_lock_irqsave(&statuslock, flags);
++
++ if (!event_buffer_initialised) {
++ for (i = 0; i < VIO_MAX_SUBTYPES; i++)
++ atomic_set(&event_buffer_available[i], 1);
++ event_buffer_initialised = 1;
++ }
++
++ viopathStatus[remoteLp].users[subtype]++;
++
++ if (!viopathStatus[remoteLp].isOpen) {
++ viopathStatus[remoteLp].isOpen = 1;
++ HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo);
++
++ /*
++ * Don't hold the spinlock during an operation that
++ * can sleep.
++ */
++ spin_unlock_irqrestore(&statuslock, flags);
++ tempNumAllocated = allocateEvents(remoteLp, 1);
++ spin_lock_irqsave(&statuslock, flags);
++
++ viopathStatus[remoteLp].numberAllocated += tempNumAllocated;
++
++ if (viopathStatus[remoteLp].numberAllocated == 0) {
++ HvCallEvent_closeLpEventPath(remoteLp,
++ HvLpEvent_Type_VirtualIo);
++
++ spin_unlock_irqrestore(&statuslock, flags);
++ return -ENOMEM;
++ }
++
++ viopathStatus[remoteLp].mSourceInst =
++ HvCallEvent_getSourceLpInstanceId(remoteLp,
++ HvLpEvent_Type_VirtualIo);
++ viopathStatus[remoteLp].mTargetInst =
++ HvCallEvent_getTargetLpInstanceId(remoteLp,
++ HvLpEvent_Type_VirtualIo);
++ HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo,
++ &vio_handleEvent);
++ sendMonMsg(remoteLp);
++ printk(VIOPATH_KERN_INFO "opening connection to partition %d, "
++ "setting sinst %d, tinst %d\n",
++ remoteLp, viopathStatus[remoteLp].mSourceInst,
++ viopathStatus[remoteLp].mTargetInst);
++ }
++
++ spin_unlock_irqrestore(&statuslock, flags);
++ tempNumAllocated = allocateEvents(remoteLp, numReq);
++ spin_lock_irqsave(&statuslock, flags);
++ viopathStatus[remoteLp].numberAllocated += tempNumAllocated;
++ spin_unlock_irqrestore(&statuslock, flags);
++
++ return 0;
++}
++EXPORT_SYMBOL(viopath_open);
++
++int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
++{
++ unsigned long flags;
++ int i;
++ int numOpen;
++ struct alloc_parms parms;
++
++ if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
++ return -EINVAL;
++
++ subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
++ if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
++ return -EINVAL;
++
++ spin_lock_irqsave(&statuslock, flags);
++ /*
++ * If the viopath_close somehow gets called before a
++ * viopath_open it could decrement to -1 which is a non
++ * recoverable state so we'll prevent this from
++ * happening.
++ */
++ if (viopathStatus[remoteLp].users[subtype] > 0)
++ viopathStatus[remoteLp].users[subtype]--;
++
++ spin_unlock_irqrestore(&statuslock, flags);
++
++ parms.used_wait_atomic = 0;
++ init_MUTEX_LOCKED(&parms.sem);
++ mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo,
++ numReq, &viopath_donealloc, &parms);
++ down(&parms.sem);
++
++ spin_lock_irqsave(&statuslock, flags);
++ for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++)
++ numOpen += viopathStatus[remoteLp].users[i];
++
++ if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) {
++ printk(VIOPATH_KERN_INFO "closing connection to partition %d",
++ remoteLp);
++
++ HvCallEvent_closeLpEventPath(remoteLp,
++ HvLpEvent_Type_VirtualIo);
++ viopathStatus[remoteLp].isOpen = 0;
++ viopathStatus[remoteLp].isActive = 0;
++
++ for (i = 0; i < VIO_MAX_SUBTYPES; i++)
++ atomic_set(&event_buffer_available[i], 0);
++ event_buffer_initialised = 0;
++ }
++ spin_unlock_irqrestore(&statuslock, flags);
++ return 0;
++}
++EXPORT_SYMBOL(viopath_close);
++
++void *vio_get_event_buffer(int subtype)
++{
++ subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
++ if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
++ return NULL;
++
++ if (atomic_dec_if_positive(&event_buffer_available[subtype]) == 0)
++ return &event_buffer[subtype * 256];
++ else
++ return NULL;
++}
++EXPORT_SYMBOL(vio_get_event_buffer);
++
++void vio_free_event_buffer(int subtype, void *buffer)
++{
++ subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
++ if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) {
++ printk(VIOPATH_KERN_WARN
++ "unexpected subtype %d freeing event buffer\n", subtype);
++ return;
++ }
++
++ if (atomic_read(&event_buffer_available[subtype]) != 0) {
++ printk(VIOPATH_KERN_WARN
++ "freeing unallocated event buffer, subtype %d\n",
++ subtype);
++ return;
++ }
++
++ if (buffer != &event_buffer[subtype * 256]) {
++ printk(VIOPATH_KERN_WARN
++ "freeing invalid event buffer, subtype %d\n", subtype);
++ }
++
++ atomic_set(&event_buffer_available[subtype], 1);
++}
++EXPORT_SYMBOL(vio_free_event_buffer);
++
++static const struct vio_error_entry vio_no_error =
++ { 0, 0, "Non-VIO Error" };
++static const struct vio_error_entry vio_unknown_error =
++ { 0, EIO, "Unknown Error" };
++
++static const struct vio_error_entry vio_default_errors[] = {
++ {0x0001, EIO, "No Connection"},
++ {0x0002, EIO, "No Receiver"},
++ {0x0003, EIO, "No Buffer Available"},
++ {0x0004, EBADRQC, "Invalid Message Type"},
++ {0x0000, 0, NULL},
++};
++
++const struct vio_error_entry *vio_lookup_rc(
++ const struct vio_error_entry *local_table, u16 rc)
++{
++ const struct vio_error_entry *cur;
++
++ if (!rc)
++ return &vio_no_error;
++ if (local_table)
++ for (cur = local_table; cur->rc; ++cur)
++ if (cur->rc == rc)
++ return cur;
++ for (cur = vio_default_errors; cur->rc; ++cur)
++ if (cur->rc == rc)
++ return cur;
++ return &vio_unknown_error;
++}
++EXPORT_SYMBOL(vio_lookup_rc);
+diff --git a/arch/powerpc/platforms/iseries/vpd_areas.h b/arch/powerpc/platforms/iseries/vpd_areas.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/vpd_areas.h
+@@ -0,0 +1,88 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _ISERIES_VPD_AREAS_H
++#define _ISERIES_VPD_AREAS_H
++
++/*
++ * This file defines the address and length of all of the VPD area passed to
++ * the OS from PLIC (most of which start from the SP).
++ */
++
++#include <asm/types.h>
++
++/* VPD Entry index is carved in stone - cannot be changed (easily). */
++#define ItVpdCecVpd 0
++#define ItVpdDynamicSpace 1
++#define ItVpdExtVpd 2
++#define ItVpdExtVpdOnPanel 3
++#define ItVpdFirstPaca 4
++#define ItVpdIoVpd 5
++#define ItVpdIplParms 6
++#define ItVpdMsVpd 7
++#define ItVpdPanelVpd 8
++#define ItVpdLpNaca 9
++#define ItVpdBackplaneAndMaybeClockCardVpd 10
++#define ItVpdRecoveryLogBuffer 11
++#define ItVpdSpCommArea 12
++#define ItVpdSpLogBuffer 13
++#define ItVpdSpLogBufferSave 14
++#define ItVpdSpCardVpd 15
++#define ItVpdFirstProcVpd 16
++#define ItVpdApModelVpd 17
++#define ItVpdClockCardVpd 18
++#define ItVpdBusExtCardVpd 19
++#define ItVpdProcCapacityVpd 20
++#define ItVpdInteractiveCapacityVpd 21
++#define ItVpdFirstSlotLabel 22
++#define ItVpdFirstLpQueue 23
++#define ItVpdFirstL3CacheVpd 24
++#define ItVpdFirstProcFruVpd 25
++
++#define ItVpdMaxEntries 26
++
++#define ItDmaMaxEntries 10
++
++#define ItVpdAreasMaxSlotLabels 192
++
++
++struct ItVpdAreas {
++ u32 xSlicDesc; // Descriptor 000-003
++ u16 xSlicSize; // Size of this control block 004-005
++ u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface006-007
++ u16 xRsvd1:15; // Reserved bits ...
++ u16 xSlicVpdEntries; // Number of VPD entries 008-009
++ u16 xSlicDmaEntries; // Number of DMA entries 00A-00B
++ u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D
++ u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F
++ u16 xSlicDmaToksOffset; // Offset into this of array 010-011
++ u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013
++ u16 xSlicDmaLensOffset; // Offset into this of array 014-015
++ u16 xSlicVpdLensOffset; // Offset into this of array 016-017
++ u16 xSlicMaxSlotLabels; // Maximum number of slot labels018-019
++ u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B
++ u8 xRsvd2[4]; // Reserved 01C-01F
++ u64 xRsvd3[12]; // Reserved 020-07F
++ u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7
++ u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF
++ u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F
++ void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
++};
++
++extern struct ItVpdAreas itVpdAreas;
++
++#endif /* _ISERIES_VPD_AREAS_H */
+diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/iseries/vpdinfo.c
+@@ -0,0 +1,271 @@
++/*
++ * This code gets the card location of the hardware
++ * Copyright (C) 2001 <Allan H Trautman> <IBM Corp>
++ * Copyright (C) 2005 Stephen Rothwel, IBM Corp
++ *
++ * 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
++ *
++ * Change Activity:
++ * Created, Feb 2, 2001
++ * Ported to ppc64, August 20, 2001
++ * End Change Activity
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++
++#include <asm/types.h>
++#include <asm/resource.h>
++#include <asm/abs_addr.h>
++#include <asm/pci-bridge.h>
++#include <asm/iSeries/HvTypes.h>
++
++#include "pci.h"
++#include "call_pci.h"
++
++/*
++ * Size of Bus VPD data
++ */
++#define BUS_VPDSIZE 1024
++
++/*
++ * Bus Vpd Tags
++ */
++#define VpdEndOfAreaTag 0x79
++#define VpdIdStringTag 0x82
++#define VpdVendorAreaTag 0x84
++
++/*
++ * Mfg Area Tags
++ */
++#define VpdFruFrameId 0x4649 // "FI"
++#define VpdSlotMapFormat 0x4D46 // "MF"
++#define VpdSlotMap 0x534D // "SM"
++
++/*
++ * Structures of the areas
++ */
++struct MfgVpdAreaStruct {
++ u16 Tag;
++ u8 TagLength;
++ u8 AreaData1;
++ u8 AreaData2;
++};
++typedef struct MfgVpdAreaStruct MfgArea;
++#define MFG_ENTRY_SIZE 3
++
++struct SlotMapStruct {
++ u8 AgentId;
++ u8 SecondaryAgentId;
++ u8 PhbId;
++ char CardLocation[3];
++ char Parms[8];
++ char Reserved[2];
++};
++typedef struct SlotMapStruct SlotMap;
++#define SLOT_ENTRY_SIZE 16
++
++/*
++ * Parse the Slot Area
++ */
++static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
++ HvAgentId agent, u8 *PhbId, char card[4])
++{
++ int SlotMapLen = MapLen;
++ SlotMap *SlotMapPtr = MapPtr;
++
++ /*
++ * Parse Slot label until we find the one requested
++ */
++ while (SlotMapLen > 0) {
++ if (SlotMapPtr->AgentId == agent) {
++ /*
++ * If Phb wasn't found, grab the entry first one found.
++ */
++ if (*PhbId == 0xff)
++ *PhbId = SlotMapPtr->PhbId;
++ /* Found it, extract the data. */
++ if (SlotMapPtr->PhbId == *PhbId) {
++ memcpy(card, &SlotMapPtr->CardLocation, 3);
++ card[3] = 0;
++ break;
++ }
++ }
++ /* Point to the next Slot */
++ SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE);
++ SlotMapLen -= SLOT_ENTRY_SIZE;
++ }
++}
++
++/*
++ * Parse the Mfg Area
++ */
++static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
++ HvAgentId agent, u8 *PhbId,
++ u8 *frame, char card[4])
++{
++ MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
++ int MfgAreaLen = AreaLen;
++ u16 SlotMapFmt = 0;
++
++ /* Parse Mfg Data */
++ while (MfgAreaLen > 0) {
++ int MfgTagLen = MfgAreaPtr->TagLength;
++ /* Frame ID (FI 4649020310 ) */
++ if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */
++ *frame = MfgAreaPtr->AreaData1;
++ /* Slot Map Format (MF 4D46020004 ) */
++ else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */
++ SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
++ + MfgAreaPtr->AreaData2;
++ /* Slot Map (SM 534D90 */
++ else if (MfgAreaPtr->Tag == VpdSlotMap) { /* SM */
++ SlotMap *SlotMapPtr;
++
++ if (SlotMapFmt == 0x1004)
++ SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
++ + MFG_ENTRY_SIZE + 1);
++ else
++ SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
++ + MFG_ENTRY_SIZE);
++ iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
++ agent, PhbId, card);
++ }
++ /*
++ * Point to the next Mfg Area
++ * Use defined size, sizeof give wrong answer
++ */
++ MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
++ + MFG_ENTRY_SIZE);
++ MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
++ }
++}
++
++/*
++ * Look for "BUS".. Data is not Null terminated.
++ * PHBID of 0xFF indicates PHB was not found in VPD Data.
++ */
++static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
++{
++ u8 *PhbPtr = AreaPtr;
++ int DataLen = AreaLength;
++ char PhbId = 0xFF;
++
++ while (DataLen > 0) {
++ if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
++ && (*(PhbPtr + 2) == 'S')) {
++ PhbPtr += 3;
++ while (*PhbPtr == ' ')
++ ++PhbPtr;
++ PhbId = (*PhbPtr & 0x0F);
++ break;
++ }
++ ++PhbPtr;
++ --DataLen;
++ }
++ return PhbId;
++}
++
++/*
++ * Parse out the VPD Areas
++ */
++static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
++ HvAgentId agent, u8 *frame, char card[4])
++{
++ u8 *TagPtr = VpdData;
++ int DataLen = VpdDataLen - 3;
++ u8 PhbId;
++
++ while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
++ int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
++ u8 *AreaData = TagPtr + 3;
++
++ if (*TagPtr == VpdIdStringTag)
++ PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
++ else if (*TagPtr == VpdVendorAreaTag)
++ iSeries_Parse_MfgArea(AreaData, AreaLen,
++ agent, &PhbId, frame, card);
++ /* Point to next Area. */
++ TagPtr = AreaData + AreaLen;
++ DataLen -= AreaLen;
++ }
++}
++
++static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
++ u8 *frame, char card[4])
++{
++ int BusVpdLen = 0;
++ u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
++
++ if (BusVpdPtr == NULL) {
++ printk("PCI: Bus VPD Buffer allocation failure.\n");
++ return;
++ }
++ BusVpdLen = HvCallPci_getBusVpd(bus, iseries_hv_addr(BusVpdPtr),
++ BUS_VPDSIZE);
++ if (BusVpdLen == 0) {
++ printk("PCI: Bus VPD Buffer zero length.\n");
++ goto out_free;
++ }
++ /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
++ /* Make sure this is what I think it is */
++ if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */
++ printk("PCI: Bus VPD Buffer missing starting tag.\n");
++ goto out_free;
++ }
++ iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
++out_free:
++ kfree(BusVpdPtr);
++}
++
++/*
++ * Prints the device information.
++ * - Pass in pci_dev* pointer to the device.
++ * - Pass in the device count
++ *
++ * Format:
++ * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
++ * controller
++ */
++void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
++{
++ struct device_node *DevNode = PciDev->sysdata;
++ struct pci_dn *pdn;
++ u16 bus;
++ u8 frame;
++ char card[4];
++ HvSubBusNumber subbus;
++ HvAgentId agent;
++
++ if (DevNode == NULL) {
++ printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
++ count);
++ return;
++ }
++
++ pdn = PCI_DN(DevNode);
++ bus = pdn->busno;
++ subbus = pdn->bussubno;
++ agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
++ ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
++ iSeries_Get_Location_Code(bus, agent, &frame, card);
++
++ printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s ",
++ count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor,
++ frame, card);
++ printk("0x%04X\n", (int)(PciDev->class >> 8));
++}
+diff --git a/arch/powerpc/platforms/maple/Makefile b/arch/powerpc/platforms/maple/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/maple/Makefile
+@@ -0,0 +1 @@
++obj-y += setup.o pci.o time.o
+diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/maple/maple.h
+@@ -0,0 +1,12 @@
++/*
++ * Declarations for maple-specific code.
++ *
++ * Maple is the name of a PPC970 evaluation board.
++ */
++extern int maple_set_rtc_time(struct rtc_time *tm);
++extern void maple_get_rtc_time(struct rtc_time *tm);
++extern unsigned long maple_get_boot_time(void);
++extern void maple_calibrate_decr(void);
++extern void maple_pci_init(void);
++extern void maple_pcibios_fixup(void);
++extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
+diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/maple/pci.c
+@@ -0,0 +1,522 @@
++/*
++ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh at kernel.crashing.org),
++ * IBM Corp.
++ *
++ * 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.
++ */
++
++#define DEBUG
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++
++#include <asm/sections.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/machdep.h>
++#include <asm/iommu.h>
++#include <asm/ppc-pci.h>
++
++#include "maple.h"
++
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++static struct pci_controller *u3_agp, *u3_ht;
++
++static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
++{
++ for (; node != 0;node = node->sibling) {
++ int * bus_range;
++ unsigned int *class_code;
++ int len;
++
++ /* For PCI<->PCI bridges or CardBus bridges, we go down */
++ class_code = (unsigned int *) get_property(node, "class-code", NULL);
++ if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
++ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
++ continue;
++ bus_range = (int *) get_property(node, "bus-range", &len);
++ if (bus_range != NULL && len > 2 * sizeof(int)) {
++ if (bus_range[1] > higher)
++ higher = bus_range[1];
++ }
++ higher = fixup_one_level_bus_range(node->child, higher);
++ }
++ return higher;
++}
++
++/* This routine fixes the "bus-range" property of all bridges in the
++ * system since they tend to have their "last" member wrong on macs
++ *
++ * Note that the bus numbers manipulated here are OF bus numbers, they
++ * are not Linux bus numbers.
++ */
++static void __init fixup_bus_range(struct device_node *bridge)
++{
++ int * bus_range;
++ int len;
++
++ /* Lookup the "bus-range" property for the hose */
++ bus_range = (int *) get_property(bridge, "bus-range", &len);
++ if (bus_range == NULL || len < 2 * sizeof(int)) {
++ printk(KERN_WARNING "Can't get bus-range for %s\n",
++ bridge->full_name);
++ return;
++ }
++ bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
++}
++
++
++#define U3_AGP_CFA0(devfn, off) \
++ ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
++ | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
++ | (((unsigned long)(off)) & 0xFCUL))
++
++#define U3_AGP_CFA1(bus, devfn, off) \
++ ((((unsigned long)(bus)) << 16) \
++ |(((unsigned long)(devfn)) << 8) \
++ |(((unsigned long)(off)) & 0xFCUL) \
++ |1UL)
++
++static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
++ u8 bus, u8 dev_fn, u8 offset)
++{
++ unsigned int caddr;
++
++ if (bus == hose->first_busno) {
++ if (dev_fn < (11 << 3))
++ return 0;
++ caddr = U3_AGP_CFA0(dev_fn, offset);
++ } else
++ caddr = U3_AGP_CFA1(bus, dev_fn, offset);
++
++ /* Uninorth will return garbage if we don't read back the value ! */
++ do {
++ out_le32(hose->cfg_addr, caddr);
++ } while (in_le32(hose->cfg_addr) != caddr);
++
++ offset &= 0x07;
++ return ((unsigned long)hose->cfg_data) + offset;
++}
++
++static int u3_agp_read_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 *val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ *val = in_8((u8 *)addr);
++ break;
++ case 2:
++ *val = in_le16((u16 *)addr);
++ break;
++ default:
++ *val = in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ out_8((u8 *)addr, val);
++ (void) in_8((u8 *)addr);
++ break;
++ case 2:
++ out_le16((u16 *)addr, val);
++ (void) in_le16((u16 *)addr);
++ break;
++ default:
++ out_le32((u32 *)addr, val);
++ (void) in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops u3_agp_pci_ops =
++{
++ u3_agp_read_config,
++ u3_agp_write_config
++};
++
++
++#define U3_HT_CFA0(devfn, off) \
++ ((((unsigned long)devfn) << 8) | offset)
++#define U3_HT_CFA1(bus, devfn, off) \
++ (U3_HT_CFA0(devfn, off) \
++ + (((unsigned long)bus) << 16) \
++ + 0x01000000UL)
++
++static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
++ u8 bus, u8 devfn, u8 offset)
++{
++ if (bus == hose->first_busno) {
++ if (PCI_SLOT(devfn) == 0)
++ return 0;
++ return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
++ } else
++ return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset);
++}
++
++static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 *val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ *val = in_8((u8 *)addr);
++ break;
++ case 2:
++ *val = in_le16((u16 *)addr);
++ break;
++ default:
++ *val = in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ out_8((u8 *)addr, val);
++ (void) in_8((u8 *)addr);
++ break;
++ case 2:
++ out_le16((u16 *)addr, val);
++ (void) in_le16((u16 *)addr);
++ break;
++ default:
++ out_le32((u32 *)addr, val);
++ (void) in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops u3_ht_pci_ops =
++{
++ u3_ht_read_config,
++ u3_ht_write_config
++};
++
++static void __init setup_u3_agp(struct pci_controller* hose)
++{
++ /* On G5, we move AGP up to high bus number so we don't need
++ * to reassign bus numbers for HT. If we ever have P2P bridges
++ * on AGP, we'll have to move pci_assign_all_buses to the
++ * pci_controller structure so we enable it for AGP and not for
++ * HT childs.
++ * We hard code the address because of the different size of
++ * the reg address cell, we shall fix that by killing struct
++ * reg_property and using some accessor functions instead
++ */
++ hose->first_busno = 0xf0;
++ hose->last_busno = 0xff;
++ hose->ops = &u3_agp_pci_ops;
++ hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
++ hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
++
++ u3_agp = hose;
++}
++
++static void __init setup_u3_ht(struct pci_controller* hose)
++{
++ hose->ops = &u3_ht_pci_ops;
++
++ /* We hard code the address because of the different size of
++ * the reg address cell, we shall fix that by killing struct
++ * reg_property and using some accessor functions instead
++ */
++ hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
++
++ hose->first_busno = 0;
++ hose->last_busno = 0xef;
++
++ u3_ht = hose;
++}
++
++static int __init add_bridge(struct device_node *dev)
++{
++ int len;
++ struct pci_controller *hose;
++ char* disp_name;
++ int *bus_range;
++ int primary = 1;
++ struct property *of_prop;
++
++ DBG("Adding PCI host bridge %s\n", dev->full_name);
++
++ bus_range = (int *) get_property(dev, "bus-range", &len);
++ if (bus_range == NULL || len < 2 * sizeof(int)) {
++ printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
++ dev->full_name);
++ }
++
++ hose = alloc_bootmem(sizeof(struct pci_controller));
++ if (hose == NULL)
++ return -ENOMEM;
++ pci_setup_pci_controller(hose);
++
++ hose->arch_data = dev;
++ hose->first_busno = bus_range ? bus_range[0] : 0;
++ hose->last_busno = bus_range ? bus_range[1] : 0xff;
++
++ of_prop = alloc_bootmem(sizeof(struct property) +
++ sizeof(hose->global_number));
++ if (of_prop) {
++ memset(of_prop, 0, sizeof(struct property));
++ of_prop->name = "linux,pci-domain";
++ of_prop->length = sizeof(hose->global_number);
++ of_prop->value = (unsigned char *)&of_prop[1];
++ memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number));
++ prom_add_property(dev, of_prop);
++ }
++
++ disp_name = NULL;
++ if (device_is_compatible(dev, "u3-agp")) {
++ setup_u3_agp(hose);
++ disp_name = "U3-AGP";
++ primary = 0;
++ } else if (device_is_compatible(dev, "u3-ht")) {
++ setup_u3_ht(hose);
++ disp_name = "U3-HT";
++ primary = 1;
++ }
++ printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
++ disp_name, hose->first_busno, hose->last_busno);
++
++ /* Interpret the "ranges" property */
++ /* This also maps the I/O region and sets isa_io/mem_base */
++ pci_process_bridge_OF_ranges(hose, dev, primary);
++ pci_setup_phb_io(hose, primary);
++
++ /* Fixup "bus-range" OF property */
++ fixup_bus_range(dev);
++
++ return 0;
++}
++
++
++void __init maple_pcibios_fixup(void)
++{
++ struct pci_dev *dev = NULL;
++
++ DBG(" -> maple_pcibios_fixup\n");
++
++ for_each_pci_dev(dev)
++ pci_read_irq_line(dev);
++
++ /* Do the mapping of the IO space */
++ phbs_remap_io();
++
++ DBG(" <- maple_pcibios_fixup\n");
++}
++
++static void __init maple_fixup_phb_resources(void)
++{
++ struct pci_controller *hose, *tmp;
++
++ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
++ unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
++ hose->io_resource.start += offset;
++ hose->io_resource.end += offset;
++ printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
++ hose->global_number,
++ hose->io_resource.start, hose->io_resource.end);
++ }
++}
++
++void __init maple_pci_init(void)
++{
++ struct device_node *np, *root;
++ struct device_node *ht = NULL;
++
++ /* Probe root PCI hosts, that is on U3 the AGP host and the
++ * HyperTransport host. That one is actually "kept" around
++ * and actually added last as it's resource management relies
++ * on the AGP resources to have been setup first
++ */
++ root = of_find_node_by_path("/");
++ if (root == NULL) {
++ printk(KERN_CRIT "maple_find_bridges: can't find root of device tree\n");
++ return;
++ }
++ for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
++ if (np->name == NULL)
++ continue;
++ if (strcmp(np->name, "pci") == 0) {
++ if (add_bridge(np) == 0)
++ of_node_get(np);
++ }
++ if (strcmp(np->name, "ht") == 0) {
++ of_node_get(np);
++ ht = np;
++ }
++ }
++ of_node_put(root);
++
++ /* Now setup the HyperTransport host if we found any
++ */
++ if (ht && add_bridge(ht) != 0)
++ of_node_put(ht);
++
++ /* Fixup the IO resources on our host bridges as the common code
++ * does it only for childs of the host bridges
++ */
++ maple_fixup_phb_resources();
++
++ /* Setup the linkage between OF nodes and PHBs */
++ pci_devs_phb_init();
++
++ /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
++ * assume there is no P2P bridge on the AGP bus, which should be a
++ * safe assumptions hopefully.
++ */
++ if (u3_agp) {
++ struct device_node *np = u3_agp->arch_data;
++ PCI_DN(np)->busno = 0xf0;
++ for (np = np->child; np; np = np->sibling)
++ PCI_DN(np)->busno = 0xf0;
++ }
++
++ /* Tell pci.c to use the common resource allocation mecanism */
++ pci_probe_only = 0;
++
++ /* Allow all IO */
++ io_page_mask = -1;
++}
++
++int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
++{
++ struct device_node *np;
++ int irq = channel ? 15 : 14;
++
++ if (pdev->vendor != PCI_VENDOR_ID_AMD ||
++ pdev->device != PCI_DEVICE_ID_AMD_8111_IDE)
++ return irq;
++
++ np = pci_device_to_OF_node(pdev);
++ if (np == NULL)
++ return irq;
++ if (np->n_intrs < 2)
++ return irq;
++ return np->intrs[channel & 0x1].line;
++}
++
++/* XXX: To remove once all firmwares are ok */
++static void fixup_maple_ide(struct pci_dev* dev)
++{
++#if 0 /* Enable this to enable IDE port 0 */
++ {
++ u8 v;
++
++ pci_read_config_byte(dev, 0x40, &v);
++ v |= 2;
++ pci_write_config_byte(dev, 0x40, v);
++ }
++#endif
++#if 0 /* fix bus master base */
++ pci_write_config_dword(dev, 0x20, 0xcc01);
++ printk("old ide resource: %lx -> %lx \n",
++ dev->resource[4].start, dev->resource[4].end);
++ dev->resource[4].start = 0xcc00;
++ dev->resource[4].end = 0xcc10;
++#endif
++#if 1 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
++ {
++ struct pci_dev *apicdev;
++ u32 v;
++
++ apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
++ if (apicdev == NULL)
++ printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
++ else {
++ pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
++ pci_read_config_dword(apicdev, 0xf4, &v);
++ v &= ~0x00000022;
++ pci_write_config_dword(apicdev, 0xf4, v);
++ pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
++ pci_read_config_dword(apicdev, 0xf4, &v);
++ v &= ~0x00000022;
++ pci_write_config_dword(apicdev, 0xf4, v);
++ pci_dev_put(apicdev);
++ }
++ }
++#endif
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
++ fixup_maple_ide);
+diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/maple/setup.c
+@@ -0,0 +1,295 @@
++/*
++ * Maple (970 eval board) setup code
++ *
++ * (c) Copyright 2004 Benjamin Herrenschmidt (benh at kernel.crashing.org),
++ * IBM Corp.
++ *
++ * 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.
++ *
++ */
++
++#define DEBUG
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/tty.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/major.h>
++#include <linux/initrd.h>
++#include <linux/vt_kern.h>
++#include <linux/console.h>
++#include <linux/ide.h>
++#include <linux/pci.h>
++#include <linux/adb.h>
++#include <linux/cuda.h>
++#include <linux/pmu.h>
++#include <linux/irq.h>
++#include <linux/seq_file.h>
++#include <linux/root_dev.h>
++#include <linux/serial.h>
++#include <linux/smp.h>
++
++#include <asm/processor.h>
++#include <asm/sections.h>
++#include <asm/prom.h>
++#include <asm/system.h>
++#include <asm/pgtable.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <asm/pci-bridge.h>
++#include <asm/iommu.h>
++#include <asm/machdep.h>
++#include <asm/dma.h>
++#include <asm/cputable.h>
++#include <asm/time.h>
++#include <asm/of_device.h>
++#include <asm/lmb.h>
++#include <asm/mpic.h>
++#include <asm/udbg.h>
++
++#include "maple.h"
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++extern void generic_find_legacy_serial_ports(u64 *physport,
++ unsigned int *default_speed);
++
++static void maple_restart(char *cmd)
++{
++ unsigned int maple_nvram_base;
++ unsigned int maple_nvram_offset;
++ unsigned int maple_nvram_command;
++ struct device_node *rtcs;
++
++ /* find NVRAM device */
++ rtcs = find_compatible_devices("nvram", "AMD8111");
++ if (rtcs && rtcs->addrs) {
++ maple_nvram_base = rtcs->addrs[0].address;
++ } else {
++ printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
++ printk(KERN_EMERG "Maple: Manual Restart Required\n");
++ return;
++ }
++
++ /* find service processor device */
++ rtcs = find_devices("service-processor");
++ if (!rtcs) {
++ printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
++ printk(KERN_EMERG "Maple: Manual Restart Required\n");
++ return;
++ }
++ maple_nvram_offset = *(unsigned int*) get_property(rtcs,
++ "restart-addr", NULL);
++ maple_nvram_command = *(unsigned int*) get_property(rtcs,
++ "restart-value", NULL);
++
++ /* send command */
++ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
++ for (;;) ;
++}
++
++static void maple_power_off(void)
++{
++ unsigned int maple_nvram_base;
++ unsigned int maple_nvram_offset;
++ unsigned int maple_nvram_command;
++ struct device_node *rtcs;
++
++ /* find NVRAM device */
++ rtcs = find_compatible_devices("nvram", "AMD8111");
++ if (rtcs && rtcs->addrs) {
++ maple_nvram_base = rtcs->addrs[0].address;
++ } else {
++ printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
++ printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
++ return;
++ }
++
++ /* find service processor device */
++ rtcs = find_devices("service-processor");
++ if (!rtcs) {
++ printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
++ printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
++ return;
++ }
++ maple_nvram_offset = *(unsigned int*) get_property(rtcs,
++ "power-off-addr", NULL);
++ maple_nvram_command = *(unsigned int*) get_property(rtcs,
++ "power-off-value", NULL);
++
++ /* send command */
++ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
++ for (;;) ;
++}
++
++static void maple_halt(void)
++{
++ maple_power_off();
++}
++
++#ifdef CONFIG_SMP
++struct smp_ops_t maple_smp_ops = {
++ .probe = smp_mpic_probe,
++ .message_pass = smp_mpic_message_pass,
++ .kick_cpu = smp_generic_kick_cpu,
++ .setup_cpu = smp_mpic_setup_cpu,
++ .give_timebase = smp_generic_give_timebase,
++ .take_timebase = smp_generic_take_timebase,
++};
++#endif /* CONFIG_SMP */
++
++void __init maple_setup_arch(void)
++{
++ /* init to some ~sane value until calibrate_delay() runs */
++ loops_per_jiffy = 50000000;
++
++ /* Setup SMP callback */
++#ifdef CONFIG_SMP
++ smp_ops = &maple_smp_ops;
++#endif
++ /* Lookup PCI hosts */
++ maple_pci_init();
++
++#ifdef CONFIG_DUMMY_CONSOLE
++ conswitchp = &dummy_con;
++#endif
++
++ printk(KERN_INFO "Using native/NAP idle loop\n");
++}
++
++/*
++ * Early initialization.
++ */
++static void __init maple_init_early(void)
++{
++ unsigned int default_speed;
++ u64 physport;
++
++ DBG(" -> maple_init_early\n");
++
++ /* Initialize hash table, from now on, we can take hash faults
++ * and call ioremap
++ */
++ hpte_init_native();
++
++ /* Find the serial port */
++ generic_find_legacy_serial_ports(&physport, &default_speed);
++
++ DBG("phys port addr: %lx\n", (long)physport);
++
++ if (physport) {
++ void *comport;
++ /* Map the uart for udbg. */
++ comport = (void *)ioremap(physport, 16);
++ udbg_init_uart(comport, default_speed);
++
++ DBG("Hello World !\n");
++ }
++
++ /* Setup interrupt mapping options */
++ ppc64_interrupt_controller = IC_OPEN_PIC;
++
++ iommu_init_early_u3();
++
++ DBG(" <- maple_init_early\n");
++}
++
++
++static __init void maple_init_IRQ(void)
++{
++ struct device_node *root;
++ unsigned int *opprop;
++ unsigned long opic_addr;
++ struct mpic *mpic;
++ unsigned char senses[128];
++ int n;
++
++ DBG(" -> maple_init_IRQ\n");
++
++ /* XXX: Non standard, replace that with a proper openpic/mpic node
++ * in the device-tree. Find the Open PIC if present */
++ root = of_find_node_by_path("/");
++ opprop = (unsigned int *) get_property(root,
++ "platform-open-pic", NULL);
++ if (opprop == 0)
++ panic("OpenPIC not found !\n");
++
++ n = prom_n_addr_cells(root);
++ for (opic_addr = 0; n > 0; --n)
++ opic_addr = (opic_addr << 32) + *opprop++;
++ of_node_put(root);
++
++ /* Obtain sense values from device-tree */
++ prom_get_irq_senses(senses, 0, 128);
++
++ mpic = mpic_alloc(opic_addr,
++ MPIC_PRIMARY | MPIC_BIG_ENDIAN |
++ MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
++ 0, 0, 128, 128, senses, 128, "U3-MPIC");
++ BUG_ON(mpic == NULL);
++ mpic_init(mpic);
++
++ DBG(" <- maple_init_IRQ\n");
++}
++
++static void __init maple_progress(char *s, unsigned short hex)
++{
++ printk("*** %04x : %s\n", hex, s ? s : "");
++}
++
++
++/*
++ * Called very early, MMU is off, device-tree isn't unflattened
++ */
++static int __init maple_probe(int platform)
++{
++ if (platform != PLATFORM_MAPLE)
++ return 0;
++ /*
++ * On U3, the DART (iommu) must be allocated now since it
++ * has an impact on htab_initialize (due to the large page it
++ * occupies having to be broken up so the DART itself is not
++ * part of the cacheable linar mapping
++ */
++ alloc_u3_dart_table();
++
++ return 1;
++}
++
++struct machdep_calls __initdata maple_md = {
++ .probe = maple_probe,
++ .setup_arch = maple_setup_arch,
++ .init_early = maple_init_early,
++ .init_IRQ = maple_init_IRQ,
++ .get_irq = mpic_get_irq,
++ .pcibios_fixup = maple_pcibios_fixup,
++ .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
++ .restart = maple_restart,
++ .power_off = maple_power_off,
++ .halt = maple_halt,
++ .get_boot_time = maple_get_boot_time,
++ .set_rtc_time = maple_set_rtc_time,
++ .get_rtc_time = maple_get_rtc_time,
++ .calibrate_decr = generic_calibrate_decr,
++ .progress = maple_progress,
++ .idle_loop = native_idle,
++};
+diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/maple/time.c
+@@ -0,0 +1,180 @@
++/*
++ * arch/ppc64/kernel/maple_time.c
++ *
++ * (c) Copyright 2004 Benjamin Herrenschmidt (benh at kernel.crashing.org),
++ * IBM Corp.
++ *
++ * 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.
++ *
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/time.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++#include <linux/interrupt.h>
++#include <linux/mc146818rtc.h>
++#include <linux/bcd.h>
++
++#include <asm/sections.h>
++#include <asm/prom.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/machdep.h>
++#include <asm/time.h>
++
++#include "maple.h"
++
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++extern void GregorianDay(struct rtc_time * tm);
++
++static int maple_rtc_addr;
++
++static int maple_clock_read(int addr)
++{
++ outb_p(addr, maple_rtc_addr);
++ return inb_p(maple_rtc_addr+1);
++}
++
++static void maple_clock_write(unsigned long val, int addr)
++{
++ outb_p(addr, maple_rtc_addr);
++ outb_p(val, maple_rtc_addr+1);
++}
++
++void maple_get_rtc_time(struct rtc_time *tm)
++{
++ int uip, i;
++
++ /* The Linux interpretation of the CMOS clock register contents:
++ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
++ * RTC registers show the second which has precisely just started.
++ * Let's hope other operating systems interpret the RTC the same way.
++ */
++
++ /* Since the UIP flag is set for about 2.2 ms and the clock
++ * is typically written with a precision of 1 jiffy, trying
++ * to obtain a precision better than a few milliseconds is
++ * an illusion. Only consistency is interesting, this also
++ * allows to use the routine for /dev/rtc without a potential
++ * 1 second kernel busy loop triggered by any reader of /dev/rtc.
++ */
++
++ for (i = 0; i<1000000; i++) {
++ uip = maple_clock_read(RTC_FREQ_SELECT);
++ tm->tm_sec = maple_clock_read(RTC_SECONDS);
++ tm->tm_min = maple_clock_read(RTC_MINUTES);
++ tm->tm_hour = maple_clock_read(RTC_HOURS);
++ tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH);
++ tm->tm_mon = maple_clock_read(RTC_MONTH);
++ tm->tm_year = maple_clock_read(RTC_YEAR);
++ uip |= maple_clock_read(RTC_FREQ_SELECT);
++ if ((uip & RTC_UIP)==0)
++ break;
++ }
++
++ if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
++ || RTC_ALWAYS_BCD) {
++ BCD_TO_BIN(tm->tm_sec);
++ BCD_TO_BIN(tm->tm_min);
++ BCD_TO_BIN(tm->tm_hour);
++ BCD_TO_BIN(tm->tm_mday);
++ BCD_TO_BIN(tm->tm_mon);
++ BCD_TO_BIN(tm->tm_year);
++ }
++ if ((tm->tm_year + 1900) < 1970)
++ tm->tm_year += 100;
++
++ GregorianDay(tm);
++}
++
++int maple_set_rtc_time(struct rtc_time *tm)
++{
++ unsigned char save_control, save_freq_select;
++ int sec, min, hour, mon, mday, year;
++
++ spin_lock(&rtc_lock);
++
++ save_control = maple_clock_read(RTC_CONTROL); /* tell the clock it's being set */
++
++ maple_clock_write((save_control|RTC_SET), RTC_CONTROL);
++
++ save_freq_select = maple_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
++
++ maple_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
++
++ sec = tm->tm_sec;
++ min = tm->tm_min;
++ hour = tm->tm_hour;
++ mon = tm->tm_mon;
++ mday = tm->tm_mday;
++ year = tm->tm_year;
++
++ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
++ BIN_TO_BCD(sec);
++ BIN_TO_BCD(min);
++ BIN_TO_BCD(hour);
++ BIN_TO_BCD(mon);
++ BIN_TO_BCD(mday);
++ BIN_TO_BCD(year);
++ }
++ maple_clock_write(sec, RTC_SECONDS);
++ maple_clock_write(min, RTC_MINUTES);
++ maple_clock_write(hour, RTC_HOURS);
++ maple_clock_write(mon, RTC_MONTH);
++ maple_clock_write(mday, RTC_DAY_OF_MONTH);
++ maple_clock_write(year, RTC_YEAR);
++
++ /* The following flags have to be released exactly in this order,
++ * otherwise the DS12887 (popular MC146818A clone with integrated
++ * battery and quartz) will not reset the oscillator and will not
++ * update precisely 500 ms later. You won't find this mentioned in
++ * the Dallas Semiconductor data sheets, but who believes data
++ * sheets anyway ... -- Markus Kuhn
++ */
++ maple_clock_write(save_control, RTC_CONTROL);
++ maple_clock_write(save_freq_select, RTC_FREQ_SELECT);
++
++ spin_unlock(&rtc_lock);
++
++ return 0;
++}
++
++unsigned long __init maple_get_boot_time(void)
++{
++ struct rtc_time tm;
++ struct device_node *rtcs;
++
++ rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
++ if (rtcs && rtcs->addrs) {
++ maple_rtc_addr = rtcs->addrs[0].address;
++ printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr);
++ } else {
++ maple_rtc_addr = RTC_PORT(0); /* legacy address */
++ printk(KERN_INFO "Maple: No device node for RTC, assuming "
++ "legacy address (0x%x)\n", maple_rtc_addr);
++ }
++
++ maple_get_rtc_time(&tm);
++ return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
++ tm.tm_hour, tm.tm_min, tm.tm_sec);
++}
++
+diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/Makefile
+@@ -0,0 +1,8 @@
++obj-y += pic.o setup.o time.o feature.o pci.o \
++ sleep.o low_i2c.o cache.o
++obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
++obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq.o
++obj-$(CONFIG_NVRAM) += nvram.o
++# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
++obj-$(CONFIG_PPC64) += nvram.o
++obj-$(CONFIG_SMP) += smp.o
+diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/backlight.c
+@@ -0,0 +1,202 @@
++/*
++ * Miscellaneous procedures for dealing with the PowerMac hardware.
++ * Contains support for the backlight.
++ *
++ * Copyright (C) 2000 Benjamin Herrenschmidt
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/stddef.h>
++#include <linux/reboot.h>
++#include <linux/nvram.h>
++#include <linux/console.h>
++#include <asm/sections.h>
++#include <asm/ptrace.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/nvram.h>
++#include <asm/backlight.h>
++
++#include <linux/adb.h>
++#include <linux/pmu.h>
++
++static struct backlight_controller *backlighter;
++static void* backlighter_data;
++static int backlight_autosave;
++static int backlight_level = BACKLIGHT_MAX;
++static int backlight_enabled = 1;
++static int backlight_req_level = -1;
++static int backlight_req_enable = -1;
++
++static void backlight_callback(void *);
++static DECLARE_WORK(backlight_work, backlight_callback, NULL);
++
++void register_backlight_controller(struct backlight_controller *ctrler,
++ void *data, char *type)
++{
++ struct device_node* bk_node;
++ char *prop;
++ int valid = 0;
++
++ /* There's already a matching controller, bail out */
++ if (backlighter != NULL)
++ return;
++
++ bk_node = find_devices("backlight");
++
++#ifdef CONFIG_ADB_PMU
++ /* Special case for the old PowerBook since I can't test on it */
++ backlight_autosave = machine_is_compatible("AAPL,3400/2400")
++ || machine_is_compatible("AAPL,3500");
++ if ((backlight_autosave
++ || machine_is_compatible("AAPL,PowerBook1998")
++ || machine_is_compatible("PowerBook1,1"))
++ && !strcmp(type, "pmu"))
++ valid = 1;
++#endif
++ if (bk_node) {
++ prop = get_property(bk_node, "backlight-control", NULL);
++ if (prop && !strncmp(prop, type, strlen(type)))
++ valid = 1;
++ }
++ if (!valid)
++ return;
++ backlighter = ctrler;
++ backlighter_data = data;
++
++ if (bk_node && !backlight_autosave)
++ prop = get_property(bk_node, "bklt", NULL);
++ else
++ prop = NULL;
++ if (prop) {
++ backlight_level = ((*prop)+1) >> 1;
++ if (backlight_level > BACKLIGHT_MAX)
++ backlight_level = BACKLIGHT_MAX;
++ }
++
++#ifdef CONFIG_ADB_PMU
++ if (backlight_autosave) {
++ struct adb_request req;
++ pmu_request(&req, NULL, 2, 0xd9, 0);
++ while (!req.complete)
++ pmu_poll();
++ backlight_level = req.reply[0] >> 4;
++ }
++#endif
++ acquire_console_sem();
++ if (!backlighter->set_enable(1, backlight_level, data))
++ backlight_enabled = 1;
++ release_console_sem();
++
++ printk(KERN_INFO "Registered \"%s\" backlight controller,"
++ "level: %d/15\n", type, backlight_level);
++}
++EXPORT_SYMBOL(register_backlight_controller);
++
++void unregister_backlight_controller(struct backlight_controller
++ *ctrler, void *data)
++{
++ /* We keep the current backlight level (for now) */
++ if (ctrler == backlighter && data == backlighter_data)
++ backlighter = NULL;
++}
++EXPORT_SYMBOL(unregister_backlight_controller);
++
++static int __set_backlight_enable(int enable)
++{
++ int rc;
++
++ if (!backlighter)
++ return -ENODEV;
++ acquire_console_sem();
++ rc = backlighter->set_enable(enable, backlight_level,
++ backlighter_data);
++ if (!rc)
++ backlight_enabled = enable;
++ release_console_sem();
++ return rc;
++}
++int set_backlight_enable(int enable)
++{
++ if (!backlighter)
++ return -ENODEV;
++ backlight_req_enable = enable;
++ schedule_work(&backlight_work);
++ return 0;
++}
++
++EXPORT_SYMBOL(set_backlight_enable);
++
++int get_backlight_enable(void)
++{
++ if (!backlighter)
++ return -ENODEV;
++ return backlight_enabled;
++}
++EXPORT_SYMBOL(get_backlight_enable);
++
++static int __set_backlight_level(int level)
++{
++ int rc = 0;
++
++ if (!backlighter)
++ return -ENODEV;
++ if (level < BACKLIGHT_MIN)
++ level = BACKLIGHT_OFF;
++ if (level > BACKLIGHT_MAX)
++ level = BACKLIGHT_MAX;
++ acquire_console_sem();
++ if (backlight_enabled)
++ rc = backlighter->set_level(level, backlighter_data);
++ if (!rc)
++ backlight_level = level;
++ release_console_sem();
++ if (!rc && !backlight_autosave) {
++ level <<=1;
++ if (level & 0x10)
++ level |= 0x01;
++ // -- todo: save to property "bklt"
++ }
++ return rc;
++}
++int set_backlight_level(int level)
++{
++ if (!backlighter)
++ return -ENODEV;
++ backlight_req_level = level;
++ schedule_work(&backlight_work);
++ return 0;
++}
++
++EXPORT_SYMBOL(set_backlight_level);
++
++int get_backlight_level(void)
++{
++ if (!backlighter)
++ return -ENODEV;
++ return backlight_level;
++}
++EXPORT_SYMBOL(get_backlight_level);
++
++static void backlight_callback(void *dummy)
++{
++ int level, enable;
++
++ do {
++ level = backlight_req_level;
++ enable = backlight_req_enable;
++ mb();
++
++ if (level >= 0)
++ __set_backlight_level(level);
++ if (enable >= 0)
++ __set_backlight_enable(enable);
++ } while(cmpxchg(&backlight_req_level, level, -1) != level ||
++ cmpxchg(&backlight_req_enable, enable, -1) != enable);
++}
+diff --git a/arch/powerpc/platforms/powermac/cache.S b/arch/powerpc/platforms/powermac/cache.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/cache.S
+@@ -0,0 +1,359 @@
++/*
++ * This file contains low-level cache management functions
++ * used for sleep and CPU speed changes on Apple machines.
++ * (In fact the only thing that is Apple-specific is that we assume
++ * that we can read from ROM at physical address 0xfff00000.)
++ *
++ * Copyright (C) 2004 Paul Mackerras (paulus at samba.org) and
++ * Benjamin Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <asm/processor.h>
++#include <asm/ppc_asm.h>
++#include <asm/cputable.h>
++
++/*
++ * Flush and disable all data caches (dL1, L2, L3). This is used
++ * when going to sleep, when doing a PMU based cpufreq transition,
++ * or when "offlining" a CPU on SMP machines. This code is over
++ * paranoid, but I've had enough issues with various CPU revs and
++ * bugs that I decided it was worth beeing over cautious
++ */
++
++_GLOBAL(flush_disable_caches)
++#ifndef CONFIG_6xx
++ blr
++#else
++BEGIN_FTR_SECTION
++ b flush_disable_745x
++END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
++BEGIN_FTR_SECTION
++ b flush_disable_75x
++END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
++ b __flush_disable_L1
++
++/* This is the code for G3 and 74[01]0 */
++flush_disable_75x:
++ mflr r10
++
++ /* Turn off EE and DR in MSR */
++ mfmsr r11
++ rlwinm r0,r11,0,~MSR_EE
++ rlwinm r0,r0,0,~MSR_DR
++ sync
++ mtmsr r0
++ isync
++
++ /* Stop DST streams */
++BEGIN_FTR_SECTION
++ DSSALL
++ sync
++END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
++
++ /* Stop DPM */
++ mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */
++ rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
++ sync
++ mtspr SPRN_HID0,r4 /* Disable DPM */
++ sync
++
++ /* Disp-flush L1. We have a weird problem here that I never
++ * totally figured out. On 750FX, using the ROM for the flush
++ * results in a non-working flush. We use that workaround for
++ * now until I finally understand what's going on. --BenH
++ */
++
++ /* ROM base by default */
++ lis r4,0xfff0
++ mfpvr r3
++ srwi r3,r3,16
++ cmplwi cr0,r3,0x7000
++ bne+ 1f
++ /* RAM base on 750FX */
++ li r4,0
++1: li r4,0x4000
++ mtctr r4
++1: lwz r0,0(r4)
++ addi r4,r4,32
++ bdnz 1b
++ sync
++ isync
++
++ /* Disable / invalidate / enable L1 data */
++ mfspr r3,SPRN_HID0
++ rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE)
++ mtspr SPRN_HID0,r3
++ sync
++ isync
++ ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI)
++ sync
++ isync
++ mtspr SPRN_HID0,r3
++ xori r3,r3,(HID0_DCI|HID0_ICFI)
++ mtspr SPRN_HID0,r3
++ sync
++
++ /* Get the current enable bit of the L2CR into r4 */
++ mfspr r5,SPRN_L2CR
++ /* Set to data-only (pre-745x bit) */
++ oris r3,r5,L2CR_L2DO at h
++ b 2f
++ /* When disabling L2, code must be in L1 */
++ .balign 32
++1: mtspr SPRN_L2CR,r3
++3: sync
++ isync
++ b 1f
++2: b 3f
++3: sync
++ isync
++ b 1b
++1: /* disp-flush L2. The interesting thing here is that the L2 can be
++ * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory
++ * but that is probbaly fine. We disp-flush over 4Mb to be safe
++ */
++ lis r4,2
++ mtctr r4
++ lis r4,0xfff0
++1: lwz r0,0(r4)
++ addi r4,r4,32
++ bdnz 1b
++ sync
++ isync
++ lis r4,2
++ mtctr r4
++ lis r4,0xfff0
++1: dcbf 0,r4
++ addi r4,r4,32
++ bdnz 1b
++ sync
++ isync
++
++ /* now disable L2 */
++ rlwinm r5,r5,0,~L2CR_L2E
++ b 2f
++ /* When disabling L2, code must be in L1 */
++ .balign 32
++1: mtspr SPRN_L2CR,r5
++3: sync
++ isync
++ b 1f
++2: b 3f
++3: sync
++ isync
++ b 1b
++1: sync
++ isync
++ /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */
++ oris r4,r5,L2CR_L2I at h
++ mtspr SPRN_L2CR,r4
++ sync
++ isync
++
++ /* Wait for the invalidation to complete */
++1: mfspr r3,SPRN_L2CR
++ rlwinm. r0,r3,0,31,31
++ bne 1b
++
++ /* Clear L2I */
++ xoris r4,r4,L2CR_L2I at h
++ sync
++ mtspr SPRN_L2CR,r4
++ sync
++
++ /* now disable the L1 data cache */
++ mfspr r0,SPRN_HID0
++ rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE)
++ mtspr SPRN_HID0,r0
++ sync
++ isync
++
++ /* Restore HID0[DPM] to whatever it was before */
++ sync
++ mfspr r0,SPRN_HID0
++ rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */
++ mtspr SPRN_HID0,r0
++ sync
++
++ /* restore DR and EE */
++ sync
++ mtmsr r11
++ isync
++
++ mtlr r10
++ blr
++
++/* This code is for 745x processors */
++flush_disable_745x:
++ /* Turn off EE and DR in MSR */
++ mfmsr r11
++ rlwinm r0,r11,0,~MSR_EE
++ rlwinm r0,r0,0,~MSR_DR
++ sync
++ mtmsr r0
++ isync
++
++ /* Stop prefetch streams */
++ DSSALL
++ sync
++
++ /* Disable L2 prefetching */
++ mfspr r0,SPRN_MSSCR0
++ rlwinm r0,r0,0,0,29
++ mtspr SPRN_MSSCR0,r0
++ sync
++ isync
++ lis r4,0
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++ dcbf 0,r4
++
++ /* Due to a bug with the HW flush on some CPU revs, we occasionally
++ * experience data corruption. I'm adding a displacement flush along
++ * with a dcbf loop over a few Mb to "help". The problem isn't totally
++ * fixed by this in theory, but at least, in practice, I couldn't reproduce
++ * it even with a big hammer...
++ */
++
++ lis r4,0x0002
++ mtctr r4
++ li r4,0
++1:
++ lwz r0,0(r4)
++ addi r4,r4,32 /* Go to start of next cache line */
++ bdnz 1b
++ isync
++
++ /* Now, flush the first 4MB of memory */
++ lis r4,0x0002
++ mtctr r4
++ li r4,0
++ sync
++1:
++ dcbf 0,r4
++ addi r4,r4,32 /* Go to start of next cache line */
++ bdnz 1b
++
++ /* Flush and disable the L1 data cache */
++ mfspr r6,SPRN_LDSTCR
++ lis r3,0xfff0 /* read from ROM for displacement flush */
++ li r4,0xfe /* start with only way 0 unlocked */
++ li r5,128 /* 128 lines in each way */
++1: mtctr r5
++ rlwimi r6,r4,0,24,31
++ mtspr SPRN_LDSTCR,r6
++ sync
++ isync
++2: lwz r0,0(r3) /* touch each cache line */
++ addi r3,r3,32
++ bdnz 2b
++ rlwinm r4,r4,1,24,30 /* move on to the next way */
++ ori r4,r4,1
++ cmpwi r4,0xff /* all done? */
++ bne 1b
++ /* now unlock the L1 data cache */
++ li r4,0
++ rlwimi r6,r4,0,24,31
++ sync
++ mtspr SPRN_LDSTCR,r6
++ sync
++ isync
++
++ /* Flush the L2 cache using the hardware assist */
++ mfspr r3,SPRN_L2CR
++ cmpwi r3,0 /* check if it is enabled first */
++ bge 4f
++ oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h
++ b 2f
++ /* When disabling/locking L2, code must be in L1 */
++ .balign 32
++1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */
++3: sync
++ isync
++ b 1f
++2: b 3f
++3: sync
++ isync
++ b 1b
++1: sync
++ isync
++ ori r0,r3,L2CR_L2HWF_745x
++ sync
++ mtspr SPRN_L2CR,r0 /* set the hardware flush bit */
++3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */
++ andi. r0,r0,L2CR_L2HWF_745x
++ bne 3b
++ sync
++ rlwinm r3,r3,0,~L2CR_L2E
++ b 2f
++ /* When disabling L2, code must be in L1 */
++ .balign 32
++1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */
++3: sync
++ isync
++ b 1f
++2: b 3f
++3: sync
++ isync
++ b 1b
++1: sync
++ isync
++ oris r4,r3,L2CR_L2I at h
++ mtspr SPRN_L2CR,r4
++ sync
++ isync
++1: mfspr r4,SPRN_L2CR
++ andis. r0,r4,L2CR_L2I at h
++ bne 1b
++ sync
++
++BEGIN_FTR_SECTION
++ /* Flush the L3 cache using the hardware assist */
++4: mfspr r3,SPRN_L3CR
++ cmpwi r3,0 /* check if it is enabled */
++ bge 6f
++ oris r0,r3,L3CR_L3IO at h
++ ori r0,r0,L3CR_L3DO
++ sync
++ mtspr SPRN_L3CR,r0 /* lock the L3 cache */
++ sync
++ isync
++ ori r0,r0,L3CR_L3HWF
++ sync
++ mtspr SPRN_L3CR,r0 /* set the hardware flush bit */
++5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */
++ andi. r0,r0,L3CR_L3HWF
++ bne 5b
++ rlwinm r3,r3,0,~L3CR_L3E
++ sync
++ mtspr SPRN_L3CR,r3 /* disable the L3 cache */
++ sync
++ ori r4,r3,L3CR_L3I
++ mtspr SPRN_L3CR,r4
++1: mfspr r4,SPRN_L3CR
++ andi. r0,r4,L3CR_L3I
++ bne 1b
++ sync
++END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
++
++6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */
++ rlwinm r0,r0,0,~HID0_DCE
++ mtspr SPRN_HID0,r0
++ sync
++ isync
++ mtmsr r11 /* restore DR and EE */
++ isync
++ blr
++#endif /* CONFIG_6xx */
+diff --git a/arch/powerpc/platforms/powermac/cpufreq.c b/arch/powerpc/platforms/powermac/cpufreq.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/cpufreq.c
+@@ -0,0 +1,726 @@
++/*
++ * arch/ppc/platforms/pmac_cpufreq.c
++ *
++ * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>
++ * Copyright (C) 2004 John Steele Scott <toojays at toojays.net>
++ *
++ * 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.
++ *
++ * TODO: Need a big cleanup here. Basically, we need to have different
++ * cpufreq_driver structures for the different type of HW instead of the
++ * current mess. We also need to better deal with the detection of the
++ * type of machine.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++#include <linux/slab.h>
++#include <linux/cpufreq.h>
++#include <linux/init.h>
++#include <linux/sysdev.h>
++#include <linux/i2c.h>
++#include <linux/hardirq.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/irq.h>
++#include <asm/pmac_feature.h>
++#include <asm/mmu_context.h>
++#include <asm/sections.h>
++#include <asm/cputable.h>
++#include <asm/time.h>
++#include <asm/system.h>
++#include <asm/mpic.h>
++#include <asm/keylargo.h>
++
++/* WARNING !!! This will cause calibrate_delay() to be called,
++ * but this is an __init function ! So you MUST go edit
++ * init/main.c to make it non-init before enabling DEBUG_FREQ
++ */
++#undef DEBUG_FREQ
++
++/*
++ * There is a problem with the core cpufreq code on SMP kernels,
++ * it won't recalculate the Bogomips properly
++ */
++#ifdef CONFIG_SMP
++#warning "WARNING, CPUFREQ not recommended on SMP kernels"
++#endif
++
++extern void low_choose_7447a_dfs(int dfs);
++extern void low_choose_750fx_pll(int pll);
++extern void low_sleep_handler(void);
++
++/*
++ * Currently, PowerMac cpufreq supports only high & low frequencies
++ * that are set by the firmware
++ */
++static unsigned int low_freq;
++static unsigned int hi_freq;
++static unsigned int cur_freq;
++static unsigned int sleep_freq;
++
++/*
++ * Different models uses different mecanisms to switch the frequency
++ */
++static int (*set_speed_proc)(int low_speed);
++static unsigned int (*get_speed_proc)(void);
++
++/*
++ * Some definitions used by the various speedprocs
++ */
++static u32 voltage_gpio;
++static u32 frequency_gpio;
++static u32 slew_done_gpio;
++static int no_schedule;
++static int has_cpu_l2lve;
++static int is_pmu_based;
++
++/* There are only two frequency states for each processor. Values
++ * are in kHz for the time being.
++ */
++#define CPUFREQ_HIGH 0
++#define CPUFREQ_LOW 1
++
++static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
++ {CPUFREQ_HIGH, 0},
++ {CPUFREQ_LOW, 0},
++ {0, CPUFREQ_TABLE_END},
++};
++
++static struct freq_attr* pmac_cpu_freqs_attr[] = {
++ &cpufreq_freq_attr_scaling_available_freqs,
++ NULL,
++};
++
++static inline void local_delay(unsigned long ms)
++{
++ if (no_schedule)
++ mdelay(ms);
++ else
++ msleep(ms);
++}
++
++#ifdef DEBUG_FREQ
++static inline void debug_calc_bogomips(void)
++{
++ /* This will cause a recalc of bogomips and display the
++ * result. We backup/restore the value to avoid affecting the
++ * core cpufreq framework's own calculation.
++ */
++ extern void calibrate_delay(void);
++
++ unsigned long save_lpj = loops_per_jiffy;
++ calibrate_delay();
++ loops_per_jiffy = save_lpj;
++}
++#endif /* DEBUG_FREQ */
++
++/* Switch CPU speed under 750FX CPU control
++ */
++static int cpu_750fx_cpu_speed(int low_speed)
++{
++ u32 hid2;
++
++ if (low_speed == 0) {
++ /* ramping up, set voltage first */
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
++ /* Make sure we sleep for at least 1ms */
++ local_delay(10);
++
++ /* tweak L2 for high voltage */
++ if (has_cpu_l2lve) {
++ hid2 = mfspr(SPRN_HID2);
++ hid2 &= ~0x2000;
++ mtspr(SPRN_HID2, hid2);
++ }
++ }
++#ifdef CONFIG_6xx
++ low_choose_750fx_pll(low_speed);
++#endif
++ if (low_speed == 1) {
++ /* tweak L2 for low voltage */
++ if (has_cpu_l2lve) {
++ hid2 = mfspr(SPRN_HID2);
++ hid2 |= 0x2000;
++ mtspr(SPRN_HID2, hid2);
++ }
++
++ /* ramping down, set voltage last */
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
++ local_delay(10);
++ }
++
++ return 0;
++}
++
++static unsigned int cpu_750fx_get_cpu_speed(void)
++{
++ if (mfspr(SPRN_HID1) & HID1_PS)
++ return low_freq;
++ else
++ return hi_freq;
++}
++
++/* Switch CPU speed using DFS */
++static int dfs_set_cpu_speed(int low_speed)
++{
++ if (low_speed == 0) {
++ /* ramping up, set voltage first */
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
++ /* Make sure we sleep for at least 1ms */
++ local_delay(1);
++ }
++
++ /* set frequency */
++#ifdef CONFIG_6xx
++ low_choose_7447a_dfs(low_speed);
++#endif
++ udelay(100);
++
++ if (low_speed == 1) {
++ /* ramping down, set voltage last */
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
++ local_delay(1);
++ }
++
++ return 0;
++}
++
++static unsigned int dfs_get_cpu_speed(void)
++{
++ if (mfspr(SPRN_HID1) & HID1_DFS)
++ return low_freq;
++ else
++ return hi_freq;
++}
++
++
++/* Switch CPU speed using slewing GPIOs
++ */
++static int gpios_set_cpu_speed(int low_speed)
++{
++ int gpio, timeout = 0;
++
++ /* If ramping up, set voltage first */
++ if (low_speed == 0) {
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
++ /* Delay is way too big but it's ok, we schedule */
++ local_delay(10);
++ }
++
++ /* Set frequency */
++ gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
++ if (low_speed == ((gpio & 0x01) == 0))
++ goto skip;
++
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,
++ low_speed ? 0x04 : 0x05);
++ udelay(200);
++ do {
++ if (++timeout > 100)
++ break;
++ local_delay(1);
++ gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0);
++ } while((gpio & 0x02) == 0);
++ skip:
++ /* If ramping down, set voltage last */
++ if (low_speed == 1) {
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
++ /* Delay is way too big but it's ok, we schedule */
++ local_delay(10);
++ }
++
++#ifdef DEBUG_FREQ
++ debug_calc_bogomips();
++#endif
++
++ return 0;
++}
++
++/* Switch CPU speed under PMU control
++ */
++static int pmu_set_cpu_speed(int low_speed)
++{
++ struct adb_request req;
++ unsigned long save_l2cr;
++ unsigned long save_l3cr;
++ unsigned int pic_prio;
++ unsigned long flags;
++
++ preempt_disable();
++
++#ifdef DEBUG_FREQ
++ printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
++#endif
++ pmu_suspend();
++
++ /* Disable all interrupt sources on openpic */
++ pic_prio = mpic_cpu_get_priority();
++ mpic_cpu_set_priority(0xf);
++
++ /* Make sure the decrementer won't interrupt us */
++ asm volatile("mtdec %0" : : "r" (0x7fffffff));
++ /* Make sure any pending DEC interrupt occuring while we did
++ * the above didn't re-enable the DEC */
++ mb();
++ asm volatile("mtdec %0" : : "r" (0x7fffffff));
++
++ /* We can now disable MSR_EE */
++ local_irq_save(flags);
++
++ /* Giveup the FPU & vec */
++ enable_kernel_fp();
++
++#ifdef CONFIG_ALTIVEC
++ if (cpu_has_feature(CPU_FTR_ALTIVEC))
++ enable_kernel_altivec();
++#endif /* CONFIG_ALTIVEC */
++
++ /* Save & disable L2 and L3 caches */
++ save_l3cr = _get_L3CR(); /* (returns -1 if not available) */
++ save_l2cr = _get_L2CR(); /* (returns -1 if not available) */
++
++ /* Send the new speed command. My assumption is that this command
++ * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep
++ */
++ pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);
++ while (!req.complete)
++ pmu_poll();
++
++ /* Prepare the northbridge for the speed transition */
++ pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);
++
++ /* Call low level code to backup CPU state and recover from
++ * hardware reset
++ */
++ low_sleep_handler();
++
++ /* Restore the northbridge */
++ pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);
++
++ /* Restore L2 cache */
++ if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
++ _set_L2CR(save_l2cr);
++ /* Restore L3 cache */
++ if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
++ _set_L3CR(save_l3cr);
++
++ /* Restore userland MMU context */
++ set_context(current->active_mm->context, current->active_mm->pgd);
++
++#ifdef DEBUG_FREQ
++ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
++#endif
++
++ /* Restore low level PMU operations */
++ pmu_unlock();
++
++ /* Restore decrementer */
++ wakeup_decrementer();
++
++ /* Restore interrupts */
++ mpic_cpu_set_priority(pic_prio);
++
++ /* Let interrupts flow again ... */
++ local_irq_restore(flags);
++
++#ifdef DEBUG_FREQ
++ debug_calc_bogomips();
++#endif
++
++ pmu_resume();
++
++ preempt_enable();
++
++ return 0;
++}
++
++static int do_set_cpu_speed(int speed_mode, int notify)
++{
++ struct cpufreq_freqs freqs;
++ unsigned long l3cr;
++ static unsigned long prev_l3cr;
++
++ freqs.old = cur_freq;
++ freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
++ freqs.cpu = smp_processor_id();
++
++ if (freqs.old == freqs.new)
++ return 0;
++
++ if (notify)
++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++ if (speed_mode == CPUFREQ_LOW &&
++ cpu_has_feature(CPU_FTR_L3CR)) {
++ l3cr = _get_L3CR();
++ if (l3cr & L3CR_L3E) {
++ prev_l3cr = l3cr;
++ _set_L3CR(0);
++ }
++ }
++ set_speed_proc(speed_mode == CPUFREQ_LOW);
++ if (speed_mode == CPUFREQ_HIGH &&
++ cpu_has_feature(CPU_FTR_L3CR)) {
++ l3cr = _get_L3CR();
++ if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
++ _set_L3CR(prev_l3cr);
++ }
++ if (notify)
++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++ cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
++
++ return 0;
++}
++
++static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)
++{
++ return cur_freq;
++}
++
++static int pmac_cpufreq_verify(struct cpufreq_policy *policy)
++{
++ return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
++}
++
++static int pmac_cpufreq_target( struct cpufreq_policy *policy,
++ unsigned int target_freq,
++ unsigned int relation)
++{
++ unsigned int newstate = 0;
++
++ if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,
++ target_freq, relation, &newstate))
++ return -EINVAL;
++
++ return do_set_cpu_speed(newstate, 1);
++}
++
++unsigned int pmac_get_one_cpufreq(int i)
++{
++ /* Supports only one CPU for now */
++ return (i == 0) ? cur_freq : 0;
++}
++
++static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
++{
++ if (policy->cpu != 0)
++ return -ENODEV;
++
++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
++ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
++ policy->cur = cur_freq;
++
++ cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
++ return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
++}
++
++static u32 read_gpio(struct device_node *np)
++{
++ u32 *reg = (u32 *)get_property(np, "reg", NULL);
++ u32 offset;
++
++ if (reg == NULL)
++ return 0;
++ /* That works for all keylargos but shall be fixed properly
++ * some day... The problem is that it seems we can't rely
++ * on the "reg" property of the GPIO nodes, they are either
++ * relative to the base of KeyLargo or to the base of the
++ * GPIO space, and the device-tree doesn't help.
++ */
++ offset = *reg;
++ if (offset < KEYLARGO_GPIO_LEVELS0)
++ offset += KEYLARGO_GPIO_LEVELS0;
++ return offset;
++}
++
++static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
++{
++ /* Ok, this could be made a bit smarter, but let's be robust for now. We
++ * always force a speed change to high speed before sleep, to make sure
++ * we have appropriate voltage and/or bus speed for the wakeup process,
++ * and to make sure our loops_per_jiffies are "good enough", that is will
++ * not cause too short delays if we sleep in low speed and wake in high
++ * speed..
++ */
++ no_schedule = 1;
++ sleep_freq = cur_freq;
++ if (cur_freq == low_freq && !is_pmu_based)
++ do_set_cpu_speed(CPUFREQ_HIGH, 0);
++ return 0;
++}
++
++static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
++{
++ /* If we resume, first check if we have a get() function */
++ if (get_speed_proc)
++ cur_freq = get_speed_proc();
++ else
++ cur_freq = 0;
++
++ /* We don't, hrm... we don't really know our speed here, best
++ * is that we force a switch to whatever it was, which is
++ * probably high speed due to our suspend() routine
++ */
++ do_set_cpu_speed(sleep_freq == low_freq ?
++ CPUFREQ_LOW : CPUFREQ_HIGH, 0);
++
++ no_schedule = 0;
++ return 0;
++}
++
++static struct cpufreq_driver pmac_cpufreq_driver = {
++ .verify = pmac_cpufreq_verify,
++ .target = pmac_cpufreq_target,
++ .get = pmac_cpufreq_get_speed,
++ .init = pmac_cpufreq_cpu_init,
++ .suspend = pmac_cpufreq_suspend,
++ .resume = pmac_cpufreq_resume,
++ .flags = CPUFREQ_PM_NO_WARN,
++ .attr = pmac_cpu_freqs_attr,
++ .name = "powermac",
++ .owner = THIS_MODULE,
++};
++
++
++static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
++{
++ struct device_node *volt_gpio_np = of_find_node_by_name(NULL,
++ "voltage-gpio");
++ struct device_node *freq_gpio_np = of_find_node_by_name(NULL,
++ "frequency-gpio");
++ struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,
++ "slewing-done");
++ u32 *value;
++
++ /*
++ * Check to see if it's GPIO driven or PMU only
++ *
++ * The way we extract the GPIO address is slightly hackish, but it
++ * works well enough for now. We need to abstract the whole GPIO
++ * stuff sooner or later anyway
++ */
++
++ if (volt_gpio_np)
++ voltage_gpio = read_gpio(volt_gpio_np);
++ if (freq_gpio_np)
++ frequency_gpio = read_gpio(freq_gpio_np);
++ if (slew_done_gpio_np)
++ slew_done_gpio = read_gpio(slew_done_gpio_np);
++
++ /* If we use the frequency GPIOs, calculate the min/max speeds based
++ * on the bus frequencies
++ */
++ if (frequency_gpio && slew_done_gpio) {
++ int lenp, rc;
++ u32 *freqs, *ratio;
++
++ freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp);
++ lenp /= sizeof(u32);
++ if (freqs == NULL || lenp != 2) {
++ printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
++ return 1;
++ }
++ ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL);
++ if (ratio == NULL) {
++ printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
++ return 1;
++ }
++
++ /* Get the min/max bus frequencies */
++ low_freq = min(freqs[0], freqs[1]);
++ hi_freq = max(freqs[0], freqs[1]);
++
++ /* Grrrr.. It _seems_ that the device-tree is lying on the low bus
++ * frequency, it claims it to be around 84Mhz on some models while
++ * it appears to be approx. 101Mhz on all. Let's hack around here...
++ * fortunately, we don't need to be too precise
++ */
++ if (low_freq < 98000000)
++ low_freq = 101000000;
++
++ /* Convert those to CPU core clocks */
++ low_freq = (low_freq * (*ratio)) / 2000;
++ hi_freq = (hi_freq * (*ratio)) / 2000;
++
++ /* Now we get the frequencies, we read the GPIO to see what is out current
++ * speed
++ */
++ rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
++ cur_freq = (rc & 0x01) ? hi_freq : low_freq;
++
++ set_speed_proc = gpios_set_cpu_speed;
++ return 1;
++ }
++
++ /* If we use the PMU, look for the min & max frequencies in the
++ * device-tree
++ */
++ value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);
++ if (!value)
++ return 1;
++ low_freq = (*value) / 1000;
++ /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree
++ * here */
++ if (low_freq < 100000)
++ low_freq *= 10;
++
++ value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);
++ if (!value)
++ return 1;
++ hi_freq = (*value) / 1000;
++ set_speed_proc = pmu_set_cpu_speed;
++ is_pmu_based = 1;
++
++ return 0;
++}
++
++static int pmac_cpufreq_init_7447A(struct device_node *cpunode)
++{
++ struct device_node *volt_gpio_np;
++
++ if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
++ return 1;
++
++ volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
++ if (volt_gpio_np)
++ voltage_gpio = read_gpio(volt_gpio_np);
++ if (!voltage_gpio){
++ printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
++ return 1;
++ }
++
++ /* OF only reports the high frequency */
++ hi_freq = cur_freq;
++ low_freq = cur_freq/2;
++
++ /* Read actual frequency from CPU */
++ cur_freq = dfs_get_cpu_speed();
++ set_speed_proc = dfs_set_cpu_speed;
++ get_speed_proc = dfs_get_cpu_speed;
++
++ return 0;
++}
++
++static int pmac_cpufreq_init_750FX(struct device_node *cpunode)
++{
++ struct device_node *volt_gpio_np;
++ u32 pvr, *value;
++
++ if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
++ return 1;
++
++ hi_freq = cur_freq;
++ value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL);
++ if (!value)
++ return 1;
++ low_freq = (*value) / 1000;
++
++ volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
++ if (volt_gpio_np)
++ voltage_gpio = read_gpio(volt_gpio_np);
++
++ pvr = mfspr(SPRN_PVR);
++ has_cpu_l2lve = !((pvr & 0xf00) == 0x100);
++
++ set_speed_proc = cpu_750fx_cpu_speed;
++ get_speed_proc = cpu_750fx_get_cpu_speed;
++ cur_freq = cpu_750fx_get_cpu_speed();
++
++ return 0;
++}
++
++/* Currently, we support the following machines:
++ *
++ * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)
++ * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
++ * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
++ * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
++ * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
++ * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
++ * - Recent MacRISC3 laptops
++ * - All new machines with 7447A CPUs
++ */
++static int __init pmac_cpufreq_setup(void)
++{
++ struct device_node *cpunode;
++ u32 *value;
++
++ if (strstr(cmd_line, "nocpufreq"))
++ return 0;
++
++ /* Assume only one CPU */
++ cpunode = find_type_devices("cpu");
++ if (!cpunode)
++ goto out;
++
++ /* Get current cpu clock freq */
++ value = (u32 *)get_property(cpunode, "clock-frequency", NULL);
++ if (!value)
++ goto out;
++ cur_freq = (*value) / 1000;
++
++ /* Check for 7447A based MacRISC3 */
++ if (machine_is_compatible("MacRISC3") &&
++ get_property(cpunode, "dynamic-power-step", NULL) &&
++ PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
++ pmac_cpufreq_init_7447A(cpunode);
++ /* Check for other MacRISC3 machines */
++ } else if (machine_is_compatible("PowerBook3,4") ||
++ machine_is_compatible("PowerBook3,5") ||
++ machine_is_compatible("MacRISC3")) {
++ pmac_cpufreq_init_MacRISC3(cpunode);
++ /* Else check for iBook2 500/600 */
++ } else if (machine_is_compatible("PowerBook4,1")) {
++ hi_freq = cur_freq;
++ low_freq = 400000;
++ set_speed_proc = pmu_set_cpu_speed;
++ is_pmu_based = 1;
++ }
++ /* Else check for TiPb 550 */
++ else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) {
++ hi_freq = cur_freq;
++ low_freq = 500000;
++ set_speed_proc = pmu_set_cpu_speed;
++ is_pmu_based = 1;
++ }
++ /* Else check for TiPb 400 & 500 */
++ else if (machine_is_compatible("PowerBook3,2")) {
++ /* We only know about the 400 MHz and the 500Mhz model
++ * they both have 300 MHz as low frequency
++ */
++ if (cur_freq < 350000 || cur_freq > 550000)
++ goto out;
++ hi_freq = cur_freq;
++ low_freq = 300000;
++ set_speed_proc = pmu_set_cpu_speed;
++ is_pmu_based = 1;
++ }
++ /* Else check for 750FX */
++ else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
++ pmac_cpufreq_init_750FX(cpunode);
++out:
++ if (set_speed_proc == NULL)
++ return -ENODEV;
++
++ pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;
++ pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;
++
++ printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");
++ printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
++ low_freq/1000, hi_freq/1000, cur_freq/1000);
++
++ return cpufreq_register_driver(&pmac_cpufreq_driver);
++}
++
++module_init(pmac_cpufreq_setup);
++
+diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/feature.c
+@@ -0,0 +1,3063 @@
++/*
++ * arch/ppc/platforms/pmac_feature.c
++ *
++ * Copyright (C) 1996-2001 Paul Mackerras (paulus at cs.anu.edu.au)
++ * Ben. Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * TODO:
++ *
++ * - Replace mdelay with some schedule loop if possible
++ * - Shorten some obfuscated delays on some routines (like modem
++ * power)
++ * - Refcount some clocks (see darwin)
++ * - Split split split...
++ *
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <asm/sections.h>
++#include <asm/errno.h>
++#include <asm/ohare.h>
++#include <asm/heathrow.h>
++#include <asm/keylargo.h>
++#include <asm/uninorth.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/pmac_feature.h>
++#include <asm/dbdma.h>
++#include <asm/pci-bridge.h>
++#include <asm/pmac_low_i2c.h>
++
++#undef DEBUG_FEATURE
++
++#ifdef DEBUG_FEATURE
++#define DBG(fmt...) printk(KERN_DEBUG fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++#ifdef CONFIG_6xx
++extern int powersave_lowspeed;
++#endif
++
++extern int powersave_nap;
++extern struct device_node *k2_skiplist[2];
++
++
++/*
++ * We use a single global lock to protect accesses. Each driver has
++ * to take care of its own locking
++ */
++static DEFINE_SPINLOCK(feature_lock);
++
++#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
++#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
++
++
++/*
++ * Instance of some macio stuffs
++ */
++struct macio_chip macio_chips[MAX_MACIO_CHIPS];
++
++struct macio_chip *macio_find(struct device_node *child, int type)
++{
++ while(child) {
++ int i;
++
++ for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
++ if (child == macio_chips[i].of_node &&
++ (!type || macio_chips[i].type == type))
++ return &macio_chips[i];
++ child = child->parent;
++ }
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(macio_find);
++
++static const char *macio_names[] =
++{
++ "Unknown",
++ "Grand Central",
++ "OHare",
++ "OHareII",
++ "Heathrow",
++ "Gatwick",
++ "Paddington",
++ "Keylargo",
++ "Pangea",
++ "Intrepid",
++ "K2"
++};
++
++
++
++/*
++ * Uninorth reg. access. Note that Uni-N regs are big endian
++ */
++
++#define UN_REG(r) (uninorth_base + ((r) >> 2))
++#define UN_IN(r) (in_be32(UN_REG(r)))
++#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
++#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
++#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
++
++static struct device_node *uninorth_node;
++static u32 __iomem *uninorth_base;
++static u32 uninorth_rev;
++static int uninorth_u3;
++static void __iomem *u3_ht;
++
++/*
++ * For each motherboard family, we have a table of functions pointers
++ * that handle the various features.
++ */
++
++typedef long (*feature_call)(struct device_node *node, long param, long value);
++
++struct feature_table_entry {
++ unsigned int selector;
++ feature_call function;
++};
++
++struct pmac_mb_def
++{
++ const char* model_string;
++ const char* model_name;
++ int model_id;
++ struct feature_table_entry* features;
++ unsigned long board_flags;
++};
++static struct pmac_mb_def pmac_mb;
++
++/*
++ * Here are the chip specific feature functions
++ */
++
++static inline int simple_feature_tweak(struct device_node *node, int type,
++ int reg, u32 mask, int value)
++{
++ struct macio_chip* macio;
++ unsigned long flags;
++
++ macio = macio_find(node, type);
++ if (!macio)
++ return -ENODEV;
++ LOCK(flags);
++ if (value)
++ MACIO_BIS(reg, mask);
++ else
++ MACIO_BIC(reg, mask);
++ (void)MACIO_IN32(reg);
++ UNLOCK(flags);
++
++ return 0;
++}
++
++#ifndef CONFIG_POWER4
++
++static long ohare_htw_scc_enable(struct device_node *node, long param,
++ long value)
++{
++ struct macio_chip* macio;
++ unsigned long chan_mask;
++ unsigned long fcr;
++ unsigned long flags;
++ int htw, trans;
++ unsigned long rmask;
++
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++ if (!strcmp(node->name, "ch-a"))
++ chan_mask = MACIO_FLAG_SCCA_ON;
++ else if (!strcmp(node->name, "ch-b"))
++ chan_mask = MACIO_FLAG_SCCB_ON;
++ else
++ return -ENODEV;
++
++ htw = (macio->type == macio_heathrow || macio->type == macio_paddington
++ || macio->type == macio_gatwick);
++ /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
++ trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
++ pmac_mb.model_id != PMAC_TYPE_YIKES);
++ if (value) {
++#ifdef CONFIG_ADB_PMU
++ if ((param & 0xfff) == PMAC_SCC_IRDA)
++ pmu_enable_irled(1);
++#endif /* CONFIG_ADB_PMU */
++ LOCK(flags);
++ fcr = MACIO_IN32(OHARE_FCR);
++ /* Check if scc cell need enabling */
++ if (!(fcr & OH_SCC_ENABLE)) {
++ fcr |= OH_SCC_ENABLE;
++ if (htw) {
++ /* Side effect: this will also power up the
++ * modem, but it's too messy to figure out on which
++ * ports this controls the tranceiver and on which
++ * it controls the modem
++ */
++ if (trans)
++ fcr &= ~HRW_SCC_TRANS_EN_N;
++ MACIO_OUT32(OHARE_FCR, fcr);
++ fcr |= (rmask = HRW_RESET_SCC);
++ MACIO_OUT32(OHARE_FCR, fcr);
++ } else {
++ fcr |= (rmask = OH_SCC_RESET);
++ MACIO_OUT32(OHARE_FCR, fcr);
++ }
++ UNLOCK(flags);
++ (void)MACIO_IN32(OHARE_FCR);
++ mdelay(15);
++ LOCK(flags);
++ fcr &= ~rmask;
++ MACIO_OUT32(OHARE_FCR, fcr);
++ }
++ if (chan_mask & MACIO_FLAG_SCCA_ON)
++ fcr |= OH_SCCA_IO;
++ if (chan_mask & MACIO_FLAG_SCCB_ON)
++ fcr |= OH_SCCB_IO;
++ MACIO_OUT32(OHARE_FCR, fcr);
++ macio->flags |= chan_mask;
++ UNLOCK(flags);
++ if (param & PMAC_SCC_FLAG_XMON)
++ macio->flags |= MACIO_FLAG_SCC_LOCKED;
++ } else {
++ if (macio->flags & MACIO_FLAG_SCC_LOCKED)
++ return -EPERM;
++ LOCK(flags);
++ fcr = MACIO_IN32(OHARE_FCR);
++ if (chan_mask & MACIO_FLAG_SCCA_ON)
++ fcr &= ~OH_SCCA_IO;
++ if (chan_mask & MACIO_FLAG_SCCB_ON)
++ fcr &= ~OH_SCCB_IO;
++ MACIO_OUT32(OHARE_FCR, fcr);
++ if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
++ fcr &= ~OH_SCC_ENABLE;
++ if (htw && trans)
++ fcr |= HRW_SCC_TRANS_EN_N;
++ MACIO_OUT32(OHARE_FCR, fcr);
++ }
++ macio->flags &= ~(chan_mask);
++ UNLOCK(flags);
++ mdelay(10);
++#ifdef CONFIG_ADB_PMU
++ if ((param & 0xfff) == PMAC_SCC_IRDA)
++ pmu_enable_irled(0);
++#endif /* CONFIG_ADB_PMU */
++ }
++ return 0;
++}
++
++static long ohare_floppy_enable(struct device_node *node, long param,
++ long value)
++{
++ return simple_feature_tweak(node, macio_ohare,
++ OHARE_FCR, OH_FLOPPY_ENABLE, value);
++}
++
++static long ohare_mesh_enable(struct device_node *node, long param, long value)
++{
++ return simple_feature_tweak(node, macio_ohare,
++ OHARE_FCR, OH_MESH_ENABLE, value);
++}
++
++static long ohare_ide_enable(struct device_node *node, long param, long value)
++{
++ switch(param) {
++ case 0:
++ /* For some reason, setting the bit in set_initial_features()
++ * doesn't stick. I'm still investigating... --BenH.
++ */
++ if (value)
++ simple_feature_tweak(node, macio_ohare,
++ OHARE_FCR, OH_IOBUS_ENABLE, 1);
++ return simple_feature_tweak(node, macio_ohare,
++ OHARE_FCR, OH_IDE0_ENABLE, value);
++ case 1:
++ return simple_feature_tweak(node, macio_ohare,
++ OHARE_FCR, OH_BAY_IDE_ENABLE, value);
++ default:
++ return -ENODEV;
++ }
++}
++
++static long ohare_ide_reset(struct device_node *node, long param, long value)
++{
++ switch(param) {
++ case 0:
++ return simple_feature_tweak(node, macio_ohare,
++ OHARE_FCR, OH_IDE0_RESET_N, !value);
++ case 1:
++ return simple_feature_tweak(node, macio_ohare,
++ OHARE_FCR, OH_IDE1_RESET_N, !value);
++ default:
++ return -ENODEV;
++ }
++}
++
++static long ohare_sleep_state(struct device_node *node, long param, long value)
++{
++ struct macio_chip* macio = &macio_chips[0];
++
++ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
++ return -EPERM;
++ if (value == 1) {
++ MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
++ } else if (value == 0) {
++ MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
++ }
++
++ return 0;
++}
++
++static long heathrow_modem_enable(struct device_node *node, long param,
++ long value)
++{
++ struct macio_chip* macio;
++ u8 gpio;
++ unsigned long flags;
++
++ macio = macio_find(node, macio_unknown);
++ if (!macio)
++ return -ENODEV;
++ gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;
++ if (!value) {
++ LOCK(flags);
++ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
++ UNLOCK(flags);
++ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
++ mdelay(250);
++ }
++ if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
++ pmac_mb.model_id != PMAC_TYPE_YIKES) {
++ LOCK(flags);
++ if (value)
++ MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
++ else
++ MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
++ UNLOCK(flags);
++ (void)MACIO_IN32(HEATHROW_FCR);
++ mdelay(250);
++ }
++ if (value) {
++ LOCK(flags);
++ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
++ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250); LOCK(flags);
++ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
++ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250); LOCK(flags);
++ MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
++ (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250);
++ }
++ return 0;
++}
++
++static long heathrow_floppy_enable(struct device_node *node, long param,
++ long value)
++{
++ return simple_feature_tweak(node, macio_unknown,
++ HEATHROW_FCR,
++ HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,
++ value);
++}
++
++static long heathrow_mesh_enable(struct device_node *node, long param,
++ long value)
++{
++ struct macio_chip* macio;
++ unsigned long flags;
++
++ macio = macio_find(node, macio_unknown);
++ if (!macio)
++ return -ENODEV;
++ LOCK(flags);
++ /* Set clear mesh cell enable */
++ if (value)
++ MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);
++ else
++ MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);
++ (void)MACIO_IN32(HEATHROW_FCR);
++ udelay(10);
++ /* Set/Clear termination power */
++ if (value)
++ MACIO_BIC(HEATHROW_MBCR, 0x04000000);
++ else
++ MACIO_BIS(HEATHROW_MBCR, 0x04000000);
++ (void)MACIO_IN32(HEATHROW_MBCR);
++ udelay(10);
++ UNLOCK(flags);
++
++ return 0;
++}
++
++static long heathrow_ide_enable(struct device_node *node, long param,
++ long value)
++{
++ switch(param) {
++ case 0:
++ return simple_feature_tweak(node, macio_unknown,
++ HEATHROW_FCR, HRW_IDE0_ENABLE, value);
++ case 1:
++ return simple_feature_tweak(node, macio_unknown,
++ HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);
++ default:
++ return -ENODEV;
++ }
++}
++
++static long heathrow_ide_reset(struct device_node *node, long param,
++ long value)
++{
++ switch(param) {
++ case 0:
++ return simple_feature_tweak(node, macio_unknown,
++ HEATHROW_FCR, HRW_IDE0_RESET_N, !value);
++ case 1:
++ return simple_feature_tweak(node, macio_unknown,
++ HEATHROW_FCR, HRW_IDE1_RESET_N, !value);
++ default:
++ return -ENODEV;
++ }
++}
++
++static long heathrow_bmac_enable(struct device_node *node, long param,
++ long value)
++{
++ struct macio_chip* macio;
++ unsigned long flags;
++
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++ if (value) {
++ LOCK(flags);
++ MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
++ MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);
++ UNLOCK(flags);
++ (void)MACIO_IN32(HEATHROW_FCR);
++ mdelay(10);
++ LOCK(flags);
++ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);
++ UNLOCK(flags);
++ (void)MACIO_IN32(HEATHROW_FCR);
++ mdelay(10);
++ } else {
++ LOCK(flags);
++ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
++ UNLOCK(flags);
++ }
++ return 0;
++}
++
++static long heathrow_sound_enable(struct device_node *node, long param,
++ long value)
++{
++ struct macio_chip* macio;
++ unsigned long flags;
++
++ /* B&W G3 and Yikes don't support that properly (the
++ * sound appear to never come back after beeing shut down).
++ */
++ if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
++ pmac_mb.model_id == PMAC_TYPE_YIKES)
++ return 0;
++
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++ if (value) {
++ LOCK(flags);
++ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
++ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
++ UNLOCK(flags);
++ (void)MACIO_IN32(HEATHROW_FCR);
++ } else {
++ LOCK(flags);
++ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
++ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
++ UNLOCK(flags);
++ }
++ return 0;
++}
++
++static u32 save_fcr[6];
++static u32 save_mbcr;
++static u32 save_gpio_levels[2];
++static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
++static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
++static u32 save_unin_clock_ctl;
++static struct dbdma_regs save_dbdma[13];
++static struct dbdma_regs save_alt_dbdma[13];
++
++static void dbdma_save(struct macio_chip *macio, struct dbdma_regs *save)
++{
++ int i;
++
++ /* Save state & config of DBDMA channels */
++ for (i = 0; i < 13; i++) {
++ volatile struct dbdma_regs __iomem * chan = (void __iomem *)
++ (macio->base + ((0x8000+i*0x100)>>2));
++ save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
++ save[i].cmdptr = in_le32(&chan->cmdptr);
++ save[i].intr_sel = in_le32(&chan->intr_sel);
++ save[i].br_sel = in_le32(&chan->br_sel);
++ save[i].wait_sel = in_le32(&chan->wait_sel);
++ }
++}
++
++static void dbdma_restore(struct macio_chip *macio, struct dbdma_regs *save)
++{
++ int i;
++
++ /* Save state & config of DBDMA channels */
++ for (i = 0; i < 13; i++) {
++ volatile struct dbdma_regs __iomem * chan = (void __iomem *)
++ (macio->base + ((0x8000+i*0x100)>>2));
++ out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
++ while (in_le32(&chan->status) & ACTIVE)
++ mb();
++ out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);
++ out_le32(&chan->cmdptr, save[i].cmdptr);
++ out_le32(&chan->intr_sel, save[i].intr_sel);
++ out_le32(&chan->br_sel, save[i].br_sel);
++ out_le32(&chan->wait_sel, save[i].wait_sel);
++ }
++}
++
++static void heathrow_sleep(struct macio_chip *macio, int secondary)
++{
++ if (secondary) {
++ dbdma_save(macio, save_alt_dbdma);
++ save_fcr[2] = MACIO_IN32(0x38);
++ save_fcr[3] = MACIO_IN32(0x3c);
++ } else {
++ dbdma_save(macio, save_dbdma);
++ save_fcr[0] = MACIO_IN32(0x38);
++ save_fcr[1] = MACIO_IN32(0x3c);
++ save_mbcr = MACIO_IN32(0x34);
++ /* Make sure sound is shut down */
++ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
++ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
++ /* This seems to be necessary as well or the fan
++ * keeps coming up and battery drains fast */
++ MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
++ MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
++ /* Make sure eth is down even if module or sleep
++ * won't work properly */
++ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
++ }
++ /* Make sure modem is shut down */
++ MACIO_OUT8(HRW_GPIO_MODEM_RESET,
++ MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
++ MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
++ MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
++
++ /* Let things settle */
++ (void)MACIO_IN32(HEATHROW_FCR);
++}
++
++static void heathrow_wakeup(struct macio_chip *macio, int secondary)
++{
++ if (secondary) {
++ MACIO_OUT32(0x38, save_fcr[2]);
++ (void)MACIO_IN32(0x38);
++ mdelay(1);
++ MACIO_OUT32(0x3c, save_fcr[3]);
++ (void)MACIO_IN32(0x38);
++ mdelay(10);
++ dbdma_restore(macio, save_alt_dbdma);
++ } else {
++ MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);
++ (void)MACIO_IN32(0x38);
++ mdelay(1);
++ MACIO_OUT32(0x3c, save_fcr[1]);
++ (void)MACIO_IN32(0x38);
++ mdelay(1);
++ MACIO_OUT32(0x34, save_mbcr);
++ (void)MACIO_IN32(0x38);
++ mdelay(10);
++ dbdma_restore(macio, save_dbdma);
++ }
++}
++
++static long heathrow_sleep_state(struct device_node *node, long param,
++ long value)
++{
++ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
++ return -EPERM;
++ if (value == 1) {
++ if (macio_chips[1].type == macio_gatwick)
++ heathrow_sleep(&macio_chips[0], 1);
++ heathrow_sleep(&macio_chips[0], 0);
++ } else if (value == 0) {
++ heathrow_wakeup(&macio_chips[0], 0);
++ if (macio_chips[1].type == macio_gatwick)
++ heathrow_wakeup(&macio_chips[0], 1);
++ }
++ return 0;
++}
++
++static long core99_scc_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip* macio;
++ unsigned long flags;
++ unsigned long chan_mask;
++ u32 fcr;
++
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++ if (!strcmp(node->name, "ch-a"))
++ chan_mask = MACIO_FLAG_SCCA_ON;
++ else if (!strcmp(node->name, "ch-b"))
++ chan_mask = MACIO_FLAG_SCCB_ON;
++ else
++ return -ENODEV;
++
++ if (value) {
++ int need_reset_scc = 0;
++ int need_reset_irda = 0;
++
++ LOCK(flags);
++ fcr = MACIO_IN32(KEYLARGO_FCR0);
++ /* Check if scc cell need enabling */
++ if (!(fcr & KL0_SCC_CELL_ENABLE)) {
++ fcr |= KL0_SCC_CELL_ENABLE;
++ need_reset_scc = 1;
++ }
++ if (chan_mask & MACIO_FLAG_SCCA_ON) {
++ fcr |= KL0_SCCA_ENABLE;
++ /* Don't enable line drivers for I2S modem */
++ if ((param & 0xfff) == PMAC_SCC_I2S1)
++ fcr &= ~KL0_SCC_A_INTF_ENABLE;
++ else
++ fcr |= KL0_SCC_A_INTF_ENABLE;
++ }
++ if (chan_mask & MACIO_FLAG_SCCB_ON) {
++ fcr |= KL0_SCCB_ENABLE;
++ /* Perform irda specific inits */
++ if ((param & 0xfff) == PMAC_SCC_IRDA) {
++ fcr &= ~KL0_SCC_B_INTF_ENABLE;
++ fcr |= KL0_IRDA_ENABLE;
++ fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;
++ fcr |= KL0_IRDA_SOURCE1_SEL;
++ fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
++ fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
++ need_reset_irda = 1;
++ } else
++ fcr |= KL0_SCC_B_INTF_ENABLE;
++ }
++ MACIO_OUT32(KEYLARGO_FCR0, fcr);
++ macio->flags |= chan_mask;
++ if (need_reset_scc) {
++ MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ UNLOCK(flags);
++ mdelay(15);
++ LOCK(flags);
++ MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);
++ }
++ if (need_reset_irda) {
++ MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ UNLOCK(flags);
++ mdelay(15);
++ LOCK(flags);
++ MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);
++ }
++ UNLOCK(flags);
++ if (param & PMAC_SCC_FLAG_XMON)
++ macio->flags |= MACIO_FLAG_SCC_LOCKED;
++ } else {
++ if (macio->flags & MACIO_FLAG_SCC_LOCKED)
++ return -EPERM;
++ LOCK(flags);
++ fcr = MACIO_IN32(KEYLARGO_FCR0);
++ if (chan_mask & MACIO_FLAG_SCCA_ON)
++ fcr &= ~KL0_SCCA_ENABLE;
++ if (chan_mask & MACIO_FLAG_SCCB_ON) {
++ fcr &= ~KL0_SCCB_ENABLE;
++ /* Perform irda specific clears */
++ if ((param & 0xfff) == PMAC_SCC_IRDA) {
++ fcr &= ~KL0_IRDA_ENABLE;
++ fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);
++ fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
++ fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
++ }
++ }
++ MACIO_OUT32(KEYLARGO_FCR0, fcr);
++ if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {
++ fcr &= ~KL0_SCC_CELL_ENABLE;
++ MACIO_OUT32(KEYLARGO_FCR0, fcr);
++ }
++ macio->flags &= ~(chan_mask);
++ UNLOCK(flags);
++ mdelay(10);
++ }
++ return 0;
++}
++
++static long
++core99_modem_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip* macio;
++ u8 gpio;
++ unsigned long flags;
++
++ /* Hack for internal USB modem */
++ if (node == NULL) {
++ if (macio_chips[0].type != macio_keylargo)
++ return -ENODEV;
++ node = macio_chips[0].of_node;
++ }
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++ gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
++ gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
++ gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
++
++ if (!value) {
++ LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
++ UNLOCK(flags);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ mdelay(250);
++ }
++ LOCK(flags);
++ if (value) {
++ MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
++ UNLOCK(flags);
++ (void)MACIO_IN32(KEYLARGO_FCR2);
++ mdelay(250);
++ } else {
++ MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
++ UNLOCK(flags);
++ }
++ if (value) {
++ LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250); LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250); LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250);
++ }
++ return 0;
++}
++
++static long
++pangea_modem_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip* macio;
++ u8 gpio;
++ unsigned long flags;
++
++ /* Hack for internal USB modem */
++ if (node == NULL) {
++ if (macio_chips[0].type != macio_pangea &&
++ macio_chips[0].type != macio_intrepid)
++ return -ENODEV;
++ node = macio_chips[0].of_node;
++ }
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++ gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
++ gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
++ gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
++
++ if (!value) {
++ LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
++ UNLOCK(flags);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ mdelay(250);
++ }
++ LOCK(flags);
++ if (value) {
++ MACIO_OUT8(KL_GPIO_MODEM_POWER,
++ KEYLARGO_GPIO_OUTPUT_ENABLE);
++ UNLOCK(flags);
++ (void)MACIO_IN32(KEYLARGO_FCR2);
++ mdelay(250);
++ } else {
++ MACIO_OUT8(KL_GPIO_MODEM_POWER,
++ KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
++ UNLOCK(flags);
++ }
++ if (value) {
++ LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250); LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250); LOCK(flags);
++ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
++ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
++ UNLOCK(flags); mdelay(250);
++ }
++ return 0;
++}
++
++static long
++core99_ata100_enable(struct device_node *node, long value)
++{
++ unsigned long flags;
++ struct pci_dev *pdev = NULL;
++ u8 pbus, pid;
++
++ if (uninorth_rev < 0x24)
++ return -ENODEV;
++
++ LOCK(flags);
++ if (value)
++ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
++ else
++ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
++ (void)UN_IN(UNI_N_CLOCK_CNTL);
++ UNLOCK(flags);
++ udelay(20);
++
++ if (value) {
++ if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
++ pdev = pci_find_slot(pbus, pid);
++ if (pdev == NULL)
++ return 0;
++ pci_enable_device(pdev);
++ pci_set_master(pdev);
++ }
++ return 0;
++}
++
++static long
++core99_ide_enable(struct device_node *node, long param, long value)
++{
++ /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
++ * based ata-100
++ */
++ switch(param) {
++ case 0:
++ return simple_feature_tweak(node, macio_unknown,
++ KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);
++ case 1:
++ return simple_feature_tweak(node, macio_unknown,
++ KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);
++ case 2:
++ return simple_feature_tweak(node, macio_unknown,
++ KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
++ case 3:
++ return core99_ata100_enable(node, value);
++ default:
++ return -ENODEV;
++ }
++}
++
++static long
++core99_ide_reset(struct device_node *node, long param, long value)
++{
++ switch(param) {
++ case 0:
++ return simple_feature_tweak(node, macio_unknown,
++ KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);
++ case 1:
++ return simple_feature_tweak(node, macio_unknown,
++ KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);
++ case 2:
++ return simple_feature_tweak(node, macio_unknown,
++ KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);
++ default:
++ return -ENODEV;
++ }
++}
++
++static long
++core99_gmac_enable(struct device_node *node, long param, long value)
++{
++ unsigned long flags;
++
++ LOCK(flags);
++ if (value)
++ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
++ else
++ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
++ (void)UN_IN(UNI_N_CLOCK_CNTL);
++ UNLOCK(flags);
++ udelay(20);
++
++ return 0;
++}
++
++static long
++core99_gmac_phy_reset(struct device_node *node, long param, long value)
++{
++ unsigned long flags;
++ struct macio_chip *macio;
++
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
++ macio->type != macio_intrepid)
++ return -ENODEV;
++
++ LOCK(flags);
++ MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
++ (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
++ UNLOCK(flags);
++ mdelay(10);
++ LOCK(flags);
++ MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */
++ KEYLARGO_GPIO_OUTOUT_DATA);
++ UNLOCK(flags);
++ mdelay(10);
++
++ return 0;
++}
++
++static long
++core99_sound_chip_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip* macio;
++ unsigned long flags;
++
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++
++ /* Do a better probe code, screamer G4 desktops &
++ * iMacs can do that too, add a recalibrate in
++ * the driver as well
++ */
++ if (pmac_mb.model_id == PMAC_TYPE_PISMO ||
++ pmac_mb.model_id == PMAC_TYPE_TITANIUM) {
++ LOCK(flags);
++ if (value)
++ MACIO_OUT8(KL_GPIO_SOUND_POWER,
++ KEYLARGO_GPIO_OUTPUT_ENABLE |
++ KEYLARGO_GPIO_OUTOUT_DATA);
++ else
++ MACIO_OUT8(KL_GPIO_SOUND_POWER,
++ KEYLARGO_GPIO_OUTPUT_ENABLE);
++ (void)MACIO_IN8(KL_GPIO_SOUND_POWER);
++ UNLOCK(flags);
++ }
++ return 0;
++}
++
++static long
++core99_airport_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip* macio;
++ unsigned long flags;
++ int state;
++
++ macio = macio_find(node, 0);
++ if (!macio)
++ return -ENODEV;
++
++ /* Hint: we allow passing of macio itself for the sake of the
++ * sleep code
++ */
++ if (node != macio->of_node &&
++ (!node->parent || node->parent != macio->of_node))
++ return -ENODEV;
++ state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;
++ if (value == state)
++ return 0;
++ if (value) {
++ /* This code is a reproduction of OF enable-cardslot
++ * and init-wireless methods, slightly hacked until
++ * I got it working.
++ */
++ LOCK(flags);
++ MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);
++ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
++ UNLOCK(flags);
++ mdelay(10);
++ LOCK(flags);
++ MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
++ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
++ UNLOCK(flags);
++
++ mdelay(10);
++
++ LOCK(flags);
++ MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
++ (void)MACIO_IN32(KEYLARGO_FCR2);
++ udelay(10);
++ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
++ (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);
++ udelay(10);
++ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
++ (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);
++ udelay(10);
++ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
++ (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);
++ udelay(10);
++ MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);
++ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);
++ udelay(10);
++ MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);
++ (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);
++ UNLOCK(flags);
++ udelay(10);
++ MACIO_OUT32(0x1c000, 0);
++ mdelay(1);
++ MACIO_OUT8(0x1a3e0, 0x41);
++ (void)MACIO_IN8(0x1a3e0);
++ udelay(10);
++ LOCK(flags);
++ MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);
++ (void)MACIO_IN32(KEYLARGO_FCR2);
++ UNLOCK(flags);
++ mdelay(100);
++
++ macio->flags |= MACIO_FLAG_AIRPORT_ON;
++ } else {
++ LOCK(flags);
++ MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
++ (void)MACIO_IN32(KEYLARGO_FCR2);
++ MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);
++ MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);
++ MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);
++ MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);
++ MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);
++ (void)MACIO_IN8(KL_GPIO_AIRPORT_4);
++ UNLOCK(flags);
++
++ macio->flags &= ~MACIO_FLAG_AIRPORT_ON;
++ }
++ return 0;
++}
++
++#ifdef CONFIG_SMP
++static long
++core99_reset_cpu(struct device_node *node, long param, long value)
++{
++ unsigned int reset_io = 0;
++ unsigned long flags;
++ struct macio_chip *macio;
++ struct device_node *np;
++ const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,
++ KL_GPIO_RESET_CPU1,
++ KL_GPIO_RESET_CPU2,
++ KL_GPIO_RESET_CPU3 };
++
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo)
++ return -ENODEV;
++
++ np = find_path_device("/cpus");
++ if (np == NULL)
++ return -ENODEV;
++ for (np = np->child; np != NULL; np = np->sibling) {
++ u32 *num = (u32 *)get_property(np, "reg", NULL);
++ u32 *rst = (u32 *)get_property(np, "soft-reset", NULL);
++ if (num == NULL || rst == NULL)
++ continue;
++ if (param == *num) {
++ reset_io = *rst;
++ break;
++ }
++ }
++ if (np == NULL || reset_io == 0)
++ reset_io = dflt_reset_lines[param];
++
++ LOCK(flags);
++ MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
++ (void)MACIO_IN8(reset_io);
++ udelay(1);
++ MACIO_OUT8(reset_io, 0);
++ (void)MACIO_IN8(reset_io);
++ UNLOCK(flags);
++
++ return 0;
++}
++#endif /* CONFIG_SMP */
++
++static long
++core99_usb_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip *macio;
++ unsigned long flags;
++ char *prop;
++ int number;
++ u32 reg;
++
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
++ macio->type != macio_intrepid)
++ return -ENODEV;
++
++ prop = (char *)get_property(node, "AAPL,clock-id", NULL);
++ if (!prop)
++ return -ENODEV;
++ if (strncmp(prop, "usb0u048", 8) == 0)
++ number = 0;
++ else if (strncmp(prop, "usb1u148", 8) == 0)
++ number = 2;
++ else if (strncmp(prop, "usb2u248", 8) == 0)
++ number = 4;
++ else
++ return -ENODEV;
++
++ /* Sorry for the brute-force locking, but this is only used during
++ * sleep and the timing seem to be critical
++ */
++ LOCK(flags);
++ if (value) {
++ /* Turn ON */
++ if (number == 0) {
++ MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ UNLOCK(flags);
++ mdelay(1);
++ LOCK(flags);
++ MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
++ } else if (number == 2) {
++ MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
++ UNLOCK(flags);
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ mdelay(1);
++ LOCK(flags);
++ MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
++ } else if (number == 4) {
++ MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
++ UNLOCK(flags);
++ (void)MACIO_IN32(KEYLARGO_FCR1);
++ mdelay(1);
++ LOCK(flags);
++ MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE);
++ }
++ if (number < 4) {
++ reg = MACIO_IN32(KEYLARGO_FCR4);
++ reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
++ KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));
++ reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
++ KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));
++ MACIO_OUT32(KEYLARGO_FCR4, reg);
++ (void)MACIO_IN32(KEYLARGO_FCR4);
++ udelay(10);
++ } else {
++ reg = MACIO_IN32(KEYLARGO_FCR3);
++ reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
++ KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0));
++ reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
++ KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1));
++ MACIO_OUT32(KEYLARGO_FCR3, reg);
++ (void)MACIO_IN32(KEYLARGO_FCR3);
++ udelay(10);
++ }
++ if (macio->type == macio_intrepid) {
++ /* wait for clock stopped bits to clear */
++ u32 test0 = 0, test1 = 0;
++ u32 status0, status1;
++ int timeout = 1000;
++
++ UNLOCK(flags);
++ switch (number) {
++ case 0:
++ test0 = UNI_N_CLOCK_STOPPED_USB0;
++ test1 = UNI_N_CLOCK_STOPPED_USB0PCI;
++ break;
++ case 2:
++ test0 = UNI_N_CLOCK_STOPPED_USB1;
++ test1 = UNI_N_CLOCK_STOPPED_USB1PCI;
++ break;
++ case 4:
++ test0 = UNI_N_CLOCK_STOPPED_USB2;
++ test1 = UNI_N_CLOCK_STOPPED_USB2PCI;
++ break;
++ }
++ do {
++ if (--timeout <= 0) {
++ printk(KERN_ERR "core99_usb_enable: "
++ "Timeout waiting for clocks\n");
++ break;
++ }
++ mdelay(1);
++ status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0);
++ status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1);
++ } while ((status0 & test0) | (status1 & test1));
++ LOCK(flags);
++ }
++ } else {
++ /* Turn OFF */
++ if (number < 4) {
++ reg = MACIO_IN32(KEYLARGO_FCR4);
++ reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
++ KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);
++ reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
++ KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);
++ MACIO_OUT32(KEYLARGO_FCR4, reg);
++ (void)MACIO_IN32(KEYLARGO_FCR4);
++ udelay(1);
++ } else {
++ reg = MACIO_IN32(KEYLARGO_FCR3);
++ reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
++ KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0);
++ reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
++ KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1);
++ MACIO_OUT32(KEYLARGO_FCR3, reg);
++ (void)MACIO_IN32(KEYLARGO_FCR3);
++ udelay(1);
++ }
++ if (number == 0) {
++ if (macio->type != macio_intrepid)
++ MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ udelay(1);
++ MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ } else if (number == 2) {
++ if (macio->type != macio_intrepid)
++ MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ udelay(1);
++ MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ } else if (number == 4) {
++ udelay(1);
++ MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
++ (void)MACIO_IN32(KEYLARGO_FCR1);
++ }
++ udelay(1);
++ }
++ UNLOCK(flags);
++
++ return 0;
++}
++
++static long
++core99_firewire_enable(struct device_node *node, long param, long value)
++{
++ unsigned long flags;
++ struct macio_chip *macio;
++
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
++ macio->type != macio_intrepid)
++ return -ENODEV;
++ if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
++ return -ENODEV;
++
++ LOCK(flags);
++ if (value) {
++ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
++ (void)UN_IN(UNI_N_CLOCK_CNTL);
++ } else {
++ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
++ (void)UN_IN(UNI_N_CLOCK_CNTL);
++ }
++ UNLOCK(flags);
++ mdelay(1);
++
++ return 0;
++}
++
++static long
++core99_firewire_cable_power(struct device_node *node, long param, long value)
++{
++ unsigned long flags;
++ struct macio_chip *macio;
++
++ /* Trick: we allow NULL node */
++ if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
++ return -ENODEV;
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
++ macio->type != macio_intrepid)
++ return -ENODEV;
++ if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
++ return -ENODEV;
++
++ LOCK(flags);
++ if (value) {
++ MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);
++ MACIO_IN8(KL_GPIO_FW_CABLE_POWER);
++ udelay(10);
++ } else {
++ MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);
++ MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);
++ }
++ UNLOCK(flags);
++ mdelay(1);
++
++ return 0;
++}
++
++static long
++intrepid_aack_delay_enable(struct device_node *node, long param, long value)
++{
++ unsigned long flags;
++
++ if (uninorth_rev < 0xd2)
++ return -ENODEV;
++
++ LOCK(flags);
++ if (param)
++ UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
++ else
++ UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
++ UNLOCK(flags);
++
++ return 0;
++}
++
++
++#endif /* CONFIG_POWER4 */
++
++static long
++core99_read_gpio(struct device_node *node, long param, long value)
++{
++ struct macio_chip *macio = &macio_chips[0];
++
++ return MACIO_IN8(param);
++}
++
++
++static long
++core99_write_gpio(struct device_node *node, long param, long value)
++{
++ struct macio_chip *macio = &macio_chips[0];
++
++ MACIO_OUT8(param, (u8)(value & 0xff));
++ return 0;
++}
++
++#ifdef CONFIG_POWER4
++static long g5_gmac_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip *macio = &macio_chips[0];
++ unsigned long flags;
++
++ if (node == NULL)
++ return -ENODEV;
++
++ LOCK(flags);
++ if (value) {
++ MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
++ mb();
++ k2_skiplist[0] = NULL;
++ } else {
++ k2_skiplist[0] = node;
++ mb();
++ MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
++ }
++
++ UNLOCK(flags);
++ mdelay(1);
++
++ return 0;
++}
++
++static long g5_fw_enable(struct device_node *node, long param, long value)
++{
++ struct macio_chip *macio = &macio_chips[0];
++ unsigned long flags;
++
++ if (node == NULL)
++ return -ENODEV;
++
++ LOCK(flags);
++ if (value) {
++ MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
++ mb();
++ k2_skiplist[1] = NULL;
++ } else {
++ k2_skiplist[1] = node;
++ mb();
++ MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
++ }
++
++ UNLOCK(flags);
++ mdelay(1);
++
++ return 0;
++}
++
++static long g5_mpic_enable(struct device_node *node, long param, long value)
++{
++ unsigned long flags;
++
++ if (node->parent == NULL || strcmp(node->parent->name, "u3"))
++ return 0;
++
++ LOCK(flags);
++ UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);
++ UNLOCK(flags);
++
++ return 0;
++}
++
++static long g5_eth_phy_reset(struct device_node *node, long param, long value)
++{
++ struct macio_chip *macio = &macio_chips[0];
++ struct device_node *phy;
++ int need_reset;
++
++ /*
++ * We must not reset the combo PHYs, only the BCM5221 found in
++ * the iMac G5.
++ */
++ phy = of_get_next_child(node, NULL);
++ if (!phy)
++ return -ENODEV;
++ need_reset = device_is_compatible(phy, "B5221");
++ of_node_put(phy);
++ if (!need_reset)
++ return 0;
++
++ /* PHY reset is GPIO 29, not in device-tree unfortunately */
++ MACIO_OUT8(K2_GPIO_EXTINT_0 + 29,
++ KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
++ /* Thankfully, this is now always called at a time when we can
++ * schedule by sungem.
++ */
++ msleep(10);
++ MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 0);
++
++ return 0;
++}
++
++static long g5_i2s_enable(struct device_node *node, long param, long value)
++{
++ /* Very crude implementation for now */
++ struct macio_chip *macio = &macio_chips[0];
++ unsigned long flags;
++
++ if (value == 0)
++ return 0; /* don't disable yet */
++
++ LOCK(flags);
++ MACIO_BIS(KEYLARGO_FCR3, KL3_CLK45_ENABLE | KL3_CLK49_ENABLE |
++ KL3_I2S0_CLK18_ENABLE);
++ udelay(10);
++ MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_I2S0_CELL_ENABLE |
++ K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE);
++ udelay(10);
++ MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_I2S0_RESET);
++ UNLOCK(flags);
++ udelay(10);
++
++ return 0;
++}
++
++
++#ifdef CONFIG_SMP
++static long g5_reset_cpu(struct device_node *node, long param, long value)
++{
++ unsigned int reset_io = 0;
++ unsigned long flags;
++ struct macio_chip *macio;
++ struct device_node *np;
++
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo2)
++ return -ENODEV;
++
++ np = find_path_device("/cpus");
++ if (np == NULL)
++ return -ENODEV;
++ for (np = np->child; np != NULL; np = np->sibling) {
++ u32 *num = (u32 *)get_property(np, "reg", NULL);
++ u32 *rst = (u32 *)get_property(np, "soft-reset", NULL);
++ if (num == NULL || rst == NULL)
++ continue;
++ if (param == *num) {
++ reset_io = *rst;
++ break;
++ }
++ }
++ if (np == NULL || reset_io == 0)
++ return -ENODEV;
++
++ LOCK(flags);
++ MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
++ (void)MACIO_IN8(reset_io);
++ udelay(1);
++ MACIO_OUT8(reset_io, 0);
++ (void)MACIO_IN8(reset_io);
++ UNLOCK(flags);
++
++ return 0;
++}
++#endif /* CONFIG_SMP */
++
++/*
++ * This can be called from pmac_smp so isn't static
++ *
++ * This takes the second CPU off the bus on dual CPU machines
++ * running UP
++ */
++void g5_phy_disable_cpu1(void)
++{
++ UN_OUT(U3_API_PHY_CONFIG_1, 0);
++}
++#endif /* CONFIG_POWER4 */
++
++#ifndef CONFIG_POWER4
++
++static void
++keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
++{
++ u32 temp;
++
++ if (sleep_mode) {
++ mdelay(1);
++ MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ mdelay(1);
++ }
++
++ MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
++ KL0_SCC_CELL_ENABLE |
++ KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
++ KL0_IRDA_CLK19_ENABLE);
++
++ MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
++ MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);
++
++ MACIO_BIC(KEYLARGO_FCR1,
++ KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
++ KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
++ KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
++ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
++ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
++ KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
++ KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
++ KL1_UIDE_ENABLE);
++
++ MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
++ MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
++
++ temp = MACIO_IN32(KEYLARGO_FCR3);
++ if (macio->rev >= 2) {
++ temp |= KL3_SHUTDOWN_PLL2X;
++ if (sleep_mode)
++ temp |= KL3_SHUTDOWN_PLL_TOTAL;
++ }
++
++ temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
++ KL3_SHUTDOWN_PLLKW35;
++ if (sleep_mode)
++ temp |= KL3_SHUTDOWN_PLLKW12;
++ temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
++ | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
++ if (sleep_mode)
++ temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
++ MACIO_OUT32(KEYLARGO_FCR3, temp);
++
++ /* Flush posted writes & wait a bit */
++ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
++}
++
++static void
++pangea_shutdown(struct macio_chip *macio, int sleep_mode)
++{
++ u32 temp;
++
++ MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
++ KL0_SCC_CELL_ENABLE |
++ KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
++
++ MACIO_BIC(KEYLARGO_FCR1,
++ KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
++ KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
++ KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
++ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
++ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
++ KL1_UIDE_ENABLE);
++ if (pmac_mb.board_flags & PMAC_MB_MOBILE)
++ MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
++
++ MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
++
++ temp = MACIO_IN32(KEYLARGO_FCR3);
++ temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
++ KL3_SHUTDOWN_PLLKW35;
++ temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE
++ | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);
++ if (sleep_mode)
++ temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);
++ MACIO_OUT32(KEYLARGO_FCR3, temp);
++
++ /* Flush posted writes & wait a bit */
++ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
++}
++
++static void
++intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
++{
++ u32 temp;
++
++ MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
++ KL0_SCC_CELL_ENABLE);
++
++ MACIO_BIC(KEYLARGO_FCR1,
++ /*KL1_USB2_CELL_ENABLE |*/
++ KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
++ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
++ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
++ if (pmac_mb.board_flags & PMAC_MB_MOBILE)
++ MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
++
++ temp = MACIO_IN32(KEYLARGO_FCR3);
++ temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |
++ KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
++ if (sleep_mode)
++ temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);
++ MACIO_OUT32(KEYLARGO_FCR3, temp);
++
++ /* Flush posted writes & wait a bit */
++ (void)MACIO_IN32(KEYLARGO_FCR0);
++ mdelay(10);
++}
++
++
++void pmac_tweak_clock_spreading(int enable)
++{
++ struct macio_chip *macio = &macio_chips[0];
++
++ /* Hack for doing clock spreading on some machines PowerBooks and
++ * iBooks. This implements the "platform-do-clockspreading" OF
++ * property as decoded manually on various models. For safety, we also
++ * check the product ID in the device-tree in cases we'll whack the i2c
++ * chip to make reasonably sure we won't set wrong values in there
++ *
++ * Of course, ultimately, we have to implement a real parser for
++ * the platform-do-* stuff...
++ */
++
++ if (macio->type == macio_intrepid) {
++ if (enable)
++ UN_OUT(UNI_N_CLOCK_SPREADING, 2);
++ else
++ UN_OUT(UNI_N_CLOCK_SPREADING, 0);
++ mdelay(40);
++ }
++
++ while (machine_is_compatible("PowerBook5,2") ||
++ machine_is_compatible("PowerBook5,3") ||
++ machine_is_compatible("PowerBook6,2") ||
++ machine_is_compatible("PowerBook6,3")) {
++ struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
++ struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
++ u8 buffer[9];
++ u32 *productID;
++ int i, rc, changed = 0;
++
++ if (dt == NULL)
++ break;
++ productID = (u32 *)get_property(dt, "pid#", NULL);
++ if (productID == NULL)
++ break;
++ while(ui2c) {
++ struct device_node *p = of_get_parent(ui2c);
++ if (p && !strcmp(p->name, "uni-n"))
++ break;
++ ui2c = of_find_node_by_type(ui2c, "i2c");
++ }
++ if (ui2c == NULL)
++ break;
++ DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
++ rc = pmac_low_i2c_open(ui2c, 1);
++ if (rc != 0)
++ break;
++ pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
++ rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
++ DBG("read result: %d,", rc);
++ if (rc != 0) {
++ pmac_low_i2c_close(ui2c);
++ break;
++ }
++ for (i=0; i<9; i++)
++ DBG(" %02x", buffer[i]);
++ DBG("\n");
++
++ switch(*productID) {
++ case 0x1182: /* AlBook 12" rev 2 */
++ case 0x1183: /* iBook G4 12" */
++ buffer[0] = (buffer[0] & 0x8f) | 0x70;
++ buffer[2] = (buffer[2] & 0x7f) | 0x00;
++ buffer[5] = (buffer[5] & 0x80) | 0x31;
++ buffer[6] = (buffer[6] & 0x40) | 0xb0;
++ buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);
++ buffer[8] = (buffer[8] & 0x00) | 0x30;
++ changed = 1;
++ break;
++ case 0x3142: /* AlBook 15" (ATI M10) */
++ case 0x3143: /* AlBook 17" (ATI M10) */
++ buffer[0] = (buffer[0] & 0xaf) | 0x50;
++ buffer[2] = (buffer[2] & 0x7f) | 0x00;
++ buffer[5] = (buffer[5] & 0x80) | 0x31;
++ buffer[6] = (buffer[6] & 0x40) | 0xb0;
++ buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);
++ buffer[8] = (buffer[8] & 0x00) | 0x30;
++ changed = 1;
++ break;
++ default:
++ DBG("i2c-hwclock: Machine model not handled\n");
++ break;
++ }
++ if (!changed) {
++ pmac_low_i2c_close(ui2c);
++ break;
++ }
++ pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
++ rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
++ DBG("write result: %d,", rc);
++ pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
++ rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
++ DBG("read result: %d,", rc);
++ if (rc != 0) {
++ pmac_low_i2c_close(ui2c);
++ break;
++ }
++ for (i=0; i<9; i++)
++ DBG(" %02x", buffer[i]);
++ pmac_low_i2c_close(ui2c);
++ break;
++ }
++}
++
++
++static int
++core99_sleep(void)
++{
++ struct macio_chip *macio;
++ int i;
++
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
++ macio->type != macio_intrepid)
++ return -ENODEV;
++
++ /* We power off the wireless slot in case it was not done
++ * by the driver. We don't power it on automatically however
++ */
++ if (macio->flags & MACIO_FLAG_AIRPORT_ON)
++ core99_airport_enable(macio->of_node, 0, 0);
++
++ /* We power off the FW cable. Should be done by the driver... */
++ if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
++ core99_firewire_enable(NULL, 0, 0);
++ core99_firewire_cable_power(NULL, 0, 0);
++ }
++
++ /* We make sure int. modem is off (in case driver lost it) */
++ if (macio->type == macio_keylargo)
++ core99_modem_enable(macio->of_node, 0, 0);
++ else
++ pangea_modem_enable(macio->of_node, 0, 0);
++
++ /* We make sure the sound is off as well */
++ core99_sound_chip_enable(macio->of_node, 0, 0);
++
++ /*
++ * Save various bits of KeyLargo
++ */
++
++ /* Save the state of the various GPIOs */
++ save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);
++ save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);
++ for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
++ save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);
++ for (i=0; i<KEYLARGO_GPIO_CNT; i++)
++ save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
++
++ /* Save the FCRs */
++ if (macio->type == macio_keylargo)
++ save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
++ save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
++ save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
++ save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
++ save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
++ save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
++ if (macio->type == macio_pangea || macio->type == macio_intrepid)
++ save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);
++
++ /* Save state & config of DBDMA channels */
++ dbdma_save(macio, save_dbdma);
++
++ /*
++ * Turn off as much as we can
++ */
++ if (macio->type == macio_pangea)
++ pangea_shutdown(macio, 1);
++ else if (macio->type == macio_intrepid)
++ intrepid_shutdown(macio, 1);
++ else if (macio->type == macio_keylargo)
++ keylargo_shutdown(macio, 1);
++
++ /*
++ * Put the host bridge to sleep
++ */
++
++ save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
++ /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it
++ * enabled !
++ */
++ UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
++ ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
++ udelay(100);
++ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
++ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
++ mdelay(10);
++
++ /*
++ * FIXME: A bit of black magic with OpenPIC (don't ask me why)
++ */
++ if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
++ MACIO_BIS(0x506e0, 0x00400000);
++ MACIO_BIS(0x506e0, 0x80000000);
++ }
++ return 0;
++}
++
++static int
++core99_wake_up(void)
++{
++ struct macio_chip *macio;
++ int i;
++
++ macio = &macio_chips[0];
++ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
++ macio->type != macio_intrepid)
++ return -ENODEV;
++
++ /*
++ * Wakeup the host bridge
++ */
++ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
++ udelay(10);
++ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
++ udelay(10);
++
++ /*
++ * Restore KeyLargo
++ */
++
++ if (macio->type == macio_keylargo) {
++ MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
++ (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
++ }
++ MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
++ (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
++ MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
++ (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
++ MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);
++ (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);
++ MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);
++ (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
++ MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
++ (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
++ if (macio->type == macio_pangea || macio->type == macio_intrepid) {
++ MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);
++ (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);
++ }
++
++ dbdma_restore(macio, save_dbdma);
++
++ MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
++ MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
++ for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
++ MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);
++ for (i=0; i<KEYLARGO_GPIO_CNT; i++)
++ MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);
++
++ /* FIXME more black magic with OpenPIC ... */
++ if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
++ MACIO_BIC(0x506e0, 0x00400000);
++ MACIO_BIC(0x506e0, 0x80000000);
++ }
++
++ UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
++ udelay(100);
++
++ return 0;
++}
++
++static long
++core99_sleep_state(struct device_node *node, long param, long value)
++{
++ /* Param == 1 means to enter the "fake sleep" mode that is
++ * used for CPU speed switch
++ */
++ if (param == 1) {
++ if (value == 1) {
++ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
++ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);
++ } else {
++ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
++ udelay(10);
++ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
++ udelay(10);
++ }
++ return 0;
++ }
++ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
++ return -EPERM;
++
++ if (value == 1)
++ return core99_sleep();
++ else if (value == 0)
++ return core99_wake_up();
++ return 0;
++}
++
++#endif /* CONFIG_POWER4 */
++
++static long
++generic_dev_can_wake(struct device_node *node, long param, long value)
++{
++ /* Todo: eventually check we are really dealing with on-board
++ * video device ...
++ */
++
++ if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP)
++ pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP;
++ return 0;
++}
++
++static long generic_get_mb_info(struct device_node *node, long param, long value)
++{
++ switch(param) {
++ case PMAC_MB_INFO_MODEL:
++ return pmac_mb.model_id;
++ case PMAC_MB_INFO_FLAGS:
++ return pmac_mb.board_flags;
++ case PMAC_MB_INFO_NAME:
++ /* hack hack hack... but should work */
++ *((const char **)value) = pmac_mb.model_name;
++ return 0;
++ }
++ return -EINVAL;
++}
++
++
++/*
++ * Table definitions
++ */
++
++/* Used on any machine
++ */
++static struct feature_table_entry any_features[] = {
++ { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },
++ { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake },
++ { 0, NULL }
++};
++
++#ifndef CONFIG_POWER4
++
++/* OHare based motherboards. Currently, we only use these on the
++ * 2400,3400 and 3500 series powerbooks. Some older desktops seem
++ * to have issues with turning on/off those asic cells
++ */
++static struct feature_table_entry ohare_features[] = {
++ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
++ { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable },
++ { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable },
++ { PMAC_FTR_IDE_ENABLE, ohare_ide_enable},
++ { PMAC_FTR_IDE_RESET, ohare_ide_reset},
++ { PMAC_FTR_SLEEP_STATE, ohare_sleep_state },
++ { 0, NULL }
++};
++
++/* Heathrow desktop machines (Beige G3).
++ * Separated as some features couldn't be properly tested
++ * and the serial port control bits appear to confuse it.
++ */
++static struct feature_table_entry heathrow_desktop_features[] = {
++ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
++ { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
++ { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
++ { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
++ { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
++ { 0, NULL }
++};
++
++/* Heathrow based laptop, that is the Wallstreet and mainstreet
++ * powerbooks.
++ */
++static struct feature_table_entry heathrow_laptop_features[] = {
++ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
++ { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
++ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
++ { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
++ { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
++ { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
++ { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
++ { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
++ { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
++ { 0, NULL }
++};
++
++/* Paddington based machines
++ * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
++ */
++static struct feature_table_entry paddington_features[] = {
++ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
++ { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
++ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
++ { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
++ { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
++ { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
++ { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
++ { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
++ { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
++ { 0, NULL }
++};
++
++/* Core99 & MacRISC 2 machines (all machines released since the
++ * iBook (included), that is all AGP machines, except pangea
++ * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
++ * used on iBook2 & iMac "flow power".
++ */
++static struct feature_table_entry core99_features[] = {
++ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
++ { PMAC_FTR_MODEM_ENABLE, core99_modem_enable },
++ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
++ { PMAC_FTR_IDE_RESET, core99_ide_reset },
++ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
++ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
++ { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
++ { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
++ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
++ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
++ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
++ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
++#ifdef CONFIG_SMP
++ { PMAC_FTR_RESET_CPU, core99_reset_cpu },
++#endif /* CONFIG_SMP */
++ { PMAC_FTR_READ_GPIO, core99_read_gpio },
++ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
++ { 0, NULL }
++};
++
++/* RackMac
++ */
++static struct feature_table_entry rackmac_features[] = {
++ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
++ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
++ { PMAC_FTR_IDE_RESET, core99_ide_reset },
++ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
++ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
++ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
++ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
++ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
++ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
++#ifdef CONFIG_SMP
++ { PMAC_FTR_RESET_CPU, core99_reset_cpu },
++#endif /* CONFIG_SMP */
++ { PMAC_FTR_READ_GPIO, core99_read_gpio },
++ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
++ { 0, NULL }
++};
++
++/* Pangea features
++ */
++static struct feature_table_entry pangea_features[] = {
++ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
++ { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
++ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
++ { PMAC_FTR_IDE_RESET, core99_ide_reset },
++ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
++ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
++ { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
++ { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
++ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
++ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
++ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
++ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
++ { PMAC_FTR_READ_GPIO, core99_read_gpio },
++ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
++ { 0, NULL }
++};
++
++/* Intrepid features
++ */
++static struct feature_table_entry intrepid_features[] = {
++ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
++ { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
++ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
++ { PMAC_FTR_IDE_RESET, core99_ide_reset },
++ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
++ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
++ { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
++ { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
++ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
++ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
++ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
++ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
++ { PMAC_FTR_READ_GPIO, core99_read_gpio },
++ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
++ { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable },
++ { 0, NULL }
++};
++
++#else /* CONFIG_POWER4 */
++
++/* G5 features
++ */
++static struct feature_table_entry g5_features[] = {
++ { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },
++ { PMAC_FTR_1394_ENABLE, g5_fw_enable },
++ { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
++ { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset },
++ { PMAC_FTR_SOUND_CHIP_ENABLE, g5_i2s_enable },
++#ifdef CONFIG_SMP
++ { PMAC_FTR_RESET_CPU, g5_reset_cpu },
++#endif /* CONFIG_SMP */
++ { PMAC_FTR_READ_GPIO, core99_read_gpio },
++ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
++ { 0, NULL }
++};
++
++#endif /* CONFIG_POWER4 */
++
++static struct pmac_mb_def pmac_mb_defs[] = {
++#ifndef CONFIG_POWER4
++ /*
++ * Desktops
++ */
++
++ { "AAPL,8500", "PowerMac 8500/8600",
++ PMAC_TYPE_PSURGE, NULL,
++ 0
++ },
++ { "AAPL,9500", "PowerMac 9500/9600",
++ PMAC_TYPE_PSURGE, NULL,
++ 0
++ },
++ { "AAPL,7200", "PowerMac 7200",
++ PMAC_TYPE_PSURGE, NULL,
++ 0
++ },
++ { "AAPL,7300", "PowerMac 7200/7300",
++ PMAC_TYPE_PSURGE, NULL,
++ 0
++ },
++ { "AAPL,7500", "PowerMac 7500",
++ PMAC_TYPE_PSURGE, NULL,
++ 0
++ },
++ { "AAPL,ShinerESB", "Apple Network Server",
++ PMAC_TYPE_ANS, NULL,
++ 0
++ },
++ { "AAPL,e407", "Alchemy",
++ PMAC_TYPE_ALCHEMY, NULL,
++ 0
++ },
++ { "AAPL,e411", "Gazelle",
++ PMAC_TYPE_GAZELLE, NULL,
++ 0
++ },
++ { "AAPL,Gossamer", "PowerMac G3 (Gossamer)",
++ PMAC_TYPE_GOSSAMER, heathrow_desktop_features,
++ 0
++ },
++ { "AAPL,PowerMac G3", "PowerMac G3 (Silk)",
++ PMAC_TYPE_SILK, heathrow_desktop_features,
++ 0
++ },
++ { "PowerMac1,1", "Blue&White G3",
++ PMAC_TYPE_YOSEMITE, paddington_features,
++ 0
++ },
++ { "PowerMac1,2", "PowerMac G4 PCI Graphics",
++ PMAC_TYPE_YIKES, paddington_features,
++ 0
++ },
++ { "PowerMac2,1", "iMac FireWire",
++ PMAC_TYPE_FW_IMAC, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
++ },
++ { "PowerMac2,2", "iMac FireWire",
++ PMAC_TYPE_FW_IMAC, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
++ },
++ { "PowerMac3,1", "PowerMac G4 AGP Graphics",
++ PMAC_TYPE_SAWTOOTH, core99_features,
++ PMAC_MB_OLD_CORE99
++ },
++ { "PowerMac3,2", "PowerMac G4 AGP Graphics",
++ PMAC_TYPE_SAWTOOTH, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
++ },
++ { "PowerMac3,3", "PowerMac G4 AGP Graphics",
++ PMAC_TYPE_SAWTOOTH, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
++ },
++ { "PowerMac3,4", "PowerMac G4 Silver",
++ PMAC_TYPE_QUICKSILVER, core99_features,
++ PMAC_MB_MAY_SLEEP
++ },
++ { "PowerMac3,5", "PowerMac G4 Silver",
++ PMAC_TYPE_QUICKSILVER, core99_features,
++ PMAC_MB_MAY_SLEEP
++ },
++ { "PowerMac3,6", "PowerMac G4 Windtunnel",
++ PMAC_TYPE_WINDTUNNEL, core99_features,
++ PMAC_MB_MAY_SLEEP,
++ },
++ { "PowerMac4,1", "iMac \"Flower Power\"",
++ PMAC_TYPE_PANGEA_IMAC, pangea_features,
++ PMAC_MB_MAY_SLEEP
++ },
++ { "PowerMac4,2", "Flat panel iMac",
++ PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,
++ PMAC_MB_CAN_SLEEP
++ },
++ { "PowerMac4,4", "eMac",
++ PMAC_TYPE_EMAC, core99_features,
++ PMAC_MB_MAY_SLEEP
++ },
++ { "PowerMac5,1", "PowerMac G4 Cube",
++ PMAC_TYPE_CUBE, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
++ },
++ { "PowerMac6,1", "Flat panel iMac",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP,
++ },
++ { "PowerMac6,3", "Flat panel iMac",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP,
++ },
++ { "PowerMac6,4", "eMac",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP,
++ },
++ { "PowerMac10,1", "Mac mini",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER,
++ },
++ { "iMac,1", "iMac (first generation)",
++ PMAC_TYPE_ORIG_IMAC, paddington_features,
++ 0
++ },
++
++ /*
++ * Xserve's
++ */
++
++ { "RackMac1,1", "XServe",
++ PMAC_TYPE_RACKMAC, rackmac_features,
++ 0,
++ },
++ { "RackMac1,2", "XServe rev. 2",
++ PMAC_TYPE_RACKMAC, rackmac_features,
++ 0,
++ },
++
++ /*
++ * Laptops
++ */
++
++ { "AAPL,3400/2400", "PowerBook 3400",
++ PMAC_TYPE_HOOPER, ohare_features,
++ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
++ },
++ { "AAPL,3500", "PowerBook 3500",
++ PMAC_TYPE_KANGA, ohare_features,
++ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
++ },
++ { "AAPL,PowerBook1998", "PowerBook Wallstreet",
++ PMAC_TYPE_WALLSTREET, heathrow_laptop_features,
++ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
++ },
++ { "PowerBook1,1", "PowerBook 101 (Lombard)",
++ PMAC_TYPE_101_PBOOK, paddington_features,
++ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
++ },
++ { "PowerBook2,1", "iBook (first generation)",
++ PMAC_TYPE_ORIG_IBOOK, core99_features,
++ PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
++ },
++ { "PowerBook2,2", "iBook FireWire",
++ PMAC_TYPE_FW_IBOOK, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
++ PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
++ },
++ { "PowerBook3,1", "PowerBook Pismo",
++ PMAC_TYPE_PISMO, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
++ PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
++ },
++ { "PowerBook3,2", "PowerBook Titanium",
++ PMAC_TYPE_TITANIUM, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
++ },
++ { "PowerBook3,3", "PowerBook Titanium II",
++ PMAC_TYPE_TITANIUM2, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
++ },
++ { "PowerBook3,4", "PowerBook Titanium III",
++ PMAC_TYPE_TITANIUM3, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
++ },
++ { "PowerBook3,5", "PowerBook Titanium IV",
++ PMAC_TYPE_TITANIUM4, core99_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
++ },
++ { "PowerBook4,1", "iBook 2",
++ PMAC_TYPE_IBOOK2, pangea_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
++ },
++ { "PowerBook4,2", "iBook 2",
++ PMAC_TYPE_IBOOK2, pangea_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
++ },
++ { "PowerBook4,3", "iBook 2 rev. 2",
++ PMAC_TYPE_IBOOK2, pangea_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
++ },
++ { "PowerBook5,1", "PowerBook G4 17\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook5,2", "PowerBook G4 15\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook5,3", "PowerBook G4 17\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook5,4", "PowerBook G4 15\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook5,5", "PowerBook G4 17\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook5,6", "PowerBook G4 15\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook5,7", "PowerBook G4 17\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook6,1", "PowerBook G4 12\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook6,2", "PowerBook G4",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook6,3", "iBook G4",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook6,4", "PowerBook G4 12\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook6,5", "iBook G4",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook6,7", "iBook G4",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++ { "PowerBook6,8", "PowerBook G4 12\"",
++ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
++ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
++ },
++#else /* CONFIG_POWER4 */
++ { "PowerMac7,2", "PowerMac G5",
++ PMAC_TYPE_POWERMAC_G5, g5_features,
++ 0,
++ },
++#ifdef CONFIG_PPC64
++ { "PowerMac7,3", "PowerMac G5",
++ PMAC_TYPE_POWERMAC_G5, g5_features,
++ 0,
++ },
++ { "PowerMac8,1", "iMac G5",
++ PMAC_TYPE_IMAC_G5, g5_features,
++ 0,
++ },
++ { "PowerMac9,1", "PowerMac G5",
++ PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
++ 0,
++ },
++ { "RackMac3,1", "XServe G5",
++ PMAC_TYPE_XSERVE_G5, g5_features,
++ 0,
++ },
++#endif /* CONFIG_PPC64 */
++#endif /* CONFIG_POWER4 */
++};
++
++/*
++ * The toplevel feature_call callback
++ */
++long pmac_do_feature_call(unsigned int selector, ...)
++{
++ struct device_node *node;
++ long param, value;
++ int i;
++ feature_call func = NULL;
++ va_list args;
++
++ if (pmac_mb.features)
++ for (i=0; pmac_mb.features[i].function; i++)
++ if (pmac_mb.features[i].selector == selector) {
++ func = pmac_mb.features[i].function;
++ break;
++ }
++ if (!func)
++ for (i=0; any_features[i].function; i++)
++ if (any_features[i].selector == selector) {
++ func = any_features[i].function;
++ break;
++ }
++ if (!func)
++ return -ENODEV;
++
++ va_start(args, selector);
++ node = (struct device_node*)va_arg(args, void*);
++ param = va_arg(args, long);
++ value = va_arg(args, long);
++ va_end(args);
++
++ return func(node, param, value);
++}
++
++static int __init probe_motherboard(void)
++{
++ int i;
++ struct macio_chip *macio = &macio_chips[0];
++ const char *model = NULL;
++ struct device_node *dt;
++
++ /* Lookup known motherboard type in device-tree. First try an
++ * exact match on the "model" property, then try a "compatible"
++ * match is none is found.
++ */
++ dt = find_devices("device-tree");
++ if (dt != NULL)
++ model = (const char *) get_property(dt, "model", NULL);
++ for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
++ if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
++ pmac_mb = pmac_mb_defs[i];
++ goto found;
++ }
++ }
++ for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
++ if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
++ pmac_mb = pmac_mb_defs[i];
++ goto found;
++ }
++ }
++
++ /* Fallback to selection depending on mac-io chip type */
++ switch(macio->type) {
++#ifndef CONFIG_POWER4
++ case macio_grand_central:
++ pmac_mb.model_id = PMAC_TYPE_PSURGE;
++ pmac_mb.model_name = "Unknown PowerSurge";
++ break;
++ case macio_ohare:
++ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;
++ pmac_mb.model_name = "Unknown OHare-based";
++ break;
++ case macio_heathrow:
++ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;
++ pmac_mb.model_name = "Unknown Heathrow-based";
++ pmac_mb.features = heathrow_desktop_features;
++ break;
++ case macio_paddington:
++ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;
++ pmac_mb.model_name = "Unknown Paddington-based";
++ pmac_mb.features = paddington_features;
++ break;
++ case macio_keylargo:
++ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;
++ pmac_mb.model_name = "Unknown Keylargo-based";
++ pmac_mb.features = core99_features;
++ break;
++ case macio_pangea:
++ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
++ pmac_mb.model_name = "Unknown Pangea-based";
++ pmac_mb.features = pangea_features;
++ break;
++ case macio_intrepid:
++ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID;
++ pmac_mb.model_name = "Unknown Intrepid-based";
++ pmac_mb.features = intrepid_features;
++ break;
++#else /* CONFIG_POWER4 */
++ case macio_keylargo2:
++ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
++ pmac_mb.model_name = "Unknown K2-based";
++ pmac_mb.features = g5_features;
++ break;
++#endif /* CONFIG_POWER4 */
++ default:
++ return -ENODEV;
++ }
++found:
++#ifndef CONFIG_POWER4
++ /* Fixup Hooper vs. Comet */
++ if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
++ u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
++ if (!mach_id_ptr)
++ return -ENODEV;
++ /* Here, I used to disable the media-bay on comet. It
++ * appears this is wrong, the floppy connector is actually
++ * a kind of media-bay and works with the current driver.
++ */
++ if (__raw_readl(mach_id_ptr) & 0x20000000UL)
++ pmac_mb.model_id = PMAC_TYPE_COMET;
++ iounmap(mach_id_ptr);
++ }
++#endif /* CONFIG_POWER4 */
++
++#ifdef CONFIG_6xx
++ /* Set default value of powersave_nap on machines that support it.
++ * It appears that uninorth rev 3 has a problem with it, we don't
++ * enable it on those. In theory, the flush-on-lock property is
++ * supposed to be set when not supported, but I'm not very confident
++ * that all Apple OF revs did it properly, I do it the paranoid way.
++ */
++ while (uninorth_base && uninorth_rev > 3) {
++ struct device_node *np = find_path_device("/cpus");
++ if (!np || !np->child) {
++ printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
++ break;
++ }
++ np = np->child;
++ /* Nap mode not supported on SMP */
++ if (np->sibling)
++ break;
++ /* Nap mode not supported if flush-on-lock property is present */
++ if (get_property(np, "flush-on-lock", NULL))
++ break;
++ powersave_nap = 1;
++ printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
++ break;
++ }
++
++ /* On CPUs that support it (750FX), lowspeed by default during
++ * NAP mode
++ */
++ powersave_lowspeed = 1;
++#endif /* CONFIG_6xx */
++#ifdef CONFIG_POWER4
++ powersave_nap = 1;
++#endif
++ /* Check for "mobile" machine */
++ if (model && (strncmp(model, "PowerBook", 9) == 0
++ || strncmp(model, "iBook", 5) == 0))
++ pmac_mb.board_flags |= PMAC_MB_MOBILE;
++
++
++ printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
++ return 0;
++}
++
++/* Initialize the Core99 UniNorth host bridge and memory controller
++ */
++static void __init probe_uninorth(void)
++{
++ unsigned long actrl;
++
++ /* Locate core99 Uni-N */
++ uninorth_node = of_find_node_by_name(NULL, "uni-n");
++ /* Locate G5 u3 */
++ if (uninorth_node == NULL) {
++ uninorth_node = of_find_node_by_name(NULL, "u3");
++ uninorth_u3 = 1;
++ }
++ if (uninorth_node && uninorth_node->n_addrs > 0) {
++ unsigned long address = uninorth_node->addrs[0].address;
++ uninorth_base = ioremap(address, 0x40000);
++ uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
++ if (uninorth_u3)
++ u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
++ } else
++ uninorth_node = NULL;
++
++ if (!uninorth_node)
++ return;
++
++ printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",
++ uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);
++ printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
++
++ /* Set the arbitrer QAck delay according to what Apple does
++ */
++ if (uninorth_rev < 0x11) {
++ actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
++ actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
++ UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
++ UN_OUT(UNI_N_ARB_CTRL, actrl);
++ }
++
++ /* Some more magic as done by them in recent MacOS X on UniNorth
++ * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
++ * memory timeout
++ */
++ if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
++ UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
++}
++
++static void __init probe_one_macio(const char *name, const char *compat, int type)
++{
++ struct device_node* node;
++ int i;
++ volatile u32 __iomem * base;
++ u32* revp;
++
++ node = find_devices(name);
++ if (!node || !node->n_addrs)
++ return;
++ if (compat)
++ do {
++ if (device_is_compatible(node, compat))
++ break;
++ node = node->next;
++ } while (node);
++ if (!node)
++ return;
++ for(i=0; i<MAX_MACIO_CHIPS; i++) {
++ if (!macio_chips[i].of_node)
++ break;
++ if (macio_chips[i].of_node == node)
++ return;
++ }
++ if (i >= MAX_MACIO_CHIPS) {
++ printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
++ printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
++ return;
++ }
++ base = ioremap(node->addrs[0].address, node->addrs[0].size);
++ if (!base) {
++ printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
++ return;
++ }
++ if (type == macio_keylargo) {
++ u32 *did = (u32 *)get_property(node, "device-id", NULL);
++ if (*did == 0x00000025)
++ type = macio_pangea;
++ if (*did == 0x0000003e)
++ type = macio_intrepid;
++ }
++ macio_chips[i].of_node = node;
++ macio_chips[i].type = type;
++ macio_chips[i].base = base;
++ macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
++ macio_chips[i].name = macio_names[type];
++ revp = (u32 *)get_property(node, "revision-id", NULL);
++ if (revp)
++ macio_chips[i].rev = *revp;
++ printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
++ macio_names[type], macio_chips[i].rev, macio_chips[i].base);
++}
++
++static int __init
++probe_macios(void)
++{
++ /* Warning, ordering is important */
++ probe_one_macio("gc", NULL, macio_grand_central);
++ probe_one_macio("ohare", NULL, macio_ohare);
++ probe_one_macio("pci106b,7", NULL, macio_ohareII);
++ probe_one_macio("mac-io", "keylargo", macio_keylargo);
++ probe_one_macio("mac-io", "paddington", macio_paddington);
++ probe_one_macio("mac-io", "gatwick", macio_gatwick);
++ probe_one_macio("mac-io", "heathrow", macio_heathrow);
++ probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);
++
++ /* Make sure the "main" macio chip appear first */
++ if (macio_chips[0].type == macio_gatwick
++ && macio_chips[1].type == macio_heathrow) {
++ struct macio_chip temp = macio_chips[0];
++ macio_chips[0] = macio_chips[1];
++ macio_chips[1] = temp;
++ }
++ if (macio_chips[0].type == macio_ohareII
++ && macio_chips[1].type == macio_ohare) {
++ struct macio_chip temp = macio_chips[0];
++ macio_chips[0] = macio_chips[1];
++ macio_chips[1] = temp;
++ }
++ macio_chips[0].lbus.index = 0;
++ macio_chips[1].lbus.index = 1;
++
++ return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
++}
++
++static void __init
++initial_serial_shutdown(struct device_node *np)
++{
++ int len;
++ struct slot_names_prop {
++ int count;
++ char name[1];
++ } *slots;
++ char *conn;
++ int port_type = PMAC_SCC_ASYNC;
++ int modem = 0;
++
++ slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);
++ conn = get_property(np, "AAPL,connector", &len);
++ if (conn && (strcmp(conn, "infrared") == 0))
++ port_type = PMAC_SCC_IRDA;
++ else if (device_is_compatible(np, "cobalt"))
++ modem = 1;
++ else if (slots && slots->count > 0) {
++ if (strcmp(slots->name, "IrDA") == 0)
++ port_type = PMAC_SCC_IRDA;
++ else if (strcmp(slots->name, "Modem") == 0)
++ modem = 1;
++ }
++ if (modem)
++ pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);
++ pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);
++}
++
++static void __init
++set_initial_features(void)
++{
++ struct device_node *np;
++
++ /* That hack appears to be necessary for some StarMax motherboards
++ * but I'm not too sure it was audited for side-effects on other
++ * ohare based machines...
++ * Since I still have difficulties figuring the right way to
++ * differenciate them all and since that hack was there for a long
++ * time, I'll keep it around
++ */
++ if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
++ struct macio_chip *macio = &macio_chips[0];
++ MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
++ } else if (macio_chips[0].type == macio_ohare) {
++ struct macio_chip *macio = &macio_chips[0];
++ MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
++ } else if (macio_chips[1].type == macio_ohare) {
++ struct macio_chip *macio = &macio_chips[1];
++ MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
++ }
++
++#ifdef CONFIG_POWER4
++ if (macio_chips[0].type == macio_keylargo2) {
++#ifndef CONFIG_SMP
++ /* On SMP machines running UP, we have the second CPU eating
++ * bus cycles. We need to take it off the bus. This is done
++ * from pmac_smp for SMP kernels running on one CPU
++ */
++ np = of_find_node_by_type(NULL, "cpu");
++ if (np != NULL)
++ np = of_find_node_by_type(np, "cpu");
++ if (np != NULL) {
++ g5_phy_disable_cpu1();
++ of_node_put(np);
++ }
++#endif /* CONFIG_SMP */
++ /* Enable GMAC for now for PCI probing. It will be disabled
++ * later on after PCI probe
++ */
++ np = of_find_node_by_name(NULL, "ethernet");
++ while(np) {
++ if (device_is_compatible(np, "K2-GMAC"))
++ g5_gmac_enable(np, 0, 1);
++ np = of_find_node_by_name(np, "ethernet");
++ }
++
++ /* Enable FW before PCI probe. Will be disabled later on
++ * Note: We should have a batter way to check that we are
++ * dealing with uninorth internal cell and not a PCI cell
++ * on the external PCI. The code below works though.
++ */
++ np = of_find_node_by_name(NULL, "firewire");
++ while(np) {
++ if (device_is_compatible(np, "pci106b,5811")) {
++ macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
++ g5_fw_enable(np, 0, 1);
++ }
++ np = of_find_node_by_name(np, "firewire");
++ }
++ }
++#else /* CONFIG_POWER4 */
++
++ if (macio_chips[0].type == macio_keylargo ||
++ macio_chips[0].type == macio_pangea ||
++ macio_chips[0].type == macio_intrepid) {
++ /* Enable GMAC for now for PCI probing. It will be disabled
++ * later on after PCI probe
++ */
++ np = of_find_node_by_name(NULL, "ethernet");
++ while(np) {
++ if (np->parent
++ && device_is_compatible(np->parent, "uni-north")
++ && device_is_compatible(np, "gmac"))
++ core99_gmac_enable(np, 0, 1);
++ np = of_find_node_by_name(np, "ethernet");
++ }
++
++ /* Enable FW before PCI probe. Will be disabled later on
++ * Note: We should have a batter way to check that we are
++ * dealing with uninorth internal cell and not a PCI cell
++ * on the external PCI. The code below works though.
++ */
++ np = of_find_node_by_name(NULL, "firewire");
++ while(np) {
++ if (np->parent
++ && device_is_compatible(np->parent, "uni-north")
++ && (device_is_compatible(np, "pci106b,18") ||
++ device_is_compatible(np, "pci106b,30") ||
++ device_is_compatible(np, "pci11c1,5811"))) {
++ macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
++ core99_firewire_enable(np, 0, 1);
++ }
++ np = of_find_node_by_name(np, "firewire");
++ }
++
++ /* Enable ATA-100 before PCI probe. */
++ np = of_find_node_by_name(NULL, "ata-6");
++ while(np) {
++ if (np->parent
++ && device_is_compatible(np->parent, "uni-north")
++ && device_is_compatible(np, "kauai-ata")) {
++ core99_ata100_enable(np, 1);
++ }
++ np = of_find_node_by_name(np, "ata-6");
++ }
++
++ /* Switch airport off */
++ np = find_devices("radio");
++ while(np) {
++ if (np && np->parent == macio_chips[0].of_node) {
++ macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
++ core99_airport_enable(np, 0, 0);
++ }
++ np = np->next;
++ }
++ }
++
++ /* On all machines that support sound PM, switch sound off */
++ if (macio_chips[0].of_node)
++ pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
++ macio_chips[0].of_node, 0, 0);
++
++ /* While on some desktop G3s, we turn it back on */
++ if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
++ && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
++ pmac_mb.model_id == PMAC_TYPE_SILK)) {
++ struct macio_chip *macio = &macio_chips[0];
++ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
++ MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
++ }
++
++ /* Some machine models need the clock chip to be properly setup for
++ * clock spreading now. This should be a platform function but we
++ * don't do these at the moment
++ */
++ pmac_tweak_clock_spreading(1);
++
++#endif /* CONFIG_POWER4 */
++
++ /* On all machines, switch modem & serial ports off */
++ np = find_devices("ch-a");
++ while(np) {
++ initial_serial_shutdown(np);
++ np = np->next;
++ }
++ np = find_devices("ch-b");
++ while(np) {
++ initial_serial_shutdown(np);
++ np = np->next;
++ }
++}
++
++void __init
++pmac_feature_init(void)
++{
++ /* Detect the UniNorth memory controller */
++ probe_uninorth();
++
++ /* Probe mac-io controllers */
++ if (probe_macios()) {
++ printk(KERN_WARNING "No mac-io chip found\n");
++ return;
++ }
++
++ /* Setup low-level i2c stuffs */
++ pmac_init_low_i2c();
++
++ /* Probe machine type */
++ if (probe_motherboard())
++ printk(KERN_WARNING "Unknown PowerMac !\n");
++
++ /* Set some initial features (turn off some chips that will
++ * be later turned on)
++ */
++ set_initial_features();
++}
++
++int __init pmac_feature_late_init(void)
++{
++#if 0
++ struct device_node *np;
++
++ /* Request some resources late */
++ if (uninorth_node)
++ request_OF_resource(uninorth_node, 0, NULL);
++ np = find_devices("hammerhead");
++ if (np)
++ request_OF_resource(np, 0, NULL);
++ np = find_devices("interrupt-controller");
++ if (np)
++ request_OF_resource(np, 0, NULL);
++#endif
++ return 0;
++}
++
++device_initcall(pmac_feature_late_init);
++
++#if 0
++static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
++{
++ int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
++ int bits[8] = { 8,16,0,32,2,4,0,0 };
++ int freq = (frq >> 8) & 0xf;
++
++ if (freqs[freq] == 0)
++ printk("%s: Unknown HT link frequency %x\n", name, freq);
++ else
++ printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",
++ name, freqs[freq],
++ bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
++}
++
++void __init pmac_check_ht_link(void)
++{
++ u32 ufreq, freq, ucfg, cfg;
++ struct device_node *pcix_node;
++ u8 px_bus, px_devfn;
++ struct pci_controller *px_hose;
++
++ (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
++ ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
++ ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
++ dump_HT_speeds("U3 HyperTransport", cfg, freq);
++
++ pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
++ if (pcix_node == NULL) {
++ printk("No PCI-X bridge found\n");
++ return;
++ }
++ if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) {
++ printk("PCI-X bridge found but not matched to pci\n");
++ return;
++ }
++ px_hose = pci_find_hose_for_OF_device(pcix_node);
++ if (px_hose == NULL) {
++ printk("PCI-X bridge found but not matched to host\n");
++ return;
++ }
++ early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
++ early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
++ dump_HT_speeds("PCI-X HT Uplink", cfg, freq);
++ early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
++ early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
++ dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
++}
++#endif /* 0 */
++
++/*
++ * Early video resume hook
++ */
++
++static void (*pmac_early_vresume_proc)(void *data);
++static void *pmac_early_vresume_data;
++
++void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
++{
++ if (_machine != _MACH_Pmac)
++ return;
++ preempt_disable();
++ pmac_early_vresume_proc = proc;
++ pmac_early_vresume_data = data;
++ preempt_enable();
++}
++EXPORT_SYMBOL(pmac_set_early_video_resume);
++
++void pmac_call_early_video_resume(void)
++{
++ if (pmac_early_vresume_proc)
++ pmac_early_vresume_proc(pmac_early_vresume_data);
++}
++
++/*
++ * AGP related suspend/resume code
++ */
++
++static struct pci_dev *pmac_agp_bridge;
++static int (*pmac_agp_suspend)(struct pci_dev *bridge);
++static int (*pmac_agp_resume)(struct pci_dev *bridge);
++
++void pmac_register_agp_pm(struct pci_dev *bridge,
++ int (*suspend)(struct pci_dev *bridge),
++ int (*resume)(struct pci_dev *bridge))
++{
++ if (suspend || resume) {
++ pmac_agp_bridge = bridge;
++ pmac_agp_suspend = suspend;
++ pmac_agp_resume = resume;
++ return;
++ }
++ if (bridge != pmac_agp_bridge)
++ return;
++ pmac_agp_suspend = pmac_agp_resume = NULL;
++ return;
++}
++EXPORT_SYMBOL(pmac_register_agp_pm);
++
++void pmac_suspend_agp_for_card(struct pci_dev *dev)
++{
++ if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
++ return;
++ if (pmac_agp_bridge->bus != dev->bus)
++ return;
++ pmac_agp_suspend(pmac_agp_bridge);
++}
++EXPORT_SYMBOL(pmac_suspend_agp_for_card);
++
++void pmac_resume_agp_for_card(struct pci_dev *dev)
++{
++ if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
++ return;
++ if (pmac_agp_bridge->bus != dev->bus)
++ return;
++ pmac_agp_resume(pmac_agp_bridge);
++}
++EXPORT_SYMBOL(pmac_resume_agp_for_card);
+diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/low_i2c.c
+@@ -0,0 +1,523 @@
++/*
++ * arch/ppc/platforms/pmac_low_i2c.c
++ *
++ * Copyright (C) 2003 Ben. Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * This file contains some low-level i2c access routines that
++ * need to be used by various bits of the PowerMac platform code
++ * at times where the real asynchronous & interrupt driven driver
++ * cannot be used. The API borrows some semantics from the darwin
++ * driver in order to ease the implementation of the platform
++ * properties parser
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++#include <asm/keylargo.h>
++#include <asm/uninorth.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/pmac_low_i2c.h>
++
++#define MAX_LOW_I2C_HOST 4
++
++#ifdef DEBUG
++#define DBG(x...) do {\
++ printk(KERN_DEBUG "KW:" x); \
++ } while(0)
++#else
++#define DBG(x...)
++#endif
++
++struct low_i2c_host;
++
++typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);
++
++struct low_i2c_host
++{
++ struct device_node *np; /* OF device node */
++ struct semaphore mutex; /* Access mutex for use by i2c-keywest */
++ low_i2c_func_t func; /* Access function */
++ unsigned int is_open : 1; /* Poor man's access control */
++ int mode; /* Current mode */
++ int channel; /* Current channel */
++ int num_channels; /* Number of channels */
++ void __iomem *base; /* For keywest-i2c, base address */
++ int bsteps; /* And register stepping */
++ int speed; /* And speed */
++};
++
++static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST];
++
++/* No locking is necessary on allocation, we are running way before
++ * anything can race with us
++ */
++static struct low_i2c_host *find_low_i2c_host(struct device_node *np)
++{
++ int i;
++
++ for (i = 0; i < MAX_LOW_I2C_HOST; i++)
++ if (low_i2c_hosts[i].np == np)
++ return &low_i2c_hosts[i];
++ return NULL;
++}
++
++/*
++ *
++ * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
++ *
++ */
++
++/*
++ * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
++ * should be moved somewhere in include/asm-ppc/
++ */
++/* Register indices */
++typedef enum {
++ reg_mode = 0,
++ reg_control,
++ reg_status,
++ reg_isr,
++ reg_ier,
++ reg_addr,
++ reg_subaddr,
++ reg_data
++} reg_t;
++
++
++/* Mode register */
++#define KW_I2C_MODE_100KHZ 0x00
++#define KW_I2C_MODE_50KHZ 0x01
++#define KW_I2C_MODE_25KHZ 0x02
++#define KW_I2C_MODE_DUMB 0x00
++#define KW_I2C_MODE_STANDARD 0x04
++#define KW_I2C_MODE_STANDARDSUB 0x08
++#define KW_I2C_MODE_COMBINED 0x0C
++#define KW_I2C_MODE_MODE_MASK 0x0C
++#define KW_I2C_MODE_CHAN_MASK 0xF0
++
++/* Control register */
++#define KW_I2C_CTL_AAK 0x01
++#define KW_I2C_CTL_XADDR 0x02
++#define KW_I2C_CTL_STOP 0x04
++#define KW_I2C_CTL_START 0x08
++
++/* Status register */
++#define KW_I2C_STAT_BUSY 0x01
++#define KW_I2C_STAT_LAST_AAK 0x02
++#define KW_I2C_STAT_LAST_RW 0x04
++#define KW_I2C_STAT_SDA 0x08
++#define KW_I2C_STAT_SCL 0x10
++
++/* IER & ISR registers */
++#define KW_I2C_IRQ_DATA 0x01
++#define KW_I2C_IRQ_ADDR 0x02
++#define KW_I2C_IRQ_STOP 0x04
++#define KW_I2C_IRQ_START 0x08
++#define KW_I2C_IRQ_MASK 0x0F
++
++/* State machine states */
++enum {
++ state_idle,
++ state_addr,
++ state_read,
++ state_write,
++ state_stop,
++ state_dead
++};
++
++#define WRONG_STATE(name) do {\
++ printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
++ name, __kw_state_names[state], isr); \
++ } while(0)
++
++static const char *__kw_state_names[] = {
++ "state_idle",
++ "state_addr",
++ "state_read",
++ "state_write",
++ "state_stop",
++ "state_dead"
++};
++
++static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
++{
++ return readb(host->base + (((unsigned int)reg) << host->bsteps));
++}
++
++static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
++{
++ writeb(val, host->base + (((unsigned)reg) << host->bsteps));
++ (void)__kw_read_reg(host, reg_subaddr);
++}
++
++#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
++#define kw_read_reg(reg) __kw_read_reg(host, reg)
++
++
++/* Don't schedule, the g5 fan controller is too
++ * timing sensitive
++ */
++static u8 kw_wait_interrupt(struct low_i2c_host* host)
++{
++ int i, j;
++ u8 isr;
++
++ for (i = 0; i < 100000; i++) {
++ isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
++ if (isr != 0)
++ return isr;
++
++ /* This code is used with the timebase frozen, we cannot rely
++ * on udelay ! For now, just use a bogus loop
++ */
++ for (j = 1; j < 10000; j++)
++ mb();
++ }
++ return isr;
++}
++
++static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)
++{
++ u8 ack;
++
++ DBG("kw_handle_interrupt(%s, isr: %x)\n", __kw_state_names[state], isr);
++
++ if (isr == 0) {
++ if (state != state_stop) {
++ DBG("KW: Timeout !\n");
++ *rc = -EIO;
++ goto stop;
++ }
++ if (state == state_stop) {
++ ack = kw_read_reg(reg_status);
++ if (!(ack & KW_I2C_STAT_BUSY)) {
++ state = state_idle;
++ kw_write_reg(reg_ier, 0x00);
++ }
++ }
++ return state;
++ }
++
++ if (isr & KW_I2C_IRQ_ADDR) {
++ ack = kw_read_reg(reg_status);
++ if (state != state_addr) {
++ kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
++ WRONG_STATE("KW_I2C_IRQ_ADDR");
++ *rc = -EIO;
++ goto stop;
++ }
++ if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
++ *rc = -ENODEV;
++ DBG("KW: NAK on address\n");
++ return state_stop;
++ } else {
++ if (rw) {
++ state = state_read;
++ if (*len > 1)
++ kw_write_reg(reg_control, KW_I2C_CTL_AAK);
++ } else {
++ state = state_write;
++ kw_write_reg(reg_data, **data);
++ (*data)++; (*len)--;
++ }
++ }
++ kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
++ }
++
++ if (isr & KW_I2C_IRQ_DATA) {
++ if (state == state_read) {
++ **data = kw_read_reg(reg_data);
++ (*data)++; (*len)--;
++ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
++ if ((*len) == 0)
++ state = state_stop;
++ else if ((*len) == 1)
++ kw_write_reg(reg_control, 0);
++ } else if (state == state_write) {
++ ack = kw_read_reg(reg_status);
++ if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
++ DBG("KW: nack on data write\n");
++ *rc = -EIO;
++ goto stop;
++ } else if (*len) {
++ kw_write_reg(reg_data, **data);
++ (*data)++; (*len)--;
++ } else {
++ kw_write_reg(reg_control, KW_I2C_CTL_STOP);
++ state = state_stop;
++ *rc = 0;
++ }
++ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
++ } else {
++ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
++ WRONG_STATE("KW_I2C_IRQ_DATA");
++ if (state != state_stop) {
++ *rc = -EIO;
++ goto stop;
++ }
++ }
++ }
++
++ if (isr & KW_I2C_IRQ_STOP) {
++ kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
++ if (state != state_stop) {
++ WRONG_STATE("KW_I2C_IRQ_STOP");
++ *rc = -EIO;
++ }
++ return state_idle;
++ }
++
++ if (isr & KW_I2C_IRQ_START)
++ kw_write_reg(reg_isr, KW_I2C_IRQ_START);
++
++ return state;
++
++ stop:
++ kw_write_reg(reg_control, KW_I2C_CTL_STOP);
++ return state_stop;
++}
++
++static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)
++{
++ u8 mode_reg = host->speed;
++ int state = state_addr;
++ int rc = 0;
++
++ /* Setup mode & subaddress if any */
++ switch(host->mode) {
++ case pmac_low_i2c_mode_dumb:
++ printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");
++ return -EINVAL;
++ case pmac_low_i2c_mode_std:
++ mode_reg |= KW_I2C_MODE_STANDARD;
++ break;
++ case pmac_low_i2c_mode_stdsub:
++ mode_reg |= KW_I2C_MODE_STANDARDSUB;
++ break;
++ case pmac_low_i2c_mode_combined:
++ mode_reg |= KW_I2C_MODE_COMBINED;
++ break;
++ }
++
++ /* Setup channel & clear pending irqs */
++ kw_write_reg(reg_isr, kw_read_reg(reg_isr));
++ kw_write_reg(reg_mode, mode_reg | (host->channel << 4));
++ kw_write_reg(reg_status, 0);
++
++ /* Set up address and r/w bit */
++ kw_write_reg(reg_addr, addr);
++
++ /* Set up the sub address */
++ if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
++ || (mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
++ kw_write_reg(reg_subaddr, subaddr);
++
++ /* Start sending address & disable interrupt*/
++ kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
++ kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
++
++ /* State machine, to turn into an interrupt handler */
++ while(state != state_idle) {
++ u8 isr = kw_wait_interrupt(host);
++ state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);
++ }
++
++ return rc;
++}
++
++static void keywest_low_i2c_add(struct device_node *np)
++{
++ struct low_i2c_host *host = find_low_i2c_host(NULL);
++ u32 *psteps, *prate, steps, aoffset = 0;
++ struct device_node *parent;
++
++ if (host == NULL) {
++ printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
++ np->full_name);
++ return;
++ }
++ memset(host, 0, sizeof(*host));
++
++ init_MUTEX(&host->mutex);
++ host->np = of_node_get(np);
++ psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
++ steps = psteps ? (*psteps) : 0x10;
++ for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
++ steps >>= 1;
++ parent = of_get_parent(np);
++ host->num_channels = 1;
++ if (parent && parent->name[0] == 'u') {
++ host->num_channels = 2;
++ aoffset = 3;
++ }
++ /* Select interface rate */
++ host->speed = KW_I2C_MODE_100KHZ;
++ prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
++ if (prate) switch(*prate) {
++ case 100:
++ host->speed = KW_I2C_MODE_100KHZ;
++ break;
++ case 50:
++ host->speed = KW_I2C_MODE_50KHZ;
++ break;
++ case 25:
++ host->speed = KW_I2C_MODE_25KHZ;
++ break;
++ }
++
++ host->mode = pmac_low_i2c_mode_std;
++ host->base = ioremap(np->addrs[0].address + aoffset,
++ np->addrs[0].size);
++ host->func = keywest_low_i2c_func;
++}
++
++/*
++ *
++ * PMU implementation
++ *
++ */
++
++
++#ifdef CONFIG_ADB_PMU
++
++static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)
++{
++ // TODO
++ return -ENODEV;
++}
++
++static void pmu_low_i2c_add(struct device_node *np)
++{
++ struct low_i2c_host *host = find_low_i2c_host(NULL);
++
++ if (host == NULL) {
++ printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
++ np->full_name);
++ return;
++ }
++ memset(host, 0, sizeof(*host));
++
++ init_MUTEX(&host->mutex);
++ host->np = of_node_get(np);
++ host->num_channels = 3;
++ host->mode = pmac_low_i2c_mode_std;
++ host->func = pmu_low_i2c_func;
++}
++
++#endif /* CONFIG_ADB_PMU */
++
++void __init pmac_init_low_i2c(void)
++{
++ struct device_node *np;
++
++ /* Probe keywest-i2c busses */
++ np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");
++ while(np) {
++ keywest_low_i2c_add(np);
++ np = of_find_compatible_node(np, "i2c", "keywest-i2c");
++ }
++
++#ifdef CONFIG_ADB_PMU
++ /* Probe PMU busses */
++ np = of_find_node_by_name(NULL, "via-pmu");
++ if (np)
++ pmu_low_i2c_add(np);
++#endif /* CONFIG_ADB_PMU */
++
++ /* TODO: Add CUDA support as well */
++}
++
++int pmac_low_i2c_lock(struct device_node *np)
++{
++ struct low_i2c_host *host = find_low_i2c_host(np);
++
++ if (!host)
++ return -ENODEV;
++ down(&host->mutex);
++ return 0;
++}
++EXPORT_SYMBOL(pmac_low_i2c_lock);
++
++int pmac_low_i2c_unlock(struct device_node *np)
++{
++ struct low_i2c_host *host = find_low_i2c_host(np);
++
++ if (!host)
++ return -ENODEV;
++ up(&host->mutex);
++ return 0;
++}
++EXPORT_SYMBOL(pmac_low_i2c_unlock);
++
++
++int pmac_low_i2c_open(struct device_node *np, int channel)
++{
++ struct low_i2c_host *host = find_low_i2c_host(np);
++
++ if (!host)
++ return -ENODEV;
++
++ if (channel >= host->num_channels)
++ return -EINVAL;
++
++ down(&host->mutex);
++ host->is_open = 1;
++ host->channel = channel;
++
++ return 0;
++}
++EXPORT_SYMBOL(pmac_low_i2c_open);
++
++int pmac_low_i2c_close(struct device_node *np)
++{
++ struct low_i2c_host *host = find_low_i2c_host(np);
++
++ if (!host)
++ return -ENODEV;
++
++ host->is_open = 0;
++ up(&host->mutex);
++
++ return 0;
++}
++EXPORT_SYMBOL(pmac_low_i2c_close);
++
++int pmac_low_i2c_setmode(struct device_node *np, int mode)
++{
++ struct low_i2c_host *host = find_low_i2c_host(np);
++
++ if (!host)
++ return -ENODEV;
++ WARN_ON(!host->is_open);
++ host->mode = mode;
++
++ return 0;
++}
++EXPORT_SYMBOL(pmac_low_i2c_setmode);
++
++int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)
++{
++ struct low_i2c_host *host = find_low_i2c_host(np);
++
++ if (!host)
++ return -ENODEV;
++ WARN_ON(!host->is_open);
++
++ return host->func(host, addrdir, subaddr, data, len);
++}
++EXPORT_SYMBOL(pmac_low_i2c_xfer);
++
+diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/nvram.c
+@@ -0,0 +1,645 @@
++/*
++ * arch/ppc/platforms/pmac_nvram.c
++ *
++ * Copyright (C) 2002 Benjamin Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * Todo: - add support for the OF persistent properties
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/stddef.h>
++#include <linux/string.h>
++#include <linux/nvram.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++#include <linux/bootmem.h>
++#include <linux/completion.h>
++#include <linux/spinlock.h>
++#include <asm/sections.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/nvram.h>
++
++#define DEBUG
++
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
++
++#define CORE99_SIGNATURE 0x5a
++#define CORE99_ADLER_START 0x14
++
++/* On Core99, nvram is either a sharp, a micron or an AMD flash */
++#define SM_FLASH_STATUS_DONE 0x80
++#define SM_FLASH_STATUS_ERR 0x38
++
++#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0
++#define SM_FLASH_CMD_ERASE_SETUP 0x20
++#define SM_FLASH_CMD_RESET 0xff
++#define SM_FLASH_CMD_WRITE_SETUP 0x40
++#define SM_FLASH_CMD_CLEAR_STATUS 0x50
++#define SM_FLASH_CMD_READ_STATUS 0x70
++
++/* CHRP NVRAM header */
++struct chrp_header {
++ u8 signature;
++ u8 cksum;
++ u16 len;
++ char name[12];
++ u8 data[0];
++};
++
++struct core99_header {
++ struct chrp_header hdr;
++ u32 adler;
++ u32 generation;
++ u32 reserved[2];
++};
++
++/*
++ * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
++ */
++static int nvram_naddrs;
++static volatile unsigned char *nvram_data;
++static int is_core_99;
++static int core99_bank = 0;
++static int nvram_partitions[3];
++// XXX Turn that into a sem
++static DEFINE_SPINLOCK(nv_lock);
++
++extern int pmac_newworld;
++extern int system_running;
++
++static int (*core99_write_bank)(int bank, u8* datas);
++static int (*core99_erase_bank)(int bank);
++
++static char *nvram_image;
++
++
++static unsigned char core99_nvram_read_byte(int addr)
++{
++ if (nvram_image == NULL)
++ return 0xff;
++ return nvram_image[addr];
++}
++
++static void core99_nvram_write_byte(int addr, unsigned char val)
++{
++ if (nvram_image == NULL)
++ return;
++ nvram_image[addr] = val;
++}
++
++static ssize_t core99_nvram_read(char *buf, size_t count, loff_t *index)
++{
++ int i;
++
++ if (nvram_image == NULL)
++ return -ENODEV;
++ if (*index > NVRAM_SIZE)
++ return 0;
++
++ i = *index;
++ if (i + count > NVRAM_SIZE)
++ count = NVRAM_SIZE - i;
++
++ memcpy(buf, &nvram_image[i], count);
++ *index = i + count;
++ return count;
++}
++
++static ssize_t core99_nvram_write(char *buf, size_t count, loff_t *index)
++{
++ int i;
++
++ if (nvram_image == NULL)
++ return -ENODEV;
++ if (*index > NVRAM_SIZE)
++ return 0;
++
++ i = *index;
++ if (i + count > NVRAM_SIZE)
++ count = NVRAM_SIZE - i;
++
++ memcpy(&nvram_image[i], buf, count);
++ *index = i + count;
++ return count;
++}
++
++static ssize_t core99_nvram_size(void)
++{
++ if (nvram_image == NULL)
++ return -ENODEV;
++ return NVRAM_SIZE;
++}
++
++#ifdef CONFIG_PPC32
++static volatile unsigned char *nvram_addr;
++static int nvram_mult;
++
++static unsigned char direct_nvram_read_byte(int addr)
++{
++ return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
++}
++
++static void direct_nvram_write_byte(int addr, unsigned char val)
++{
++ out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
++}
++
++
++static unsigned char indirect_nvram_read_byte(int addr)
++{
++ unsigned char val;
++ unsigned long flags;
++
++ spin_lock_irqsave(&nv_lock, flags);
++ out_8(nvram_addr, addr >> 5);
++ val = in_8(&nvram_data[(addr & 0x1f) << 4]);
++ spin_unlock_irqrestore(&nv_lock, flags);
++
++ return val;
++}
++
++static void indirect_nvram_write_byte(int addr, unsigned char val)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&nv_lock, flags);
++ out_8(nvram_addr, addr >> 5);
++ out_8(&nvram_data[(addr & 0x1f) << 4], val);
++ spin_unlock_irqrestore(&nv_lock, flags);
++}
++
++
++#ifdef CONFIG_ADB_PMU
++
++static void pmu_nvram_complete(struct adb_request *req)
++{
++ if (req->arg)
++ complete((struct completion *)req->arg);
++}
++
++static unsigned char pmu_nvram_read_byte(int addr)
++{
++ struct adb_request req;
++ DECLARE_COMPLETION(req_complete);
++
++ req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
++ if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
++ (addr >> 8) & 0xff, addr & 0xff))
++ return 0xff;
++ if (system_state == SYSTEM_RUNNING)
++ wait_for_completion(&req_complete);
++ while (!req.complete)
++ pmu_poll();
++ return req.reply[0];
++}
++
++static void pmu_nvram_write_byte(int addr, unsigned char val)
++{
++ struct adb_request req;
++ DECLARE_COMPLETION(req_complete);
++
++ req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
++ if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
++ (addr >> 8) & 0xff, addr & 0xff, val))
++ return;
++ if (system_state == SYSTEM_RUNNING)
++ wait_for_completion(&req_complete);
++ while (!req.complete)
++ pmu_poll();
++}
++
++#endif /* CONFIG_ADB_PMU */
++#endif /* CONFIG_PPC32 */
++
++static u8 chrp_checksum(struct chrp_header* hdr)
++{
++ u8 *ptr;
++ u16 sum = hdr->signature;
++ for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
++ sum += *ptr;
++ while (sum > 0xFF)
++ sum = (sum & 0xFF) + (sum>>8);
++ return sum;
++}
++
++static u32 core99_calc_adler(u8 *buffer)
++{
++ int cnt;
++ u32 low, high;
++
++ buffer += CORE99_ADLER_START;
++ low = 1;
++ high = 0;
++ for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
++ if ((cnt % 5000) == 0) {
++ high %= 65521UL;
++ high %= 65521UL;
++ }
++ low += buffer[cnt];
++ high += low;
++ }
++ low %= 65521UL;
++ high %= 65521UL;
++
++ return (high << 16) | low;
++}
++
++static u32 core99_check(u8* datas)
++{
++ struct core99_header* hdr99 = (struct core99_header*)datas;
++
++ if (hdr99->hdr.signature != CORE99_SIGNATURE) {
++ DBG("Invalid signature\n");
++ return 0;
++ }
++ if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
++ DBG("Invalid checksum\n");
++ return 0;
++ }
++ if (hdr99->adler != core99_calc_adler(datas)) {
++ DBG("Invalid adler\n");
++ return 0;
++ }
++ return hdr99->generation;
++}
++
++static int sm_erase_bank(int bank)
++{
++ int stat, i;
++ unsigned long timeout;
++
++ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
++
++ DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
++
++ out_8(base, SM_FLASH_CMD_ERASE_SETUP);
++ out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
++ timeout = 0;
++ do {
++ if (++timeout > 1000000) {
++ printk(KERN_ERR "nvram: Sharp/Micron flash erase timeout !\n");
++ break;
++ }
++ out_8(base, SM_FLASH_CMD_READ_STATUS);
++ stat = in_8(base);
++ } while (!(stat & SM_FLASH_STATUS_DONE));
++
++ out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
++ out_8(base, SM_FLASH_CMD_RESET);
++
++ for (i=0; i<NVRAM_SIZE; i++)
++ if (base[i] != 0xff) {
++ printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
++ return -ENXIO;
++ }
++ return 0;
++}
++
++static int sm_write_bank(int bank, u8* datas)
++{
++ int i, stat = 0;
++ unsigned long timeout;
++
++ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
++
++ DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
++
++ for (i=0; i<NVRAM_SIZE; i++) {
++ out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
++ udelay(1);
++ out_8(base+i, datas[i]);
++ timeout = 0;
++ do {
++ if (++timeout > 1000000) {
++ printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
++ break;
++ }
++ out_8(base, SM_FLASH_CMD_READ_STATUS);
++ stat = in_8(base);
++ } while (!(stat & SM_FLASH_STATUS_DONE));
++ if (!(stat & SM_FLASH_STATUS_DONE))
++ break;
++ }
++ out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
++ out_8(base, SM_FLASH_CMD_RESET);
++ for (i=0; i<NVRAM_SIZE; i++)
++ if (base[i] != datas[i]) {
++ printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
++ return -ENXIO;
++ }
++ return 0;
++}
++
++static int amd_erase_bank(int bank)
++{
++ int i, stat = 0;
++ unsigned long timeout;
++
++ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
++
++ DBG("nvram: AMD Erasing bank %d...\n", bank);
++
++ /* Unlock 1 */
++ out_8(base+0x555, 0xaa);
++ udelay(1);
++ /* Unlock 2 */
++ out_8(base+0x2aa, 0x55);
++ udelay(1);
++
++ /* Sector-Erase */
++ out_8(base+0x555, 0x80);
++ udelay(1);
++ out_8(base+0x555, 0xaa);
++ udelay(1);
++ out_8(base+0x2aa, 0x55);
++ udelay(1);
++ out_8(base, 0x30);
++ udelay(1);
++
++ timeout = 0;
++ do {
++ if (++timeout > 1000000) {
++ printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
++ break;
++ }
++ stat = in_8(base) ^ in_8(base);
++ } while (stat != 0);
++
++ /* Reset */
++ out_8(base, 0xf0);
++ udelay(1);
++
++ for (i=0; i<NVRAM_SIZE; i++)
++ if (base[i] != 0xff) {
++ printk(KERN_ERR "nvram: AMD flash erase failed !\n");
++ return -ENXIO;
++ }
++ return 0;
++}
++
++static int amd_write_bank(int bank, u8* datas)
++{
++ int i, stat = 0;
++ unsigned long timeout;
++
++ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
++
++ DBG("nvram: AMD Writing bank %d...\n", bank);
++
++ for (i=0; i<NVRAM_SIZE; i++) {
++ /* Unlock 1 */
++ out_8(base+0x555, 0xaa);
++ udelay(1);
++ /* Unlock 2 */
++ out_8(base+0x2aa, 0x55);
++ udelay(1);
++
++ /* Write single word */
++ out_8(base+0x555, 0xa0);
++ udelay(1);
++ out_8(base+i, datas[i]);
++
++ timeout = 0;
++ do {
++ if (++timeout > 1000000) {
++ printk(KERN_ERR "nvram: AMD flash write timeout !\n");
++ break;
++ }
++ stat = in_8(base) ^ in_8(base);
++ } while (stat != 0);
++ if (stat != 0)
++ break;
++ }
++
++ /* Reset */
++ out_8(base, 0xf0);
++ udelay(1);
++
++ for (i=0; i<NVRAM_SIZE; i++)
++ if (base[i] != datas[i]) {
++ printk(KERN_ERR "nvram: AMD flash write failed !\n");
++ return -ENXIO;
++ }
++ return 0;
++}
++
++static void __init lookup_partitions(void)
++{
++ u8 buffer[17];
++ int i, offset;
++ struct chrp_header* hdr;
++
++ if (pmac_newworld) {
++ nvram_partitions[pmac_nvram_OF] = -1;
++ nvram_partitions[pmac_nvram_XPRAM] = -1;
++ nvram_partitions[pmac_nvram_NR] = -1;
++ hdr = (struct chrp_header *)buffer;
++
++ offset = 0;
++ buffer[16] = 0;
++ do {
++ for (i=0;i<16;i++)
++ buffer[i] = ppc_md.nvram_read_val(offset+i);
++ if (!strcmp(hdr->name, "common"))
++ nvram_partitions[pmac_nvram_OF] = offset + 0x10;
++ if (!strcmp(hdr->name, "APL,MacOS75")) {
++ nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
++ nvram_partitions[pmac_nvram_NR] = offset + 0x110;
++ }
++ offset += (hdr->len * 0x10);
++ } while(offset < NVRAM_SIZE);
++ } else {
++ nvram_partitions[pmac_nvram_OF] = 0x1800;
++ nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
++ nvram_partitions[pmac_nvram_NR] = 0x1400;
++ }
++ DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
++ DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
++ DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
++}
++
++static void core99_nvram_sync(void)
++{
++ struct core99_header* hdr99;
++ unsigned long flags;
++
++ if (!is_core_99 || !nvram_data || !nvram_image)
++ return;
++
++ spin_lock_irqsave(&nv_lock, flags);
++ if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
++ NVRAM_SIZE))
++ goto bail;
++
++ DBG("Updating nvram...\n");
++
++ hdr99 = (struct core99_header*)nvram_image;
++ hdr99->generation++;
++ hdr99->hdr.signature = CORE99_SIGNATURE;
++ hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
++ hdr99->adler = core99_calc_adler(nvram_image);
++ core99_bank = core99_bank ? 0 : 1;
++ if (core99_erase_bank)
++ if (core99_erase_bank(core99_bank)) {
++ printk("nvram: Error erasing bank %d\n", core99_bank);
++ goto bail;
++ }
++ if (core99_write_bank)
++ if (core99_write_bank(core99_bank, nvram_image))
++ printk("nvram: Error writing bank %d\n", core99_bank);
++ bail:
++ spin_unlock_irqrestore(&nv_lock, flags);
++
++#ifdef DEBUG
++ mdelay(2000);
++#endif
++}
++
++static int __init core99_nvram_setup(struct device_node *dp)
++{
++ int i;
++ u32 gen_bank0, gen_bank1;
++
++ if (nvram_naddrs < 1) {
++ printk(KERN_ERR "nvram: no address\n");
++ return -EINVAL;
++ }
++ nvram_image = alloc_bootmem(NVRAM_SIZE);
++ if (nvram_image == NULL) {
++ printk(KERN_ERR "nvram: can't allocate ram image\n");
++ return -ENOMEM;
++ }
++ nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
++ nvram_naddrs = 1; /* Make sure we get the correct case */
++
++ DBG("nvram: Checking bank 0...\n");
++
++ gen_bank0 = core99_check((u8 *)nvram_data);
++ gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
++ core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
++
++ DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
++ DBG("nvram: Active bank is: %d\n", core99_bank);
++
++ for (i=0; i<NVRAM_SIZE; i++)
++ nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
++
++ ppc_md.nvram_read_val = core99_nvram_read_byte;
++ ppc_md.nvram_write_val = core99_nvram_write_byte;
++ ppc_md.nvram_read = core99_nvram_read;
++ ppc_md.nvram_write = core99_nvram_write;
++ ppc_md.nvram_size = core99_nvram_size;
++ ppc_md.nvram_sync = core99_nvram_sync;
++ /*
++ * Maybe we could be smarter here though making an exclusive list
++ * of known flash chips is a bit nasty as older OF didn't provide us
++ * with a useful "compatible" entry. A solution would be to really
++ * identify the chip using flash id commands and base ourselves on
++ * a list of known chips IDs
++ */
++ if (device_is_compatible(dp, "amd-0137")) {
++ core99_erase_bank = amd_erase_bank;
++ core99_write_bank = amd_write_bank;
++ } else {
++ core99_erase_bank = sm_erase_bank;
++ core99_write_bank = sm_write_bank;
++ }
++ return 0;
++}
++
++int __init pmac_nvram_init(void)
++{
++ struct device_node *dp;
++ int err = 0;
++
++ nvram_naddrs = 0;
++
++ dp = find_devices("nvram");
++ if (dp == NULL) {
++ printk(KERN_ERR "Can't find NVRAM device\n");
++ return -ENODEV;
++ }
++ nvram_naddrs = dp->n_addrs;
++ is_core_99 = device_is_compatible(dp, "nvram,flash");
++ if (is_core_99)
++ err = core99_nvram_setup(dp);
++#ifdef CONFIG_PPC32
++ else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
++ nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
++ dp->addrs[0].size);
++ nvram_mult = 1;
++ ppc_md.nvram_read_val = direct_nvram_read_byte;
++ ppc_md.nvram_write_val = direct_nvram_write_byte;
++ } else if (nvram_naddrs == 1) {
++ nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
++ nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
++ ppc_md.nvram_read_val = direct_nvram_read_byte;
++ ppc_md.nvram_write_val = direct_nvram_write_byte;
++ } else if (nvram_naddrs == 2) {
++ nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
++ nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
++ ppc_md.nvram_read_val = indirect_nvram_read_byte;
++ ppc_md.nvram_write_val = indirect_nvram_write_byte;
++ } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
++#ifdef CONFIG_ADB_PMU
++ nvram_naddrs = -1;
++ ppc_md.nvram_read_val = pmu_nvram_read_byte;
++ ppc_md.nvram_write_val = pmu_nvram_write_byte;
++#endif /* CONFIG_ADB_PMU */
++ }
++#endif
++ else {
++ printk(KERN_ERR "Incompatible type of NVRAM\n");
++ return -ENXIO;
++ }
++ lookup_partitions();
++ return err;
++}
++
++int pmac_get_partition(int partition)
++{
++ return nvram_partitions[partition];
++}
++
++u8 pmac_xpram_read(int xpaddr)
++{
++ int offset = pmac_get_partition(pmac_nvram_XPRAM);
++
++ if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
++ return 0xff;
++
++ return ppc_md.nvram_read_val(xpaddr + offset);
++}
++
++void pmac_xpram_write(int xpaddr, u8 data)
++{
++ int offset = pmac_get_partition(pmac_nvram_XPRAM);
++
++ if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
++ return;
++
++ ppc_md.nvram_write_val(xpaddr + offset, data);
++}
++
++EXPORT_SYMBOL(pmac_get_partition);
++EXPORT_SYMBOL(pmac_xpram_read);
++EXPORT_SYMBOL(pmac_xpram_write);
+diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/pci.c
+@@ -0,0 +1,1170 @@
++/*
++ * Support for PCI bridges found on Power Macintoshes.
++ *
++ * Copyright (C) 2003 Benjamin Herrenschmuidt (benh at kernel.crashing.org)
++ * Copyright (C) 1997 Paul Mackerras (paulus at samba.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/kernel.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++
++#include <asm/sections.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/machdep.h>
++#include <asm/pmac_feature.h>
++#include <asm/grackle.h>
++#ifdef CONFIG_PPC64
++#include <asm/iommu.h>
++#include <asm/ppc-pci.h>
++#endif
++
++#undef DEBUG
++
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++static int add_bridge(struct device_node *dev);
++
++/* XXX Could be per-controller, but I don't think we risk anything by
++ * assuming we won't have both UniNorth and Bandit */
++static int has_uninorth;
++#ifdef CONFIG_PPC64
++static struct pci_controller *u3_agp;
++static struct pci_controller *u3_ht;
++#endif /* CONFIG_PPC64 */
++
++extern u8 pci_cache_line_size;
++extern int pcibios_assign_bus_offset;
++
++struct device_node *k2_skiplist[2];
++
++/*
++ * Magic constants for enabling cache coherency in the bandit/PSX bridge.
++ */
++#define BANDIT_DEVID_2 8
++#define BANDIT_REVID 3
++
++#define BANDIT_DEVNUM 11
++#define BANDIT_MAGIC 0x50
++#define BANDIT_COHERENT 0x40
++
++static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
++{
++ for (; node != 0;node = node->sibling) {
++ int * bus_range;
++ unsigned int *class_code;
++ int len;
++
++ /* For PCI<->PCI bridges or CardBus bridges, we go down */
++ class_code = (unsigned int *) get_property(node, "class-code", NULL);
++ if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
++ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
++ continue;
++ bus_range = (int *) get_property(node, "bus-range", &len);
++ if (bus_range != NULL && len > 2 * sizeof(int)) {
++ if (bus_range[1] > higher)
++ higher = bus_range[1];
++ }
++ higher = fixup_one_level_bus_range(node->child, higher);
++ }
++ return higher;
++}
++
++/* This routine fixes the "bus-range" property of all bridges in the
++ * system since they tend to have their "last" member wrong on macs
++ *
++ * Note that the bus numbers manipulated here are OF bus numbers, they
++ * are not Linux bus numbers.
++ */
++static void __init fixup_bus_range(struct device_node *bridge)
++{
++ int * bus_range;
++ int len;
++
++ /* Lookup the "bus-range" property for the hose */
++ bus_range = (int *) get_property(bridge, "bus-range", &len);
++ if (bus_range == NULL || len < 2 * sizeof(int)) {
++ printk(KERN_WARNING "Can't get bus-range for %s\n",
++ bridge->full_name);
++ return;
++ }
++ bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
++}
++
++/*
++ * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers.
++ *
++ * The "Bandit" version is present in all early PCI PowerMacs,
++ * and up to the first ones using Grackle. Some machines may
++ * have 2 bandit controllers (2 PCI busses).
++ *
++ * "Chaos" is used in some "Bandit"-type machines as a bridge
++ * for the separate display bus. It is accessed the same
++ * way as bandit, but cannot be probed for devices. It therefore
++ * has its own config access functions.
++ *
++ * The "UniNorth" version is present in all Core99 machines
++ * (iBook, G4, new IMacs, and all the recent Apple machines).
++ * It contains 3 controllers in one ASIC.
++ *
++ * The U3 is the bridge used on G5 machines. It contains an
++ * AGP bus which is dealt with the old UniNorth access routines
++ * and a HyperTransport bus which uses its own set of access
++ * functions.
++ */
++
++#define MACRISC_CFA0(devfn, off) \
++ ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
++ | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
++ | (((unsigned long)(off)) & 0xFCUL))
++
++#define MACRISC_CFA1(bus, devfn, off) \
++ ((((unsigned long)(bus)) << 16) \
++ |(((unsigned long)(devfn)) << 8) \
++ |(((unsigned long)(off)) & 0xFCUL) \
++ |1UL)
++
++static unsigned long macrisc_cfg_access(struct pci_controller* hose,
++ u8 bus, u8 dev_fn, u8 offset)
++{
++ unsigned int caddr;
++
++ if (bus == hose->first_busno) {
++ if (dev_fn < (11 << 3))
++ return 0;
++ caddr = MACRISC_CFA0(dev_fn, offset);
++ } else
++ caddr = MACRISC_CFA1(bus, dev_fn, offset);
++
++ /* Uninorth will return garbage if we don't read back the value ! */
++ do {
++ out_le32(hose->cfg_addr, caddr);
++ } while (in_le32(hose->cfg_addr) != caddr);
++
++ offset &= has_uninorth ? 0x07 : 0x03;
++ return ((unsigned long)hose->cfg_data) + offset;
++}
++
++static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 *val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ *val = in_8((u8 *)addr);
++ break;
++ case 2:
++ *val = in_le16((u16 *)addr);
++ break;
++ default:
++ *val = in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ out_8((u8 *)addr, val);
++ (void) in_8((u8 *)addr);
++ break;
++ case 2:
++ out_le16((u16 *)addr, val);
++ (void) in_le16((u16 *)addr);
++ break;
++ default:
++ out_le32((u32 *)addr, val);
++ (void) in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops macrisc_pci_ops =
++{
++ macrisc_read_config,
++ macrisc_write_config
++};
++
++#ifdef CONFIG_PPC32
++/*
++ * Verify that a specific (bus, dev_fn) exists on chaos
++ */
++static int
++chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
++{
++ struct device_node *np;
++ u32 *vendor, *device;
++
++ np = pci_busdev_to_OF_node(bus, devfn);
++ if (np == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ vendor = (u32 *)get_property(np, "vendor-id", NULL);
++ device = (u32 *)get_property(np, "device-id", NULL);
++ if (vendor == NULL || device == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10)
++ && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24))
++ return PCIBIOS_BAD_REGISTER_NUMBER;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int
++chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
++ int len, u32 *val)
++{
++ int result = chaos_validate_dev(bus, devfn, offset);
++ if (result == PCIBIOS_BAD_REGISTER_NUMBER)
++ *val = ~0U;
++ if (result != PCIBIOS_SUCCESSFUL)
++ return result;
++ return macrisc_read_config(bus, devfn, offset, len, val);
++}
++
++static int
++chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
++ int len, u32 val)
++{
++ int result = chaos_validate_dev(bus, devfn, offset);
++ if (result != PCIBIOS_SUCCESSFUL)
++ return result;
++ return macrisc_write_config(bus, devfn, offset, len, val);
++}
++
++static struct pci_ops chaos_pci_ops =
++{
++ chaos_read_config,
++ chaos_write_config
++};
++
++static void __init setup_chaos(struct pci_controller *hose,
++ struct reg_property *addr)
++{
++ /* assume a `chaos' bridge */
++ hose->ops = &chaos_pci_ops;
++ hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
++ hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
++}
++#else
++#define setup_chaos(hose, addr)
++#endif /* CONFIG_PPC32 */
++
++#ifdef CONFIG_PPC64
++/*
++ * These versions of U3 HyperTransport config space access ops do not
++ * implement self-view of the HT host yet
++ */
++
++/*
++ * This function deals with some "special cases" devices.
++ *
++ * 0 -> No special case
++ * 1 -> Skip the device but act as if the access was successfull
++ * (return 0xff's on reads, eventually, cache config space
++ * accesses in a later version)
++ * -1 -> Hide the device (unsuccessful acess)
++ */
++static int u3_ht_skip_device(struct pci_controller *hose,
++ struct pci_bus *bus, unsigned int devfn)
++{
++ struct device_node *busdn, *dn;
++ int i;
++
++ /* We only allow config cycles to devices that are in OF device-tree
++ * as we are apparently having some weird things going on with some
++ * revs of K2 on recent G5s
++ */
++ if (bus->self)
++ busdn = pci_device_to_OF_node(bus->self);
++ else
++ busdn = hose->arch_data;
++ for (dn = busdn->child; dn; dn = dn->sibling)
++ if (dn->data && PCI_DN(dn)->devfn == devfn)
++ break;
++ if (dn == NULL)
++ return -1;
++
++ /*
++ * When a device in K2 is powered down, we die on config
++ * cycle accesses. Fix that here.
++ */
++ for (i=0; i<2; i++)
++ if (k2_skiplist[i] == dn)
++ return 1;
++
++ return 0;
++}
++
++#define U3_HT_CFA0(devfn, off) \
++ ((((unsigned long)devfn) << 8) | offset)
++#define U3_HT_CFA1(bus, devfn, off) \
++ (U3_HT_CFA0(devfn, off) \
++ + (((unsigned long)bus) << 16) \
++ + 0x01000000UL)
++
++static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
++ u8 bus, u8 devfn, u8 offset)
++{
++ if (bus == hose->first_busno) {
++ /* For now, we don't self probe U3 HT bridge */
++ if (PCI_SLOT(devfn) == 0)
++ return 0;
++ return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
++ } else
++ return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset);
++}
++
++static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 *val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ switch (u3_ht_skip_device(hose, bus, devfn)) {
++ case 0:
++ break;
++ case 1:
++ switch (len) {
++ case 1:
++ *val = 0xff; break;
++ case 2:
++ *val = 0xffff; break;
++ default:
++ *val = 0xfffffffful; break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++ default:
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ *val = in_8((u8 *)addr);
++ break;
++ case 2:
++ *val = in_le16((u16 *)addr);
++ break;
++ default:
++ *val = in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
++ int offset, int len, u32 val)
++{
++ struct pci_controller *hose;
++ unsigned long addr;
++
++ hose = pci_bus_to_host(bus);
++ if (hose == NULL)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
++ if (!addr)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ switch (u3_ht_skip_device(hose, bus, devfn)) {
++ case 0:
++ break;
++ case 1:
++ return PCIBIOS_SUCCESSFUL;
++ default:
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ switch (len) {
++ case 1:
++ out_8((u8 *)addr, val);
++ (void) in_8((u8 *)addr);
++ break;
++ case 2:
++ out_le16((u16 *)addr, val);
++ (void) in_le16((u16 *)addr);
++ break;
++ default:
++ out_le32((u32 *)addr, val);
++ (void) in_le32((u32 *)addr);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops u3_ht_pci_ops =
++{
++ u3_ht_read_config,
++ u3_ht_write_config
++};
++#endif /* CONFIG_PPC64 */
++
++#ifdef CONFIG_PPC32
++/*
++ * For a bandit bridge, turn on cache coherency if necessary.
++ * N.B. we could clean this up using the hose ops directly.
++ */
++static void __init init_bandit(struct pci_controller *bp)
++{
++ unsigned int vendev, magic;
++ int rev;
++
++ /* read the word at offset 0 in config space for device 11 */
++ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
++ udelay(2);
++ vendev = in_le32(bp->cfg_data);
++ if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +
++ PCI_VENDOR_ID_APPLE) {
++ /* read the revision id */
++ out_le32(bp->cfg_addr,
++ (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
++ udelay(2);
++ rev = in_8(bp->cfg_data);
++ if (rev != BANDIT_REVID)
++ printk(KERN_WARNING
++ "Unknown revision %d for bandit\n", rev);
++ } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
++ printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
++ return;
++ }
++
++ /* read the word at offset 0x50 */
++ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
++ udelay(2);
++ magic = in_le32(bp->cfg_data);
++ if ((magic & BANDIT_COHERENT) != 0)
++ return;
++ magic |= BANDIT_COHERENT;
++ udelay(2);
++ out_le32(bp->cfg_data, magic);
++ printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");
++}
++
++/*
++ * Tweak the PCI-PCI bridge chip on the blue & white G3s.
++ */
++static void __init init_p2pbridge(void)
++{
++ struct device_node *p2pbridge;
++ struct pci_controller* hose;
++ u8 bus, devfn;
++ u16 val;
++
++ /* XXX it would be better here to identify the specific
++ PCI-PCI bridge chip we have. */
++ if ((p2pbridge = find_devices("pci-bridge")) == 0
++ || p2pbridge->parent == NULL
++ || strcmp(p2pbridge->parent->name, "pci") != 0)
++ return;
++ if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
++ DBG("Can't find PCI infos for PCI<->PCI bridge\n");
++ return;
++ }
++ /* Warning: At this point, we have not yet renumbered all busses.
++ * So we must use OF walking to find out hose
++ */
++ hose = pci_find_hose_for_OF_device(p2pbridge);
++ if (!hose) {
++ DBG("Can't find hose for PCI<->PCI bridge\n");
++ return;
++ }
++ if (early_read_config_word(hose, bus, devfn,
++ PCI_BRIDGE_CONTROL, &val) < 0) {
++ printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
++ return;
++ }
++ val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
++ early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
++}
++
++/*
++ * Some Apple desktop machines have a NEC PD720100A USB2 controller
++ * on the motherboard. Open Firmware, on these, will disable the
++ * EHCI part of it so it behaves like a pair of OHCI's. This fixup
++ * code re-enables it ;)
++ */
++static void __init fixup_nec_usb2(void)
++{
++ struct device_node *nec;
++
++ for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {
++ struct pci_controller *hose;
++ u32 data, *prop;
++ u8 bus, devfn;
++
++ prop = (u32 *)get_property(nec, "vendor-id", NULL);
++ if (prop == NULL)
++ continue;
++ if (0x1033 != *prop)
++ continue;
++ prop = (u32 *)get_property(nec, "device-id", NULL);
++ if (prop == NULL)
++ continue;
++ if (0x0035 != *prop)
++ continue;
++ prop = (u32 *)get_property(nec, "reg", NULL);
++ if (prop == NULL)
++ continue;
++ devfn = (prop[0] >> 8) & 0xff;
++ bus = (prop[0] >> 16) & 0xff;
++ if (PCI_FUNC(devfn) != 0)
++ continue;
++ hose = pci_find_hose_for_OF_device(nec);
++ if (!hose)
++ continue;
++ early_read_config_dword(hose, bus, devfn, 0xe4, &data);
++ if (data & 1UL) {
++ printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n");
++ data &= ~1UL;
++ early_write_config_dword(hose, bus, devfn, 0xe4, data);
++ early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,
++ nec->intrs[0].line);
++ }
++ }
++}
++
++static void __init setup_bandit(struct pci_controller *hose,
++ struct reg_property *addr)
++{
++ hose->ops = ¯isc_pci_ops;
++ hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
++ hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
++ init_bandit(hose);
++}
++
++static int __init setup_uninorth(struct pci_controller *hose,
++ struct reg_property *addr)
++{
++ pci_assign_all_buses = 1;
++ has_uninorth = 1;
++ hose->ops = ¯isc_pci_ops;
++ hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
++ hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
++ /* We "know" that the bridge at f2000000 has the PCI slots. */
++ return addr->address == 0xf2000000;
++}
++#endif
++
++#ifdef CONFIG_PPC64
++static void __init setup_u3_agp(struct pci_controller* hose)
++{
++ /* On G5, we move AGP up to high bus number so we don't need
++ * to reassign bus numbers for HT. If we ever have P2P bridges
++ * on AGP, we'll have to move pci_assign_all_busses to the
++ * pci_controller structure so we enable it for AGP and not for
++ * HT childs.
++ * We hard code the address because of the different size of
++ * the reg address cell, we shall fix that by killing struct
++ * reg_property and using some accessor functions instead
++ */
++ hose->first_busno = 0xf0;
++ hose->last_busno = 0xff;
++ has_uninorth = 1;
++ hose->ops = ¯isc_pci_ops;
++ hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
++ hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
++
++ u3_agp = hose;
++}
++
++static void __init setup_u3_ht(struct pci_controller* hose)
++{
++ struct device_node *np = (struct device_node *)hose->arch_data;
++ int i, cur;
++
++ hose->ops = &u3_ht_pci_ops;
++
++ /* We hard code the address because of the different size of
++ * the reg address cell, we shall fix that by killing struct
++ * reg_property and using some accessor functions instead
++ */
++ hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
++
++ /*
++ * /ht node doesn't expose a "ranges" property, so we "remove" regions that
++ * have been allocated to AGP. So far, this version of the code doesn't assign
++ * any of the 0xfxxxxxxx "fine" memory regions to /ht.
++ * We need to fix that sooner or later by either parsing all child "ranges"
++ * properties or figuring out the U3 address space decoding logic and
++ * then read its configuration register (if any).
++ */
++ hose->io_base_phys = 0xf4000000;
++ hose->pci_io_size = 0x00400000;
++ hose->io_resource.name = np->full_name;
++ hose->io_resource.start = 0;
++ hose->io_resource.end = 0x003fffff;
++ hose->io_resource.flags = IORESOURCE_IO;
++ hose->pci_mem_offset = 0;
++ hose->first_busno = 0;
++ hose->last_busno = 0xef;
++ hose->mem_resources[0].name = np->full_name;
++ hose->mem_resources[0].start = 0x80000000;
++ hose->mem_resources[0].end = 0xefffffff;
++ hose->mem_resources[0].flags = IORESOURCE_MEM;
++
++ u3_ht = hose;
++
++ if (u3_agp == NULL) {
++ DBG("U3 has no AGP, using full resource range\n");
++ return;
++ }
++
++ /* We "remove" the AGP resources from the resources allocated to HT, that
++ * is we create "holes". However, that code does assumptions that so far
++ * happen to be true (cross fingers...), typically that resources in the
++ * AGP node are properly ordered
++ */
++ cur = 0;
++ for (i=0; i<3; i++) {
++ struct resource *res = &u3_agp->mem_resources[i];
++ if (res->flags != IORESOURCE_MEM)
++ continue;
++ /* We don't care about "fine" resources */
++ if (res->start >= 0xf0000000)
++ continue;
++ /* Check if it's just a matter of "shrinking" us in one direction */
++ if (hose->mem_resources[cur].start == res->start) {
++ DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
++ cur, hose->mem_resources[cur].start, res->end + 1);
++ hose->mem_resources[cur].start = res->end + 1;
++ continue;
++ }
++ if (hose->mem_resources[cur].end == res->end) {
++ DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
++ cur, hose->mem_resources[cur].end, res->start - 1);
++ hose->mem_resources[cur].end = res->start - 1;
++ continue;
++ }
++ /* No, it's not the case, we need a hole */
++ if (cur == 2) {
++ /* not enough resources for a hole, we drop part of the range */
++ printk(KERN_WARNING "Running out of resources for /ht host !\n");
++ hose->mem_resources[cur].end = res->start - 1;
++ continue;
++ }
++ cur++;
++ DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
++ cur-1, res->start - 1, cur, res->end + 1);
++ hose->mem_resources[cur].name = np->full_name;
++ hose->mem_resources[cur].flags = IORESOURCE_MEM;
++ hose->mem_resources[cur].start = res->end + 1;
++ hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
++ hose->mem_resources[cur-1].end = res->start - 1;
++ }
++}
++
++/* XXX this needs to be converged between ppc32 and ppc64... */
++static struct pci_controller * __init pcibios_alloc_controller(void)
++{
++ struct pci_controller *hose;
++
++ hose = alloc_bootmem(sizeof(struct pci_controller));
++ if (hose)
++ pci_setup_pci_controller(hose);
++ return hose;
++}
++#endif
++
++/*
++ * We assume that if we have a G3 powermac, we have one bridge called
++ * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
++ * if we have one or more bandit or chaos bridges, we don't have a MPC106.
++ */
++static int __init add_bridge(struct device_node *dev)
++{
++ int len;
++ struct pci_controller *hose;
++#ifdef CONFIG_PPC32
++ struct reg_property *addr;
++#endif
++ char *disp_name;
++ int *bus_range;
++ int primary = 1;
++
++ DBG("Adding PCI host bridge %s\n", dev->full_name);
++
++#ifdef CONFIG_PPC32
++ /* XXX fix this */
++ addr = (struct reg_property *) get_property(dev, "reg", &len);
++ if (addr == NULL || len < sizeof(*addr)) {
++ printk(KERN_WARNING "Can't use %s: no address\n",
++ dev->full_name);
++ return -ENODEV;
++ }
++#endif
++ bus_range = (int *) get_property(dev, "bus-range", &len);
++ if (bus_range == NULL || len < 2 * sizeof(int)) {
++ printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
++ dev->full_name);
++ }
++
++ hose = pcibios_alloc_controller();
++ if (!hose)
++ return -ENOMEM;
++ hose->arch_data = dev;
++ hose->first_busno = bus_range ? bus_range[0] : 0;
++ hose->last_busno = bus_range ? bus_range[1] : 0xff;
++
++ disp_name = NULL;
++#ifdef CONFIG_POWER4
++ if (device_is_compatible(dev, "u3-agp")) {
++ setup_u3_agp(hose);
++ disp_name = "U3-AGP";
++ primary = 0;
++ } else if (device_is_compatible(dev, "u3-ht")) {
++ setup_u3_ht(hose);
++ disp_name = "U3-HT";
++ primary = 1;
++ }
++ printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
++ disp_name, hose->first_busno, hose->last_busno);
++#else
++ if (device_is_compatible(dev, "uni-north")) {
++ primary = setup_uninorth(hose, addr);
++ disp_name = "UniNorth";
++ } else if (strcmp(dev->name, "pci") == 0) {
++ /* XXX assume this is a mpc106 (grackle) */
++ setup_grackle(hose);
++ disp_name = "Grackle (MPC106)";
++ } else if (strcmp(dev->name, "bandit") == 0) {
++ setup_bandit(hose, addr);
++ disp_name = "Bandit";
++ } else if (strcmp(dev->name, "chaos") == 0) {
++ setup_chaos(hose, addr);
++ disp_name = "Chaos";
++ primary = 0;
++ }
++ printk(KERN_INFO "Found %s PCI host bridge at 0x%08lx. Firmware bus number: %d->%d\n",
++ disp_name, addr->address, hose->first_busno, hose->last_busno);
++#endif
++ DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
++ hose, hose->cfg_addr, hose->cfg_data);
++
++ /* Interpret the "ranges" property */
++ /* This also maps the I/O region and sets isa_io/mem_base */
++ pci_process_bridge_OF_ranges(hose, dev, primary);
++
++ /* Fixup "bus-range" OF property */
++ fixup_bus_range(dev);
++
++ return 0;
++}
++
++static void __init
++pcibios_fixup_OF_interrupts(void)
++{
++ struct pci_dev* dev = NULL;
++
++ /*
++ * Open Firmware often doesn't initialize the
++ * PCI_INTERRUPT_LINE config register properly, so we
++ * should find the device node and apply the interrupt
++ * obtained from the OF device-tree
++ */
++ for_each_pci_dev(dev) {
++ struct device_node *node;
++ node = pci_device_to_OF_node(dev);
++ /* this is the node, see if it has interrupts */
++ if (node && node->n_intrs > 0)
++ dev->irq = node->intrs[0].line;
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++ }
++}
++
++void __init
++pmac_pcibios_fixup(void)
++{
++ /* Fixup interrupts according to OF tree */
++ pcibios_fixup_OF_interrupts();
++}
++
++#ifdef CONFIG_PPC64
++static void __init pmac_fixup_phb_resources(void)
++{
++ struct pci_controller *hose, *tmp;
++
++ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
++ printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
++ hose->global_number,
++ hose->io_resource.start, hose->io_resource.end);
++ }
++}
++#endif
++
++void __init pmac_pci_init(void)
++{
++ struct device_node *np, *root;
++ struct device_node *ht = NULL;
++
++ root = of_find_node_by_path("/");
++ if (root == NULL) {
++ printk(KERN_CRIT "pmac_pci_init: can't find root "
++ "of device tree\n");
++ return;
++ }
++ for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
++ if (np->name == NULL)
++ continue;
++ if (strcmp(np->name, "bandit") == 0
++ || strcmp(np->name, "chaos") == 0
++ || strcmp(np->name, "pci") == 0) {
++ if (add_bridge(np) == 0)
++ of_node_get(np);
++ }
++ if (strcmp(np->name, "ht") == 0) {
++ of_node_get(np);
++ ht = np;
++ }
++ }
++ of_node_put(root);
++
++#ifdef CONFIG_PPC64
++ /* Probe HT last as it relies on the agp resources to be already
++ * setup
++ */
++ if (ht && add_bridge(ht) != 0)
++ of_node_put(ht);
++
++ /*
++ * We need to call pci_setup_phb_io for the HT bridge first
++ * so it gets the I/O port numbers starting at 0, and we
++ * need to call it for the AGP bridge after that so it gets
++ * small positive I/O port numbers.
++ */
++ if (u3_ht)
++ pci_setup_phb_io(u3_ht, 1);
++ if (u3_agp)
++ pci_setup_phb_io(u3_agp, 0);
++
++ /*
++ * On ppc64, fixup the IO resources on our host bridges as
++ * the common code does it only for children of the host bridges
++ */
++ pmac_fixup_phb_resources();
++
++ /* Setup the linkage between OF nodes and PHBs */
++ pci_devs_phb_init();
++
++ /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
++ * assume there is no P2P bridge on the AGP bus, which should be a
++ * safe assumptions hopefully.
++ */
++ if (u3_agp) {
++ struct device_node *np = u3_agp->arch_data;
++ PCI_DN(np)->busno = 0xf0;
++ for (np = np->child; np; np = np->sibling)
++ PCI_DN(np)->busno = 0xf0;
++ }
++
++ /* map in PCI I/O space */
++ phbs_remap_io();
++
++ /* pmac_check_ht_link(); */
++
++ /* Tell pci.c to not use the common resource allocation mechanism */
++ pci_probe_only = 1;
++
++ /* Allow all IO */
++ io_page_mask = -1;
++
++#else /* CONFIG_PPC64 */
++ init_p2pbridge();
++ fixup_nec_usb2();
++
++ /* We are still having some issues with the Xserve G4, enabling
++ * some offset between bus number and domains for now when we
++ * assign all busses should help for now
++ */
++ if (pci_assign_all_buses)
++ pcibios_assign_bus_offset = 0x10;
++#endif
++}
++
++int
++pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
++{
++ struct device_node* node;
++ int updatecfg = 0;
++ int uninorth_child;
++
++ node = pci_device_to_OF_node(dev);
++
++ /* We don't want to enable USB controllers absent from the OF tree
++ * (iBook second controller)
++ */
++ if (dev->vendor == PCI_VENDOR_ID_APPLE
++ && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))
++ && !node) {
++ printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",
++ pci_name(dev));
++ return -EINVAL;
++ }
++
++ if (!node)
++ return 0;
++
++ uninorth_child = node->parent &&
++ device_is_compatible(node->parent, "uni-north");
++
++ /* Firewire & GMAC were disabled after PCI probe, the driver is
++ * claiming them, we must re-enable them now.
++ */
++ if (uninorth_child && !strcmp(node->name, "firewire") &&
++ (device_is_compatible(node, "pci106b,18") ||
++ device_is_compatible(node, "pci106b,30") ||
++ device_is_compatible(node, "pci11c1,5811"))) {
++ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
++ pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
++ updatecfg = 1;
++ }
++ if (uninorth_child && !strcmp(node->name, "ethernet") &&
++ device_is_compatible(node, "gmac")) {
++ pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
++ updatecfg = 1;
++ }
++
++ if (updatecfg) {
++ u16 cmd;
++
++ /*
++ * Make sure PCI is correctly configured
++ *
++ * We use old pci_bios versions of the function since, by
++ * default, gmac is not powered up, and so will be absent
++ * from the kernel initial PCI lookup.
++ *
++ * Should be replaced by 2.4 new PCI mechanisms and really
++ * register the device.
++ */
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
++ | PCI_COMMAND_INVALIDATE;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
++ L1_CACHE_BYTES >> 2);
++ }
++
++ return 0;
++}
++
++/* We power down some devices after they have been probed. They'll
++ * be powered back on later on
++ */
++void __init pmac_pcibios_after_init(void)
++{
++ struct device_node* nd;
++
++#ifdef CONFIG_BLK_DEV_IDE
++ struct pci_dev *dev = NULL;
++
++ /* OF fails to initialize IDE controllers on macs
++ * (and maybe other machines)
++ *
++ * Ideally, this should be moved to the IDE layer, but we need
++ * to check specifically with Andre Hedrick how to do it cleanly
++ * since the common IDE code seem to care about the fact that the
++ * BIOS may have disabled a controller.
++ *
++ * -- BenH
++ */
++ for_each_pci_dev(dev) {
++ if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
++ pci_enable_device(dev);
++ }
++#endif /* CONFIG_BLK_DEV_IDE */
++
++ nd = find_devices("firewire");
++ while (nd) {
++ if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
++ device_is_compatible(nd, "pci106b,30") ||
++ device_is_compatible(nd, "pci11c1,5811"))
++ && device_is_compatible(nd->parent, "uni-north")) {
++ pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
++ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
++ }
++ nd = nd->next;
++ }
++ nd = find_devices("ethernet");
++ while (nd) {
++ if (nd->parent && device_is_compatible(nd, "gmac")
++ && device_is_compatible(nd->parent, "uni-north"))
++ pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
++ nd = nd->next;
++ }
++}
++
++#ifdef CONFIG_PPC32
++void pmac_pci_fixup_cardbus(struct pci_dev* dev)
++{
++ if (_machine != _MACH_Pmac)
++ return;
++ /*
++ * Fix the interrupt routing on the various cardbus bridges
++ * used on powerbooks
++ */
++ if (dev->vendor != PCI_VENDOR_ID_TI)
++ return;
++ if (dev->device == PCI_DEVICE_ID_TI_1130 ||
++ dev->device == PCI_DEVICE_ID_TI_1131) {
++ u8 val;
++ /* Enable PCI interrupt */
++ if (pci_read_config_byte(dev, 0x91, &val) == 0)
++ pci_write_config_byte(dev, 0x91, val | 0x30);
++ /* Disable ISA interrupt mode */
++ if (pci_read_config_byte(dev, 0x92, &val) == 0)
++ pci_write_config_byte(dev, 0x92, val & ~0x06);
++ }
++ if (dev->device == PCI_DEVICE_ID_TI_1210 ||
++ dev->device == PCI_DEVICE_ID_TI_1211 ||
++ dev->device == PCI_DEVICE_ID_TI_1410 ||
++ dev->device == PCI_DEVICE_ID_TI_1510) {
++ u8 val;
++ /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA
++ signal out the MFUNC0 pin */
++ if (pci_read_config_byte(dev, 0x8c, &val) == 0)
++ pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2);
++ /* Disable ISA interrupt mode */
++ if (pci_read_config_byte(dev, 0x92, &val) == 0)
++ pci_write_config_byte(dev, 0x92, val & ~0x06);
++ }
++}
++
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);
++
++void pmac_pci_fixup_pciata(struct pci_dev* dev)
++{
++ u8 progif = 0;
++
++ /*
++ * On PowerMacs, we try to switch any PCI ATA controller to
++ * fully native mode
++ */
++ if (_machine != _MACH_Pmac)
++ return;
++ /* Some controllers don't have the class IDE */
++ if (dev->vendor == PCI_VENDOR_ID_PROMISE)
++ switch(dev->device) {
++ case PCI_DEVICE_ID_PROMISE_20246:
++ case PCI_DEVICE_ID_PROMISE_20262:
++ case PCI_DEVICE_ID_PROMISE_20263:
++ case PCI_DEVICE_ID_PROMISE_20265:
++ case PCI_DEVICE_ID_PROMISE_20267:
++ case PCI_DEVICE_ID_PROMISE_20268:
++ case PCI_DEVICE_ID_PROMISE_20269:
++ case PCI_DEVICE_ID_PROMISE_20270:
++ case PCI_DEVICE_ID_PROMISE_20271:
++ case PCI_DEVICE_ID_PROMISE_20275:
++ case PCI_DEVICE_ID_PROMISE_20276:
++ case PCI_DEVICE_ID_PROMISE_20277:
++ goto good;
++ }
++ /* Others, check PCI class */
++ if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
++ return;
++ good:
++ pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
++ if ((progif & 5) != 5) {
++ printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev));
++ (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
++ if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
++ (progif & 5) != 5)
++ printk(KERN_ERR "Rewrite of PROGIF failed !\n");
++ }
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
++#endif
++
++/*
++ * Disable second function on K2-SATA, it's broken
++ * and disable IO BARs on first one
++ */
++static void fixup_k2_sata(struct pci_dev* dev)
++{
++ int i;
++ u16 cmd;
++
++ if (PCI_FUNC(dev->devfn) > 0) {
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ for (i = 0; i < 6; i++) {
++ dev->resource[i].start = dev->resource[i].end = 0;
++ dev->resource[i].flags = 0;
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
++ }
++ } else {
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd &= ~PCI_COMMAND_IO;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ for (i = 0; i < 5; i++) {
++ dev->resource[i].start = dev->resource[i].end = 0;
++ dev->resource[i].flags = 0;
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
++ }
++ }
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
++
+diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/pic.c
+@@ -0,0 +1,678 @@
++/*
++ * Support for the interrupt controllers found on Power Macintosh,
++ * currently Apple's "Grand Central" interrupt controller in all
++ * it's incarnations. OpenPIC support used on newer machines is
++ * in a separate file
++ *
++ * Copyright (C) 1997 Paul Mackerras (paulus at samba.org)
++ *
++ * Maintained by Benjamin Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/stddef.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/signal.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <linux/sysdev.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++#include <linux/module.h>
++
++#include <asm/sections.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/time.h>
++#include <asm/pmac_feature.h>
++#include <asm/mpic.h>
++
++#include "pmac.h"
++
++/*
++ * XXX this should be in xmon.h, but putting it there means xmon.h
++ * has to include <linux/interrupt.h> (to get irqreturn_t), which
++ * causes all sorts of problems. -- paulus
++ */
++extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
++
++#ifdef CONFIG_PPC32
++struct pmac_irq_hw {
++ unsigned int event;
++ unsigned int enable;
++ unsigned int ack;
++ unsigned int level;
++};
++
++/* Default addresses */
++static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
++ (struct pmac_irq_hw *) 0xf3000020,
++ (struct pmac_irq_hw *) 0xf3000010,
++ (struct pmac_irq_hw *) 0xf4000020,
++ (struct pmac_irq_hw *) 0xf4000010,
++};
++
++#define GC_LEVEL_MASK 0x3ff00000
++#define OHARE_LEVEL_MASK 0x1ff00000
++#define HEATHROW_LEVEL_MASK 0x1ff00000
++
++static int max_irqs;
++static int max_real_irqs;
++static u32 level_mask[4];
++
++static DEFINE_SPINLOCK(pmac_pic_lock);
++
++#define GATWICK_IRQ_POOL_SIZE 10
++static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
++
++/*
++ * Mark an irq as "lost". This is only used on the pmac
++ * since it can lose interrupts (see pmac_set_irq_mask).
++ * -- Cort
++ */
++void
++__set_lost(unsigned long irq_nr, int nokick)
++{
++ if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
++ atomic_inc(&ppc_n_lost_interrupts);
++ if (!nokick)
++ set_dec(1);
++ }
++}
++
++static void
++pmac_mask_and_ack_irq(unsigned int irq_nr)
++{
++ unsigned long bit = 1UL << (irq_nr & 0x1f);
++ int i = irq_nr >> 5;
++ unsigned long flags;
++
++ if ((unsigned)irq_nr >= max_irqs)
++ return;
++
++ clear_bit(irq_nr, ppc_cached_irq_mask);
++ if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
++ atomic_dec(&ppc_n_lost_interrupts);
++ spin_lock_irqsave(&pmac_pic_lock, flags);
++ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
++ out_le32(&pmac_irq_hw[i]->ack, bit);
++ do {
++ /* make sure ack gets to controller before we enable
++ interrupts */
++ mb();
++ } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
++ != (ppc_cached_irq_mask[i] & bit));
++ spin_unlock_irqrestore(&pmac_pic_lock, flags);
++}
++
++static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
++{
++ unsigned long bit = 1UL << (irq_nr & 0x1f);
++ int i = irq_nr >> 5;
++ unsigned long flags;
++
++ if ((unsigned)irq_nr >= max_irqs)
++ return;
++
++ spin_lock_irqsave(&pmac_pic_lock, flags);
++ /* enable unmasked interrupts */
++ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
++
++ do {
++ /* make sure mask gets to controller before we
++ return to user */
++ mb();
++ } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
++ != (ppc_cached_irq_mask[i] & bit));
++
++ /*
++ * Unfortunately, setting the bit in the enable register
++ * when the device interrupt is already on *doesn't* set
++ * the bit in the flag register or request another interrupt.
++ */
++ if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
++ __set_lost((ulong)irq_nr, nokicklost);
++ spin_unlock_irqrestore(&pmac_pic_lock, flags);
++}
++
++/* When an irq gets requested for the first client, if it's an
++ * edge interrupt, we clear any previous one on the controller
++ */
++static unsigned int pmac_startup_irq(unsigned int irq_nr)
++{
++ unsigned long bit = 1UL << (irq_nr & 0x1f);
++ int i = irq_nr >> 5;
++
++ if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
++ out_le32(&pmac_irq_hw[i]->ack, bit);
++ set_bit(irq_nr, ppc_cached_irq_mask);
++ pmac_set_irq_mask(irq_nr, 0);
++
++ return 0;
++}
++
++static void pmac_mask_irq(unsigned int irq_nr)
++{
++ clear_bit(irq_nr, ppc_cached_irq_mask);
++ pmac_set_irq_mask(irq_nr, 0);
++ mb();
++}
++
++static void pmac_unmask_irq(unsigned int irq_nr)
++{
++ set_bit(irq_nr, ppc_cached_irq_mask);
++ pmac_set_irq_mask(irq_nr, 0);
++}
++
++static void pmac_end_irq(unsigned int irq_nr)
++{
++ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
++ && irq_desc[irq_nr].action) {
++ set_bit(irq_nr, ppc_cached_irq_mask);
++ pmac_set_irq_mask(irq_nr, 1);
++ }
++}
++
++
++struct hw_interrupt_type pmac_pic = {
++ .typename = " PMAC-PIC ",
++ .startup = pmac_startup_irq,
++ .enable = pmac_unmask_irq,
++ .disable = pmac_mask_irq,
++ .ack = pmac_mask_and_ack_irq,
++ .end = pmac_end_irq,
++};
++
++struct hw_interrupt_type gatwick_pic = {
++ .typename = " GATWICK ",
++ .startup = pmac_startup_irq,
++ .enable = pmac_unmask_irq,
++ .disable = pmac_mask_irq,
++ .ack = pmac_mask_and_ack_irq,
++ .end = pmac_end_irq,
++};
++
++static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
++{
++ int irq, bits;
++
++ for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
++ int i = irq >> 5;
++ bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
++ /* We must read level interrupts from the level register */
++ bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
++ bits &= ppc_cached_irq_mask[i];
++ if (bits == 0)
++ continue;
++ irq += __ilog2(bits);
++ __do_IRQ(irq, regs);
++ return IRQ_HANDLED;
++ }
++ printk("gatwick irq not from gatwick pic\n");
++ return IRQ_NONE;
++}
++
++int
++pmac_get_irq(struct pt_regs *regs)
++{
++ int irq;
++ unsigned long bits = 0;
++
++#ifdef CONFIG_SMP
++ void psurge_smp_message_recv(struct pt_regs *);
++
++ /* IPI's are a hack on the powersurge -- Cort */
++ if ( smp_processor_id() != 0 ) {
++ psurge_smp_message_recv(regs);
++ return -2; /* ignore, already handled */
++ }
++#endif /* CONFIG_SMP */
++ for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
++ int i = irq >> 5;
++ bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
++ /* We must read level interrupts from the level register */
++ bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
++ bits &= ppc_cached_irq_mask[i];
++ if (bits == 0)
++ continue;
++ irq += __ilog2(bits);
++ break;
++ }
++
++ return irq;
++}
++
++/* This routine will fix some missing interrupt values in the device tree
++ * on the gatwick mac-io controller used by some PowerBooks
++ */
++static void __init
++pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
++{
++ struct device_node *node;
++ int count;
++
++ memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
++ node = gw->child;
++ count = 0;
++ while(node)
++ {
++ /* Fix SCC */
++ if (strcasecmp(node->name, "escc") == 0)
++ if (node->child) {
++ if (node->child->n_intrs < 3) {
++ node->child->intrs = &gatwick_int_pool[count];
++ count += 3;
++ }
++ node->child->n_intrs = 3;
++ node->child->intrs[0].line = 15+irq_base;
++ node->child->intrs[1].line = 4+irq_base;
++ node->child->intrs[2].line = 5+irq_base;
++ printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
++ node->child->intrs[0].line,
++ node->child->intrs[1].line,
++ node->child->intrs[2].line);
++ }
++ /* Fix media-bay & left SWIM */
++ if (strcasecmp(node->name, "media-bay") == 0) {
++ struct device_node* ya_node;
++
++ if (node->n_intrs == 0)
++ node->intrs = &gatwick_int_pool[count++];
++ node->n_intrs = 1;
++ node->intrs[0].line = 29+irq_base;
++ printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
++ node->intrs[0].line);
++
++ ya_node = node->child;
++ while(ya_node)
++ {
++ if (strcasecmp(ya_node->name, "floppy") == 0) {
++ if (ya_node->n_intrs < 2) {
++ ya_node->intrs = &gatwick_int_pool[count];
++ count += 2;
++ }
++ ya_node->n_intrs = 2;
++ ya_node->intrs[0].line = 19+irq_base;
++ ya_node->intrs[1].line = 1+irq_base;
++ printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
++ ya_node->intrs[0].line, ya_node->intrs[1].line);
++ }
++ if (strcasecmp(ya_node->name, "ata4") == 0) {
++ if (ya_node->n_intrs < 2) {
++ ya_node->intrs = &gatwick_int_pool[count];
++ count += 2;
++ }
++ ya_node->n_intrs = 2;
++ ya_node->intrs[0].line = 14+irq_base;
++ ya_node->intrs[1].line = 3+irq_base;
++ printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
++ ya_node->intrs[0].line, ya_node->intrs[1].line);
++ }
++ ya_node = ya_node->sibling;
++ }
++ }
++ node = node->sibling;
++ }
++ if (count > 10) {
++ printk("WARNING !! Gatwick interrupt pool overflow\n");
++ printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
++ printk(" requested = %d\n", count);
++ }
++}
++
++/*
++ * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
++ * card which includes an ohare chip that acts as a second interrupt
++ * controller. If we find this second ohare, set it up and fix the
++ * interrupt value in the device tree for the ethernet chip.
++ */
++static int __init enable_second_ohare(void)
++{
++ unsigned char bus, devfn;
++ unsigned short cmd;
++ unsigned long addr;
++ struct device_node *irqctrler = find_devices("pci106b,7");
++ struct device_node *ether;
++
++ if (irqctrler == NULL || irqctrler->n_addrs <= 0)
++ return -1;
++ addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
++ pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
++ max_irqs = 64;
++ if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
++ struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
++ if (!hose)
++ printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
++ else {
++ early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
++ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
++ cmd &= ~PCI_COMMAND_IO;
++ early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
++ }
++ }
++
++ /* Fix interrupt for the modem/ethernet combo controller. The number
++ in the device tree (27) is bogus (correct for the ethernet-only
++ board but not the combo ethernet/modem board).
++ The real interrupt is 28 on the second controller -> 28+32 = 60.
++ */
++ ether = find_devices("pci1011,14");
++ if (ether && ether->n_intrs > 0) {
++ ether->intrs[0].line = 60;
++ printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
++ ether->intrs[0].line);
++ }
++
++ /* Return the interrupt number of the cascade */
++ return irqctrler->intrs[0].line;
++}
++
++#ifdef CONFIG_XMON
++static struct irqaction xmon_action = {
++ .handler = xmon_irq,
++ .flags = 0,
++ .mask = CPU_MASK_NONE,
++ .name = "NMI - XMON"
++};
++#endif
++
++static struct irqaction gatwick_cascade_action = {
++ .handler = gatwick_action,
++ .flags = SA_INTERRUPT,
++ .mask = CPU_MASK_NONE,
++ .name = "cascade",
++};
++#endif /* CONFIG_PPC32 */
++
++static int pmac_u3_cascade(struct pt_regs *regs, void *data)
++{
++ return mpic_get_one_irq((struct mpic *)data, regs);
++}
++
++void __init pmac_pic_init(void)
++{
++ struct device_node *irqctrler = NULL;
++ struct device_node *irqctrler2 = NULL;
++ struct device_node *np;
++#ifdef CONFIG_PPC32
++ int i;
++ unsigned long addr;
++ int irq_cascade = -1;
++#endif
++ struct mpic *mpic1, *mpic2;
++
++ /* We first try to detect Apple's new Core99 chipset, since mac-io
++ * is quite different on those machines and contains an IBM MPIC2.
++ */
++ np = find_type_devices("open-pic");
++ while (np) {
++ if (np->parent && !strcmp(np->parent->name, "u3"))
++ irqctrler2 = np;
++ else
++ irqctrler = np;
++ np = np->next;
++ }
++ if (irqctrler != NULL && irqctrler->n_addrs > 0) {
++ unsigned char senses[128];
++
++ printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n",
++ (unsigned int)irqctrler->addrs[0].address);
++ pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0);
++
++ prom_get_irq_senses(senses, 0, 128);
++ mpic1 = mpic_alloc(irqctrler->addrs[0].address,
++ MPIC_PRIMARY | MPIC_WANTS_RESET,
++ 0, 0, 128, 252, senses, 128, " OpenPIC ");
++ BUG_ON(mpic1 == NULL);
++ mpic_init(mpic1);
++
++ if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
++ irqctrler2->n_addrs > 0) {
++ printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
++ (u32)irqctrler2->addrs[0].address,
++ irqctrler2->intrs[0].line);
++
++ pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
++ prom_get_irq_senses(senses, 128, 128 + 124);
++
++ /* We don't need to set MPIC_BROKEN_U3 here since we don't have
++ * hypertransport interrupts routed to it
++ */
++ mpic2 = mpic_alloc(irqctrler2->addrs[0].address,
++ MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
++ 0, 128, 124, 0, senses, 124,
++ " U3-MPIC ");
++ BUG_ON(mpic2 == NULL);
++ mpic_init(mpic2);
++ mpic_setup_cascade(irqctrler2->intrs[0].line,
++ pmac_u3_cascade, mpic2);
++ }
++#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
++ {
++ struct device_node* pswitch;
++ int nmi_irq;
++
++ pswitch = find_devices("programmer-switch");
++ if (pswitch && pswitch->n_intrs) {
++ nmi_irq = pswitch->intrs[0].line;
++ mpic_irq_set_priority(nmi_irq, 9);
++ setup_irq(nmi_irq, &xmon_action);
++ }
++ }
++#endif /* CONFIG_XMON */
++ return;
++ }
++ irqctrler = NULL;
++
++#ifdef CONFIG_PPC32
++ /* Get the level/edge settings, assume if it's not
++ * a Grand Central nor an OHare, then it's an Heathrow
++ * (or Paddington).
++ */
++ ppc_md.get_irq = pmac_get_irq;
++ if (find_devices("gc"))
++ level_mask[0] = GC_LEVEL_MASK;
++ else if (find_devices("ohare")) {
++ level_mask[0] = OHARE_LEVEL_MASK;
++ /* We might have a second cascaded ohare */
++ level_mask[1] = OHARE_LEVEL_MASK;
++ } else {
++ level_mask[0] = HEATHROW_LEVEL_MASK;
++ level_mask[1] = 0;
++ /* We might have a second cascaded heathrow */
++ level_mask[2] = HEATHROW_LEVEL_MASK;
++ level_mask[3] = 0;
++ }
++
++ /*
++ * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
++ * 1998 G3 Series PowerBooks have 128,
++ * other powermacs have 32.
++ * The combo ethernet/modem card for the Powerstar powerbooks
++ * (2400/3400/3500, ohare based) has a second ohare chip
++ * effectively making a total of 64.
++ */
++ max_irqs = max_real_irqs = 32;
++ irqctrler = find_devices("mac-io");
++ if (irqctrler)
++ {
++ max_real_irqs = 64;
++ if (irqctrler->next)
++ max_irqs = 128;
++ else
++ max_irqs = 64;
++ }
++ for ( i = 0; i < max_real_irqs ; i++ )
++ irq_desc[i].handler = &pmac_pic;
++
++ /* get addresses of first controller */
++ if (irqctrler) {
++ if (irqctrler->n_addrs > 0) {
++ addr = (unsigned long)
++ ioremap(irqctrler->addrs[0].address, 0x40);
++ for (i = 0; i < 2; ++i)
++ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
++ (addr + (2 - i) * 0x10);
++ }
++
++ /* get addresses of second controller */
++ irqctrler = irqctrler->next;
++ if (irqctrler && irqctrler->n_addrs > 0) {
++ addr = (unsigned long)
++ ioremap(irqctrler->addrs[0].address, 0x40);
++ for (i = 2; i < 4; ++i)
++ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
++ (addr + (4 - i) * 0x10);
++ irq_cascade = irqctrler->intrs[0].line;
++ if (device_is_compatible(irqctrler, "gatwick"))
++ pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
++ }
++ } else {
++ /* older powermacs have a GC (grand central) or ohare at
++ f3000000, with interrupt control registers at f3000020. */
++ addr = (unsigned long) ioremap(0xf3000000, 0x40);
++ pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
++ }
++
++ /* PowerBooks 3400 and 3500 can have a second controller in a second
++ ohare chip, on the combo ethernet/modem card */
++ if (machine_is_compatible("AAPL,3400/2400")
++ || machine_is_compatible("AAPL,3500"))
++ irq_cascade = enable_second_ohare();
++
++ /* disable all interrupts in all controllers */
++ for (i = 0; i * 32 < max_irqs; ++i)
++ out_le32(&pmac_irq_hw[i]->enable, 0);
++ /* mark level interrupts */
++ for (i = 0; i < max_irqs; i++)
++ if (level_mask[i >> 5] & (1UL << (i & 0x1f)))
++ irq_desc[i].status = IRQ_LEVEL;
++
++ /* get interrupt line of secondary interrupt controller */
++ if (irq_cascade >= 0) {
++ printk(KERN_INFO "irq: secondary controller on irq %d\n",
++ (int)irq_cascade);
++ for ( i = max_real_irqs ; i < max_irqs ; i++ )
++ irq_desc[i].handler = &gatwick_pic;
++ setup_irq(irq_cascade, &gatwick_cascade_action);
++ }
++ printk("System has %d possible interrupts\n", max_irqs);
++ if (max_irqs != max_real_irqs)
++ printk(KERN_DEBUG "%d interrupts on main controller\n",
++ max_real_irqs);
++
++#ifdef CONFIG_XMON
++ setup_irq(20, &xmon_action);
++#endif /* CONFIG_XMON */
++#endif /* CONFIG_PPC32 */
++}
++
++#ifdef CONFIG_PM
++/*
++ * These procedures are used in implementing sleep on the powerbooks.
++ * sleep_save_intrs() saves the states of all interrupt enables
++ * and disables all interrupts except for the nominated one.
++ * sleep_restore_intrs() restores the states of all interrupt enables.
++ */
++unsigned long sleep_save_mask[2];
++
++/* This used to be passed by the PMU driver but that link got
++ * broken with the new driver model. We use this tweak for now...
++ */
++static int pmacpic_find_viaint(void)
++{
++ int viaint = -1;
++
++#ifdef CONFIG_ADB_PMU
++ struct device_node *np;
++
++ if (pmu_get_model() != PMU_OHARE_BASED)
++ goto not_found;
++ np = of_find_node_by_name(NULL, "via-pmu");
++ if (np == NULL)
++ goto not_found;
++ viaint = np->intrs[0].line;
++#endif /* CONFIG_ADB_PMU */
++
++not_found:
++ return viaint;
++}
++
++static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
++{
++ int viaint = pmacpic_find_viaint();
++
++ sleep_save_mask[0] = ppc_cached_irq_mask[0];
++ sleep_save_mask[1] = ppc_cached_irq_mask[1];
++ ppc_cached_irq_mask[0] = 0;
++ ppc_cached_irq_mask[1] = 0;
++ if (viaint > 0)
++ set_bit(viaint, ppc_cached_irq_mask);
++ out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
++ if (max_real_irqs > 32)
++ out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
++ (void)in_le32(&pmac_irq_hw[0]->event);
++ /* make sure mask gets to controller before we return to caller */
++ mb();
++ (void)in_le32(&pmac_irq_hw[0]->enable);
++
++ return 0;
++}
++
++static int pmacpic_resume(struct sys_device *sysdev)
++{
++ int i;
++
++ out_le32(&pmac_irq_hw[0]->enable, 0);
++ if (max_real_irqs > 32)
++ out_le32(&pmac_irq_hw[1]->enable, 0);
++ mb();
++ for (i = 0; i < max_real_irqs; ++i)
++ if (test_bit(i, sleep_save_mask))
++ pmac_unmask_irq(i);
++
++ return 0;
++}
++
++#endif /* CONFIG_PM */
++
++static struct sysdev_class pmacpic_sysclass = {
++ set_kset_name("pmac_pic"),
++};
++
++static struct sys_device device_pmacpic = {
++ .id = 0,
++ .cls = &pmacpic_sysclass,
++};
++
++static struct sysdev_driver driver_pmacpic = {
++#ifdef CONFIG_PM
++ .suspend = &pmacpic_suspend,
++ .resume = &pmacpic_resume,
++#endif /* CONFIG_PM */
++};
++
++static int __init init_pmacpic_sysfs(void)
++{
++#ifdef CONFIG_PPC32
++ if (max_irqs == 0)
++ return -ENODEV;
++#endif
++ printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
++ sysdev_class_register(&pmacpic_sysclass);
++ sysdev_register(&device_pmacpic);
++ sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
++ return 0;
++}
++
++subsys_initcall(init_pmacpic_sysfs);
++
+diff --git a/arch/powerpc/platforms/powermac/pic.h b/arch/powerpc/platforms/powermac/pic.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/pic.h
+@@ -0,0 +1,11 @@
++#ifndef __PPC_PLATFORMS_PMAC_PIC_H
++#define __PPC_PLATFORMS_PMAC_PIC_H
++
++#include <linux/irq.h>
++
++extern struct hw_interrupt_type pmac_pic;
++
++void pmac_pic_init(void);
++int pmac_get_irq(struct pt_regs *regs);
++
++#endif /* __PPC_PLATFORMS_PMAC_PIC_H */
+diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/pmac.h
+@@ -0,0 +1,51 @@
++#ifndef __PMAC_H__
++#define __PMAC_H__
++
++#include <linux/pci.h>
++#include <linux/ide.h>
++#include <linux/irq.h>
++
++/*
++ * Declaration for the various functions exported by the
++ * pmac_* files. Mostly for use by pmac_setup
++ */
++
++struct rtc_time;
++
++extern long pmac_time_init(void);
++extern unsigned long pmac_get_boot_time(void);
++extern void pmac_get_rtc_time(struct rtc_time *);
++extern int pmac_set_rtc_time(struct rtc_time *);
++extern void pmac_read_rtc_time(void);
++extern void pmac_calibrate_decr(void);
++extern void pmac_pcibios_fixup(void);
++extern void pmac_pci_init(void);
++extern unsigned long pmac_ide_get_base(int index);
++extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
++ unsigned long data_port, unsigned long ctrl_port, int *irq);
++
++extern void pmac_nvram_update(void);
++extern unsigned char pmac_nvram_read_byte(int addr);
++extern void pmac_nvram_write_byte(int addr, unsigned char val);
++extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
++extern void pmac_pcibios_after_init(void);
++extern int of_show_percpuinfo(struct seq_file *m, int i);
++
++extern void pmac_pci_init(void);
++extern void pmac_setup_pci_dma(void);
++extern void pmac_check_ht_link(void);
++
++extern void pmac_setup_smp(void);
++
++extern unsigned long pmac_ide_get_base(int index);
++extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
++ unsigned long data_port, unsigned long ctrl_port, int *irq);
++
++extern int pmac_nvram_init(void);
++
++extern struct hw_interrupt_type pmac_pic;
++
++void pmac_pic_init(void);
++int pmac_get_irq(struct pt_regs *regs);
++
++#endif /* __PMAC_H__ */
+diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/setup.c
+@@ -0,0 +1,794 @@
++/*
++ * Powermac setup and early boot code plus other random bits.
++ *
++ * PowerPC version
++ * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
++ *
++ * Adapted for Power Macintosh by Paul Mackerras
++ * Copyright (C) 1996 Paul Mackerras (paulus at samba.org)
++ *
++ * Derived from "arch/alpha/kernel/setup.c"
++ * Copyright (C) 1995 Linus Torvalds
++ *
++ * Maintained by Benjamin Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++/*
++ * bootup setup stuff..
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/tty.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/major.h>
++#include <linux/initrd.h>
++#include <linux/vt_kern.h>
++#include <linux/console.h>
++#include <linux/ide.h>
++#include <linux/pci.h>
++#include <linux/adb.h>
++#include <linux/cuda.h>
++#include <linux/pmu.h>
++#include <linux/irq.h>
++#include <linux/seq_file.h>
++#include <linux/root_dev.h>
++#include <linux/bitops.h>
++#include <linux/suspend.h>
++
++#include <asm/reg.h>
++#include <asm/sections.h>
++#include <asm/prom.h>
++#include <asm/system.h>
++#include <asm/pgtable.h>
++#include <asm/io.h>
++#include <asm/pci-bridge.h>
++#include <asm/ohare.h>
++#include <asm/mediabay.h>
++#include <asm/machdep.h>
++#include <asm/dma.h>
++#include <asm/cputable.h>
++#include <asm/btext.h>
++#include <asm/pmac_feature.h>
++#include <asm/time.h>
++#include <asm/of_device.h>
++#include <asm/mmu_context.h>
++#include <asm/iommu.h>
++#include <asm/smu.h>
++#include <asm/pmc.h>
++#include <asm/mpic.h>
++
++#include "pmac.h"
++
++#undef SHOW_GATWICK_IRQS
++
++unsigned char drive_info;
++
++int ppc_override_l2cr = 0;
++int ppc_override_l2cr_value;
++int has_l2cache = 0;
++
++int pmac_newworld = 1;
++
++static int current_root_goodness = -1;
++
++extern int pmac_newworld;
++extern struct machdep_calls pmac_md;
++
++#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
++
++#ifdef CONFIG_PPC64
++#include <asm/udbg.h>
++int sccdbg;
++#endif
++
++extern void zs_kgdb_hook(int tty_num);
++
++sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
++EXPORT_SYMBOL(sys_ctrler);
++
++#ifdef CONFIG_PMAC_SMU
++unsigned long smu_cmdbuf_abs;
++EXPORT_SYMBOL(smu_cmdbuf_abs);
++#endif
++
++#ifdef CONFIG_SMP
++extern struct smp_ops_t psurge_smp_ops;
++extern struct smp_ops_t core99_smp_ops;
++#endif /* CONFIG_SMP */
++
++static void pmac_show_cpuinfo(struct seq_file *m)
++{
++ struct device_node *np;
++ char *pp;
++ int plen;
++ int mbmodel;
++ unsigned int mbflags;
++ char* mbname;
++
++ mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL,
++ PMAC_MB_INFO_MODEL, 0);
++ mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL,
++ PMAC_MB_INFO_FLAGS, 0);
++ if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME,
++ (long) &mbname) != 0)
++ mbname = "Unknown";
++
++ /* find motherboard type */
++ seq_printf(m, "machine\t\t: ");
++ np = of_find_node_by_path("/");
++ if (np != NULL) {
++ pp = (char *) get_property(np, "model", NULL);
++ if (pp != NULL)
++ seq_printf(m, "%s\n", pp);
++ else
++ seq_printf(m, "PowerMac\n");
++ pp = (char *) get_property(np, "compatible", &plen);
++ if (pp != NULL) {
++ seq_printf(m, "motherboard\t:");
++ while (plen > 0) {
++ int l = strlen(pp) + 1;
++ seq_printf(m, " %s", pp);
++ plen -= l;
++ pp += l;
++ }
++ seq_printf(m, "\n");
++ }
++ of_node_put(np);
++ } else
++ seq_printf(m, "PowerMac\n");
++
++ /* print parsed model */
++ seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
++ seq_printf(m, "pmac flags\t: %08x\n", mbflags);
++
++ /* find l2 cache info */
++ np = of_find_node_by_name(NULL, "l2-cache");
++ if (np == NULL)
++ np = of_find_node_by_type(NULL, "cache");
++ if (np != NULL) {
++ unsigned int *ic = (unsigned int *)
++ get_property(np, "i-cache-size", NULL);
++ unsigned int *dc = (unsigned int *)
++ get_property(np, "d-cache-size", NULL);
++ seq_printf(m, "L2 cache\t:");
++ has_l2cache = 1;
++ if (get_property(np, "cache-unified", NULL) != 0 && dc) {
++ seq_printf(m, " %dK unified", *dc / 1024);
++ } else {
++ if (ic)
++ seq_printf(m, " %dK instruction", *ic / 1024);
++ if (dc)
++ seq_printf(m, "%s %dK data",
++ (ic? " +": ""), *dc / 1024);
++ }
++ pp = get_property(np, "ram-type", NULL);
++ if (pp)
++ seq_printf(m, " %s", pp);
++ seq_printf(m, "\n");
++ of_node_put(np);
++ }
++
++ /* Indicate newworld/oldworld */
++ seq_printf(m, "pmac-generation\t: %s\n",
++ pmac_newworld ? "NewWorld" : "OldWorld");
++}
++
++static void pmac_show_percpuinfo(struct seq_file *m, int i)
++{
++#ifdef CONFIG_CPU_FREQ_PMAC
++ extern unsigned int pmac_get_one_cpufreq(int i);
++ unsigned int freq = pmac_get_one_cpufreq(i);
++ if (freq != 0) {
++ seq_printf(m, "clock\t\t: %dMHz\n", freq/1000);
++ return;
++ }
++#endif /* CONFIG_CPU_FREQ_PMAC */
++}
++
++#ifndef CONFIG_ADB_CUDA
++int find_via_cuda(void)
++{
++ if (!find_devices("via-cuda"))
++ return 0;
++ printk("WARNING ! Your machine is CUDA-based but your kernel\n");
++ printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n");
++ return 0;
++}
++#endif
++
++#ifndef CONFIG_ADB_PMU
++int find_via_pmu(void)
++{
++ if (!find_devices("via-pmu"))
++ return 0;
++ printk("WARNING ! Your machine is PMU-based but your kernel\n");
++ printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");
++ return 0;
++}
++#endif
++
++#ifndef CONFIG_PMAC_SMU
++int smu_init(void)
++{
++ /* should check and warn if SMU is present */
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_PPC32
++static volatile u32 *sysctrl_regs;
++
++static void __init ohare_init(void)
++{
++ /* this area has the CPU identification register
++ and some registers used by smp boards */
++ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
++
++ /*
++ * Turn on the L2 cache.
++ * We assume that we have a PSX memory controller iff
++ * we have an ohare I/O controller.
++ */
++ if (find_devices("ohare") != NULL) {
++ if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
++ if (sysctrl_regs[4] & 0x10)
++ sysctrl_regs[4] |= 0x04000020;
++ else
++ sysctrl_regs[4] |= 0x04000000;
++ if(has_l2cache)
++ printk(KERN_INFO "Level 2 cache enabled\n");
++ }
++ }
++}
++
++static void __init l2cr_init(void)
++{
++ /* Checks "l2cr-value" property in the registry */
++ if (cpu_has_feature(CPU_FTR_L2CR)) {
++ struct device_node *np = find_devices("cpus");
++ if (np == 0)
++ np = find_type_devices("cpu");
++ if (np != 0) {
++ unsigned int *l2cr = (unsigned int *)
++ get_property(np, "l2cr-value", NULL);
++ if (l2cr != 0) {
++ ppc_override_l2cr = 1;
++ ppc_override_l2cr_value = *l2cr;
++ _set_L2CR(0);
++ _set_L2CR(ppc_override_l2cr_value);
++ }
++ }
++ }
++
++ if (ppc_override_l2cr)
++ printk(KERN_INFO "L2CR overridden (0x%x), "
++ "backside cache is %s\n",
++ ppc_override_l2cr_value,
++ (ppc_override_l2cr_value & 0x80000000)
++ ? "enabled" : "disabled");
++}
++#endif
++
++void __init pmac_setup_arch(void)
++{
++ struct device_node *cpu, *ic;
++ int *fp;
++ unsigned long pvr;
++
++ pvr = PVR_VER(mfspr(SPRN_PVR));
++
++ /* Set loops_per_jiffy to a half-way reasonable value,
++ for use until calibrate_delay gets called. */
++ loops_per_jiffy = 50000000 / HZ;
++ cpu = of_find_node_by_type(NULL, "cpu");
++ if (cpu != NULL) {
++ fp = (int *) get_property(cpu, "clock-frequency", NULL);
++ if (fp != NULL) {
++ if (pvr >= 0x30 && pvr < 0x80)
++ /* PPC970 etc. */
++ loops_per_jiffy = *fp / (3 * HZ);
++ else if (pvr == 4 || pvr >= 8)
++ /* 604, G3, G4 etc. */
++ loops_per_jiffy = *fp / HZ;
++ else
++ /* 601, 603, etc. */
++ loops_per_jiffy = *fp / (2 * HZ);
++ }
++ of_node_put(cpu);
++ }
++
++ /* See if newworld or oldworld */
++ for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; )
++ if (get_property(ic, "interrupt-controller", NULL))
++ break;
++ pmac_newworld = (ic != NULL);
++ if (ic)
++ of_node_put(ic);
++
++ /* Lookup PCI hosts */
++ pmac_pci_init();
++
++#ifdef CONFIG_PPC32
++ ohare_init();
++ l2cr_init();
++#endif /* CONFIG_PPC32 */
++
++#ifdef CONFIG_PPC64
++ /* Probe motherboard chipset */
++ /* this is done earlier in setup_arch for 32-bit */
++ pmac_feature_init();
++
++ /* We can NAP */
++ powersave_nap = 1;
++ printk(KERN_INFO "Using native/NAP idle loop\n");
++#endif
++
++#ifdef CONFIG_KGDB
++ zs_kgdb_hook(0);
++#endif
++
++ find_via_cuda();
++ find_via_pmu();
++ smu_init();
++
++#ifdef CONFIG_NVRAM
++ pmac_nvram_init();
++#endif
++
++#ifdef CONFIG_PPC32
++#ifdef CONFIG_BLK_DEV_INITRD
++ if (initrd_start)
++ ROOT_DEV = Root_RAM0;
++ else
++#endif
++ ROOT_DEV = DEFAULT_ROOT_DEVICE;
++#endif
++
++#ifdef CONFIG_SMP
++ /* Check for Core99 */
++ if (find_devices("uni-n") || find_devices("u3"))
++ smp_ops = &core99_smp_ops;
++#ifdef CONFIG_PPC32
++ else
++ smp_ops = &psurge_smp_ops;
++#endif
++#endif /* CONFIG_SMP */
++}
++
++char *bootpath;
++char *bootdevice;
++void *boot_host;
++int boot_target;
++int boot_part;
++extern dev_t boot_dev;
++
++#ifdef CONFIG_SCSI
++void __init note_scsi_host(struct device_node *node, void *host)
++{
++ int l;
++ char *p;
++
++ l = strlen(node->full_name);
++ if (bootpath != NULL && bootdevice != NULL
++ && strncmp(node->full_name, bootdevice, l) == 0
++ && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
++ boot_host = host;
++ /*
++ * There's a bug in OF 1.0.5. (Why am I not surprised.)
++ * If you pass a path like scsi/sd at 1:0 to canon, it returns
++ * something like /bandit at F2000000/gc at 10/53c94 at 10000/sd at 0,0
++ * That is, the scsi target number doesn't get preserved.
++ * So we pick the target number out of bootpath and use that.
++ */
++ p = strstr(bootpath, "/sd@");
++ if (p != NULL) {
++ p += 4;
++ boot_target = simple_strtoul(p, NULL, 10);
++ p = strchr(p, ':');
++ if (p != NULL)
++ boot_part = simple_strtoul(p + 1, NULL, 10);
++ }
++ }
++}
++EXPORT_SYMBOL(note_scsi_host);
++#endif
++
++#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
++static dev_t __init find_ide_boot(void)
++{
++ char *p;
++ int n;
++ dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
++
++ if (bootdevice == NULL)
++ return 0;
++ p = strrchr(bootdevice, '/');
++ if (p == NULL)
++ return 0;
++ n = p - bootdevice;
++
++ return pmac_find_ide_boot(bootdevice, n);
++}
++#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
++
++static void __init find_boot_device(void)
++{
++#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
++ boot_dev = find_ide_boot();
++#endif
++}
++
++/* TODO: Merge the suspend-to-ram with the common code !!!
++ * currently, this is a stub implementation for suspend-to-disk
++ * only
++ */
++
++#ifdef CONFIG_SOFTWARE_SUSPEND
++
++static int pmac_pm_prepare(suspend_state_t state)
++{
++ printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
++
++ return 0;
++}
++
++static int pmac_pm_enter(suspend_state_t state)
++{
++ printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
++
++ /* Giveup the lazy FPU & vec so we don't have to back them
++ * up from the low level code
++ */
++ enable_kernel_fp();
++
++#ifdef CONFIG_ALTIVEC
++ if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
++ enable_kernel_altivec();
++#endif /* CONFIG_ALTIVEC */
++
++ return 0;
++}
++
++static int pmac_pm_finish(suspend_state_t state)
++{
++ printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
++
++ /* Restore userland MMU context */
++ set_context(current->active_mm->context, current->active_mm->pgd);
++
++ return 0;
++}
++
++static struct pm_ops pmac_pm_ops = {
++ .pm_disk_mode = PM_DISK_SHUTDOWN,
++ .prepare = pmac_pm_prepare,
++ .enter = pmac_pm_enter,
++ .finish = pmac_pm_finish,
++};
++
++#endif /* CONFIG_SOFTWARE_SUSPEND */
++
++static int initializing = 1;
++
++static int pmac_late_init(void)
++{
++ initializing = 0;
++#ifdef CONFIG_SOFTWARE_SUSPEND
++ pm_set_ops(&pmac_pm_ops);
++#endif /* CONFIG_SOFTWARE_SUSPEND */
++ return 0;
++}
++
++late_initcall(pmac_late_init);
++
++/* can't be __init - can be called whenever a disk is first accessed */
++void note_bootable_part(dev_t dev, int part, int goodness)
++{
++ static int found_boot = 0;
++ char *p;
++
++ if (!initializing)
++ return;
++ if ((goodness <= current_root_goodness) &&
++ ROOT_DEV != DEFAULT_ROOT_DEVICE)
++ return;
++ p = strstr(saved_command_line, "root=");
++ if (p != NULL && (p == saved_command_line || p[-1] == ' '))
++ return;
++
++ if (!found_boot) {
++ find_boot_device();
++ found_boot = 1;
++ }
++ if (!boot_dev || dev == boot_dev) {
++ ROOT_DEV = dev + part;
++ boot_dev = 0;
++ current_root_goodness = goodness;
++ }
++}
++
++#ifdef CONFIG_ADB_CUDA
++static void cuda_restart(void)
++{
++ struct adb_request req;
++
++ cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM);
++ for (;;)
++ cuda_poll();
++}
++
++static void cuda_shutdown(void)
++{
++ struct adb_request req;
++
++ cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN);
++ for (;;)
++ cuda_poll();
++}
++
++#else
++#define cuda_restart()
++#define cuda_shutdown()
++#endif
++
++#ifndef CONFIG_ADB_PMU
++#define pmu_restart()
++#define pmu_shutdown()
++#endif
++
++#ifndef CONFIG_PMAC_SMU
++#define smu_restart()
++#define smu_shutdown()
++#endif
++
++static void pmac_restart(char *cmd)
++{
++ switch (sys_ctrler) {
++ case SYS_CTRLER_CUDA:
++ cuda_restart();
++ break;
++ case SYS_CTRLER_PMU:
++ pmu_restart();
++ break;
++ case SYS_CTRLER_SMU:
++ smu_restart();
++ break;
++ default: ;
++ }
++}
++
++static void pmac_power_off(void)
++{
++ switch (sys_ctrler) {
++ case SYS_CTRLER_CUDA:
++ cuda_shutdown();
++ break;
++ case SYS_CTRLER_PMU:
++ pmu_shutdown();
++ break;
++ case SYS_CTRLER_SMU:
++ smu_shutdown();
++ break;
++ default: ;
++ }
++}
++
++static void
++pmac_halt(void)
++{
++ pmac_power_off();
++}
++
++#ifdef CONFIG_PPC32
++void __init pmac_init(void)
++{
++ /* isa_io_base gets set in pmac_pci_init */
++ isa_mem_base = PMAC_ISA_MEM_BASE;
++ pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
++ ISA_DMA_THRESHOLD = ~0L;
++ DMA_MODE_READ = 1;
++ DMA_MODE_WRITE = 2;
++
++ ppc_md = pmac_md;
++
++#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
++ ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
++ ppc_ide_md.default_io_base = pmac_ide_get_base;
++#endif /* CONFIG_BLK_DEV_IDE_PMAC */
++#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
++
++ if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
++
++}
++#endif
++
++/*
++ * Early initialization.
++ */
++static void __init pmac_init_early(void)
++{
++#ifdef CONFIG_PPC64
++ /* Initialize hash table, from now on, we can take hash faults
++ * and call ioremap
++ */
++ hpte_init_native();
++
++ /* Init SCC */
++ if (strstr(cmd_line, "sccdbg")) {
++ sccdbg = 1;
++ udbg_init_scc(NULL);
++ }
++
++ /* Setup interrupt mapping options */
++ ppc64_interrupt_controller = IC_OPEN_PIC;
++
++ iommu_init_early_u3();
++#endif
++}
++
++static void __init pmac_progress(char *s, unsigned short hex)
++{
++#ifdef CONFIG_PPC64
++ if (sccdbg) {
++ udbg_puts(s);
++ udbg_puts("\n");
++ return;
++ }
++#endif
++#ifdef CONFIG_BOOTX_TEXT
++ if (boot_text_mapped) {
++ btext_drawstring(s);
++ btext_drawchar('\n');
++ }
++#endif /* CONFIG_BOOTX_TEXT */
++}
++
++/*
++ * pmac has no legacy IO, anything calling this function has to
++ * fail or bad things will happen
++ */
++static int pmac_check_legacy_ioport(unsigned int baseport)
++{
++ return -ENODEV;
++}
++
++static int __init pmac_declare_of_platform_devices(void)
++{
++ struct device_node *np, *npp;
++
++ np = find_devices("uni-n");
++ if (np) {
++ for (np = np->child; np != NULL; np = np->sibling)
++ if (strncmp(np->name, "i2c", 3) == 0) {
++ of_platform_device_create(np, "uni-n-i2c",
++ NULL);
++ break;
++ }
++ }
++ np = find_devices("valkyrie");
++ if (np)
++ of_platform_device_create(np, "valkyrie", NULL);
++ np = find_devices("platinum");
++ if (np)
++ of_platform_device_create(np, "platinum", NULL);
++
++ npp = of_find_node_by_name(NULL, "u3");
++ if (npp) {
++ for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) {
++ if (strncmp(np->name, "i2c", 3) == 0) {
++ of_platform_device_create(np, "u3-i2c", NULL);
++ of_node_put(np);
++ break;
++ }
++ }
++ of_node_put(npp);
++ }
++ np = of_find_node_by_type(NULL, "smu");
++ if (np) {
++ of_platform_device_create(np, "smu", NULL);
++ of_node_put(np);
++ }
++
++ return 0;
++}
++
++device_initcall(pmac_declare_of_platform_devices);
++
++/*
++ * Called very early, MMU is off, device-tree isn't unflattened
++ */
++static int __init pmac_probe(int platform)
++{
++#ifdef CONFIG_PPC64
++ if (platform != PLATFORM_POWERMAC)
++ return 0;
++
++ /*
++ * On U3, the DART (iommu) must be allocated now since it
++ * has an impact on htab_initialize (due to the large page it
++ * occupies having to be broken up so the DART itself is not
++ * part of the cacheable linar mapping
++ */
++ alloc_u3_dart_table();
++#endif
++
++#ifdef CONFIG_PMAC_SMU
++ /*
++ * SMU based G5s need some memory below 2Gb, at least the current
++ * driver needs that. We have to allocate it now. We allocate 4k
++ * (1 small page) for now.
++ */
++ smu_cmdbuf_abs = lmb_alloc_base(4096, 4096, 0x80000000UL);
++#endif /* CONFIG_PMAC_SMU */
++
++ return 1;
++}
++
++#ifdef CONFIG_PPC64
++static int pmac_probe_mode(struct pci_bus *bus)
++{
++ struct device_node *node = bus->sysdata;
++
++ /* We need to use normal PCI probing for the AGP bus,
++ since the device for the AGP bridge isn't in the tree. */
++ if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
++ return PCI_PROBE_NORMAL;
++
++ return PCI_PROBE_DEVTREE;
++}
++#endif
++
++struct machdep_calls __initdata pmac_md = {
++#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
++ .cpu_die = generic_mach_cpu_die,
++#endif
++ .probe = pmac_probe,
++ .setup_arch = pmac_setup_arch,
++ .init_early = pmac_init_early,
++ .show_cpuinfo = pmac_show_cpuinfo,
++ .show_percpuinfo = pmac_show_percpuinfo,
++ .init_IRQ = pmac_pic_init,
++ .get_irq = mpic_get_irq, /* changed later */
++ .pcibios_fixup = pmac_pcibios_fixup,
++ .restart = pmac_restart,
++ .power_off = pmac_power_off,
++ .halt = pmac_halt,
++ .time_init = pmac_time_init,
++ .get_boot_time = pmac_get_boot_time,
++ .set_rtc_time = pmac_set_rtc_time,
++ .get_rtc_time = pmac_get_rtc_time,
++ .calibrate_decr = pmac_calibrate_decr,
++ .feature_call = pmac_do_feature_call,
++ .check_legacy_ioport = pmac_check_legacy_ioport,
++ .progress = pmac_progress,
++#ifdef CONFIG_PPC64
++ .pci_probe_mode = pmac_probe_mode,
++ .idle_loop = native_idle,
++ .enable_pmcs = power4_enable_pmcs,
++#endif
++#ifdef CONFIG_PPC32
++ .pcibios_enable_device_hook = pmac_pci_enable_device_hook,
++ .pcibios_after_init = pmac_pcibios_after_init,
++ .phys_mem_access_prot = pci_phys_mem_access_prot,
++#endif
++};
+diff --git a/arch/powerpc/platforms/powermac/sleep.S b/arch/powerpc/platforms/powermac/sleep.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/sleep.S
+@@ -0,0 +1,396 @@
++/*
++ * This file contains sleep low-level functions for PowerBook G3.
++ * Copyright (C) 1999 Benjamin Herrenschmidt (benh at kernel.crashing.org)
++ * and Paul Mackerras (paulus at samba.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/config.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/ppc_asm.h>
++#include <asm/cputable.h>
++#include <asm/cache.h>
++#include <asm/thread_info.h>
++#include <asm/asm-offsets.h>
++
++#define MAGIC 0x4c617273 /* 'Lars' */
++
++/*
++ * Structure for storing CPU registers on the stack.
++ */
++#define SL_SP 0
++#define SL_PC 4
++#define SL_MSR 8
++#define SL_SDR1 0xc
++#define SL_SPRG0 0x10 /* 4 sprg's */
++#define SL_DBAT0 0x20
++#define SL_IBAT0 0x28
++#define SL_DBAT1 0x30
++#define SL_IBAT1 0x38
++#define SL_DBAT2 0x40
++#define SL_IBAT2 0x48
++#define SL_DBAT3 0x50
++#define SL_IBAT3 0x58
++#define SL_TB 0x60
++#define SL_R2 0x68
++#define SL_CR 0x6c
++#define SL_R12 0x70 /* r12 to r31 */
++#define SL_SIZE (SL_R12 + 80)
++
++ .section .text
++ .align 5
++
++#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC)
++
++/* This gets called by via-pmu.c late during the sleep process.
++ * The PMU was already send the sleep command and will shut us down
++ * soon. We need to save all that is needed and setup the wakeup
++ * vector that will be called by the ROM on wakeup
++ */
++_GLOBAL(low_sleep_handler)
++#ifndef CONFIG_6xx
++ blr
++#else
++ mflr r0
++ stw r0,4(r1)
++ stwu r1,-SL_SIZE(r1)
++ mfcr r0
++ stw r0,SL_CR(r1)
++ stw r2,SL_R2(r1)
++ stmw r12,SL_R12(r1)
++
++ /* Save MSR & SDR1 */
++ mfmsr r4
++ stw r4,SL_MSR(r1)
++ mfsdr1 r4
++ stw r4,SL_SDR1(r1)
++
++ /* Get a stable timebase and save it */
++1: mftbu r4
++ stw r4,SL_TB(r1)
++ mftb r5
++ stw r5,SL_TB+4(r1)
++ mftbu r3
++ cmpw r3,r4
++ bne 1b
++
++ /* Save SPRGs */
++ mfsprg r4,0
++ stw r4,SL_SPRG0(r1)
++ mfsprg r4,1
++ stw r4,SL_SPRG0+4(r1)
++ mfsprg r4,2
++ stw r4,SL_SPRG0+8(r1)
++ mfsprg r4,3
++ stw r4,SL_SPRG0+12(r1)
++
++ /* Save BATs */
++ mfdbatu r4,0
++ stw r4,SL_DBAT0(r1)
++ mfdbatl r4,0
++ stw r4,SL_DBAT0+4(r1)
++ mfdbatu r4,1
++ stw r4,SL_DBAT1(r1)
++ mfdbatl r4,1
++ stw r4,SL_DBAT1+4(r1)
++ mfdbatu r4,2
++ stw r4,SL_DBAT2(r1)
++ mfdbatl r4,2
++ stw r4,SL_DBAT2+4(r1)
++ mfdbatu r4,3
++ stw r4,SL_DBAT3(r1)
++ mfdbatl r4,3
++ stw r4,SL_DBAT3+4(r1)
++ mfibatu r4,0
++ stw r4,SL_IBAT0(r1)
++ mfibatl r4,0
++ stw r4,SL_IBAT0+4(r1)
++ mfibatu r4,1
++ stw r4,SL_IBAT1(r1)
++ mfibatl r4,1
++ stw r4,SL_IBAT1+4(r1)
++ mfibatu r4,2
++ stw r4,SL_IBAT2(r1)
++ mfibatl r4,2
++ stw r4,SL_IBAT2+4(r1)
++ mfibatu r4,3
++ stw r4,SL_IBAT3(r1)
++ mfibatl r4,3
++ stw r4,SL_IBAT3+4(r1)
++
++ /* Backup various CPU config stuffs */
++ bl __save_cpu_setup
++
++ /* The ROM can wake us up via 2 different vectors:
++ * - On wallstreet & lombard, we must write a magic
++ * value 'Lars' at address 4 and a pointer to a
++ * memory location containing the PC to resume from
++ * at address 0.
++ * - On Core99, we must store the wakeup vector at
++ * address 0x80 and eventually it's parameters
++ * at address 0x84. I've have some trouble with those
++ * parameters however and I no longer use them.
++ */
++ lis r5,grackle_wake_up at ha
++ addi r5,r5,grackle_wake_up at l
++ tophys(r5,r5)
++ stw r5,SL_PC(r1)
++ lis r4,KERNELBASE at h
++ tophys(r5,r1)
++ addi r5,r5,SL_PC
++ lis r6,MAGIC at ha
++ addi r6,r6,MAGIC at l
++ stw r5,0(r4)
++ stw r6,4(r4)
++ /* Setup stuffs at 0x80-0x84 for Core99 */
++ lis r3,core99_wake_up at ha
++ addi r3,r3,core99_wake_up at l
++ tophys(r3,r3)
++ stw r3,0x80(r4)
++ stw r5,0x84(r4)
++ /* Store a pointer to our backup storage into
++ * a kernel global
++ */
++ lis r3,sleep_storage at ha
++ addi r3,r3,sleep_storage at l
++ stw r5,0(r3)
++
++ .globl low_cpu_die
++low_cpu_die:
++ /* Flush & disable all caches */
++ bl flush_disable_caches
++
++ /* Turn off data relocation. */
++ mfmsr r3 /* Save MSR in r7 */
++ rlwinm r3,r3,0,28,26 /* Turn off DR bit */
++ sync
++ mtmsr r3
++ isync
++
++BEGIN_FTR_SECTION
++ /* Flush any pending L2 data prefetches to work around HW bug */
++ sync
++ lis r3,0xfff0
++ lwz r0,0(r3) /* perform cache-inhibited load to ROM */
++ sync /* (caches are disabled at this point) */
++END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
++
++/*
++ * Set the HID0 and MSR for sleep.
++ */
++ mfspr r2,SPRN_HID0
++ rlwinm r2,r2,0,10,7 /* clear doze, nap */
++ oris r2,r2,HID0_SLEEP at h
++ sync
++ isync
++ mtspr SPRN_HID0,r2
++ sync
++
++/* This loop puts us back to sleep in case we have a spurrious
++ * wakeup so that the host bridge properly stays asleep. The
++ * CPU will be turned off, either after a known time (about 1
++ * second) on wallstreet & lombard, or as soon as the CPU enters
++ * SLEEP mode on core99
++ */
++ mfmsr r2
++ oris r2,r2,MSR_POW at h
++1: sync
++ mtmsr r2
++ isync
++ b 1b
++
++/*
++ * Here is the resume code.
++ */
++
++
++/*
++ * Core99 machines resume here
++ * r4 has the physical address of SL_PC(sp) (unused)
++ */
++_GLOBAL(core99_wake_up)
++ /* Make sure HID0 no longer contains any sleep bit and that data cache
++ * is disabled
++ */
++ mfspr r3,SPRN_HID0
++ rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */
++ rlwinm 3,r3,0,18,15 /* clear DCE, ICE */
++ mtspr SPRN_HID0,r3
++ sync
++ isync
++
++ /* sanitize MSR */
++ mfmsr r3
++ ori r3,r3,MSR_EE|MSR_IP
++ xori r3,r3,MSR_EE|MSR_IP
++ sync
++ isync
++ mtmsr r3
++ sync
++ isync
++
++ /* Recover sleep storage */
++ lis r3,sleep_storage at ha
++ addi r3,r3,sleep_storage at l
++ tophys(r3,r3)
++ lwz r1,0(r3)
++
++ /* Pass thru to older resume code ... */
++/*
++ * Here is the resume code for older machines.
++ * r1 has the physical address of SL_PC(sp).
++ */
++
++grackle_wake_up:
++
++ /* Restore the kernel's segment registers before
++ * we do any r1 memory access as we are not sure they
++ * are in a sane state above the first 256Mb region
++ */
++ li r0,16 /* load up segment register values */
++ mtctr r0 /* for context 0 */
++ lis r3,0x2000 /* Ku = 1, VSID = 0 */
++ li r4,0
++3: mtsrin r3,r4
++ addi r3,r3,0x111 /* increment VSID */
++ addis r4,r4,0x1000 /* address of next segment */
++ bdnz 3b
++ sync
++ isync
++
++ subi r1,r1,SL_PC
++
++ /* Restore various CPU config stuffs */
++ bl __restore_cpu_setup
++
++ /* Make sure all FPRs have been initialized */
++ bl reloc_offset
++ bl __init_fpu_registers
++
++ /* Invalidate & enable L1 cache, we don't care about
++ * whatever the ROM may have tried to write to memory
++ */
++ bl __inval_enable_L1
++
++ /* Restore the BATs, and SDR1. Then we can turn on the MMU. */
++ lwz r4,SL_SDR1(r1)
++ mtsdr1 r4
++ lwz r4,SL_SPRG0(r1)
++ mtsprg 0,r4
++ lwz r4,SL_SPRG0+4(r1)
++ mtsprg 1,r4
++ lwz r4,SL_SPRG0+8(r1)
++ mtsprg 2,r4
++ lwz r4,SL_SPRG0+12(r1)
++ mtsprg 3,r4
++
++ lwz r4,SL_DBAT0(r1)
++ mtdbatu 0,r4
++ lwz r4,SL_DBAT0+4(r1)
++ mtdbatl 0,r4
++ lwz r4,SL_DBAT1(r1)
++ mtdbatu 1,r4
++ lwz r4,SL_DBAT1+4(r1)
++ mtdbatl 1,r4
++ lwz r4,SL_DBAT2(r1)
++ mtdbatu 2,r4
++ lwz r4,SL_DBAT2+4(r1)
++ mtdbatl 2,r4
++ lwz r4,SL_DBAT3(r1)
++ mtdbatu 3,r4
++ lwz r4,SL_DBAT3+4(r1)
++ mtdbatl 3,r4
++ lwz r4,SL_IBAT0(r1)
++ mtibatu 0,r4
++ lwz r4,SL_IBAT0+4(r1)
++ mtibatl 0,r4
++ lwz r4,SL_IBAT1(r1)
++ mtibatu 1,r4
++ lwz r4,SL_IBAT1+4(r1)
++ mtibatl 1,r4
++ lwz r4,SL_IBAT2(r1)
++ mtibatu 2,r4
++ lwz r4,SL_IBAT2+4(r1)
++ mtibatl 2,r4
++ lwz r4,SL_IBAT3(r1)
++ mtibatu 3,r4
++ lwz r4,SL_IBAT3+4(r1)
++ mtibatl 3,r4
++
++BEGIN_FTR_SECTION
++ li r4,0
++ mtspr SPRN_DBAT4U,r4
++ mtspr SPRN_DBAT4L,r4
++ mtspr SPRN_DBAT5U,r4
++ mtspr SPRN_DBAT5L,r4
++ mtspr SPRN_DBAT6U,r4
++ mtspr SPRN_DBAT6L,r4
++ mtspr SPRN_DBAT7U,r4
++ mtspr SPRN_DBAT7L,r4
++ mtspr SPRN_IBAT4U,r4
++ mtspr SPRN_IBAT4L,r4
++ mtspr SPRN_IBAT5U,r4
++ mtspr SPRN_IBAT5L,r4
++ mtspr SPRN_IBAT6U,r4
++ mtspr SPRN_IBAT6L,r4
++ mtspr SPRN_IBAT7U,r4
++ mtspr SPRN_IBAT7L,r4
++END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
++
++ /* Flush all TLBs */
++ lis r4,0x1000
++1: addic. r4,r4,-0x1000
++ tlbie r4
++ blt 1b
++ sync
++
++ /* restore the MSR and turn on the MMU */
++ lwz r3,SL_MSR(r1)
++ bl turn_on_mmu
++
++ /* get back the stack pointer */
++ tovirt(r1,r1)
++
++ /* Restore TB */
++ li r3,0
++ mttbl r3
++ lwz r3,SL_TB(r1)
++ lwz r4,SL_TB+4(r1)
++ mttbu r3
++ mttbl r4
++
++ /* Restore the callee-saved registers and return */
++ lwz r0,SL_CR(r1)
++ mtcr r0
++ lwz r2,SL_R2(r1)
++ lmw r12,SL_R12(r1)
++ addi r1,r1,SL_SIZE
++ lwz r0,4(r1)
++ mtlr r0
++ blr
++
++turn_on_mmu:
++ mflr r4
++ tovirt(r4,r4)
++ mtsrr0 r4
++ mtsrr1 r3
++ sync
++ isync
++ rfi
++
++#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
++
++ .section .data
++ .balign L1_CACHE_BYTES
++sleep_storage:
++ .long 0
++ .balign L1_CACHE_BYTES, 0
++
++#endif /* CONFIG_6xx */
++ .section .text
+diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/smp.c
+@@ -0,0 +1,865 @@
++/*
++ * SMP support for power macintosh.
++ *
++ * We support both the old "powersurge" SMP architecture
++ * and the current Core99 (G4 PowerMac) machines.
++ *
++ * Note that we don't support the very first rev. of
++ * Apple/DayStar 2 CPUs board, the one with the funky
++ * watchdog. Hopefully, none of these should be there except
++ * maybe internally to Apple. I should probably still add some
++ * code to detect this card though and disable SMP. --BenH.
++ *
++ * Support Macintosh G4 SMP by Troy Benjegerdes (hozer at drgw.net)
++ * and Ben Herrenschmidt <benh at kernel.crashing.org>.
++ *
++ * Support for DayStar quad CPU cards
++ * Copyright (C) XLR8, Inc. 1994-2000
++ *
++ * 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/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/errno.h>
++#include <linux/hardirq.h>
++#include <linux/cpu.h>
++
++#include <asm/ptrace.h>
++#include <asm/atomic.h>
++#include <asm/irq.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/sections.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/smp.h>
++#include <asm/machdep.h>
++#include <asm/pmac_feature.h>
++#include <asm/time.h>
++#include <asm/mpic.h>
++#include <asm/cacheflush.h>
++#include <asm/keylargo.h>
++#include <asm/pmac_low_i2c.h>
++
++#undef DEBUG
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++extern void __secondary_start_pmac_0(void);
++
++#ifdef CONFIG_PPC32
++
++/* Sync flag for HW tb sync */
++static volatile int sec_tb_reset = 0;
++
++/*
++ * Powersurge (old powermac SMP) support.
++ */
++
++/* Addresses for powersurge registers */
++#define HAMMERHEAD_BASE 0xf8000000
++#define HHEAD_CONFIG 0x90
++#define HHEAD_SEC_INTR 0xc0
++
++/* register for interrupting the primary processor on the powersurge */
++/* N.B. this is actually the ethernet ROM! */
++#define PSURGE_PRI_INTR 0xf3019000
++
++/* register for storing the start address for the secondary processor */
++/* N.B. this is the PCI config space address register for the 1st bridge */
++#define PSURGE_START 0xf2800000
++
++/* Daystar/XLR8 4-CPU card */
++#define PSURGE_QUAD_REG_ADDR 0xf8800000
++
++#define PSURGE_QUAD_IRQ_SET 0
++#define PSURGE_QUAD_IRQ_CLR 1
++#define PSURGE_QUAD_IRQ_PRIMARY 2
++#define PSURGE_QUAD_CKSTOP_CTL 3
++#define PSURGE_QUAD_PRIMARY_ARB 4
++#define PSURGE_QUAD_BOARD_ID 6
++#define PSURGE_QUAD_WHICH_CPU 7
++#define PSURGE_QUAD_CKSTOP_RDBK 8
++#define PSURGE_QUAD_RESET_CTL 11
++
++#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))
++#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)
++#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
++#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
++
++/* virtual addresses for the above */
++static volatile u8 __iomem *hhead_base;
++static volatile u8 __iomem *quad_base;
++static volatile u32 __iomem *psurge_pri_intr;
++static volatile u8 __iomem *psurge_sec_intr;
++static volatile u32 __iomem *psurge_start;
++
++/* values for psurge_type */
++#define PSURGE_NONE -1
++#define PSURGE_DUAL 0
++#define PSURGE_QUAD_OKEE 1
++#define PSURGE_QUAD_COTTON 2
++#define PSURGE_QUAD_ICEGRASS 3
++
++/* what sort of powersurge board we have */
++static int psurge_type = PSURGE_NONE;
++
++/*
++ * Set and clear IPIs for powersurge.
++ */
++static inline void psurge_set_ipi(int cpu)
++{
++ if (psurge_type == PSURGE_NONE)
++ return;
++ if (cpu == 0)
++ in_be32(psurge_pri_intr);
++ else if (psurge_type == PSURGE_DUAL)
++ out_8(psurge_sec_intr, 0);
++ else
++ PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
++}
++
++static inline void psurge_clr_ipi(int cpu)
++{
++ if (cpu > 0) {
++ switch(psurge_type) {
++ case PSURGE_DUAL:
++ out_8(psurge_sec_intr, ~0);
++ case PSURGE_NONE:
++ break;
++ default:
++ PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
++ }
++ }
++}
++
++/*
++ * On powersurge (old SMP powermac architecture) we don't have
++ * separate IPIs for separate messages like openpic does. Instead
++ * we have a bitmap for each processor, where a 1 bit means that
++ * the corresponding message is pending for that processor.
++ * Ideally each cpu's entry would be in a different cache line.
++ * -- paulus.
++ */
++static unsigned long psurge_smp_message[NR_CPUS];
++
++void psurge_smp_message_recv(struct pt_regs *regs)
++{
++ int cpu = smp_processor_id();
++ int msg;
++
++ /* clear interrupt */
++ psurge_clr_ipi(cpu);
++
++ if (num_online_cpus() < 2)
++ return;
++
++ /* make sure there is a message there */
++ for (msg = 0; msg < 4; msg++)
++ if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
++ smp_message_recv(msg, regs);
++}
++
++irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
++{
++ psurge_smp_message_recv(regs);
++ return IRQ_HANDLED;
++}
++
++static void smp_psurge_message_pass(int target, int msg)
++{
++ int i;
++
++ if (num_online_cpus() < 2)
++ return;
++
++ for (i = 0; i < NR_CPUS; i++) {
++ if (!cpu_online(i))
++ continue;
++ if (target == MSG_ALL
++ || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
++ || target == i) {
++ set_bit(msg, &psurge_smp_message[i]);
++ psurge_set_ipi(i);
++ }
++ }
++}
++
++/*
++ * Determine a quad card presence. We read the board ID register, we
++ * force the data bus to change to something else, and we read it again.
++ * It it's stable, then the register probably exist (ugh !)
++ */
++static int __init psurge_quad_probe(void)
++{
++ int type;
++ unsigned int i;
++
++ type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
++ if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
++ || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
++ return PSURGE_DUAL;
++
++ /* looks OK, try a slightly more rigorous test */
++ /* bogus is not necessarily cacheline-aligned,
++ though I don't suppose that really matters. -- paulus */
++ for (i = 0; i < 100; i++) {
++ volatile u32 bogus[8];
++ bogus[(0+i)%8] = 0x00000000;
++ bogus[(1+i)%8] = 0x55555555;
++ bogus[(2+i)%8] = 0xFFFFFFFF;
++ bogus[(3+i)%8] = 0xAAAAAAAA;
++ bogus[(4+i)%8] = 0x33333333;
++ bogus[(5+i)%8] = 0xCCCCCCCC;
++ bogus[(6+i)%8] = 0xCCCCCCCC;
++ bogus[(7+i)%8] = 0x33333333;
++ wmb();
++ asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
++ mb();
++ if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
++ return PSURGE_DUAL;
++ }
++ return type;
++}
++
++static void __init psurge_quad_init(void)
++{
++ int procbits;
++
++ if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
++ procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
++ if (psurge_type == PSURGE_QUAD_ICEGRASS)
++ PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
++ else
++ PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
++ mdelay(33);
++ out_8(psurge_sec_intr, ~0);
++ PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
++ PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
++ if (psurge_type != PSURGE_QUAD_ICEGRASS)
++ PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
++ PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
++ mdelay(33);
++ PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
++ mdelay(33);
++ PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
++ mdelay(33);
++}
++
++static int __init smp_psurge_probe(void)
++{
++ int i, ncpus;
++
++ /* We don't do SMP on the PPC601 -- paulus */
++ if (PVR_VER(mfspr(SPRN_PVR)) == 1)
++ return 1;
++
++ /*
++ * The powersurge cpu board can be used in the generation
++ * of powermacs that have a socket for an upgradeable cpu card,
++ * including the 7500, 8500, 9500, 9600.
++ * The device tree doesn't tell you if you have 2 cpus because
++ * OF doesn't know anything about the 2nd processor.
++ * Instead we look for magic bits in magic registers,
++ * in the hammerhead memory controller in the case of the
++ * dual-cpu powersurge board. -- paulus.
++ */
++ if (find_devices("hammerhead") == NULL)
++ return 1;
++
++ hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
++ quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
++ psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
++
++ psurge_type = psurge_quad_probe();
++ if (psurge_type != PSURGE_DUAL) {
++ psurge_quad_init();
++ /* All released cards using this HW design have 4 CPUs */
++ ncpus = 4;
++ } else {
++ iounmap(quad_base);
++ if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
++ /* not a dual-cpu card */
++ iounmap(hhead_base);
++ psurge_type = PSURGE_NONE;
++ return 1;
++ }
++ ncpus = 2;
++ }
++
++ psurge_start = ioremap(PSURGE_START, 4);
++ psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
++
++ /* this is not actually strictly necessary -- paulus. */
++ for (i = 1; i < ncpus; ++i)
++ smp_hw_index[i] = i;
++
++ if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
++
++ return ncpus;
++}
++
++static void __init smp_psurge_kick_cpu(int nr)
++{
++ unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
++ unsigned long a;
++
++ /* may need to flush here if secondary bats aren't setup */
++ for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
++ asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
++ asm volatile("sync");
++
++ if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
++
++ out_be32(psurge_start, start);
++ mb();
++
++ psurge_set_ipi(nr);
++ udelay(10);
++ psurge_clr_ipi(nr);
++
++ if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
++}
++
++/*
++ * With the dual-cpu powersurge board, the decrementers and timebases
++ * of both cpus are frozen after the secondary cpu is started up,
++ * until we give the secondary cpu another interrupt. This routine
++ * uses this to get the timebases synchronized.
++ * -- paulus.
++ */
++static void __init psurge_dual_sync_tb(int cpu_nr)
++{
++ int t;
++
++ set_dec(tb_ticks_per_jiffy);
++ set_tb(0, 0);
++ last_jiffy_stamp(cpu_nr) = 0;
++
++ if (cpu_nr > 0) {
++ mb();
++ sec_tb_reset = 1;
++ return;
++ }
++
++ /* wait for the secondary to have reset its TB before proceeding */
++ for (t = 10000000; t > 0 && !sec_tb_reset; --t)
++ ;
++
++ /* now interrupt the secondary, starting both TBs */
++ psurge_set_ipi(1);
++
++ smp_tb_synchronized = 1;
++}
++
++static struct irqaction psurge_irqaction = {
++ .handler = psurge_primary_intr,
++ .flags = SA_INTERRUPT,
++ .mask = CPU_MASK_NONE,
++ .name = "primary IPI",
++};
++
++static void __init smp_psurge_setup_cpu(int cpu_nr)
++{
++
++ if (cpu_nr == 0) {
++ /* If we failed to start the second CPU, we should still
++ * send it an IPI to start the timebase & DEC or we might
++ * have them stuck.
++ */
++ if (num_online_cpus() < 2) {
++ if (psurge_type == PSURGE_DUAL)
++ psurge_set_ipi(1);
++ return;
++ }
++ /* reset the entry point so if we get another intr we won't
++ * try to startup again */
++ out_be32(psurge_start, 0x100);
++ if (setup_irq(30, &psurge_irqaction))
++ printk(KERN_ERR "Couldn't get primary IPI interrupt");
++ }
++
++ if (psurge_type == PSURGE_DUAL)
++ psurge_dual_sync_tb(cpu_nr);
++}
++
++void __init smp_psurge_take_timebase(void)
++{
++ /* Dummy implementation */
++}
++
++void __init smp_psurge_give_timebase(void)
++{
++ /* Dummy implementation */
++}
++
++/* PowerSurge-style Macs */
++struct smp_ops_t psurge_smp_ops = {
++ .message_pass = smp_psurge_message_pass,
++ .probe = smp_psurge_probe,
++ .kick_cpu = smp_psurge_kick_cpu,
++ .setup_cpu = smp_psurge_setup_cpu,
++ .give_timebase = smp_psurge_give_timebase,
++ .take_timebase = smp_psurge_take_timebase,
++};
++#endif /* CONFIG_PPC32 - actually powersurge support */
++
++#ifdef CONFIG_PPC64
++/*
++ * G5s enable/disable the timebase via an i2c-connected clock chip.
++ */
++static struct device_node *pmac_tb_clock_chip_host;
++static u8 pmac_tb_pulsar_addr;
++static void (*pmac_tb_freeze)(int freeze);
++static DEFINE_SPINLOCK(timebase_lock);
++static unsigned long timebase;
++
++static void smp_core99_cypress_tb_freeze(int freeze)
++{
++ u8 data;
++ int rc;
++
++ /* Strangely, the device-tree says address is 0xd2, but darwin
++ * accesses 0xd0 ...
++ */
++ pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
++ rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
++ 0xd0 | pmac_low_i2c_read,
++ 0x81, &data, 1);
++ if (rc != 0)
++ goto bail;
++
++ data = (data & 0xf3) | (freeze ? 0x00 : 0x0c);
++
++ pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
++ rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
++ 0xd0 | pmac_low_i2c_write,
++ 0x81, &data, 1);
++
++ bail:
++ if (rc != 0) {
++ printk("Cypress Timebase %s rc: %d\n",
++ freeze ? "freeze" : "unfreeze", rc);
++ panic("Timebase freeze failed !\n");
++ }
++}
++
++
++static void smp_core99_pulsar_tb_freeze(int freeze)
++{
++ u8 data;
++ int rc;
++
++ pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
++ rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
++ pmac_tb_pulsar_addr | pmac_low_i2c_read,
++ 0x2e, &data, 1);
++ if (rc != 0)
++ goto bail;
++
++ data = (data & 0x88) | (freeze ? 0x11 : 0x22);
++
++ pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
++ rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
++ pmac_tb_pulsar_addr | pmac_low_i2c_write,
++ 0x2e, &data, 1);
++ bail:
++ if (rc != 0) {
++ printk(KERN_ERR "Pulsar Timebase %s rc: %d\n",
++ freeze ? "freeze" : "unfreeze", rc);
++ panic("Timebase freeze failed !\n");
++ }
++}
++
++
++static void smp_core99_give_timebase(void)
++{
++ /* Open i2c bus for synchronous access */
++ if (pmac_low_i2c_open(pmac_tb_clock_chip_host, 0))
++ panic("Can't open i2c for TB sync !\n");
++
++ spin_lock(&timebase_lock);
++ (*pmac_tb_freeze)(1);
++ mb();
++ timebase = get_tb();
++ spin_unlock(&timebase_lock);
++
++ while (timebase)
++ barrier();
++
++ spin_lock(&timebase_lock);
++ (*pmac_tb_freeze)(0);
++ spin_unlock(&timebase_lock);
++
++ /* Close i2c bus */
++ pmac_low_i2c_close(pmac_tb_clock_chip_host);
++}
++
++
++static void __devinit smp_core99_take_timebase(void)
++{
++ while (!timebase)
++ barrier();
++ spin_lock(&timebase_lock);
++ set_tb(timebase >> 32, timebase & 0xffffffff);
++ timebase = 0;
++ spin_unlock(&timebase_lock);
++}
++
++static void __init smp_core99_setup(int ncpus)
++{
++ struct device_node *cc = NULL;
++ struct device_node *p;
++ u32 *reg;
++ int ok;
++
++ /* HW sync only on these platforms */
++ if (!machine_is_compatible("PowerMac7,2") &&
++ !machine_is_compatible("PowerMac7,3") &&
++ !machine_is_compatible("RackMac3,1"))
++ return;
++
++ /* Look for the clock chip */
++ while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
++ p = of_get_parent(cc);
++ ok = p && device_is_compatible(p, "uni-n-i2c");
++ of_node_put(p);
++ if (!ok)
++ continue;
++
++ reg = (u32 *)get_property(cc, "reg", NULL);
++ if (reg == NULL)
++ continue;
++
++ switch (*reg) {
++ case 0xd2:
++ if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
++ pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
++ pmac_tb_pulsar_addr = 0xd2;
++ printk(KERN_INFO "Timebase clock is Pulsar chip\n");
++ } else if (device_is_compatible(cc, "cy28508")) {
++ pmac_tb_freeze = smp_core99_cypress_tb_freeze;
++ printk(KERN_INFO "Timebase clock is Cypress chip\n");
++ }
++ break;
++ case 0xd4:
++ pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
++ pmac_tb_pulsar_addr = 0xd4;
++ printk(KERN_INFO "Timebase clock is Pulsar chip\n");
++ break;
++ }
++ if (pmac_tb_freeze != NULL) {
++ pmac_tb_clock_chip_host = of_get_parent(cc);
++ of_node_put(cc);
++ break;
++ }
++ }
++ if (pmac_tb_freeze == NULL) {
++ smp_ops->give_timebase = smp_generic_give_timebase;
++ smp_ops->take_timebase = smp_generic_take_timebase;
++ }
++}
++
++/* nothing to do here, caches are already set up by service processor */
++static inline void __devinit core99_init_caches(int cpu)
++{
++}
++
++#else /* CONFIG_PPC64 */
++
++/*
++ * SMP G4 powermacs use a GPIO to enable/disable the timebase.
++ */
++
++static unsigned int core99_tb_gpio; /* Timebase freeze GPIO */
++
++static unsigned int pri_tb_hi, pri_tb_lo;
++static unsigned int pri_tb_stamp;
++
++/* not __init, called in sleep/wakeup code */
++void smp_core99_give_timebase(void)
++{
++ unsigned long flags;
++ unsigned int t;
++
++ /* wait for the secondary to be in take_timebase */
++ for (t = 100000; t > 0 && !sec_tb_reset; --t)
++ udelay(10);
++ if (!sec_tb_reset) {
++ printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
++ return;
++ }
++
++ /* freeze the timebase and read it */
++ /* disable interrupts so the timebase is disabled for the
++ shortest possible time */
++ local_irq_save(flags);
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
++ pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
++ mb();
++ pri_tb_hi = get_tbu();
++ pri_tb_lo = get_tbl();
++ pri_tb_stamp = last_jiffy_stamp(smp_processor_id());
++ mb();
++
++ /* tell the secondary we're ready */
++ sec_tb_reset = 2;
++ mb();
++
++ /* wait for the secondary to have taken it */
++ for (t = 100000; t > 0 && sec_tb_reset; --t)
++ udelay(10);
++ if (sec_tb_reset)
++ printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");
++ else
++ smp_tb_synchronized = 1;
++
++ /* Now, restart the timebase by leaving the GPIO to an open collector */
++ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
++ pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
++ local_irq_restore(flags);
++}
++
++/* not __init, called in sleep/wakeup code */
++void smp_core99_take_timebase(void)
++{
++ unsigned long flags;
++
++ /* tell the primary we're here */
++ sec_tb_reset = 1;
++ mb();
++
++ /* wait for the primary to set pri_tb_hi/lo */
++ while (sec_tb_reset < 2)
++ mb();
++
++ /* set our stuff the same as the primary */
++ local_irq_save(flags);
++ set_dec(1);
++ set_tb(pri_tb_hi, pri_tb_lo);
++ last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp;
++ mb();
++
++ /* tell the primary we're done */
++ sec_tb_reset = 0;
++ mb();
++ local_irq_restore(flags);
++}
++
++/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
++volatile static long int core99_l2_cache;
++volatile static long int core99_l3_cache;
++
++static void __devinit core99_init_caches(int cpu)
++{
++ if (!cpu_has_feature(CPU_FTR_L2CR))
++ return;
++
++ if (cpu == 0) {
++ core99_l2_cache = _get_L2CR();
++ printk("CPU0: L2CR is %lx\n", core99_l2_cache);
++ } else {
++ printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
++ _set_L2CR(0);
++ _set_L2CR(core99_l2_cache);
++ printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
++ }
++
++ if (!cpu_has_feature(CPU_FTR_L3CR))
++ return;
++
++ if (cpu == 0){
++ core99_l3_cache = _get_L3CR();
++ printk("CPU0: L3CR is %lx\n", core99_l3_cache);
++ } else {
++ printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
++ _set_L3CR(0);
++ _set_L3CR(core99_l3_cache);
++ printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
++ }
++}
++
++static void __init smp_core99_setup(int ncpus)
++{
++ struct device_node *cpu;
++ u32 *tbprop = NULL;
++ int i;
++
++ core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */
++ cpu = of_find_node_by_type(NULL, "cpu");
++ if (cpu != NULL) {
++ tbprop = (u32 *)get_property(cpu, "timebase-enable", NULL);
++ if (tbprop)
++ core99_tb_gpio = *tbprop;
++ of_node_put(cpu);
++ }
++
++ /* XXX should get this from reg properties */
++ for (i = 1; i < ncpus; ++i)
++ smp_hw_index[i] = i;
++ powersave_nap = 0;
++}
++#endif
++
++static int __init smp_core99_probe(void)
++{
++ struct device_node *cpus;
++ int ncpus = 0;
++
++ if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
++
++ /* Count CPUs in the device-tree */
++ for (cpus = NULL; (cpus = of_find_node_by_type(cpus, "cpu")) != NULL;)
++ ++ncpus;
++
++ printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
++
++ /* Nothing more to do if less than 2 of them */
++ if (ncpus <= 1)
++ return 1;
++
++ smp_core99_setup(ncpus);
++ mpic_request_ipis();
++ core99_init_caches(0);
++
++ return ncpus;
++}
++
++static void __devinit smp_core99_kick_cpu(int nr)
++{
++ unsigned int save_vector;
++ unsigned long new_vector;
++ unsigned long flags;
++ volatile unsigned int *vector
++ = ((volatile unsigned int *)(KERNELBASE+0x100));
++
++ if (nr < 0 || nr > 3)
++ return;
++ if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
++
++ local_irq_save(flags);
++ local_irq_disable();
++
++ /* Save reset vector */
++ save_vector = *vector;
++
++ /* Setup fake reset vector that does
++ * b __secondary_start_pmac_0 + nr*8 - KERNELBASE
++ */
++ new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8;
++ *vector = 0x48000002 + new_vector - KERNELBASE;
++
++ /* flush data cache and inval instruction cache */
++ flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
++
++ /* Put some life in our friend */
++ pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
++
++ /* FIXME: We wait a bit for the CPU to take the exception, I should
++ * instead wait for the entry code to set something for me. Well,
++ * ideally, all that crap will be done in prom.c and the CPU left
++ * in a RAM-based wait loop like CHRP.
++ */
++ mdelay(1);
++
++ /* Restore our exception vector */
++ *vector = save_vector;
++ flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
++
++ local_irq_restore(flags);
++ if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
++}
++
++static void __devinit smp_core99_setup_cpu(int cpu_nr)
++{
++ /* Setup L2/L3 */
++ if (cpu_nr != 0)
++ core99_init_caches(cpu_nr);
++
++ /* Setup openpic */
++ mpic_setup_this_cpu();
++
++ if (cpu_nr == 0) {
++#ifdef CONFIG_POWER4
++ extern void g5_phy_disable_cpu1(void);
++
++ /* If we didn't start the second CPU, we must take
++ * it off the bus
++ */
++ if (machine_is_compatible("MacRISC4") &&
++ num_online_cpus() < 2)
++ g5_phy_disable_cpu1();
++#endif /* CONFIG_POWER4 */
++ if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
++ }
++}
++
++
++/* Core99 Macs (dual G4s and G5s) */
++struct smp_ops_t core99_smp_ops = {
++ .message_pass = smp_mpic_message_pass,
++ .probe = smp_core99_probe,
++ .kick_cpu = smp_core99_kick_cpu,
++ .setup_cpu = smp_core99_setup_cpu,
++ .give_timebase = smp_core99_give_timebase,
++ .take_timebase = smp_core99_take_timebase,
++};
++
++#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
++
++int __cpu_disable(void)
++{
++ cpu_clear(smp_processor_id(), cpu_online_map);
++
++ /* XXX reset cpu affinity here */
++ mpic_cpu_set_priority(0xf);
++ asm volatile("mtdec %0" : : "r" (0x7fffffff));
++ mb();
++ udelay(20);
++ asm volatile("mtdec %0" : : "r" (0x7fffffff));
++ return 0;
++}
++
++extern void low_cpu_die(void) __attribute__((noreturn)); /* in sleep.S */
++static int cpu_dead[NR_CPUS];
++
++void cpu_die(void)
++{
++ local_irq_disable();
++ cpu_dead[smp_processor_id()] = 1;
++ mb();
++ low_cpu_die();
++}
++
++void __cpu_die(unsigned int cpu)
++{
++ int timeout;
++
++ timeout = 1000;
++ while (!cpu_dead[cpu]) {
++ if (--timeout == 0) {
++ printk("CPU %u refused to die!\n", cpu);
++ break;
++ }
++ msleep(1);
++ }
++ cpu_callin_map[cpu] = 0;
++ cpu_dead[cpu] = 0;
++}
++
++#endif
+diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/powermac/time.c
+@@ -0,0 +1,360 @@
++/*
++ * Support for periodic interrupts (100 per second) and for getting
++ * the current time from the RTC on Power Macintoshes.
++ *
++ * We use the decrementer register for our periodic interrupts.
++ *
++ * Paul Mackerras August 1996.
++ * Copyright (C) 1996 Paul Mackerras.
++ * Copyright (C) 2003-2005 Benjamin Herrenschmidt.
++ *
++ */
++#include <linux/config.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/time.h>
++#include <linux/adb.h>
++#include <linux/cuda.h>
++#include <linux/pmu.h>
++#include <linux/interrupt.h>
++#include <linux/hardirq.h>
++#include <linux/rtc.h>
++
++#include <asm/sections.h>
++#include <asm/prom.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/machdep.h>
++#include <asm/time.h>
++#include <asm/nvram.h>
++#include <asm/smu.h>
++
++#undef DEBUG
++
++#ifdef DEBUG
++#define DBG(x...) printk(x)
++#else
++#define DBG(x...)
++#endif
++
++/* Apparently the RTC stores seconds since 1 Jan 1904 */
++#define RTC_OFFSET 2082844800
++
++/*
++ * Calibrate the decrementer frequency with the VIA timer 1.
++ */
++#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
++
++/* VIA registers */
++#define RS 0x200 /* skip between registers */
++#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
++#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
++#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
++#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
++#define ACR (11*RS) /* Auxiliary control register */
++#define IFR (13*RS) /* Interrupt flag register */
++
++/* Bits in ACR */
++#define T1MODE 0xc0 /* Timer 1 mode */
++#define T1MODE_CONT 0x40 /* continuous interrupts */
++
++/* Bits in IFR and IER */
++#define T1_INT 0x40 /* Timer 1 interrupt */
++
++long __init pmac_time_init(void)
++{
++ s32 delta = 0;
++#ifdef CONFIG_NVRAM
++ int dst;
++
++ delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
++ delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
++ delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
++ if (delta & 0x00800000UL)
++ delta |= 0xFF000000UL;
++ dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
++ printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
++ dst ? "on" : "off");
++#endif
++ return delta;
++}
++
++static void to_rtc_time(unsigned long now, struct rtc_time *tm)
++{
++ to_tm(now, tm);
++ tm->tm_year -= 1900;
++ tm->tm_mon -= 1;
++}
++
++static unsigned long from_rtc_time(struct rtc_time *tm)
++{
++ return mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
++ tm->tm_hour, tm->tm_min, tm->tm_sec);
++}
++
++#ifdef CONFIG_ADB_CUDA
++static unsigned long cuda_get_time(void)
++{
++ struct adb_request req;
++ unsigned long now;
++
++ if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
++ return 0;
++ while (!req.complete)
++ cuda_poll();
++ if (req.reply_len != 7)
++ printk(KERN_ERR "cuda_get_time: got %d byte reply\n",
++ req.reply_len);
++ now = (req.reply[3] << 24) + (req.reply[4] << 16)
++ + (req.reply[5] << 8) + req.reply[6];
++ return now - RTC_OFFSET;
++}
++
++#define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm))
++
++static int cuda_set_rtc_time(struct rtc_time *tm)
++{
++ unsigned int nowtime;
++ struct adb_request req;
++
++ nowtime = from_rtc_time(tm) + RTC_OFFSET;
++ if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
++ nowtime >> 24, nowtime >> 16, nowtime >> 8,
++ nowtime) < 0)
++ return -ENXIO;
++ while (!req.complete)
++ cuda_poll();
++ if ((req.reply_len != 3) && (req.reply_len != 7))
++ printk(KERN_ERR "cuda_set_rtc_time: got %d byte reply\n",
++ req.reply_len);
++ return 0;
++}
++
++#else
++#define cuda_get_time() 0
++#define cuda_get_rtc_time(tm)
++#define cuda_set_rtc_time(tm) 0
++#endif
++
++#ifdef CONFIG_ADB_PMU
++static unsigned long pmu_get_time(void)
++{
++ struct adb_request req;
++ unsigned long now;
++
++ if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
++ return 0;
++ pmu_wait_complete(&req);
++ if (req.reply_len != 4)
++ printk(KERN_ERR "pmu_get_time: got %d byte reply from PMU\n",
++ req.reply_len);
++ now = (req.reply[0] << 24) + (req.reply[1] << 16)
++ + (req.reply[2] << 8) + req.reply[3];
++ return now - RTC_OFFSET;
++}
++
++#define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm))
++
++static int pmu_set_rtc_time(struct rtc_time *tm)
++{
++ unsigned int nowtime;
++ struct adb_request req;
++
++ nowtime = from_rtc_time(tm) + RTC_OFFSET;
++ if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24,
++ nowtime >> 16, nowtime >> 8, nowtime) < 0)
++ return -ENXIO;
++ pmu_wait_complete(&req);
++ if (req.reply_len != 0)
++ printk(KERN_ERR "pmu_set_rtc_time: %d byte reply from PMU\n",
++ req.reply_len);
++ return 0;
++}
++
++#else
++#define pmu_get_time() 0
++#define pmu_get_rtc_time(tm)
++#define pmu_set_rtc_time(tm) 0
++#endif
++
++#ifdef CONFIG_PMAC_SMU
++static unsigned long smu_get_time(void)
++{
++ struct rtc_time tm;
++
++ if (smu_get_rtc_time(&tm, 1))
++ return 0;
++ return from_rtc_time(&tm);
++}
++
++#else
++#define smu_get_time() 0
++#define smu_get_rtc_time(tm, spin)
++#define smu_set_rtc_time(tm, spin) 0
++#endif
++
++unsigned long pmac_get_boot_time(void)
++{
++ /* Get the time from the RTC, used only at boot time */
++ switch (sys_ctrler) {
++ case SYS_CTRLER_CUDA:
++ return cuda_get_time();
++ case SYS_CTRLER_PMU:
++ return pmu_get_time();
++ case SYS_CTRLER_SMU:
++ return smu_get_time();
++ default:
++ return 0;
++ }
++}
++
++void pmac_get_rtc_time(struct rtc_time *tm)
++{
++ /* Get the time from the RTC, used only at boot time */
++ switch (sys_ctrler) {
++ case SYS_CTRLER_CUDA:
++ cuda_get_rtc_time(tm);
++ break;
++ case SYS_CTRLER_PMU:
++ pmu_get_rtc_time(tm);
++ break;
++ case SYS_CTRLER_SMU:
++ smu_get_rtc_time(tm, 1);
++ break;
++ default:
++ ;
++ }
++}
++
++int pmac_set_rtc_time(struct rtc_time *tm)
++{
++ switch (sys_ctrler) {
++ case SYS_CTRLER_CUDA:
++ return cuda_set_rtc_time(tm);
++ case SYS_CTRLER_PMU:
++ return pmu_set_rtc_time(tm);
++ case SYS_CTRLER_SMU:
++ return smu_set_rtc_time(tm, 1);
++ default:
++ return -ENODEV;
++ }
++}
++
++#ifdef CONFIG_PPC32
++/*
++ * Calibrate the decrementer register using VIA timer 1.
++ * This is used both on powermacs and CHRP machines.
++ */
++int __init via_calibrate_decr(void)
++{
++ struct device_node *vias;
++ volatile unsigned char __iomem *via;
++ int count = VIA_TIMER_FREQ_6 / 100;
++ unsigned int dstart, dend;
++
++ vias = find_devices("via-cuda");
++ if (vias == 0)
++ vias = find_devices("via-pmu");
++ if (vias == 0)
++ vias = find_devices("via");
++ if (vias == 0 || vias->n_addrs == 0)
++ return 0;
++ via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
++
++ /* set timer 1 for continuous interrupts */
++ out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
++ /* set the counter to a small value */
++ out_8(&via[T1CH], 2);
++ /* set the latch to `count' */
++ out_8(&via[T1LL], count);
++ out_8(&via[T1LH], count >> 8);
++ /* wait until it hits 0 */
++ while ((in_8(&via[IFR]) & T1_INT) == 0)
++ ;
++ dstart = get_dec();
++ /* clear the interrupt & wait until it hits 0 again */
++ in_8(&via[T1CL]);
++ while ((in_8(&via[IFR]) & T1_INT) == 0)
++ ;
++ dend = get_dec();
++
++ ppc_tb_freq = (dstart - dend) * 100 / 6;
++
++ iounmap(via);
++
++ return 1;
++}
++#endif
++
++#ifdef CONFIG_PM
++/*
++ * Reset the time after a sleep.
++ */
++static int
++time_sleep_notify(struct pmu_sleep_notifier *self, int when)
++{
++ static unsigned long time_diff;
++ unsigned long flags;
++ unsigned long seq;
++ struct timespec tv;
++
++ switch (when) {
++ case PBOOK_SLEEP_NOW:
++ do {
++ seq = read_seqbegin_irqsave(&xtime_lock, flags);
++ time_diff = xtime.tv_sec - pmac_get_boot_time();
++ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
++ break;
++ case PBOOK_WAKE:
++ tv.tv_sec = pmac_get_boot_time() + time_diff;
++ tv.tv_nsec = 0;
++ do_settimeofday(&tv);
++ break;
++ }
++ return PBOOK_SLEEP_OK;
++}
++
++static struct pmu_sleep_notifier time_sleep_notifier = {
++ time_sleep_notify, SLEEP_LEVEL_MISC,
++};
++#endif /* CONFIG_PM */
++
++/*
++ * Query the OF and get the decr frequency.
++ */
++void __init pmac_calibrate_decr(void)
++{
++#ifdef CONFIG_PM
++ /* XXX why here? */
++ pmu_register_sleep_notifier(&time_sleep_notifier);
++#endif /* CONFIG_PM */
++
++ generic_calibrate_decr();
++
++#ifdef CONFIG_PPC32
++ /* We assume MacRISC2 machines have correct device-tree
++ * calibration. That's better since the VIA itself seems
++ * to be slightly off. --BenH
++ */
++ if (!machine_is_compatible("MacRISC2") &&
++ !machine_is_compatible("MacRISC3") &&
++ !machine_is_compatible("MacRISC4"))
++ if (via_calibrate_decr())
++ return;
++
++ /* Special case: QuickSilver G4s seem to have a badly calibrated
++ * timebase-frequency in OF, VIA is much better on these. We should
++ * probably implement calibration based on the KL timer on these
++ * machines anyway... -BenH
++ */
++ if (machine_is_compatible("PowerMac3,5"))
++ if (via_calibrate_decr())
++ return;
++#endif
++}
+diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/prep/Kconfig
+@@ -0,0 +1,22 @@
++
++config PREP_RESIDUAL
++ bool "Support for PReP Residual Data"
++ depends on PPC_PREP
++ help
++ Some PReP systems have residual data passed to the kernel by the
++ firmware. This allows detection of memory size, devices present and
++ other useful pieces of information. Sometimes this information is
++ not present or incorrect, in which case it could lead to the machine
++ behaving incorrectly. If this happens, either disable PREP_RESIDUAL
++ or pass the 'noresidual' option to the kernel.
++
++ If you are running a PReP system, say Y here, otherwise say N.
++
++config PROC_PREPRESIDUAL
++ bool "Support for reading of PReP Residual Data in /proc"
++ depends on PREP_RESIDUAL && PROC_FS
++ help
++ Enabling this option will create a /proc/residual file which allows
++ you to get at the residual data on PReP systems. You will need a tool
++ (lsresidual) to parse it. If you aren't on a PReP system, you don't
++ want this.
+diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/Kconfig
+@@ -0,0 +1,42 @@
++
++config PPC_SPLPAR
++ depends on PPC_PSERIES
++ bool "Support for shared-processor logical partitions"
++ default n
++ help
++ Enabling this option will make the kernel run more efficiently
++ on logically-partitioned pSeries systems which use shared
++ processors, that is, which share physical processors between
++ two or more partitions.
++
++config HMT
++ bool "Hardware multithreading"
++ depends on SMP && PPC_PSERIES && BROKEN
++ help
++ This option enables hardware multithreading on RS64 cpus.
++ pSeries systems p620 and p660 have such a cpu type.
++
++config EEH
++ bool "PCI Extended Error Handling (EEH)" if EMBEDDED
++ depends on PPC_PSERIES
++ default y if !EMBEDDED
++
++config RTAS_PROC
++ bool "Proc interface to RTAS"
++ depends on PPC_RTAS
++ default y
++
++config RTAS_FLASH
++ tristate "Firmware flash interface"
++ depends on PPC64 && RTAS_PROC
++
++config SCANLOG
++ tristate "Scanlog dump interface"
++ depends on RTAS_PROC && PPC_PSERIES
++
++config LPARCFG
++ tristate "LPAR Configuration Data"
++ depends on PPC_PSERIES || PPC_ISERIES
++ help
++ Provide system capacity information via human readable
++ <key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
+diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/Makefile
+@@ -0,0 +1,5 @@
++obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \
++ setup.o iommu.o rtas-fw.o ras.o
++obj-$(CONFIG_SMP) += smp.o
++obj-$(CONFIG_IBMVIO) += vio.o
++obj-$(CONFIG_XICS) += xics.o
+diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/hvCall.S
+@@ -0,0 +1,131 @@
++/*
++ * arch/ppc64/kernel/pSeries_hvCall.S
++ *
++ * This file contains the generic code to perform a call to the
++ * pSeries LPAR hypervisor.
++ * NOTE: this file will go away when we move to inline this work.
++ *
++ * 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 <asm/hvcall.h>
++#include <asm/processor.h>
++#include <asm/ppc_asm.h>
++
++#define STK_PARM(i) (48 + ((i)-3)*8)
++
++ .text
++
++/* long plpar_hcall(unsigned long opcode, R3
++ unsigned long arg1, R4
++ unsigned long arg2, R5
++ unsigned long arg3, R6
++ unsigned long arg4, R7
++ unsigned long *out1, R8
++ unsigned long *out2, R9
++ unsigned long *out3); R10
++ */
++_GLOBAL(plpar_hcall)
++ HMT_MEDIUM
++
++ mfcr r0
++
++ std r8,STK_PARM(r8)(r1) /* Save out ptrs */
++ std r9,STK_PARM(r9)(r1)
++ std r10,STK_PARM(r10)(r1)
++
++ stw r0,8(r1)
++
++ HVSC /* invoke the hypervisor */
++
++ lwz r0,8(r1)
++
++ ld r8,STK_PARM(r8)(r1) /* Fetch r4-r6 ret args */
++ ld r9,STK_PARM(r9)(r1)
++ ld r10,STK_PARM(r10)(r1)
++ std r4,0(r8)
++ std r5,0(r9)
++ std r6,0(r10)
++
++ mtcrf 0xff,r0
++ blr /* return r3 = status */
++
++
++/* Simple interface with no output values (other than status) */
++_GLOBAL(plpar_hcall_norets)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HVSC /* invoke the hypervisor */
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++ blr /* return r3 = status */
++
++
++/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3
++ unsigned long arg1, R4
++ unsigned long arg2, R5
++ unsigned long arg3, R6
++ unsigned long arg4, R7
++ unsigned long arg5, R8
++ unsigned long arg6, R9
++ unsigned long arg7, R10
++ unsigned long arg8, 112(R1)
++ unsigned long *out1); 120(R1)
++ */
++_GLOBAL(plpar_hcall_8arg_2ret)
++ HMT_MEDIUM
++
++ mfcr r0
++ ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
++ stw r0,8(r1)
++
++ HVSC /* invoke the hypervisor */
++
++ lwz r0,8(r1)
++ ld r10,STK_PARM(r12)(r1) /* Fetch r4 ret arg */
++ std r4,0(r10)
++ mtcrf 0xff,r0
++ blr /* return r3 = status */
++
++
++/* long plpar_hcall_4out(unsigned long opcode, R3
++ unsigned long arg1, R4
++ unsigned long arg2, R5
++ unsigned long arg3, R6
++ unsigned long arg4, R7
++ unsigned long *out1, R8
++ unsigned long *out2, R9
++ unsigned long *out3, R10
++ unsigned long *out4); 112(R1)
++ */
++_GLOBAL(plpar_hcall_4out)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ std r8,STK_PARM(r8)(r1) /* Save out ptrs */
++ std r9,STK_PARM(r9)(r1)
++ std r10,STK_PARM(r10)(r1)
++
++ HVSC /* invoke the hypervisor */
++
++ lwz r0,8(r1)
++
++ ld r8,STK_PARM(r8)(r1) /* Fetch r4-r7 ret args */
++ ld r9,STK_PARM(r9)(r1)
++ ld r10,STK_PARM(r10)(r1)
++ ld r11,STK_PARM(r11)(r1)
++ std r4,0(r8)
++ std r5,0(r9)
++ std r6,0(r10)
++ std r7,0(r11)
++
++ mtcrf 0xff,r0
++ blr /* return r3 = status */
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -0,0 +1,606 @@
++/*
++ * arch/ppc64/kernel/pSeries_iommu.c
++ *
++ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
++ *
++ * Rewrite, cleanup:
++ *
++ * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
++ *
++ * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
++ *
++ *
++ * 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/init.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/rtas.h>
++#include <asm/ppcdebug.h>
++#include <asm/iommu.h>
++#include <asm/pci-bridge.h>
++#include <asm/machdep.h>
++#include <asm/abs_addr.h>
++#include <asm/plpar_wrappers.h>
++#include <asm/pSeries_reconfig.h>
++#include <asm/systemcfg.h>
++#include <asm/firmware.h>
++#include <asm/tce.h>
++#include <asm/ppc-pci.h>
++
++#define DBG(fmt...)
++
++extern int is_python(struct device_node *);
++
++static void tce_build_pSeries(struct iommu_table *tbl, long index,
++ long npages, unsigned long uaddr,
++ enum dma_data_direction direction)
++{
++ union tce_entry t;
++ union tce_entry *tp;
++
++ index <<= TCE_PAGE_FACTOR;
++ npages <<= TCE_PAGE_FACTOR;
++
++ t.te_word = 0;
++ t.te_rdwr = 1; // Read allowed
++
++ if (direction != DMA_TO_DEVICE)
++ t.te_pciwr = 1;
++
++ tp = ((union tce_entry *)tbl->it_base) + index;
++
++ while (npages--) {
++ /* can't move this out since we might cross LMB boundary */
++ t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
++
++ tp->te_word = t.te_word;
++
++ uaddr += TCE_PAGE_SIZE;
++ tp++;
++ }
++}
++
++
++static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
++{
++ union tce_entry t;
++ union tce_entry *tp;
++
++ npages <<= TCE_PAGE_FACTOR;
++ index <<= TCE_PAGE_FACTOR;
++
++ t.te_word = 0;
++ tp = ((union tce_entry *)tbl->it_base) + index;
++
++ while (npages--) {
++ tp->te_word = t.te_word;
++
++ tp++;
++ }
++}
++
++
++static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
++ long npages, unsigned long uaddr,
++ enum dma_data_direction direction)
++{
++ u64 rc;
++ union tce_entry tce;
++
++ tce.te_word = 0;
++ tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
++ tce.te_rdwr = 1;
++ if (direction != DMA_TO_DEVICE)
++ tce.te_pciwr = 1;
++
++ while (npages--) {
++ rc = plpar_tce_put((u64)tbl->it_index,
++ (u64)tcenum << 12,
++ tce.te_word );
++
++ if (rc && printk_ratelimit()) {
++ printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
++ printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
++ printk("\ttcenum = 0x%lx\n", (u64)tcenum);
++ printk("\ttce val = 0x%lx\n", tce.te_word );
++ show_stack(current, (unsigned long *)__get_SP());
++ }
++
++ tcenum++;
++ tce.te_rpn++;
++ }
++}
++
++static DEFINE_PER_CPU(void *, tce_page) = NULL;
++
++static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
++ long npages, unsigned long uaddr,
++ enum dma_data_direction direction)
++{
++ u64 rc;
++ union tce_entry tce, *tcep;
++ long l, limit;
++
++ tcenum <<= TCE_PAGE_FACTOR;
++ npages <<= TCE_PAGE_FACTOR;
++
++ if (npages == 1)
++ return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
++ direction);
++
++ tcep = __get_cpu_var(tce_page);
++
++ /* This is safe to do since interrupts are off when we're called
++ * from iommu_alloc{,_sg}()
++ */
++ if (!tcep) {
++ tcep = (void *)__get_free_page(GFP_ATOMIC);
++ /* If allocation fails, fall back to the loop implementation */
++ if (!tcep)
++ return tce_build_pSeriesLP(tbl, tcenum, npages,
++ uaddr, direction);
++ __get_cpu_var(tce_page) = tcep;
++ }
++
++ tce.te_word = 0;
++ tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
++ tce.te_rdwr = 1;
++ if (direction != DMA_TO_DEVICE)
++ tce.te_pciwr = 1;
++
++ /* We can map max one pageful of TCEs at a time */
++ do {
++ /*
++ * Set up the page with TCE data, looping through and setting
++ * the values.
++ */
++ limit = min_t(long, npages, 4096/sizeof(union tce_entry));
++
++ for (l = 0; l < limit; l++) {
++ tcep[l] = tce;
++ tce.te_rpn++;
++ }
++
++ rc = plpar_tce_put_indirect((u64)tbl->it_index,
++ (u64)tcenum << 12,
++ (u64)virt_to_abs(tcep),
++ limit);
++
++ npages -= limit;
++ tcenum += limit;
++ } while (npages > 0 && !rc);
++
++ if (rc && printk_ratelimit()) {
++ printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
++ printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
++ printk("\tnpages = 0x%lx\n", (u64)npages);
++ printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
++ show_stack(current, (unsigned long *)__get_SP());
++ }
++}
++
++static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
++{
++ u64 rc;
++ union tce_entry tce;
++
++ tcenum <<= TCE_PAGE_FACTOR;
++ npages <<= TCE_PAGE_FACTOR;
++
++ tce.te_word = 0;
++
++ while (npages--) {
++ rc = plpar_tce_put((u64)tbl->it_index,
++ (u64)tcenum << 12,
++ tce.te_word);
++
++ if (rc && printk_ratelimit()) {
++ printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
++ printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
++ printk("\ttcenum = 0x%lx\n", (u64)tcenum);
++ printk("\ttce val = 0x%lx\n", tce.te_word );
++ show_stack(current, (unsigned long *)__get_SP());
++ }
++
++ tcenum++;
++ }
++}
++
++
++static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
++{
++ u64 rc;
++ union tce_entry tce;
++
++ tcenum <<= TCE_PAGE_FACTOR;
++ npages <<= TCE_PAGE_FACTOR;
++
++ tce.te_word = 0;
++
++ rc = plpar_tce_stuff((u64)tbl->it_index,
++ (u64)tcenum << 12,
++ tce.te_word,
++ npages);
++
++ if (rc && printk_ratelimit()) {
++ printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
++ printk("\trc = %ld\n", rc);
++ printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
++ printk("\tnpages = 0x%lx\n", (u64)npages);
++ printk("\ttce val = 0x%lx\n", tce.te_word );
++ show_stack(current, (unsigned long *)__get_SP());
++ }
++}
++
++static void iommu_table_setparms(struct pci_controller *phb,
++ struct device_node *dn,
++ struct iommu_table *tbl)
++{
++ struct device_node *node;
++ unsigned long *basep;
++ unsigned int *sizep;
++
++ node = (struct device_node *)phb->arch_data;
++
++ basep = (unsigned long *)get_property(node, "linux,tce-base", NULL);
++ sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL);
++ if (basep == NULL || sizep == NULL) {
++ printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has "
++ "missing tce entries !\n", dn->full_name);
++ return;
++ }
++
++ tbl->it_base = (unsigned long)__va(*basep);
++ memset((void *)tbl->it_base, 0, *sizep);
++
++ tbl->it_busno = phb->bus->number;
++
++ /* Units of tce entries */
++ tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
++
++ /* Test if we are going over 2GB of DMA space */
++ if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
++ udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
++ panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
++ }
++
++ phb->dma_window_base_cur += phb->dma_window_size;
++
++ /* Set the tce table size - measured in entries */
++ tbl->it_size = phb->dma_window_size >> PAGE_SHIFT;
++
++ tbl->it_index = 0;
++ tbl->it_blocksize = 16;
++ tbl->it_type = TCE_PCI;
++}
++
++/*
++ * iommu_table_setparms_lpar
++ *
++ * Function: On pSeries LPAR systems, return TCE table info, given a pci bus.
++ *
++ * ToDo: properly interpret the ibm,dma-window property. The definition is:
++ * logical-bus-number (1 word)
++ * phys-address (#address-cells words)
++ * size (#cell-size words)
++ *
++ * Currently we hard code these sizes (more or less).
++ */
++static void iommu_table_setparms_lpar(struct pci_controller *phb,
++ struct device_node *dn,
++ struct iommu_table *tbl,
++ unsigned int *dma_window)
++{
++ tbl->it_busno = PCI_DN(dn)->bussubno;
++
++ /* TODO: Parse field size properties properly. */
++ tbl->it_size = (((unsigned long)dma_window[4] << 32) |
++ (unsigned long)dma_window[5]) >> PAGE_SHIFT;
++ tbl->it_offset = (((unsigned long)dma_window[2] << 32) |
++ (unsigned long)dma_window[3]) >> PAGE_SHIFT;
++ tbl->it_base = 0;
++ tbl->it_index = dma_window[0];
++ tbl->it_blocksize = 16;
++ tbl->it_type = TCE_PCI;
++}
++
++static void iommu_bus_setup_pSeries(struct pci_bus *bus)
++{
++ struct device_node *dn;
++ struct iommu_table *tbl;
++ struct device_node *isa_dn, *isa_dn_orig;
++ struct device_node *tmp;
++ struct pci_dn *pci;
++ int children;
++
++ DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
++
++ dn = pci_bus_to_OF_node(bus);
++ pci = PCI_DN(dn);
++
++ if (bus->self) {
++ /* This is not a root bus, any setup will be done for the
++ * device-side of the bridge in iommu_dev_setup_pSeries().
++ */
++ return;
++ }
++
++ /* Check if the ISA bus on the system is under
++ * this PHB.
++ */
++ isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa");
++
++ while (isa_dn && isa_dn != dn)
++ isa_dn = isa_dn->parent;
++
++ if (isa_dn_orig)
++ of_node_put(isa_dn_orig);
++
++ /* Count number of direct PCI children of the PHB.
++ * All PCI device nodes have class-code property, so it's
++ * an easy way to find them.
++ */
++ for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
++ if (get_property(tmp, "class-code", NULL))
++ children++;
++
++ DBG("Children: %d\n", children);
++
++ /* Calculate amount of DMA window per slot. Each window must be
++ * a power of two (due to pci_alloc_consistent requirements).
++ *
++ * Keep 256MB aside for PHBs with ISA.
++ */
++
++ if (!isa_dn) {
++ /* No ISA/IDE - just set window size and return */
++ pci->phb->dma_window_size = 0x80000000ul; /* To be divided */
++
++ while (pci->phb->dma_window_size * children > 0x80000000ul)
++ pci->phb->dma_window_size >>= 1;
++ DBG("No ISA/IDE, window size is 0x%lx\n",
++ pci->phb->dma_window_size);
++ pci->phb->dma_window_base_cur = 0;
++
++ return;
++ }
++
++ /* If we have ISA, then we probably have an IDE
++ * controller too. Allocate a 128MB table but
++ * skip the first 128MB to avoid stepping on ISA
++ * space.
++ */
++ pci->phb->dma_window_size = 0x8000000ul;
++ pci->phb->dma_window_base_cur = 0x8000000ul;
++
++ tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
++
++ iommu_table_setparms(pci->phb, dn, tbl);
++ pci->iommu_table = iommu_init_table(tbl);
++
++ /* Divide the rest (1.75GB) among the children */
++ pci->phb->dma_window_size = 0x80000000ul;
++ while (pci->phb->dma_window_size * children > 0x70000000ul)
++ pci->phb->dma_window_size >>= 1;
++
++ DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
++
++}
++
++
++static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
++{
++ struct iommu_table *tbl;
++ struct device_node *dn, *pdn;
++ struct pci_dn *ppci;
++ unsigned int *dma_window = NULL;
++
++ DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
++
++ dn = pci_bus_to_OF_node(bus);
++
++ /* Find nearest ibm,dma-window, walking up the device tree */
++ for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
++ dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
++ if (dma_window != NULL)
++ break;
++ }
++
++ if (dma_window == NULL) {
++ DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name);
++ return;
++ }
++
++ ppci = pdn->data;
++ if (!ppci->iommu_table) {
++ /* Bussubno hasn't been copied yet.
++ * Do it now because iommu_table_setparms_lpar needs it.
++ */
++
++ ppci->bussubno = bus->number;
++
++ tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
++ GFP_KERNEL);
++
++ iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
++
++ ppci->iommu_table = iommu_init_table(tbl);
++ }
++
++ if (pdn != dn)
++ PCI_DN(dn)->iommu_table = ppci->iommu_table;
++}
++
++
++static void iommu_dev_setup_pSeries(struct pci_dev *dev)
++{
++ struct device_node *dn, *mydn;
++ struct iommu_table *tbl;
++
++ DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev));
++
++ mydn = dn = pci_device_to_OF_node(dev);
++
++ /* If we're the direct child of a root bus, then we need to allocate
++ * an iommu table ourselves. The bus setup code should have setup
++ * the window sizes already.
++ */
++ if (!dev->bus->self) {
++ DBG(" --> first child, no bridge. Allocating iommu table.\n");
++ tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
++ iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl);
++ PCI_DN(mydn)->iommu_table = iommu_init_table(tbl);
++
++ return;
++ }
++
++ /* If this device is further down the bus tree, search upwards until
++ * an already allocated iommu table is found and use that.
++ */
++
++ while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
++ dn = dn->parent;
++
++ if (dn && dn->data) {
++ PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
++ } else {
++ DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev));
++ }
++}
++
++static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
++{
++ int err = NOTIFY_OK;
++ struct device_node *np = node;
++ struct pci_dn *pci = np->data;
++
++ switch (action) {
++ case PSERIES_RECONFIG_REMOVE:
++ if (pci->iommu_table &&
++ get_property(np, "ibm,dma-window", NULL))
++ iommu_free_table(np);
++ break;
++ default:
++ err = NOTIFY_DONE;
++ break;
++ }
++ return err;
++}
++
++static struct notifier_block iommu_reconfig_nb = {
++ .notifier_call = iommu_reconfig_notifier,
++};
++
++static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
++{
++ struct device_node *pdn, *dn;
++ struct iommu_table *tbl;
++ int *dma_window = NULL;
++ struct pci_dn *pci;
++
++ DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev));
++
++ /* dev setup for LPAR is a little tricky, since the device tree might
++ * contain the dma-window properties per-device and not neccesarily
++ * for the bus. So we need to search upwards in the tree until we
++ * either hit a dma-window property, OR find a parent with a table
++ * already allocated.
++ */
++ dn = pci_device_to_OF_node(dev);
++
++ for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table;
++ pdn = pdn->parent) {
++ dma_window = (unsigned int *)
++ get_property(pdn, "ibm,dma-window", NULL);
++ if (dma_window)
++ break;
++ }
++
++ /* Check for parent == NULL so we don't try to setup the empty EADS
++ * slots on POWER4 machines.
++ */
++ if (dma_window == NULL || pdn->parent == NULL) {
++ DBG("No dma window for device, linking to parent\n");
++ PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table;
++ return;
++ } else {
++ DBG("Found DMA window, allocating table\n");
++ }
++
++ pci = pdn->data;
++ if (!pci->iommu_table) {
++ /* iommu_table_setparms_lpar needs bussubno. */
++ pci->bussubno = pci->phb->bus->number;
++
++ tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
++ GFP_KERNEL);
++
++ iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
++
++ pci->iommu_table = iommu_init_table(tbl);
++ }
++
++ if (pdn != dn)
++ PCI_DN(dn)->iommu_table = pci->iommu_table;
++}
++
++static void iommu_bus_setup_null(struct pci_bus *b) { }
++static void iommu_dev_setup_null(struct pci_dev *d) { }
++
++/* These are called very early. */
++void iommu_init_early_pSeries(void)
++{
++ if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) {
++ /* Direct I/O, IOMMU off */
++ ppc_md.iommu_dev_setup = iommu_dev_setup_null;
++ ppc_md.iommu_bus_setup = iommu_bus_setup_null;
++ pci_direct_iommu_init();
++
++ return;
++ }
++
++ if (systemcfg->platform & PLATFORM_LPAR) {
++ if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
++ ppc_md.tce_build = tce_buildmulti_pSeriesLP;
++ ppc_md.tce_free = tce_freemulti_pSeriesLP;
++ } else {
++ ppc_md.tce_build = tce_build_pSeriesLP;
++ ppc_md.tce_free = tce_free_pSeriesLP;
++ }
++ ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP;
++ ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP;
++ } else {
++ ppc_md.tce_build = tce_build_pSeries;
++ ppc_md.tce_free = tce_free_pSeries;
++ ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries;
++ ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
++ }
++
++
++ pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
++
++ pci_iommu_init();
++}
++
+diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/lpar.c
+@@ -0,0 +1,517 @@
++/*
++ * pSeries_lpar.c
++ * Copyright (C) 2001 Todd Inglett, IBM Corporation
++ *
++ * pSeries LPAR support.
++ *
++ * 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 DEBUG
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/dma-mapping.h>
++#include <asm/processor.h>
++#include <asm/mmu.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/machdep.h>
++#include <asm/abs_addr.h>
++#include <asm/mmu_context.h>
++#include <asm/ppcdebug.h>
++#include <asm/iommu.h>
++#include <asm/tlbflush.h>
++#include <asm/tlb.h>
++#include <asm/prom.h>
++#include <asm/abs_addr.h>
++#include <asm/cputable.h>
++#include <asm/plpar_wrappers.h>
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/* in pSeries_hvCall.S */
++EXPORT_SYMBOL(plpar_hcall);
++EXPORT_SYMBOL(plpar_hcall_4out);
++EXPORT_SYMBOL(plpar_hcall_norets);
++EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
++
++extern void pSeries_find_serial_port(void);
++
++
++int vtermno; /* virtual terminal# for udbg */
++
++#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
++static void udbg_hvsi_putc(unsigned char c)
++{
++ /* packet's seqno isn't used anyways */
++ uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
++ int rc;
++
++ if (c == '\n')
++ udbg_hvsi_putc('\r');
++
++ do {
++ rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
++ } while (rc == H_Busy);
++}
++
++static long hvsi_udbg_buf_len;
++static uint8_t hvsi_udbg_buf[256];
++
++static int udbg_hvsi_getc_poll(void)
++{
++ unsigned char ch;
++ int rc, i;
++
++ if (hvsi_udbg_buf_len == 0) {
++ rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
++ if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
++ /* bad read or non-data packet */
++ hvsi_udbg_buf_len = 0;
++ } else {
++ /* remove the packet header */
++ for (i = 4; i < hvsi_udbg_buf_len; i++)
++ hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
++ hvsi_udbg_buf_len -= 4;
++ }
++ }
++
++ if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
++ /* no data ready */
++ hvsi_udbg_buf_len = 0;
++ return -1;
++ }
++
++ ch = hvsi_udbg_buf[0];
++ /* shift remaining data down */
++ for (i = 1; i < hvsi_udbg_buf_len; i++) {
++ hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
++ }
++ hvsi_udbg_buf_len--;
++
++ return ch;
++}
++
++static unsigned char udbg_hvsi_getc(void)
++{
++ int ch;
++ for (;;) {
++ ch = udbg_hvsi_getc_poll();
++ if (ch == -1) {
++ /* This shouldn't be needed...but... */
++ volatile unsigned long delay;
++ for (delay=0; delay < 2000000; delay++)
++ ;
++ } else {
++ return ch;
++ }
++ }
++}
++
++static void udbg_putcLP(unsigned char c)
++{
++ char buf[16];
++ unsigned long rc;
++
++ if (c == '\n')
++ udbg_putcLP('\r');
++
++ buf[0] = c;
++ do {
++ rc = plpar_put_term_char(vtermno, 1, buf);
++ } while(rc == H_Busy);
++}
++
++/* Buffered chars getc */
++static long inbuflen;
++static long inbuf[2]; /* must be 2 longs */
++
++static int udbg_getc_pollLP(void)
++{
++ /* The interface is tricky because it may return up to 16 chars.
++ * We save them statically for future calls to udbg_getc().
++ */
++ char ch, *buf = (char *)inbuf;
++ int i;
++ long rc;
++ if (inbuflen == 0) {
++ /* get some more chars. */
++ inbuflen = 0;
++ rc = plpar_get_term_char(vtermno, &inbuflen, buf);
++ if (rc != H_Success)
++ inbuflen = 0; /* otherwise inbuflen is garbage */
++ }
++ if (inbuflen <= 0 || inbuflen > 16) {
++ /* Catch error case as well as other oddities (corruption) */
++ inbuflen = 0;
++ return -1;
++ }
++ ch = buf[0];
++ for (i = 1; i < inbuflen; i++) /* shuffle them down. */
++ buf[i-1] = buf[i];
++ inbuflen--;
++ return ch;
++}
++
++static unsigned char udbg_getcLP(void)
++{
++ int ch;
++ for (;;) {
++ ch = udbg_getc_pollLP();
++ if (ch == -1) {
++ /* This shouldn't be needed...but... */
++ volatile unsigned long delay;
++ for (delay=0; delay < 2000000; delay++)
++ ;
++ } else {
++ return ch;
++ }
++ }
++}
++
++/* call this from early_init() for a working debug console on
++ * vterm capable LPAR machines
++ */
++void udbg_init_debug_lpar(void)
++{
++ vtermno = 0;
++ udbg_putc = udbg_putcLP;
++ udbg_getc = udbg_getcLP;
++ udbg_getc_poll = udbg_getc_pollLP;
++}
++
++/* returns 0 if couldn't find or use /chosen/stdout as console */
++int find_udbg_vterm(void)
++{
++ struct device_node *stdout_node;
++ u32 *termno;
++ char *name;
++ int found = 0;
++
++ /* find the boot console from /chosen/stdout */
++ if (!of_chosen)
++ return 0;
++ name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
++ if (name == NULL)
++ return 0;
++ stdout_node = of_find_node_by_path(name);
++ if (!stdout_node)
++ return 0;
++
++ /* now we have the stdout node; figure out what type of device it is. */
++ name = (char *)get_property(stdout_node, "name", NULL);
++ if (!name) {
++ printk(KERN_WARNING "stdout node missing 'name' property!\n");
++ goto out;
++ }
++
++ if (strncmp(name, "vty", 3) == 0) {
++ if (device_is_compatible(stdout_node, "hvterm1")) {
++ termno = (u32 *)get_property(stdout_node, "reg", NULL);
++ if (termno) {
++ vtermno = termno[0];
++ udbg_putc = udbg_putcLP;
++ udbg_getc = udbg_getcLP;
++ udbg_getc_poll = udbg_getc_pollLP;
++ found = 1;
++ }
++ } else if (device_is_compatible(stdout_node, "hvterm-protocol")) {
++ termno = (u32 *)get_property(stdout_node, "reg", NULL);
++ if (termno) {
++ vtermno = termno[0];
++ udbg_putc = udbg_hvsi_putc;
++ udbg_getc = udbg_hvsi_getc;
++ udbg_getc_poll = udbg_hvsi_getc_poll;
++ found = 1;
++ }
++ }
++ } else if (strncmp(name, "serial", 6)) {
++ /* XXX fix ISA serial console */
++ printk(KERN_WARNING "serial stdout on LPAR ('%s')! "
++ "can't print udbg messages\n",
++ stdout_node->full_name);
++ } else {
++ printk(KERN_WARNING "don't know how to print to stdout '%s'\n",
++ stdout_node->full_name);
++ }
++
++out:
++ of_node_put(stdout_node);
++ return found;
++}
++
++void vpa_init(int cpu)
++{
++ int hwcpu = get_hard_smp_processor_id(cpu);
++ unsigned long vpa = (unsigned long)&(paca[cpu].lppaca);
++ long ret;
++ unsigned long flags;
++
++ /* Register the Virtual Processor Area (VPA) */
++ flags = 1UL << (63 - 18);
++
++ if (cpu_has_feature(CPU_FTR_ALTIVEC))
++ paca[cpu].lppaca.vmxregs_in_use = 1;
++
++ ret = register_vpa(flags, hwcpu, __pa(vpa));
++
++ if (ret)
++ printk(KERN_ERR "WARNING: vpa_init: VPA registration for "
++ "cpu %d (hw %d) of area %lx returns %ld\n",
++ cpu, hwcpu, __pa(vpa), ret);
++}
++
++long pSeries_lpar_hpte_insert(unsigned long hpte_group,
++ unsigned long va, unsigned long prpn,
++ unsigned long vflags, unsigned long rflags)
++{
++ unsigned long lpar_rc;
++ unsigned long flags;
++ unsigned long slot;
++ unsigned long hpte_v, hpte_r;
++ unsigned long dummy0, dummy1;
++
++ hpte_v = ((va >> 23) << HPTE_V_AVPN_SHIFT) | vflags | HPTE_V_VALID;
++ if (vflags & HPTE_V_LARGE)
++ hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT);
++
++ hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
++
++ /* Now fill in the actual HPTE */
++ /* Set CEC cookie to 0 */
++ /* Zero page = 0 */
++ /* I-cache Invalidate = 0 */
++ /* I-cache synchronize = 0 */
++ /* Exact = 0 */
++ flags = 0;
++
++ /* XXX why is this here? - Anton */
++ if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
++ hpte_r &= ~_PAGE_COHERENT;
++
++ lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
++ hpte_r, &slot, &dummy0, &dummy1);
++
++ if (unlikely(lpar_rc == H_PTEG_Full))
++ return -1;
++
++ /*
++ * Since we try and ioremap PHBs we don't own, the pte insert
++ * will fail. However we must catch the failure in hash_page
++ * or we will loop forever, so return -2 in this case.
++ */
++ if (unlikely(lpar_rc != H_Success))
++ return -2;
++
++ /* Because of iSeries, we have to pass down the secondary
++ * bucket bit here as well
++ */
++ return (slot & 7) | (!!(vflags & HPTE_V_SECONDARY) << 3);
++}
++
++static DEFINE_SPINLOCK(pSeries_lpar_tlbie_lock);
++
++static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
++{
++ unsigned long slot_offset;
++ unsigned long lpar_rc;
++ int i;
++ unsigned long dummy1, dummy2;
++
++ /* pick a random slot to start at */
++ slot_offset = mftb() & 0x7;
++
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++
++ /* don't remove a bolted entry */
++ lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,
++ (0x1UL << 4), &dummy1, &dummy2);
++
++ if (lpar_rc == H_Success)
++ return i;
++
++ BUG_ON(lpar_rc != H_Not_Found);
++
++ slot_offset++;
++ slot_offset &= 0x7;
++ }
++
++ return -1;
++}
++
++static void pSeries_lpar_hptab_clear(void)
++{
++ unsigned long size_bytes = 1UL << ppc64_pft_size;
++ unsigned long hpte_count = size_bytes >> 4;
++ unsigned long dummy1, dummy2;
++ int i;
++
++ /* TODO: Use bulk call */
++ for (i = 0; i < hpte_count; i++)
++ plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
++}
++
++/*
++ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
++ * the low 3 bits of flags happen to line up. So no transform is needed.
++ * We can probably optimize here and assume the high bits of newpp are
++ * already zero. For now I am paranoid.
++ */
++static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
++ unsigned long va, int large, int local)
++{
++ unsigned long lpar_rc;
++ unsigned long flags = (newpp & 7) | H_AVPN;
++ unsigned long avpn = va >> 23;
++
++ if (large)
++ avpn &= ~0x1UL;
++
++ lpar_rc = plpar_pte_protect(flags, slot, (avpn << 7));
++
++ if (lpar_rc == H_Not_Found)
++ return -1;
++
++ BUG_ON(lpar_rc != H_Success);
++
++ return 0;
++}
++
++static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
++{
++ unsigned long dword0;
++ unsigned long lpar_rc;
++ unsigned long dummy_word1;
++ unsigned long flags;
++
++ /* Read 1 pte at a time */
++ /* Do not need RPN to logical page translation */
++ /* No cross CEC PFT access */
++ flags = 0;
++
++ lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
++
++ BUG_ON(lpar_rc != H_Success);
++
++ return dword0;
++}
++
++static long pSeries_lpar_hpte_find(unsigned long vpn)
++{
++ unsigned long hash;
++ unsigned long i, j;
++ long slot;
++ unsigned long hpte_v;
++
++ hash = hpt_hash(vpn, 0);
++
++ for (j = 0; j < 2; j++) {
++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++ hpte_v = pSeries_lpar_hpte_getword0(slot);
++
++ if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11))
++ && (hpte_v & HPTE_V_VALID)
++ && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
++ /* HPTE matches */
++ if (j)
++ slot = -slot;
++ return slot;
++ }
++ ++slot;
++ }
++ hash = ~hash;
++ }
++
++ return -1;
++}
++
++static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
++ unsigned long ea)
++{
++ unsigned long lpar_rc;
++ unsigned long vsid, va, vpn, flags;
++ long slot;
++
++ vsid = get_kernel_vsid(ea);
++ va = (vsid << 28) | (ea & 0x0fffffff);
++ vpn = va >> PAGE_SHIFT;
++
++ slot = pSeries_lpar_hpte_find(vpn);
++ BUG_ON(slot == -1);
++
++ flags = newpp & 7;
++ lpar_rc = plpar_pte_protect(flags, slot, 0);
++
++ BUG_ON(lpar_rc != H_Success);
++}
++
++static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
++ int large, int local)
++{
++ unsigned long avpn = va >> 23;
++ unsigned long lpar_rc;
++ unsigned long dummy1, dummy2;
++
++ if (large)
++ avpn &= ~0x1UL;
++
++ lpar_rc = plpar_pte_remove(H_AVPN, slot, (avpn << 7), &dummy1,
++ &dummy2);
++
++ if (lpar_rc == H_Not_Found)
++ return;
++
++ BUG_ON(lpar_rc != H_Success);
++}
++
++/*
++ * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
++ * lock.
++ */
++void pSeries_lpar_flush_hash_range(unsigned long number, int local)
++{
++ int i;
++ unsigned long flags = 0;
++ struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
++ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
++
++ if (lock_tlbie)
++ spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
++
++ for (i = 0; i < number; i++)
++ flush_hash_page(batch->vaddr[i], batch->pte[i], local);
++
++ if (lock_tlbie)
++ spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
++}
++
++void hpte_init_lpar(void)
++{
++ ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate;
++ ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp;
++ ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
++ ppc_md.hpte_insert = pSeries_lpar_hpte_insert;
++ ppc_md.hpte_remove = pSeries_lpar_hpte_remove;
++ ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
++ ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear;
++
++ htab_finish_init();
++}
+diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/nvram.c
+@@ -0,0 +1,148 @@
++/*
++ * c 2001 PPC 64 Team, IBM Corp
++ *
++ * 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.
++ *
++ * /dev/nvram driver for PPC64
++ *
++ * This perhaps should live in drivers/char
++ */
++
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <asm/uaccess.h>
++#include <asm/nvram.h>
++#include <asm/rtas.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++
++static unsigned int nvram_size;
++static int nvram_fetch, nvram_store;
++static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
++static DEFINE_SPINLOCK(nvram_lock);
++
++
++static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
++{
++ unsigned int i;
++ unsigned long len;
++ int done;
++ unsigned long flags;
++ char *p = buf;
++
++
++ if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE)
++ return -ENODEV;
++
++ if (*index >= nvram_size)
++ return 0;
++
++ i = *index;
++ if (i + count > nvram_size)
++ count = nvram_size - i;
++
++ spin_lock_irqsave(&nvram_lock, flags);
++
++ for (; count != 0; count -= len) {
++ len = count;
++ if (len > NVRW_CNT)
++ len = NVRW_CNT;
++
++ if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf),
++ len) != 0) || len != done) {
++ spin_unlock_irqrestore(&nvram_lock, flags);
++ return -EIO;
++ }
++
++ memcpy(p, nvram_buf, len);
++
++ p += len;
++ i += len;
++ }
++
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ *index = i;
++ return p - buf;
++}
++
++static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index)
++{
++ unsigned int i;
++ unsigned long len;
++ int done;
++ unsigned long flags;
++ const char *p = buf;
++
++ if (nvram_size == 0 || nvram_store == RTAS_UNKNOWN_SERVICE)
++ return -ENODEV;
++
++ if (*index >= nvram_size)
++ return 0;
++
++ i = *index;
++ if (i + count > nvram_size)
++ count = nvram_size - i;
++
++ spin_lock_irqsave(&nvram_lock, flags);
++
++ for (; count != 0; count -= len) {
++ len = count;
++ if (len > NVRW_CNT)
++ len = NVRW_CNT;
++
++ memcpy(nvram_buf, p, len);
++
++ if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf),
++ len) != 0) || len != done) {
++ spin_unlock_irqrestore(&nvram_lock, flags);
++ return -EIO;
++ }
++
++ p += len;
++ i += len;
++ }
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ *index = i;
++ return p - buf;
++}
++
++static ssize_t pSeries_nvram_get_size(void)
++{
++ return nvram_size ? nvram_size : -ENODEV;
++}
++
++int __init pSeries_nvram_init(void)
++{
++ struct device_node *nvram;
++ unsigned int *nbytes_p, proplen;
++
++ nvram = of_find_node_by_type(NULL, "nvram");
++ if (nvram == NULL)
++ return -ENODEV;
++
++ nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
++ if (nbytes_p == NULL || proplen != sizeof(unsigned int))
++ return -EIO;
++
++ nvram_size = *nbytes_p;
++
++ nvram_fetch = rtas_token("nvram-fetch");
++ nvram_store = rtas_token("nvram-store");
++ printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size);
++ of_node_put(nvram);
++
++ ppc_md.nvram_read = pSeries_nvram_read;
++ ppc_md.nvram_write = pSeries_nvram_write;
++ ppc_md.nvram_size = pSeries_nvram_get_size;
++
++ return 0;
++}
+diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/pci.c
+@@ -0,0 +1,142 @@
++/*
++ * arch/ppc64/kernel/pSeries_pci.c
++ *
++ * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
++ * Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * pSeries specific routines for PCI.
++ *
++ * 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/ioport.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++
++#include <asm/pci-bridge.h>
++#include <asm/prom.h>
++#include <asm/ppc-pci.h>
++
++static int __devinitdata s7a_workaround = -1;
++
++#if 0
++void pcibios_name_device(struct pci_dev *dev)
++{
++ struct device_node *dn;
++
++ /*
++ * Add IBM loc code (slot) as a prefix to the device names for service
++ */
++ dn = pci_device_to_OF_node(dev);
++ if (dn) {
++ char *loc_code = get_property(dn, "ibm,loc-code", 0);
++ if (loc_code) {
++ int loc_len = strlen(loc_code);
++ if (loc_len < sizeof(dev->dev.name)) {
++ memmove(dev->dev.name+loc_len+1, dev->dev.name,
++ sizeof(dev->dev.name)-loc_len-1);
++ memcpy(dev->dev.name, loc_code, loc_len);
++ dev->dev.name[loc_len] = ' ';
++ dev->dev.name[sizeof(dev->dev.name)-1] = '\0';
++ }
++ }
++ }
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
++#endif
++
++static void __devinit check_s7a(void)
++{
++ struct device_node *root;
++ char *model;
++
++ s7a_workaround = 0;
++ root = of_find_node_by_path("/");
++ if (root) {
++ model = get_property(root, "model", NULL);
++ if (model && !strcmp(model, "IBM,7013-S7A"))
++ s7a_workaround = 1;
++ of_node_put(root);
++ }
++}
++
++void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
++{
++ struct pci_dev *dev;
++
++ if (s7a_workaround < 0)
++ check_s7a();
++ list_for_each_entry(dev, &bus->devices, bus_list) {
++ pci_read_irq_line(dev);
++ if (s7a_workaround) {
++ if (dev->irq > 16) {
++ dev->irq -= 3;
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
++ dev->irq);
++ }
++ }
++ }
++}
++
++static void __init pSeries_request_regions(void)
++{
++ if (!isa_io_base)
++ return;
++
++ request_region(0x20,0x20,"pic1");
++ request_region(0xa0,0x20,"pic2");
++ request_region(0x00,0x20,"dma1");
++ request_region(0x40,0x20,"timer");
++ request_region(0x80,0x10,"dma page reg");
++ request_region(0xc0,0x20,"dma2");
++}
++
++void __init pSeries_final_fixup(void)
++{
++ phbs_remap_io();
++ pSeries_request_regions();
++
++ pci_addr_cache_build();
++}
++
++/*
++ * Assume the winbond 82c105 is the IDE controller on a
++ * p610. We should probably be more careful in case
++ * someone tries to plug in a similar adapter.
++ */
++static void fixup_winbond_82c105(struct pci_dev* dev)
++{
++ int i;
++ unsigned int reg;
++
++ if (!(systemcfg->platform & PLATFORM_PSERIES))
++ return;
++
++ printk("Using INTC for W82c105 IDE controller.\n");
++ pci_read_config_dword(dev, 0x40, ®);
++ /* Enable LEGIRQ to use INTC instead of ISA interrupts */
++ pci_write_config_dword(dev, 0x40, reg | (1<<11));
++
++ for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) {
++ /* zap the 2nd function of the winbond chip */
++ if (dev->resource[i].flags & IORESOURCE_IO
++ && dev->bus->number == 0 && dev->devfn == 0x81)
++ dev->resource[i].flags &= ~IORESOURCE_IO;
++ }
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
++ fixup_winbond_82c105);
+diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/ras.c
+@@ -0,0 +1,352 @@
++/*
++ * Copyright (C) 2001 Dave Engebretsen IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/* Change Activity:
++ * 2001/09/21 : engebret : Created with minimal EPOW and HW exception support.
++ * End Change Activity
++ */
++
++#include <linux/errno.h>
++#include <linux/threads.h>
++#include <linux/kernel_stat.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/timex.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/random.h>
++#include <linux/sysrq.h>
++#include <linux/bitops.h>
++
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/irq.h>
++#include <asm/cache.h>
++#include <asm/prom.h>
++#include <asm/ptrace.h>
++#include <asm/machdep.h>
++#include <asm/rtas.h>
++#include <asm/ppcdebug.h>
++
++static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
++static DEFINE_SPINLOCK(ras_log_buf_lock);
++
++char mce_data_buf[RTAS_ERROR_LOG_MAX]
++;
++/* This is true if we are using the firmware NMI handler (typically LPAR) */
++extern int fwnmi_active;
++
++static int ras_get_sensor_state_token;
++static int ras_check_exception_token;
++
++#define EPOW_SENSOR_TOKEN 9
++#define EPOW_SENSOR_INDEX 0
++#define RAS_VECTOR_OFFSET 0x500
++
++static irqreturn_t ras_epow_interrupt(int irq, void *dev_id,
++ struct pt_regs * regs);
++static irqreturn_t ras_error_interrupt(int irq, void *dev_id,
++ struct pt_regs * regs);
++
++/* #define DEBUG */
++
++static void request_ras_irqs(struct device_node *np, char *propname,
++ irqreturn_t (*handler)(int, void *, struct pt_regs *),
++ const char *name)
++{
++ unsigned int *ireg, len, i;
++ int virq, n_intr;
++
++ ireg = (unsigned int *)get_property(np, propname, &len);
++ if (ireg == NULL)
++ return;
++ n_intr = prom_n_intr_cells(np);
++ len /= n_intr * sizeof(*ireg);
++
++ for (i = 0; i < len; i++) {
++ virq = virt_irq_create_mapping(*ireg);
++ if (virq == NO_IRQ) {
++ printk(KERN_ERR "Unable to allocate interrupt "
++ "number for %s\n", np->full_name);
++ return;
++ }
++ if (request_irq(irq_offset_up(virq), handler, 0, name, NULL)) {
++ printk(KERN_ERR "Unable to request interrupt %d for "
++ "%s\n", irq_offset_up(virq), np->full_name);
++ return;
++ }
++ ireg += n_intr;
++ }
++}
++
++/*
++ * Initialize handlers for the set of interrupts caused by hardware errors
++ * and power system events.
++ */
++static int __init init_ras_IRQ(void)
++{
++ struct device_node *np;
++
++ ras_get_sensor_state_token = rtas_token("get-sensor-state");
++ ras_check_exception_token = rtas_token("check-exception");
++
++ /* Internal Errors */
++ np = of_find_node_by_path("/event-sources/internal-errors");
++ if (np != NULL) {
++ request_ras_irqs(np, "open-pic-interrupt", ras_error_interrupt,
++ "RAS_ERROR");
++ request_ras_irqs(np, "interrupts", ras_error_interrupt,
++ "RAS_ERROR");
++ of_node_put(np);
++ }
++
++ /* EPOW Events */
++ np = of_find_node_by_path("/event-sources/epow-events");
++ if (np != NULL) {
++ request_ras_irqs(np, "open-pic-interrupt", ras_epow_interrupt,
++ "RAS_EPOW");
++ request_ras_irqs(np, "interrupts", ras_epow_interrupt,
++ "RAS_EPOW");
++ of_node_put(np);
++ }
++
++ return 1;
++}
++__initcall(init_ras_IRQ);
++
++/*
++ * Handle power subsystem events (EPOW).
++ *
++ * Presently we just log the event has occurred. This should be fixed
++ * to examine the type of power failure and take appropriate action where
++ * the time horizon permits something useful to be done.
++ */
++static irqreturn_t
++ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ int status = 0xdeadbeef;
++ int state = 0;
++ int critical;
++
++ status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
++ EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);
++
++ if (state > 3)
++ critical = 1; /* Time Critical */
++ else
++ critical = 0;
++
++ spin_lock(&ras_log_buf_lock);
++
++ status = rtas_call(ras_check_exception_token, 6, 1, NULL,
++ RAS_VECTOR_OFFSET,
++ virt_irq_to_real(irq_offset_down(irq)),
++ RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
++ critical, __pa(&ras_log_buf),
++ rtas_get_error_log_max());
++
++ udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
++ *((unsigned long *)&ras_log_buf), status, state);
++ printk(KERN_WARNING "EPOW <0x%lx 0x%x 0x%x>\n",
++ *((unsigned long *)&ras_log_buf), status, state);
++
++ /* format and print the extended information */
++ log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
++
++ spin_unlock(&ras_log_buf_lock);
++ return IRQ_HANDLED;
++}
++
++/*
++ * Handle hardware error interrupts.
++ *
++ * RTAS check-exception is called to collect data on the exception. If
++ * the error is deemed recoverable, we log a warning and return.
++ * For nonrecoverable errors, an error is logged and we stop all processing
++ * as quickly as possible in order to prevent propagation of the failure.
++ */
++static irqreturn_t
++ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++{
++ struct rtas_error_log *rtas_elog;
++ int status = 0xdeadbeef;
++ int fatal;
++
++ spin_lock(&ras_log_buf_lock);
++
++ status = rtas_call(ras_check_exception_token, 6, 1, NULL,
++ RAS_VECTOR_OFFSET,
++ virt_irq_to_real(irq_offset_down(irq)),
++ RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
++ __pa(&ras_log_buf),
++ rtas_get_error_log_max());
++
++ rtas_elog = (struct rtas_error_log *)ras_log_buf;
++
++ if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC))
++ fatal = 1;
++ else
++ fatal = 0;
++
++ /* format and print the extended information */
++ log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
++
++ if (fatal) {
++ udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
++ *((unsigned long *)&ras_log_buf), status);
++ printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
++ *((unsigned long *)&ras_log_buf), status);
++
++#ifndef DEBUG
++ /* Don't actually power off when debugging so we can test
++ * without actually failing while injecting errors.
++ * Error data will not be logged to syslog.
++ */
++ ppc_md.power_off();
++#endif
++ } else {
++ udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
++ *((unsigned long *)&ras_log_buf), status);
++ printk(KERN_WARNING
++ "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
++ *((unsigned long *)&ras_log_buf), status);
++ }
++
++ spin_unlock(&ras_log_buf_lock);
++ return IRQ_HANDLED;
++}
++
++/* Get the error information for errors coming through the
++ * FWNMI vectors. The pt_regs' r3 will be updated to reflect
++ * the actual r3 if possible, and a ptr to the error log entry
++ * will be returned if found.
++ *
++ * The mce_data_buf does not have any locks or protection around it,
++ * if a second machine check comes in, or a system reset is done
++ * before we have logged the error, then we will get corruption in the
++ * error log. This is preferable over holding off on calling
++ * ibm,nmi-interlock which would result in us checkstopping if a
++ * second machine check did come in.
++ */
++static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
++{
++ unsigned long errdata = regs->gpr[3];
++ struct rtas_error_log *errhdr = NULL;
++ unsigned long *savep;
++
++ if ((errdata >= 0x7000 && errdata < 0x7fff0) ||
++ (errdata >= rtas.base && errdata < rtas.base + rtas.size - 16)) {
++ savep = __va(errdata);
++ regs->gpr[3] = savep[0]; /* restore original r3 */
++ memset(mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
++ memcpy(mce_data_buf, (char *)(savep + 1), RTAS_ERROR_LOG_MAX);
++ errhdr = (struct rtas_error_log *)mce_data_buf;
++ } else {
++ printk("FWNMI: corrupt r3\n");
++ }
++ return errhdr;
++}
++
++/* Call this when done with the data returned by FWNMI_get_errinfo.
++ * It will release the saved data area for other CPUs in the
++ * partition to receive FWNMI errors.
++ */
++static void fwnmi_release_errinfo(void)
++{
++ int ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
++ if (ret != 0)
++ printk("FWNMI: nmi-interlock failed: %d\n", ret);
++}
++
++void pSeries_system_reset_exception(struct pt_regs *regs)
++{
++ if (fwnmi_active) {
++ struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
++ if (errhdr) {
++ /* XXX Should look at FWNMI information */
++ }
++ fwnmi_release_errinfo();
++ }
++}
++
++/*
++ * See if we can recover from a machine check exception.
++ * This is only called on power4 (or above) and only via
++ * the Firmware Non-Maskable Interrupts (fwnmi) handler
++ * which provides the error analysis for us.
++ *
++ * Return 1 if corrected (or delivered a signal).
++ * Return 0 if there is nothing we can do.
++ */
++static int recover_mce(struct pt_regs *regs, struct rtas_error_log * err)
++{
++ int nonfatal = 0;
++
++ if (err->disposition == RTAS_DISP_FULLY_RECOVERED) {
++ /* Platform corrected itself */
++ nonfatal = 1;
++ } else if ((regs->msr & MSR_RI) &&
++ user_mode(regs) &&
++ err->severity == RTAS_SEVERITY_ERROR_SYNC &&
++ err->disposition == RTAS_DISP_NOT_RECOVERED &&
++ err->target == RTAS_TARGET_MEMORY &&
++ err->type == RTAS_TYPE_ECC_UNCORR &&
++ !(current->pid == 0 || current->pid == 1)) {
++ /* Kill off a user process with an ECC error */
++ printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
++ current->pid);
++ /* XXX something better for ECC error? */
++ _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
++ nonfatal = 1;
++ }
++
++ log_error((char *)err, ERR_TYPE_RTAS_LOG, !nonfatal);
++
++ return nonfatal;
++}
++
++/*
++ * Handle a machine check.
++ *
++ * Note that on Power 4 and beyond Firmware Non-Maskable Interrupts (fwnmi)
++ * should be present. If so the handler which called us tells us if the
++ * error was recovered (never true if RI=0).
++ *
++ * On hardware prior to Power 4 these exceptions were asynchronous which
++ * means we can't tell exactly where it occurred and so we can't recover.
++ */
++int pSeries_machine_check_exception(struct pt_regs *regs)
++{
++ struct rtas_error_log *errp;
++
++ if (fwnmi_active) {
++ errp = fwnmi_get_errinfo(regs);
++ fwnmi_release_errinfo();
++ if (errp && recover_mce(regs, errp))
++ return 1;
++ }
++
++ return 0;
++}
+diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/reconfig.c
+@@ -0,0 +1,426 @@
++/*
++ * pSeries_reconfig.c - support for dynamic reconfiguration (including PCI
++ * Hotplug and Dynamic Logical Partitioning on RPA platforms).
++ *
++ * Copyright (C) 2005 Nathan Lynch
++ * Copyright (C) 2005 IBM 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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/kref.h>
++#include <linux/notifier.h>
++#include <linux/proc_fs.h>
++
++#include <asm/prom.h>
++#include <asm/pSeries_reconfig.h>
++#include <asm/uaccess.h>
++
++
++
++/*
++ * Routines for "runtime" addition and removal of device tree nodes.
++ */
++#ifdef CONFIG_PROC_DEVICETREE
++/*
++ * Add a node to /proc/device-tree.
++ */
++static void add_node_proc_entries(struct device_node *np)
++{
++ struct proc_dir_entry *ent;
++
++ ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
++ if (ent)
++ proc_device_tree_add_node(np, ent);
++}
++
++static void remove_node_proc_entries(struct device_node *np)
++{
++ struct property *pp = np->properties;
++ struct device_node *parent = np->parent;
++
++ while (pp) {
++ remove_proc_entry(pp->name, np->pde);
++ pp = pp->next;
++ }
++ if (np->pde)
++ remove_proc_entry(np->pde->name, parent->pde);
++}
++#else /* !CONFIG_PROC_DEVICETREE */
++static void add_node_proc_entries(struct device_node *np)
++{
++ return;
++}
++
++static void remove_node_proc_entries(struct device_node *np)
++{
++ return;
++}
++#endif /* CONFIG_PROC_DEVICETREE */
++
++/**
++ * derive_parent - basically like dirname(1)
++ * @path: the full_name of a node to be added to the tree
++ *
++ * Returns the node which should be the parent of the node
++ * described by path. E.g., for path = "/foo/bar", returns
++ * the node with full_name = "/foo".
++ */
++static struct device_node *derive_parent(const char *path)
++{
++ struct device_node *parent = NULL;
++ char *parent_path = "/";
++ size_t parent_path_len = strrchr(path, '/') - path + 1;
++
++ /* reject if path is "/" */
++ if (!strcmp(path, "/"))
++ return ERR_PTR(-EINVAL);
++
++ if (strrchr(path, '/') != path) {
++ parent_path = kmalloc(parent_path_len, GFP_KERNEL);
++ if (!parent_path)
++ return ERR_PTR(-ENOMEM);
++ strlcpy(parent_path, path, parent_path_len);
++ }
++ parent = of_find_node_by_path(parent_path);
++ if (!parent)
++ return ERR_PTR(-EINVAL);
++ if (strcmp(parent_path, "/"))
++ kfree(parent_path);
++ return parent;
++}
++
++static struct notifier_block *pSeries_reconfig_chain;
++
++int pSeries_reconfig_notifier_register(struct notifier_block *nb)
++{
++ return notifier_chain_register(&pSeries_reconfig_chain, nb);
++}
++
++void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
++{
++ notifier_chain_unregister(&pSeries_reconfig_chain, nb);
++}
++
++static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
++{
++ struct device_node *np;
++ int err = -ENOMEM;
++
++ np = kzalloc(sizeof(*np), GFP_KERNEL);
++ if (!np)
++ goto out_err;
++
++ np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
++ if (!np->full_name)
++ goto out_err;
++
++ strcpy(np->full_name, path);
++
++ np->properties = proplist;
++ OF_MARK_DYNAMIC(np);
++ kref_init(&np->kref);
++
++ np->parent = derive_parent(path);
++ if (IS_ERR(np->parent)) {
++ err = PTR_ERR(np->parent);
++ goto out_err;
++ }
++
++ err = notifier_call_chain(&pSeries_reconfig_chain,
++ PSERIES_RECONFIG_ADD, np);
++ if (err == NOTIFY_BAD) {
++ printk(KERN_ERR "Failed to add device node %s\n", path);
++ err = -ENOMEM; /* For now, safe to assume kmalloc failure */
++ goto out_err;
++ }
++
++ of_attach_node(np);
++
++ add_node_proc_entries(np);
++
++ of_node_put(np->parent);
++
++ return 0;
++
++out_err:
++ if (np) {
++ of_node_put(np->parent);
++ kfree(np->full_name);
++ kfree(np);
++ }
++ return err;
++}
++
++static int pSeries_reconfig_remove_node(struct device_node *np)
++{
++ struct device_node *parent, *child;
++
++ parent = of_get_parent(np);
++ if (!parent)
++ return -EINVAL;
++
++ if ((child = of_get_next_child(np, NULL))) {
++ of_node_put(child);
++ return -EBUSY;
++ }
++
++ remove_node_proc_entries(np);
++
++ notifier_call_chain(&pSeries_reconfig_chain,
++ PSERIES_RECONFIG_REMOVE, np);
++ of_detach_node(np);
++
++ of_node_put(parent);
++ of_node_put(np); /* Must decrement the refcount */
++ return 0;
++}
++
++/*
++ * /proc/ppc64/ofdt - yucky binary interface for adding and removing
++ * OF device nodes. Should be deprecated as soon as we get an
++ * in-kernel wrapper for the RTAS ibm,configure-connector call.
++ */
++
++static void release_prop_list(const struct property *prop)
++{
++ struct property *next;
++ for (; prop; prop = next) {
++ next = prop->next;
++ kfree(prop->name);
++ kfree(prop->value);
++ kfree(prop);
++ }
++
++}
++
++/**
++ * parse_next_property - process the next property from raw input buffer
++ * @buf: input buffer, must be nul-terminated
++ * @end: end of the input buffer + 1, for validation
++ * @name: return value; set to property name in buf
++ * @length: return value; set to length of value
++ * @value: return value; set to the property value in buf
++ *
++ * Note that the caller must make copies of the name and value returned,
++ * this function does no allocation or copying of the data. Return value
++ * is set to the next name in buf, or NULL on error.
++ */
++static char * parse_next_property(char *buf, char *end, char **name, int *length,
++ unsigned char **value)
++{
++ char *tmp;
++
++ *name = buf;
++
++ tmp = strchr(buf, ' ');
++ if (!tmp) {
++ printk(KERN_ERR "property parse failed in %s at line %d\n",
++ __FUNCTION__, __LINE__);
++ return NULL;
++ }
++ *tmp = '\0';
++
++ if (++tmp >= end) {
++ printk(KERN_ERR "property parse failed in %s at line %d\n",
++ __FUNCTION__, __LINE__);
++ return NULL;
++ }
++
++ /* now we're on the length */
++ *length = -1;
++ *length = simple_strtoul(tmp, &tmp, 10);
++ if (*length == -1) {
++ printk(KERN_ERR "property parse failed in %s at line %d\n",
++ __FUNCTION__, __LINE__);
++ return NULL;
++ }
++ if (*tmp != ' ' || ++tmp >= end) {
++ printk(KERN_ERR "property parse failed in %s at line %d\n",
++ __FUNCTION__, __LINE__);
++ return NULL;
++ }
++
++ /* now we're on the value */
++ *value = tmp;
++ tmp += *length;
++ if (tmp > end) {
++ printk(KERN_ERR "property parse failed in %s at line %d\n",
++ __FUNCTION__, __LINE__);
++ return NULL;
++ }
++ else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
++ printk(KERN_ERR "property parse failed in %s at line %d\n",
++ __FUNCTION__, __LINE__);
++ return NULL;
++ }
++ tmp++;
++
++ /* and now we should be on the next name, or the end */
++ return tmp;
++}
++
++static struct property *new_property(const char *name, const int length,
++ const unsigned char *value, struct property *last)
++{
++ struct property *new = kmalloc(sizeof(*new), GFP_KERNEL);
++
++ if (!new)
++ return NULL;
++ memset(new, 0, sizeof(*new));
++
++ if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
++ goto cleanup;
++ if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
++ goto cleanup;
++
++ strcpy(new->name, name);
++ memcpy(new->value, value, length);
++ *(((char *)new->value) + length) = 0;
++ new->length = length;
++ new->next = last;
++ return new;
++
++cleanup:
++ if (new->name)
++ kfree(new->name);
++ if (new->value)
++ kfree(new->value);
++ kfree(new);
++ return NULL;
++}
++
++static int do_add_node(char *buf, size_t bufsize)
++{
++ char *path, *end, *name;
++ struct device_node *np;
++ struct property *prop = NULL;
++ unsigned char* value;
++ int length, rv = 0;
++
++ end = buf + bufsize;
++ path = buf;
++ buf = strchr(buf, ' ');
++ if (!buf)
++ return -EINVAL;
++ *buf = '\0';
++ buf++;
++
++ if ((np = of_find_node_by_path(path))) {
++ of_node_put(np);
++ return -EINVAL;
++ }
++
++ /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */
++ while (buf < end &&
++ (buf = parse_next_property(buf, end, &name, &length, &value))) {
++ struct property *last = prop;
++
++ prop = new_property(name, length, value, last);
++ if (!prop) {
++ rv = -ENOMEM;
++ prop = last;
++ goto out;
++ }
++ }
++ if (!buf) {
++ rv = -EINVAL;
++ goto out;
++ }
++
++ rv = pSeries_reconfig_add_node(path, prop);
++
++out:
++ if (rv)
++ release_prop_list(prop);
++ return rv;
++}
++
++static int do_remove_node(char *buf)
++{
++ struct device_node *node;
++ int rv = -ENODEV;
++
++ if ((node = of_find_node_by_path(buf)))
++ rv = pSeries_reconfig_remove_node(node);
++
++ of_node_put(node);
++ return rv;
++}
++
++/**
++ * ofdt_write - perform operations on the Open Firmware device tree
++ *
++ * @file: not used
++ * @buf: command and arguments
++ * @count: size of the command buffer
++ * @off: not used
++ *
++ * Operations supported at this time are addition and removal of
++ * whole nodes along with their properties. Operations on individual
++ * properties are not implemented (yet).
++ */
++static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count,
++ loff_t *off)
++{
++ int rv = 0;
++ char *kbuf;
++ char *tmp;
++
++ if (!(kbuf = kmalloc(count + 1, GFP_KERNEL))) {
++ rv = -ENOMEM;
++ goto out;
++ }
++ if (copy_from_user(kbuf, buf, count)) {
++ rv = -EFAULT;
++ goto out;
++ }
++
++ kbuf[count] = '\0';
++
++ tmp = strchr(kbuf, ' ');
++ if (!tmp) {
++ rv = -EINVAL;
++ goto out;
++ }
++ *tmp = '\0';
++ tmp++;
++
++ if (!strcmp(kbuf, "add_node"))
++ rv = do_add_node(tmp, count - (tmp - kbuf));
++ else if (!strcmp(kbuf, "remove_node"))
++ rv = do_remove_node(tmp);
++ else
++ rv = -EINVAL;
++out:
++ kfree(kbuf);
++ return rv ? rv : count;
++}
++
++static struct file_operations ofdt_fops = {
++ .write = ofdt_write
++};
++
++/* create /proc/ppc64/ofdt write-only by root */
++static int proc_ppc64_create_ofdt(void)
++{
++ struct proc_dir_entry *ent;
++
++ if (!(systemcfg->platform & PLATFORM_PSERIES))
++ return 0;
++
++ ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
++ if (ent) {
++ ent->nlink = 1;
++ ent->data = NULL;
++ ent->size = 0;
++ ent->proc_fops = &ofdt_fops;
++ }
++
++ return 0;
++}
++__initcall(proc_ppc64_create_ofdt);
+diff --git a/arch/powerpc/platforms/pseries/rtas-fw.c b/arch/powerpc/platforms/pseries/rtas-fw.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/rtas-fw.c
+@@ -0,0 +1,138 @@
++/*
++ *
++ * Procedures for firmware flash updates on pSeries systems.
++ *
++ * Peter Bergner, IBM March 2001.
++ * Copyright (C) 2001 IBM.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <stdarg.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/spinlock.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/prom.h>
++#include <asm/rtas.h>
++#include <asm/semaphore.h>
++#include <asm/machdep.h>
++#include <asm/page.h>
++#include <asm/param.h>
++#include <asm/system.h>
++#include <asm/abs_addr.h>
++#include <asm/udbg.h>
++#include <asm/delay.h>
++#include <asm/uaccess.h>
++#include <asm/systemcfg.h>
++
++#include "rtas-fw.h"
++
++struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
++
++#define FLASH_BLOCK_LIST_VERSION (1UL)
++
++static void rtas_flash_firmware(void)
++{
++ unsigned long image_size;
++ struct flash_block_list *f, *next, *flist;
++ unsigned long rtas_block_list;
++ int i, status, update_token;
++
++ update_token = rtas_token("ibm,update-flash-64-and-reboot");
++ if (update_token == RTAS_UNKNOWN_SERVICE) {
++ printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
++ printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
++ return;
++ }
++
++ /* NOTE: the "first" block list is a global var with no data
++ * blocks in the kernel data segment. We do this because
++ * we want to ensure this block_list addr is under 4GB.
++ */
++ rtas_firmware_flash_list.num_blocks = 0;
++ flist = (struct flash_block_list *)&rtas_firmware_flash_list;
++ rtas_block_list = virt_to_abs(flist);
++ if (rtas_block_list >= 4UL*1024*1024*1024) {
++ printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
++ return;
++ }
++
++ printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
++ /* Update the block_list in place. */
++ image_size = 0;
++ for (f = flist; f; f = next) {
++ /* Translate data addrs to absolute */
++ for (i = 0; i < f->num_blocks; i++) {
++ f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
++ image_size += f->blocks[i].length;
++ }
++ next = f->next;
++ /* Don't translate NULL pointer for last entry */
++ if (f->next)
++ f->next = (struct flash_block_list *)virt_to_abs(f->next);
++ else
++ f->next = NULL;
++ /* make num_blocks into the version/length field */
++ f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
++ }
++
++ printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
++ printk(KERN_ALERT "FLASH: performing flash and reboot\n");
++ rtas_progress("Flashing \n", 0x0);
++ rtas_progress("Please Wait... ", 0x0);
++ printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
++ status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
++ switch (status) { /* should only get "bad" status */
++ case 0:
++ printk(KERN_ALERT "FLASH: success\n");
++ break;
++ case -1:
++ printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n");
++ break;
++ case -3:
++ printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n");
++ break;
++ case -4:
++ printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n");
++ break;
++ default:
++ printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
++ break;
++ }
++}
++
++void rtas_flash_bypass_warning(void)
++{
++ printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");
++ printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");
++}
++
++
++void rtas_fw_restart(char *cmd)
++{
++ if (rtas_firmware_flash_list.next)
++ rtas_flash_firmware();
++ rtas_restart(cmd);
++}
++
++void rtas_fw_power_off(void)
++{
++ if (rtas_firmware_flash_list.next)
++ rtas_flash_bypass_warning();
++ rtas_power_off();
++}
++
++void rtas_fw_halt(void)
++{
++ if (rtas_firmware_flash_list.next)
++ rtas_flash_bypass_warning();
++ rtas_halt();
++}
++
++EXPORT_SYMBOL(rtas_firmware_flash_list);
+diff --git a/arch/powerpc/platforms/pseries/rtas-fw.h b/arch/powerpc/platforms/pseries/rtas-fw.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/rtas-fw.h
+@@ -0,0 +1,3 @@
++void rtas_fw_restart(char *cmd);
++void rtas_fw_power_off(void);
++void rtas_fw_halt(void);
+diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/setup.c
+@@ -0,0 +1,607 @@
++/*
++ * 64-bit pSeries and RS/6000 setup code.
++ *
++ * Copyright (C) 1995 Linus Torvalds
++ * Adapted from 'alpha' version by Gary Thomas
++ * Modified by Cort Dougan (cort at cs.nmt.edu)
++ * Modified by PPC64 Team, IBM Corp
++ *
++ * 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.
++ */
++
++/*
++ * bootup setup stuff..
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/cpu.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/tty.h>
++#include <linux/major.h>
++#include <linux/interrupt.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/console.h>
++#include <linux/pci.h>
++#include <linux/utsname.h>
++#include <linux/adb.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/seq_file.h>
++#include <linux/root_dev.h>
++
++#include <asm/mmu.h>
++#include <asm/processor.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/prom.h>
++#include <asm/rtas.h>
++#include <asm/pci-bridge.h>
++#include <asm/iommu.h>
++#include <asm/dma.h>
++#include <asm/machdep.h>
++#include <asm/irq.h>
++#include <asm/time.h>
++#include <asm/nvram.h>
++#include <asm/plpar_wrappers.h>
++#include "xics.h"
++#include <asm/firmware.h>
++#include <asm/pmc.h>
++#include <asm/mpic.h>
++#include <asm/ppc-pci.h>
++#include <asm/i8259.h>
++#include <asm/udbg.h>
++
++#include "rtas-fw.h"
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++extern void find_udbg_vterm(void);
++extern void system_reset_fwnmi(void); /* from head.S */
++extern void machine_check_fwnmi(void); /* from head.S */
++extern void generic_find_legacy_serial_ports(u64 *physport,
++ unsigned int *default_speed);
++
++int fwnmi_active; /* TRUE if an FWNMI handler is present */
++
++extern void pSeries_system_reset_exception(struct pt_regs *regs);
++extern int pSeries_machine_check_exception(struct pt_regs *regs);
++
++static void pseries_shared_idle(void);
++static void pseries_dedicated_idle(void);
++
++struct mpic *pSeries_mpic;
++
++void pSeries_show_cpuinfo(struct seq_file *m)
++{
++ struct device_node *root;
++ const char *model = "";
++
++ root = of_find_node_by_path("/");
++ if (root)
++ model = get_property(root, "model", NULL);
++ seq_printf(m, "machine\t\t: CHRP %s\n", model);
++ of_node_put(root);
++}
++
++/* Initialize firmware assisted non-maskable interrupts if
++ * the firmware supports this feature.
++ *
++ */
++static void __init fwnmi_init(void)
++{
++ int ret;
++ int ibm_nmi_register = rtas_token("ibm,nmi-register");
++ if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
++ return;
++ ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
++ __pa((unsigned long)system_reset_fwnmi),
++ __pa((unsigned long)machine_check_fwnmi));
++ if (ret == 0)
++ fwnmi_active = 1;
++}
++
++static void __init pSeries_init_mpic(void)
++{
++ unsigned int *addrp;
++ struct device_node *np;
++ unsigned long intack = 0;
++
++ /* All ISUs are setup, complete initialization */
++ mpic_init(pSeries_mpic);
++
++ /* Check what kind of cascade ACK we have */
++ if (!(np = of_find_node_by_name(NULL, "pci"))
++ || !(addrp = (unsigned int *)
++ get_property(np, "8259-interrupt-acknowledge", NULL)))
++ printk(KERN_ERR "Cannot find pci to get ack address\n");
++ else
++ intack = addrp[prom_n_addr_cells(np)-1];
++ of_node_put(np);
++
++ /* Setup the legacy interrupts & controller */
++ i8259_init(intack, 0);
++
++ /* Hook cascade to mpic */
++ mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL);
++}
++
++static void __init pSeries_setup_mpic(void)
++{
++ unsigned int *opprop;
++ unsigned long openpic_addr = 0;
++ unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS];
++ struct device_node *root;
++ int irq_count;
++
++ /* Find the Open PIC if present */
++ root = of_find_node_by_path("/");
++ opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL);
++ if (opprop != 0) {
++ int n = prom_n_addr_cells(root);
++
++ for (openpic_addr = 0; n > 0; --n)
++ openpic_addr = (openpic_addr << 32) + *opprop++;
++ printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
++ }
++ of_node_put(root);
++
++ BUG_ON(openpic_addr == 0);
++
++ /* Get the sense values from OF */
++ prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
++
++ /* Setup the openpic driver */
++ irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
++ pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY,
++ 16, 16, irq_count, /* isu size, irq offset, irq count */
++ NR_IRQS - 4, /* ipi offset */
++ senses, irq_count, /* sense & sense size */
++ " MPIC ");
++}
++
++static void pseries_lpar_enable_pmcs(void)
++{
++ unsigned long set, reset;
++
++ power4_enable_pmcs();
++
++ set = 1UL << 63;
++ reset = 0;
++ plpar_hcall_norets(H_PERFMON, set, reset);
++
++ /* instruct hypervisor to maintain PMCs */
++ if (firmware_has_feature(FW_FEATURE_SPLPAR))
++ get_paca()->lppaca.pmcregs_in_use = 1;
++}
++
++static void __init pSeries_setup_arch(void)
++{
++ /* Fixup ppc_md depending on the type of interrupt controller */
++ if (ppc64_interrupt_controller == IC_OPEN_PIC) {
++ ppc_md.init_IRQ = pSeries_init_mpic;
++ ppc_md.get_irq = mpic_get_irq;
++ ppc_md.cpu_irq_down = mpic_teardown_this_cpu;
++ /* Allocate the mpic now, so that find_and_init_phbs() can
++ * fill the ISUs */
++ pSeries_setup_mpic();
++ } else {
++ ppc_md.init_IRQ = xics_init_IRQ;
++ ppc_md.get_irq = xics_get_irq;
++ ppc_md.cpu_irq_down = xics_teardown_cpu;
++ }
++
++#ifdef CONFIG_SMP
++ smp_init_pSeries();
++#endif
++ /* openpic global configuration register (64-bit format). */
++ /* openpic Interrupt Source Unit pointer (64-bit format). */
++ /* python0 facility area (mmio) (64-bit format) REAL address. */
++
++ /* init to some ~sane value until calibrate_delay() runs */
++ loops_per_jiffy = 50000000;
++
++ if (ROOT_DEV == 0) {
++ printk("No ramdisk, default root is /dev/sda2\n");
++ ROOT_DEV = Root_SDA2;
++ }
++
++ fwnmi_init();
++
++ /* Find and initialize PCI host bridges */
++ init_pci_config_tokens();
++ find_and_init_phbs();
++ eeh_init();
++
++ pSeries_nvram_init();
++
++ /* Choose an idle loop */
++ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
++ vpa_init(boot_cpuid);
++ if (get_paca()->lppaca.shared_proc) {
++ printk(KERN_INFO "Using shared processor idle loop\n");
++ ppc_md.idle_loop = pseries_shared_idle;
++ } else {
++ printk(KERN_INFO "Using dedicated idle loop\n");
++ ppc_md.idle_loop = pseries_dedicated_idle;
++ }
++ } else {
++ printk(KERN_INFO "Using default idle loop\n");
++ ppc_md.idle_loop = default_idle;
++ }
++
++ if (systemcfg->platform & PLATFORM_LPAR)
++ ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
++ else
++ ppc_md.enable_pmcs = power4_enable_pmcs;
++}
++
++static int __init pSeries_init_panel(void)
++{
++ /* Manually leave the kernel version on the panel. */
++ ppc_md.progress("Linux ppc64\n", 0);
++ ppc_md.progress(system_utsname.version, 0);
++
++ return 0;
++}
++arch_initcall(pSeries_init_panel);
++
++
++/* Build up the ppc64_firmware_features bitmask field
++ * using contents of device-tree/ibm,hypertas-functions.
++ * Ultimately this functionality may be moved into prom.c prom_init().
++ */
++static void __init fw_feature_init(void)
++{
++ struct device_node * dn;
++ char * hypertas;
++ unsigned int len;
++
++ DBG(" -> fw_feature_init()\n");
++
++ ppc64_firmware_features = 0;
++ dn = of_find_node_by_path("/rtas");
++ if (dn == NULL) {
++ printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
++ goto no_rtas;
++ }
++
++ hypertas = get_property(dn, "ibm,hypertas-functions", &len);
++ if (hypertas) {
++ while (len > 0){
++ int i, hypertas_len;
++ /* check value against table of strings */
++ for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) {
++ if ((firmware_features_table[i].name) &&
++ (strcmp(firmware_features_table[i].name,hypertas))==0) {
++ /* we have a match */
++ ppc64_firmware_features |=
++ (firmware_features_table[i].val);
++ break;
++ }
++ }
++ hypertas_len = strlen(hypertas);
++ len -= hypertas_len +1;
++ hypertas+= hypertas_len +1;
++ }
++ }
++
++ of_node_put(dn);
++ no_rtas:
++ printk(KERN_INFO "firmware_features = 0x%lx\n",
++ ppc64_firmware_features);
++
++ DBG(" <- fw_feature_init()\n");
++}
++
++
++static void __init pSeries_discover_pic(void)
++{
++ struct device_node *np;
++ char *typep;
++
++ /*
++ * Setup interrupt mapping options that are needed for finish_device_tree
++ * to properly parse the OF interrupt tree & do the virtual irq mapping
++ */
++ __irq_offset_value = NUM_ISA_INTERRUPTS;
++ ppc64_interrupt_controller = IC_INVALID;
++ for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
++ typep = (char *)get_property(np, "compatible", NULL);
++ if (strstr(typep, "open-pic"))
++ ppc64_interrupt_controller = IC_OPEN_PIC;
++ else if (strstr(typep, "ppc-xicp"))
++ ppc64_interrupt_controller = IC_PPC_XIC;
++ else
++ printk("pSeries_discover_pic: failed to recognize"
++ " interrupt-controller\n");
++ break;
++ }
++}
++
++static void pSeries_mach_cpu_die(void)
++{
++ local_irq_disable();
++ idle_task_exit();
++ /* Some hardware requires clearing the CPPR, while other hardware does not
++ * it is safe either way
++ */
++ pSeriesLP_cppr_info(0, 0);
++ rtas_stop_self();
++ /* Should never get here... */
++ BUG();
++ for(;;);
++}
++
++
++/*
++ * Early initialization. Relocation is on but do not reference unbolted pages
++ */
++static void __init pSeries_init_early(void)
++{
++ void *comport;
++ int iommu_off = 0;
++ unsigned int default_speed;
++ u64 physport;
++
++ DBG(" -> pSeries_init_early()\n");
++
++ fw_feature_init();
++
++ if (systemcfg->platform & PLATFORM_LPAR)
++ hpte_init_lpar();
++ else {
++ hpte_init_native();
++ iommu_off = (of_chosen &&
++ get_property(of_chosen, "linux,iommu-off", NULL));
++ }
++
++ generic_find_legacy_serial_ports(&physport, &default_speed);
++
++ if (systemcfg->platform & PLATFORM_LPAR)
++ find_udbg_vterm();
++ else if (physport) {
++ /* Map the uart for udbg. */
++ comport = (void *)ioremap(physport, 16);
++ udbg_init_uart(comport, default_speed);
++
++ DBG("Hello World !\n");
++ }
++
++
++ iommu_init_early_pSeries();
++
++ pSeries_discover_pic();
++
++ DBG(" <- pSeries_init_early()\n");
++}
++
++
++static int pSeries_check_legacy_ioport(unsigned int baseport)
++{
++ struct device_node *np;
++
++#define I8042_DATA_REG 0x60
++#define FDC_BASE 0x3f0
++
++
++ switch(baseport) {
++ case I8042_DATA_REG:
++ np = of_find_node_by_type(NULL, "8042");
++ if (np == NULL)
++ return -ENODEV;
++ of_node_put(np);
++ break;
++ case FDC_BASE:
++ np = of_find_node_by_type(NULL, "fdc");
++ if (np == NULL)
++ return -ENODEV;
++ of_node_put(np);
++ break;
++ }
++ return 0;
++}
++
++/*
++ * Called very early, MMU is off, device-tree isn't unflattened
++ */
++extern struct machdep_calls pSeries_md;
++
++static int __init pSeries_probe(int platform)
++{
++ if (platform != PLATFORM_PSERIES &&
++ platform != PLATFORM_PSERIES_LPAR)
++ return 0;
++
++ /* if we have some ppc_md fixups for LPAR to do, do
++ * it here ...
++ */
++
++ return 1;
++}
++
++DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
++
++static inline void dedicated_idle_sleep(unsigned int cpu)
++{
++ struct paca_struct *ppaca = &paca[cpu ^ 1];
++
++ /* Only sleep if the other thread is not idle */
++ if (!(ppaca->lppaca.idle)) {
++ local_irq_disable();
++
++ /*
++ * We are about to sleep the thread and so wont be polling any
++ * more.
++ */
++ clear_thread_flag(TIF_POLLING_NRFLAG);
++
++ /*
++ * SMT dynamic mode. Cede will result in this thread going
++ * dormant, if the partner thread is still doing work. Thread
++ * wakes up if partner goes idle, an interrupt is presented, or
++ * a prod occurs. Returning from the cede enables external
++ * interrupts.
++ */
++ if (!need_resched())
++ cede_processor();
++ else
++ local_irq_enable();
++ } else {
++ /*
++ * Give the HV an opportunity at the processor, since we are
++ * not doing any work.
++ */
++ poll_pending();
++ }
++}
++
++static void pseries_dedicated_idle(void)
++{
++ long oldval;
++ struct paca_struct *lpaca = get_paca();
++ unsigned int cpu = smp_processor_id();
++ unsigned long start_snooze;
++ unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
++
++ while (1) {
++ /*
++ * Indicate to the HV that we are idle. Now would be
++ * a good time to find other work to dispatch.
++ */
++ lpaca->lppaca.idle = 1;
++
++ oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
++ if (!oldval) {
++ set_thread_flag(TIF_POLLING_NRFLAG);
++
++ start_snooze = __get_tb() +
++ *smt_snooze_delay * tb_ticks_per_usec;
++
++ while (!need_resched() && !cpu_is_offline(cpu)) {
++ ppc64_runlatch_off();
++
++ /*
++ * Go into low thread priority and possibly
++ * low power mode.
++ */
++ HMT_low();
++ HMT_very_low();
++
++ if (*smt_snooze_delay != 0 &&
++ __get_tb() > start_snooze) {
++ HMT_medium();
++ dedicated_idle_sleep(cpu);
++ }
++
++ }
++
++ HMT_medium();
++ clear_thread_flag(TIF_POLLING_NRFLAG);
++ } else {
++ set_need_resched();
++ }
++
++ lpaca->lppaca.idle = 0;
++ ppc64_runlatch_on();
++
++ schedule();
++
++ if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
++ cpu_die();
++ }
++}
++
++static void pseries_shared_idle(void)
++{
++ struct paca_struct *lpaca = get_paca();
++ unsigned int cpu = smp_processor_id();
++
++ while (1) {
++ /*
++ * Indicate to the HV that we are idle. Now would be
++ * a good time to find other work to dispatch.
++ */
++ lpaca->lppaca.idle = 1;
++
++ while (!need_resched() && !cpu_is_offline(cpu)) {
++ local_irq_disable();
++ ppc64_runlatch_off();
++
++ /*
++ * Yield the processor to the hypervisor. We return if
++ * an external interrupt occurs (which are driven prior
++ * to returning here) or if a prod occurs from another
++ * processor. When returning here, external interrupts
++ * are enabled.
++ *
++ * Check need_resched() again with interrupts disabled
++ * to avoid a race.
++ */
++ if (!need_resched())
++ cede_processor();
++ else
++ local_irq_enable();
++
++ HMT_medium();
++ }
++
++ lpaca->lppaca.idle = 0;
++ ppc64_runlatch_on();
++
++ schedule();
++
++ if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
++ cpu_die();
++ }
++}
++
++static int pSeries_pci_probe_mode(struct pci_bus *bus)
++{
++ if (systemcfg->platform & PLATFORM_LPAR)
++ return PCI_PROBE_DEVTREE;
++ return PCI_PROBE_NORMAL;
++}
++
++struct machdep_calls __initdata pSeries_md = {
++ .probe = pSeries_probe,
++ .setup_arch = pSeries_setup_arch,
++ .init_early = pSeries_init_early,
++ .show_cpuinfo = pSeries_show_cpuinfo,
++ .log_error = pSeries_log_error,
++ .pcibios_fixup = pSeries_final_fixup,
++ .pci_probe_mode = pSeries_pci_probe_mode,
++ .irq_bus_setup = pSeries_irq_bus_setup,
++ .restart = rtas_fw_restart,
++ .power_off = rtas_fw_power_off,
++ .halt = rtas_fw_halt,
++ .panic = rtas_os_term,
++ .cpu_die = pSeries_mach_cpu_die,
++ .get_boot_time = rtas_get_boot_time,
++ .get_rtc_time = rtas_get_rtc_time,
++ .set_rtc_time = rtas_set_rtc_time,
++ .calibrate_decr = generic_calibrate_decr,
++ .progress = rtas_progress,
++ .check_legacy_ioport = pSeries_check_legacy_ioport,
++ .system_reset_exception = pSeries_system_reset_exception,
++ .machine_check_exception = pSeries_machine_check_exception,
++};
+diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/smp.c
+@@ -0,0 +1,471 @@
++/*
++ * SMP support for pSeries machines.
++ *
++ * Dave Engebretsen, Peter Bergner, and
++ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
++ *
++ * Plus various changes from other IBM teams...
++ *
++ * 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.
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/cache.h>
++#include <linux/err.h>
++#include <linux/sysdev.h>
++#include <linux/cpu.h>
++
++#include <asm/ptrace.h>
++#include <asm/atomic.h>
++#include <asm/irq.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/smp.h>
++#include <asm/paca.h>
++#include <asm/time.h>
++#include <asm/machdep.h>
++#include "xics.h"
++#include <asm/cputable.h>
++#include <asm/firmware.h>
++#include <asm/system.h>
++#include <asm/rtas.h>
++#include <asm/plpar_wrappers.h>
++#include <asm/pSeries_reconfig.h>
++#include <asm/mpic.h>
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/*
++ * The primary thread of each non-boot processor is recorded here before
++ * smp init.
++ */
++static cpumask_t of_spin_map;
++
++extern void pSeries_secondary_smp_init(unsigned long);
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++/* Get state of physical CPU.
++ * Return codes:
++ * 0 - The processor is in the RTAS stopped state
++ * 1 - stop-self is in progress
++ * 2 - The processor is not in the RTAS stopped state
++ * -1 - Hardware Error
++ * -2 - Hardware Busy, Try again later.
++ */
++static int query_cpu_stopped(unsigned int pcpu)
++{
++ int cpu_status;
++ int status, qcss_tok;
++
++ qcss_tok = rtas_token("query-cpu-stopped-state");
++ if (qcss_tok == RTAS_UNKNOWN_SERVICE)
++ return -1;
++ status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
++ if (status != 0) {
++ printk(KERN_ERR
++ "RTAS query-cpu-stopped-state failed: %i\n", status);
++ return status;
++ }
++
++ return cpu_status;
++}
++
++int pSeries_cpu_disable(void)
++{
++ int cpu = smp_processor_id();
++
++ cpu_clear(cpu, cpu_online_map);
++ systemcfg->processorCount--;
++
++ /*fix boot_cpuid here*/
++ if (cpu == boot_cpuid)
++ boot_cpuid = any_online_cpu(cpu_online_map);
++
++ /* FIXME: abstract this to not be platform specific later on */
++ xics_migrate_irqs_away();
++ return 0;
++}
++
++void pSeries_cpu_die(unsigned int cpu)
++{
++ int tries;
++ int cpu_status;
++ unsigned int pcpu = get_hard_smp_processor_id(cpu);
++
++ for (tries = 0; tries < 25; tries++) {
++ cpu_status = query_cpu_stopped(pcpu);
++ if (cpu_status == 0 || cpu_status == -1)
++ break;
++ msleep(200);
++ }
++ if (cpu_status != 0) {
++ printk("Querying DEAD? cpu %i (%i) shows %i\n",
++ cpu, pcpu, cpu_status);
++ }
++
++ /* Isolation and deallocation are definatly done by
++ * drslot_chrp_cpu. If they were not they would be
++ * done here. Change isolate state to Isolate and
++ * change allocation-state to Unusable.
++ */
++ paca[cpu].cpu_start = 0;
++}
++
++/*
++ * Update cpu_present_map and paca(s) for a new cpu node. The wrinkle
++ * here is that a cpu device node may represent up to two logical cpus
++ * in the SMT case. We must honor the assumption in other code that
++ * the logical ids for sibling SMT threads x and y are adjacent, such
++ * that x^1 == y and y^1 == x.
++ */
++static int pSeries_add_processor(struct device_node *np)
++{
++ unsigned int cpu;
++ cpumask_t candidate_map, tmp = CPU_MASK_NONE;
++ int err = -ENOSPC, len, nthreads, i;
++ u32 *intserv;
++
++ intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len);
++ if (!intserv)
++ return 0;
++
++ nthreads = len / sizeof(u32);
++ for (i = 0; i < nthreads; i++)
++ cpu_set(i, tmp);
++
++ lock_cpu_hotplug();
++
++ BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
++
++ /* Get a bitmap of unoccupied slots. */
++ cpus_xor(candidate_map, cpu_possible_map, cpu_present_map);
++ if (cpus_empty(candidate_map)) {
++ /* If we get here, it most likely means that NR_CPUS is
++ * less than the partition's max processors setting.
++ */
++ printk(KERN_ERR "Cannot add cpu %s; this system configuration"
++ " supports %d logical cpus.\n", np->full_name,
++ cpus_weight(cpu_possible_map));
++ goto out_unlock;
++ }
++
++ while (!cpus_empty(tmp))
++ if (cpus_subset(tmp, candidate_map))
++ /* Found a range where we can insert the new cpu(s) */
++ break;
++ else
++ cpus_shift_left(tmp, tmp, nthreads);
++
++ if (cpus_empty(tmp)) {
++ printk(KERN_ERR "Unable to find space in cpu_present_map for"
++ " processor %s with %d thread(s)\n", np->name,
++ nthreads);
++ goto out_unlock;
++ }
++
++ for_each_cpu_mask(cpu, tmp) {
++ BUG_ON(cpu_isset(cpu, cpu_present_map));
++ cpu_set(cpu, cpu_present_map);
++ set_hard_smp_processor_id(cpu, *intserv++);
++ }
++ err = 0;
++out_unlock:
++ unlock_cpu_hotplug();
++ return err;
++}
++
++/*
++ * Update the present map for a cpu node which is going away, and set
++ * the hard id in the paca(s) to -1 to be consistent with boot time
++ * convention for non-present cpus.
++ */
++static void pSeries_remove_processor(struct device_node *np)
++{
++ unsigned int cpu;
++ int len, nthreads, i;
++ u32 *intserv;
++
++ intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len);
++ if (!intserv)
++ return;
++
++ nthreads = len / sizeof(u32);
++
++ lock_cpu_hotplug();
++ for (i = 0; i < nthreads; i++) {
++ for_each_present_cpu(cpu) {
++ if (get_hard_smp_processor_id(cpu) != intserv[i])
++ continue;
++ BUG_ON(cpu_online(cpu));
++ cpu_clear(cpu, cpu_present_map);
++ set_hard_smp_processor_id(cpu, -1);
++ break;
++ }
++ if (cpu == NR_CPUS)
++ printk(KERN_WARNING "Could not find cpu to remove "
++ "with physical id 0x%x\n", intserv[i]);
++ }
++ unlock_cpu_hotplug();
++}
++
++static int pSeries_smp_notifier(struct notifier_block *nb, unsigned long action, void *node)
++{
++ int err = NOTIFY_OK;
++
++ switch (action) {
++ case PSERIES_RECONFIG_ADD:
++ if (pSeries_add_processor(node))
++ err = NOTIFY_BAD;
++ break;
++ case PSERIES_RECONFIG_REMOVE:
++ pSeries_remove_processor(node);
++ break;
++ default:
++ err = NOTIFY_DONE;
++ break;
++ }
++ return err;
++}
++
++static struct notifier_block pSeries_smp_nb = {
++ .notifier_call = pSeries_smp_notifier,
++};
++
++#endif /* CONFIG_HOTPLUG_CPU */
++
++/**
++ * smp_startup_cpu() - start the given cpu
++ *
++ * At boot time, there is nothing to do for primary threads which were
++ * started from Open Firmware. For anything else, call RTAS with the
++ * appropriate start location.
++ *
++ * Returns:
++ * 0 - failure
++ * 1 - success
++ */
++static inline int __devinit smp_startup_cpu(unsigned int lcpu)
++{
++ int status;
++ unsigned long start_here = __pa((u32)*((unsigned long *)
++ pSeries_secondary_smp_init));
++ unsigned int pcpu;
++ int start_cpu;
++
++ if (cpu_isset(lcpu, of_spin_map))
++ /* Already started by OF and sitting in spin loop */
++ return 1;
++
++ pcpu = get_hard_smp_processor_id(lcpu);
++
++ /* Fixup atomic count: it exited inside IRQ handler. */
++ paca[lcpu].__current->thread_info->preempt_count = 0;
++
++ /*
++ * If the RTAS start-cpu token does not exist then presume the
++ * cpu is already spinning.
++ */
++ start_cpu = rtas_token("start-cpu");
++ if (start_cpu == RTAS_UNKNOWN_SERVICE)
++ return 1;
++
++ status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
++ if (status != 0) {
++ printk(KERN_ERR "start-cpu failed: %i\n", status);
++ return 0;
++ }
++
++ return 1;
++}
++
++#ifdef CONFIG_XICS
++static inline void smp_xics_do_message(int cpu, int msg)
++{
++ set_bit(msg, &xics_ipi_message[cpu].value);
++ mb();
++ xics_cause_IPI(cpu);
++}
++
++static void smp_xics_message_pass(int target, int msg)
++{
++ unsigned int i;
++
++ if (target < NR_CPUS) {
++ smp_xics_do_message(target, msg);
++ } else {
++ for_each_online_cpu(i) {
++ if (target == MSG_ALL_BUT_SELF
++ && i == smp_processor_id())
++ continue;
++ smp_xics_do_message(i, msg);
++ }
++ }
++}
++
++static int __init smp_xics_probe(void)
++{
++ xics_request_IPIs();
++
++ return cpus_weight(cpu_possible_map);
++}
++
++static void __devinit smp_xics_setup_cpu(int cpu)
++{
++ if (cpu != boot_cpuid)
++ xics_setup_cpu();
++
++ if (firmware_has_feature(FW_FEATURE_SPLPAR))
++ vpa_init(cpu);
++
++ cpu_clear(cpu, of_spin_map);
++
++}
++#endif /* CONFIG_XICS */
++
++static DEFINE_SPINLOCK(timebase_lock);
++static unsigned long timebase = 0;
++
++static void __devinit pSeries_give_timebase(void)
++{
++ spin_lock(&timebase_lock);
++ rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
++ timebase = get_tb();
++ spin_unlock(&timebase_lock);
++
++ while (timebase)
++ barrier();
++ rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
++}
++
++static void __devinit pSeries_take_timebase(void)
++{
++ while (!timebase)
++ barrier();
++ spin_lock(&timebase_lock);
++ set_tb(timebase >> 32, timebase & 0xffffffff);
++ timebase = 0;
++ spin_unlock(&timebase_lock);
++}
++
++static void __devinit smp_pSeries_kick_cpu(int nr)
++{
++ BUG_ON(nr < 0 || nr >= NR_CPUS);
++
++ if (!smp_startup_cpu(nr))
++ return;
++
++ /*
++ * The processor is currently spinning, waiting for the
++ * cpu_start field to become non-zero After we set cpu_start,
++ * the processor will continue on to secondary_start
++ */
++ paca[nr].cpu_start = 1;
++}
++
++static int smp_pSeries_cpu_bootable(unsigned int nr)
++{
++ /* Special case - we inhibit secondary thread startup
++ * during boot if the user requests it. Odd-numbered
++ * cpus are assumed to be secondary threads.
++ */
++ if (system_state < SYSTEM_RUNNING &&
++ cpu_has_feature(CPU_FTR_SMT) &&
++ !smt_enabled_at_boot && nr % 2 != 0)
++ return 0;
++
++ return 1;
++}
++#ifdef CONFIG_MPIC
++static struct smp_ops_t pSeries_mpic_smp_ops = {
++ .message_pass = smp_mpic_message_pass,
++ .probe = smp_mpic_probe,
++ .kick_cpu = smp_pSeries_kick_cpu,
++ .setup_cpu = smp_mpic_setup_cpu,
++};
++#endif
++#ifdef CONFIG_XICS
++static struct smp_ops_t pSeries_xics_smp_ops = {
++ .message_pass = smp_xics_message_pass,
++ .probe = smp_xics_probe,
++ .kick_cpu = smp_pSeries_kick_cpu,
++ .setup_cpu = smp_xics_setup_cpu,
++ .cpu_bootable = smp_pSeries_cpu_bootable,
++};
++#endif
++
++/* This is called very early */
++void __init smp_init_pSeries(void)
++{
++ int i;
++
++ DBG(" -> smp_init_pSeries()\n");
++
++ switch (ppc64_interrupt_controller) {
++#ifdef CONFIG_MPIC
++ case IC_OPEN_PIC:
++ smp_ops = &pSeries_mpic_smp_ops;
++ break;
++#endif
++#ifdef CONFIG_XICS
++ case IC_PPC_XIC:
++ smp_ops = &pSeries_xics_smp_ops;
++ break;
++#endif
++ default:
++ panic("Invalid interrupt controller");
++ }
++
++#ifdef CONFIG_HOTPLUG_CPU
++ smp_ops->cpu_disable = pSeries_cpu_disable;
++ smp_ops->cpu_die = pSeries_cpu_die;
++
++ /* Processors can be added/removed only on LPAR */
++ if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
++ pSeries_reconfig_notifier_register(&pSeries_smp_nb);
++#endif
++
++ /* Mark threads which are still spinning in hold loops. */
++ if (cpu_has_feature(CPU_FTR_SMT)) {
++ for_each_present_cpu(i) {
++ if (i % 2 == 0)
++ /*
++ * Even-numbered logical cpus correspond to
++ * primary threads.
++ */
++ cpu_set(i, of_spin_map);
++ }
++ } else {
++ of_spin_map = cpu_present_map;
++ }
++
++ cpu_clear(boot_cpuid, of_spin_map);
++
++ /* Non-lpar has additional take/give timebase */
++ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
++ smp_ops->give_timebase = pSeries_give_timebase;
++ smp_ops->take_timebase = pSeries_take_timebase;
++ }
++
++ DBG(" <- smp_init_pSeries()\n");
++}
++
+diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/vio.c
+@@ -0,0 +1,274 @@
++/*
++ * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
++ *
++ * Copyright (c) 2003-2005 IBM Corp.
++ * Dave Engebretsen engebret at us.ibm.com
++ * Santiago Leon santil at us.ibm.com
++ * Hollis Blanchard <hollisb at us.ibm.com>
++ * Stephen Rothwell
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/kobject.h>
++#include <asm/iommu.h>
++#include <asm/dma.h>
++#include <asm/prom.h>
++#include <asm/vio.h>
++#include <asm/hvcall.h>
++#include <asm/tce.h>
++
++extern struct subsystem devices_subsys; /* needed for vio_find_name() */
++
++static void probe_bus_pseries(void)
++{
++ struct device_node *node_vroot, *of_node;
++
++ node_vroot = find_devices("vdevice");
++ if ((node_vroot == NULL) || (node_vroot->child == NULL))
++ /* this machine doesn't do virtual IO, and that's ok */
++ return;
++
++ /*
++ * Create struct vio_devices for each virtual device in the device tree.
++ * Drivers will associate with them later.
++ */
++ for (of_node = node_vroot->child; of_node != NULL;
++ of_node = of_node->sibling) {
++ printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
++ vio_register_device_node(of_node);
++ }
++}
++
++/**
++ * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
++ * vio_device_id
++ */
++static int vio_match_device_pseries(const struct vio_device_id *id,
++ const struct vio_dev *dev)
++{
++ return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
++ device_is_compatible(dev->dev.platform_data, id->compat);
++}
++
++static void vio_release_device_pseries(struct device *dev)
++{
++ /* XXX free TCE table */
++ of_node_put(dev->platform_data);
++}
++
++static ssize_t viodev_show_devspec(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct device_node *of_node = dev->platform_data;
++
++ return sprintf(buf, "%s\n", of_node->full_name);
++}
++DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
++
++static void vio_unregister_device_pseries(struct vio_dev *viodev)
++{
++ device_remove_file(&viodev->dev, &dev_attr_devspec);
++}
++
++static struct vio_bus_ops vio_bus_ops_pseries = {
++ .match = vio_match_device_pseries,
++ .unregister_device = vio_unregister_device_pseries,
++ .release_device = vio_release_device_pseries,
++};
++
++/**
++ * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
++ */
++static int __init vio_bus_init_pseries(void)
++{
++ int err;
++
++ err = vio_bus_init(&vio_bus_ops_pseries);
++ if (err == 0)
++ probe_bus_pseries();
++ return err;
++}
++
++__initcall(vio_bus_init_pseries);
++
++/**
++ * vio_build_iommu_table: - gets the dma information from OF and
++ * builds the TCE tree.
++ * @dev: the virtual device.
++ *
++ * Returns a pointer to the built tce tree, or NULL if it can't
++ * find property.
++*/
++static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
++{
++ unsigned int *dma_window;
++ struct iommu_table *newTceTable;
++ unsigned long offset;
++ int dma_window_property_size;
++
++ dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
++ if(!dma_window) {
++ return NULL;
++ }
++
++ newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
++
++ /* There should be some code to extract the phys-encoded offset
++ using prom_n_addr_cells(). However, according to a comment
++ on earlier versions, it's always zero, so we don't bother */
++ offset = dma_window[1] >> PAGE_SHIFT;
++
++ /* TCE table size - measured in tce entries */
++ newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
++ /* offset for VIO should always be 0 */
++ newTceTable->it_offset = offset;
++ newTceTable->it_busno = 0;
++ newTceTable->it_index = (unsigned long)dma_window[0];
++ newTceTable->it_type = TCE_VB;
++
++ return iommu_init_table(newTceTable);
++}
++
++/**
++ * vio_register_device_node: - Register a new vio device.
++ * @of_node: The OF node for this device.
++ *
++ * Creates and initializes a vio_dev structure from the data in
++ * of_node (dev.platform_data) and adds it to the list of virtual devices.
++ * Returns a pointer to the created vio_dev or NULL if node has
++ * NULL device_type or compatible fields.
++ */
++struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
++{
++ struct vio_dev *viodev;
++ unsigned int *unit_address;
++ unsigned int *irq_p;
++
++ /* we need the 'device_type' property, in order to match with drivers */
++ if ((NULL == of_node->type)) {
++ printk(KERN_WARNING
++ "%s: node %s missing 'device_type'\n", __FUNCTION__,
++ of_node->name ? of_node->name : "<unknown>");
++ return NULL;
++ }
++
++ unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
++ if (!unit_address) {
++ printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
++ of_node->name ? of_node->name : "<unknown>");
++ return NULL;
++ }
++
++ /* allocate a vio_dev for this node */
++ viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
++ if (!viodev) {
++ return NULL;
++ }
++ memset(viodev, 0, sizeof(struct vio_dev));
++
++ viodev->dev.platform_data = of_node_get(of_node);
++
++ viodev->irq = NO_IRQ;
++ irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
++ if (irq_p) {
++ int virq = virt_irq_create_mapping(*irq_p);
++ if (virq == NO_IRQ) {
++ printk(KERN_ERR "Unable to allocate interrupt "
++ "number for %s\n", of_node->full_name);
++ } else
++ viodev->irq = irq_offset_up(virq);
++ }
++
++ snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
++ viodev->name = of_node->name;
++ viodev->type = of_node->type;
++ viodev->unit_address = *unit_address;
++ viodev->iommu_table = vio_build_iommu_table(viodev);
++
++ /* register with generic device framework */
++ if (vio_register_device(viodev) == NULL) {
++ /* XXX free TCE table */
++ kfree(viodev);
++ return NULL;
++ }
++ device_create_file(&viodev->dev, &dev_attr_devspec);
++
++ return viodev;
++}
++EXPORT_SYMBOL(vio_register_device_node);
++
++/**
++ * vio_get_attribute: - get attribute for virtual device
++ * @vdev: The vio device to get property.
++ * @which: The property/attribute to be extracted.
++ * @length: Pointer to length of returned data size (unused if NULL).
++ *
++ * Calls prom.c's get_property() to return the value of the
++ * attribute specified by the preprocessor constant @which
++*/
++const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
++{
++ return get_property(vdev->dev.platform_data, (char*)which, length);
++}
++EXPORT_SYMBOL(vio_get_attribute);
++
++/* vio_find_name() - internal because only vio.c knows how we formatted the
++ * kobject name
++ * XXX once vio_bus_type.devices is actually used as a kset in
++ * drivers/base/bus.c, this function should be removed in favor of
++ * "device_find(kobj_name, &vio_bus_type)"
++ */
++static struct vio_dev *vio_find_name(const char *kobj_name)
++{
++ struct kobject *found;
++
++ found = kset_find_obj(&devices_subsys.kset, kobj_name);
++ if (!found)
++ return NULL;
++
++ return to_vio_dev(container_of(found, struct device, kobj));
++}
++
++/**
++ * vio_find_node - find an already-registered vio_dev
++ * @vnode: device_node of the virtual device we're looking for
++ */
++struct vio_dev *vio_find_node(struct device_node *vnode)
++{
++ uint32_t *unit_address;
++ char kobj_name[BUS_ID_SIZE];
++
++ /* construct the kobject name from the device node */
++ unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
++ if (!unit_address)
++ return NULL;
++ snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
++
++ return vio_find_name(kobj_name);
++}
++EXPORT_SYMBOL(vio_find_node);
++
++int vio_enable_interrupts(struct vio_dev *dev)
++{
++ int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
++ if (rc != H_Success)
++ printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
++ return rc;
++}
++EXPORT_SYMBOL(vio_enable_interrupts);
++
++int vio_disable_interrupts(struct vio_dev *dev)
++{
++ int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
++ if (rc != H_Success)
++ printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
++ return rc;
++}
++EXPORT_SYMBOL(vio_disable_interrupts);
+diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/xics.c
+@@ -0,0 +1,747 @@
++/*
++ * arch/powerpc/platforms/pseries/xics.c
++ *
++ * Copyright 2000 IBM Corporation.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/threads.h>
++#include <linux/kernel.h>
++#include <linux/irq.h>
++#include <linux/smp.h>
++#include <linux/interrupt.h>
++#include <linux/signal.h>
++#include <linux/init.h>
++#include <linux/gfp.h>
++#include <linux/radix-tree.h>
++#include <linux/cpu.h>
++#include <asm/prom.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/smp.h>
++#include <asm/rtas.h>
++#include <asm/hvcall.h>
++#include <asm/machdep.h>
++#include <asm/i8259.h>
++
++#include "xics.h"
++
++static unsigned int xics_startup(unsigned int irq);
++static void xics_enable_irq(unsigned int irq);
++static void xics_disable_irq(unsigned int irq);
++static void xics_mask_and_ack_irq(unsigned int irq);
++static void xics_end_irq(unsigned int irq);
++static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
++
++static struct hw_interrupt_type xics_pic = {
++ .typename = " XICS ",
++ .startup = xics_startup,
++ .enable = xics_enable_irq,
++ .disable = xics_disable_irq,
++ .ack = xics_mask_and_ack_irq,
++ .end = xics_end_irq,
++ .set_affinity = xics_set_affinity
++};
++
++static struct hw_interrupt_type xics_8259_pic = {
++ .typename = " XICS/8259",
++ .ack = xics_mask_and_ack_irq,
++};
++
++/* This is used to map real irq numbers to virtual */
++static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC);
++
++#define XICS_IPI 2
++#define XICS_IRQ_SPURIOUS 0
++
++/* Want a priority other than 0. Various HW issues require this. */
++#define DEFAULT_PRIORITY 5
++
++/*
++ * Mark IPIs as higher priority so we can take them inside interrupts that
++ * arent marked SA_INTERRUPT
++ */
++#define IPI_PRIORITY 4
++
++struct xics_ipl {
++ union {
++ u32 word;
++ u8 bytes[4];
++ } xirr_poll;
++ union {
++ u32 word;
++ u8 bytes[4];
++ } xirr;
++ u32 dummy;
++ union {
++ u32 word;
++ u8 bytes[4];
++ } qirr;
++};
++
++static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
++
++static int xics_irq_8259_cascade = 0;
++static int xics_irq_8259_cascade_real = 0;
++static unsigned int default_server = 0xFF;
++static unsigned int default_distrib_server = 0;
++static unsigned int interrupt_server_size = 8;
++
++/*
++ * XICS only has a single IPI, so encode the messages per CPU
++ */
++struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
++
++/* RTAS service tokens */
++static int ibm_get_xive;
++static int ibm_set_xive;
++static int ibm_int_on;
++static int ibm_int_off;
++
++typedef struct {
++ int (*xirr_info_get)(int cpu);
++ void (*xirr_info_set)(int cpu, int val);
++ void (*cppr_info)(int cpu, u8 val);
++ void (*qirr_info)(int cpu, u8 val);
++} xics_ops;
++
++
++/* SMP */
++
++static int pSeries_xirr_info_get(int n_cpu)
++{
++ return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
++}
++
++static void pSeries_xirr_info_set(int n_cpu, int value)
++{
++ out_be32(&xics_per_cpu[n_cpu]->xirr.word, value);
++}
++
++static void pSeries_cppr_info(int n_cpu, u8 value)
++{
++ out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value);
++}
++
++static void pSeries_qirr_info(int n_cpu, u8 value)
++{
++ out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value);
++}
++
++static xics_ops pSeries_ops = {
++ pSeries_xirr_info_get,
++ pSeries_xirr_info_set,
++ pSeries_cppr_info,
++ pSeries_qirr_info
++};
++
++static xics_ops *ops = &pSeries_ops;
++
++
++/* LPAR */
++
++static inline long plpar_eoi(unsigned long xirr)
++{
++ return plpar_hcall_norets(H_EOI, xirr);
++}
++
++static inline long plpar_cppr(unsigned long cppr)
++{
++ return plpar_hcall_norets(H_CPPR, cppr);
++}
++
++static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr)
++{
++ return plpar_hcall_norets(H_IPI, servernum, mfrr);
++}
++
++static inline long plpar_xirr(unsigned long *xirr_ret)
++{
++ unsigned long dummy;
++ return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy);
++}
++
++static int pSeriesLP_xirr_info_get(int n_cpu)
++{
++ unsigned long lpar_rc;
++ unsigned long return_value;
++
++ lpar_rc = plpar_xirr(&return_value);
++ if (lpar_rc != H_Success)
++ panic(" bad return code xirr - rc = %lx \n", lpar_rc);
++ return (int)return_value;
++}
++
++static void pSeriesLP_xirr_info_set(int n_cpu, int value)
++{
++ unsigned long lpar_rc;
++ unsigned long val64 = value & 0xffffffff;
++
++ lpar_rc = plpar_eoi(val64);
++ if (lpar_rc != H_Success)
++ panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
++ val64);
++}
++
++void pSeriesLP_cppr_info(int n_cpu, u8 value)
++{
++ unsigned long lpar_rc;
++
++ lpar_rc = plpar_cppr(value);
++ if (lpar_rc != H_Success)
++ panic("bad return code cppr - rc = %lx\n", lpar_rc);
++}
++
++static void pSeriesLP_qirr_info(int n_cpu , u8 value)
++{
++ unsigned long lpar_rc;
++
++ lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
++ if (lpar_rc != H_Success)
++ panic("bad return code qirr - rc = %lx\n", lpar_rc);
++}
++
++xics_ops pSeriesLP_ops = {
++ pSeriesLP_xirr_info_get,
++ pSeriesLP_xirr_info_set,
++ pSeriesLP_cppr_info,
++ pSeriesLP_qirr_info
++};
++
++static unsigned int xics_startup(unsigned int virq)
++{
++ unsigned int irq;
++
++ irq = irq_offset_down(virq);
++ if (radix_tree_insert(&irq_map, virt_irq_to_real(irq),
++ &virt_irq_to_real_map[irq]) == -ENOMEM)
++ printk(KERN_CRIT "Out of memory creating real -> virtual"
++ " IRQ mapping for irq %u (real 0x%x)\n",
++ virq, virt_irq_to_real(irq));
++ xics_enable_irq(virq);
++ return 0; /* return value is ignored */
++}
++
++static unsigned int real_irq_to_virt(unsigned int real_irq)
++{
++ unsigned int *ptr;
++
++ ptr = radix_tree_lookup(&irq_map, real_irq);
++ if (ptr == NULL)
++ return NO_IRQ;
++ return ptr - virt_irq_to_real_map;
++}
++
++#ifdef CONFIG_SMP
++static int get_irq_server(unsigned int irq)
++{
++ unsigned int server;
++ /* For the moment only implement delivery to all cpus or one cpu */
++ cpumask_t cpumask = irq_affinity[irq];
++ cpumask_t tmp = CPU_MASK_NONE;
++
++ if (!distribute_irqs)
++ return default_server;
++
++ if (cpus_equal(cpumask, CPU_MASK_ALL)) {
++ server = default_distrib_server;
++ } else {
++ cpus_and(tmp, cpu_online_map, cpumask);
++
++ if (cpus_empty(tmp))
++ server = default_distrib_server;
++ else
++ server = get_hard_smp_processor_id(first_cpu(tmp));
++ }
++
++ return server;
++
++}
++#else
++static int get_irq_server(unsigned int irq)
++{
++ return default_server;
++}
++#endif
++
++static void xics_enable_irq(unsigned int virq)
++{
++ unsigned int irq;
++ int call_status;
++ unsigned int server;
++
++ irq = virt_irq_to_real(irq_offset_down(virq));
++ if (irq == XICS_IPI)
++ return;
++
++ server = get_irq_server(virq);
++ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
++ DEFAULT_PRIORITY);
++ if (call_status != 0) {
++ printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
++ "returned %d\n", irq, call_status);
++ printk("set_xive %x, server %x\n", ibm_set_xive, server);
++ return;
++ }
++
++ /* Now unmask the interrupt (often a no-op) */
++ call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
++ if (call_status != 0) {
++ printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
++ "returned %d\n", irq, call_status);
++ return;
++ }
++}
++
++static void xics_disable_real_irq(unsigned int irq)
++{
++ int call_status;
++ unsigned int server;
++
++ if (irq == XICS_IPI)
++ return;
++
++ call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
++ if (call_status != 0) {
++ printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
++ "ibm_int_off returned %d\n", irq, call_status);
++ return;
++ }
++
++ server = get_irq_server(irq);
++ /* Have to set XIVE to 0xff to be able to remove a slot */
++ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
++ if (call_status != 0) {
++ printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
++ " returned %d\n", irq, call_status);
++ return;
++ }
++}
++
++static void xics_disable_irq(unsigned int virq)
++{
++ unsigned int irq;
++
++ irq = virt_irq_to_real(irq_offset_down(virq));
++ xics_disable_real_irq(irq);
++}
++
++static void xics_end_irq(unsigned int irq)
++{
++ int cpu = smp_processor_id();
++
++ iosync();
++ ops->xirr_info_set(cpu, ((0xff << 24) |
++ (virt_irq_to_real(irq_offset_down(irq)))));
++
++}
++
++static void xics_mask_and_ack_irq(unsigned int irq)
++{
++ int cpu = smp_processor_id();
++
++ if (irq < irq_offset_value()) {
++ i8259_pic.ack(irq);
++ iosync();
++ ops->xirr_info_set(cpu, ((0xff<<24) |
++ xics_irq_8259_cascade_real));
++ iosync();
++ }
++}
++
++int xics_get_irq(struct pt_regs *regs)
++{
++ unsigned int cpu = smp_processor_id();
++ unsigned int vec;
++ int irq;
++
++ vec = ops->xirr_info_get(cpu);
++ /* (vec >> 24) == old priority */
++ vec &= 0x00ffffff;
++
++ /* for sanity, this had better be < NR_IRQS - 16 */
++ if (vec == xics_irq_8259_cascade_real) {
++ irq = i8259_irq(regs);
++ if (irq == -1) {
++ /* Spurious cascaded interrupt. Still must ack xics */
++ xics_end_irq(irq_offset_up(xics_irq_8259_cascade));
++
++ irq = -1;
++ }
++ } else if (vec == XICS_IRQ_SPURIOUS) {
++ irq = -1;
++ } else {
++ irq = real_irq_to_virt(vec);
++ if (irq == NO_IRQ)
++ irq = real_irq_to_virt_slowpath(vec);
++ if (irq == NO_IRQ) {
++ printk(KERN_ERR "Interrupt %u (real) is invalid,"
++ " disabling it.\n", vec);
++ xics_disable_real_irq(vec);
++ } else
++ irq = irq_offset_up(irq);
++ }
++ return irq;
++}
++
++#ifdef CONFIG_SMP
++
++irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
++{
++ int cpu = smp_processor_id();
++
++ ops->qirr_info(cpu, 0xff);
++
++ WARN_ON(cpu_is_offline(cpu));
++
++ while (xics_ipi_message[cpu].value) {
++ if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
++ &xics_ipi_message[cpu].value)) {
++ mb();
++ smp_message_recv(PPC_MSG_CALL_FUNCTION, regs);
++ }
++ if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
++ &xics_ipi_message[cpu].value)) {
++ mb();
++ smp_message_recv(PPC_MSG_RESCHEDULE, regs);
++ }
++#if 0
++ if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK,
++ &xics_ipi_message[cpu].value)) {
++ mb();
++ smp_message_recv(PPC_MSG_MIGRATE_TASK, regs);
++ }
++#endif
++#ifdef CONFIG_DEBUGGER
++ if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
++ &xics_ipi_message[cpu].value)) {
++ mb();
++ smp_message_recv(PPC_MSG_DEBUGGER_BREAK, regs);
++ }
++#endif
++ }
++ return IRQ_HANDLED;
++}
++
++void xics_cause_IPI(int cpu)
++{
++ ops->qirr_info(cpu, IPI_PRIORITY);
++}
++#endif /* CONFIG_SMP */
++
++void xics_setup_cpu(void)
++{
++ int cpu = smp_processor_id();
++
++ ops->cppr_info(cpu, 0xff);
++ iosync();
++
++ /*
++ * Put the calling processor into the GIQ. This is really only
++ * necessary from a secondary thread as the OF start-cpu interface
++ * performs this function for us on primary threads.
++ *
++ * XXX: undo of teardown on kexec needs this too, as may hotplug
++ */
++ rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
++ (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
++}
++
++void xics_init_IRQ(void)
++{
++ int i;
++ unsigned long intr_size = 0;
++ struct device_node *np;
++ uint *ireg, ilen, indx = 0;
++ unsigned long intr_base = 0;
++ struct xics_interrupt_node {
++ unsigned long addr;
++ unsigned long size;
++ } intnodes[NR_CPUS];
++
++ ppc64_boot_msg(0x20, "XICS Init");
++
++ ibm_get_xive = rtas_token("ibm,get-xive");
++ ibm_set_xive = rtas_token("ibm,set-xive");
++ ibm_int_on = rtas_token("ibm,int-on");
++ ibm_int_off = rtas_token("ibm,int-off");
++
++ np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation");
++ if (!np)
++ panic("xics_init_IRQ: can't find interrupt presentation");
++
++nextnode:
++ ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL);
++ if (ireg) {
++ /*
++ * set node starting index for this node
++ */
++ indx = *ireg;
++ }
++
++ ireg = (uint *)get_property(np, "reg", &ilen);
++ if (!ireg)
++ panic("xics_init_IRQ: can't find interrupt reg property");
++
++ while (ilen) {
++ intnodes[indx].addr = (unsigned long)*ireg++ << 32;
++ ilen -= sizeof(uint);
++ intnodes[indx].addr |= *ireg++;
++ ilen -= sizeof(uint);
++ intnodes[indx].size = (unsigned long)*ireg++ << 32;
++ ilen -= sizeof(uint);
++ intnodes[indx].size |= *ireg++;
++ ilen -= sizeof(uint);
++ indx++;
++ if (indx >= NR_CPUS) break;
++ }
++
++ np = of_find_node_by_type(np, "PowerPC-External-Interrupt-Presentation");
++ if ((indx < NR_CPUS) && np) goto nextnode;
++
++ /* Find the server numbers for the boot cpu. */
++ for (np = of_find_node_by_type(NULL, "cpu");
++ np;
++ np = of_find_node_by_type(np, "cpu")) {
++ ireg = (uint *)get_property(np, "reg", &ilen);
++ if (ireg && ireg[0] == boot_cpuid_phys) {
++ ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s",
++ &ilen);
++ i = ilen / sizeof(int);
++ if (ireg && i > 0) {
++ default_server = ireg[0];
++ default_distrib_server = ireg[i-1]; /* take last element */
++ }
++ ireg = (uint *)get_property(np,
++ "ibm,interrupt-server#-size", NULL);
++ if (ireg)
++ interrupt_server_size = *ireg;
++ break;
++ }
++ }
++ of_node_put(np);
++
++ intr_base = intnodes[0].addr;
++ intr_size = intnodes[0].size;
++
++ np = of_find_node_by_type(NULL, "interrupt-controller");
++ if (!np) {
++ printk(KERN_WARNING "xics: no ISA interrupt controller\n");
++ xics_irq_8259_cascade_real = -1;
++ xics_irq_8259_cascade = -1;
++ } else {
++ ireg = (uint *) get_property(np, "interrupts", NULL);
++ if (!ireg)
++ panic("xics_init_IRQ: can't find ISA interrupts property");
++
++ xics_irq_8259_cascade_real = *ireg;
++ xics_irq_8259_cascade
++ = virt_irq_create_mapping(xics_irq_8259_cascade_real);
++ of_node_put(np);
++ }
++
++ if (systemcfg->platform == PLATFORM_PSERIES) {
++#ifdef CONFIG_SMP
++ for_each_cpu(i) {
++ int hard_id;
++
++ /* FIXME: Do this dynamically! --RR */
++ if (!cpu_present(i))
++ continue;
++
++ hard_id = get_hard_smp_processor_id(i);
++ xics_per_cpu[i] = ioremap(intnodes[hard_id].addr,
++ intnodes[hard_id].size);
++ }
++#else
++ xics_per_cpu[0] = ioremap(intr_base, intr_size);
++#endif /* CONFIG_SMP */
++ } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
++ ops = &pSeriesLP_ops;
++ }
++
++ xics_8259_pic.enable = i8259_pic.enable;
++ xics_8259_pic.disable = i8259_pic.disable;
++ for (i = 0; i < 16; ++i)
++ get_irq_desc(i)->handler = &xics_8259_pic;
++ for (; i < NR_IRQS; ++i)
++ get_irq_desc(i)->handler = &xics_pic;
++
++ xics_setup_cpu();
++
++ ppc64_boot_msg(0x21, "XICS Done");
++}
++
++/*
++ * We cant do this in init_IRQ because we need the memory subsystem up for
++ * request_irq()
++ */
++static int __init xics_setup_i8259(void)
++{
++ if (ppc64_interrupt_controller == IC_PPC_XIC &&
++ xics_irq_8259_cascade != -1) {
++ if (request_irq(irq_offset_up(xics_irq_8259_cascade),
++ no_action, 0, "8259 cascade", NULL))
++ printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
++ "cascade\n");
++ i8259_init(0, 0);
++ }
++ return 0;
++}
++arch_initcall(xics_setup_i8259);
++
++#ifdef CONFIG_SMP
++void xics_request_IPIs(void)
++{
++ virt_irq_to_real_map[XICS_IPI] = XICS_IPI;
++
++ /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
++ request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, SA_INTERRUPT,
++ "IPI", NULL);
++ get_irq_desc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU;
++}
++#endif
++
++static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
++{
++ unsigned int irq;
++ int status;
++ int xics_status[2];
++ unsigned long newmask;
++ cpumask_t tmp = CPU_MASK_NONE;
++
++ irq = virt_irq_to_real(irq_offset_down(virq));
++ if (irq == XICS_IPI || irq == NO_IRQ)
++ return;
++
++ status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
++
++ if (status) {
++ printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
++ "returns %d\n", irq, status);
++ return;
++ }
++
++ /* For the moment only implement delivery to all cpus or one cpu */
++ if (cpus_equal(cpumask, CPU_MASK_ALL)) {
++ newmask = default_distrib_server;
++ } else {
++ cpus_and(tmp, cpu_online_map, cpumask);
++ if (cpus_empty(tmp))
++ return;
++ newmask = get_hard_smp_processor_id(first_cpu(tmp));
++ }
++
++ status = rtas_call(ibm_set_xive, 3, 1, NULL,
++ irq, newmask, xics_status[1]);
++
++ if (status) {
++ printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
++ "returns %d\n", irq, status);
++ return;
++ }
++}
++
++void xics_teardown_cpu(int secondary)
++{
++ int cpu = smp_processor_id();
++
++ ops->cppr_info(cpu, 0x00);
++ iosync();
++
++ /*
++ * Some machines need to have at least one cpu in the GIQ,
++ * so leave the master cpu in the group.
++ */
++ if (secondary) {
++ /*
++ * we need to EOI the IPI if we got here from kexec down IPI
++ *
++ * probably need to check all the other interrupts too
++ * should we be flagging idle loop instead?
++ * or creating some task to be scheduled?
++ */
++ ops->xirr_info_set(cpu, XICS_IPI);
++ rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
++ (1UL << interrupt_server_size) - 1 -
++ default_distrib_server, 0);
++ }
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++/* Interrupts are disabled. */
++void xics_migrate_irqs_away(void)
++{
++ int status;
++ unsigned int irq, virq, cpu = smp_processor_id();
++
++ /* Reject any interrupt that was queued to us... */
++ ops->cppr_info(cpu, 0);
++ iosync();
++
++ /* remove ourselves from the global interrupt queue */
++ status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
++ (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
++ WARN_ON(status < 0);
++
++ /* Allow IPIs again... */
++ ops->cppr_info(cpu, DEFAULT_PRIORITY);
++ iosync();
++
++ for_each_irq(virq) {
++ irq_desc_t *desc;
++ int xics_status[2];
++ unsigned long flags;
++
++ /* We cant set affinity on ISA interrupts */
++ if (virq < irq_offset_value())
++ continue;
++
++ desc = get_irq_desc(virq);
++ irq = virt_irq_to_real(irq_offset_down(virq));
++
++ /* We need to get IPIs still. */
++ if (irq == XICS_IPI || irq == NO_IRQ)
++ continue;
++
++ /* We only need to migrate enabled IRQS */
++ if (desc == NULL || desc->handler == NULL
++ || desc->action == NULL
++ || desc->handler->set_affinity == NULL)
++ continue;
++
++ spin_lock_irqsave(&desc->lock, flags);
++
++ status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
++ if (status) {
++ printk(KERN_ERR "migrate_irqs_away: irq=%u "
++ "ibm,get-xive returns %d\n",
++ virq, status);
++ goto unlock;
++ }
++
++ /*
++ * We only support delivery to all cpus or to one cpu.
++ * The irq has to be migrated only in the single cpu
++ * case.
++ */
++ if (xics_status[0] != get_hard_smp_processor_id(cpu))
++ goto unlock;
++
++ printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
++ virq, cpu);
++
++ /* Reset affinity to all cpus */
++ desc->handler->set_affinity(virq, CPU_MASK_ALL);
++ irq_affinity[virq] = CPU_MASK_ALL;
++unlock:
++ spin_unlock_irqrestore(&desc->lock, flags);
++ }
++}
++#endif
+diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/xics.h
+@@ -0,0 +1,34 @@
++/*
++ * arch/powerpc/platforms/pseries/xics.h
++ *
++ * Copyright 2000 IBM Corporation.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#ifndef _POWERPC_KERNEL_XICS_H
++#define _POWERPC_KERNEL_XICS_H
++
++#include <linux/cache.h>
++
++void xics_init_IRQ(void);
++int xics_get_irq(struct pt_regs *);
++void xics_setup_cpu(void);
++void xics_teardown_cpu(int secondary);
++void xics_cause_IPI(int cpu);
++void xics_request_IPIs(void);
++void xics_migrate_irqs_away(void);
++
++/* first argument is ignored for now*/
++void pSeriesLP_cppr_info(int n_cpu, u8 value);
++
++struct xics_ipi_struct {
++ volatile unsigned long value;
++} ____cacheline_aligned;
++
++extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
++
++#endif /* _POWERPC_KERNEL_XICS_H */
+diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/sysdev/Makefile
+@@ -0,0 +1,7 @@
++obj-$(CONFIG_MPIC) += mpic.o
++obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
++obj-$(CONFIG_PPC_I8259) += i8259.o
++obj-$(CONFIG_PPC_MPC106) += grackle.o
++obj-$(CONFIG_BOOKE) += dcr.o
++obj-$(CONFIG_40x) += dcr.o
++obj-$(CONFIG_U3_DART) += u3_iommu.o
+diff --git a/arch/powerpc/sysdev/dcr.S b/arch/powerpc/sysdev/dcr.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/sysdev/dcr.S
+@@ -0,0 +1,41 @@
++/*
++ * arch/ppc/syslib/dcr.S
++ *
++ * "Indirect" DCR access
++ *
++ * Copyright (c) 2004 Eugene Surovegin <ebs at 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 <asm/ppc_asm.h>
++#include <asm/processor.h>
++
++#define DCR_ACCESS_PROLOG(table) \
++ rlwinm r3,r3,4,18,27; \
++ lis r5,table at h; \
++ ori r5,r5,table at l; \
++ add r3,r3,r5; \
++ mtctr r3; \
++ bctr
++
++_GLOBAL(__mfdcr)
++ DCR_ACCESS_PROLOG(__mfdcr_table)
++
++_GLOBAL(__mtdcr)
++ DCR_ACCESS_PROLOG(__mtdcr_table)
++
++__mfdcr_table:
++ mfdcr r3,0; blr
++__mtdcr_table:
++ mtdcr 0,r4; blr
++
++dcr = 1
++ .rept 1023
++ mfdcr r3,dcr; blr
++ mtdcr dcr,r4; blr
++ dcr = dcr + 1
++ .endr
+diff --git a/arch/powerpc/sysdev/grackle.c b/arch/powerpc/sysdev/grackle.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/sysdev/grackle.c
+@@ -0,0 +1,64 @@
++/*
++ * Functions for setting up and using a MPC106 northbridge
++ * Extracted from arch/powerpc/platforms/powermac/pci.c.
++ *
++ * Copyright (C) 2003 Benjamin Herrenschmuidt (benh at kernel.crashing.org)
++ * Copyright (C) 1997 Paul Mackerras (paulus at samba.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/kernel.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/grackle.h>
++
++#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
++ | (((o) & ~3) << 24))
++
++#define GRACKLE_PICR1_STG 0x00000040
++#define GRACKLE_PICR1_LOOPSNOOP 0x00000010
++
++/* N.B. this is called before bridges is initialized, so we can't
++ use grackle_pcibios_{read,write}_config_dword. */
++static inline void grackle_set_stg(struct pci_controller* bp, int enable)
++{
++ unsigned int val;
++
++ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
++ val = in_le32(bp->cfg_data);
++ val = enable? (val | GRACKLE_PICR1_STG) :
++ (val & ~GRACKLE_PICR1_STG);
++ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
++ out_le32(bp->cfg_data, val);
++ (void)in_le32(bp->cfg_data);
++}
++
++static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
++{
++ unsigned int val;
++
++ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
++ val = in_le32(bp->cfg_data);
++ val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
++ (val & ~GRACKLE_PICR1_LOOPSNOOP);
++ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
++ out_le32(bp->cfg_data, val);
++ (void)in_le32(bp->cfg_data);
++}
++
++void __init setup_grackle(struct pci_controller *hose)
++{
++ setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
++ if (machine_is_compatible("AAPL,PowerBook1998"))
++ grackle_set_loop_snoop(hose, 1);
++#if 0 /* Disabled for now, HW problems ??? */
++ grackle_set_stg(hose, 1);
++#endif
++}
+diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/sysdev/i8259.c
+@@ -0,0 +1,221 @@
++/*
++ * i8259 interrupt controller driver.
++ *
++ * 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/ioport.h>
++#include <linux/interrupt.h>
++#include <asm/io.h>
++#include <asm/i8259.h>
++
++static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */
++
++static unsigned char cached_8259[2] = { 0xff, 0xff };
++#define cached_A1 (cached_8259[0])
++#define cached_21 (cached_8259[1])
++
++static DEFINE_SPINLOCK(i8259_lock);
++
++static int i8259_pic_irq_offset;
++
++/*
++ * Acknowledge the IRQ using either the PCI host bridge's interrupt
++ * acknowledge feature or poll. How i8259_init() is called determines
++ * which is called. It should be noted that polling is broken on some
++ * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
++ */
++int i8259_irq(struct pt_regs *regs)
++{
++ int irq;
++
++ spin_lock(&i8259_lock);
++
++ /* Either int-ack or poll for the IRQ */
++ if (pci_intack)
++ irq = readb(pci_intack);
++ else {
++ /* Perform an interrupt acknowledge cycle on controller 1. */
++ outb(0x0C, 0x20); /* prepare for poll */
++ irq = inb(0x20) & 7;
++ if (irq == 2 ) {
++ /*
++ * Interrupt is cascaded so perform interrupt
++ * acknowledge on controller 2.
++ */
++ outb(0x0C, 0xA0); /* prepare for poll */
++ irq = (inb(0xA0) & 7) + 8;
++ }
++ }
++
++ if (irq == 7) {
++ /*
++ * This may be a spurious interrupt.
++ *
++ * Read the interrupt status register (ISR). If the most
++ * significant bit is not set then there is no valid
++ * interrupt.
++ */
++ if (!pci_intack)
++ outb(0x0B, 0x20); /* ISR register */
++ if(~inb(0x20) & 0x80)
++ irq = -1;
++ }
++
++ spin_unlock(&i8259_lock);
++ return irq + i8259_pic_irq_offset;
++}
++
++int i8259_irq_cascade(struct pt_regs *regs, void *unused)
++{
++ return i8259_irq(regs);
++}
++
++static void i8259_mask_and_ack_irq(unsigned int irq_nr)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&i8259_lock, flags);
++ irq_nr -= i8259_pic_irq_offset;
++ if (irq_nr > 7) {
++ cached_A1 |= 1 << (irq_nr-8);
++ inb(0xA1); /* DUMMY */
++ outb(cached_A1, 0xA1);
++ outb(0x20, 0xA0); /* Non-specific EOI */
++ outb(0x20, 0x20); /* Non-specific EOI to cascade */
++ } else {
++ cached_21 |= 1 << irq_nr;
++ inb(0x21); /* DUMMY */
++ outb(cached_21, 0x21);
++ outb(0x20, 0x20); /* Non-specific EOI */
++ }
++ spin_unlock_irqrestore(&i8259_lock, flags);
++}
++
++static void i8259_set_irq_mask(int irq_nr)
++{
++ outb(cached_A1,0xA1);
++ outb(cached_21,0x21);
++}
++
++static void i8259_mask_irq(unsigned int irq_nr)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&i8259_lock, flags);
++ irq_nr -= i8259_pic_irq_offset;
++ if (irq_nr < 8)
++ cached_21 |= 1 << irq_nr;
++ else
++ cached_A1 |= 1 << (irq_nr-8);
++ i8259_set_irq_mask(irq_nr);
++ spin_unlock_irqrestore(&i8259_lock, flags);
++}
++
++static void i8259_unmask_irq(unsigned int irq_nr)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&i8259_lock, flags);
++ irq_nr -= i8259_pic_irq_offset;
++ if (irq_nr < 8)
++ cached_21 &= ~(1 << irq_nr);
++ else
++ cached_A1 &= ~(1 << (irq_nr-8));
++ i8259_set_irq_mask(irq_nr);
++ spin_unlock_irqrestore(&i8259_lock, flags);
++}
++
++static void i8259_end_irq(unsigned int irq)
++{
++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))
++ && irq_desc[irq].action)
++ i8259_unmask_irq(irq);
++}
++
++struct hw_interrupt_type i8259_pic = {
++ .typename = " i8259 ",
++ .enable = i8259_unmask_irq,
++ .disable = i8259_mask_irq,
++ .ack = i8259_mask_and_ack_irq,
++ .end = i8259_end_irq,
++};
++
++static struct resource pic1_iores = {
++ .name = "8259 (master)",
++ .start = 0x20,
++ .end = 0x21,
++ .flags = IORESOURCE_BUSY,
++};
++
++static struct resource pic2_iores = {
++ .name = "8259 (slave)",
++ .start = 0xa0,
++ .end = 0xa1,
++ .flags = IORESOURCE_BUSY,
++};
++
++static struct resource pic_edgectrl_iores = {
++ .name = "8259 edge control",
++ .start = 0x4d0,
++ .end = 0x4d1,
++ .flags = IORESOURCE_BUSY,
++};
++
++static struct irqaction i8259_irqaction = {
++ .handler = no_action,
++ .flags = SA_INTERRUPT,
++ .mask = CPU_MASK_NONE,
++ .name = "82c59 secondary cascade",
++};
++
++/*
++ * i8259_init()
++ * intack_addr - PCI interrupt acknowledge (real) address which will return
++ * the active irq from the 8259
++ */
++void __init i8259_init(unsigned long intack_addr, int offset)
++{
++ unsigned long flags;
++ int i;
++
++ spin_lock_irqsave(&i8259_lock, flags);
++ i8259_pic_irq_offset = offset;
++
++ /* init master interrupt controller */
++ outb(0x11, 0x20); /* Start init sequence */
++ outb(0x00, 0x21); /* Vector base */
++ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
++ outb(0x01, 0x21); /* Select 8086 mode */
++
++ /* init slave interrupt controller */
++ outb(0x11, 0xA0); /* Start init sequence */
++ outb(0x08, 0xA1); /* Vector base */
++ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
++ outb(0x01, 0xA1); /* Select 8086 mode */
++
++ /* always read ISR */
++ outb(0x0B, 0x20);
++ outb(0x0B, 0xA0);
++
++ /* Mask all interrupts */
++ outb(cached_A1, 0xA1);
++ outb(cached_21, 0x21);
++
++ spin_unlock_irqrestore(&i8259_lock, flags);
++
++ /* reserve our resources */
++ setup_irq(offset + 2, &i8259_irqaction);
++ request_resource(&ioport_resource, &pic1_iores);
++ request_resource(&ioport_resource, &pic2_iores);
++ request_resource(&ioport_resource, &pic_edgectrl_iores);
++
++ if (intack_addr != 0)
++ pci_intack = ioremap(intack_addr, 1);
++
++ for (i = 0; i < NUM_ISA_INTERRUPTS; ++i)
++ irq_desc[offset + i].handler = &i8259_pic;
++}
+diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/sysdev/indirect_pci.c
+@@ -0,0 +1,134 @@
++/*
++ * Support for indirect PCI bridges.
++ *
++ * Copyright (C) 1998 Gabriel Paubert.
++ *
++ * 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/kernel.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/init.h>
++
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/machdep.h>
++
++#ifdef CONFIG_PPC_INDIRECT_PCI_BE
++#define PCI_CFG_OUT out_be32
++#else
++#define PCI_CFG_OUT out_le32
++#endif
++
++static int
++indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
++ int len, u32 *val)
++{
++ struct pci_controller *hose = bus->sysdata;
++ volatile void __iomem *cfg_data;
++ u8 cfg_type = 0;
++
++ if (ppc_md.pci_exclude_device)
++ if (ppc_md.pci_exclude_device(bus->number, devfn))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (hose->set_cfg_type)
++ if (bus->number != hose->first_busno)
++ cfg_type = 1;
++
++ PCI_CFG_OUT(hose->cfg_addr,
++ (0x80000000 | ((bus->number - hose->bus_offset) << 16)
++ | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
++
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ cfg_data = hose->cfg_data + (offset & 3);
++ switch (len) {
++ case 1:
++ *val = in_8(cfg_data);
++ break;
++ case 2:
++ *val = in_le16(cfg_data);
++ break;
++ default:
++ *val = in_le32(cfg_data);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int
++indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
++ int len, u32 val)
++{
++ struct pci_controller *hose = bus->sysdata;
++ volatile void __iomem *cfg_data;
++ u8 cfg_type = 0;
++
++ if (ppc_md.pci_exclude_device)
++ if (ppc_md.pci_exclude_device(bus->number, devfn))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (hose->set_cfg_type)
++ if (bus->number != hose->first_busno)
++ cfg_type = 1;
++
++ PCI_CFG_OUT(hose->cfg_addr,
++ (0x80000000 | ((bus->number - hose->bus_offset) << 16)
++ | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
++
++ /*
++ * Note: the caller has already checked that offset is
++ * suitably aligned and that len is 1, 2 or 4.
++ */
++ cfg_data = hose->cfg_data + (offset & 3);
++ switch (len) {
++ case 1:
++ out_8(cfg_data, val);
++ break;
++ case 2:
++ out_le16(cfg_data, val);
++ break;
++ default:
++ out_le32(cfg_data, val);
++ break;
++ }
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops indirect_pci_ops =
++{
++ indirect_read_config,
++ indirect_write_config
++};
++
++void __init
++setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
++ void __iomem * cfg_data)
++{
++ hose->cfg_addr = cfg_addr;
++ hose->cfg_data = cfg_data;
++ hose->ops = &indirect_pci_ops;
++}
++
++void __init
++setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
++{
++ unsigned long base = cfg_addr & PAGE_MASK;
++ void __iomem *mbase, *addr, *data;
++
++ mbase = ioremap(base, PAGE_SIZE);
++ addr = mbase + (cfg_addr & ~PAGE_MASK);
++ if ((cfg_data & PAGE_MASK) != base)
++ mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
++ data = mbase + (cfg_data & ~PAGE_MASK);
++ setup_indirect_pci_nomap(hose, addr, data);
++}
+diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/sysdev/mpic.c
+@@ -0,0 +1,927 @@
++/*
++ * arch/powerpc/kernel/mpic.c
++ *
++ * Driver for interrupt controllers following the OpenPIC standard, the
++ * common implementation beeing IBM's MPIC. This driver also can deal
++ * with various broken implementations of this HW.
++ *
++ * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
++ *
++ * 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.
++ */
++
++#undef DEBUG
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/smp.h>
++#include <linux/interrupt.h>
++#include <linux/bootmem.h>
++#include <linux/spinlock.h>
++#include <linux/pci.h>
++
++#include <asm/ptrace.h>
++#include <asm/signal.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/irq.h>
++#include <asm/machdep.h>
++#include <asm/mpic.h>
++#include <asm/smp.h>
++
++#ifdef DEBUG
++#define DBG(fmt...) printk(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++static struct mpic *mpics;
++static struct mpic *mpic_primary;
++static DEFINE_SPINLOCK(mpic_lock);
++
++#ifdef CONFIG_PPC32 /* XXX for now */
++#define distribute_irqs CONFIG_IRQ_ALL_CPUS
++#endif
++
++/*
++ * Register accessor functions
++ */
++
++
++static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base,
++ unsigned int reg)
++{
++ if (be)
++ return in_be32(base + (reg >> 2));
++ else
++ return in_le32(base + (reg >> 2));
++}
++
++static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
++ unsigned int reg, u32 value)
++{
++ if (be)
++ out_be32(base + (reg >> 2), value);
++ else
++ out_le32(base + (reg >> 2), value);
++}
++
++static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
++{
++ unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
++ unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
++
++ if (mpic->flags & MPIC_BROKEN_IPI)
++ be = !be;
++ return _mpic_read(be, mpic->gregs, offset);
++}
++
++static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
++{
++ unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
++
++ _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
++}
++
++static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
++{
++ unsigned int cpu = 0;
++
++ if (mpic->flags & MPIC_PRIMARY)
++ cpu = hard_smp_processor_id();
++
++ return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg);
++}
++
++static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
++{
++ unsigned int cpu = 0;
++
++ if (mpic->flags & MPIC_PRIMARY)
++ cpu = hard_smp_processor_id();
++
++ _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value);
++}
++
++static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg)
++{
++ unsigned int isu = src_no >> mpic->isu_shift;
++ unsigned int idx = src_no & mpic->isu_mask;
++
++ return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
++ reg + (idx * MPIC_IRQ_STRIDE));
++}
++
++static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
++ unsigned int reg, u32 value)
++{
++ unsigned int isu = src_no >> mpic->isu_shift;
++ unsigned int idx = src_no & mpic->isu_mask;
++
++ _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
++ reg + (idx * MPIC_IRQ_STRIDE), value);
++}
++
++#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
++#define mpic_write(b,r,v) _mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v))
++#define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i))
++#define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v))
++#define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i))
++#define mpic_cpu_write(i,v) _mpic_cpu_write(mpic,(i),(v))
++#define mpic_irq_read(s,r) _mpic_irq_read(mpic,(s),(r))
++#define mpic_irq_write(s,r,v) _mpic_irq_write(mpic,(s),(r),(v))
++
++
++/*
++ * Low level utility functions
++ */
++
++
++
++/* Check if we have one of those nice broken MPICs with a flipped endian on
++ * reads from IPI registers
++ */
++static void __init mpic_test_broken_ipi(struct mpic *mpic)
++{
++ u32 r;
++
++ mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
++ r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
++
++ if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
++ printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
++ mpic->flags |= MPIC_BROKEN_IPI;
++ }
++}
++
++#ifdef CONFIG_MPIC_BROKEN_U3
++
++/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
++ * to force the edge setting on the MPIC and do the ack workaround.
++ */
++static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no)
++{
++ if (source_no >= 128 || !mpic->fixups)
++ return 0;
++ return mpic->fixups[source_no].base != NULL;
++}
++
++static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
++{
++ struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
++ u32 tmp;
++
++ spin_lock(&mpic->fixup_lock);
++ writeb(0x11 + 2 * fixup->irq, fixup->base);
++ tmp = readl(fixup->base + 2);
++ writel(tmp | 0x80000000ul, fixup->base + 2);
++ /* config writes shouldn't be posted but let's be safe ... */
++ (void)readl(fixup->base + 2);
++ spin_unlock(&mpic->fixup_lock);
++}
++
++
++static void __init mpic_amd8111_read_irq(struct mpic *mpic, u8 __iomem *devbase)
++{
++ int i, irq;
++ u32 tmp;
++
++ printk(KERN_INFO "mpic: - Workarounds on AMD 8111 @ %p\n", devbase);
++
++ for (i=0; i < 24; i++) {
++ writeb(0x10 + 2*i, devbase + 0xf2);
++ tmp = readl(devbase + 0xf4);
++ if ((tmp & 0x1) || !(tmp & 0x20))
++ continue;
++ irq = (tmp >> 16) & 0xff;
++ mpic->fixups[irq].irq = i;
++ mpic->fixups[irq].base = devbase + 0xf2;
++ }
++}
++
++static void __init mpic_amd8131_read_irq(struct mpic *mpic, u8 __iomem *devbase)
++{
++ int i, irq;
++ u32 tmp;
++
++ printk(KERN_INFO "mpic: - Workarounds on AMD 8131 @ %p\n", devbase);
++
++ for (i=0; i < 4; i++) {
++ writeb(0x10 + 2*i, devbase + 0xba);
++ tmp = readl(devbase + 0xbc);
++ if ((tmp & 0x1) || !(tmp & 0x20))
++ continue;
++ irq = (tmp >> 16) & 0xff;
++ mpic->fixups[irq].irq = i;
++ mpic->fixups[irq].base = devbase + 0xba;
++ }
++}
++
++static void __init mpic_scan_ioapics(struct mpic *mpic)
++{
++ unsigned int devfn;
++ u8 __iomem *cfgspace;
++
++ printk(KERN_INFO "mpic: Setting up IO-APICs workarounds for U3\n");
++
++ /* Allocate fixups array */
++ mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
++ BUG_ON(mpic->fixups == NULL);
++ memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
++
++ /* Init spinlock */
++ spin_lock_init(&mpic->fixup_lock);
++
++ /* Map u3 config space. We assume all IO-APICs are on the primary bus
++ * and slot will never be above "0xf" so we only need to map 32k
++ */
++ cfgspace = (unsigned char __iomem *)ioremap(0xf2000000, 0x8000);
++ BUG_ON(cfgspace == NULL);
++
++ /* Now we scan all slots. We do a very quick scan, we read the header type,
++ * vendor ID and device ID only, that's plenty enough
++ */
++ for (devfn = 0; devfn < PCI_DEVFN(0x10,0); devfn ++) {
++ u8 __iomem *devbase = cfgspace + (devfn << 8);
++ u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
++ u32 l = readl(devbase + PCI_VENDOR_ID);
++ u16 vendor_id, device_id;
++ int multifunc = 0;
++
++ DBG("devfn %x, l: %x\n", devfn, l);
++
++ /* If no device, skip */
++ if (l == 0xffffffff || l == 0x00000000 ||
++ l == 0x0000ffff || l == 0xffff0000)
++ goto next;
++
++ /* Check if it's a multifunction device (only really used
++ * to function 0 though
++ */
++ multifunc = !!(hdr_type & 0x80);
++ vendor_id = l & 0xffff;
++ device_id = (l >> 16) & 0xffff;
++
++ /* If a known device, go to fixup setup code */
++ if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7460)
++ mpic_amd8111_read_irq(mpic, devbase);
++ if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7450)
++ mpic_amd8131_read_irq(mpic, devbase);
++ next:
++ /* next device, if function 0 */
++ if ((PCI_FUNC(devfn) == 0) && !multifunc)
++ devfn += 7;
++ }
++}
++
++#endif /* CONFIG_MPIC_BROKEN_U3 */
++
++
++/* Find an mpic associated with a given linux interrupt */
++static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
++{
++ struct mpic *mpic = mpics;
++
++ while(mpic) {
++ /* search IPIs first since they may override the main interrupts */
++ if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) {
++ if (is_ipi)
++ *is_ipi = 1;
++ return mpic;
++ }
++ if (irq >= mpic->irq_offset &&
++ irq < (mpic->irq_offset + mpic->irq_count)) {
++ if (is_ipi)
++ *is_ipi = 0;
++ return mpic;
++ }
++ mpic = mpic -> next;
++ }
++ return NULL;
++}
++
++/* Convert a cpu mask from logical to physical cpu numbers. */
++static inline u32 mpic_physmask(u32 cpumask)
++{
++ int i;
++ u32 mask = 0;
++
++ for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
++ mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
++ return mask;
++}
++
++#ifdef CONFIG_SMP
++/* Get the mpic structure from the IPI number */
++static inline struct mpic * mpic_from_ipi(unsigned int ipi)
++{
++ return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi);
++}
++#endif
++
++/* Get the mpic structure from the irq number */
++static inline struct mpic * mpic_from_irq(unsigned int irq)
++{
++ return container_of(irq_desc[irq].handler, struct mpic, hc_irq);
++}
++
++/* Send an EOI */
++static inline void mpic_eoi(struct mpic *mpic)
++{
++ mpic_cpu_write(MPIC_CPU_EOI, 0);
++ (void)mpic_cpu_read(MPIC_CPU_WHOAMI);
++}
++
++#ifdef CONFIG_SMP
++static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct mpic *mpic = dev_id;
++
++ smp_message_recv(irq - mpic->ipi_offset, regs);
++ return IRQ_HANDLED;
++}
++#endif /* CONFIG_SMP */
++
++/*
++ * Linux descriptor level callbacks
++ */
++
++
++static void mpic_enable_irq(unsigned int irq)
++{
++ unsigned int loops = 100000;
++ struct mpic *mpic = mpic_from_irq(irq);
++ unsigned int src = irq - mpic->irq_offset;
++
++ DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
++
++ mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
++ mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & ~MPIC_VECPRI_MASK);
++
++ /* make sure mask gets to controller before we return to user */
++ do {
++ if (!loops--) {
++ printk(KERN_ERR "mpic_enable_irq timeout\n");
++ break;
++ }
++ } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
++}
++
++static void mpic_disable_irq(unsigned int irq)
++{
++ unsigned int loops = 100000;
++ struct mpic *mpic = mpic_from_irq(irq);
++ unsigned int src = irq - mpic->irq_offset;
++
++ DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
++
++ mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
++ mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | MPIC_VECPRI_MASK);
++
++ /* make sure mask gets to controller before we return to user */
++ do {
++ if (!loops--) {
++ printk(KERN_ERR "mpic_enable_irq timeout\n");
++ break;
++ }
++ } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
++}
++
++static void mpic_end_irq(unsigned int irq)
++{
++ struct mpic *mpic = mpic_from_irq(irq);
++
++ DBG("%s: end_irq: %d\n", mpic->name, irq);
++
++ /* We always EOI on end_irq() even for edge interrupts since that
++ * should only lower the priority, the MPIC should have properly
++ * latched another edge interrupt coming in anyway
++ */
++
++#ifdef CONFIG_MPIC_BROKEN_U3
++ if (mpic->flags & MPIC_BROKEN_U3) {
++ unsigned int src = irq - mpic->irq_offset;
++ if (mpic_is_ht_interrupt(mpic, src))
++ mpic_apic_end_irq(mpic, src);
++ }
++#endif /* CONFIG_MPIC_BROKEN_U3 */
++
++ mpic_eoi(mpic);
++}
++
++#ifdef CONFIG_SMP
++
++static void mpic_enable_ipi(unsigned int irq)
++{
++ struct mpic *mpic = mpic_from_ipi(irq);
++ unsigned int src = irq - mpic->ipi_offset;
++
++ DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
++ mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
++}
++
++static void mpic_disable_ipi(unsigned int irq)
++{
++ /* NEVER disable an IPI... that's just plain wrong! */
++}
++
++static void mpic_end_ipi(unsigned int irq)
++{
++ struct mpic *mpic = mpic_from_ipi(irq);
++
++ /*
++ * IPIs are marked IRQ_PER_CPU. This has the side effect of
++ * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
++ * applying to them. We EOI them late to avoid re-entering.
++ * We mark IPI's with SA_INTERRUPT as they must run with
++ * irqs disabled.
++ */
++ mpic_eoi(mpic);
++}
++
++#endif /* CONFIG_SMP */
++
++static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
++{
++ struct mpic *mpic = mpic_from_irq(irq);
++
++ cpumask_t tmp;
++
++ cpus_and(tmp, cpumask, cpu_online_map);
++
++ mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
++ mpic_physmask(cpus_addr(tmp)[0]));
++}
++
++
++/*
++ * Exported functions
++ */
++
++
++struct mpic * __init mpic_alloc(unsigned long phys_addr,
++ unsigned int flags,
++ unsigned int isu_size,
++ unsigned int irq_offset,
++ unsigned int irq_count,
++ unsigned int ipi_offset,
++ unsigned char *senses,
++ unsigned int senses_count,
++ const char *name)
++{
++ struct mpic *mpic;
++ u32 reg;
++ const char *vers;
++ int i;
++
++ mpic = alloc_bootmem(sizeof(struct mpic));
++ if (mpic == NULL)
++ return NULL;
++
++
++ memset(mpic, 0, sizeof(struct mpic));
++ mpic->name = name;
++
++ mpic->hc_irq.typename = name;
++ mpic->hc_irq.enable = mpic_enable_irq;
++ mpic->hc_irq.disable = mpic_disable_irq;
++ mpic->hc_irq.end = mpic_end_irq;
++ if (flags & MPIC_PRIMARY)
++ mpic->hc_irq.set_affinity = mpic_set_affinity;
++#ifdef CONFIG_SMP
++ mpic->hc_ipi.typename = name;
++ mpic->hc_ipi.enable = mpic_enable_ipi;
++ mpic->hc_ipi.disable = mpic_disable_ipi;
++ mpic->hc_ipi.end = mpic_end_ipi;
++#endif /* CONFIG_SMP */
++
++ mpic->flags = flags;
++ mpic->isu_size = isu_size;
++ mpic->irq_offset = irq_offset;
++ mpic->irq_count = irq_count;
++ mpic->ipi_offset = ipi_offset;
++ mpic->num_sources = 0; /* so far */
++ mpic->senses = senses;
++ mpic->senses_count = senses_count;
++
++ /* Map the global registers */
++ mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
++ mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
++ BUG_ON(mpic->gregs == NULL);
++
++ /* Reset */
++ if (flags & MPIC_WANTS_RESET) {
++ mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
++ mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
++ | MPIC_GREG_GCONF_RESET);
++ while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
++ & MPIC_GREG_GCONF_RESET)
++ mb();
++ }
++
++ /* Read feature register, calculate num CPUs and, for non-ISU
++ * MPICs, num sources as well. On ISU MPICs, sources are counted
++ * as ISUs are added
++ */
++ reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
++ mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
++ >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
++ if (isu_size == 0)
++ mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
++ >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
++
++ /* Map the per-CPU registers */
++ for (i = 0; i < mpic->num_cpus; i++) {
++ mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
++ i * MPIC_CPU_STRIDE, 0x1000);
++ BUG_ON(mpic->cpuregs[i] == NULL);
++ }
++
++ /* Initialize main ISU if none provided */
++ if (mpic->isu_size == 0) {
++ mpic->isu_size = mpic->num_sources;
++ mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
++ MPIC_IRQ_STRIDE * mpic->isu_size);
++ BUG_ON(mpic->isus[0] == NULL);
++ }
++ mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
++ mpic->isu_mask = (1 << mpic->isu_shift) - 1;
++
++ /* Display version */
++ switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
++ case 1:
++ vers = "1.0";
++ break;
++ case 2:
++ vers = "1.2";
++ break;
++ case 3:
++ vers = "1.3";
++ break;
++ default:
++ vers = "<unknown>";
++ break;
++ }
++ printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n",
++ name, vers, phys_addr, mpic->num_cpus);
++ printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size,
++ mpic->isu_shift, mpic->isu_mask);
++
++ mpic->next = mpics;
++ mpics = mpic;
++
++ if (flags & MPIC_PRIMARY)
++ mpic_primary = mpic;
++
++ return mpic;
++}
++
++void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
++ unsigned long phys_addr)
++{
++ unsigned int isu_first = isu_num * mpic->isu_size;
++
++ BUG_ON(isu_num >= MPIC_MAX_ISU);
++
++ mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
++ if ((isu_first + mpic->isu_size) > mpic->num_sources)
++ mpic->num_sources = isu_first + mpic->isu_size;
++}
++
++void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
++ void *data)
++{
++ struct mpic *mpic = mpic_find(irq, NULL);
++ unsigned long flags;
++
++ /* Synchronization here is a bit dodgy, so don't try to replace cascade
++ * interrupts on the fly too often ... but normally it's set up at boot.
++ */
++ spin_lock_irqsave(&mpic_lock, flags);
++ if (mpic->cascade)
++ mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
++ mpic->cascade = NULL;
++ wmb();
++ mpic->cascade_vec = irq - mpic->irq_offset;
++ mpic->cascade_data = data;
++ wmb();
++ mpic->cascade = handler;
++ mpic_enable_irq(irq);
++ spin_unlock_irqrestore(&mpic_lock, flags);
++}
++
++void __init mpic_init(struct mpic *mpic)
++{
++ int i;
++
++ BUG_ON(mpic->num_sources == 0);
++
++ printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
++
++ /* Set current processor priority to max */
++ mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
++
++ /* Initialize timers: just disable them all */
++ for (i = 0; i < 4; i++) {
++ mpic_write(mpic->tmregs,
++ i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
++ mpic_write(mpic->tmregs,
++ i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
++ MPIC_VECPRI_MASK |
++ (MPIC_VEC_TIMER_0 + i));
++ }
++
++ /* Initialize IPIs to our reserved vectors and mark them disabled for now */
++ mpic_test_broken_ipi(mpic);
++ for (i = 0; i < 4; i++) {
++ mpic_ipi_write(i,
++ MPIC_VECPRI_MASK |
++ (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
++ (MPIC_VEC_IPI_0 + i));
++#ifdef CONFIG_SMP
++ if (!(mpic->flags & MPIC_PRIMARY))
++ continue;
++ irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
++ irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi;
++#endif /* CONFIG_SMP */
++ }
++
++ /* Initialize interrupt sources */
++ if (mpic->irq_count == 0)
++ mpic->irq_count = mpic->num_sources;
++
++#ifdef CONFIG_MPIC_BROKEN_U3
++ /* Do the ioapic fixups on U3 broken mpic */
++ DBG("MPIC flags: %x\n", mpic->flags);
++ if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
++ mpic_scan_ioapics(mpic);
++#endif /* CONFIG_MPIC_BROKEN_U3 */
++
++ for (i = 0; i < mpic->num_sources; i++) {
++ /* start with vector = source number, and masked */
++ u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
++ int level = 0;
++
++ /* if it's an IPI, we skip it */
++ if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
++ (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4))
++ continue;
++
++ /* do senses munging */
++ if (mpic->senses && i < mpic->senses_count) {
++ if (mpic->senses[i] & IRQ_SENSE_LEVEL)
++ vecpri |= MPIC_VECPRI_SENSE_LEVEL;
++ if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
++ vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
++ } else
++ vecpri |= MPIC_VECPRI_SENSE_LEVEL;
++
++ /* remember if it was a level interrupts */
++ level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
++
++ /* deal with broken U3 */
++ if (mpic->flags & MPIC_BROKEN_U3) {
++#ifdef CONFIG_MPIC_BROKEN_U3
++ if (mpic_is_ht_interrupt(mpic, i)) {
++ vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
++ MPIC_VECPRI_POLARITY_MASK);
++ vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
++ }
++#else
++ printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n");
++#endif
++ }
++
++ DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
++ (level != 0));
++
++ /* init hw */
++ mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
++ mpic_irq_write(i, MPIC_IRQ_DESTINATION,
++ 1 << hard_smp_processor_id());
++
++ /* init linux descriptors */
++ if (i < mpic->irq_count) {
++ irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0;
++ irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq;
++ }
++ }
++
++ /* Init spurrious vector */
++ mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
++
++ /* Disable 8259 passthrough */
++ mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
++ mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
++ | MPIC_GREG_GCONF_8259_PTHROU_DIS);
++
++ /* Set current processor priority to 0 */
++ mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
++}
++
++
++
++void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
++{
++ int is_ipi;
++ struct mpic *mpic = mpic_find(irq, &is_ipi);
++ unsigned long flags;
++ u32 reg;
++
++ spin_lock_irqsave(&mpic_lock, flags);
++ if (is_ipi) {
++ reg = mpic_ipi_read(irq - mpic->ipi_offset) & MPIC_VECPRI_PRIORITY_MASK;
++ mpic_ipi_write(irq - mpic->ipi_offset,
++ reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
++ } else {
++ reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI)
++ & MPIC_VECPRI_PRIORITY_MASK;
++ mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
++ reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
++ }
++ spin_unlock_irqrestore(&mpic_lock, flags);
++}
++
++unsigned int mpic_irq_get_priority(unsigned int irq)
++{
++ int is_ipi;
++ struct mpic *mpic = mpic_find(irq, &is_ipi);
++ unsigned long flags;
++ u32 reg;
++
++ spin_lock_irqsave(&mpic_lock, flags);
++ if (is_ipi)
++ reg = mpic_ipi_read(irq - mpic->ipi_offset);
++ else
++ reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI);
++ spin_unlock_irqrestore(&mpic_lock, flags);
++ return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
++}
++
++void mpic_setup_this_cpu(void)
++{
++#ifdef CONFIG_SMP
++ struct mpic *mpic = mpic_primary;
++ unsigned long flags;
++ u32 msk = 1 << hard_smp_processor_id();
++ unsigned int i;
++
++ BUG_ON(mpic == NULL);
++
++ DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
++
++ spin_lock_irqsave(&mpic_lock, flags);
++
++ /* let the mpic know we want intrs. default affinity is 0xffffffff
++ * until changed via /proc. That's how it's done on x86. If we want
++ * it differently, then we should make sure we also change the default
++ * values of irq_affinity in irq.c.
++ */
++ if (distribute_irqs) {
++ for (i = 0; i < mpic->num_sources ; i++)
++ mpic_irq_write(i, MPIC_IRQ_DESTINATION,
++ mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
++ }
++
++ /* Set current processor priority to 0 */
++ mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
++
++ spin_unlock_irqrestore(&mpic_lock, flags);
++#endif /* CONFIG_SMP */
++}
++
++int mpic_cpu_get_priority(void)
++{
++ struct mpic *mpic = mpic_primary;
++
++ return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
++}
++
++void mpic_cpu_set_priority(int prio)
++{
++ struct mpic *mpic = mpic_primary;
++
++ prio &= MPIC_CPU_TASKPRI_MASK;
++ mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
++}
++
++/*
++ * XXX: someone who knows mpic should check this.
++ * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
++ * or can we reset the mpic in the new kernel?
++ */
++void mpic_teardown_this_cpu(int secondary)
++{
++ struct mpic *mpic = mpic_primary;
++ unsigned long flags;
++ u32 msk = 1 << hard_smp_processor_id();
++ unsigned int i;
++
++ BUG_ON(mpic == NULL);
++
++ DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
++ spin_lock_irqsave(&mpic_lock, flags);
++
++ /* let the mpic know we don't want intrs. */
++ for (i = 0; i < mpic->num_sources ; i++)
++ mpic_irq_write(i, MPIC_IRQ_DESTINATION,
++ mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
++
++ /* Set current processor priority to max */
++ mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
++
++ spin_unlock_irqrestore(&mpic_lock, flags);
++}
++
++
++void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
++{
++ struct mpic *mpic = mpic_primary;
++
++ BUG_ON(mpic == NULL);
++
++ DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
++
++ mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
++ mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
++}
++
++int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
++{
++ u32 irq;
++
++ irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
++ DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
++
++ if (mpic->cascade && irq == mpic->cascade_vec) {
++ DBG("%s: cascading ...\n", mpic->name);
++ irq = mpic->cascade(regs, mpic->cascade_data);
++ mpic_eoi(mpic);
++ return irq;
++ }
++ if (unlikely(irq == MPIC_VEC_SPURRIOUS))
++ return -1;
++ if (irq < MPIC_VEC_IPI_0)
++ return irq + mpic->irq_offset;
++ DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
++ return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
++}
++
++int mpic_get_irq(struct pt_regs *regs)
++{
++ struct mpic *mpic = mpic_primary;
++
++ BUG_ON(mpic == NULL);
++
++ return mpic_get_one_irq(mpic, regs);
++}
++
++
++#ifdef CONFIG_SMP
++void mpic_request_ipis(void)
++{
++ struct mpic *mpic = mpic_primary;
++
++ BUG_ON(mpic == NULL);
++
++ printk("requesting IPIs ... \n");
++
++ /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
++ request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
++ "IPI0 (call function)", mpic);
++ request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
++ "IPI1 (reschedule)", mpic);
++ request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
++ "IPI2 (unused)", mpic);
++ request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
++ "IPI3 (debugger break)", mpic);
++
++ printk("IPIs requested... \n");
++}
++
++void smp_mpic_message_pass(int target, int msg)
++{
++ /* make sure we're sending something that translates to an IPI */
++ if ((unsigned int)msg > 3) {
++ printk("SMP %d: smp_message_pass: unknown msg %d\n",
++ smp_processor_id(), msg);
++ return;
++ }
++ switch (target) {
++ case MSG_ALL:
++ mpic_send_ipi(msg, 0xffffffff);
++ break;
++ case MSG_ALL_BUT_SELF:
++ mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
++ break;
++ default:
++ mpic_send_ipi(msg, 1 << target);
++ break;
++ }
++}
++#endif /* CONFIG_SMP */
+diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/u3_iommu.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/sysdev/u3_iommu.c
+@@ -0,0 +1,327 @@
++/*
++ * arch/ppc64/kernel/u3_iommu.c
++ *
++ * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
++ *
++ * Based on pSeries_iommu.c:
++ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
++ * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
++ *
++ * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu.
++ *
++ *
++ * 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/init.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/vmalloc.h>
++#include <asm/io.h>
++#include <asm/prom.h>
++#include <asm/ppcdebug.h>
++#include <asm/iommu.h>
++#include <asm/pci-bridge.h>
++#include <asm/machdep.h>
++#include <asm/abs_addr.h>
++#include <asm/cacheflush.h>
++#include <asm/lmb.h>
++#include <asm/dart.h>
++#include <asm/ppc-pci.h>
++
++extern int iommu_force_on;
++
++/* Physical base address and size of the DART table */
++unsigned long dart_tablebase; /* exported to htab_initialize */
++static unsigned long dart_tablesize;
++
++/* Virtual base address of the DART table */
++static u32 *dart_vbase;
++
++/* Mapped base address for the dart */
++static unsigned int *dart;
++
++/* Dummy val that entries are set to when unused */
++static unsigned int dart_emptyval;
++
++static struct iommu_table iommu_table_u3;
++static int iommu_table_u3_inited;
++static int dart_dirty;
++
++#define DBG(...)
++
++static inline void dart_tlb_invalidate_all(void)
++{
++ unsigned long l = 0;
++ unsigned int reg;
++ unsigned long limit;
++
++ DBG("dart: flush\n");
++
++ /* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
++ * control register and wait for it to clear.
++ *
++ * Gotcha: Sometimes, the DART won't detect that the bit gets
++ * set. If so, clear it and set it again.
++ */
++
++ limit = 0;
++
++retry:
++ reg = in_be32((unsigned int *)dart+DARTCNTL);
++ reg |= DARTCNTL_FLUSHTLB;
++ out_be32((unsigned int *)dart+DARTCNTL, reg);
++
++ l = 0;
++ while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) &&
++ l < (1L<<limit)) {
++ l++;
++ }
++ if (l == (1L<<limit)) {
++ if (limit < 4) {
++ limit++;
++ reg = in_be32((unsigned int *)dart+DARTCNTL);
++ reg &= ~DARTCNTL_FLUSHTLB;
++ out_be32((unsigned int *)dart+DARTCNTL, reg);
++ goto retry;
++ } else
++ panic("U3-DART: TLB did not flush after waiting a long "
++ "time. Buggy U3 ?");
++ }
++}
++
++static void dart_flush(struct iommu_table *tbl)
++{
++ if (dart_dirty)
++ dart_tlb_invalidate_all();
++ dart_dirty = 0;
++}
++
++static void dart_build(struct iommu_table *tbl, long index,
++ long npages, unsigned long uaddr,
++ enum dma_data_direction direction)
++{
++ unsigned int *dp;
++ unsigned int rpn;
++
++ DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
++
++ index <<= DART_PAGE_FACTOR;
++ npages <<= DART_PAGE_FACTOR;
++
++ dp = ((unsigned int*)tbl->it_base) + index;
++
++ /* On U3, all memory is contigous, so we can move this
++ * out of the loop.
++ */
++ while (npages--) {
++ rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
++
++ *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
++
++ rpn++;
++ uaddr += DART_PAGE_SIZE;
++ }
++
++ dart_dirty = 1;
++}
++
++
++static void dart_free(struct iommu_table *tbl, long index, long npages)
++{
++ unsigned int *dp;
++
++ /* We don't worry about flushing the TLB cache. The only drawback of
++ * not doing it is that we won't catch buggy device drivers doing
++ * bad DMAs, but then no 32-bit architecture ever does either.
++ */
++
++ DBG("dart: free at: %lx, %lx\n", index, npages);
++
++ index <<= DART_PAGE_FACTOR;
++ npages <<= DART_PAGE_FACTOR;
++
++ dp = ((unsigned int *)tbl->it_base) + index;
++
++ while (npages--)
++ *(dp++) = dart_emptyval;
++}
++
++
++static int dart_init(struct device_node *dart_node)
++{
++ unsigned int regword;
++ unsigned int i;
++ unsigned long tmp;
++
++ if (dart_tablebase == 0 || dart_tablesize == 0) {
++ printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n");
++ return -ENODEV;
++ }
++
++ /* Make sure nothing from the DART range remains in the CPU cache
++ * from a previous mapping that existed before the kernel took
++ * over
++ */
++ flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize);
++
++ /* Allocate a spare page to map all invalid DART pages. We need to do
++ * that to work around what looks like a problem with the HT bridge
++ * prefetching into invalid pages and corrupting data
++ */
++ tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
++ if (!tmp)
++ panic("U3-DART: Cannot allocate spare page!");
++ dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK);
++
++ /* Map in DART registers. FIXME: Use device node to get base address */
++ dart = ioremap(DART_BASE, 0x7000);
++ if (dart == NULL)
++ panic("U3-DART: Cannot map registers!");
++
++ /* Set initial control register contents: table base,
++ * table size and enable bit
++ */
++ regword = DARTCNTL_ENABLE |
++ ((dart_tablebase >> DART_PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
++ (((dart_tablesize >> DART_PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
++ << DARTCNTL_SIZE_SHIFT);
++ dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
++
++ /* Fill initial table */
++ for (i = 0; i < dart_tablesize/4; i++)
++ dart_vbase[i] = dart_emptyval;
++
++ /* Initialize DART with table base and enable it. */
++ out_be32((unsigned int *)dart, regword);
++
++ /* Invalidate DART to get rid of possible stale TLBs */
++ dart_tlb_invalidate_all();
++
++ printk(KERN_INFO "U3/CPC925 DART IOMMU initialized\n");
++
++ return 0;
++}
++
++static void iommu_table_u3_setup(void)
++{
++ iommu_table_u3.it_busno = 0;
++ iommu_table_u3.it_offset = 0;
++ /* it_size is in number of entries */
++ iommu_table_u3.it_size = dart_tablesize / sizeof(u32);
++
++ /* Initialize the common IOMMU code */
++ iommu_table_u3.it_base = (unsigned long)dart_vbase;
++ iommu_table_u3.it_index = 0;
++ iommu_table_u3.it_blocksize = 1;
++ iommu_init_table(&iommu_table_u3);
++
++ /* Reserve the last page of the DART to avoid possible prefetch
++ * past the DART mapped area
++ */
++ set_bit(iommu_table_u3.it_size - 1, iommu_table_u3.it_map);
++}
++
++static void iommu_dev_setup_u3(struct pci_dev *dev)
++{
++ struct device_node *dn;
++
++ /* We only have one iommu table on the mac for now, which makes
++ * things simple. Setup all PCI devices to point to this table
++ *
++ * We must use pci_device_to_OF_node() to make sure that
++ * we get the real "final" pointer to the device in the
++ * pci_dev sysdata and not the temporary PHB one
++ */
++ dn = pci_device_to_OF_node(dev);
++
++ if (dn)
++ PCI_DN(dn)->iommu_table = &iommu_table_u3;
++}
++
++static void iommu_bus_setup_u3(struct pci_bus *bus)
++{
++ struct device_node *dn;
++
++ if (!iommu_table_u3_inited) {
++ iommu_table_u3_inited = 1;
++ iommu_table_u3_setup();
++ }
++
++ dn = pci_bus_to_OF_node(bus);
++
++ if (dn)
++ PCI_DN(dn)->iommu_table = &iommu_table_u3;
++}
++
++static void iommu_dev_setup_null(struct pci_dev *dev) { }
++static void iommu_bus_setup_null(struct pci_bus *bus) { }
++
++void iommu_init_early_u3(void)
++{
++ struct device_node *dn;
++
++ /* Find the DART in the device-tree */
++ dn = of_find_compatible_node(NULL, "dart", "u3-dart");
++ if (dn == NULL)
++ return;
++
++ /* Setup low level TCE operations for the core IOMMU code */
++ ppc_md.tce_build = dart_build;
++ ppc_md.tce_free = dart_free;
++ ppc_md.tce_flush = dart_flush;
++
++ /* Initialize the DART HW */
++ if (dart_init(dn)) {
++ /* If init failed, use direct iommu and null setup functions */
++ ppc_md.iommu_dev_setup = iommu_dev_setup_null;
++ ppc_md.iommu_bus_setup = iommu_bus_setup_null;
++
++ /* Setup pci_dma ops */
++ pci_direct_iommu_init();
++ } else {
++ ppc_md.iommu_dev_setup = iommu_dev_setup_u3;
++ ppc_md.iommu_bus_setup = iommu_bus_setup_u3;
++
++ /* Setup pci_dma ops */
++ pci_iommu_init();
++ }
++}
++
++
++void __init alloc_u3_dart_table(void)
++{
++ /* Only reserve DART space if machine has more than 2GB of RAM
++ * or if requested with iommu=on on cmdline.
++ */
++ if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
++ return;
++
++ /* 512 pages (2MB) is max DART tablesize. */
++ dart_tablesize = 1UL << 21;
++ /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
++ * will blow up an entire large page anyway in the kernel mapping
++ */
++ dart_tablebase = (unsigned long)
++ abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
++
++ printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase);
++}
+diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/Makefile
+@@ -0,0 +1,11 @@
++# Makefile for xmon
++
++ifdef CONFIG_PPC64
++EXTRA_CFLAGS += -mno-minimal-toc
++endif
++
++obj-$(CONFIG_8xx) += start_8xx.o
++obj-$(CONFIG_6xx) += start_32.o
++obj-$(CONFIG_4xx) += start_32.o
++obj-$(CONFIG_PPC64) += start_64.o
++obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+diff --git a/arch/powerpc/xmon/ansidecl.h b/arch/powerpc/xmon/ansidecl.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/ansidecl.h
+@@ -0,0 +1,141 @@
++/* ANSI and traditional C compatibility macros
++ Copyright 1991, 1992 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++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. */
++
++/* ANSI and traditional C compatibility macros
++
++ ANSI C is assumed if __STDC__ is #defined.
++
++ Macro ANSI C definition Traditional C definition
++ ----- ---- - ---------- ----------- - ----------
++ PTR `void *' `char *'
++ LONG_DOUBLE `long double' `double'
++ VOLATILE `volatile' `'
++ SIGNED `signed' `'
++ PTRCONST `void *const' `char *'
++ ANSI_PROTOTYPES 1 not defined
++
++ CONST is also defined, but is obsolete. Just use const.
++
++ DEFUN (name, arglist, args)
++
++ Defines function NAME.
++
++ ARGLIST lists the arguments, separated by commas and enclosed in
++ parentheses. ARGLIST becomes the argument list in traditional C.
++
++ ARGS list the arguments with their types. It becomes a prototype in
++ ANSI C, and the type declarations in traditional C. Arguments should
++ be separated with `AND'. For functions with a variable number of
++ arguments, the last thing listed should be `DOTS'.
++
++ DEFUN_VOID (name)
++
++ Defines a function NAME, which takes no arguments.
++
++ obsolete -- EXFUN (name, (prototype)) -- obsolete.
++
++ Replaced by PARAMS. Do not use; will disappear someday soon.
++ Was used in external function declarations.
++ In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
++ parentheses). In traditional C it is `NAME()'.
++ For a function that takes no arguments, PROTOTYPE should be `(void)'.
++
++ PARAMS ((args))
++
++ We could use the EXFUN macro to handle prototype declarations, but
++ the name is misleading and the result is ugly. So we just define a
++ simple macro to handle the parameter lists, as in:
++
++ static int foo PARAMS ((int, char));
++
++ This produces: `static int foo();' or `static int foo (int, char);'
++
++ EXFUN would have done it like this:
++
++ static int EXFUN (foo, (int, char));
++
++ but the function is not external...and it's hard to visually parse
++ the function name out of the mess. EXFUN should be considered
++ obsolete; new code should be written to use PARAMS.
++
++ For example:
++ extern int printf PARAMS ((CONST char *format DOTS));
++ int DEFUN(fprintf, (stream, format),
++ FILE *stream AND CONST char *format DOTS) { ... }
++ void DEFUN_VOID(abort) { ... }
++*/
++
++#ifndef _ANSIDECL_H
++
++#define _ANSIDECL_H 1
++
++
++/* Every source file includes this file,
++ so they will all get the switch for lint. */
++/* LINTLIBRARY */
++
++
++#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32)
++/* All known AIX compilers implement these things (but don't always
++ define __STDC__). The RISC/OS MIPS compiler defines these things
++ in SVR4 mode, but does not define __STDC__. */
++
++#define PTR void *
++#define PTRCONST void *CONST
++#define LONG_DOUBLE long double
++
++#define AND ,
++#define NOARGS void
++#define CONST const
++#define VOLATILE volatile
++#define SIGNED signed
++#define DOTS , ...
++
++#define EXFUN(name, proto) name proto
++#define DEFUN(name, arglist, args) name(args)
++#define DEFUN_VOID(name) name(void)
++
++#define PROTO(type, name, arglist) type name arglist
++#define PARAMS(paramlist) paramlist
++#define ANSI_PROTOTYPES 1
++
++#else /* Not ANSI C. */
++
++#define PTR char *
++#define PTRCONST PTR
++#define LONG_DOUBLE double
++
++#define AND ;
++#define NOARGS
++#define CONST
++#ifndef const /* some systems define it in header files for non-ansi mode */
++#define const
++#endif
++#define VOLATILE
++#define SIGNED
++#define DOTS
++
++#define EXFUN(name, proto) name()
++#define DEFUN(name, arglist, args) name arglist args;
++#define DEFUN_VOID(name) name()
++#define PROTO(type, name, arglist) type name ()
++#define PARAMS(paramlist) ()
++
++#endif /* ANSI C. */
++
++#endif /* ansidecl.h */
+diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/nonstdio.h
+@@ -0,0 +1,22 @@
++typedef int FILE;
++extern FILE *xmon_stdin, *xmon_stdout;
++#define EOF (-1)
++#define stdin xmon_stdin
++#define stdout xmon_stdout
++#define printf xmon_printf
++#define fprintf xmon_fprintf
++#define fputs xmon_fputs
++#define fgets xmon_fgets
++#define putchar xmon_putchar
++#define getchar xmon_getchar
++#define putc xmon_putc
++#define getc xmon_getc
++#define fopen(n, m) NULL
++#define fflush(f) do {} while (0)
++#define fclose(f) do {} while (0)
++extern char *fgets(char *, int, void *);
++extern void xmon_printf(const char *, ...);
++extern void xmon_fprintf(void *, const char *, ...);
++extern void xmon_sprintf(char *, const char *, ...);
++
++#define perror(s) printf("%s: no files!\n", (s))
+diff --git a/arch/powerpc/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/ppc-dis.c
+@@ -0,0 +1,184 @@
++/* ppc-dis.c -- Disassemble PowerPC instructions
++ Copyright 1994 Free Software Foundation, Inc.
++ Written by Ian Lance Taylor, Cygnus Support
++
++This file is part of GDB, GAS, and the GNU binutils.
++
++GDB, GAS, and the GNU binutils are free software; you can redistribute
++them and/or modify them 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.
++
++GDB, GAS, and the GNU binutils are distributed in the hope that they
++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 file; see the file COPYING. If not, write to the Free
++Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
++
++#include "nonstdio.h"
++#include "ansidecl.h"
++#include "ppc.h"
++
++extern void print_address (unsigned long memaddr);
++
++/* Print a PowerPC or POWER instruction. */
++
++int
++print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
++{
++ const struct powerpc_opcode *opcode;
++ const struct powerpc_opcode *opcode_end;
++ unsigned long op;
++
++ if (dialect == 0)
++ dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
++ | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
++
++ /* Get the major opcode of the instruction. */
++ op = PPC_OP (insn);
++
++ /* Find the first match in the opcode table. We could speed this up
++ a bit by doing a binary search on the major opcode. */
++ opcode_end = powerpc_opcodes + powerpc_num_opcodes;
++ again:
++ for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
++ {
++ unsigned long table_op;
++ const unsigned char *opindex;
++ const struct powerpc_operand *operand;
++ int invalid;
++ int need_comma;
++ int need_paren;
++
++ table_op = PPC_OP (opcode->opcode);
++ if (op < table_op)
++ break;
++ if (op > table_op)
++ continue;
++
++ if ((insn & opcode->mask) != opcode->opcode
++ || (opcode->flags & dialect) == 0)
++ continue;
++
++ /* Make two passes over the operands. First see if any of them
++ have extraction functions, and, if they do, make sure the
++ instruction is valid. */
++ invalid = 0;
++ for (opindex = opcode->operands; *opindex != 0; opindex++)
++ {
++ operand = powerpc_operands + *opindex;
++ if (operand->extract)
++ (*operand->extract) (insn, dialect, &invalid);
++ }
++ if (invalid)
++ continue;
++
++ /* The instruction is valid. */
++ printf("%s", opcode->name);
++ if (opcode->operands[0] != 0)
++ printf("\t");
++
++ /* Now extract and print the operands. */
++ need_comma = 0;
++ need_paren = 0;
++ for (opindex = opcode->operands; *opindex != 0; opindex++)
++ {
++ long value;
++
++ operand = powerpc_operands + *opindex;
++
++ /* Operands that are marked FAKE are simply ignored. We
++ already made sure that the extract function considered
++ the instruction to be valid. */
++ if ((operand->flags & PPC_OPERAND_FAKE) != 0)
++ continue;
++
++ /* Extract the value from the instruction. */
++ if (operand->extract)
++ value = (*operand->extract) (insn, dialect, &invalid);
++ else
++ {
++ value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
++ if ((operand->flags & PPC_OPERAND_SIGNED) != 0
++ && (value & (1 << (operand->bits - 1))) != 0)
++ value -= 1 << operand->bits;
++ }
++
++ /* If the operand is optional, and the value is zero, don't
++ print anything. */
++ if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
++ && (operand->flags & PPC_OPERAND_NEXT) == 0
++ && value == 0)
++ continue;
++
++ if (need_comma)
++ {
++ printf(",");
++ need_comma = 0;
++ }
++
++ /* Print the operand as directed by the flags. */
++ if ((operand->flags & PPC_OPERAND_GPR) != 0)
++ printf("r%ld", value);
++ else if ((operand->flags & PPC_OPERAND_FPR) != 0)
++ printf("f%ld", value);
++ else if ((operand->flags & PPC_OPERAND_VR) != 0)
++ printf("v%ld", value);
++ else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
++ print_address (memaddr + value);
++ else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
++ print_address (value & 0xffffffff);
++ else if ((operand->flags & PPC_OPERAND_CR) == 0
++ || (dialect & PPC_OPCODE_PPC) == 0)
++ printf("%ld", value);
++ else
++ {
++ if (operand->bits == 3)
++ printf("cr%d", value);
++ else
++ {
++ static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
++ int cr;
++ int cc;
++
++ cr = value >> 2;
++ if (cr != 0)
++ printf("4*cr%d+", cr);
++ cc = value & 3;
++ printf("%s", cbnames[cc]);
++ }
++ }
++
++ if (need_paren)
++ {
++ printf(")");
++ need_paren = 0;
++ }
++
++ if ((operand->flags & PPC_OPERAND_PARENS) == 0)
++ need_comma = 1;
++ else
++ {
++ printf("(");
++ need_paren = 1;
++ }
++ }
++
++ /* We have found and printed an instruction; return. */
++ return 4;
++ }
++
++ if ((dialect & PPC_OPCODE_ANY) != 0)
++ {
++ dialect = ~PPC_OPCODE_ANY;
++ goto again;
++ }
++
++ /* We could not find a match. */
++ printf(".long 0x%lx", insn);
++
++ return 4;
++}
+diff --git a/arch/powerpc/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/ppc-opc.c
+@@ -0,0 +1,4621 @@
++/* ppc-opc.c -- PowerPC opcode list
++ Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
++ Free Software Foundation, Inc.
++ Written by Ian Lance Taylor, Cygnus Support
++
++ This file is part of GDB, GAS, and the GNU binutils.
++
++ GDB, GAS, and the GNU binutils are free software; you can redistribute
++ them and/or modify them 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.
++
++ GDB, GAS, and the GNU binutils are distributed in the hope that they
++ 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 file; see the file COPYING. If not, write to the Free
++ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
++ 02111-1307, USA. */
++
++#include <linux/stddef.h>
++#include "nonstdio.h"
++#include "ppc.h"
++
++#define ATTRIBUTE_UNUSED
++#define _(x) x
++
++/* This file holds the PowerPC opcode table. The opcode table
++ includes almost all of the extended instruction mnemonics. This
++ permits the disassembler to use them, and simplifies the assembler
++ logic, at the cost of increasing the table size. The table is
++ strictly constant data, so the compiler should be able to put it in
++ the .text section.
++
++ This file also holds the operand table. All knowledge about
++ inserting operands into instructions and vice-versa is kept in this
++ file. */
++
++/* Local insertion and extraction functions. */
++
++static unsigned long insert_bat (unsigned long, long, int, const char **);
++static long extract_bat (unsigned long, int, int *);
++static unsigned long insert_bba (unsigned long, long, int, const char **);
++static long extract_bba (unsigned long, int, int *);
++static unsigned long insert_bd (unsigned long, long, int, const char **);
++static long extract_bd (unsigned long, int, int *);
++static unsigned long insert_bdm (unsigned long, long, int, const char **);
++static long extract_bdm (unsigned long, int, int *);
++static unsigned long insert_bdp (unsigned long, long, int, const char **);
++static long extract_bdp (unsigned long, int, int *);
++static unsigned long insert_bo (unsigned long, long, int, const char **);
++static long extract_bo (unsigned long, int, int *);
++static unsigned long insert_boe (unsigned long, long, int, const char **);
++static long extract_boe (unsigned long, int, int *);
++static unsigned long insert_dq (unsigned long, long, int, const char **);
++static long extract_dq (unsigned long, int, int *);
++static unsigned long insert_ds (unsigned long, long, int, const char **);
++static long extract_ds (unsigned long, int, int *);
++static unsigned long insert_de (unsigned long, long, int, const char **);
++static long extract_de (unsigned long, int, int *);
++static unsigned long insert_des (unsigned long, long, int, const char **);
++static long extract_des (unsigned long, int, int *);
++static unsigned long insert_fxm (unsigned long, long, int, const char **);
++static long extract_fxm (unsigned long, int, int *);
++static unsigned long insert_li (unsigned long, long, int, const char **);
++static long extract_li (unsigned long, int, int *);
++static unsigned long insert_mbe (unsigned long, long, int, const char **);
++static long extract_mbe (unsigned long, int, int *);
++static unsigned long insert_mb6 (unsigned long, long, int, const char **);
++static long extract_mb6 (unsigned long, int, int *);
++static unsigned long insert_nb (unsigned long, long, int, const char **);
++static long extract_nb (unsigned long, int, int *);
++static unsigned long insert_nsi (unsigned long, long, int, const char **);
++static long extract_nsi (unsigned long, int, int *);
++static unsigned long insert_ral (unsigned long, long, int, const char **);
++static unsigned long insert_ram (unsigned long, long, int, const char **);
++static unsigned long insert_raq (unsigned long, long, int, const char **);
++static unsigned long insert_ras (unsigned long, long, int, const char **);
++static unsigned long insert_rbs (unsigned long, long, int, const char **);
++static long extract_rbs (unsigned long, int, int *);
++static unsigned long insert_rsq (unsigned long, long, int, const char **);
++static unsigned long insert_rtq (unsigned long, long, int, const char **);
++static unsigned long insert_sh6 (unsigned long, long, int, const char **);
++static long extract_sh6 (unsigned long, int, int *);
++static unsigned long insert_spr (unsigned long, long, int, const char **);
++static long extract_spr (unsigned long, int, int *);
++static unsigned long insert_tbr (unsigned long, long, int, const char **);
++static long extract_tbr (unsigned long, int, int *);
++static unsigned long insert_ev2 (unsigned long, long, int, const char **);
++static long extract_ev2 (unsigned long, int, int *);
++static unsigned long insert_ev4 (unsigned long, long, int, const char **);
++static long extract_ev4 (unsigned long, int, int *);
++static unsigned long insert_ev8 (unsigned long, long, int, const char **);
++static long extract_ev8 (unsigned long, int, int *);
++
++/* The operands table.
++
++ The fields are bits, shift, insert, extract, flags.
++
++ We used to put parens around the various additions, like the one
++ for BA just below. However, that caused trouble with feeble
++ compilers with a limit on depth of a parenthesized expression, like
++ (reportedly) the compiler in Microsoft Developer Studio 5. So we
++ omit the parens, since the macros are never used in a context where
++ the addition will be ambiguous. */
++
++const struct powerpc_operand powerpc_operands[] =
++{
++ /* The zero index is used to indicate the end of the list of
++ operands. */
++#define UNUSED 0
++ { 0, 0, NULL, NULL, 0 },
++
++ /* The BA field in an XL form instruction. */
++#define BA UNUSED + 1
++#define BA_MASK (0x1f << 16)
++ { 5, 16, NULL, NULL, PPC_OPERAND_CR },
++
++ /* The BA field in an XL form instruction when it must be the same
++ as the BT field in the same instruction. */
++#define BAT BA + 1
++ { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE },
++
++ /* The BB field in an XL form instruction. */
++#define BB BAT + 1
++#define BB_MASK (0x1f << 11)
++ { 5, 11, NULL, NULL, PPC_OPERAND_CR },
++
++ /* The BB field in an XL form instruction when it must be the same
++ as the BA field in the same instruction. */
++#define BBA BB + 1
++ { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE },
++
++ /* The BD field in a B form instruction. The lower two bits are
++ forced to zero. */
++#define BD BBA + 1
++ { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
++
++ /* The BD field in a B form instruction when absolute addressing is
++ used. */
++#define BDA BD + 1
++ { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
++
++ /* The BD field in a B form instruction when the - modifier is used.
++ This sets the y bit of the BO field appropriately. */
++#define BDM BDA + 1
++ { 16, 0, insert_bdm, extract_bdm,
++ PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
++
++ /* The BD field in a B form instruction when the - modifier is used
++ and absolute address is used. */
++#define BDMA BDM + 1
++ { 16, 0, insert_bdm, extract_bdm,
++ PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
++
++ /* The BD field in a B form instruction when the + modifier is used.
++ This sets the y bit of the BO field appropriately. */
++#define BDP BDMA + 1
++ { 16, 0, insert_bdp, extract_bdp,
++ PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
++
++ /* The BD field in a B form instruction when the + modifier is used
++ and absolute addressing is used. */
++#define BDPA BDP + 1
++ { 16, 0, insert_bdp, extract_bdp,
++ PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
++
++ /* The BF field in an X or XL form instruction. */
++#define BF BDPA + 1
++ { 3, 23, NULL, NULL, PPC_OPERAND_CR },
++
++ /* An optional BF field. This is used for comparison instructions,
++ in which an omitted BF field is taken as zero. */
++#define OBF BF + 1
++ { 3, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
++
++ /* The BFA field in an X or XL form instruction. */
++#define BFA OBF + 1
++ { 3, 18, NULL, NULL, PPC_OPERAND_CR },
++
++ /* The BI field in a B form or XL form instruction. */
++#define BI BFA + 1
++#define BI_MASK (0x1f << 16)
++ { 5, 16, NULL, NULL, PPC_OPERAND_CR },
++
++ /* The BO field in a B form instruction. Certain values are
++ illegal. */
++#define BO BI + 1
++#define BO_MASK (0x1f << 21)
++ { 5, 21, insert_bo, extract_bo, 0 },
++
++ /* The BO field in a B form instruction when the + or - modifier is
++ used. This is like the BO field, but it must be even. */
++#define BOE BO + 1
++ { 5, 21, insert_boe, extract_boe, 0 },
++
++ /* The BT field in an X or XL form instruction. */
++#define BT BOE + 1
++ { 5, 21, NULL, NULL, PPC_OPERAND_CR },
++
++ /* The condition register number portion of the BI field in a B form
++ or XL form instruction. This is used for the extended
++ conditional branch mnemonics, which set the lower two bits of the
++ BI field. This field is optional. */
++#define CR BT + 1
++ { 3, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
++
++ /* The CRB field in an X form instruction. */
++#define CRB CR + 1
++ { 5, 6, NULL, NULL, 0 },
++
++ /* The CRFD field in an X form instruction. */
++#define CRFD CRB + 1
++ { 3, 23, NULL, NULL, PPC_OPERAND_CR },
++
++ /* The CRFS field in an X form instruction. */
++#define CRFS CRFD + 1
++ { 3, 0, NULL, NULL, PPC_OPERAND_CR },
++
++ /* The CT field in an X form instruction. */
++#define CT CRFS + 1
++ { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
++
++ /* The D field in a D form instruction. This is a displacement off
++ a register, and implies that the next operand is a register in
++ parentheses. */
++#define D CT + 1
++ { 16, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
++
++ /* The DE field in a DE form instruction. This is like D, but is 12
++ bits only. */
++#define DE D + 1
++ { 14, 0, insert_de, extract_de, PPC_OPERAND_PARENS },
++
++ /* The DES field in a DES form instruction. This is like DS, but is 14
++ bits only (12 stored.) */
++#define DES DE + 1
++ { 14, 0, insert_des, extract_des, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
++
++ /* The DQ field in a DQ form instruction. This is like D, but the
++ lower four bits are forced to zero. */
++#define DQ DES + 1
++ { 16, 0, insert_dq, extract_dq,
++ PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DQ },
++
++ /* The DS field in a DS form instruction. This is like D, but the
++ lower two bits are forced to zero. */
++#define DS DQ + 1
++ { 16, 0, insert_ds, extract_ds,
++ PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DS },
++
++ /* The E field in a wrteei instruction. */
++#define E DS + 1
++ { 1, 15, NULL, NULL, 0 },
++
++ /* The FL1 field in a POWER SC form instruction. */
++#define FL1 E + 1
++ { 4, 12, NULL, NULL, 0 },
++
++ /* The FL2 field in a POWER SC form instruction. */
++#define FL2 FL1 + 1
++ { 3, 2, NULL, NULL, 0 },
++
++ /* The FLM field in an XFL form instruction. */
++#define FLM FL2 + 1
++ { 8, 17, NULL, NULL, 0 },
++
++ /* The FRA field in an X or A form instruction. */
++#define FRA FLM + 1
++#define FRA_MASK (0x1f << 16)
++ { 5, 16, NULL, NULL, PPC_OPERAND_FPR },
++
++ /* The FRB field in an X or A form instruction. */
++#define FRB FRA + 1
++#define FRB_MASK (0x1f << 11)
++ { 5, 11, NULL, NULL, PPC_OPERAND_FPR },
++
++ /* The FRC field in an A form instruction. */
++#define FRC FRB + 1
++#define FRC_MASK (0x1f << 6)
++ { 5, 6, NULL, NULL, PPC_OPERAND_FPR },
++
++ /* The FRS field in an X form instruction or the FRT field in a D, X
++ or A form instruction. */
++#define FRS FRC + 1
++#define FRT FRS
++ { 5, 21, NULL, NULL, PPC_OPERAND_FPR },
++
++ /* The FXM field in an XFX instruction. */
++#define FXM FRS + 1
++#define FXM_MASK (0xff << 12)
++ { 8, 12, insert_fxm, extract_fxm, 0 },
++
++ /* Power4 version for mfcr. */
++#define FXM4 FXM + 1
++ { 8, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL },
++
++ /* The L field in a D or X form instruction. */
++#define L FXM4 + 1
++ { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
++
++ /* The LEV field in a POWER SC form instruction. */
++#define LEV L + 1
++ { 7, 5, NULL, NULL, 0 },
++
++ /* The LI field in an I form instruction. The lower two bits are
++ forced to zero. */
++#define LI LEV + 1
++ { 26, 0, insert_li, extract_li, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
++
++ /* The LI field in an I form instruction when used as an absolute
++ address. */
++#define LIA LI + 1
++ { 26, 0, insert_li, extract_li, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
++
++ /* The LS field in an X (sync) form instruction. */
++#define LS LIA + 1
++ { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
++
++ /* The MB field in an M form instruction. */
++#define MB LS + 1
++#define MB_MASK (0x1f << 6)
++ { 5, 6, NULL, NULL, 0 },
++
++ /* The ME field in an M form instruction. */
++#define ME MB + 1
++#define ME_MASK (0x1f << 1)
++ { 5, 1, NULL, NULL, 0 },
++
++ /* The MB and ME fields in an M form instruction expressed a single
++ operand which is a bitmask indicating which bits to select. This
++ is a two operand form using PPC_OPERAND_NEXT. See the
++ description in opcode/ppc.h for what this means. */
++#define MBE ME + 1
++ { 5, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
++ { 32, 0, insert_mbe, extract_mbe, 0 },
++
++ /* The MB or ME field in an MD or MDS form instruction. The high
++ bit is wrapped to the low end. */
++#define MB6 MBE + 2
++#define ME6 MB6
++#define MB6_MASK (0x3f << 5)
++ { 6, 5, insert_mb6, extract_mb6, 0 },
++
++ /* The MO field in an mbar instruction. */
++#define MO MB6 + 1
++ { 5, 21, NULL, NULL, 0 },
++
++ /* The NB field in an X form instruction. The value 32 is stored as
++ 0. */
++#define NB MO + 1
++ { 6, 11, insert_nb, extract_nb, 0 },
++
++ /* The NSI field in a D form instruction. This is the same as the
++ SI field, only negated. */
++#define NSI NB + 1
++ { 16, 0, insert_nsi, extract_nsi,
++ PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
++
++ /* The RA field in an D, DS, DQ, X, XO, M, or MDS form instruction. */
++#define RA NSI + 1
++#define RA_MASK (0x1f << 16)
++ { 5, 16, NULL, NULL, PPC_OPERAND_GPR },
++
++ /* The RA field in the DQ form lq instruction, which has special
++ value restrictions. */
++#define RAQ RA + 1
++ { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR },
++
++ /* The RA field in a D or X form instruction which is an updating
++ load, which means that the RA field may not be zero and may not
++ equal the RT field. */
++#define RAL RAQ + 1
++ { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR },
++
++ /* The RA field in an lmw instruction, which has special value
++ restrictions. */
++#define RAM RAL + 1
++ { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR },
++
++ /* The RA field in a D or X form instruction which is an updating
++ store or an updating floating point load, which means that the RA
++ field may not be zero. */
++#define RAS RAM + 1
++ { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR },
++
++ /* The RB field in an X, XO, M, or MDS form instruction. */
++#define RB RAS + 1
++#define RB_MASK (0x1f << 11)
++ { 5, 11, NULL, NULL, PPC_OPERAND_GPR },
++
++ /* The RB field in an X form instruction when it must be the same as
++ the RS field in the instruction. This is used for extended
++ mnemonics like mr. */
++#define RBS RB + 1
++ { 5, 1, insert_rbs, extract_rbs, PPC_OPERAND_FAKE },
++
++ /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form
++ instruction or the RT field in a D, DS, X, XFX or XO form
++ instruction. */
++#define RS RBS + 1
++#define RT RS
++#define RT_MASK (0x1f << 21)
++ { 5, 21, NULL, NULL, PPC_OPERAND_GPR },
++
++ /* The RS field of the DS form stq instruction, which has special
++ value restrictions. */
++#define RSQ RS + 1
++ { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR },
++
++ /* The RT field of the DQ form lq instruction, which has special
++ value restrictions. */
++#define RTQ RSQ + 1
++ { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR },
++
++ /* The SH field in an X or M form instruction. */
++#define SH RTQ + 1
++#define SH_MASK (0x1f << 11)
++ { 5, 11, NULL, NULL, 0 },
++
++ /* The SH field in an MD form instruction. This is split. */
++#define SH6 SH + 1
++#define SH6_MASK ((0x1f << 11) | (1 << 1))
++ { 6, 1, insert_sh6, extract_sh6, 0 },
++
++ /* The SI field in a D form instruction. */
++#define SI SH6 + 1
++ { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
++
++ /* The SI field in a D form instruction when we accept a wide range
++ of positive values. */
++#define SISIGNOPT SI + 1
++ { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
++
++ /* The SPR field in an XFX form instruction. This is flipped--the
++ lower 5 bits are stored in the upper 5 and vice- versa. */
++#define SPR SISIGNOPT + 1
++#define PMR SPR
++#define SPR_MASK (0x3ff << 11)
++ { 10, 11, insert_spr, extract_spr, 0 },
++
++ /* The BAT index number in an XFX form m[ft]ibat[lu] instruction. */
++#define SPRBAT SPR + 1
++#define SPRBAT_MASK (0x3 << 17)
++ { 2, 17, NULL, NULL, 0 },
++
++ /* The SPRG register number in an XFX form m[ft]sprg instruction. */
++#define SPRG SPRBAT + 1
++#define SPRG_MASK (0x3 << 16)
++ { 2, 16, NULL, NULL, 0 },
++
++ /* The SR field in an X form instruction. */
++#define SR SPRG + 1
++ { 4, 16, NULL, NULL, 0 },
++
++ /* The STRM field in an X AltiVec form instruction. */
++#define STRM SR + 1
++#define STRM_MASK (0x3 << 21)
++ { 2, 21, NULL, NULL, 0 },
++
++ /* The SV field in a POWER SC form instruction. */
++#define SV STRM + 1
++ { 14, 2, NULL, NULL, 0 },
++
++ /* The TBR field in an XFX form instruction. This is like the SPR
++ field, but it is optional. */
++#define TBR SV + 1
++ { 10, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
++
++ /* The TO field in a D or X form instruction. */
++#define TO TBR + 1
++#define TO_MASK (0x1f << 21)
++ { 5, 21, NULL, NULL, 0 },
++
++ /* The U field in an X form instruction. */
++#define U TO + 1
++ { 4, 12, NULL, NULL, 0 },
++
++ /* The UI field in a D form instruction. */
++#define UI U + 1
++ { 16, 0, NULL, NULL, 0 },
++
++ /* The VA field in a VA, VX or VXR form instruction. */
++#define VA UI + 1
++#define VA_MASK (0x1f << 16)
++ { 5, 16, NULL, NULL, PPC_OPERAND_VR },
++
++ /* The VB field in a VA, VX or VXR form instruction. */
++#define VB VA + 1
++#define VB_MASK (0x1f << 11)
++ { 5, 11, NULL, NULL, PPC_OPERAND_VR },
++
++ /* The VC field in a VA form instruction. */
++#define VC VB + 1
++#define VC_MASK (0x1f << 6)
++ { 5, 6, NULL, NULL, PPC_OPERAND_VR },
++
++ /* The VD or VS field in a VA, VX, VXR or X form instruction. */
++#define VD VC + 1
++#define VS VD
++#define VD_MASK (0x1f << 21)
++ { 5, 21, NULL, NULL, PPC_OPERAND_VR },
++
++ /* The SIMM field in a VX form instruction. */
++#define SIMM VD + 1
++ { 5, 16, NULL, NULL, PPC_OPERAND_SIGNED},
++
++ /* The UIMM field in a VX form instruction. */
++#define UIMM SIMM + 1
++ { 5, 16, NULL, NULL, 0 },
++
++ /* The SHB field in a VA form instruction. */
++#define SHB UIMM + 1
++ { 4, 6, NULL, NULL, 0 },
++
++ /* The other UIMM field in a EVX form instruction. */
++#define EVUIMM SHB + 1
++ { 5, 11, NULL, NULL, 0 },
++
++ /* The other UIMM field in a half word EVX form instruction. */
++#define EVUIMM_2 EVUIMM + 1
++ { 32, 11, insert_ev2, extract_ev2, PPC_OPERAND_PARENS },
++
++ /* The other UIMM field in a word EVX form instruction. */
++#define EVUIMM_4 EVUIMM_2 + 1
++ { 32, 11, insert_ev4, extract_ev4, PPC_OPERAND_PARENS },
++
++ /* The other UIMM field in a double EVX form instruction. */
++#define EVUIMM_8 EVUIMM_4 + 1
++ { 32, 11, insert_ev8, extract_ev8, PPC_OPERAND_PARENS },
++
++ /* The WS field. */
++#define WS EVUIMM_8 + 1
++#define WS_MASK (0x7 << 11)
++ { 3, 11, NULL, NULL, 0 },
++
++ /* The L field in an mtmsrd instruction */
++#define MTMSRD_L WS + 1
++ { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL },
++
++};
++
++/* The functions used to insert and extract complicated operands. */
++
++/* The BA field in an XL form instruction when it must be the same as
++ the BT field in the same instruction. This operand is marked FAKE.
++ The insertion function just copies the BT field into the BA field,
++ and the extraction function just checks that the fields are the
++ same. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_bat (unsigned long insn,
++ long value ATTRIBUTE_UNUSED,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | (((insn >> 21) & 0x1f) << 16);
++}
++
++static long
++extract_bat (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid)
++{
++ if (((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f))
++ *invalid = 1;
++ return 0;
++}
++
++/* The BB field in an XL form instruction when it must be the same as
++ the BA field in the same instruction. This operand is marked FAKE.
++ The insertion function just copies the BA field into the BB field,
++ and the extraction function just checks that the fields are the
++ same. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_bba (unsigned long insn,
++ long value ATTRIBUTE_UNUSED,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | (((insn >> 16) & 0x1f) << 11);
++}
++
++static long
++extract_bba (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid)
++{
++ if (((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f))
++ *invalid = 1;
++ return 0;
++}
++
++/* The BD field in a B form instruction. The lower two bits are
++ forced to zero. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_bd (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | (value & 0xfffc);
++}
++
++/*ARGSUSED*/
++static long
++extract_bd (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
++}
++
++/* The BD field in a B form instruction when the - modifier is used.
++ This modifier means that the branch is not expected to be taken.
++ For chips built to versions of the architecture prior to version 2
++ (ie. not Power4 compatible), we set the y bit of the BO field to 1
++ if the offset is negative. When extracting, we require that the y
++ bit be 1 and that the offset be positive, since if the y bit is 0
++ we just want to print the normal form of the instruction.
++ Power4 compatible targets use two bits, "a", and "t", instead of
++ the "y" bit. "at" == 00 => no hint, "at" == 01 => unpredictable,
++ "at" == 10 => not taken, "at" == 11 => taken. The "t" bit is 00001
++ in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000
++ for branch on CTR. We only handle the taken/not-taken hint here. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_bdm (unsigned long insn,
++ long value,
++ int dialect,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ if ((dialect & PPC_OPCODE_POWER4) == 0)
++ {
++ if ((value & 0x8000) != 0)
++ insn |= 1 << 21;
++ }
++ else
++ {
++ if ((insn & (0x14 << 21)) == (0x04 << 21))
++ insn |= 0x02 << 21;
++ else if ((insn & (0x14 << 21)) == (0x10 << 21))
++ insn |= 0x08 << 21;
++ }
++ return insn | (value & 0xfffc);
++}
++
++static long
++extract_bdm (unsigned long insn,
++ int dialect,
++ int *invalid)
++{
++ if ((dialect & PPC_OPCODE_POWER4) == 0)
++ {
++ if (((insn & (1 << 21)) == 0) != ((insn & (1 << 15)) == 0))
++ *invalid = 1;
++ }
++ else
++ {
++ if ((insn & (0x17 << 21)) != (0x06 << 21)
++ && (insn & (0x1d << 21)) != (0x18 << 21))
++ *invalid = 1;
++ }
++
++ return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
++}
++
++/* The BD field in a B form instruction when the + modifier is used.
++ This is like BDM, above, except that the branch is expected to be
++ taken. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_bdp (unsigned long insn,
++ long value,
++ int dialect,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ if ((dialect & PPC_OPCODE_POWER4) == 0)
++ {
++ if ((value & 0x8000) == 0)
++ insn |= 1 << 21;
++ }
++ else
++ {
++ if ((insn & (0x14 << 21)) == (0x04 << 21))
++ insn |= 0x03 << 21;
++ else if ((insn & (0x14 << 21)) == (0x10 << 21))
++ insn |= 0x09 << 21;
++ }
++ return insn | (value & 0xfffc);
++}
++
++static long
++extract_bdp (unsigned long insn,
++ int dialect,
++ int *invalid)
++{
++ if ((dialect & PPC_OPCODE_POWER4) == 0)
++ {
++ if (((insn & (1 << 21)) == 0) == ((insn & (1 << 15)) == 0))
++ *invalid = 1;
++ }
++ else
++ {
++ if ((insn & (0x17 << 21)) != (0x07 << 21)
++ && (insn & (0x1d << 21)) != (0x19 << 21))
++ *invalid = 1;
++ }
++
++ return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
++}
++
++/* Check for legal values of a BO field. */
++
++static int
++valid_bo (long value, int dialect)
++{
++ if ((dialect & PPC_OPCODE_POWER4) == 0)
++ {
++ /* Certain encodings have bits that are required to be zero.
++ These are (z must be zero, y may be anything):
++ 001zy
++ 011zy
++ 1z00y
++ 1z01y
++ 1z1zz
++ */
++ switch (value & 0x14)
++ {
++ default:
++ case 0:
++ return 1;
++ case 0x4:
++ return (value & 0x2) == 0;
++ case 0x10:
++ return (value & 0x8) == 0;
++ case 0x14:
++ return value == 0x14;
++ }
++ }
++ else
++ {
++ /* Certain encodings have bits that are required to be zero.
++ These are (z must be zero, a & t may be anything):
++ 0000z
++ 0001z
++ 0100z
++ 0101z
++ 001at
++ 011at
++ 1a00t
++ 1a01t
++ 1z1zz
++ */
++ if ((value & 0x14) == 0)
++ return (value & 0x1) == 0;
++ else if ((value & 0x14) == 0x14)
++ return value == 0x14;
++ else
++ return 1;
++ }
++}
++
++/* The BO field in a B form instruction. Warn about attempts to set
++ the field to an illegal value. */
++
++static unsigned long
++insert_bo (unsigned long insn,
++ long value,
++ int dialect,
++ const char **errmsg)
++{
++ if (!valid_bo (value, dialect))
++ *errmsg = _("invalid conditional option");
++ return insn | ((value & 0x1f) << 21);
++}
++
++static long
++extract_bo (unsigned long insn,
++ int dialect,
++ int *invalid)
++{
++ long value;
++
++ value = (insn >> 21) & 0x1f;
++ if (!valid_bo (value, dialect))
++ *invalid = 1;
++ return value;
++}
++
++/* The BO field in a B form instruction when the + or - modifier is
++ used. This is like the BO field, but it must be even. When
++ extracting it, we force it to be even. */
++
++static unsigned long
++insert_boe (unsigned long insn,
++ long value,
++ int dialect,
++ const char **errmsg)
++{
++ if (!valid_bo (value, dialect))
++ *errmsg = _("invalid conditional option");
++ else if ((value & 1) != 0)
++ *errmsg = _("attempt to set y bit when using + or - modifier");
++
++ return insn | ((value & 0x1f) << 21);
++}
++
++static long
++extract_boe (unsigned long insn,
++ int dialect,
++ int *invalid)
++{
++ long value;
++
++ value = (insn >> 21) & 0x1f;
++ if (!valid_bo (value, dialect))
++ *invalid = 1;
++ return value & 0x1e;
++}
++
++/* The DQ field in a DQ form instruction. This is like D, but the
++ lower four bits are forced to zero. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_dq (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 0xf) != 0)
++ *errmsg = _("offset not a multiple of 16");
++ return insn | (value & 0xfff0);
++}
++
++/*ARGSUSED*/
++static long
++extract_dq (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return ((insn & 0xfff0) ^ 0x8000) - 0x8000;
++}
++
++static unsigned long
++insert_ev2 (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 1) != 0)
++ *errmsg = _("offset not a multiple of 2");
++ if ((value > 62) != 0)
++ *errmsg = _("offset greater than 62");
++ return insn | ((value & 0x3e) << 10);
++}
++
++static long
++extract_ev2 (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return (insn >> 10) & 0x3e;
++}
++
++static unsigned long
++insert_ev4 (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 3) != 0)
++ *errmsg = _("offset not a multiple of 4");
++ if ((value > 124) != 0)
++ *errmsg = _("offset greater than 124");
++ return insn | ((value & 0x7c) << 9);
++}
++
++static long
++extract_ev4 (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return (insn >> 9) & 0x7c;
++}
++
++static unsigned long
++insert_ev8 (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 7) != 0)
++ *errmsg = _("offset not a multiple of 8");
++ if ((value > 248) != 0)
++ *errmsg = _("offset greater than 248");
++ return insn | ((value & 0xf8) << 8);
++}
++
++static long
++extract_ev8 (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return (insn >> 8) & 0xf8;
++}
++
++/* The DS field in a DS form instruction. This is like D, but the
++ lower two bits are forced to zero. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_ds (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 3) != 0)
++ *errmsg = _("offset not a multiple of 4");
++ return insn | (value & 0xfffc);
++}
++
++/*ARGSUSED*/
++static long
++extract_ds (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
++}
++
++/* The DE field in a DE form instruction. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_de (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if (value > 2047 || value < -2048)
++ *errmsg = _("offset not between -2048 and 2047");
++ return insn | ((value << 4) & 0xfff0);
++}
++
++/*ARGSUSED*/
++static long
++extract_de (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return (insn & 0xfff0) >> 4;
++}
++
++/* The DES field in a DES form instruction. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_des (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if (value > 8191 || value < -8192)
++ *errmsg = _("offset not between -8192 and 8191");
++ else if ((value & 3) != 0)
++ *errmsg = _("offset not a multiple of 4");
++ return insn | ((value << 2) & 0xfff0);
++}
++
++/*ARGSUSED*/
++static long
++extract_des (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return (((insn >> 2) & 0x3ffc) ^ 0x2000) - 0x2000;
++}
++
++/* FXM mask in mfcr and mtcrf instructions. */
++
++static unsigned long
++insert_fxm (unsigned long insn,
++ long value,
++ int dialect,
++ const char **errmsg)
++{
++ /* If the optional field on mfcr is missing that means we want to use
++ the old form of the instruction that moves the whole cr. In that
++ case we'll have VALUE zero. There doesn't seem to be a way to
++ distinguish this from the case where someone writes mfcr %r3,0. */
++ if (value == 0)
++ ;
++
++ /* If only one bit of the FXM field is set, we can use the new form
++ of the instruction, which is faster. Unlike the Power4 branch hint
++ encoding, this is not backward compatible. */
++ else if ((dialect & PPC_OPCODE_POWER4) != 0 && (value & -value) == value)
++ insn |= 1 << 20;
++
++ /* Any other value on mfcr is an error. */
++ else if ((insn & (0x3ff << 1)) == 19 << 1)
++ {
++ *errmsg = _("ignoring invalid mfcr mask");
++ value = 0;
++ }
++
++ return insn | ((value & 0xff) << 12);
++}
++
++static long
++extract_fxm (unsigned long insn,
++ int dialect,
++ int *invalid)
++{
++ long mask = (insn >> 12) & 0xff;
++
++ /* Is this a Power4 insn? */
++ if ((insn & (1 << 20)) != 0)
++ {
++ if ((dialect & PPC_OPCODE_POWER4) == 0)
++ *invalid = 1;
++ else
++ {
++ /* Exactly one bit of MASK should be set. */
++ if (mask == 0 || (mask & -mask) != mask)
++ *invalid = 1;
++ }
++ }
++
++ /* Check that non-power4 form of mfcr has a zero MASK. */
++ else if ((insn & (0x3ff << 1)) == 19 << 1)
++ {
++ if (mask != 0)
++ *invalid = 1;
++ }
++
++ return mask;
++}
++
++/* The LI field in an I form instruction. The lower two bits are
++ forced to zero. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_li (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 3) != 0)
++ *errmsg = _("ignoring least significant bits in branch offset");
++ return insn | (value & 0x3fffffc);
++}
++
++/*ARGSUSED*/
++static long
++extract_li (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return ((insn & 0x3fffffc) ^ 0x2000000) - 0x2000000;
++}
++
++/* The MB and ME fields in an M form instruction expressed as a single
++ operand which is itself a bitmask. The extraction function always
++ marks it as invalid, since we never want to recognize an
++ instruction which uses a field of this type. */
++
++static unsigned long
++insert_mbe (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ unsigned long uval, mask;
++ int mb, me, mx, count, last;
++
++ uval = value;
++
++ if (uval == 0)
++ {
++ *errmsg = _("illegal bitmask");
++ return insn;
++ }
++
++ mb = 0;
++ me = 32;
++ if ((uval & 1) != 0)
++ last = 1;
++ else
++ last = 0;
++ count = 0;
++
++ /* mb: location of last 0->1 transition */
++ /* me: location of last 1->0 transition */
++ /* count: # transitions */
++
++ for (mx = 0, mask = 1L << 31; mx < 32; ++mx, mask >>= 1)
++ {
++ if ((uval & mask) && !last)
++ {
++ ++count;
++ mb = mx;
++ last = 1;
++ }
++ else if (!(uval & mask) && last)
++ {
++ ++count;
++ me = mx;
++ last = 0;
++ }
++ }
++ if (me == 0)
++ me = 32;
++
++ if (count != 2 && (count != 0 || ! last))
++ *errmsg = _("illegal bitmask");
++
++ return insn | (mb << 6) | ((me - 1) << 1);
++}
++
++static long
++extract_mbe (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid)
++{
++ long ret;
++ int mb, me;
++ int i;
++
++ *invalid = 1;
++
++ mb = (insn >> 6) & 0x1f;
++ me = (insn >> 1) & 0x1f;
++ if (mb < me + 1)
++ {
++ ret = 0;
++ for (i = mb; i <= me; i++)
++ ret |= 1L << (31 - i);
++ }
++ else if (mb == me + 1)
++ ret = ~0;
++ else /* (mb > me + 1) */
++ {
++ ret = ~0;
++ for (i = me + 1; i < mb; i++)
++ ret &= ~(1L << (31 - i));
++ }
++ return ret;
++}
++
++/* The MB or ME field in an MD or MDS form instruction. The high bit
++ is wrapped to the low end. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_mb6 (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | ((value & 0x1f) << 6) | (value & 0x20);
++}
++
++/*ARGSUSED*/
++static long
++extract_mb6 (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return ((insn >> 6) & 0x1f) | (insn & 0x20);
++}
++
++/* The NB field in an X form instruction. The value 32 is stored as
++ 0. */
++
++static unsigned long
++insert_nb (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if (value < 0 || value > 32)
++ *errmsg = _("value out of range");
++ if (value == 32)
++ value = 0;
++ return insn | ((value & 0x1f) << 11);
++}
++
++/*ARGSUSED*/
++static long
++extract_nb (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ long ret;
++
++ ret = (insn >> 11) & 0x1f;
++ if (ret == 0)
++ ret = 32;
++ return ret;
++}
++
++/* The NSI field in a D form instruction. This is the same as the SI
++ field, only negated. The extraction function always marks it as
++ invalid, since we never want to recognize an instruction which uses
++ a field of this type. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_nsi (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | (-value & 0xffff);
++}
++
++static long
++extract_nsi (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid)
++{
++ *invalid = 1;
++ return -(((insn & 0xffff) ^ 0x8000) - 0x8000);
++}
++
++/* The RA field in a D or X form instruction which is an updating
++ load, which means that the RA field may not be zero and may not
++ equal the RT field. */
++
++static unsigned long
++insert_ral (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if (value == 0
++ || (unsigned long) value == ((insn >> 21) & 0x1f))
++ *errmsg = "invalid register operand when updating";
++ return insn | ((value & 0x1f) << 16);
++}
++
++/* The RA field in an lmw instruction, which has special value
++ restrictions. */
++
++static unsigned long
++insert_ram (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((unsigned long) value >= ((insn >> 21) & 0x1f))
++ *errmsg = _("index register in load range");
++ return insn | ((value & 0x1f) << 16);
++}
++
++/* The RA field in the DQ form lq instruction, which has special
++ value restrictions. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_raq (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ long rtvalue = (insn & RT_MASK) >> 21;
++
++ if (value == rtvalue)
++ *errmsg = _("source and target register operands must be different");
++ return insn | ((value & 0x1f) << 16);
++}
++
++/* The RA field in a D or X form instruction which is an updating
++ store or an updating floating point load, which means that the RA
++ field may not be zero. */
++
++static unsigned long
++insert_ras (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if (value == 0)
++ *errmsg = _("invalid register operand when updating");
++ return insn | ((value & 0x1f) << 16);
++}
++
++/* The RB field in an X form instruction when it must be the same as
++ the RS field in the instruction. This is used for extended
++ mnemonics like mr. This operand is marked FAKE. The insertion
++ function just copies the BT field into the BA field, and the
++ extraction function just checks that the fields are the same. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_rbs (unsigned long insn,
++ long value ATTRIBUTE_UNUSED,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | (((insn >> 21) & 0x1f) << 11);
++}
++
++static long
++extract_rbs (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid)
++{
++ if (((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f))
++ *invalid = 1;
++ return 0;
++}
++
++/* The RT field of the DQ form lq instruction, which has special
++ value restrictions. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_rtq (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 1) != 0)
++ *errmsg = _("target register operand must be even");
++ return insn | ((value & 0x1f) << 21);
++}
++
++/* The RS field of the DS form stq instruction, which has special
++ value restrictions. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_rsq (unsigned long insn,
++ long value ATTRIBUTE_UNUSED,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg)
++{
++ if ((value & 1) != 0)
++ *errmsg = _("source register operand must be even");
++ return insn | ((value & 0x1f) << 21);
++}
++
++/* The SH field in an MD form instruction. This is split. */
++
++/*ARGSUSED*/
++static unsigned long
++insert_sh6 (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
++}
++
++/*ARGSUSED*/
++static long
++extract_sh6 (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
++}
++
++/* The SPR field in an XFX form instruction. This is flipped--the
++ lower 5 bits are stored in the upper 5 and vice- versa. */
++
++static unsigned long
++insert_spr (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
++}
++
++static long
++extract_spr (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
++}
++
++/* The TBR field in an XFX instruction. This is just like SPR, but it
++ is optional. When TBR is omitted, it must be inserted as 268 (the
++ magic number of the TB register). These functions treat 0
++ (indicating an omitted optional operand) as 268. This means that
++ ``mftb 4,0'' is not handled correctly. This does not matter very
++ much, since the architecture manual does not define mftb as
++ accepting any values other than 268 or 269. */
++
++#define TB (268)
++
++static unsigned long
++insert_tbr (unsigned long insn,
++ long value,
++ int dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ if (value == 0)
++ value = TB;
++ return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
++}
++
++static long
++extract_tbr (unsigned long insn,
++ int dialect ATTRIBUTE_UNUSED,
++ int *invalid ATTRIBUTE_UNUSED)
++{
++ long ret;
++
++ ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
++ if (ret == TB)
++ ret = 0;
++ return ret;
++}
++
++/* Macros used to form opcodes. */
++
++/* The main opcode. */
++#define OP(x) ((((unsigned long)(x)) & 0x3f) << 26)
++#define OP_MASK OP (0x3f)
++
++/* The main opcode combined with a trap code in the TO field of a D
++ form instruction. Used for extended mnemonics for the trap
++ instructions. */
++#define OPTO(x,to) (OP (x) | ((((unsigned long)(to)) & 0x1f) << 21))
++#define OPTO_MASK (OP_MASK | TO_MASK)
++
++/* The main opcode combined with a comparison size bit in the L field
++ of a D form or X form instruction. Used for extended mnemonics for
++ the comparison instructions. */
++#define OPL(x,l) (OP (x) | ((((unsigned long)(l)) & 1) << 21))
++#define OPL_MASK OPL (0x3f,1)
++
++/* An A form instruction. */
++#define A(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1) | (((unsigned long)(rc)) & 1))
++#define A_MASK A (0x3f, 0x1f, 1)
++
++/* An A_MASK with the FRB field fixed. */
++#define AFRB_MASK (A_MASK | FRB_MASK)
++
++/* An A_MASK with the FRC field fixed. */
++#define AFRC_MASK (A_MASK | FRC_MASK)
++
++/* An A_MASK with the FRA and FRC fields fixed. */
++#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK)
++
++/* A B form instruction. */
++#define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1))
++#define B_MASK B (0x3f, 1, 1)
++
++/* A B form instruction setting the BO field. */
++#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21))
++#define BBO_MASK BBO (0x3f, 0x1f, 1, 1)
++
++/* A BBO_MASK with the y bit of the BO field removed. This permits
++ matching a conditional branch regardless of the setting of the y
++ bit. Similarly for the 'at' bits used for power4 branch hints. */
++#define Y_MASK (((unsigned long) 1) << 21)
++#define AT1_MASK (((unsigned long) 3) << 21)
++#define AT2_MASK (((unsigned long) 9) << 21)
++#define BBOY_MASK (BBO_MASK &~ Y_MASK)
++#define BBOAT_MASK (BBO_MASK &~ AT1_MASK)
++
++/* A B form instruction setting the BO field and the condition bits of
++ the BI field. */
++#define BBOCB(op, bo, cb, aa, lk) \
++ (BBO ((op), (bo), (aa), (lk)) | ((((unsigned long)(cb)) & 0x3) << 16))
++#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1)
++
++/* A BBOCB_MASK with the y bit of the BO field removed. */
++#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK)
++#define BBOATCB_MASK (BBOCB_MASK &~ AT1_MASK)
++#define BBOAT2CB_MASK (BBOCB_MASK &~ AT2_MASK)
++
++/* A BBOYCB_MASK in which the BI field is fixed. */
++#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK)
++#define BBOATBI_MASK (BBOAT2CB_MASK | BI_MASK)
++
++/* An Context form instruction. */
++#define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7))
++#define CTX_MASK CTX(0x3f, 0x7)
++
++/* An User Context form instruction. */
++#define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f))
++#define UCTX_MASK UCTX(0x3f, 0x1f)
++
++/* The main opcode mask with the RA field clear. */
++#define DRA_MASK (OP_MASK | RA_MASK)
++
++/* A DS form instruction. */
++#define DSO(op, xop) (OP (op) | ((xop) & 0x3))
++#define DS_MASK DSO (0x3f, 3)
++
++/* A DE form instruction. */
++#define DEO(op, xop) (OP (op) | ((xop) & 0xf))
++#define DE_MASK DEO (0x3e, 0xf)
++
++/* An EVSEL form instruction. */
++#define EVSEL(op, xop) (OP (op) | (((unsigned long)(xop)) & 0xff) << 3)
++#define EVSEL_MASK EVSEL(0x3f, 0xff)
++
++/* An M form instruction. */
++#define M(op, rc) (OP (op) | ((rc) & 1))
++#define M_MASK M (0x3f, 1)
++
++/* An M form instruction with the ME field specified. */
++#define MME(op, me, rc) (M ((op), (rc)) | ((((unsigned long)(me)) & 0x1f) << 1))
++
++/* An M_MASK with the MB and ME fields fixed. */
++#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK)
++
++/* An M_MASK with the SH and ME fields fixed. */
++#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK)
++
++/* An MD form instruction. */
++#define MD(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x7) << 2) | ((rc) & 1))
++#define MD_MASK MD (0x3f, 0x7, 1)
++
++/* An MD_MASK with the MB field fixed. */
++#define MDMB_MASK (MD_MASK | MB6_MASK)
++
++/* An MD_MASK with the SH field fixed. */
++#define MDSH_MASK (MD_MASK | SH6_MASK)
++
++/* An MDS form instruction. */
++#define MDS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0xf) << 1) | ((rc) & 1))
++#define MDS_MASK MDS (0x3f, 0xf, 1)
++
++/* An MDS_MASK with the MB field fixed. */
++#define MDSMB_MASK (MDS_MASK | MB6_MASK)
++
++/* An SC form instruction. */
++#define SC(op, sa, lk) (OP (op) | ((((unsigned long)(sa)) & 1) << 1) | ((lk) & 1))
++#define SC_MASK (OP_MASK | (((unsigned long)0x3ff) << 16) | (((unsigned long)1) << 1) | 1)
++
++/* An VX form instruction. */
++#define VX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7ff))
++
++/* The mask for an VX form instruction. */
++#define VX_MASK VX(0x3f, 0x7ff)
++
++/* An VA form instruction. */
++#define VXA(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x03f))
++
++/* The mask for an VA form instruction. */
++#define VXA_MASK VXA(0x3f, 0x3f)
++
++/* An VXR form instruction. */
++#define VXR(op, xop, rc) (OP (op) | (((rc) & 1) << 10) | (((unsigned long)(xop)) & 0x3ff))
++
++/* The mask for a VXR form instruction. */
++#define VXR_MASK VXR(0x3f, 0x3ff, 1)
++
++/* An X form instruction. */
++#define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1))
++
++/* An X form instruction with the RC bit specified. */
++#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
++
++/* The mask for an X form instruction. */
++#define X_MASK XRC (0x3f, 0x3ff, 1)
++
++/* An X_MASK with the RA field fixed. */
++#define XRA_MASK (X_MASK | RA_MASK)
++
++/* An X_MASK with the RB field fixed. */
++#define XRB_MASK (X_MASK | RB_MASK)
++
++/* An X_MASK with the RT field fixed. */
++#define XRT_MASK (X_MASK | RT_MASK)
++
++/* An X_MASK with the RA and RB fields fixed. */
++#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
++
++/* An XRARB_MASK, but with the L bit clear. */
++#define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16))
++
++/* An X_MASK with the RT and RA fields fixed. */
++#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK)
++
++/* An XRTRA_MASK, but with L bit clear. */
++#define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21))
++
++/* An X form comparison instruction. */
++#define XCMPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21))
++
++/* The mask for an X form comparison instruction. */
++#define XCMP_MASK (X_MASK | (((unsigned long)1) << 22))
++
++/* The mask for an X form comparison instruction with the L field
++ fixed. */
++#define XCMPL_MASK (XCMP_MASK | (((unsigned long)1) << 21))
++
++/* An X form trap instruction with the TO field specified. */
++#define XTO(op, xop, to) (X ((op), (xop)) | ((((unsigned long)(to)) & 0x1f) << 21))
++#define XTO_MASK (X_MASK | TO_MASK)
++
++/* An X form tlb instruction with the SH field specified. */
++#define XTLB(op, xop, sh) (X ((op), (xop)) | ((((unsigned long)(sh)) & 0x1f) << 11))
++#define XTLB_MASK (X_MASK | SH_MASK)
++
++/* An X form sync instruction. */
++#define XSYNC(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 3) << 21))
++
++/* An X form sync instruction with everything filled in except the LS field. */
++#define XSYNC_MASK (0xff9fffff)
++
++/* An X form AltiVec dss instruction. */
++#define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25))
++#define XDSS_MASK XDSS(0x3f, 0x3ff, 1)
++
++/* An XFL form instruction. */
++#define XFL(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1) | (((unsigned long)(rc)) & 1))
++#define XFL_MASK (XFL (0x3f, 0x3ff, 1) | (((unsigned long)1) << 25) | (((unsigned long)1) << 16))
++
++/* An X form isel instruction. */
++#define XISEL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1))
++#define XISEL_MASK XISEL(0x3f, 0x1f)
++
++/* An XL form instruction with the LK field set to 0. */
++#define XL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1))
++
++/* An XL form instruction which uses the LK field. */
++#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1))
++
++/* The mask for an XL form instruction. */
++#define XL_MASK XLLK (0x3f, 0x3ff, 1)
++
++/* An XL form instruction which explicitly sets the BO field. */
++#define XLO(op, bo, xop, lk) \
++ (XLLK ((op), (xop), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21))
++#define XLO_MASK (XL_MASK | BO_MASK)
++
++/* An XL form instruction which explicitly sets the y bit of the BO
++ field. */
++#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | ((((unsigned long)(y)) & 1) << 21))
++#define XLYLK_MASK (XL_MASK | Y_MASK)
++
++/* An XL form instruction which sets the BO field and the condition
++ bits of the BI field. */
++#define XLOCB(op, bo, cb, xop, lk) \
++ (XLO ((op), (bo), (xop), (lk)) | ((((unsigned long)(cb)) & 3) << 16))
++#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1)
++
++/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed. */
++#define XLBB_MASK (XL_MASK | BB_MASK)
++#define XLYBB_MASK (XLYLK_MASK | BB_MASK)
++#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK)
++
++/* An XL_MASK with the BO and BB fields fixed. */
++#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK)
++
++/* An XL_MASK with the BO, BI and BB fields fixed. */
++#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK)
++
++/* An XO form instruction. */
++#define XO(op, xop, oe, rc) \
++ (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1) | ((((unsigned long)(oe)) & 1) << 10) | (((unsigned long)(rc)) & 1))
++#define XO_MASK XO (0x3f, 0x1ff, 1, 1)
++
++/* An XO_MASK with the RB field fixed. */
++#define XORB_MASK (XO_MASK | RB_MASK)
++
++/* An XS form instruction. */
++#define XS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 2) | (((unsigned long)(rc)) & 1))
++#define XS_MASK XS (0x3f, 0x1ff, 1)
++
++/* A mask for the FXM version of an XFX form instruction. */
++#define XFXFXM_MASK (X_MASK | (1 << 11))
++
++/* An XFX form instruction with the FXM field filled in. */
++#define XFXM(op, xop, fxm) \
++ (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12))
++
++/* An XFX form instruction with the SPR field filled in. */
++#define XSPR(op, xop, spr) \
++ (X ((op), (xop)) | ((((unsigned long)(spr)) & 0x1f) << 16) | ((((unsigned long)(spr)) & 0x3e0) << 6))
++#define XSPR_MASK (X_MASK | SPR_MASK)
++
++/* An XFX form instruction with the SPR field filled in except for the
++ SPRBAT field. */
++#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK)
++
++/* An XFX form instruction with the SPR field filled in except for the
++ SPRG field. */
++#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK)
++
++/* An X form instruction with everything filled in except the E field. */
++#define XE_MASK (0xffff7fff)
++
++/* An X form user context instruction. */
++#define XUC(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f))
++#define XUC_MASK XUC(0x3f, 0x1f)
++
++/* The BO encodings used in extended conditional branch mnemonics. */
++#define BODNZF (0x0)
++#define BODNZFP (0x1)
++#define BODZF (0x2)
++#define BODZFP (0x3)
++#define BODNZT (0x8)
++#define BODNZTP (0x9)
++#define BODZT (0xa)
++#define BODZTP (0xb)
++
++#define BOF (0x4)
++#define BOFP (0x5)
++#define BOFM4 (0x6)
++#define BOFP4 (0x7)
++#define BOT (0xc)
++#define BOTP (0xd)
++#define BOTM4 (0xe)
++#define BOTP4 (0xf)
++
++#define BODNZ (0x10)
++#define BODNZP (0x11)
++#define BODZ (0x12)
++#define BODZP (0x13)
++#define BODNZM4 (0x18)
++#define BODNZP4 (0x19)
++#define BODZM4 (0x1a)
++#define BODZP4 (0x1b)
++
++#define BOU (0x14)
++
++/* The BI condition bit encodings used in extended conditional branch
++ mnemonics. */
++#define CBLT (0)
++#define CBGT (1)
++#define CBEQ (2)
++#define CBSO (3)
++
++/* The TO encodings used in extended trap mnemonics. */
++#define TOLGT (0x1)
++#define TOLLT (0x2)
++#define TOEQ (0x4)
++#define TOLGE (0x5)
++#define TOLNL (0x5)
++#define TOLLE (0x6)
++#define TOLNG (0x6)
++#define TOGT (0x8)
++#define TOGE (0xc)
++#define TONL (0xc)
++#define TOLT (0x10)
++#define TOLE (0x14)
++#define TONG (0x14)
++#define TONE (0x18)
++#define TOU (0x1f)
++
++/* Smaller names for the flags so each entry in the opcodes table will
++ fit on a single line. */
++#undef PPC
++#define PPC PPC_OPCODE_PPC
++#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON
++#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM
++#define POWER4 PPC_OPCODE_POWER4
++#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC
++#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC
++#define PPC403 PPC_OPCODE_403
++#define PPC405 PPC403
++#define PPC440 PPC_OPCODE_440
++#define PPC750 PPC
++#define PPC860 PPC
++#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_PPC
++#define POWER PPC_OPCODE_POWER
++#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2
++#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2
++#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_32
++#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON
++#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_32
++#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601
++#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON
++#define MFDEC1 PPC_OPCODE_POWER
++#define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE
++#define BOOKE PPC_OPCODE_BOOKE
++#define BOOKE64 PPC_OPCODE_BOOKE64
++#define CLASSIC PPC_OPCODE_CLASSIC
++#define PPCSPE PPC_OPCODE_SPE
++#define PPCISEL PPC_OPCODE_ISEL
++#define PPCEFS PPC_OPCODE_EFS
++#define PPCBRLK PPC_OPCODE_BRLOCK
++#define PPCPMR PPC_OPCODE_PMR
++#define PPCCHLK PPC_OPCODE_CACHELCK
++#define PPCCHLK64 PPC_OPCODE_CACHELCK | PPC_OPCODE_BOOKE64
++#define PPCRFMCI PPC_OPCODE_RFMCI
++
++/* The opcode table.
++
++ The format of the opcode table is:
++
++ NAME OPCODE MASK FLAGS { OPERANDS }
++
++ NAME is the name of the instruction.
++ OPCODE is the instruction opcode.
++ MASK is the opcode mask; this is used to tell the disassembler
++ which bits in the actual opcode must match OPCODE.
++ FLAGS are flags indicated what processors support the instruction.
++ OPERANDS is the list of operands.
++
++ The disassembler reads the table in order and prints the first
++ instruction which matches, so this table is sorted to put more
++ specific instructions before more general instructions. It is also
++ sorted by major opcode. */
++
++const struct powerpc_opcode powerpc_opcodes[] = {
++{ "attn", X(0,256), X_MASK, POWER4, { 0 } },
++{ "tdlgti", OPTO(2,TOLGT), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdllti", OPTO(2,TOLLT), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdeqi", OPTO(2,TOEQ), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdlgei", OPTO(2,TOLGE), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdlnli", OPTO(2,TOLNL), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdllei", OPTO(2,TOLLE), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdlngi", OPTO(2,TOLNG), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdgti", OPTO(2,TOGT), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdgei", OPTO(2,TOGE), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdnli", OPTO(2,TONL), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdlti", OPTO(2,TOLT), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdlei", OPTO(2,TOLE), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdngi", OPTO(2,TONG), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdnei", OPTO(2,TONE), OPTO_MASK, PPC64, { RA, SI } },
++{ "tdi", OP(2), OP_MASK, PPC64, { TO, RA, SI } },
++
++{ "twlgti", OPTO(3,TOLGT), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tlgti", OPTO(3,TOLGT), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twllti", OPTO(3,TOLLT), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tllti", OPTO(3,TOLLT), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "tweqi", OPTO(3,TOEQ), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "teqi", OPTO(3,TOEQ), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twlgei", OPTO(3,TOLGE), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tlgei", OPTO(3,TOLGE), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twlnli", OPTO(3,TOLNL), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tlnli", OPTO(3,TOLNL), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twllei", OPTO(3,TOLLE), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tllei", OPTO(3,TOLLE), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twlngi", OPTO(3,TOLNG), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tlngi", OPTO(3,TOLNG), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twgti", OPTO(3,TOGT), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tgti", OPTO(3,TOGT), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twgei", OPTO(3,TOGE), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tgei", OPTO(3,TOGE), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twnli", OPTO(3,TONL), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tnli", OPTO(3,TONL), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twlti", OPTO(3,TOLT), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tlti", OPTO(3,TOLT), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twlei", OPTO(3,TOLE), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tlei", OPTO(3,TOLE), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twngi", OPTO(3,TONG), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tngi", OPTO(3,TONG), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twnei", OPTO(3,TONE), OPTO_MASK, PPCCOM, { RA, SI } },
++{ "tnei", OPTO(3,TONE), OPTO_MASK, PWRCOM, { RA, SI } },
++{ "twi", OP(3), OP_MASK, PPCCOM, { TO, RA, SI } },
++{ "ti", OP(3), OP_MASK, PWRCOM, { TO, RA, SI } },
++
++{ "macchw", XO(4,172,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchw.", XO(4,172,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwo", XO(4,172,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwo.", XO(4,172,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchws", XO(4,236,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchws.", XO(4,236,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwso", XO(4,236,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwso.", XO(4,236,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwsu", XO(4,204,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwsu.", XO(4,204,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwsuo", XO(4,204,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwsuo.", XO(4,204,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwu", XO(4,140,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwu.", XO(4,140,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwuo", XO(4,140,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "macchwuo.", XO(4,140,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhw", XO(4,44,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhw.", XO(4,44,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwo", XO(4,44,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwo.", XO(4,44,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhws", XO(4,108,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhws.", XO(4,108,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwso", XO(4,108,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwso.", XO(4,108,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwsu", XO(4,76,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwsu.", XO(4,76,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwsuo", XO(4,76,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwsuo.", XO(4,76,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwu", XO(4,12,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwu.", XO(4,12,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwuo", XO(4,12,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "machhwuo.", XO(4,12,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhw", XO(4,428,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhw.", XO(4,428,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwo", XO(4,428,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwo.", XO(4,428,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhws", XO(4,492,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhws.", XO(4,492,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwso", XO(4,492,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwso.", XO(4,492,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwsu", XO(4,460,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwsu.", XO(4,460,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwsuo", XO(4,460,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwsuo.", XO(4,460,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwu", XO(4,396,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwu.", XO(4,396,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwuo", XO(4,396,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "maclhwuo.", XO(4,396,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulchw", XRC(4,168,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulchw.", XRC(4,168,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulchwu", XRC(4,136,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulchwu.", XRC(4,136,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulhhw", XRC(4,40,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulhhw.", XRC(4,40,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulhhwu", XRC(4,8,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mulhhwu.", XRC(4,8,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mullhw", XRC(4,424,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mullhw.", XRC(4,424,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mullhwu", XRC(4,392,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mullhwu.", XRC(4,392,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchw", XO(4,174,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchw.", XO(4,174,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchwo", XO(4,174,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchwo.", XO(4,174,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchws", XO(4,238,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchws.", XO(4,238,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchwso", XO(4,238,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmacchwso.", XO(4,238,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhw", XO(4,46,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhw.", XO(4,46,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhwo", XO(4,46,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhwo.", XO(4,46,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhws", XO(4,110,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhws.", XO(4,110,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhwso", XO(4,110,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmachhwso.", XO(4,110,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhw", XO(4,430,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhw.", XO(4,430,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhwo", XO(4,430,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhwo.", XO(4,430,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhws", XO(4,494,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhws.", XO(4,494,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhwso", XO(4,494,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
++{ "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } },
++{ "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } },
++{ "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vaddshs", VX(4, 832), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vaddsws", VX(4, 896), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vaddubm", VX(4, 0), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vaddubs", VX(4, 512), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vadduhm", VX(4, 64), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vadduhs", VX(4, 576), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vadduwm", VX(4, 128), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vadduws", VX(4, 640), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vand", VX(4, 1028), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vandc", VX(4, 1092), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vavgsb", VX(4, 1282), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vavgsh", VX(4, 1346), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vavgsw", VX(4, 1410), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vavgub", VX(4, 1026), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vavguh", VX(4, 1090), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vavguw", VX(4, 1154), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcfsx", VX(4, 842), VX_MASK, PPCVEC, { VD, VB, UIMM } },
++{ "vcfux", VX(4, 778), VX_MASK, PPCVEC, { VD, VB, UIMM } },
++{ "vcmpbfp", VXR(4, 966, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpbfp.", VXR(4, 966, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpeqfp", VXR(4, 198, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpeqfp.", VXR(4, 198, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpequb", VXR(4, 6, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpequb.", VXR(4, 6, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpequh", VXR(4, 70, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpequh.", VXR(4, 70, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpequw", VXR(4, 134, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpequw.", VXR(4, 134, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgefp", VXR(4, 454, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgefp.", VXR(4, 454, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtfp", VXR(4, 710, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtfp.", VXR(4, 710, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtsb", VXR(4, 774, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtsb.", VXR(4, 774, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtsh", VXR(4, 838, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtsh.", VXR(4, 838, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtsw", VXR(4, 902, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtsw.", VXR(4, 902, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtub", VXR(4, 518, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtub.", VXR(4, 518, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtuh", VXR(4, 582, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtuh.", VXR(4, 582, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtuw", VXR(4, 646, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vcmpgtuw.", VXR(4, 646, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
++{ "vctsxs", VX(4, 970), VX_MASK, PPCVEC, { VD, VB, UIMM } },
++{ "vctuxs", VX(4, 906), VX_MASK, PPCVEC, { VD, VB, UIMM } },
++{ "vexptefp", VX(4, 394), VX_MASK, PPCVEC, { VD, VB } },
++{ "vlogefp", VX(4, 458), VX_MASK, PPCVEC, { VD, VB } },
++{ "vmaddfp", VXA(4, 46), VXA_MASK, PPCVEC, { VD, VA, VC, VB } },
++{ "vmaxfp", VX(4, 1034), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmaxsb", VX(4, 258), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmaxsh", VX(4, 322), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmaxsw", VX(4, 386), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmaxub", VX(4, 2), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmaxuh", VX(4, 66), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmaxuw", VX(4, 130), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmhaddshs", VXA(4, 32), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmhraddshs", VXA(4, 33), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vminfp", VX(4, 1098), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vminsb", VX(4, 770), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vminsh", VX(4, 834), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vminsw", VX(4, 898), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vminub", VX(4, 514), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vminuh", VX(4, 578), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vminuw", VX(4, 642), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmladduhm", VXA(4, 34), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmrghb", VX(4, 12), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmrghh", VX(4, 76), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmrghw", VX(4, 140), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmrglb", VX(4, 268), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmrglh", VX(4, 332), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmrglw", VX(4, 396), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmsummbm", VXA(4, 37), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmsumshm", VXA(4, 40), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmsumshs", VXA(4, 41), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmsumubm", VXA(4, 36), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmsumuhm", VXA(4, 38), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmsumuhs", VXA(4, 39), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vmulesb", VX(4, 776), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmulesh", VX(4, 840), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmuleub", VX(4, 520), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmuleuh", VX(4, 584), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmulosb", VX(4, 264), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmulosh", VX(4, 328), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmuloub", VX(4, 8), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vmulouh", VX(4, 72), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vnmsubfp", VXA(4, 47), VXA_MASK, PPCVEC, { VD, VA, VC, VB } },
++{ "vnor", VX(4, 1284), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vor", VX(4, 1156), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vperm", VXA(4, 43), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vpkpx", VX(4, 782), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkshss", VX(4, 398), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkshus", VX(4, 270), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkswss", VX(4, 462), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkswus", VX(4, 334), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkuhum", VX(4, 14), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkuhus", VX(4, 142), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkuwum", VX(4, 78), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vpkuwus", VX(4, 206), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vrefp", VX(4, 266), VX_MASK, PPCVEC, { VD, VB } },
++{ "vrfim", VX(4, 714), VX_MASK, PPCVEC, { VD, VB } },
++{ "vrfin", VX(4, 522), VX_MASK, PPCVEC, { VD, VB } },
++{ "vrfip", VX(4, 650), VX_MASK, PPCVEC, { VD, VB } },
++{ "vrfiz", VX(4, 586), VX_MASK, PPCVEC, { VD, VB } },
++{ "vrlb", VX(4, 4), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vrlh", VX(4, 68), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vrlw", VX(4, 132), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vrsqrtefp", VX(4, 330), VX_MASK, PPCVEC, { VD, VB } },
++{ "vsel", VXA(4, 42), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
++{ "vsl", VX(4, 452), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vslb", VX(4, 260), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsldoi", VXA(4, 44), VXA_MASK, PPCVEC, { VD, VA, VB, SHB } },
++{ "vslh", VX(4, 324), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vslo", VX(4, 1036), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vslw", VX(4, 388), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vspltb", VX(4, 524), VX_MASK, PPCVEC, { VD, VB, UIMM } },
++{ "vsplth", VX(4, 588), VX_MASK, PPCVEC, { VD, VB, UIMM } },
++{ "vspltisb", VX(4, 780), VX_MASK, PPCVEC, { VD, SIMM } },
++{ "vspltish", VX(4, 844), VX_MASK, PPCVEC, { VD, SIMM } },
++{ "vspltisw", VX(4, 908), VX_MASK, PPCVEC, { VD, SIMM } },
++{ "vspltw", VX(4, 652), VX_MASK, PPCVEC, { VD, VB, UIMM } },
++{ "vsr", VX(4, 708), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsrab", VX(4, 772), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsrah", VX(4, 836), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsraw", VX(4, 900), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsrb", VX(4, 516), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsrh", VX(4, 580), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsro", VX(4, 1100), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsrw", VX(4, 644), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubcuw", VX(4, 1408), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubfp", VX(4, 74), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubsbs", VX(4, 1792), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubshs", VX(4, 1856), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubsws", VX(4, 1920), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsububm", VX(4, 1024), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsububs", VX(4, 1536), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubuhm", VX(4, 1088), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubuhs", VX(4, 1600), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubuwm", VX(4, 1152), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsubuws", VX(4, 1664), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsumsws", VX(4, 1928), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsum2sws", VX(4, 1672), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsum4sbs", VX(4, 1800), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsum4shs", VX(4, 1608), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vsum4ubs", VX(4, 1544), VX_MASK, PPCVEC, { VD, VA, VB } },
++{ "vupkhpx", VX(4, 846), VX_MASK, PPCVEC, { VD, VB } },
++{ "vupkhsb", VX(4, 526), VX_MASK, PPCVEC, { VD, VB } },
++{ "vupkhsh", VX(4, 590), VX_MASK, PPCVEC, { VD, VB } },
++{ "vupklpx", VX(4, 974), VX_MASK, PPCVEC, { VD, VB } },
++{ "vupklsb", VX(4, 654), VX_MASK, PPCVEC, { VD, VB } },
++{ "vupklsh", VX(4, 718), VX_MASK, PPCVEC, { VD, VB } },
++{ "vxor", VX(4, 1220), VX_MASK, PPCVEC, { VD, VA, VB } },
++
++{ "evaddw", VX(4, 512), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evaddiw", VX(4, 514), VX_MASK, PPCSPE, { RS, RB, UIMM } },
++{ "evsubfw", VX(4, 516), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evsubw", VX(4, 516), VX_MASK, PPCSPE, { RS, RB, RA } },
++{ "evsubifw", VX(4, 518), VX_MASK, PPCSPE, { RS, UIMM, RB } },
++{ "evsubiw", VX(4, 518), VX_MASK, PPCSPE, { RS, RB, UIMM } },
++{ "evabs", VX(4, 520), VX_MASK, PPCSPE, { RS, RA } },
++{ "evneg", VX(4, 521), VX_MASK, PPCSPE, { RS, RA } },
++{ "evextsb", VX(4, 522), VX_MASK, PPCSPE, { RS, RA } },
++{ "evextsh", VX(4, 523), VX_MASK, PPCSPE, { RS, RA } },
++{ "evrndw", VX(4, 524), VX_MASK, PPCSPE, { RS, RA } },
++{ "evcntlzw", VX(4, 525), VX_MASK, PPCSPE, { RS, RA } },
++{ "evcntlsw", VX(4, 526), VX_MASK, PPCSPE, { RS, RA } },
++
++{ "brinc", VX(4, 527), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evand", VX(4, 529), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evandc", VX(4, 530), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmr", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, BBA } },
++{ "evor", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evorc", VX(4, 539), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evxor", VX(4, 534), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "eveqv", VX(4, 537), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evnand", VX(4, 542), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evnot", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, BBA } },
++{ "evnor", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evrlw", VX(4, 552), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evrlwi", VX(4, 554), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
++{ "evslw", VX(4, 548), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evslwi", VX(4, 550), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
++{ "evsrws", VX(4, 545), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evsrwu", VX(4, 544), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evsrwis", VX(4, 547), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
++{ "evsrwiu", VX(4, 546), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
++{ "evsplati", VX(4, 553), VX_MASK, PPCSPE, { RS, SIMM } },
++{ "evsplatfi", VX(4, 555), VX_MASK, PPCSPE, { RS, SIMM } },
++{ "evmergehi", VX(4, 556), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmergelo", VX(4, 557), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmergehilo",VX(4,558), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmergelohi",VX(4,559), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evcmpgts", VX(4, 561), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evcmpgtu", VX(4, 560), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evcmplts", VX(4, 563), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evcmpltu", VX(4, 562), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evcmpeq", VX(4, 564), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evsel", EVSEL(4,79),EVSEL_MASK, PPCSPE, { RS, RA, RB, CRFS } },
++
++{ "evldd", VX(4, 769), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
++{ "evlddx", VX(4, 768), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evldw", VX(4, 771), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
++{ "evldwx", VX(4, 770), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evldh", VX(4, 773), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
++{ "evldhx", VX(4, 772), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlwhe", VX(4, 785), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evlwhex", VX(4, 784), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlwhou", VX(4, 789), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evlwhoux", VX(4, 788), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlwhos", VX(4, 791), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evlwhosx", VX(4, 790), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlwwsplat",VX(4, 793), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evlwwsplatx",VX(4, 792), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlwhsplat",VX(4, 797), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evlwhsplatx",VX(4, 796), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlhhesplat",VX(4, 777), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } },
++{ "evlhhesplatx",VX(4, 776), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlhhousplat",VX(4, 781), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } },
++{ "evlhhousplatx",VX(4, 780), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evlhhossplat",VX(4, 783), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } },
++{ "evlhhossplatx",VX(4, 782), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evstdd", VX(4, 801), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
++{ "evstddx", VX(4, 800), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evstdw", VX(4, 803), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
++{ "evstdwx", VX(4, 802), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evstdh", VX(4, 805), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
++{ "evstdhx", VX(4, 804), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evstwwe", VX(4, 825), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evstwwex", VX(4, 824), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evstwwo", VX(4, 829), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evstwwox", VX(4, 828), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evstwhe", VX(4, 817), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evstwhex", VX(4, 816), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evstwho", VX(4, 821), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
++{ "evstwhox", VX(4, 820), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evfsabs", VX(4, 644), VX_MASK, PPCSPE, { RS, RA } },
++{ "evfsnabs", VX(4, 645), VX_MASK, PPCSPE, { RS, RA } },
++{ "evfsneg", VX(4, 646), VX_MASK, PPCSPE, { RS, RA } },
++{ "evfsadd", VX(4, 640), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evfssub", VX(4, 641), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evfsmul", VX(4, 648), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evfsdiv", VX(4, 649), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evfscmpgt", VX(4, 652), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evfscmplt", VX(4, 653), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evfscmpeq", VX(4, 654), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evfststgt", VX(4, 668), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evfststlt", VX(4, 669), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evfststeq", VX(4, 670), VX_MASK, PPCSPE, { CRFD, RA, RB } },
++{ "evfscfui", VX(4, 656), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfsctuiz", VX(4, 664), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfscfsi", VX(4, 657), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfscfuf", VX(4, 658), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfscfsf", VX(4, 659), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfsctui", VX(4, 660), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfsctsi", VX(4, 661), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfsctsiz", VX(4, 666), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfsctuf", VX(4, 662), VX_MASK, PPCSPE, { RS, RB } },
++{ "evfsctsf", VX(4, 663), VX_MASK, PPCSPE, { RS, RB } },
++
++{ "efsabs", VX(4, 708), VX_MASK, PPCEFS, { RS, RA } },
++{ "efsnabs", VX(4, 709), VX_MASK, PPCEFS, { RS, RA } },
++{ "efsneg", VX(4, 710), VX_MASK, PPCEFS, { RS, RA } },
++{ "efsadd", VX(4, 704), VX_MASK, PPCEFS, { RS, RA, RB } },
++{ "efssub", VX(4, 705), VX_MASK, PPCEFS, { RS, RA, RB } },
++{ "efsmul", VX(4, 712), VX_MASK, PPCEFS, { RS, RA, RB } },
++{ "efsdiv", VX(4, 713), VX_MASK, PPCEFS, { RS, RA, RB } },
++{ "efscmpgt", VX(4, 716), VX_MASK, PPCEFS, { CRFD, RA, RB } },
++{ "efscmplt", VX(4, 717), VX_MASK, PPCEFS, { CRFD, RA, RB } },
++{ "efscmpeq", VX(4, 718), VX_MASK, PPCEFS, { CRFD, RA, RB } },
++{ "efststgt", VX(4, 732), VX_MASK, PPCEFS, { CRFD, RA, RB } },
++{ "efststlt", VX(4, 733), VX_MASK, PPCEFS, { CRFD, RA, RB } },
++{ "efststeq", VX(4, 734), VX_MASK, PPCEFS, { CRFD, RA, RB } },
++{ "efscfui", VX(4, 720), VX_MASK, PPCEFS, { RS, RB } },
++{ "efsctuiz", VX(4, 728), VX_MASK, PPCEFS, { RS, RB } },
++{ "efscfsi", VX(4, 721), VX_MASK, PPCEFS, { RS, RB } },
++{ "efscfuf", VX(4, 722), VX_MASK, PPCEFS, { RS, RB } },
++{ "efscfsf", VX(4, 723), VX_MASK, PPCEFS, { RS, RB } },
++{ "efsctui", VX(4, 724), VX_MASK, PPCEFS, { RS, RB } },
++{ "efsctsi", VX(4, 725), VX_MASK, PPCEFS, { RS, RB } },
++{ "efsctsiz", VX(4, 730), VX_MASK, PPCEFS, { RS, RB } },
++{ "efsctuf", VX(4, 726), VX_MASK, PPCEFS, { RS, RB } },
++{ "efsctsf", VX(4, 727), VX_MASK, PPCEFS, { RS, RB } },
++
++{ "evmhossf", VX(4, 1031), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhossfa", VX(4, 1063), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmf", VX(4, 1039), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmfa", VX(4, 1071), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmi", VX(4, 1037), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmia", VX(4, 1069), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhoumi", VX(4, 1036), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhoumia", VX(4, 1068), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhessf", VX(4, 1027), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhessfa", VX(4, 1059), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmf", VX(4, 1035), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmfa", VX(4, 1067), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmi", VX(4, 1033), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmia", VX(4, 1065), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmheumi", VX(4, 1032), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmheumia", VX(4, 1064), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmhossfaaw",VX(4, 1287), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhossiaaw",VX(4, 1285), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmfaaw",VX(4, 1295), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmiaaw",VX(4, 1293), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhousiaaw",VX(4, 1284), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhoumiaaw",VX(4, 1292), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhessfaaw",VX(4, 1283), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhessiaaw",VX(4, 1281), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmfaaw",VX(4, 1291), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmiaaw",VX(4, 1289), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmheusiaaw",VX(4, 1280), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmheumiaaw",VX(4, 1288), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmhossfanw",VX(4, 1415), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhossianw",VX(4, 1413), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmfanw",VX(4, 1423), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhosmianw",VX(4, 1421), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhousianw",VX(4, 1412), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhoumianw",VX(4, 1420), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhessfanw",VX(4, 1411), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhessianw",VX(4, 1409), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmfanw",VX(4, 1419), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhesmianw",VX(4, 1417), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmheusianw",VX(4, 1408), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmheumianw",VX(4, 1416), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmhogsmfaa",VX(4, 1327), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhogsmiaa",VX(4, 1325), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhogumiaa",VX(4, 1324), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhegsmfaa",VX(4, 1323), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhegsmiaa",VX(4, 1321), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhegumiaa",VX(4, 1320), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmhogsmfan",VX(4, 1455), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhogsmian",VX(4, 1453), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhogumian",VX(4, 1452), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhegsmfan",VX(4, 1451), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhegsmian",VX(4, 1449), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmhegumian",VX(4, 1448), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmwhssf", VX(4, 1095), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwhssfa", VX(4, 1127), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwhsmf", VX(4, 1103), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwhsmfa", VX(4, 1135), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwhsmi", VX(4, 1101), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwhsmia", VX(4, 1133), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwhumi", VX(4, 1100), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwhumia", VX(4, 1132), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmwlumi", VX(4, 1096), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwlumia", VX(4, 1128), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmwlssiaaw",VX(4, 1345), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwlsmiaaw",VX(4, 1353), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwlusiaaw",VX(4, 1344), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwlumiaaw",VX(4, 1352), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmwlssianw",VX(4, 1473), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwlsmianw",VX(4, 1481), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwlusianw",VX(4, 1472), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwlumianw",VX(4, 1480), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmwssf", VX(4, 1107), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwssfa", VX(4, 1139), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmf", VX(4, 1115), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmfa", VX(4, 1147), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmi", VX(4, 1113), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmia", VX(4, 1145), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwumi", VX(4, 1112), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwumia", VX(4, 1144), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmwssfaa", VX(4, 1363), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmfaa", VX(4, 1371), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmiaa", VX(4, 1369), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwumiaa", VX(4, 1368), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evmwssfan", VX(4, 1491), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmfan", VX(4, 1499), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwsmian", VX(4, 1497), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evmwumian", VX(4, 1496), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "evaddssiaaw",VX(4, 1217), VX_MASK, PPCSPE, { RS, RA } },
++{ "evaddsmiaaw",VX(4, 1225), VX_MASK, PPCSPE, { RS, RA } },
++{ "evaddusiaaw",VX(4, 1216), VX_MASK, PPCSPE, { RS, RA } },
++{ "evaddumiaaw",VX(4, 1224), VX_MASK, PPCSPE, { RS, RA } },
++
++{ "evsubfssiaaw",VX(4, 1219), VX_MASK, PPCSPE, { RS, RA } },
++{ "evsubfsmiaaw",VX(4, 1227), VX_MASK, PPCSPE, { RS, RA } },
++{ "evsubfusiaaw",VX(4, 1218), VX_MASK, PPCSPE, { RS, RA } },
++{ "evsubfumiaaw",VX(4, 1226), VX_MASK, PPCSPE, { RS, RA } },
++
++{ "evmra", VX(4, 1220), VX_MASK, PPCSPE, { RS, RA } },
++
++{ "evdivws", VX(4, 1222), VX_MASK, PPCSPE, { RS, RA, RB } },
++{ "evdivwu", VX(4, 1223), VX_MASK, PPCSPE, { RS, RA, RB } },
++
++{ "mulli", OP(7), OP_MASK, PPCCOM, { RT, RA, SI } },
++{ "muli", OP(7), OP_MASK, PWRCOM, { RT, RA, SI } },
++
++{ "subfic", OP(8), OP_MASK, PPCCOM, { RT, RA, SI } },
++{ "sfi", OP(8), OP_MASK, PWRCOM, { RT, RA, SI } },
++
++{ "dozi", OP(9), OP_MASK, M601, { RT, RA, SI } },
++
++{ "bce", B(9,0,0), B_MASK, BOOKE64, { BO, BI, BD } },
++{ "bcel", B(9,0,1), B_MASK, BOOKE64, { BO, BI, BD } },
++{ "bcea", B(9,1,0), B_MASK, BOOKE64, { BO, BI, BDA } },
++{ "bcela", B(9,1,1), B_MASK, BOOKE64, { BO, BI, BDA } },
++
++{ "cmplwi", OPL(10,0), OPL_MASK, PPCCOM, { OBF, RA, UI } },
++{ "cmpldi", OPL(10,1), OPL_MASK, PPC64, { OBF, RA, UI } },
++{ "cmpli", OP(10), OP_MASK, PPC, { BF, L, RA, UI } },
++{ "cmpli", OP(10), OP_MASK, PWRCOM, { BF, RA, UI } },
++
++{ "cmpwi", OPL(11,0), OPL_MASK, PPCCOM, { OBF, RA, SI } },
++{ "cmpdi", OPL(11,1), OPL_MASK, PPC64, { OBF, RA, SI } },
++{ "cmpi", OP(11), OP_MASK, PPC, { BF, L, RA, SI } },
++{ "cmpi", OP(11), OP_MASK, PWRCOM, { BF, RA, SI } },
++
++{ "addic", OP(12), OP_MASK, PPCCOM, { RT, RA, SI } },
++{ "ai", OP(12), OP_MASK, PWRCOM, { RT, RA, SI } },
++{ "subic", OP(12), OP_MASK, PPCCOM, { RT, RA, NSI } },
++
++{ "addic.", OP(13), OP_MASK, PPCCOM, { RT, RA, SI } },
++{ "ai.", OP(13), OP_MASK, PWRCOM, { RT, RA, SI } },
++{ "subic.", OP(13), OP_MASK, PPCCOM, { RT, RA, NSI } },
++
++{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } },
++{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } },
++{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA, SI } },
++{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA } },
++{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA, NSI } },
++{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA } },
++
++{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } },
++{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } },
++{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA,SISIGNOPT } },
++{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA,SISIGNOPT } },
++{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA, NSI } },
++
++{ "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } },
++{ "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } },
++{ "bdnz", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BD } },
++{ "bdn", BBO(16,BODNZ,0,0), BBOATBI_MASK, PWRCOM, { BD } },
++{ "bdnzl-", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } },
++{ "bdnzl+", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } },
++{ "bdnzl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BD } },
++{ "bdnl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PWRCOM, { BD } },
++{ "bdnza-", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } },
++{ "bdnza+", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } },
++{ "bdnza", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDA } },
++{ "bdna", BBO(16,BODNZ,1,0), BBOATBI_MASK, PWRCOM, { BDA } },
++{ "bdnzla-", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } },
++{ "bdnzla+", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } },
++{ "bdnzla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDA } },
++{ "bdnla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PWRCOM, { BDA } },
++{ "bdz-", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } },
++{ "bdz+", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } },
++{ "bdz", BBO(16,BODZ,0,0), BBOATBI_MASK, COM, { BD } },
++{ "bdzl-", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } },
++{ "bdzl+", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } },
++{ "bdzl", BBO(16,BODZ,0,1), BBOATBI_MASK, COM, { BD } },
++{ "bdza-", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } },
++{ "bdza+", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } },
++{ "bdza", BBO(16,BODZ,1,0), BBOATBI_MASK, COM, { BDA } },
++{ "bdzla-", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } },
++{ "bdzla+", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } },
++{ "bdzla", BBO(16,BODZ,1,1), BBOATBI_MASK, COM, { BDA } },
++{ "blt-", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "blt+", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "blt", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bltl-", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bltl+", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bltl", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "blta-", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "blta+", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "blta", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bltla-", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bltla+", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bltla", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bgt-", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bgt+", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bgt", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bgtl-", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bgtl+", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bgtl", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "bgta-", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bgta+", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bgta", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bgtla-", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bgtla+", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bgtla", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "beq-", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "beq+", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "beq", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "beql-", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "beql+", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "beql", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "beqa-", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "beqa+", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "beqa", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "beqla-", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "beqla+", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "beqla", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bso-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bso+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bso", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bsol-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bsol+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bsol", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "bsoa-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bsoa+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bsoa", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bsola-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bsola+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bsola", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bun-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bun+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bun", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } },
++{ "bunl-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bunl+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bunl", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } },
++{ "buna-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "buna+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "buna", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } },
++{ "bunla-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bunla+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bunla", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } },
++{ "bge-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bge+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bge", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bgel-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bgel+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bgel", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "bgea-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bgea+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bgea", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bgela-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bgela+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bgela", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bnl-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bnl+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bnl", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bnll-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bnll+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bnll", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "bnla-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnla+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnla", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bnlla-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnlla+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnlla", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "ble-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "ble+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "ble", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "blel-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "blel+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "blel", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "blea-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "blea+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "blea", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "blela-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "blela+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "blela", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bng-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bng+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bng", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bngl-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bngl+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bngl", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "bnga-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnga+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnga", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bngla-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bngla+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bngla", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bne-", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bne+", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bne", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bnel-", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bnel+", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bnel", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "bnea-", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnea+", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnea", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bnela-", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnela+", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnela", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bns-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bns+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bns", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } },
++{ "bnsl-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bnsl+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bnsl", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } },
++{ "bnsa-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnsa+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnsa", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bnsla-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnsla+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnsla", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } },
++{ "bnu-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bnu+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bnu", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } },
++{ "bnul-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
++{ "bnul+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
++{ "bnul", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } },
++{ "bnua-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnua+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnua", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } },
++{ "bnula-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
++{ "bnula+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
++{ "bnula", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } },
++{ "bdnzt-", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdnzt+", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdnzt", BBO(16,BODNZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdnztl", BBO(16,BODNZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdnzta", BBO(16,BODNZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bdnzf-", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdnzf+", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdnzf", BBO(16,BODNZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdnzfl", BBO(16,BODNZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdnzfa", BBO(16,BODNZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bt-", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } },
++{ "bt+", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } },
++{ "bt", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BD } },
++{ "bbt", BBO(16,BOT,0,0), BBOAT_MASK, PWRCOM, { BI, BD } },
++{ "btl-", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } },
++{ "btl+", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } },
++{ "btl", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BD } },
++{ "bbtl", BBO(16,BOT,0,1), BBOAT_MASK, PWRCOM, { BI, BD } },
++{ "bta-", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } },
++{ "bta+", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } },
++{ "bta", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } },
++{ "bbta", BBO(16,BOT,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } },
++{ "btla-", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } },
++{ "btla+", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } },
++{ "btla", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } },
++{ "bbtla", BBO(16,BOT,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } },
++{ "bf-", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } },
++{ "bf+", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } },
++{ "bf", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BD } },
++{ "bbf", BBO(16,BOF,0,0), BBOAT_MASK, PWRCOM, { BI, BD } },
++{ "bfl-", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } },
++{ "bfl+", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } },
++{ "bfl", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BD } },
++{ "bbfl", BBO(16,BOF,0,1), BBOAT_MASK, PWRCOM, { BI, BD } },
++{ "bfa-", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } },
++{ "bfa+", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } },
++{ "bfa", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } },
++{ "bbfa", BBO(16,BOF,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } },
++{ "bfla-", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } },
++{ "bfla+", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } },
++{ "bfla", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } },
++{ "bbfla", BBO(16,BOF,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } },
++{ "bdzt-", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdzt+", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdzt", BBO(16,BODZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdztl-", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdztl+", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdztl", BBO(16,BODZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdzta-", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdzta+", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdzta", BBO(16,BODZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdztla", BBO(16,BODZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bdzf-", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdzf+", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdzf", BBO(16,BODZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdzfl-", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
++{ "bdzfl+", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
++{ "bdzfl", BBO(16,BODZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
++{ "bdzfa-", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdzfa+", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdzfa", BBO(16,BODZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
++{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
++{ "bdzfla", BBO(16,BODZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
++{ "bc-", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDM } },
++{ "bc+", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDP } },
++{ "bc", B(16,0,0), B_MASK, COM, { BO, BI, BD } },
++{ "bcl-", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDM } },
++{ "bcl+", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDP } },
++{ "bcl", B(16,0,1), B_MASK, COM, { BO, BI, BD } },
++{ "bca-", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDMA } },
++{ "bca+", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDPA } },
++{ "bca", B(16,1,0), B_MASK, COM, { BO, BI, BDA } },
++{ "bcla-", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDMA } },
++{ "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } },
++{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } },
++
++{ "sc", SC(17,1,0), 0xffffffff, PPC, { 0 } },
++{ "svc", SC(17,0,0), SC_MASK, POWER, { LEV, FL1, FL2 } },
++{ "svcl", SC(17,0,1), SC_MASK, POWER, { LEV, FL1, FL2 } },
++{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } },
++{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } },
++
++{ "b", B(18,0,0), B_MASK, COM, { LI } },
++{ "bl", B(18,0,1), B_MASK, COM, { LI } },
++{ "ba", B(18,1,0), B_MASK, COM, { LIA } },
++{ "bla", B(18,1,1), B_MASK, COM, { LIA } },
++
++{ "mcrf", XL(19,0), XLBB_MASK|(3 << 21)|(3 << 16), COM, { BF, BFA } },
++
++{ "blr", XLO(19,BOU,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } },
++{ "br", XLO(19,BOU,16,0), XLBOBIBB_MASK, PWRCOM, { 0 } },
++{ "blrl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } },
++{ "brl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PWRCOM, { 0 } },
++{ "bdnzlr", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } },
++{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdnzlr-", XLO(19,BODNZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdnzlr+", XLO(19,BODNZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } },
++{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdnzlrl-",XLO(19,BODNZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdnzlrl+",XLO(19,BODNZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bdzlr", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } },
++{ "bdzlr-", XLO(19,BODZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdzlr-", XLO(19,BODZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bdzlr+", XLO(19,BODZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdzlr+", XLO(19,BODZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bdzlrl", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } },
++{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdzlrl-", XLO(19,BODZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
++{ "bdzlrl+", XLO(19,BODZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
++{ "bltlr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bltlr-", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltlr-", XLOCB(19,BOTM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bltlr+", XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltlr+", XLOCB(19,BOTP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bltr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bltlrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltlrl-", XLOCB(19,BOTM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltlrl+", XLOCB(19,BOTP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bltrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bgtlr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgtlr-", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtlr-", XLOCB(19,BOTM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtlr+", XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtlr+", XLOCB(19,BOTP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bgtlrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtlrl-", XLOCB(19,BOTM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtlrl+", XLOCB(19,BOTP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "beqlr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "beqlr-", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqlr-", XLOCB(19,BOTM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqlr+", XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqlr+", XLOCB(19,BOTP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "beqlrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqlrl-", XLOCB(19,BOTM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqlrl+", XLOCB(19,BOTP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bsolr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bsolr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsolr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsolr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsolr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsor", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bsolrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsolrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsolrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsorl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bunlr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bunlr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunlr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bunlr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunlr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bunlrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunlrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunlrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgelr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgelr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgelr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgelr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgelr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bger", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bgelrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgelrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgelrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgerl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnllr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnllr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnllr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnllr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnllr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnlr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnllrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnllrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnllrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnlrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "blelr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "blelr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blelr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "blelr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blelr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bler", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "blelrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blelrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blelrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "blerl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnglr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnglr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnglr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnglr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnglr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bngr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnglrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnglrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnglrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bngrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnelr", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnelr-", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnelr-", XLOCB(19,BOFM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnelr+", XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnelr+", XLOCB(19,BOFP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bner", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnelrl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnelrl-", XLOCB(19,BOFM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnelrl+", XLOCB(19,BOFP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnerl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnslr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnslr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnslr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnslr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnslr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnsr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnslrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnslrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnslrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnsrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
++{ "bnulr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnulr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnulr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnulr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnulr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnulrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnulrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnulrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "btlr", XLO(19,BOT,16,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "btlr-", XLO(19,BOT,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btlr-", XLO(19,BOTM4,16,0), XLBOBB_MASK, POWER4, { BI } },
++{ "btlr+", XLO(19,BOTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btlr+", XLO(19,BOTP4,16,0), XLBOBB_MASK, POWER4, { BI } },
++{ "bbtr", XLO(19,BOT,16,0), XLBOBB_MASK, PWRCOM, { BI } },
++{ "btlrl", XLO(19,BOT,16,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "btlrl-", XLO(19,BOT,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btlrl-", XLO(19,BOTM4,16,1), XLBOBB_MASK, POWER4, { BI } },
++{ "btlrl+", XLO(19,BOTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btlrl+", XLO(19,BOTP4,16,1), XLBOBB_MASK, POWER4, { BI } },
++{ "bbtrl", XLO(19,BOT,16,1), XLBOBB_MASK, PWRCOM, { BI } },
++{ "bflr", XLO(19,BOF,16,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bflr-", XLO(19,BOF,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bflr-", XLO(19,BOFM4,16,0), XLBOBB_MASK, POWER4, { BI } },
++{ "bflr+", XLO(19,BOFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bflr+", XLO(19,BOFP4,16,0), XLBOBB_MASK, POWER4, { BI } },
++{ "bbfr", XLO(19,BOF,16,0), XLBOBB_MASK, PWRCOM, { BI } },
++{ "bflrl", XLO(19,BOF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bflrl-", XLO(19,BOF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bflrl-", XLO(19,BOFM4,16,1), XLBOBB_MASK, POWER4, { BI } },
++{ "bflrl+", XLO(19,BOFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bflrl+", XLO(19,BOFP4,16,1), XLBOBB_MASK, POWER4, { BI } },
++{ "bbfrl", XLO(19,BOF,16,1), XLBOBB_MASK, PWRCOM, { BI } },
++{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdztlr", XLO(19,BODZT,16,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdzflr", XLO(19,BODZF,16,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bclr", XLLK(19,16,0), XLYBB_MASK, PPCCOM, { BO, BI } },
++{ "bclrl", XLLK(19,16,1), XLYBB_MASK, PPCCOM, { BO, BI } },
++{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } },
++{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } },
++{ "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } },
++{ "bclrel", XLLK(19,17,1), XLBB_MASK, BOOKE64, { BO, BI } },
++
++{ "rfid", XL(19,18), 0xffffffff, PPC64, { 0 } },
++
++{ "crnot", XL(19,33), XL_MASK, PPCCOM, { BT, BA, BBA } },
++{ "crnor", XL(19,33), XL_MASK, COM, { BT, BA, BB } },
++{ "rfmci", X(19,38), 0xffffffff, PPCRFMCI, { 0 } },
++
++{ "rfi", XL(19,50), 0xffffffff, COM, { 0 } },
++{ "rfci", XL(19,51), 0xffffffff, PPC403 | BOOKE, { 0 } },
++
++{ "rfsvc", XL(19,82), 0xffffffff, POWER, { 0 } },
++
++{ "crandc", XL(19,129), XL_MASK, COM, { BT, BA, BB } },
++
++{ "isync", XL(19,150), 0xffffffff, PPCCOM, { 0 } },
++{ "ics", XL(19,150), 0xffffffff, PWRCOM, { 0 } },
++
++{ "crclr", XL(19,193), XL_MASK, PPCCOM, { BT, BAT, BBA } },
++{ "crxor", XL(19,193), XL_MASK, COM, { BT, BA, BB } },
++
++{ "crnand", XL(19,225), XL_MASK, COM, { BT, BA, BB } },
++
++{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } },
++
++{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } },
++{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } },
++
++{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } },
++
++{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } },
++{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } },
++
++{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } },
++{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } },
++{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltctr-", XLOCB(19,BOTM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltctr+", XLOCB(19,BOTP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltctrl-",XLOCB(19,BOTM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bltctrl+",XLOCB(19,BOTP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtctr", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtctr-", XLOCB(19,BOTM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtctr+", XLOCB(19,BOTP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtctrl-",XLOCB(19,BOTM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgtctrl+",XLOCB(19,BOTP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqctr", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqctr-", XLOCB(19,BOTM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqctr+", XLOCB(19,BOTP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqctrl-",XLOCB(19,BOTM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "beqctrl+",XLOCB(19,BOTP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsoctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsoctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsoctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsoctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bsoctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bunctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bunctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgectr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgectr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgectr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgectrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bgectrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnlctr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnlctr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnlctr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnlctrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnlctrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "blectr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blectr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blectr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blectrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "blectrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bngctr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bngctr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bngctr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bngctrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bngctrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnectr", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnectr-", XLOCB(19,BOFM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnectr+", XLOCB(19,BOFP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnectrl-",XLOCB(19,BOFM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnectrl+",XLOCB(19,BOFP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnsctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnsctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnsctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnsctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnsctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnuctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnuctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnuctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
++{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnuctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
++{ "bnuctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
++{ "btctr", XLO(19,BOT,528,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "btctr-", XLO(19,BOT,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btctr-", XLO(19,BOTM4,528,0), XLBOBB_MASK, POWER4, { BI } },
++{ "btctr+", XLO(19,BOTP,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btctr+", XLO(19,BOTP4,528,0), XLBOBB_MASK, POWER4, { BI } },
++{ "btctrl", XLO(19,BOT,528,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btctrl-", XLO(19,BOTM4,528,1), XLBOBB_MASK, POWER4, { BI } },
++{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "btctrl+", XLO(19,BOTP4,528,1), XLBOBB_MASK, POWER4, { BI } },
++{ "bfctr", XLO(19,BOF,528,0), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bfctr-", XLO(19,BOF,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bfctr-", XLO(19,BOFM4,528,0), XLBOBB_MASK, POWER4, { BI } },
++{ "bfctr+", XLO(19,BOFP,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bfctr+", XLO(19,BOFP4,528,0), XLBOBB_MASK, POWER4, { BI } },
++{ "bfctrl", XLO(19,BOF,528,1), XLBOBB_MASK, PPCCOM, { BI } },
++{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } },
++{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
++{ "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } },
++{ "bcctr", XLLK(19,528,0), XLYBB_MASK, PPCCOM, { BO, BI } },
++{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bcctrl", XLLK(19,528,1), XLYBB_MASK, PPCCOM, { BO, BI } },
++{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
++{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } },
++{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } },
++{ "bcctre", XLLK(19,529,0), XLYBB_MASK, BOOKE64, { BO, BI } },
++{ "bcctrel", XLLK(19,529,1), XLYBB_MASK, BOOKE64, { BO, BI } },
++
++{ "rlwimi", M(20,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
++{ "rlimi", M(20,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
++
++{ "rlwimi.", M(20,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
++{ "rlimi.", M(20,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
++
++{ "rotlwi", MME(21,31,0), MMBME_MASK, PPCCOM, { RA, RS, SH } },
++{ "clrlwi", MME(21,31,0), MSHME_MASK, PPCCOM, { RA, RS, MB } },
++{ "rlwinm", M(21,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
++{ "rlinm", M(21,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
++{ "rotlwi.", MME(21,31,1), MMBME_MASK, PPCCOM, { RA,RS,SH } },
++{ "clrlwi.", MME(21,31,1), MSHME_MASK, PPCCOM, { RA, RS, MB } },
++{ "rlwinm.", M(21,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
++{ "rlinm.", M(21,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
++
++{ "rlmi", M(22,0), M_MASK, M601, { RA,RS,RB,MBE,ME } },
++{ "rlmi.", M(22,1), M_MASK, M601, { RA,RS,RB,MBE,ME } },
++
++{ "be", B(22,0,0), B_MASK, BOOKE64, { LI } },
++{ "bel", B(22,0,1), B_MASK, BOOKE64, { LI } },
++{ "bea", B(22,1,0), B_MASK, BOOKE64, { LIA } },
++{ "bela", B(22,1,1), B_MASK, BOOKE64, { LIA } },
++
++{ "rotlw", MME(23,31,0), MMBME_MASK, PPCCOM, { RA, RS, RB } },
++{ "rlwnm", M(23,0), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } },
++{ "rlnm", M(23,0), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } },
++{ "rotlw.", MME(23,31,1), MMBME_MASK, PPCCOM, { RA, RS, RB } },
++{ "rlwnm.", M(23,1), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } },
++{ "rlnm.", M(23,1), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } },
++
++{ "nop", OP(24), 0xffffffff, PPCCOM, { 0 } },
++{ "ori", OP(24), OP_MASK, PPCCOM, { RA, RS, UI } },
++{ "oril", OP(24), OP_MASK, PWRCOM, { RA, RS, UI } },
++
++{ "oris", OP(25), OP_MASK, PPCCOM, { RA, RS, UI } },
++{ "oriu", OP(25), OP_MASK, PWRCOM, { RA, RS, UI } },
++
++{ "xori", OP(26), OP_MASK, PPCCOM, { RA, RS, UI } },
++{ "xoril", OP(26), OP_MASK, PWRCOM, { RA, RS, UI } },
++
++{ "xoris", OP(27), OP_MASK, PPCCOM, { RA, RS, UI } },
++{ "xoriu", OP(27), OP_MASK, PWRCOM, { RA, RS, UI } },
++
++{ "andi.", OP(28), OP_MASK, PPCCOM, { RA, RS, UI } },
++{ "andil.", OP(28), OP_MASK, PWRCOM, { RA, RS, UI } },
++
++{ "andis.", OP(29), OP_MASK, PPCCOM, { RA, RS, UI } },
++{ "andiu.", OP(29), OP_MASK, PWRCOM, { RA, RS, UI } },
++
++{ "rotldi", MD(30,0,0), MDMB_MASK, PPC64, { RA, RS, SH6 } },
++{ "clrldi", MD(30,0,0), MDSH_MASK, PPC64, { RA, RS, MB6 } },
++{ "rldicl", MD(30,0,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
++{ "rotldi.", MD(30,0,1), MDMB_MASK, PPC64, { RA, RS, SH6 } },
++{ "clrldi.", MD(30,0,1), MDSH_MASK, PPC64, { RA, RS, MB6 } },
++{ "rldicl.", MD(30,0,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
++
++{ "rldicr", MD(30,1,0), MD_MASK, PPC64, { RA, RS, SH6, ME6 } },
++{ "rldicr.", MD(30,1,1), MD_MASK, PPC64, { RA, RS, SH6, ME6 } },
++
++{ "rldic", MD(30,2,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
++{ "rldic.", MD(30,2,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
++
++{ "rldimi", MD(30,3,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
++{ "rldimi.", MD(30,3,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
++
++{ "rotld", MDS(30,8,0), MDSMB_MASK, PPC64, { RA, RS, RB } },
++{ "rldcl", MDS(30,8,0), MDS_MASK, PPC64, { RA, RS, RB, MB6 } },
++{ "rotld.", MDS(30,8,1), MDSMB_MASK, PPC64, { RA, RS, RB } },
++{ "rldcl.", MDS(30,8,1), MDS_MASK, PPC64, { RA, RS, RB, MB6 } },
++
++{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
++{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
++
++{ "cmpw", XCMPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
++{ "cmpd", XCMPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
++{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } },
++{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
++
++{ "twlgt", XTO(31,4,TOLGT), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tlgt", XTO(31,4,TOLGT), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twllt", XTO(31,4,TOLLT), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tllt", XTO(31,4,TOLLT), XTO_MASK, PWRCOM, { RA, RB } },
++{ "tweq", XTO(31,4,TOEQ), XTO_MASK, PPCCOM, { RA, RB } },
++{ "teq", XTO(31,4,TOEQ), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twlge", XTO(31,4,TOLGE), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tlge", XTO(31,4,TOLGE), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twlnl", XTO(31,4,TOLNL), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tlnl", XTO(31,4,TOLNL), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twlle", XTO(31,4,TOLLE), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tlle", XTO(31,4,TOLLE), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twlng", XTO(31,4,TOLNG), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tlng", XTO(31,4,TOLNG), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twgt", XTO(31,4,TOGT), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tgt", XTO(31,4,TOGT), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twge", XTO(31,4,TOGE), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tge", XTO(31,4,TOGE), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twnl", XTO(31,4,TONL), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tnl", XTO(31,4,TONL), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twlt", XTO(31,4,TOLT), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tlt", XTO(31,4,TOLT), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twle", XTO(31,4,TOLE), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tle", XTO(31,4,TOLE), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twng", XTO(31,4,TONG), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tng", XTO(31,4,TONG), XTO_MASK, PWRCOM, { RA, RB } },
++{ "twne", XTO(31,4,TONE), XTO_MASK, PPCCOM, { RA, RB } },
++{ "tne", XTO(31,4,TONE), XTO_MASK, PWRCOM, { RA, RB } },
++{ "trap", XTO(31,4,TOU), 0xffffffff, PPCCOM, { 0 } },
++{ "tw", X(31,4), X_MASK, PPCCOM, { TO, RA, RB } },
++{ "t", X(31,4), X_MASK, PWRCOM, { TO, RA, RB } },
++
++{ "subfc", XO(31,8,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sf", XO(31,8,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "subc", XO(31,8,0,0), XO_MASK, PPC, { RT, RB, RA } },
++{ "subfc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sf.", XO(31,8,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "subc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RB, RA } },
++{ "subfco", XO(31,8,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sfo", XO(31,8,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "subco", XO(31,8,1,0), XO_MASK, PPC, { RT, RB, RA } },
++{ "subfco.", XO(31,8,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sfo.", XO(31,8,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "subco.", XO(31,8,1,1), XO_MASK, PPC, { RT, RB, RA } },
++
++{ "mulhdu", XO(31,9,0,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "mulhdu.", XO(31,9,0,1), XO_MASK, PPC64, { RT, RA, RB } },
++
++{ "addc", XO(31,10,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "a", XO(31,10,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "addc.", XO(31,10,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "a.", XO(31,10,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "addco", XO(31,10,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "ao", XO(31,10,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "addco.", XO(31,10,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "ao.", XO(31,10,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "mulhwu", XO(31,11,0,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "mulhwu.", XO(31,11,0,1), XO_MASK, PPC, { RT, RA, RB } },
++
++{ "isellt", X(31,15), X_MASK, PPCISEL, { RT, RA, RB } },
++{ "iselgt", X(31,47), X_MASK, PPCISEL, { RT, RA, RB } },
++{ "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } },
++{ "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } },
++
++{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4, { RT } },
++{ "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } },
++
++{ "lwarx", X(31,20), X_MASK, PPC, { RT, RA, RB } },
++
++{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA, RB } },
++
++{ "icbt", X(31,22), X_MASK, BOOKE, { CT, RA, RB } },
++{ "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } },
++
++{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA, RB } },
++{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } },
++{ "sl", XRC(31,24,0), X_MASK, PWRCOM, { RA, RS, RB } },
++{ "slw.", XRC(31,24,1), X_MASK, PPCCOM, { RA, RS, RB } },
++{ "sl.", XRC(31,24,1), X_MASK, PWRCOM, { RA, RS, RB } },
++
++{ "cntlzw", XRC(31,26,0), XRB_MASK, PPCCOM, { RA, RS } },
++{ "cntlz", XRC(31,26,0), XRB_MASK, PWRCOM, { RA, RS } },
++{ "cntlzw.", XRC(31,26,1), XRB_MASK, PPCCOM, { RA, RS } },
++{ "cntlz.", XRC(31,26,1), XRB_MASK, PWRCOM, { RA, RS } },
++
++{ "sld", XRC(31,27,0), X_MASK, PPC64, { RA, RS, RB } },
++{ "sld.", XRC(31,27,1), X_MASK, PPC64, { RA, RS, RB } },
++
++{ "and", XRC(31,28,0), X_MASK, COM, { RA, RS, RB } },
++{ "and.", XRC(31,28,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "maskg", XRC(31,29,0), X_MASK, M601, { RA, RS, RB } },
++{ "maskg.", XRC(31,29,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } },
++
++{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "cmplw", XCMPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
++{ "cmpld", XCMPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
++{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } },
++{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
++
++{ "subf", XO(31,40,0,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "sub", XO(31,40,0,0), XO_MASK, PPC, { RT, RB, RA } },
++{ "subf.", XO(31,40,0,1), XO_MASK, PPC, { RT, RA, RB } },
++{ "sub.", XO(31,40,0,1), XO_MASK, PPC, { RT, RB, RA } },
++{ "subfo", XO(31,40,1,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "subo", XO(31,40,1,0), XO_MASK, PPC, { RT, RB, RA } },
++{ "subfo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RA, RB } },
++{ "subo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RB, RA } },
++
++{ "ldux", X(31,53), X_MASK, PPC64, { RT, RAL, RB } },
++
++{ "dcbst", X(31,54), XRT_MASK, PPC, { RA, RB } },
++
++{ "lwzux", X(31,55), X_MASK, PPCCOM, { RT, RAL, RB } },
++{ "lux", X(31,55), X_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "dcbste", X(31,62), XRT_MASK, BOOKE64, { RA, RB } },
++
++{ "lwzuxe", X(31,63), X_MASK, BOOKE64, { RT, RAL, RB } },
++
++{ "cntlzd", XRC(31,58,0), XRB_MASK, PPC64, { RA, RS } },
++{ "cntlzd.", XRC(31,58,1), XRB_MASK, PPC64, { RA, RS } },
++
++{ "andc", XRC(31,60,0), X_MASK, COM, { RA, RS, RB } },
++{ "andc.", XRC(31,60,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "tdlgt", XTO(31,68,TOLGT), XTO_MASK, PPC64, { RA, RB } },
++{ "tdllt", XTO(31,68,TOLLT), XTO_MASK, PPC64, { RA, RB } },
++{ "tdeq", XTO(31,68,TOEQ), XTO_MASK, PPC64, { RA, RB } },
++{ "tdlge", XTO(31,68,TOLGE), XTO_MASK, PPC64, { RA, RB } },
++{ "tdlnl", XTO(31,68,TOLNL), XTO_MASK, PPC64, { RA, RB } },
++{ "tdlle", XTO(31,68,TOLLE), XTO_MASK, PPC64, { RA, RB } },
++{ "tdlng", XTO(31,68,TOLNG), XTO_MASK, PPC64, { RA, RB } },
++{ "tdgt", XTO(31,68,TOGT), XTO_MASK, PPC64, { RA, RB } },
++{ "tdge", XTO(31,68,TOGE), XTO_MASK, PPC64, { RA, RB } },
++{ "tdnl", XTO(31,68,TONL), XTO_MASK, PPC64, { RA, RB } },
++{ "tdlt", XTO(31,68,TOLT), XTO_MASK, PPC64, { RA, RB } },
++{ "tdle", XTO(31,68,TOLE), XTO_MASK, PPC64, { RA, RB } },
++{ "tdng", XTO(31,68,TONG), XTO_MASK, PPC64, { RA, RB } },
++{ "tdne", XTO(31,68,TONE), XTO_MASK, PPC64, { RA, RB } },
++{ "td", X(31,68), X_MASK, PPC64, { TO, RA, RB } },
++
++{ "mulhd", XO(31,73,0,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "mulhd.", XO(31,73,0,1), XO_MASK, PPC64, { RT, RA, RB } },
++
++{ "mulhw", XO(31,75,0,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "mulhw.", XO(31,75,0,1), XO_MASK, PPC, { RT, RA, RB } },
++
++{ "dlmzb", XRC(31,78,0), X_MASK, PPC403|PPC440, { RA, RS, RB } },
++{ "dlmzb.", XRC(31,78,1), X_MASK, PPC403|PPC440, { RA, RS, RB } },
++
++{ "mtsrd", X(31,82), XRB_MASK|(1<<20), PPC64, { SR, RS } },
++
++{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } },
++
++{ "ldarx", X(31,84), X_MASK, PPC64, { RT, RA, RB } },
++
++{ "dcbf", X(31,86), XRT_MASK, PPC, { RA, RB } },
++
++{ "lbzx", X(31,87), X_MASK, COM, { RT, RA, RB } },
++
++{ "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } },
++
++{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } },
++{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } },
++{ "nego", XO(31,104,1,0), XORB_MASK, COM, { RT, RA } },
++{ "nego.", XO(31,104,1,1), XORB_MASK, COM, { RT, RA } },
++
++{ "mul", XO(31,107,0,0), XO_MASK, M601, { RT, RA, RB } },
++{ "mul.", XO(31,107,0,1), XO_MASK, M601, { RT, RA, RB } },
++{ "mulo", XO(31,107,1,0), XO_MASK, M601, { RT, RA, RB } },
++{ "mulo.", XO(31,107,1,1), XO_MASK, M601, { RT, RA, RB } },
++
++{ "mtsrdin", X(31,114), XRA_MASK, PPC64, { RS, RB } },
++
++{ "clf", X(31,118), XTO_MASK, POWER, { RA, RB } },
++
++{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } },
++
++{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } },
++{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } },
++{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } },
++{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } },
++
++{ "wrtee", X(31,131), XRARB_MASK, PPC403 | BOOKE, { RS } },
++
++{ "dcbtstls",X(31,134), X_MASK, PPCCHLK, { CT, RA, RB }},
++
++{ "subfe", XO(31,136,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sfe", XO(31,136,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "subfe.", XO(31,136,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sfe.", XO(31,136,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "subfeo", XO(31,136,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sfeo", XO(31,136,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "subfeo.", XO(31,136,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "sfeo.", XO(31,136,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "adde", XO(31,138,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "ae", XO(31,138,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "adde.", XO(31,138,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "ae.", XO(31,138,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "addeo", XO(31,138,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "aeo", XO(31,138,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "addeo.", XO(31,138,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "aeo.", XO(31,138,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }},
++
++{ "mtcr", XFXM(31,144,0xff), XRARB_MASK, COM, { RS }},
++{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } },
++
++{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } },
++
++{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA, RB } },
++
++{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA, RB } },
++
++{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA, RB } },
++{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } },
++
++{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } },
++{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } },
++{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } },
++
++{ "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }},
++{ "dcbtlse", X(31,174), X_MASK, PPCCHLK64, { CT, RA, RB }},
++
++{ "mtmsrd", X(31,178), XRLARB_MASK, PPC64, { RS, MTMSRD_L } },
++
++{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } },
++
++{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } },
++{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA, RB } },
++
++{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } },
++{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } },
++
++{ "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } },
++
++{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfze", XO(31,200,0,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "subfze.", XO(31,200,0,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfze.", XO(31,200,0,1), XORB_MASK, PWRCOM, { RT, RA } },
++{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfzeo", XO(31,200,1,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfzeo.", XO(31,200,1,1), XORB_MASK, PWRCOM, { RT, RA } },
++
++{ "addze", XO(31,202,0,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "aze", XO(31,202,0,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "addze.", XO(31,202,0,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "aze.", XO(31,202,0,1), XORB_MASK, PWRCOM, { RT, RA } },
++{ "addzeo", XO(31,202,1,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "azeo", XO(31,202,1,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "azeo.", XO(31,202,1,1), XORB_MASK, PWRCOM, { RT, RA } },
++
++{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } },
++
++{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA, RB } },
++
++{ "stbx", X(31,215), X_MASK, COM, { RS, RA, RB } },
++
++{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } },
++{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } },
++{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }},
++
++{ "subfme", XO(31,232,0,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfme", XO(31,232,0,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "subfme.", XO(31,232,0,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfme.", XO(31,232,0,1), XORB_MASK, PWRCOM, { RT, RA } },
++{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfmeo", XO(31,232,1,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "sfmeo.", XO(31,232,1,1), XORB_MASK, PWRCOM, { RT, RA } },
++
++{ "mulld", XO(31,233,0,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "mulld.", XO(31,233,0,1), XO_MASK, PPC64, { RT, RA, RB } },
++{ "mulldo", XO(31,233,1,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "mulldo.", XO(31,233,1,1), XO_MASK, PPC64, { RT, RA, RB } },
++
++{ "addme", XO(31,234,0,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "ame", XO(31,234,0,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "addme.", XO(31,234,0,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "ame.", XO(31,234,0,1), XORB_MASK, PWRCOM, { RT, RA } },
++{ "addmeo", XO(31,234,1,0), XORB_MASK, PPCCOM, { RT, RA } },
++{ "ameo", XO(31,234,1,0), XORB_MASK, PWRCOM, { RT, RA } },
++{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPCCOM, { RT, RA } },
++{ "ameo.", XO(31,234,1,1), XORB_MASK, PWRCOM, { RT, RA } },
++
++{ "mullw", XO(31,235,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "muls", XO(31,235,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "mullw.", XO(31,235,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "muls.", XO(31,235,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "mullwo", XO(31,235,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "mulso", XO(31,235,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "mullwo.", XO(31,235,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "mulso.", XO(31,235,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "icblce", X(31,238), X_MASK, PPCCHLK64, { CT, RA, RB }},
++{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } },
++{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } },
++
++{ "dcbtst", X(31,246), XRT_MASK, PPC, { CT, RA, RB } },
++
++{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } },
++
++{ "slliq", XRC(31,248,0), X_MASK, M601, { RA, RS, SH } },
++{ "slliq.", XRC(31,248,1), X_MASK, M601, { RA, RS, SH } },
++
++{ "dcbtste", X(31,253), X_MASK, BOOKE64, { CT, RA, RB } },
++
++{ "stbuxe", X(31,255), X_MASK, BOOKE64, { RS, RAS, RB } },
++
++{ "mfdcrx", X(31,259), X_MASK, BOOKE, { RS, RA } },
++
++{ "doz", XO(31,264,0,0), XO_MASK, M601, { RT, RA, RB } },
++{ "doz.", XO(31,264,0,1), XO_MASK, M601, { RT, RA, RB } },
++{ "dozo", XO(31,264,1,0), XO_MASK, M601, { RT, RA, RB } },
++{ "dozo.", XO(31,264,1,1), XO_MASK, M601, { RT, RA, RB } },
++
++{ "add", XO(31,266,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "cax", XO(31,266,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "add.", XO(31,266,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "cax.", XO(31,266,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "addo", XO(31,266,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "caxo", XO(31,266,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
++{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
++{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "tlbiel", X(31,274), XRTRA_MASK, POWER4, { RB } },
++
++{ "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } },
++
++{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } },
++{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } },
++
++{ "dcbt", X(31,278), XRT_MASK, PPC, { CT, RA, RB } },
++
++{ "lhzx", X(31,279), X_MASK, COM, { RT, RA, RB } },
++
++{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } },
++{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } },
++
++{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } },
++{ "tlbi", X(31,306), XRT_MASK, POWER, { RA, RB } },
++
++{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } },
++
++{ "lhzux", X(31,311), X_MASK, COM, { RT, RAL, RB } },
++
++{ "xor", XRC(31,316,0), X_MASK, COM, { RA, RS, RB } },
++{ "xor.", XRC(31,316,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "lhzuxe", X(31,319), X_MASK, BOOKE64, { RT, RAL, RB } },
++
++{ "mfexisr", XSPR(31,323,64), XSPR_MASK, PPC403, { RT } },
++{ "mfexier", XSPR(31,323,66), XSPR_MASK, PPC403, { RT } },
++{ "mfbr0", XSPR(31,323,128), XSPR_MASK, PPC403, { RT } },
++{ "mfbr1", XSPR(31,323,129), XSPR_MASK, PPC403, { RT } },
++{ "mfbr2", XSPR(31,323,130), XSPR_MASK, PPC403, { RT } },
++{ "mfbr3", XSPR(31,323,131), XSPR_MASK, PPC403, { RT } },
++{ "mfbr4", XSPR(31,323,132), XSPR_MASK, PPC403, { RT } },
++{ "mfbr5", XSPR(31,323,133), XSPR_MASK, PPC403, { RT } },
++{ "mfbr6", XSPR(31,323,134), XSPR_MASK, PPC403, { RT } },
++{ "mfbr7", XSPR(31,323,135), XSPR_MASK, PPC403, { RT } },
++{ "mfbear", XSPR(31,323,144), XSPR_MASK, PPC403, { RT } },
++{ "mfbesr", XSPR(31,323,145), XSPR_MASK, PPC403, { RT } },
++{ "mfiocr", XSPR(31,323,160), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacr0", XSPR(31,323,192), XSPR_MASK, PPC403, { RT } },
++{ "mfdmact0", XSPR(31,323,193), XSPR_MASK, PPC403, { RT } },
++{ "mfdmada0", XSPR(31,323,194), XSPR_MASK, PPC403, { RT } },
++{ "mfdmasa0", XSPR(31,323,195), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacc0", XSPR(31,323,196), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacr1", XSPR(31,323,200), XSPR_MASK, PPC403, { RT } },
++{ "mfdmact1", XSPR(31,323,201), XSPR_MASK, PPC403, { RT } },
++{ "mfdmada1", XSPR(31,323,202), XSPR_MASK, PPC403, { RT } },
++{ "mfdmasa1", XSPR(31,323,203), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacc1", XSPR(31,323,204), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacr2", XSPR(31,323,208), XSPR_MASK, PPC403, { RT } },
++{ "mfdmact2", XSPR(31,323,209), XSPR_MASK, PPC403, { RT } },
++{ "mfdmada2", XSPR(31,323,210), XSPR_MASK, PPC403, { RT } },
++{ "mfdmasa2", XSPR(31,323,211), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacc2", XSPR(31,323,212), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacr3", XSPR(31,323,216), XSPR_MASK, PPC403, { RT } },
++{ "mfdmact3", XSPR(31,323,217), XSPR_MASK, PPC403, { RT } },
++{ "mfdmada3", XSPR(31,323,218), XSPR_MASK, PPC403, { RT } },
++{ "mfdmasa3", XSPR(31,323,219), XSPR_MASK, PPC403, { RT } },
++{ "mfdmacc3", XSPR(31,323,220), XSPR_MASK, PPC403, { RT } },
++{ "mfdmasr", XSPR(31,323,224), XSPR_MASK, PPC403, { RT } },
++{ "mfdcr", X(31,323), X_MASK, PPC403 | BOOKE, { RT, SPR } },
++
++{ "div", XO(31,331,0,0), XO_MASK, M601, { RT, RA, RB } },
++{ "div.", XO(31,331,0,1), XO_MASK, M601, { RT, RA, RB } },
++{ "divo", XO(31,331,1,0), XO_MASK, M601, { RT, RA, RB } },
++{ "divo.", XO(31,331,1,1), XO_MASK, M601, { RT, RA, RB } },
++
++{ "mfpmr", X(31,334), X_MASK, PPCPMR, { RT, PMR }},
++
++{ "mfmq", XSPR(31,339,0), XSPR_MASK, M601, { RT } },
++{ "mfxer", XSPR(31,339,1), XSPR_MASK, COM, { RT } },
++{ "mfrtcu", XSPR(31,339,4), XSPR_MASK, COM, { RT } },
++{ "mfrtcl", XSPR(31,339,5), XSPR_MASK, COM, { RT } },
++{ "mfdec", XSPR(31,339,6), XSPR_MASK, MFDEC1, { RT } },
++{ "mfdec", XSPR(31,339,22), XSPR_MASK, MFDEC2, { RT } },
++{ "mflr", XSPR(31,339,8), XSPR_MASK, COM, { RT } },
++{ "mfctr", XSPR(31,339,9), XSPR_MASK, COM, { RT } },
++{ "mftid", XSPR(31,339,17), XSPR_MASK, POWER, { RT } },
++{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, COM, { RT } },
++{ "mfdar", XSPR(31,339,19), XSPR_MASK, COM, { RT } },
++{ "mfsdr0", XSPR(31,339,24), XSPR_MASK, POWER, { RT } },
++{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } },
++{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } },
++{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } },
++{ "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } },
++{ "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } },
++{ "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } },
++{ "mfcsrr1", XSPR(31,339,59), XSPR_MASK, BOOKE, { RT } },
++{ "mfdear", XSPR(31,339,61), XSPR_MASK, BOOKE, { RT } },
++{ "mfdear", XSPR(31,339,981), XSPR_MASK, PPC403, { RT } },
++{ "mfesr", XSPR(31,339,62), XSPR_MASK, BOOKE, { RT } },
++{ "mfesr", XSPR(31,339,980), XSPR_MASK, PPC403, { RT } },
++{ "mfivpr", XSPR(31,339,63), XSPR_MASK, BOOKE, { RT } },
++{ "mfcmpa", XSPR(31,339,144), XSPR_MASK, PPC860, { RT } },
++{ "mfcmpb", XSPR(31,339,145), XSPR_MASK, PPC860, { RT } },
++{ "mfcmpc", XSPR(31,339,146), XSPR_MASK, PPC860, { RT } },
++{ "mfcmpd", XSPR(31,339,147), XSPR_MASK, PPC860, { RT } },
++{ "mficr", XSPR(31,339,148), XSPR_MASK, PPC860, { RT } },
++{ "mfder", XSPR(31,339,149), XSPR_MASK, PPC860, { RT } },
++{ "mfcounta", XSPR(31,339,150), XSPR_MASK, PPC860, { RT } },
++{ "mfcountb", XSPR(31,339,151), XSPR_MASK, PPC860, { RT } },
++{ "mfcmpe", XSPR(31,339,152), XSPR_MASK, PPC860, { RT } },
++{ "mfcmpf", XSPR(31,339,153), XSPR_MASK, PPC860, { RT } },
++{ "mfcmpg", XSPR(31,339,154), XSPR_MASK, PPC860, { RT } },
++{ "mfcmph", XSPR(31,339,155), XSPR_MASK, PPC860, { RT } },
++{ "mflctrl1", XSPR(31,339,156), XSPR_MASK, PPC860, { RT } },
++{ "mflctrl2", XSPR(31,339,157), XSPR_MASK, PPC860, { RT } },
++{ "mfictrl", XSPR(31,339,158), XSPR_MASK, PPC860, { RT } },
++{ "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } },
++{ "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } },
++{ "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } },
++{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405, { RT } },
++{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405, { RT } },
++{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405, { RT } },
++{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405, { RT } },
++{ "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } },
++{ "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
++{ "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } },
++{ "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
++{ "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } },
++{ "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } },
++{ "mfsprg", XSPR(31,339,272), XSPRG_MASK, PPC, { RT, SPRG } },
++{ "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } },
++{ "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } },
++{ "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } },
++{ "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } },
++{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } },
++{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } },
++{ "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } },
++{ "mfpvr", XSPR(31,339,287), XSPR_MASK, PPC, { RT } },
++{ "mfdbsr", XSPR(31,339,304), XSPR_MASK, BOOKE, { RT } },
++{ "mfdbsr", XSPR(31,339,1008), XSPR_MASK, PPC403, { RT } },
++{ "mfdbcr0", XSPR(31,339,308), XSPR_MASK, BOOKE, { RT } },
++{ "mfdbcr0", XSPR(31,339,1010), XSPR_MASK, PPC405, { RT } },
++{ "mfdbcr1", XSPR(31,339,309), XSPR_MASK, BOOKE, { RT } },
++{ "mfdbcr1", XSPR(31,339,957), XSPR_MASK, PPC405, { RT } },
++{ "mfdbcr2", XSPR(31,339,310), XSPR_MASK, BOOKE, { RT } },
++{ "mfiac1", XSPR(31,339,312), XSPR_MASK, BOOKE, { RT } },
++{ "mfiac1", XSPR(31,339,1012), XSPR_MASK, PPC403, { RT } },
++{ "mfiac2", XSPR(31,339,313), XSPR_MASK, BOOKE, { RT } },
++{ "mfiac2", XSPR(31,339,1013), XSPR_MASK, PPC403, { RT } },
++{ "mfiac3", XSPR(31,339,314), XSPR_MASK, BOOKE, { RT } },
++{ "mfiac3", XSPR(31,339,948), XSPR_MASK, PPC405, { RT } },
++{ "mfiac4", XSPR(31,339,315), XSPR_MASK, BOOKE, { RT } },
++{ "mfiac4", XSPR(31,339,949), XSPR_MASK, PPC405, { RT } },
++{ "mfdac1", XSPR(31,339,316), XSPR_MASK, BOOKE, { RT } },
++{ "mfdac1", XSPR(31,339,1014), XSPR_MASK, PPC403, { RT } },
++{ "mfdac2", XSPR(31,339,317), XSPR_MASK, BOOKE, { RT } },
++{ "mfdac2", XSPR(31,339,1015), XSPR_MASK, PPC403, { RT } },
++{ "mfdvc1", XSPR(31,339,318), XSPR_MASK, BOOKE, { RT } },
++{ "mfdvc1", XSPR(31,339,950), XSPR_MASK, PPC405, { RT } },
++{ "mfdvc2", XSPR(31,339,319), XSPR_MASK, BOOKE, { RT } },
++{ "mfdvc2", XSPR(31,339,951), XSPR_MASK, PPC405, { RT } },
++{ "mftsr", XSPR(31,339,336), XSPR_MASK, BOOKE, { RT } },
++{ "mftsr", XSPR(31,339,984), XSPR_MASK, PPC403, { RT } },
++{ "mftcr", XSPR(31,339,340), XSPR_MASK, BOOKE, { RT } },
++{ "mftcr", XSPR(31,339,986), XSPR_MASK, PPC403, { RT } },
++{ "mfivor0", XSPR(31,339,400), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor1", XSPR(31,339,401), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor2", XSPR(31,339,402), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor3", XSPR(31,339,403), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor4", XSPR(31,339,404), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor5", XSPR(31,339,405), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor6", XSPR(31,339,406), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor7", XSPR(31,339,407), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor8", XSPR(31,339,408), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor9", XSPR(31,339,409), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor10", XSPR(31,339,410), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor11", XSPR(31,339,411), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor12", XSPR(31,339,412), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor13", XSPR(31,339,413), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor14", XSPR(31,339,414), XSPR_MASK, BOOKE, { RT } },
++{ "mfivor15", XSPR(31,339,415), XSPR_MASK, BOOKE, { RT } },
++{ "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } },
++{ "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } },
++{ "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } },
++{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
++{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
++{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
++{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
++{ "mfic_cst", XSPR(31,339,560), XSPR_MASK, PPC860, { RT } },
++{ "mfic_adr", XSPR(31,339,561), XSPR_MASK, PPC860, { RT } },
++{ "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } },
++{ "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } },
++{ "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } },
++{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } },
++{ "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } },
++{ "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } },
++{ "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } },
++{ "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } },
++{ "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } },
++{ "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_ctr", XSPR(31,339,784), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_ap", XSPR(31,339,786), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_epn", XSPR(31,339,787), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_twc", XSPR(31,339,789), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_rpn", XSPR(31,339,790), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_ctr", XSPR(31,339,792), XSPR_MASK, PPC860, { RT } },
++{ "mfm_casid", XSPR(31,339,793), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_ap", XSPR(31,339,794), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_epn", XSPR(31,339,795), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_twb", XSPR(31,339,796), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_twc", XSPR(31,339,797), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_rpn", XSPR(31,339,798), XSPR_MASK, PPC860, { RT } },
++{ "mfm_tw", XSPR(31,339,799), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_dbcam", XSPR(31,339,816), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_dbram0",XSPR(31,339,817), XSPR_MASK, PPC860, { RT } },
++{ "mfmi_dbram1",XSPR(31,339,818), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_dbcam", XSPR(31,339,824), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_dbram0",XSPR(31,339,825), XSPR_MASK, PPC860, { RT } },
++{ "mfmd_dbram1",XSPR(31,339,826), XSPR_MASK, PPC860, { RT } },
++{ "mfummcr0", XSPR(31,339,936), XSPR_MASK, PPC750, { RT } },
++{ "mfupmc1", XSPR(31,339,937), XSPR_MASK, PPC750, { RT } },
++{ "mfupmc2", XSPR(31,339,938), XSPR_MASK, PPC750, { RT } },
++{ "mfusia", XSPR(31,339,939), XSPR_MASK, PPC750, { RT } },
++{ "mfummcr1", XSPR(31,339,940), XSPR_MASK, PPC750, { RT } },
++{ "mfupmc3", XSPR(31,339,941), XSPR_MASK, PPC750, { RT } },
++{ "mfupmc4", XSPR(31,339,942), XSPR_MASK, PPC750, { RT } },
++{ "mfzpr", XSPR(31,339,944), XSPR_MASK, PPC403, { RT } },
++{ "mfccr0", XSPR(31,339,947), XSPR_MASK, PPC405, { RT } },
++{ "mfmmcr0", XSPR(31,339,952), XSPR_MASK, PPC750, { RT } },
++{ "mfpmc1", XSPR(31,339,953), XSPR_MASK, PPC750, { RT } },
++{ "mfsgr", XSPR(31,339,953), XSPR_MASK, PPC403, { RT } },
++{ "mfpmc2", XSPR(31,339,954), XSPR_MASK, PPC750, { RT } },
++{ "mfdcwr", XSPR(31,339,954), XSPR_MASK, PPC403, { RT } },
++{ "mfsia", XSPR(31,339,955), XSPR_MASK, PPC750, { RT } },
++{ "mfsler", XSPR(31,339,955), XSPR_MASK, PPC405, { RT } },
++{ "mfmmcr1", XSPR(31,339,956), XSPR_MASK, PPC750, { RT } },
++{ "mfsu0r", XSPR(31,339,956), XSPR_MASK, PPC405, { RT } },
++{ "mfpmc3", XSPR(31,339,957), XSPR_MASK, PPC750, { RT } },
++{ "mfpmc4", XSPR(31,339,958), XSPR_MASK, PPC750, { RT } },
++{ "mficdbdr", XSPR(31,339,979), XSPR_MASK, PPC403, { RT } },
++{ "mfevpr", XSPR(31,339,982), XSPR_MASK, PPC403, { RT } },
++{ "mfcdbcr", XSPR(31,339,983), XSPR_MASK, PPC403, { RT } },
++{ "mfpit", XSPR(31,339,987), XSPR_MASK, PPC403, { RT } },
++{ "mftbhi", XSPR(31,339,988), XSPR_MASK, PPC403, { RT } },
++{ "mftblo", XSPR(31,339,989), XSPR_MASK, PPC403, { RT } },
++{ "mfsrr2", XSPR(31,339,990), XSPR_MASK, PPC403, { RT } },
++{ "mfsrr3", XSPR(31,339,991), XSPR_MASK, PPC403, { RT } },
++{ "mfl2cr", XSPR(31,339,1017), XSPR_MASK, PPC750, { RT } },
++{ "mfdccr", XSPR(31,339,1018), XSPR_MASK, PPC403, { RT } },
++{ "mficcr", XSPR(31,339,1019), XSPR_MASK, PPC403, { RT } },
++{ "mfictc", XSPR(31,339,1019), XSPR_MASK, PPC750, { RT } },
++{ "mfpbl1", XSPR(31,339,1020), XSPR_MASK, PPC403, { RT } },
++{ "mfthrm1", XSPR(31,339,1020), XSPR_MASK, PPC750, { RT } },
++{ "mfpbu1", XSPR(31,339,1021), XSPR_MASK, PPC403, { RT } },
++{ "mfthrm2", XSPR(31,339,1021), XSPR_MASK, PPC750, { RT } },
++{ "mfpbl2", XSPR(31,339,1022), XSPR_MASK, PPC403, { RT } },
++{ "mfthrm3", XSPR(31,339,1022), XSPR_MASK, PPC750, { RT } },
++{ "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } },
++{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } },
++
++{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA, RB } },
++
++{ "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
++{ "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
++
++{ "lhax", X(31,343), X_MASK, COM, { RT, RA, RB } },
++
++{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
++{ "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
++
++{ "dccci", X(31,454), XRT_MASK, PPC403|PPC440, { RA, RB } },
++
++{ "abs", XO(31,360,0,0), XORB_MASK, M601, { RT, RA } },
++{ "abs.", XO(31,360,0,1), XORB_MASK, M601, { RT, RA } },
++{ "abso", XO(31,360,1,0), XORB_MASK, M601, { RT, RA } },
++{ "abso.", XO(31,360,1,1), XORB_MASK, M601, { RT, RA } },
++
++{ "divs", XO(31,363,0,0), XO_MASK, M601, { RT, RA, RB } },
++{ "divs.", XO(31,363,0,1), XO_MASK, M601, { RT, RA, RB } },
++{ "divso", XO(31,363,1,0), XO_MASK, M601, { RT, RA, RB } },
++{ "divso.", XO(31,363,1,1), XO_MASK, M601, { RT, RA, RB } },
++
++{ "tlbia", X(31,370), 0xffffffff, PPC, { 0 } },
++
++{ "lwaux", X(31,373), X_MASK, PPC64, { RT, RAL, RB } },
++
++{ "lhaux", X(31,375), X_MASK, COM, { RT, RAL, RB } },
++
++{ "lhauxe", X(31,383), X_MASK, BOOKE64, { RT, RAL, RB } },
++
++{ "mtdcrx", X(31,387), X_MASK, BOOKE, { RA, RS } },
++
++{ "dcblc", X(31,390), X_MASK, PPCCHLK, { CT, RA, RB }},
++
++{ "subfe64", XO(31,392,0,0), XO_MASK, BOOKE64, { RT, RA, RB } },
++{ "subfe64o",XO(31,392,1,0), XO_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "adde64", XO(31,394,0,0), XO_MASK, BOOKE64, { RT, RA, RB } },
++{ "adde64o", XO(31,394,1,0), XO_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "dcblce", X(31,398), X_MASK, PPCCHLK64, { CT, RA, RB }},
++
++{ "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } },
++
++{ "sthx", X(31,407), X_MASK, COM, { RS, RA, RB } },
++
++{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } },
++
++{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } },
++
++{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } },
++
++{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } },
++
++{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } },
++{ "orc.", XRC(31,412,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } },
++{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } },
++
++{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } },
++
++{ "ecowx", X(31,438), X_MASK, PPC, { RT, RA, RB } },
++
++{ "sthux", X(31,439), X_MASK, COM, { RS, RAS, RB } },
++
++{ "sthuxe", X(31,447), X_MASK, BOOKE64, { RS, RAS, RB } },
++
++{ "mr", XRC(31,444,0), X_MASK, COM, { RA, RS, RBS } },
++{ "or", XRC(31,444,0), X_MASK, COM, { RA, RS, RB } },
++{ "mr.", XRC(31,444,1), X_MASK, COM, { RA, RS, RBS } },
++{ "or.", XRC(31,444,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "mtexisr", XSPR(31,451,64), XSPR_MASK, PPC403, { RS } },
++{ "mtexier", XSPR(31,451,66), XSPR_MASK, PPC403, { RS } },
++{ "mtbr0", XSPR(31,451,128), XSPR_MASK, PPC403, { RS } },
++{ "mtbr1", XSPR(31,451,129), XSPR_MASK, PPC403, { RS } },
++{ "mtbr2", XSPR(31,451,130), XSPR_MASK, PPC403, { RS } },
++{ "mtbr3", XSPR(31,451,131), XSPR_MASK, PPC403, { RS } },
++{ "mtbr4", XSPR(31,451,132), XSPR_MASK, PPC403, { RS } },
++{ "mtbr5", XSPR(31,451,133), XSPR_MASK, PPC403, { RS } },
++{ "mtbr6", XSPR(31,451,134), XSPR_MASK, PPC403, { RS } },
++{ "mtbr7", XSPR(31,451,135), XSPR_MASK, PPC403, { RS } },
++{ "mtbear", XSPR(31,451,144), XSPR_MASK, PPC403, { RS } },
++{ "mtbesr", XSPR(31,451,145), XSPR_MASK, PPC403, { RS } },
++{ "mtiocr", XSPR(31,451,160), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacr0", XSPR(31,451,192), XSPR_MASK, PPC403, { RS } },
++{ "mtdmact0", XSPR(31,451,193), XSPR_MASK, PPC403, { RS } },
++{ "mtdmada0", XSPR(31,451,194), XSPR_MASK, PPC403, { RS } },
++{ "mtdmasa0", XSPR(31,451,195), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacc0", XSPR(31,451,196), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacr1", XSPR(31,451,200), XSPR_MASK, PPC403, { RS } },
++{ "mtdmact1", XSPR(31,451,201), XSPR_MASK, PPC403, { RS } },
++{ "mtdmada1", XSPR(31,451,202), XSPR_MASK, PPC403, { RS } },
++{ "mtdmasa1", XSPR(31,451,203), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacc1", XSPR(31,451,204), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacr2", XSPR(31,451,208), XSPR_MASK, PPC403, { RS } },
++{ "mtdmact2", XSPR(31,451,209), XSPR_MASK, PPC403, { RS } },
++{ "mtdmada2", XSPR(31,451,210), XSPR_MASK, PPC403, { RS } },
++{ "mtdmasa2", XSPR(31,451,211), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacc2", XSPR(31,451,212), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacr3", XSPR(31,451,216), XSPR_MASK, PPC403, { RS } },
++{ "mtdmact3", XSPR(31,451,217), XSPR_MASK, PPC403, { RS } },
++{ "mtdmada3", XSPR(31,451,218), XSPR_MASK, PPC403, { RS } },
++{ "mtdmasa3", XSPR(31,451,219), XSPR_MASK, PPC403, { RS } },
++{ "mtdmacc3", XSPR(31,451,220), XSPR_MASK, PPC403, { RS } },
++{ "mtdmasr", XSPR(31,451,224), XSPR_MASK, PPC403, { RS } },
++{ "mtdcr", X(31,451), X_MASK, PPC403 | BOOKE, { SPR, RS } },
++
++{ "subfze64",XO(31,456,0,0), XORB_MASK, BOOKE64, { RT, RA } },
++{ "subfze64o",XO(31,456,1,0), XORB_MASK, BOOKE64, { RT, RA } },
++
++{ "divdu", XO(31,457,0,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "divdu.", XO(31,457,0,1), XO_MASK, PPC64, { RT, RA, RB } },
++{ "divduo", XO(31,457,1,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "divduo.", XO(31,457,1,1), XO_MASK, PPC64, { RT, RA, RB } },
++
++{ "addze64", XO(31,458,0,0), XORB_MASK, BOOKE64, { RT, RA } },
++{ "addze64o",XO(31,458,1,0), XORB_MASK, BOOKE64, { RT, RA } },
++
++{ "divwu", XO(31,459,0,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "divwu.", XO(31,459,0,1), XO_MASK, PPC, { RT, RA, RB } },
++{ "divwuo", XO(31,459,1,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "divwuo.", XO(31,459,1,1), XO_MASK, PPC, { RT, RA, RB } },
++
++{ "mtmq", XSPR(31,467,0), XSPR_MASK, M601, { RS } },
++{ "mtxer", XSPR(31,467,1), XSPR_MASK, COM, { RS } },
++{ "mtlr", XSPR(31,467,8), XSPR_MASK, COM, { RS } },
++{ "mtctr", XSPR(31,467,9), XSPR_MASK, COM, { RS } },
++{ "mttid", XSPR(31,467,17), XSPR_MASK, POWER, { RS } },
++{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, COM, { RS } },
++{ "mtdar", XSPR(31,467,19), XSPR_MASK, COM, { RS } },
++{ "mtrtcu", XSPR(31,467,20), XSPR_MASK, COM, { RS } },
++{ "mtrtcl", XSPR(31,467,21), XSPR_MASK, COM, { RS } },
++{ "mtdec", XSPR(31,467,22), XSPR_MASK, COM, { RS } },
++{ "mtsdr0", XSPR(31,467,24), XSPR_MASK, POWER, { RS } },
++{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } },
++{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } },
++{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } },
++{ "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } },
++{ "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } },
++{ "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } },
++{ "mtcsrr0", XSPR(31,467,58), XSPR_MASK, BOOKE, { RS } },
++{ "mtcsrr1", XSPR(31,467,59), XSPR_MASK, BOOKE, { RS } },
++{ "mtdear", XSPR(31,467,61), XSPR_MASK, BOOKE, { RS } },
++{ "mtdear", XSPR(31,467,981), XSPR_MASK, PPC403, { RS } },
++{ "mtesr", XSPR(31,467,62), XSPR_MASK, BOOKE, { RS } },
++{ "mtesr", XSPR(31,467,980), XSPR_MASK, PPC403, { RS } },
++{ "mtivpr", XSPR(31,467,63), XSPR_MASK, BOOKE, { RS } },
++{ "mtcmpa", XSPR(31,467,144), XSPR_MASK, PPC860, { RS } },
++{ "mtcmpb", XSPR(31,467,145), XSPR_MASK, PPC860, { RS } },
++{ "mtcmpc", XSPR(31,467,146), XSPR_MASK, PPC860, { RS } },
++{ "mtcmpd", XSPR(31,467,147), XSPR_MASK, PPC860, { RS } },
++{ "mticr", XSPR(31,467,148), XSPR_MASK, PPC860, { RS } },
++{ "mtder", XSPR(31,467,149), XSPR_MASK, PPC860, { RS } },
++{ "mtcounta", XSPR(31,467,150), XSPR_MASK, PPC860, { RS } },
++{ "mtcountb", XSPR(31,467,151), XSPR_MASK, PPC860, { RS } },
++{ "mtcmpe", XSPR(31,467,152), XSPR_MASK, PPC860, { RS } },
++{ "mtcmpf", XSPR(31,467,153), XSPR_MASK, PPC860, { RS } },
++{ "mtcmpg", XSPR(31,467,154), XSPR_MASK, PPC860, { RS } },
++{ "mtcmph", XSPR(31,467,155), XSPR_MASK, PPC860, { RS } },
++{ "mtlctrl1", XSPR(31,467,156), XSPR_MASK, PPC860, { RS } },
++{ "mtlctrl2", XSPR(31,467,157), XSPR_MASK, PPC860, { RS } },
++{ "mtictrl", XSPR(31,467,158), XSPR_MASK, PPC860, { RS } },
++{ "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } },
++{ "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } },
++{ "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } },
++{ "mtsprg", XSPR(31,467,272), XSPRG_MASK,PPC, { SPRG, RS } },
++{ "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } },
++{ "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } },
++{ "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } },
++{ "mtsprg3", XSPR(31,467,275), XSPR_MASK, PPC, { RS } },
++{ "mtsprg4", XSPR(31,467,276), XSPR_MASK, PPC405 | BOOKE, { RS } },
++{ "mtsprg5", XSPR(31,467,277), XSPR_MASK, PPC405 | BOOKE, { RS } },
++{ "mtsprg6", XSPR(31,467,278), XSPR_MASK, PPC405 | BOOKE, { RS } },
++{ "mtsprg7", XSPR(31,467,279), XSPR_MASK, PPC405 | BOOKE, { RS } },
++{ "mtasr", XSPR(31,467,280), XSPR_MASK, PPC64, { RS } },
++{ "mtear", XSPR(31,467,282), XSPR_MASK, PPC, { RS } },
++{ "mttbl", XSPR(31,467,284), XSPR_MASK, PPC, { RS } },
++{ "mttbu", XSPR(31,467,285), XSPR_MASK, PPC, { RS } },
++{ "mtdbsr", XSPR(31,467,304), XSPR_MASK, BOOKE, { RS } },
++{ "mtdbsr", XSPR(31,467,1008), XSPR_MASK, PPC403, { RS } },
++{ "mtdbcr0", XSPR(31,467,308), XSPR_MASK, BOOKE, { RS } },
++{ "mtdbcr0", XSPR(31,467,1010), XSPR_MASK, PPC405, { RS } },
++{ "mtdbcr1", XSPR(31,467,309), XSPR_MASK, BOOKE, { RS } },
++{ "mtdbcr1", XSPR(31,467,957), XSPR_MASK, PPC405, { RS } },
++{ "mtdbcr2", XSPR(31,467,310), XSPR_MASK, BOOKE, { RS } },
++{ "mtiac1", XSPR(31,467,312), XSPR_MASK, BOOKE, { RS } },
++{ "mtiac1", XSPR(31,467,1012), XSPR_MASK, PPC403, { RS } },
++{ "mtiac2", XSPR(31,467,313), XSPR_MASK, BOOKE, { RS } },
++{ "mtiac2", XSPR(31,467,1013), XSPR_MASK, PPC403, { RS } },
++{ "mtiac3", XSPR(31,467,314), XSPR_MASK, BOOKE, { RS } },
++{ "mtiac3", XSPR(31,467,948), XSPR_MASK, PPC405, { RS } },
++{ "mtiac4", XSPR(31,467,315), XSPR_MASK, BOOKE, { RS } },
++{ "mtiac4", XSPR(31,467,949), XSPR_MASK, PPC405, { RS } },
++{ "mtdac1", XSPR(31,467,316), XSPR_MASK, BOOKE, { RS } },
++{ "mtdac1", XSPR(31,467,1014), XSPR_MASK, PPC403, { RS } },
++{ "mtdac2", XSPR(31,467,317), XSPR_MASK, BOOKE, { RS } },
++{ "mtdac2", XSPR(31,467,1015), XSPR_MASK, PPC403, { RS } },
++{ "mtdvc1", XSPR(31,467,318), XSPR_MASK, BOOKE, { RS } },
++{ "mtdvc1", XSPR(31,467,950), XSPR_MASK, PPC405, { RS } },
++{ "mtdvc2", XSPR(31,467,319), XSPR_MASK, BOOKE, { RS } },
++{ "mtdvc2", XSPR(31,467,951), XSPR_MASK, PPC405, { RS } },
++{ "mttsr", XSPR(31,467,336), XSPR_MASK, BOOKE, { RS } },
++{ "mttsr", XSPR(31,467,984), XSPR_MASK, PPC403, { RS } },
++{ "mttcr", XSPR(31,467,340), XSPR_MASK, BOOKE, { RS } },
++{ "mttcr", XSPR(31,467,986), XSPR_MASK, PPC403, { RS } },
++{ "mtivor0", XSPR(31,467,400), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor1", XSPR(31,467,401), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor2", XSPR(31,467,402), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor3", XSPR(31,467,403), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor4", XSPR(31,467,404), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor5", XSPR(31,467,405), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor6", XSPR(31,467,406), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor7", XSPR(31,467,407), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor8", XSPR(31,467,408), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor9", XSPR(31,467,409), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor10", XSPR(31,467,410), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor11", XSPR(31,467,411), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor12", XSPR(31,467,412), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor13", XSPR(31,467,413), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor14", XSPR(31,467,414), XSPR_MASK, BOOKE, { RS } },
++{ "mtivor15", XSPR(31,467,415), XSPR_MASK, BOOKE, { RS } },
++{ "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } },
++{ "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } },
++{ "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } },
++{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
++{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
++{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
++{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
++{ "mtmcsrr0", XSPR(31,467,570), XSPR_MASK, PPCRFMCI, { RS } },
++{ "mtmcsrr1", XSPR(31,467,571), XSPR_MASK, PPCRFMCI, { RS } },
++{ "mtmcsr", XSPR(31,467,572), XSPR_MASK, PPCRFMCI, { RS } },
++{ "mtummcr0", XSPR(31,467,936), XSPR_MASK, PPC750, { RS } },
++{ "mtupmc1", XSPR(31,467,937), XSPR_MASK, PPC750, { RS } },
++{ "mtupmc2", XSPR(31,467,938), XSPR_MASK, PPC750, { RS } },
++{ "mtusia", XSPR(31,467,939), XSPR_MASK, PPC750, { RS } },
++{ "mtummcr1", XSPR(31,467,940), XSPR_MASK, PPC750, { RS } },
++{ "mtupmc3", XSPR(31,467,941), XSPR_MASK, PPC750, { RS } },
++{ "mtupmc4", XSPR(31,467,942), XSPR_MASK, PPC750, { RS } },
++{ "mtzpr", XSPR(31,467,944), XSPR_MASK, PPC403, { RS } },
++{ "mtccr0", XSPR(31,467,947), XSPR_MASK, PPC405, { RS } },
++{ "mtmmcr0", XSPR(31,467,952), XSPR_MASK, PPC750, { RS } },
++{ "mtsgr", XSPR(31,467,953), XSPR_MASK, PPC403, { RS } },
++{ "mtpmc1", XSPR(31,467,953), XSPR_MASK, PPC750, { RS } },
++{ "mtdcwr", XSPR(31,467,954), XSPR_MASK, PPC403, { RS } },
++{ "mtpmc2", XSPR(31,467,954), XSPR_MASK, PPC750, { RS } },
++{ "mtsler", XSPR(31,467,955), XSPR_MASK, PPC405, { RS } },
++{ "mtsia", XSPR(31,467,955), XSPR_MASK, PPC750, { RS } },
++{ "mtsu0r", XSPR(31,467,956), XSPR_MASK, PPC405, { RS } },
++{ "mtmmcr1", XSPR(31,467,956), XSPR_MASK, PPC750, { RS } },
++{ "mtpmc3", XSPR(31,467,957), XSPR_MASK, PPC750, { RS } },
++{ "mtpmc4", XSPR(31,467,958), XSPR_MASK, PPC750, { RS } },
++{ "mticdbdr", XSPR(31,467,979), XSPR_MASK, PPC403, { RS } },
++{ "mtevpr", XSPR(31,467,982), XSPR_MASK, PPC403, { RS } },
++{ "mtcdbcr", XSPR(31,467,983), XSPR_MASK, PPC403, { RS } },
++{ "mtpit", XSPR(31,467,987), XSPR_MASK, PPC403, { RS } },
++{ "mttbhi", XSPR(31,467,988), XSPR_MASK, PPC403, { RS } },
++{ "mttblo", XSPR(31,467,989), XSPR_MASK, PPC403, { RS } },
++{ "mtsrr2", XSPR(31,467,990), XSPR_MASK, PPC403, { RS } },
++{ "mtsrr3", XSPR(31,467,991), XSPR_MASK, PPC403, { RS } },
++{ "mtl2cr", XSPR(31,467,1017), XSPR_MASK, PPC750, { RS } },
++{ "mtdccr", XSPR(31,467,1018), XSPR_MASK, PPC403, { RS } },
++{ "mticcr", XSPR(31,467,1019), XSPR_MASK, PPC403, { RS } },
++{ "mtictc", XSPR(31,467,1019), XSPR_MASK, PPC750, { RS } },
++{ "mtpbl1", XSPR(31,467,1020), XSPR_MASK, PPC403, { RS } },
++{ "mtthrm1", XSPR(31,467,1020), XSPR_MASK, PPC750, { RS } },
++{ "mtpbu1", XSPR(31,467,1021), XSPR_MASK, PPC403, { RS } },
++{ "mtthrm2", XSPR(31,467,1021), XSPR_MASK, PPC750, { RS } },
++{ "mtpbl2", XSPR(31,467,1022), XSPR_MASK, PPC403, { RS } },
++{ "mtthrm3", XSPR(31,467,1022), XSPR_MASK, PPC750, { RS } },
++{ "mtpbu2", XSPR(31,467,1023), XSPR_MASK, PPC403, { RS } },
++{ "mtspr", X(31,467), X_MASK, COM, { SPR, RS } },
++
++{ "dcbi", X(31,470), XRT_MASK, PPC, { RA, RB } },
++
++{ "nand", XRC(31,476,0), X_MASK, COM, { RA, RS, RB } },
++{ "nand.", XRC(31,476,1), X_MASK, COM, { RA, RS, RB } },
++
++{ "dcbie", X(31,478), XRT_MASK, BOOKE64, { RA, RB } },
++
++{ "dcread", X(31,486), X_MASK, PPC403|PPC440, { RT, RA, RB }},
++
++{ "mtpmr", X(31,462), X_MASK, PPCPMR, { PMR, RS }},
++
++{ "icbtls", X(31,486), X_MASK, PPCCHLK, { CT, RA, RB }},
++
++{ "nabs", XO(31,488,0,0), XORB_MASK, M601, { RT, RA } },
++{ "subfme64",XO(31,488,0,0), XORB_MASK, BOOKE64, { RT, RA } },
++{ "nabs.", XO(31,488,0,1), XORB_MASK, M601, { RT, RA } },
++{ "nabso", XO(31,488,1,0), XORB_MASK, M601, { RT, RA } },
++{ "subfme64o",XO(31,488,1,0), XORB_MASK, BOOKE64, { RT, RA } },
++{ "nabso.", XO(31,488,1,1), XORB_MASK, M601, { RT, RA } },
++
++{ "divd", XO(31,489,0,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "divd.", XO(31,489,0,1), XO_MASK, PPC64, { RT, RA, RB } },
++{ "divdo", XO(31,489,1,0), XO_MASK, PPC64, { RT, RA, RB } },
++{ "divdo.", XO(31,489,1,1), XO_MASK, PPC64, { RT, RA, RB } },
++
++{ "addme64", XO(31,490,0,0), XORB_MASK, BOOKE64, { RT, RA } },
++{ "addme64o",XO(31,490,1,0), XORB_MASK, BOOKE64, { RT, RA } },
++
++{ "divw", XO(31,491,0,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "divw.", XO(31,491,0,1), XO_MASK, PPC, { RT, RA, RB } },
++{ "divwo", XO(31,491,1,0), XO_MASK, PPC, { RT, RA, RB } },
++{ "divwo.", XO(31,491,1,1), XO_MASK, PPC, { RT, RA, RB } },
++
++{ "icbtlse", X(31,494), X_MASK, PPCCHLK64, { CT, RA, RB }},
++
++{ "slbia", X(31,498), 0xffffffff, PPC64, { 0 } },
++
++{ "cli", X(31,502), XRB_MASK, POWER, { RT, RA } },
++
++{ "stdcxe.", XRC(31,511,1), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "mcrxr", X(31,512), XRARB_MASK|(3<<21), COM, { BF } },
++
++{ "bblels", X(31,518), X_MASK, PPCBRLK, { 0 }},
++{ "mcrxr64", X(31,544), XRARB_MASK|(3<<21), BOOKE64, { BF } },
++
++{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } },
++
++{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA, RB } },
++{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA, RB } },
++{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA, RB } },
++
++{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } },
++{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } },
++{ "srw.", XRC(31,536,1), X_MASK, PPCCOM, { RA, RS, RB } },
++{ "sr.", XRC(31,536,1), X_MASK, PWRCOM, { RA, RS, RB } },
++
++{ "rrib", XRC(31,537,0), X_MASK, M601, { RA, RS, RB } },
++{ "rrib.", XRC(31,537,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "srd", XRC(31,539,0), X_MASK, PPC64, { RA, RS, RB } },
++{ "srd.", XRC(31,539,1), X_MASK, PPC64, { RA, RS, RB } },
++
++{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } },
++{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA, RB } },
++
++{ "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }},
++{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } },
++
++{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } },
++
++{ "lfsuxe", X(31,575), X_MASK, BOOKE64, { FRT, RAS, RB } },
++
++{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } },
++
++{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA, NB } },
++{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA, NB } },
++
++{ "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } },
++{ "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } },
++{ "msync", X(31,598), 0xffffffff, BOOKE, { 0 } },
++{ "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } },
++{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } },
++
++{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA, RB } },
++
++{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA, RB } },
++
++{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "dclst", X(31,630), XRB_MASK, PWRCOM, { RS, RA } },
++
++{ "lfdux", X(31,631), X_MASK, COM, { FRT, RAS, RB } },
++
++{ "lfduxe", X(31,639), X_MASK, BOOKE64, { FRT, RAS, RB } },
++
++{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } },
++
++{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA, RB } },
++{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA, RB } },
++
++{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA, RB } },
++{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA, RB } },
++
++{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA, RB } },
++
++{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } },
++{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } },
++{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA, RB } },
++
++{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } },
++
++{ "sriq", XRC(31,696,0), X_MASK, M601, { RA, RS, SH } },
++{ "sriq.", XRC(31,696,1), X_MASK, M601, { RA, RS, SH } },
++
++{ "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } },
++
++{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA, NB } },
++{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA, NB } },
++
++{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA, RB } },
++
++{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } },
++{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } },
++{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA, RB } },
++
++{ "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } },
++
++{ "stfdux", X(31,759), X_MASK, COM, { FRS, RAS, RB } },
++
++{ "srliq", XRC(31,760,0), X_MASK, M601, { RA, RS, SH } },
++{ "srliq.", XRC(31,760,1), X_MASK, M601, { RA, RS, SH } },
++
++{ "dcbae", X(31,766), XRT_MASK, BOOKE64, { RA, RB } },
++
++{ "stfduxe", X(31,767), X_MASK, BOOKE64, { FRS, RAS, RB } },
++
++{ "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } },
++{ "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } },
++
++{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA, RB } },
++
++{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } },
++{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } },
++{ "sraw.", XRC(31,792,1), X_MASK, PPCCOM, { RA, RS, RB } },
++{ "sra.", XRC(31,792,1), X_MASK, PWRCOM, { RA, RS, RB } },
++
++{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } },
++{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } },
++
++{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA, RB } },
++{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA, RB } },
++
++{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } },
++
++{ "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } },
++{ "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } },
++
++{ "srawi", XRC(31,824,0), X_MASK, PPCCOM, { RA, RS, SH } },
++{ "srai", XRC(31,824,0), X_MASK, PWRCOM, { RA, RS, SH } },
++{ "srawi.", XRC(31,824,1), X_MASK, PPCCOM, { RA, RS, SH } },
++{ "srai.", XRC(31,824,1), X_MASK, PWRCOM, { RA, RS, SH } },
++
++{ "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } },
++
++{ "mbar", X(31,854), X_MASK, BOOKE, { MO } },
++{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } },
++
++{ "tlbsx", XRC(31,914,0), X_MASK, BOOKE, { RA, RB } },
++{ "tlbsx", XRC(31,914,0), X_MASK, PPC403, { RT, RA, RB } },
++{ "tlbsx.", XRC(31,914,1), X_MASK, BOOKE, { RA, RB } },
++{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403, { RT, RA, RB } },
++{ "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RA, RB } },
++{ "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RA, RB } },
++
++{ "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } },
++
++{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA, RB } },
++
++{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } },
++{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "srea", XRC(31,921,0), X_MASK, M601, { RA, RS, RB } },
++{ "srea.", XRC(31,921,1), X_MASK, M601, { RA, RS, RB } },
++
++{ "extsh", XRC(31,922,0), XRB_MASK, PPCCOM, { RA, RS } },
++{ "exts", XRC(31,922,0), XRB_MASK, PWRCOM, { RA, RS } },
++{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } },
++{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } },
++
++{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA, RB } },
++
++{ "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } },
++{ "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } },
++{ "tlbre", X(31,946), X_MASK, BOOKE, { 0 } },
++{ "tlbre", X(31,946), X_MASK, PPC403, { RS, RA, SH } },
++
++{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } },
++{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } },
++
++{ "extsb", XRC(31,954,0), XRB_MASK, PPC, { RA, RS} },
++{ "extsb.", XRC(31,954,1), XRB_MASK, PPC, { RA, RS} },
++
++{ "stduxe", X(31,959), X_MASK, BOOKE64, { RS, RAS, RB } },
++
++{ "iccci", X(31,966), XRT_MASK, PPC403|PPC440, { RA, RB } },
++
++{ "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } },
++{ "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } },
++{ "tlbwe", X(31,978), X_MASK, BOOKE, { 0 } },
++{ "tlbwe", X(31,978), X_MASK, PPC403, { RS, RA, SH } },
++{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } },
++
++{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } },
++
++{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA, RB } },
++
++{ "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } },
++{ "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } },
++
++{ "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } },
++
++{ "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } },
++{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA, RB } },
++
++{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } },
++
++{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
++{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
++
++{ "dcbze", X(31,1022), XRT_MASK, BOOKE64, { RA, RB } },
++
++{ "lvebx", X(31, 7), X_MASK, PPCVEC, { VD, RA, RB } },
++{ "lvehx", X(31, 39), X_MASK, PPCVEC, { VD, RA, RB } },
++{ "lvewx", X(31, 71), X_MASK, PPCVEC, { VD, RA, RB } },
++{ "lvsl", X(31, 6), X_MASK, PPCVEC, { VD, RA, RB } },
++{ "lvsr", X(31, 38), X_MASK, PPCVEC, { VD, RA, RB } },
++{ "lvx", X(31, 103), X_MASK, PPCVEC, { VD, RA, RB } },
++{ "lvxl", X(31, 359), X_MASK, PPCVEC, { VD, RA, RB } },
++{ "stvebx", X(31, 135), X_MASK, PPCVEC, { VS, RA, RB } },
++{ "stvehx", X(31, 167), X_MASK, PPCVEC, { VS, RA, RB } },
++{ "stvewx", X(31, 199), X_MASK, PPCVEC, { VS, RA, RB } },
++{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } },
++{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } },
++
++{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA } },
++{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA } },
++
++{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } },
++{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA } },
++
++{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA } },
++
++{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } },
++
++{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA } },
++{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA } },
++
++{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } },
++{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA } },
++
++{ "stb", OP(38), OP_MASK, COM, { RS, D, RA } },
++
++{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } },
++
++{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA } },
++
++{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } },
++
++{ "lha", OP(42), OP_MASK, COM, { RT, D, RA } },
++
++{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } },
++
++{ "sth", OP(44), OP_MASK, COM, { RS, D, RA } },
++
++{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } },
++
++{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } },
++{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA } },
++
++{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA } },
++{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA } },
++
++{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA } },
++
++{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } },
++
++{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA } },
++
++{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } },
++
++{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA } },
++
++{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } },
++
++{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA } },
++
++{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } },
++
++{ "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } },
++
++{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA } },
++
++{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA } },
++
++{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA } },
++{ "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } },
++{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA } },
++{ "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } },
++{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA } },
++{ "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } },
++{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA } },
++{ "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } },
++{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA } },
++{ "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } },
++{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA } },
++{ "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } },
++{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA } },
++{ "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } },
++
++{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA } },
++
++{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } },
++
++{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA } },
++
++{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
++{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
++
++{ "fsubs", A(59,20,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
++{ "fsubs.", A(59,20,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
++
++{ "fadds", A(59,21,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
++{ "fadds.", A(59,21,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
++
++{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
++{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
++
++{ "fres", A(59,24,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
++{ "fres.", A(59,24,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
++
++{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } },
++{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } },
++
++{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++
++{ "fmadds", A(59,29,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++{ "fmadds.", A(59,29,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++
++{ "fnmsubs", A(59,30,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++{ "fnmsubs.",A(59,30,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++
++{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++
++{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } },
++
++{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } },
++
++{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA } },
++{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA } },
++{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA } },
++{ "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } },
++{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA } },
++{ "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } },
++{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA } },
++{ "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } },
++{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA } },
++{ "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } },
++{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA } },
++{ "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } },
++
++{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA } },
++
++{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } },
++
++{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA } },
++
++{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
++
++{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } },
++{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } },
++
++{ "fctiw", XRC(63,14,0), XRA_MASK, PPCCOM, { FRT, FRB } },
++{ "fcir", XRC(63,14,0), XRA_MASK, POWER2, { FRT, FRB } },
++{ "fctiw.", XRC(63,14,1), XRA_MASK, PPCCOM, { FRT, FRB } },
++{ "fcir.", XRC(63,14,1), XRA_MASK, POWER2, { FRT, FRB } },
++
++{ "fctiwz", XRC(63,15,0), XRA_MASK, PPCCOM, { FRT, FRB } },
++{ "fcirz", XRC(63,15,0), XRA_MASK, POWER2, { FRT, FRB } },
++{ "fctiwz.", XRC(63,15,1), XRA_MASK, PPCCOM, { FRT, FRB } },
++{ "fcirz.", XRC(63,15,1), XRA_MASK, POWER2, { FRT, FRB } },
++
++{ "fdiv", A(63,18,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
++{ "fd", A(63,18,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
++{ "fdiv.", A(63,18,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
++{ "fd.", A(63,18,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
++
++{ "fsub", A(63,20,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
++{ "fs", A(63,20,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
++{ "fsub.", A(63,20,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
++{ "fs.", A(63,20,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
++
++{ "fadd", A(63,21,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
++{ "fa", A(63,21,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
++{ "fadd.", A(63,21,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
++{ "fa.", A(63,21,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
++
++{ "fsqrt", A(63,22,0), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } },
++{ "fsqrt.", A(63,22,1), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } },
++
++{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
++
++{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
++{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
++{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
++{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
++
++{ "frsqrte", A(63,26,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
++{ "frsqrte.",A(63,26,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
++
++{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++{ "fmsub.", A(63,28,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fms.", A(63,28,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++
++{ "fmadd", A(63,29,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fma", A(63,29,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++{ "fmadd.", A(63,29,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fma.", A(63,29,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++
++{ "fnmsub", A(63,30,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fnms", A(63,30,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++{ "fnmsub.", A(63,30,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fnms.", A(63,30,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++
++{ "fnmadd", A(63,31,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fnma", A(63,31,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++{ "fnmadd.", A(63,31,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
++{ "fnma.", A(63,31,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
++
++{ "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
++
++{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } },
++{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } },
++
++{ "fneg", XRC(63,40,0), XRA_MASK, COM, { FRT, FRB } },
++{ "fneg.", XRC(63,40,1), XRA_MASK, COM, { FRT, FRB } },
++
++{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } },
++
++{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } },
++{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } },
++
++{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } },
++{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } },
++
++{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
++{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
++
++{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } },
++{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } },
++
++{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } },
++{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } },
++
++{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } },
++{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } },
++
++{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } },
++{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } },
++
++{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } },
++{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } },
++
++{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } },
++{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } },
++
++{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } },
++{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } },
++
++};
++
++const int powerpc_num_opcodes =
++ sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]);
++
++/* The macro table. This is only used by the assembler. */
++
++/* The expressions of the form (-x ! 31) & (x | 31) have the value 0
++ when x=0; 32-x when x is between 1 and 31; are negative if x is
++ negative; and are 32 or more otherwise. This is what you want
++ when, for instance, you are emulating a right shift by a
++ rotate-left-and-mask, because the underlying instructions support
++ shifts of size 0 but not shifts of size 32. By comparison, when
++ extracting x bits from some word you want to use just 32-x, because
++ the underlying instructions don't support extracting 0 bits but do
++ support extracting the whole word (32 bits in this case). */
++
++const struct powerpc_macro powerpc_macros[] = {
++{ "extldi", 4, PPC64, "rldicr %0,%1,%3,(%2)-1" },
++{ "extldi.", 4, PPC64, "rldicr. %0,%1,%3,(%2)-1" },
++{ "extrdi", 4, PPC64, "rldicl %0,%1,(%2)+(%3),64-(%2)" },
++{ "extrdi.", 4, PPC64, "rldicl. %0,%1,(%2)+(%3),64-(%2)" },
++{ "insrdi", 4, PPC64, "rldimi %0,%1,64-((%2)+(%3)),%3" },
++{ "insrdi.", 4, PPC64, "rldimi. %0,%1,64-((%2)+(%3)),%3" },
++{ "rotrdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),0" },
++{ "rotrdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),0" },
++{ "sldi", 3, PPC64, "rldicr %0,%1,%2,63-(%2)" },
++{ "sldi.", 3, PPC64, "rldicr. %0,%1,%2,63-(%2)" },
++{ "srdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),%2" },
++{ "srdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),%2" },
++{ "clrrdi", 3, PPC64, "rldicr %0,%1,0,63-(%2)" },
++{ "clrrdi.", 3, PPC64, "rldicr. %0,%1,0,63-(%2)" },
++{ "clrlsldi",4, PPC64, "rldic %0,%1,%3,(%2)-(%3)" },
++{ "clrlsldi.",4, PPC64, "rldic. %0,%1,%3,(%2)-(%3)" },
++
++{ "extlwi", 4, PPCCOM, "rlwinm %0,%1,%3,0,(%2)-1" },
++{ "extlwi.", 4, PPCCOM, "rlwinm. %0,%1,%3,0,(%2)-1" },
++{ "extrwi", 4, PPCCOM, "rlwinm %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" },
++{ "extrwi.", 4, PPCCOM, "rlwinm. %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" },
++{ "inslwi", 4, PPCCOM, "rlwimi %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1" },
++{ "inslwi.", 4, PPCCOM, "rlwimi. %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1"},
++{ "insrwi", 4, PPCCOM, "rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" },
++{ "insrwi.", 4, PPCCOM, "rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"},
++{ "rotrwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),0,31" },
++{ "rotrwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),0,31" },
++{ "slwi", 3, PPCCOM, "rlwinm %0,%1,%2,0,31-(%2)" },
++{ "sli", 3, PWRCOM, "rlinm %0,%1,%2,0,31-(%2)" },
++{ "slwi.", 3, PPCCOM, "rlwinm. %0,%1,%2,0,31-(%2)" },
++{ "sli.", 3, PWRCOM, "rlinm. %0,%1,%2,0,31-(%2)" },
++{ "srwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
++{ "sri", 3, PWRCOM, "rlinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
++{ "srwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
++{ "sri.", 3, PWRCOM, "rlinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
++{ "clrrwi", 3, PPCCOM, "rlwinm %0,%1,0,0,31-(%2)" },
++{ "clrrwi.", 3, PPCCOM, "rlwinm. %0,%1,0,0,31-(%2)" },
++{ "clrlslwi",4, PPCCOM, "rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" },
++{ "clrlslwi.",4, PPCCOM, "rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" },
++};
++
++const int powerpc_num_macros =
++ sizeof (powerpc_macros) / sizeof (powerpc_macros[0]);
+diff --git a/arch/powerpc/xmon/ppc.h b/arch/powerpc/xmon/ppc.h
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/ppc.h
+@@ -0,0 +1,307 @@
++/* ppc.h -- Header file for PowerPC opcode table
++ Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003
++ Free Software Foundation, Inc.
++ Written by Ian Lance Taylor, Cygnus Support
++
++This file is part of GDB, GAS, and the GNU binutils.
++
++GDB, GAS, and the GNU binutils are free software; you can redistribute
++them and/or modify them under the terms of the GNU General Public
++License as published by the Free Software Foundation; either version
++1, or (at your option) any later version.
++
++GDB, GAS, and the GNU binutils are distributed in the hope that they
++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 file; see the file COPYING. If not, write to the Free
++Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
++
++#ifndef PPC_H
++#define PPC_H
++
++/* The opcode table is an array of struct powerpc_opcode. */
++
++struct powerpc_opcode
++{
++ /* The opcode name. */
++ const char *name;
++
++ /* The opcode itself. Those bits which will be filled in with
++ operands are zeroes. */
++ unsigned long opcode;
++
++ /* The opcode mask. This is used by the disassembler. This is a
++ mask containing ones indicating those bits which must match the
++ opcode field, and zeroes indicating those bits which need not
++ match (and are presumably filled in by operands). */
++ unsigned long mask;
++
++ /* One bit flags for the opcode. These are used to indicate which
++ specific processors support the instructions. The defined values
++ are listed below. */
++ unsigned long flags;
++
++ /* An array of operand codes. Each code is an index into the
++ operand table. They appear in the order which the operands must
++ appear in assembly code, and are terminated by a zero. */
++ unsigned char operands[8];
++};
++
++/* The table itself is sorted by major opcode number, and is otherwise
++ in the order in which the disassembler should consider
++ instructions. */
++extern const struct powerpc_opcode powerpc_opcodes[];
++extern const int powerpc_num_opcodes;
++
++/* Values defined for the flags field of a struct powerpc_opcode. */
++
++/* Opcode is defined for the PowerPC architecture. */
++#define PPC_OPCODE_PPC 1
++
++/* Opcode is defined for the POWER (RS/6000) architecture. */
++#define PPC_OPCODE_POWER 2
++
++/* Opcode is defined for the POWER2 (Rios 2) architecture. */
++#define PPC_OPCODE_POWER2 4
++
++/* Opcode is only defined on 32 bit architectures. */
++#define PPC_OPCODE_32 8
++
++/* Opcode is only defined on 64 bit architectures. */
++#define PPC_OPCODE_64 0x10
++
++/* Opcode is supported by the Motorola PowerPC 601 processor. The 601
++ is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
++ but it also supports many additional POWER instructions. */
++#define PPC_OPCODE_601 0x20
++
++/* Opcode is supported in both the Power and PowerPC architectures
++ (ie, compiler's -mcpu=common or assembler's -mcom). */
++#define PPC_OPCODE_COMMON 0x40
++
++/* Opcode is supported for any Power or PowerPC platform (this is
++ for the assembler's -many option, and it eliminates duplicates). */
++#define PPC_OPCODE_ANY 0x80
++
++/* Opcode is supported as part of the 64-bit bridge. */
++#define PPC_OPCODE_64_BRIDGE 0x100
++
++/* Opcode is supported by Altivec Vector Unit */
++#define PPC_OPCODE_ALTIVEC 0x200
++
++/* Opcode is supported by PowerPC 403 processor. */
++#define PPC_OPCODE_403 0x400
++
++/* Opcode is supported by PowerPC BookE processor. */
++#define PPC_OPCODE_BOOKE 0x800
++
++/* Opcode is only supported by 64-bit PowerPC BookE processor. */
++#define PPC_OPCODE_BOOKE64 0x1000
++
++/* Opcode is supported by PowerPC 440 processor. */
++#define PPC_OPCODE_440 0x2000
++
++/* Opcode is only supported by Power4 architecture. */
++#define PPC_OPCODE_POWER4 0x4000
++
++/* Opcode isn't supported by Power4 architecture. */
++#define PPC_OPCODE_NOPOWER4 0x8000
++
++/* Opcode is only supported by POWERPC Classic architecture. */
++#define PPC_OPCODE_CLASSIC 0x10000
++
++/* Opcode is only supported by e500x2 Core. */
++#define PPC_OPCODE_SPE 0x20000
++
++/* Opcode is supported by e500x2 Integer select APU. */
++#define PPC_OPCODE_ISEL 0x40000
++
++/* Opcode is an e500 SPE floating point instruction. */
++#define PPC_OPCODE_EFS 0x80000
++
++/* Opcode is supported by branch locking APU. */
++#define PPC_OPCODE_BRLOCK 0x100000
++
++/* Opcode is supported by performance monitor APU. */
++#define PPC_OPCODE_PMR 0x200000
++
++/* Opcode is supported by cache locking APU. */
++#define PPC_OPCODE_CACHELCK 0x400000
++
++/* Opcode is supported by machine check APU. */
++#define PPC_OPCODE_RFMCI 0x800000
++
++/* A macro to extract the major opcode from an instruction. */
++#define PPC_OP(i) (((i) >> 26) & 0x3f)
++
++/* The operands table is an array of struct powerpc_operand. */
++
++struct powerpc_operand
++{
++ /* The number of bits in the operand. */
++ int bits;
++
++ /* How far the operand is left shifted in the instruction. */
++ int shift;
++
++ /* Insertion function. This is used by the assembler. To insert an
++ operand value into an instruction, check this field.
++
++ If it is NULL, execute
++ i |= (op & ((1 << o->bits) - 1)) << o->shift;
++ (i is the instruction which we are filling in, o is a pointer to
++ this structure, and op is the opcode value; this assumes twos
++ complement arithmetic).
++
++ If this field is not NULL, then simply call it with the
++ instruction and the operand value. It will return the new value
++ of the instruction. If the ERRMSG argument is not NULL, then if
++ the operand value is illegal, *ERRMSG will be set to a warning
++ string (the operand will be inserted in any case). If the
++ operand value is legal, *ERRMSG will be unchanged (most operands
++ can accept any value). */
++ unsigned long (*insert)
++ (unsigned long instruction, long op, int dialect, const char **errmsg);
++
++ /* Extraction function. This is used by the disassembler. To
++ extract this operand type from an instruction, check this field.
++
++ If it is NULL, compute
++ op = ((i) >> o->shift) & ((1 << o->bits) - 1);
++ if ((o->flags & PPC_OPERAND_SIGNED) != 0
++ && (op & (1 << (o->bits - 1))) != 0)
++ op -= 1 << o->bits;
++ (i is the instruction, o is a pointer to this structure, and op
++ is the result; this assumes twos complement arithmetic).
++
++ If this field is not NULL, then simply call it with the
++ instruction value. It will return the value of the operand. If
++ the INVALID argument is not NULL, *INVALID will be set to
++ non-zero if this operand type can not actually be extracted from
++ this operand (i.e., the instruction does not match). If the
++ operand is valid, *INVALID will not be changed. */
++ long (*extract) (unsigned long instruction, int dialect, int *invalid);
++
++ /* One bit syntax flags. */
++ unsigned long flags;
++};
++
++/* Elements in the table are retrieved by indexing with values from
++ the operands field of the powerpc_opcodes table. */
++
++extern const struct powerpc_operand powerpc_operands[];
++
++/* Values defined for the flags field of a struct powerpc_operand. */
++
++/* This operand takes signed values. */
++#define PPC_OPERAND_SIGNED (01)
++
++/* This operand takes signed values, but also accepts a full positive
++ range of values when running in 32 bit mode. That is, if bits is
++ 16, it takes any value from -0x8000 to 0xffff. In 64 bit mode,
++ this flag is ignored. */
++#define PPC_OPERAND_SIGNOPT (02)
++
++/* This operand does not actually exist in the assembler input. This
++ is used to support extended mnemonics such as mr, for which two
++ operands fields are identical. The assembler should call the
++ insert function with any op value. The disassembler should call
++ the extract function, ignore the return value, and check the value
++ placed in the valid argument. */
++#define PPC_OPERAND_FAKE (04)
++
++/* The next operand should be wrapped in parentheses rather than
++ separated from this one by a comma. This is used for the load and
++ store instructions which want their operands to look like
++ reg,displacement(reg)
++ */
++#define PPC_OPERAND_PARENS (010)
++
++/* This operand may use the symbolic names for the CR fields, which
++ are
++ lt 0 gt 1 eq 2 so 3 un 3
++ cr0 0 cr1 1 cr2 2 cr3 3
++ cr4 4 cr5 5 cr6 6 cr7 7
++ These may be combined arithmetically, as in cr2*4+gt. These are
++ only supported on the PowerPC, not the POWER. */
++#define PPC_OPERAND_CR (020)
++
++/* This operand names a register. The disassembler uses this to print
++ register names with a leading 'r'. */
++#define PPC_OPERAND_GPR (040)
++
++/* This operand names a floating point register. The disassembler
++ prints these with a leading 'f'. */
++#define PPC_OPERAND_FPR (0100)
++
++/* This operand is a relative branch displacement. The disassembler
++ prints these symbolically if possible. */
++#define PPC_OPERAND_RELATIVE (0200)
++
++/* This operand is an absolute branch address. The disassembler
++ prints these symbolically if possible. */
++#define PPC_OPERAND_ABSOLUTE (0400)
++
++/* This operand is optional, and is zero if omitted. This is used for
++ the optional BF and L fields in the comparison instructions. The
++ assembler must count the number of operands remaining on the line,
++ and the number of operands remaining for the opcode, and decide
++ whether this operand is present or not. The disassembler should
++ print this operand out only if it is not zero. */
++#define PPC_OPERAND_OPTIONAL (01000)
++
++/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
++ is omitted, then for the next operand use this operand value plus
++ 1, ignoring the next operand field for the opcode. This wretched
++ hack is needed because the Power rotate instructions can take
++ either 4 or 5 operands. The disassembler should print this operand
++ out regardless of the PPC_OPERAND_OPTIONAL field. */
++#define PPC_OPERAND_NEXT (02000)
++
++/* This operand should be regarded as a negative number for the
++ purposes of overflow checking (i.e., the normal most negative
++ number is disallowed and one more than the normal most positive
++ number is allowed). This flag will only be set for a signed
++ operand. */
++#define PPC_OPERAND_NEGATIVE (04000)
++
++/* This operand names a vector unit register. The disassembler
++ prints these with a leading 'v'. */
++#define PPC_OPERAND_VR (010000)
++
++/* This operand is for the DS field in a DS form instruction. */
++#define PPC_OPERAND_DS (020000)
++
++/* This operand is for the DQ field in a DQ form instruction. */
++#define PPC_OPERAND_DQ (040000)
++
++/* The POWER and PowerPC assemblers use a few macros. We keep them
++ with the operands table for simplicity. The macro table is an
++ array of struct powerpc_macro. */
++
++struct powerpc_macro
++{
++ /* The macro name. */
++ const char *name;
++
++ /* The number of operands the macro takes. */
++ unsigned int operands;
++
++ /* One bit flags for the opcode. These are used to indicate which
++ specific processors support the instructions. The values are the
++ same as those for the struct powerpc_opcode flags field. */
++ unsigned long flags;
++
++ /* A format string to turn the macro into a normal instruction.
++ Each %N in the string is replaced with operand number N (zero
++ based). */
++ const char *format;
++};
++
++extern const struct powerpc_macro powerpc_macros[];
++extern const int powerpc_num_macros;
++
++#endif /* PPC_H */
+diff --git a/arch/powerpc/xmon/setjmp.S b/arch/powerpc/xmon/setjmp.S
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/setjmp.S
+@@ -0,0 +1,135 @@
++/*
++ * Copyright (C) 1996 Paul Mackerras.
++ *
++ * 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.
++ *
++ * NOTE: assert(sizeof(buf) > 23 * sizeof(long))
++ */
++#include <asm/processor.h>
++#include <asm/ppc_asm.h>
++#include <asm/asm-offsets.h>
++
++_GLOBAL(xmon_setjmp)
++ mflr r0
++ STL r0,0(r3)
++ STL r1,SZL(r3)
++ STL r2,2*SZL(r3)
++ mfcr r0
++ STL r0,3*SZL(r3)
++ STL r13,4*SZL(r3)
++ STL r14,5*SZL(r3)
++ STL r15,6*SZL(r3)
++ STL r16,7*SZL(r3)
++ STL r17,8*SZL(r3)
++ STL r18,9*SZL(r3)
++ STL r19,10*SZL(r3)
++ STL r20,11*SZL(r3)
++ STL r21,12*SZL(r3)
++ STL r22,13*SZL(r3)
++ STL r23,14*SZL(r3)
++ STL r24,15*SZL(r3)
++ STL r25,16*SZL(r3)
++ STL r26,17*SZL(r3)
++ STL r27,18*SZL(r3)
++ STL r28,19*SZL(r3)
++ STL r29,20*SZL(r3)
++ STL r30,21*SZL(r3)
++ STL r31,22*SZL(r3)
++ li r3,0
++ blr
++
++_GLOBAL(xmon_longjmp)
++ CMPI r4,0
++ bne 1f
++ li r4,1
++1: LDL r13,4*SZL(r3)
++ LDL r14,5*SZL(r3)
++ LDL r15,6*SZL(r3)
++ LDL r16,7*SZL(r3)
++ LDL r17,8*SZL(r3)
++ LDL r18,9*SZL(r3)
++ LDL r19,10*SZL(r3)
++ LDL r20,11*SZL(r3)
++ LDL r21,12*SZL(r3)
++ LDL r22,13*SZL(r3)
++ LDL r23,14*SZL(r3)
++ LDL r24,15*SZL(r3)
++ LDL r25,16*SZL(r3)
++ LDL r26,17*SZL(r3)
++ LDL r27,18*SZL(r3)
++ LDL r28,19*SZL(r3)
++ LDL r29,20*SZL(r3)
++ LDL r30,21*SZL(r3)
++ LDL r31,22*SZL(r3)
++ LDL r0,3*SZL(r3)
++ mtcrf 0x38,r0
++ LDL r0,0(r3)
++ LDL r1,SZL(r3)
++ LDL r2,2*SZL(r3)
++ mtlr r0
++ mr r3,r4
++ blr
++
++/*
++ * Grab the register values as they are now.
++ * This won't do a particularily good job because we really
++ * want our caller's caller's registers, and our caller has
++ * already executed its prologue.
++ * ToDo: We could reach back into the caller's save area to do
++ * a better job of representing the caller's state (note that
++ * that will be different for 32-bit and 64-bit, because of the
++ * different ABIs, though).
++ */
++_GLOBAL(xmon_save_regs)
++ STL r0,0*SZL(r3)
++ STL r2,2*SZL(r3)
++ STL r3,3*SZL(r3)
++ STL r4,4*SZL(r3)
++ STL r5,5*SZL(r3)
++ STL r6,6*SZL(r3)
++ STL r7,7*SZL(r3)
++ STL r8,8*SZL(r3)
++ STL r9,9*SZL(r3)
++ STL r10,10*SZL(r3)
++ STL r11,11*SZL(r3)
++ STL r12,12*SZL(r3)
++ STL r13,13*SZL(r3)
++ STL r14,14*SZL(r3)
++ STL r15,15*SZL(r3)
++ STL r16,16*SZL(r3)
++ STL r17,17*SZL(r3)
++ STL r18,18*SZL(r3)
++ STL r19,19*SZL(r3)
++ STL r20,20*SZL(r3)
++ STL r21,21*SZL(r3)
++ STL r22,22*SZL(r3)
++ STL r23,23*SZL(r3)
++ STL r24,24*SZL(r3)
++ STL r25,25*SZL(r3)
++ STL r26,26*SZL(r3)
++ STL r27,27*SZL(r3)
++ STL r28,28*SZL(r3)
++ STL r29,29*SZL(r3)
++ STL r30,30*SZL(r3)
++ STL r31,31*SZL(r3)
++ /* go up one stack frame for SP */
++ LDL r4,0(r1)
++ STL r4,1*SZL(r3)
++ /* get caller's LR */
++ LDL r0,LRSAVE(r4)
++ STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
++ STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
++ mfmsr r0
++ STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
++ mfctr r0
++ STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
++ mfxer r0
++ STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
++ mfcr r0
++ STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
++ li r0,0
++ STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
++ blr
+diff --git a/arch/powerpc/xmon/start_32.c b/arch/powerpc/xmon/start_32.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/start_32.c
+@@ -0,0 +1,624 @@
++/*
++ * Copyright (C) 1996 Paul Mackerras.
++ */
++#include <linux/config.h>
++#include <linux/string.h>
++#include <asm/machdep.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++#include <linux/cuda.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/sysrq.h>
++#include <linux/bitops.h>
++#include <asm/xmon.h>
++#include <asm/prom.h>
++#include <asm/bootx.h>
++#include <asm/machdep.h>
++#include <asm/errno.h>
++#include <asm/pmac_feature.h>
++#include <asm/processor.h>
++#include <asm/delay.h>
++#include <asm/btext.h>
++
++static volatile unsigned char __iomem *sccc, *sccd;
++unsigned int TXRDY, RXRDY, DLAB;
++static int xmon_expect(const char *str, unsigned int timeout);
++
++static int use_serial;
++static int use_screen;
++static int via_modem;
++static int xmon_use_sccb;
++static struct device_node *channel_node;
++
++#define TB_SPEED 25000000
++
++static inline unsigned int readtb(void)
++{
++ unsigned int ret;
++
++ asm volatile("mftb %0" : "=r" (ret) :);
++ return ret;
++}
++
++void buf_access(void)
++{
++ if (DLAB)
++ sccd[3] &= ~DLAB; /* reset DLAB */
++}
++
++extern int adb_init(void);
++
++#ifdef CONFIG_PPC_CHRP
++/*
++ * This looks in the "ranges" property for the primary PCI host bridge
++ * to find the physical address of the start of PCI/ISA I/O space.
++ * It is basically a cut-down version of pci_process_bridge_OF_ranges.
++ */
++static unsigned long chrp_find_phys_io_base(void)
++{
++ struct device_node *node;
++ unsigned int *ranges;
++ unsigned long base = CHRP_ISA_IO_BASE;
++ int rlen = 0;
++ int np;
++
++ node = find_devices("isa");
++ if (node != NULL) {
++ node = node->parent;
++ if (node == NULL || node->type == NULL
++ || strcmp(node->type, "pci") != 0)
++ node = NULL;
++ }
++ if (node == NULL)
++ node = find_devices("pci");
++ if (node == NULL)
++ return base;
++
++ ranges = (unsigned int *) get_property(node, "ranges", &rlen);
++ np = prom_n_addr_cells(node) + 5;
++ while ((rlen -= np * sizeof(unsigned int)) >= 0) {
++ if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
++ /* I/O space starting at 0, grab the phys base */
++ base = ranges[np - 3];
++ break;
++ }
++ ranges += np;
++ }
++ return base;
++}
++#endif /* CONFIG_PPC_CHRP */
++
++#ifdef CONFIG_MAGIC_SYSRQ
++static void sysrq_handle_xmon(int key, struct pt_regs *regs,
++ struct tty_struct *tty)
++{
++ xmon(regs);
++}
++
++static struct sysrq_key_op sysrq_xmon_op =
++{
++ .handler = sysrq_handle_xmon,
++ .help_msg = "Xmon",
++ .action_msg = "Entering xmon",
++};
++#endif
++
++void
++xmon_map_scc(void)
++{
++#ifdef CONFIG_PPC_MULTIPLATFORM
++ volatile unsigned char __iomem *base;
++
++ if (_machine == _MACH_Pmac) {
++ struct device_node *np;
++ unsigned long addr;
++#ifdef CONFIG_BOOTX_TEXT
++ if (!use_screen && !use_serial
++ && !machine_is_compatible("iMac")) {
++ /* see if there is a keyboard in the device tree
++ with a parent of type "adb" */
++ for (np = find_devices("keyboard"); np; np = np->next)
++ if (np->parent && np->parent->type
++ && strcmp(np->parent->type, "adb") == 0)
++ break;
++
++ /* needs to be hacked if xmon_printk is to be used
++ from within find_via_pmu() */
++#ifdef CONFIG_ADB_PMU
++ if (np != NULL && boot_text_mapped && find_via_pmu())
++ use_screen = 1;
++#endif
++#ifdef CONFIG_ADB_CUDA
++ if (np != NULL && boot_text_mapped && find_via_cuda())
++ use_screen = 1;
++#endif
++ }
++ if (!use_screen && (np = find_devices("escc")) != NULL) {
++ /*
++ * look for the device node for the serial port
++ * we're using and see if it says it has a modem
++ */
++ char *name = xmon_use_sccb? "ch-b": "ch-a";
++ char *slots;
++ int l;
++
++ np = np->child;
++ while (np != NULL && strcmp(np->name, name) != 0)
++ np = np->sibling;
++ if (np != NULL) {
++ /* XXX should parse this properly */
++ channel_node = np;
++ slots = get_property(np, "slot-names", &l);
++ if (slots != NULL && l >= 10
++ && strcmp(slots+4, "Modem") == 0)
++ via_modem = 1;
++ }
++ }
++ btext_drawstring("xmon uses ");
++ if (use_screen)
++ btext_drawstring("screen and keyboard\n");
++ else {
++ if (via_modem)
++ btext_drawstring("modem on ");
++ btext_drawstring(xmon_use_sccb? "printer": "modem");
++ btext_drawstring(" port\n");
++ }
++
++#endif /* CONFIG_BOOTX_TEXT */
++
++#ifdef CHRP_ESCC
++ addr = 0xc1013020;
++#else
++ addr = 0xf3013020;
++#endif
++ TXRDY = 4;
++ RXRDY = 1;
++
++ np = find_devices("mac-io");
++ if (np && np->n_addrs)
++ addr = np->addrs[0].address + 0x13020;
++ base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
++ sccc = base + (addr & ~PAGE_MASK);
++ sccd = sccc + 0x10;
++
++ } else {
++ base = (volatile unsigned char *) isa_io_base;
++
++#ifdef CONFIG_PPC_CHRP
++ if (_machine == _MACH_chrp)
++ base = (volatile unsigned char __iomem *)
++ ioremap(chrp_find_phys_io_base(), 0x1000);
++#endif
++
++ sccc = base + 0x3fd;
++ sccd = base + 0x3f8;
++ if (xmon_use_sccb) {
++ sccc -= 0x100;
++ sccd -= 0x100;
++ }
++ TXRDY = 0x20;
++ RXRDY = 1;
++ DLAB = 0x80;
++ }
++#elif defined(CONFIG_GEMINI)
++ /* should already be mapped by the kernel boot */
++ sccc = (volatile unsigned char __iomem *) 0xffeffb0d;
++ sccd = (volatile unsigned char __iomem *) 0xffeffb08;
++ TXRDY = 0x20;
++ RXRDY = 1;
++ DLAB = 0x80;
++#elif defined(CONFIG_405GP)
++ sccc = (volatile unsigned char __iomem *)0xef600305;
++ sccd = (volatile unsigned char __iomem *)0xef600300;
++ TXRDY = 0x20;
++ RXRDY = 1;
++ DLAB = 0x80;
++#endif /* platform */
++
++ register_sysrq_key('x', &sysrq_xmon_op);
++}
++
++static int scc_initialized = 0;
++
++void xmon_init_scc(void);
++extern void cuda_poll(void);
++
++static inline void do_poll_adb(void)
++{
++#ifdef CONFIG_ADB_PMU
++ if (sys_ctrler == SYS_CTRLER_PMU)
++ pmu_poll_adb();
++#endif /* CONFIG_ADB_PMU */
++#ifdef CONFIG_ADB_CUDA
++ if (sys_ctrler == SYS_CTRLER_CUDA)
++ cuda_poll();
++#endif /* CONFIG_ADB_CUDA */
++}
++
++int
++xmon_write(void *handle, void *ptr, int nb)
++{
++ char *p = ptr;
++ int i, c, ct;
++
++#ifdef CONFIG_SMP
++ static unsigned long xmon_write_lock;
++ int lock_wait = 1000000;
++ int locked;
++
++ while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
++ if (--lock_wait == 0)
++ break;
++#endif
++
++#ifdef CONFIG_BOOTX_TEXT
++ if (use_screen) {
++ /* write it on the screen */
++ for (i = 0; i < nb; ++i)
++ btext_drawchar(*p++);
++ goto out;
++ }
++#endif
++ if (!scc_initialized)
++ xmon_init_scc();
++ ct = 0;
++ for (i = 0; i < nb; ++i) {
++ while ((*sccc & TXRDY) == 0)
++ do_poll_adb();
++ c = p[i];
++ if (c == '\n' && !ct) {
++ c = '\r';
++ ct = 1;
++ --i;
++ } else {
++ ct = 0;
++ }
++ buf_access();
++ *sccd = c;
++ eieio();
++ }
++
++ out:
++#ifdef CONFIG_SMP
++ if (!locked)
++ clear_bit(0, &xmon_write_lock);
++#endif
++ return nb;
++}
++
++int xmon_wants_key;
++int xmon_adb_keycode;
++
++#ifdef CONFIG_BOOTX_TEXT
++static int xmon_adb_shiftstate;
++
++static unsigned char xmon_keytab[128] =
++ "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
++ "yt123465=97-80]o" /* 0x10 - 0x1f */
++ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
++ "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
++ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
++ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
++
++static unsigned char xmon_shift_keytab[128] =
++ "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
++ "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
++ "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
++ "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
++ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
++ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
++
++static int
++xmon_get_adb_key(void)
++{
++ int k, t, on;
++
++ xmon_wants_key = 1;
++ for (;;) {
++ xmon_adb_keycode = -1;
++ t = 0;
++ on = 0;
++ do {
++ if (--t < 0) {
++ on = 1 - on;
++ btext_drawchar(on? 0xdb: 0x20);
++ btext_drawchar('\b');
++ t = 200000;
++ }
++ do_poll_adb();
++ } while (xmon_adb_keycode == -1);
++ k = xmon_adb_keycode;
++ if (on)
++ btext_drawstring(" \b");
++
++ /* test for shift keys */
++ if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
++ xmon_adb_shiftstate = (k & 0x80) == 0;
++ continue;
++ }
++ if (k >= 0x80)
++ continue; /* ignore up transitions */
++ k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
++ if (k != 0)
++ break;
++ }
++ xmon_wants_key = 0;
++ return k;
++}
++#endif /* CONFIG_BOOTX_TEXT */
++
++int
++xmon_read(void *handle, void *ptr, int nb)
++{
++ char *p = ptr;
++ int i;
++
++#ifdef CONFIG_BOOTX_TEXT
++ if (use_screen) {
++ for (i = 0; i < nb; ++i)
++ *p++ = xmon_get_adb_key();
++ return i;
++ }
++#endif
++ if (!scc_initialized)
++ xmon_init_scc();
++ for (i = 0; i < nb; ++i) {
++ while ((*sccc & RXRDY) == 0)
++ do_poll_adb();
++ buf_access();
++ *p++ = *sccd;
++ }
++ return i;
++}
++
++int
++xmon_read_poll(void)
++{
++ if ((*sccc & RXRDY) == 0) {
++ do_poll_adb();
++ return -1;
++ }
++ buf_access();
++ return *sccd;
++}
++
++static unsigned char scc_inittab[] = {
++ 13, 0, /* set baud rate divisor */
++ 12, 1,
++ 14, 1, /* baud rate gen enable, src=rtxc */
++ 11, 0x50, /* clocks = br gen */
++ 5, 0xea, /* tx 8 bits, assert DTR & RTS */
++ 4, 0x46, /* x16 clock, 1 stop */
++ 3, 0xc1, /* rx enable, 8 bits */
++};
++
++void
++xmon_init_scc(void)
++{
++ if ( _machine == _MACH_chrp )
++ {
++ sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
++ sccd[0] = 12; eieio(); /* DLL = 9600 baud */
++ sccd[1] = 0; eieio();
++ sccd[2] = 0; eieio(); /* FCR = 0 */
++ sccd[3] = 3; eieio(); /* LCR = 8N1 */
++ sccd[1] = 0; eieio(); /* IER = 0 */
++ }
++ else if ( _machine == _MACH_Pmac )
++ {
++ int i, x;
++
++ if (channel_node != 0)
++ pmac_call_feature(
++ PMAC_FTR_SCC_ENABLE,
++ channel_node,
++ PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
++ printk(KERN_INFO "Serial port locked ON by debugger !\n");
++ if (via_modem && channel_node != 0) {
++ unsigned int t0;
++
++ pmac_call_feature(
++ PMAC_FTR_MODEM_ENABLE,
++ channel_node, 0, 1);
++ printk(KERN_INFO "Modem powered up by debugger !\n");
++ t0 = readtb();
++ while (readtb() - t0 < 3*TB_SPEED)
++ eieio();
++ }
++ /* use the B channel if requested */
++ if (xmon_use_sccb) {
++ sccc = (volatile unsigned char *)
++ ((unsigned long)sccc & ~0x20);
++ sccd = sccc + 0x10;
++ }
++ for (i = 20000; i != 0; --i) {
++ x = *sccc; eieio();
++ }
++ *sccc = 9; eieio(); /* reset A or B side */
++ *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
++ for (i = 0; i < sizeof(scc_inittab); ++i) {
++ *sccc = scc_inittab[i];
++ eieio();
++ }
++ }
++ scc_initialized = 1;
++ if (via_modem) {
++ for (;;) {
++ xmon_write(NULL, "ATE1V1\r", 7);
++ if (xmon_expect("OK", 5)) {
++ xmon_write(NULL, "ATA\r", 4);
++ if (xmon_expect("CONNECT", 40))
++ break;
++ }
++ xmon_write(NULL, "+++", 3);
++ xmon_expect("OK", 3);
++ }
++ }
++}
++
++void *xmon_stdin;
++void *xmon_stdout;
++void *xmon_stderr;
++
++int xmon_putc(int c, void *f)
++{
++ char ch = c;
++
++ if (c == '\n')
++ xmon_putc('\r', f);
++ return xmon_write(f, &ch, 1) == 1? c: -1;
++}
++
++int xmon_putchar(int c)
++{
++ return xmon_putc(c, xmon_stdout);
++}
++
++int xmon_fputs(char *str, void *f)
++{
++ int n = strlen(str);
++
++ return xmon_write(f, str, n) == n? 0: -1;
++}
++
++int
++xmon_readchar(void)
++{
++ char ch;
++
++ for (;;) {
++ switch (xmon_read(xmon_stdin, &ch, 1)) {
++ case 1:
++ return ch;
++ case -1:
++ xmon_printf("read(stdin) returned -1\r\n", 0, 0);
++ return -1;
++ }
++ }
++}
++
++static char line[256];
++static char *lineptr;
++static int lineleft;
++
++int xmon_expect(const char *str, unsigned int timeout)
++{
++ int c;
++ unsigned int t0;
++
++ timeout *= TB_SPEED;
++ t0 = readtb();
++ do {
++ lineptr = line;
++ for (;;) {
++ c = xmon_read_poll();
++ if (c == -1) {
++ if (readtb() - t0 > timeout)
++ return 0;
++ continue;
++ }
++ if (c == '\n')
++ break;
++ if (c != '\r' && lineptr < &line[sizeof(line) - 1])
++ *lineptr++ = c;
++ }
++ *lineptr = 0;
++ } while (strstr(line, str) == NULL);
++ return 1;
++}
++
++int
++xmon_getchar(void)
++{
++ int c;
++
++ if (lineleft == 0) {
++ lineptr = line;
++ for (;;) {
++ c = xmon_readchar();
++ if (c == -1 || c == 4)
++ break;
++ if (c == '\r' || c == '\n') {
++ *lineptr++ = '\n';
++ xmon_putchar('\n');
++ break;
++ }
++ switch (c) {
++ case 0177:
++ case '\b':
++ if (lineptr > line) {
++ xmon_putchar('\b');
++ xmon_putchar(' ');
++ xmon_putchar('\b');
++ --lineptr;
++ }
++ break;
++ case 'U' & 0x1F:
++ while (lineptr > line) {
++ xmon_putchar('\b');
++ xmon_putchar(' ');
++ xmon_putchar('\b');
++ --lineptr;
++ }
++ break;
++ default:
++ if (lineptr >= &line[sizeof(line) - 1])
++ xmon_putchar('\a');
++ else {
++ xmon_putchar(c);
++ *lineptr++ = c;
++ }
++ }
++ }
++ lineleft = lineptr - line;
++ lineptr = line;
++ }
++ if (lineleft == 0)
++ return -1;
++ --lineleft;
++ return *lineptr++;
++}
++
++char *
++xmon_fgets(char *str, int nb, void *f)
++{
++ char *p;
++ int c;
++
++ for (p = str; p < str + nb - 1; ) {
++ c = xmon_getchar();
++ if (c == -1) {
++ if (p == str)
++ return NULL;
++ break;
++ }
++ *p++ = c;
++ if (c == '\n')
++ break;
++ }
++ *p = 0;
++ return str;
++}
++
++void
++xmon_enter(void)
++{
++#ifdef CONFIG_ADB_PMU
++ if (_machine == _MACH_Pmac) {
++ pmu_suspend();
++ }
++#endif
++}
++
++void
++xmon_leave(void)
++{
++#ifdef CONFIG_ADB_PMU
++ if (_machine == _MACH_Pmac) {
++ pmu_resume();
++ }
++#endif
++}
+diff --git a/arch/powerpc/xmon/start_64.c b/arch/powerpc/xmon/start_64.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/start_64.c
+@@ -0,0 +1,187 @@
++/*
++ * Copyright (C) 1996 Paul Mackerras.
++ *
++ * 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/string.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/sysrq.h>
++#include <linux/init.h>
++#include <asm/machdep.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/prom.h>
++#include <asm/processor.h>
++#include <asm/udbg.h>
++#include <asm/system.h>
++#include "nonstdio.h"
++
++#ifdef CONFIG_MAGIC_SYSRQ
++
++static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
++ struct tty_struct *tty)
++{
++ /* ensure xmon is enabled */
++ xmon_init(1);
++ debugger(pt_regs);
++}
++
++static struct sysrq_key_op sysrq_xmon_op =
++{
++ .handler = sysrq_handle_xmon,
++ .help_msg = "Xmon",
++ .action_msg = "Entering xmon",
++};
++
++static int __init setup_xmon_sysrq(void)
++{
++ register_sysrq_key('x', &sysrq_xmon_op);
++ return 0;
++}
++__initcall(setup_xmon_sysrq);
++#endif /* CONFIG_MAGIC_SYSRQ */
++
++int
++xmon_write(void *handle, void *ptr, int nb)
++{
++ return udbg_write(ptr, nb);
++}
++
++int
++xmon_read(void *handle, void *ptr, int nb)
++{
++ return udbg_read(ptr, nb);
++}
++
++int
++xmon_read_poll(void)
++{
++ if (udbg_getc_poll)
++ return udbg_getc_poll();
++ return -1;
++}
++
++FILE *xmon_stdin;
++FILE *xmon_stdout;
++
++int
++xmon_putc(int c, void *f)
++{
++ char ch = c;
++
++ if (c == '\n')
++ xmon_putc('\r', f);
++ return xmon_write(f, &ch, 1) == 1? c: -1;
++}
++
++int
++xmon_putchar(int c)
++{
++ return xmon_putc(c, xmon_stdout);
++}
++
++int
++xmon_fputs(char *str, void *f)
++{
++ int n = strlen(str);
++
++ return xmon_write(f, str, n) == n? 0: -1;
++}
++
++int
++xmon_readchar(void)
++{
++ char ch;
++
++ for (;;) {
++ switch (xmon_read(xmon_stdin, &ch, 1)) {
++ case 1:
++ return ch;
++ case -1:
++ xmon_printf("read(stdin) returned -1\r\n", 0, 0);
++ return -1;
++ }
++ }
++}
++
++static char line[256];
++static char *lineptr;
++static int lineleft;
++
++int
++xmon_getchar(void)
++{
++ int c;
++
++ if (lineleft == 0) {
++ lineptr = line;
++ for (;;) {
++ c = xmon_readchar();
++ if (c == -1 || c == 4)
++ break;
++ if (c == '\r' || c == '\n') {
++ *lineptr++ = '\n';
++ xmon_putchar('\n');
++ break;
++ }
++ switch (c) {
++ case 0177:
++ case '\b':
++ if (lineptr > line) {
++ xmon_putchar('\b');
++ xmon_putchar(' ');
++ xmon_putchar('\b');
++ --lineptr;
++ }
++ break;
++ case 'U' & 0x1F:
++ while (lineptr > line) {
++ xmon_putchar('\b');
++ xmon_putchar(' ');
++ xmon_putchar('\b');
++ --lineptr;
++ }
++ break;
++ default:
++ if (lineptr >= &line[sizeof(line) - 1])
++ xmon_putchar('\a');
++ else {
++ xmon_putchar(c);
++ *lineptr++ = c;
++ }
++ }
++ }
++ lineleft = lineptr - line;
++ lineptr = line;
++ }
++ if (lineleft == 0)
++ return -1;
++ --lineleft;
++ return *lineptr++;
++}
++
++char *
++xmon_fgets(char *str, int nb, void *f)
++{
++ char *p;
++ int c;
++
++ for (p = str; p < str + nb - 1; ) {
++ c = xmon_getchar();
++ if (c == -1) {
++ if (p == str)
++ return NULL;
++ break;
++ }
++ *p++ = c;
++ if (c == '\n')
++ break;
++ }
++ *p = 0;
++ return str;
++}
+diff --git a/arch/powerpc/xmon/start_8xx.c b/arch/powerpc/xmon/start_8xx.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/start_8xx.c
+@@ -0,0 +1,287 @@
++/*
++ * Copyright (C) 1996 Paul Mackerras.
++ * Copyright (C) 2000 Dan Malek.
++ * Quick hack of Paul's code to make XMON work on 8xx processors. Lots
++ * of assumptions, like the SMC1 is used, it has been initialized by the
++ * loader at some point, and we can just stuff and suck bytes.
++ * We rely upon the 8xx uart driver to support us, as the interface
++ * changes between boot up and operational phases of the kernel.
++ */
++#include <linux/string.h>
++#include <asm/machdep.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <linux/kernel.h>
++#include <asm/8xx_immap.h>
++#include <asm/mpc8xx.h>
++#include <asm/commproc.h>
++
++extern void xmon_printf(const char *fmt, ...);
++extern int xmon_8xx_write(char *str, int nb);
++extern int xmon_8xx_read_poll(void);
++extern int xmon_8xx_read_char(void);
++void prom_drawhex(uint);
++void prom_drawstring(const char *str);
++
++static int use_screen = 1; /* default */
++
++#define TB_SPEED 25000000
++
++static inline unsigned int readtb(void)
++{
++ unsigned int ret;
++
++ asm volatile("mftb %0" : "=r" (ret) :);
++ return ret;
++}
++
++void buf_access(void)
++{
++}
++
++void
++xmon_map_scc(void)
++{
++
++ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
++ use_screen = 0;
++
++ prom_drawstring("xmon uses serial port\n");
++}
++
++static int scc_initialized = 0;
++
++void xmon_init_scc(void);
++
++int
++xmon_write(void *handle, void *ptr, int nb)
++{
++ char *p = ptr;
++ int i, c, ct;
++
++ if (!scc_initialized)
++ xmon_init_scc();
++
++ return(xmon_8xx_write(ptr, nb));
++}
++
++int xmon_wants_key;
++
++int
++xmon_read(void *handle, void *ptr, int nb)
++{
++ char *p = ptr;
++ int i;
++
++ if (!scc_initialized)
++ xmon_init_scc();
++
++ for (i = 0; i < nb; ++i) {
++ *p++ = xmon_8xx_read_char();
++ }
++ return i;
++}
++
++int
++xmon_read_poll(void)
++{
++ return(xmon_8xx_read_poll());
++}
++
++void
++xmon_init_scc()
++{
++ scc_initialized = 1;
++}
++
++#if 0
++extern int (*prom_entry)(void *);
++
++int
++xmon_exit(void)
++{
++ struct prom_args {
++ char *service;
++ } args;
++
++ for (;;) {
++ args.service = "exit";
++ (*prom_entry)(&args);
++ }
++}
++#endif
++
++void *xmon_stdin;
++void *xmon_stdout;
++void *xmon_stderr;
++
++void
++xmon_init(void)
++{
++}
++
++int
++xmon_putc(int c, void *f)
++{
++ char ch = c;
++
++ if (c == '\n')
++ xmon_putc('\r', f);
++ return xmon_write(f, &ch, 1) == 1? c: -1;
++}
++
++int
++xmon_putchar(int c)
++{
++ return xmon_putc(c, xmon_stdout);
++}
++
++int
++xmon_fputs(char *str, void *f)
++{
++ int n = strlen(str);
++
++ return xmon_write(f, str, n) == n? 0: -1;
++}
++
++int
++xmon_readchar(void)
++{
++ char ch;
++
++ for (;;) {
++ switch (xmon_read(xmon_stdin, &ch, 1)) {
++ case 1:
++ return ch;
++ case -1:
++ xmon_printf("read(stdin) returned -1\r\n", 0, 0);
++ return -1;
++ }
++ }
++}
++
++static char line[256];
++static char *lineptr;
++static int lineleft;
++
++#if 0
++int xmon_expect(const char *str, unsigned int timeout)
++{
++ int c;
++ unsigned int t0;
++
++ timeout *= TB_SPEED;
++ t0 = readtb();
++ do {
++ lineptr = line;
++ for (;;) {
++ c = xmon_read_poll();
++ if (c == -1) {
++ if (readtb() - t0 > timeout)
++ return 0;
++ continue;
++ }
++ if (c == '\n')
++ break;
++ if (c != '\r' && lineptr < &line[sizeof(line) - 1])
++ *lineptr++ = c;
++ }
++ *lineptr = 0;
++ } while (strstr(line, str) == NULL);
++ return 1;
++}
++#endif
++
++int
++xmon_getchar(void)
++{
++ int c;
++
++ if (lineleft == 0) {
++ lineptr = line;
++ for (;;) {
++ c = xmon_readchar();
++ if (c == -1 || c == 4)
++ break;
++ if (c == '\r' || c == '\n') {
++ *lineptr++ = '\n';
++ xmon_putchar('\n');
++ break;
++ }
++ switch (c) {
++ case 0177:
++ case '\b':
++ if (lineptr > line) {
++ xmon_putchar('\b');
++ xmon_putchar(' ');
++ xmon_putchar('\b');
++ --lineptr;
++ }
++ break;
++ case 'U' & 0x1F:
++ while (lineptr > line) {
++ xmon_putchar('\b');
++ xmon_putchar(' ');
++ xmon_putchar('\b');
++ --lineptr;
++ }
++ break;
++ default:
++ if (lineptr >= &line[sizeof(line) - 1])
++ xmon_putchar('\a');
++ else {
++ xmon_putchar(c);
++ *lineptr++ = c;
++ }
++ }
++ }
++ lineleft = lineptr - line;
++ lineptr = line;
++ }
++ if (lineleft == 0)
++ return -1;
++ --lineleft;
++ return *lineptr++;
++}
++
++char *
++xmon_fgets(char *str, int nb, void *f)
++{
++ char *p;
++ int c;
++
++ for (p = str; p < str + nb - 1; ) {
++ c = xmon_getchar();
++ if (c == -1) {
++ if (p == str)
++ return 0;
++ break;
++ }
++ *p++ = c;
++ if (c == '\n')
++ break;
++ }
++ *p = 0;
++ return str;
++}
++
++void
++prom_drawhex(uint val)
++{
++ unsigned char buf[10];
++
++ int i;
++ for (i = 7; i >= 0; i--)
++ {
++ buf[i] = "0123456789abcdef"[val & 0x0f];
++ val >>= 4;
++ }
++ buf[8] = '\0';
++ xmon_fputs(buf, xmon_stdout);
++}
++
++void
++prom_drawstring(const char *str)
++{
++ xmon_fputs(str, xmon_stdout);
++}
+diff --git a/arch/powerpc/xmon/subr_prf.c b/arch/powerpc/xmon/subr_prf.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/subr_prf.c
+@@ -0,0 +1,54 @@
++/*
++ * Written by Cort Dougan to replace the version originally used
++ * by Paul Mackerras, which came from NetBSD and thus had copyright
++ * conflicts with Linux.
++ *
++ * This file makes liberal use of the standard linux utility
++ * routines to reduce the size of the binary. We assume we can
++ * trust some parts of Linux inside the debugger.
++ * -- Cort (cort at cs.nmt.edu)
++ *
++ * Copyright (C) 1999 Cort Dougan.
++ *
++ * 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/kernel.h>
++#include <linux/string.h>
++#include <linux/module.h>
++#include <stdarg.h>
++#include "nonstdio.h"
++
++extern int xmon_write(void *, void *, int);
++
++void xmon_vfprintf(void *f, const char *fmt, va_list ap)
++{
++ static char xmon_buf[2048];
++ int n;
++
++ n = vsprintf(xmon_buf, fmt, ap);
++ xmon_write(f, xmon_buf, n);
++}
++
++void xmon_printf(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ xmon_vfprintf(stdout, fmt, ap);
++ va_end(ap);
++}
++EXPORT_SYMBOL(xmon_printf);
++
++void xmon_fprintf(void *f, const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ xmon_vfprintf(f, fmt, ap);
++ va_end(ap);
++}
++
+diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
+new file mode 100644
+--- /dev/null
++++ b/arch/powerpc/xmon/xmon.c
+@@ -0,0 +1,2529 @@
++/*
++ * Routines providing a simple monitor for use on the PowerMac.
++ *
++ * Copyright (C) 1996 Paul Mackerras.
++ *
++ * 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/errno.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/mm.h>
++#include <linux/reboot.h>
++#include <linux/delay.h>
++#include <linux/kallsyms.h>
++#include <linux/cpumask.h>
++#include <linux/module.h>
++
++#include <asm/ptrace.h>
++#include <asm/string.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/xmon.h>
++#ifdef CONFIG_PMAC_BACKLIGHT
++#include <asm/backlight.h>
++#endif
++#include <asm/processor.h>
++#include <asm/pgtable.h>
++#include <asm/mmu.h>
++#include <asm/mmu_context.h>
++#include <asm/cputable.h>
++#include <asm/rtas.h>
++#include <asm/sstep.h>
++#include <asm/bug.h>
++
++#ifdef CONFIG_PPC64
++#include <asm/hvcall.h>
++#include <asm/paca.h>
++#endif
++
++#include "nonstdio.h"
++
++#define scanhex xmon_scanhex
++#define skipbl xmon_skipbl
++
++#ifdef CONFIG_SMP
++cpumask_t cpus_in_xmon = CPU_MASK_NONE;
++static unsigned long xmon_taken = 1;
++static int xmon_owner;
++static int xmon_gate;
++#endif /* CONFIG_SMP */
++
++static unsigned long in_xmon = 0;
++
++static unsigned long adrs;
++static int size = 1;
++#define MAX_DUMP (128 * 1024)
++static unsigned long ndump = 64;
++static unsigned long nidump = 16;
++static unsigned long ncsum = 4096;
++static int termch;
++static char tmpstr[128];
++
++#define JMP_BUF_LEN 23
++static long bus_error_jmp[JMP_BUF_LEN];
++static int catch_memory_errors;
++static long *xmon_fault_jmp[NR_CPUS];
++#define setjmp xmon_setjmp
++#define longjmp xmon_longjmp
++
++/* Breakpoint stuff */
++struct bpt {
++ unsigned long address;
++ unsigned int instr[2];
++ atomic_t ref_count;
++ int enabled;
++ unsigned long pad;
++};
++
++/* Bits in bpt.enabled */
++#define BP_IABR_TE 1 /* IABR translation enabled */
++#define BP_IABR 2
++#define BP_TRAP 8
++#define BP_DABR 0x10
++
++#define NBPTS 256
++static struct bpt bpts[NBPTS];
++static struct bpt dabr;
++static struct bpt *iabr;
++static unsigned bpinstr = 0x7fe00008; /* trap */
++
++#define BP_NUM(bp) ((bp) - bpts + 1)
++
++/* Prototypes */
++static int cmds(struct pt_regs *);
++static int mread(unsigned long, void *, int);
++static int mwrite(unsigned long, void *, int);
++static int handle_fault(struct pt_regs *);
++static void byterev(unsigned char *, int);
++static void memex(void);
++static int bsesc(void);
++static void dump(void);
++static void prdump(unsigned long, long);
++static int ppc_inst_dump(unsigned long, long, int);
++void print_address(unsigned long);
++static void backtrace(struct pt_regs *);
++static void excprint(struct pt_regs *);
++static void prregs(struct pt_regs *);
++static void memops(int);
++static void memlocate(void);
++static void memzcan(void);
++static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
++int skipbl(void);
++int scanhex(unsigned long *valp);
++static void scannl(void);
++static int hexdigit(int);
++void getstring(char *, int);
++static void flush_input(void);
++static int inchar(void);
++static void take_input(char *);
++static unsigned long read_spr(int);
++static void write_spr(int, unsigned long);
++static void super_regs(void);
++static void remove_bpts(void);
++static void insert_bpts(void);
++static void remove_cpu_bpts(void);
++static void insert_cpu_bpts(void);
++static struct bpt *at_breakpoint(unsigned long pc);
++static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
++static int do_step(struct pt_regs *);
++static void bpt_cmds(void);
++static void cacheflush(void);
++static int cpu_cmd(void);
++static void csum(void);
++static void bootcmds(void);
++static void proccall(void);
++void dump_segments(void);
++static void symbol_lookup(void);
++static void xmon_print_symbol(unsigned long address, const char *mid,
++ const char *after);
++static const char *getvecname(unsigned long vec);
++
++extern int print_insn_powerpc(unsigned long, unsigned long, int);
++extern void printf(const char *fmt, ...);
++extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
++extern int xmon_putc(int c, void *f);
++extern int putchar(int ch);
++
++extern void xmon_enter(void);
++extern void xmon_leave(void);
++
++extern int xmon_read_poll(void);
++extern long setjmp(long *);
++extern void longjmp(long *, long);
++extern void xmon_save_regs(struct pt_regs *);
++
++#ifdef CONFIG_PPC64
++#define REG "%.16lx"
++#define REGS_PER_LINE 4
++#define LAST_VOLATILE 13
++#else
++#define REG "%.8lx"
++#define REGS_PER_LINE 8
++#define LAST_VOLATILE 12
++#endif
++
++#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
++
++#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
++ || ('a' <= (c) && (c) <= 'f') \
++ || ('A' <= (c) && (c) <= 'F'))
++#define isalnum(c) (('0' <= (c) && (c) <= '9') \
++ || ('a' <= (c) && (c) <= 'z') \
++ || ('A' <= (c) && (c) <= 'Z'))
++#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
++
++static char *help_string = "\
++Commands:\n\
++ b show breakpoints\n\
++ bd set data breakpoint\n\
++ bi set instruction breakpoint\n\
++ bc clear breakpoint\n"
++#ifdef CONFIG_SMP
++ "\
++ c print cpus stopped in xmon\n\
++ c# try to switch to cpu number h (in hex)\n"
++#endif
++ "\
++ C checksum\n\
++ d dump bytes\n\
++ di dump instructions\n\
++ df dump float values\n\
++ dd dump double values\n\
++ e print exception information\n\
++ f flush cache\n\
++ la lookup symbol+offset of specified address\n\
++ ls lookup address of specified symbol\n\
++ m examine/change memory\n\
++ mm move a block of memory\n\
++ ms set a block of memory\n\
++ md compare two blocks of memory\n\
++ ml locate a block of memory\n\
++ mz zero a block of memory\n\
++ mi show information about memory allocation\n\
++ p call a procedure\n\
++ r print registers\n\
++ s single step\n\
++ S print special registers\n\
++ t print backtrace\n\
++ x exit monitor and recover\n\
++ X exit monitor and dont recover\n"
++#ifdef CONFIG_PPC64
++" u dump segment table or SLB\n"
++#endif
++#ifdef CONFIG_PPC_STD_MMU_32
++" u dump segment registers\n"
++#endif
++" ? help\n"
++" zr reboot\n\
++ zh halt\n"
++;
++
++static struct pt_regs *xmon_regs;
++
++static inline void sync(void)
++{
++ asm volatile("sync; isync");
++}
++
++static inline void store_inst(void *p)
++{
++ asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
++}
++
++static inline void cflush(void *p)
++{
++ asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
++}
++
++static inline void cinval(void *p)
++{
++ asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
++}
++
++/*
++ * Disable surveillance (the service processor watchdog function)
++ * while we are in xmon.
++ * XXX we should re-enable it when we leave. :)
++ */
++#define SURVEILLANCE_TOKEN 9000
++
++static inline void disable_surveillance(void)
++{
++#ifdef CONFIG_PPC_PSERIES
++ /* Since this can't be a module, args should end up below 4GB. */
++ static struct rtas_args args;
++
++ /*
++ * At this point we have got all the cpus we can into
++ * xmon, so there is hopefully no other cpu calling RTAS
++ * at the moment, even though we don't take rtas.lock.
++ * If we did try to take rtas.lock there would be a
++ * real possibility of deadlock.
++ */
++ args.token = rtas_token("set-indicator");
++ if (args.token == RTAS_UNKNOWN_SERVICE)
++ return;
++ args.nargs = 3;
++ args.nret = 1;
++ args.rets = &args.args[3];
++ args.args[0] = SURVEILLANCE_TOKEN;
++ args.args[1] = 0;
++ args.args[2] = 0;
++ enter_rtas(__pa(&args));
++#endif /* CONFIG_PPC_PSERIES */
++}
++
++#ifdef CONFIG_SMP
++static int xmon_speaker;
++
++static void get_output_lock(void)
++{
++ int me = smp_processor_id() + 0x100;
++ int last_speaker = 0, prev;
++ long timeout;
++
++ if (xmon_speaker == me)
++ return;
++ for (;;) {
++ if (xmon_speaker == 0) {
++ last_speaker = cmpxchg(&xmon_speaker, 0, me);
++ if (last_speaker == 0)
++ return;
++ }
++ timeout = 10000000;
++ while (xmon_speaker == last_speaker) {
++ if (--timeout > 0)
++ continue;
++ /* hostile takeover */
++ prev = cmpxchg(&xmon_speaker, last_speaker, me);
++ if (prev == last_speaker)
++ return;
++ break;
++ }
++ }
++}
++
++static void release_output_lock(void)
++{
++ xmon_speaker = 0;
++}
++#endif
++
++int xmon_core(struct pt_regs *regs, int fromipi)
++{
++ int cmd = 0;
++ unsigned long msr;
++ struct bpt *bp;
++ long recurse_jmp[JMP_BUF_LEN];
++ unsigned long offset;
++#ifdef CONFIG_SMP
++ int cpu;
++ int secondary;
++ unsigned long timeout;
++#endif
++
++ msr = mfmsr();
++ mtmsr(msr & ~MSR_EE); /* disable interrupts */
++
++ bp = in_breakpoint_table(regs->nip, &offset);
++ if (bp != NULL) {
++ regs->nip = bp->address + offset;
++ atomic_dec(&bp->ref_count);
++ }
++
++ remove_cpu_bpts();
++
++#ifdef CONFIG_SMP
++ cpu = smp_processor_id();
++ if (cpu_isset(cpu, cpus_in_xmon)) {
++ get_output_lock();
++ excprint(regs);
++ printf("cpu 0x%x: Exception %lx %s in xmon, "
++ "returning to main loop\n",
++ cpu, regs->trap, getvecname(TRAP(regs)));
++ release_output_lock();
++ longjmp(xmon_fault_jmp[cpu], 1);
++ }
++
++ if (setjmp(recurse_jmp) != 0) {
++ if (!in_xmon || !xmon_gate) {
++ get_output_lock();
++ printf("xmon: WARNING: bad recursive fault "
++ "on cpu 0x%x\n", cpu);
++ release_output_lock();
++ goto waiting;
++ }
++ secondary = !(xmon_taken && cpu == xmon_owner);
++ goto cmdloop;
++ }
++
++ xmon_fault_jmp[cpu] = recurse_jmp;
++ cpu_set(cpu, cpus_in_xmon);
++
++ bp = NULL;
++ if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
++ bp = at_breakpoint(regs->nip);
++ if (bp || (regs->msr & MSR_RI) == 0)
++ fromipi = 0;
++
++ if (!fromipi) {
++ get_output_lock();
++ excprint(regs);
++ if (bp) {
++ printf("cpu 0x%x stopped at breakpoint 0x%x (",
++ cpu, BP_NUM(bp));
++ xmon_print_symbol(regs->nip, " ", ")\n");
++ }
++ if ((regs->msr & MSR_RI) == 0)
++ printf("WARNING: exception is not recoverable, "
++ "can't continue\n");
++ release_output_lock();
++ }
++
++ waiting:
++ secondary = 1;
++ while (secondary && !xmon_gate) {
++ if (in_xmon == 0) {
++ if (fromipi)
++ goto leave;
++ secondary = test_and_set_bit(0, &in_xmon);
++ }
++ barrier();
++ }
++
++ if (!secondary && !xmon_gate) {
++ /* we are the first cpu to come in */
++ /* interrupt other cpu(s) */
++ int ncpus = num_online_cpus();
++
++ xmon_owner = cpu;
++ mb();
++ if (ncpus > 1) {
++ smp_send_debugger_break(MSG_ALL_BUT_SELF);
++ /* wait for other cpus to come in */
++ for (timeout = 100000000; timeout != 0; --timeout) {
++ if (cpus_weight(cpus_in_xmon) >= ncpus)
++ break;
++ barrier();
++ }
++ }
++ remove_bpts();
++ disable_surveillance();
++ /* for breakpoint or single step, print the current instr. */
++ if (bp || TRAP(regs) == 0xd00)
++ ppc_inst_dump(regs->nip, 1, 0);
++ printf("enter ? for help\n");
++ mb();
++ xmon_gate = 1;
++ barrier();
++ }
++
++ cmdloop:
++ while (in_xmon) {
++ if (secondary) {
++ if (cpu == xmon_owner) {
++ if (!test_and_set_bit(0, &xmon_taken)) {
++ secondary = 0;
++ continue;
++ }
++ /* missed it */
++ while (cpu == xmon_owner)
++ barrier();
++ }
++ barrier();
++ } else {
++ cmd = cmds(regs);
++ if (cmd != 0) {
++ /* exiting xmon */
++ insert_bpts();
++ xmon_gate = 0;
++ wmb();
++ in_xmon = 0;
++ break;
++ }
++ /* have switched to some other cpu */
++ secondary = 1;
++ }
++ }
++ leave:
++ cpu_clear(cpu, cpus_in_xmon);
++ xmon_fault_jmp[cpu] = NULL;
++
++#else
++ /* UP is simple... */
++ if (in_xmon) {
++ printf("Exception %lx %s in xmon, returning to main loop\n",
++ regs->trap, getvecname(TRAP(regs)));
++ longjmp(xmon_fault_jmp[0], 1);
++ }
++ if (setjmp(recurse_jmp) == 0) {
++ xmon_fault_jmp[0] = recurse_jmp;
++ in_xmon = 1;
++
++ excprint(regs);
++ bp = at_breakpoint(regs->nip);
++ if (bp) {
++ printf("Stopped at breakpoint %x (", BP_NUM(bp));
++ xmon_print_symbol(regs->nip, " ", ")\n");
++ }
++ if ((regs->msr & MSR_RI) == 0)
++ printf("WARNING: exception is not recoverable, "
++ "can't continue\n");
++ remove_bpts();
++ disable_surveillance();
++ /* for breakpoint or single step, print the current instr. */
++ if (bp || TRAP(regs) == 0xd00)
++ ppc_inst_dump(regs->nip, 1, 0);
++ printf("enter ? for help\n");
++ }
++
++ cmd = cmds(regs);
++
++ insert_bpts();
++ in_xmon = 0;
++#endif
++
++ if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
++ bp = at_breakpoint(regs->nip);
++ if (bp != NULL) {
++ int stepped = emulate_step(regs, bp->instr[0]);
++ if (stepped == 0) {
++ regs->nip = (unsigned long) &bp->instr[0];
++ atomic_inc(&bp->ref_count);
++ } else if (stepped < 0) {
++ printf("Couldn't single-step %s instruction\n",
++ (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
++ }
++ }
++ }
++
++ insert_cpu_bpts();
++
++ mtmsr(msr); /* restore interrupt enable */
++
++ return cmd != 'X';
++}
++
++int xmon(struct pt_regs *excp)
++{
++ struct pt_regs regs;
++
++ if (excp == NULL) {
++ xmon_save_regs(®s);
++ excp = ®s;
++ }
++ return xmon_core(excp, 0);
++}
++EXPORT_SYMBOL(xmon);
++
++irqreturn_t
++xmon_irq(int irq, void *d, struct pt_regs *regs)
++{
++ unsigned long flags;
++ local_irq_save(flags);
++ printf("Keyboard interrupt\n");
++ xmon(regs);
++ local_irq_restore(flags);
++ return IRQ_HANDLED;
++}
++
++int xmon_bpt(struct pt_regs *regs)
++{
++ struct bpt *bp;
++ unsigned long offset;
++
++ if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
++ return 0;
++
++ /* Are we at the trap at bp->instr[1] for some bp? */
++ bp = in_breakpoint_table(regs->nip, &offset);
++ if (bp != NULL && offset == 4) {
++ regs->nip = bp->address + 4;
++ atomic_dec(&bp->ref_count);
++ return 1;
++ }
++
++ /* Are we at a breakpoint? */
++ bp = at_breakpoint(regs->nip);
++ if (!bp)
++ return 0;
++
++ xmon_core(regs, 0);
++
++ return 1;
++}
++
++int xmon_sstep(struct pt_regs *regs)
++{
++ if (user_mode(regs))
++ return 0;
++ xmon_core(regs, 0);
++ return 1;
++}
++
++int xmon_dabr_match(struct pt_regs *regs)
++{
++ if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
++ return 0;
++ if (dabr.enabled == 0)
++ return 0;
++ xmon_core(regs, 0);
++ return 1;
++}
++
++int xmon_iabr_match(struct pt_regs *regs)
++{
++ if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
++ return 0;
++ if (iabr == 0)
++ return 0;
++ xmon_core(regs, 0);
++ return 1;
++}
++
++int xmon_ipi(struct pt_regs *regs)
++{
++#ifdef CONFIG_SMP
++ if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
++ xmon_core(regs, 1);
++#endif
++ return 0;
++}
++
++int xmon_fault_handler(struct pt_regs *regs)
++{
++ struct bpt *bp;
++ unsigned long offset;
++
++ if (in_xmon && catch_memory_errors)
++ handle_fault(regs); /* doesn't return */
++
++ if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
++ bp = in_breakpoint_table(regs->nip, &offset);
++ if (bp != NULL) {
++ regs->nip = bp->address + offset;
++ atomic_dec(&bp->ref_count);
++ }
++ }
++
++ return 0;
++}
++
++static struct bpt *at_breakpoint(unsigned long pc)
++{
++ int i;
++ struct bpt *bp;
++
++ bp = bpts;
++ for (i = 0; i < NBPTS; ++i, ++bp)
++ if (bp->enabled && pc == bp->address)
++ return bp;
++ return NULL;
++}
++
++static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
++{
++ unsigned long off;
++
++ off = nip - (unsigned long) bpts;
++ if (off >= sizeof(bpts))
++ return NULL;
++ off %= sizeof(struct bpt);
++ if (off != offsetof(struct bpt, instr[0])
++ && off != offsetof(struct bpt, instr[1]))
++ return NULL;
++ *offp = off - offsetof(struct bpt, instr[0]);
++ return (struct bpt *) (nip - off);
++}
++
++static struct bpt *new_breakpoint(unsigned long a)
++{
++ struct bpt *bp;
++
++ a &= ~3UL;
++ bp = at_breakpoint(a);
++ if (bp)
++ return bp;
++
++ for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
++ if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
++ bp->address = a;
++ bp->instr[1] = bpinstr;
++ store_inst(&bp->instr[1]);
++ return bp;
++ }
++ }
++
++ printf("Sorry, no free breakpoints. Please clear one first.\n");
++ return NULL;
++}
++
++static void insert_bpts(void)
++{
++ int i;
++ struct bpt *bp;
++
++ bp = bpts;
++ for (i = 0; i < NBPTS; ++i, ++bp) {
++ if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
++ continue;
++ if (mread(bp->address, &bp->instr[0], 4) != 4) {
++ printf("Couldn't read instruction at %lx, "
++ "disabling breakpoint there\n", bp->address);
++ bp->enabled = 0;
++ continue;
++ }
++ if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
++ printf("Breakpoint at %lx is on an mtmsrd or rfid "
++ "instruction, disabling it\n", bp->address);
++ bp->enabled = 0;
++ continue;
++ }
++ store_inst(&bp->instr[0]);
++ if (bp->enabled & BP_IABR)
++ continue;
++ if (mwrite(bp->address, &bpinstr, 4) != 4) {
++ printf("Couldn't write instruction at %lx, "
++ "disabling breakpoint there\n", bp->address);
++ bp->enabled &= ~BP_TRAP;
++ continue;
++ }
++ store_inst((void *)bp->address);
++ }
++}
++
++static void insert_cpu_bpts(void)
++{
++ if (dabr.enabled)
++ set_dabr(dabr.address | (dabr.enabled & 7));
++ if (iabr && cpu_has_feature(CPU_FTR_IABR))
++ mtspr(SPRN_IABR, iabr->address
++ | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
++}
++
++static void remove_bpts(void)
++{
++ int i;
++ struct bpt *bp;
++ unsigned instr;
++
++ bp = bpts;
++ for (i = 0; i < NBPTS; ++i, ++bp) {
++ if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
++ continue;
++ if (mread(bp->address, &instr, 4) == 4
++ && instr == bpinstr
++ && mwrite(bp->address, &bp->instr, 4) != 4)
++ printf("Couldn't remove breakpoint at %lx\n",
++ bp->address);
++ else
++ store_inst((void *)bp->address);
++ }
++}
++
++static void remove_cpu_bpts(void)
++{
++ set_dabr(0);
++ if (cpu_has_feature(CPU_FTR_IABR))
++ mtspr(SPRN_IABR, 0);
++}
++
++/* Command interpreting routine */
++static char *last_cmd;
++
++static int
++cmds(struct pt_regs *excp)
++{
++ int cmd = 0;
++
++ last_cmd = NULL;
++ xmon_regs = excp;
++ for(;;) {
++#ifdef CONFIG_SMP
++ printf("%x:", smp_processor_id());
++#endif /* CONFIG_SMP */
++ printf("mon> ");
++ fflush(stdout);
++ flush_input();
++ termch = 0;
++ cmd = skipbl();
++ if( cmd == '\n' ) {
++ if (last_cmd == NULL)
++ continue;
++ take_input(last_cmd);
++ last_cmd = NULL;
++ cmd = inchar();
++ }
++ switch (cmd) {
++ case 'm':
++ cmd = inchar();
++ switch (cmd) {
++ case 'm':
++ case 's':
++ case 'd':
++ memops(cmd);
++ break;
++ case 'l':
++ memlocate();
++ break;
++ case 'z':
++ memzcan();
++ break;
++ case 'i':
++ show_mem();
++ break;
++ default:
++ termch = cmd;
++ memex();
++ }
++ break;
++ case 'd':
++ dump();
++ break;
++ case 'l':
++ symbol_lookup();
++ break;
++ case 'r':
++ prregs(excp); /* print regs */
++ break;
++ case 'e':
++ excprint(excp);
++ break;
++ case 'S':
++ super_regs();
++ break;
++ case 't':
++ backtrace(excp);
++ break;
++ case 'f':
++ cacheflush();
++ break;
++ case 's':
++ if (do_step(excp))
++ return cmd;
++ break;
++ case 'x':
++ case 'X':
++ case EOF:
++ return cmd;
++ case '?':
++ printf(help_string);
++ break;
++ case 'b':
++ bpt_cmds();
++ break;
++ case 'C':
++ csum();
++ break;
++ case 'c':
++ if (cpu_cmd())
++ return 0;
++ break;
++ case 'z':
++ bootcmds();
++ break;
++ case 'p':
++ proccall();
++ break;
++#ifdef CONFIG_PPC_STD_MMU
++ case 'u':
++ dump_segments();
++ break;
++#endif
++ default:
++ printf("Unrecognized command: ");
++ do {
++ if (' ' < cmd && cmd <= '~')
++ putchar(cmd);
++ else
++ printf("\\x%x", cmd);
++ cmd = inchar();
++ } while (cmd != '\n');
++ printf(" (type ? for help)\n");
++ break;
++ }
++ }
++}
++
++/*
++ * Step a single instruction.
++ * Some instructions we emulate, others we execute with MSR_SE set.
++ */
++static int do_step(struct pt_regs *regs)
++{
++ unsigned int instr;
++ int stepped;
++
++ /* check we are in 64-bit kernel mode, translation enabled */
++ if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
++ if (mread(regs->nip, &instr, 4) == 4) {
++ stepped = emulate_step(regs, instr);
++ if (stepped < 0) {
++ printf("Couldn't single-step %s instruction\n",
++ (IS_RFID(instr)? "rfid": "mtmsrd"));
++ return 0;
++ }
++ if (stepped > 0) {
++ regs->trap = 0xd00 | (regs->trap & 1);
++ printf("stepped to ");
++ xmon_print_symbol(regs->nip, " ", "\n");
++ ppc_inst_dump(regs->nip, 1, 0);
++ return 0;
++ }
++ }
++ }
++ regs->msr |= MSR_SE;
++ return 1;
++}
++
++static void bootcmds(void)
++{
++ int cmd;
++
++ cmd = inchar();
++ if (cmd == 'r')
++ ppc_md.restart(NULL);
++ else if (cmd == 'h')
++ ppc_md.halt();
++ else if (cmd == 'p')
++ ppc_md.power_off();
++}
++
++static int cpu_cmd(void)
++{
++#ifdef CONFIG_SMP
++ unsigned long cpu;
++ int timeout;
++ int count;
++
++ if (!scanhex(&cpu)) {
++ /* print cpus waiting or in xmon */
++ printf("cpus stopped:");
++ count = 0;
++ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++ if (cpu_isset(cpu, cpus_in_xmon)) {
++ if (count == 0)
++ printf(" %x", cpu);
++ ++count;
++ } else {
++ if (count > 1)
++ printf("-%x", cpu - 1);
++ count = 0;
++ }
++ }
++ if (count > 1)
++ printf("-%x", NR_CPUS - 1);
++ printf("\n");
++ return 0;
++ }
++ /* try to switch to cpu specified */
++ if (!cpu_isset(cpu, cpus_in_xmon)) {
++ printf("cpu 0x%x isn't in xmon\n", cpu);
++ return 0;
++ }
++ xmon_taken = 0;
++ mb();
++ xmon_owner = cpu;
++ timeout = 10000000;
++ while (!xmon_taken) {
++ if (--timeout == 0) {
++ if (test_and_set_bit(0, &xmon_taken))
++ break;
++ /* take control back */
++ mb();
++ xmon_owner = smp_processor_id();
++ printf("cpu %u didn't take control\n", cpu);
++ return 0;
++ }
++ barrier();
++ }
++ return 1;
++#else
++ return 0;
++#endif /* CONFIG_SMP */
++}
++
++static unsigned short fcstab[256] = {
++ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
++ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
++ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
++ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
++ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
++ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
++ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
++ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
++ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
++ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
++ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
++ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
++ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
++ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
++ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
++ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
++ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
++ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
++ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
++ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
++ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
++ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
++ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
++ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
++ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
++ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
++ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
++ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
++ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
++ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
++ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
++ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
++};
++
++#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
++
++static void
++csum(void)
++{
++ unsigned int i;
++ unsigned short fcs;
++ unsigned char v;
++
++ if (!scanhex(&adrs))
++ return;
++ if (!scanhex(&ncsum))
++ return;
++ fcs = 0xffff;
++ for (i = 0; i < ncsum; ++i) {
++ if (mread(adrs+i, &v, 1) == 0) {
++ printf("csum stopped at %x\n", adrs+i);
++ break;
++ }
++ fcs = FCS(fcs, v);
++ }
++ printf("%x\n", fcs);
++}
++
++/*
++ * Check if this is a suitable place to put a breakpoint.
++ */
++static long check_bp_loc(unsigned long addr)
++{
++ unsigned int instr;
++
++ addr &= ~3;
++ if (addr < KERNELBASE) {
++ printf("Breakpoints may only be placed at kernel addresses\n");
++ return 0;
++ }
++ if (!mread(addr, &instr, sizeof(instr))) {
++ printf("Can't read instruction at address %lx\n", addr);
++ return 0;
++ }
++ if (IS_MTMSRD(instr) || IS_RFID(instr)) {
++ printf("Breakpoints may not be placed on mtmsrd or rfid "
++ "instructions\n");
++ return 0;
++ }
++ return 1;
++}
++
++static char *breakpoint_help_string =
++ "Breakpoint command usage:\n"
++ "b show breakpoints\n"
++ "b <addr> [cnt] set breakpoint at given instr addr\n"
++ "bc clear all breakpoints\n"
++ "bc <n/addr> clear breakpoint number n or at addr\n"
++ "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
++ "bd <addr> [cnt] set hardware data breakpoint\n"
++ "";
++
++static void
++bpt_cmds(void)
++{
++ int cmd;
++ unsigned long a;
++ int mode, i;
++ struct bpt *bp;
++ const char badaddr[] = "Only kernel addresses are permitted "
++ "for breakpoints\n";
++
++ cmd = inchar();
++ switch (cmd) {
++#ifndef CONFIG_8xx
++ case 'd': /* bd - hardware data breakpoint */
++ mode = 7;
++ cmd = inchar();
++ if (cmd == 'r')
++ mode = 5;
++ else if (cmd == 'w')
++ mode = 6;
++ else
++ termch = cmd;
++ dabr.address = 0;
++ dabr.enabled = 0;
++ if (scanhex(&dabr.address)) {
++ if (dabr.address < KERNELBASE) {
++ printf(badaddr);
++ break;
++ }
++ dabr.address &= ~7;
++ dabr.enabled = mode | BP_DABR;
++ }
++ break;
++
++ case 'i': /* bi - hardware instr breakpoint */
++ if (!cpu_has_feature(CPU_FTR_IABR)) {
++ printf("Hardware instruction breakpoint "
++ "not supported on this cpu\n");
++ break;
++ }
++ if (iabr) {
++ iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
++ iabr = NULL;
++ }
++ if (!scanhex(&a))
++ break;
++ if (!check_bp_loc(a))
++ break;
++ bp = new_breakpoint(a);
++ if (bp != NULL) {
++ bp->enabled |= BP_IABR | BP_IABR_TE;
++ iabr = bp;
++ }
++ break;
++#endif
++
++ case 'c':
++ if (!scanhex(&a)) {
++ /* clear all breakpoints */
++ for (i = 0; i < NBPTS; ++i)
++ bpts[i].enabled = 0;
++ iabr = NULL;
++ dabr.enabled = 0;
++ printf("All breakpoints cleared\n");
++ break;
++ }
++
++ if (a <= NBPTS && a >= 1) {
++ /* assume a breakpoint number */
++ bp = &bpts[a-1]; /* bp nums are 1 based */
++ } else {
++ /* assume a breakpoint address */
++ bp = at_breakpoint(a);
++ if (bp == 0) {
++ printf("No breakpoint at %x\n", a);
++ break;
++ }
++ }
++
++ printf("Cleared breakpoint %x (", BP_NUM(bp));
++ xmon_print_symbol(bp->address, " ", ")\n");
++ bp->enabled = 0;
++ break;
++
++ default:
++ termch = cmd;
++ cmd = skipbl();
++ if (cmd == '?') {
++ printf(breakpoint_help_string);
++ break;
++ }
++ termch = cmd;
++ if (!scanhex(&a)) {
++ /* print all breakpoints */
++ printf(" type address\n");
++ if (dabr.enabled) {
++ printf(" data "REG" [", dabr.address);
++ if (dabr.enabled & 1)
++ printf("r");
++ if (dabr.enabled & 2)
++ printf("w");
++ printf("]\n");
++ }
++ for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
++ if (!bp->enabled)
++ continue;
++ printf("%2x %s ", BP_NUM(bp),
++ (bp->enabled & BP_IABR)? "inst": "trap");
++ xmon_print_symbol(bp->address, " ", "\n");
++ }
++ break;
++ }
++
++ if (!check_bp_loc(a))
++ break;
++ bp = new_breakpoint(a);
++ if (bp != NULL)
++ bp->enabled |= BP_TRAP;
++ break;
++ }
++}
++
++/* Very cheap human name for vector lookup. */
++static
++const char *getvecname(unsigned long vec)
++{
++ char *ret;
++
++ switch (vec) {
++ case 0x100: ret = "(System Reset)"; break;
++ case 0x200: ret = "(Machine Check)"; break;
++ case 0x300: ret = "(Data Access)"; break;
++ case 0x380: ret = "(Data SLB Access)"; break;
++ case 0x400: ret = "(Instruction Access)"; break;
++ case 0x480: ret = "(Instruction SLB Access)"; break;
++ case 0x500: ret = "(Hardware Interrupt)"; break;
++ case 0x600: ret = "(Alignment)"; break;
++ case 0x700: ret = "(Program Check)"; break;
++ case 0x800: ret = "(FPU Unavailable)"; break;
++ case 0x900: ret = "(Decrementer)"; break;
++ case 0xc00: ret = "(System Call)"; break;
++ case 0xd00: ret = "(Single Step)"; break;
++ case 0xf00: ret = "(Performance Monitor)"; break;
++ case 0xf20: ret = "(Altivec Unavailable)"; break;
++ case 0x1300: ret = "(Instruction Breakpoint)"; break;
++ default: ret = "";
++ }
++ return ret;
++}
++
++static void get_function_bounds(unsigned long pc, unsigned long *startp,
++ unsigned long *endp)
++{
++ unsigned long size, offset;
++ const char *name;
++ char *modname;
++
++ *startp = *endp = 0;
++ if (pc == 0)
++ return;
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
++ if (name != NULL) {
++ *startp = pc - offset;
++ *endp = pc - offset + size;
++ }
++ sync();
++ }
++ catch_memory_errors = 0;
++}
++
++static int xmon_depth_to_print = 64;
++
++#ifdef CONFIG_PPC64
++#define LRSAVE_OFFSET 0x10
++#define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
++#define MARKER_OFFSET 0x60
++#define REGS_OFFSET 0x70
++#else
++#define LRSAVE_OFFSET 4
++#define REG_FRAME_MARKER 0x72656773
++#define MARKER_OFFSET 8
++#define REGS_OFFSET 16
++#endif
++
++static void xmon_show_stack(unsigned long sp, unsigned long lr,
++ unsigned long pc)
++{
++ unsigned long ip;
++ unsigned long newsp;
++ unsigned long marker;
++ int count = 0;
++ struct pt_regs regs;
++
++ do {
++ if (sp < PAGE_OFFSET) {
++ if (sp != 0)
++ printf("SP (%lx) is in userspace\n", sp);
++ break;
++ }
++
++ if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
++ || !mread(sp, &newsp, sizeof(unsigned long))) {
++ printf("Couldn't read stack frame at %lx\n", sp);
++ break;
++ }
++
++ /*
++ * For the first stack frame, try to work out if
++ * LR and/or the saved LR value in the bottommost
++ * stack frame are valid.
++ */
++ if ((pc | lr) != 0) {
++ unsigned long fnstart, fnend;
++ unsigned long nextip;
++ int printip = 1;
++
++ get_function_bounds(pc, &fnstart, &fnend);
++ nextip = 0;
++ if (newsp > sp)
++ mread(newsp + LRSAVE_OFFSET, &nextip,
++ sizeof(unsigned long));
++ if (lr == ip) {
++ if (lr < PAGE_OFFSET
++ || (fnstart <= lr && lr < fnend))
++ printip = 0;
++ } else if (lr == nextip) {
++ printip = 0;
++ } else if (lr >= PAGE_OFFSET
++ && !(fnstart <= lr && lr < fnend)) {
++ printf("[link register ] ");
++ xmon_print_symbol(lr, " ", "\n");
++ }
++ if (printip) {
++ printf("["REG"] ", sp);
++ xmon_print_symbol(ip, " ", " (unreliable)\n");
++ }
++ pc = lr = 0;
++
++ } else {
++ printf("["REG"] ", sp);
++ xmon_print_symbol(ip, " ", "\n");
++ }
++
++ /* Look for "regshere" marker to see if this is
++ an exception frame. */
++ if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
++ && marker == REG_FRAME_MARKER) {
++ if (mread(sp + REGS_OFFSET, ®s, sizeof(regs))
++ != sizeof(regs)) {
++ printf("Couldn't read registers at %lx\n",
++ sp + REGS_OFFSET);
++ break;
++ }
++ printf("--- Exception: %lx %s at ", regs.trap,
++ getvecname(TRAP(®s)));
++ pc = regs.nip;
++ lr = regs.link;
++ xmon_print_symbol(pc, " ", "\n");
++ }
++
++ if (newsp == 0)
++ break;
++
++ sp = newsp;
++ } while (count++ < xmon_depth_to_print);
++}
++
++static void backtrace(struct pt_regs *excp)
++{
++ unsigned long sp;
++
++ if (scanhex(&sp))
++ xmon_show_stack(sp, 0, 0);
++ else
++ xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
++ scannl();
++}
++
++static void print_bug_trap(struct pt_regs *regs)
++{
++ struct bug_entry *bug;
++ unsigned long addr;
++
++ if (regs->msr & MSR_PR)
++ return; /* not in kernel */
++ addr = regs->nip; /* address of trap instruction */
++ if (addr < PAGE_OFFSET)
++ return;
++ bug = find_bug(regs->nip);
++ if (bug == NULL)
++ return;
++ if (bug->line & BUG_WARNING_TRAP)
++ return;
++
++ printf("kernel BUG in %s at %s:%d!\n",
++ bug->function, bug->file, (unsigned int)bug->line);
++}
++
++void excprint(struct pt_regs *fp)
++{
++ unsigned long trap;
++
++#ifdef CONFIG_SMP
++ printf("cpu 0x%x: ", smp_processor_id());
++#endif /* CONFIG_SMP */
++
++ trap = TRAP(fp);
++ printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
++ printf(" pc: ");
++ xmon_print_symbol(fp->nip, ": ", "\n");
++
++ printf(" lr: ", fp->link);
++ xmon_print_symbol(fp->link, ": ", "\n");
++
++ printf(" sp: %lx\n", fp->gpr[1]);
++ printf(" msr: %lx\n", fp->msr);
++
++ if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
++ printf(" dar: %lx\n", fp->dar);
++ if (trap != 0x380)
++ printf(" dsisr: %lx\n", fp->dsisr);
++ }
++
++ printf(" current = 0x%lx\n", current);
++#ifdef CONFIG_PPC64
++ printf(" paca = 0x%lx\n", get_paca());
++#endif
++ if (current) {
++ printf(" pid = %ld, comm = %s\n",
++ current->pid, current->comm);
++ }
++
++ if (trap == 0x700)
++ print_bug_trap(fp);
++}
++
++void prregs(struct pt_regs *fp)
++{
++ int n, trap;
++ unsigned long base;
++ struct pt_regs regs;
++
++ if (scanhex(&base)) {
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ regs = *(struct pt_regs *)base;
++ sync();
++ __delay(200);
++ } else {
++ catch_memory_errors = 0;
++ printf("*** Error reading registers from "REG"\n",
++ base);
++ return;
++ }
++ catch_memory_errors = 0;
++ fp = ®s;
++ }
++
++#ifdef CONFIG_PPC64
++ if (FULL_REGS(fp)) {
++ for (n = 0; n < 16; ++n)
++ printf("R%.2ld = "REG" R%.2ld = "REG"\n",
++ n, fp->gpr[n], n+16, fp->gpr[n+16]);
++ } else {
++ for (n = 0; n < 7; ++n)
++ printf("R%.2ld = "REG" R%.2ld = "REG"\n",
++ n, fp->gpr[n], n+7, fp->gpr[n+7]);
++ }
++#else
++ for (n = 0; n < 32; ++n) {
++ printf("R%.2d = %.8x%s", n, fp->gpr[n],
++ (n & 3) == 3? "\n": " ");
++ if (n == 12 && !FULL_REGS(fp)) {
++ printf("\n");
++ break;
++ }
++ }
++#endif
++ printf("pc = ");
++ xmon_print_symbol(fp->nip, " ", "\n");
++ printf("lr = ");
++ xmon_print_symbol(fp->link, " ", "\n");
++ printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
++ printf("ctr = "REG" xer = "REG" trap = %4lx\n",
++ fp->ctr, fp->xer, fp->trap);
++ trap = TRAP(fp);
++ if (trap == 0x300 || trap == 0x380 || trap == 0x600)
++ printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
++}
++
++void cacheflush(void)
++{
++ int cmd;
++ unsigned long nflush;
++
++ cmd = inchar();
++ if (cmd != 'i')
++ termch = cmd;
++ scanhex((void *)&adrs);
++ if (termch != '\n')
++ termch = 0;
++ nflush = 1;
++ scanhex(&nflush);
++ nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++
++ if (cmd != 'i') {
++ for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
++ cflush((void *) adrs);
++ } else {
++ for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
++ cinval((void *) adrs);
++ }
++ sync();
++ /* wait a little while to see if we get a machine check */
++ __delay(200);
++ }
++ catch_memory_errors = 0;
++}
++
++unsigned long
++read_spr(int n)
++{
++ unsigned int instrs[2];
++ unsigned long (*code)(void);
++ unsigned long opd[3];
++ unsigned long ret = -1UL;
++
++ instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
++ instrs[1] = 0x4e800020;
++ opd[0] = (unsigned long)instrs;
++ opd[1] = 0;
++ opd[2] = 0;
++ store_inst(instrs);
++ store_inst(instrs+1);
++ code = (unsigned long (*)(void)) opd;
++
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++
++ ret = code();
++
++ sync();
++ /* wait a little while to see if we get a machine check */
++ __delay(200);
++ n = size;
++ }
++
++ return ret;
++}
++
++void
++write_spr(int n, unsigned long val)
++{
++ unsigned int instrs[2];
++ unsigned long (*code)(unsigned long);
++ unsigned long opd[3];
++
++ instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
++ instrs[1] = 0x4e800020;
++ opd[0] = (unsigned long)instrs;
++ opd[1] = 0;
++ opd[2] = 0;
++ store_inst(instrs);
++ store_inst(instrs+1);
++ code = (unsigned long (*)(unsigned long)) opd;
++
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++
++ code(val);
++
++ sync();
++ /* wait a little while to see if we get a machine check */
++ __delay(200);
++ n = size;
++ }
++}
++
++static unsigned long regno;
++extern char exc_prolog;
++extern char dec_exc;
++
++void super_regs(void)
++{
++ int cmd;
++ unsigned long val;
++#ifdef CONFIG_PPC_ISERIES
++ struct paca_struct *ptrPaca = NULL;
++ struct lppaca *ptrLpPaca = NULL;
++ struct ItLpRegSave *ptrLpRegSave = NULL;
++#endif
++
++ cmd = skipbl();
++ if (cmd == '\n') {
++ unsigned long sp, toc;
++ asm("mr %0,1" : "=r" (sp) :);
++ asm("mr %0,2" : "=r" (toc) :);
++
++ printf("msr = "REG" sprg0= "REG"\n",
++ mfmsr(), mfspr(SPRN_SPRG0));
++ printf("pvr = "REG" sprg1= "REG"\n",
++ mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
++ printf("dec = "REG" sprg2= "REG"\n",
++ mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
++ printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
++ printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
++#ifdef CONFIG_PPC_ISERIES
++ // Dump out relevant Paca data areas.
++ printf("Paca: \n");
++ ptrPaca = get_paca();
++
++ printf(" Local Processor Control Area (LpPaca): \n");
++ ptrLpPaca = ptrPaca->lppaca_ptr;
++ printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
++ ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
++ printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
++ ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
++ printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
++
++ printf(" Local Processor Register Save Area (LpRegSave): \n");
++ ptrLpRegSave = ptrPaca->reg_save_ptr;
++ printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
++ ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
++ printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
++ ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
++ printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
++ ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
++#endif
++
++ return;
++ }
++
++ scanhex(®no);
++ switch (cmd) {
++ case 'w':
++ val = read_spr(regno);
++ scanhex(&val);
++ write_spr(regno, val);
++ /* fall through */
++ case 'r':
++ printf("spr %lx = %lx\n", regno, read_spr(regno));
++ break;
++ }
++ scannl();
++}
++
++/*
++ * Stuff for reading and writing memory safely
++ */
++int
++mread(unsigned long adrs, void *buf, int size)
++{
++ volatile int n;
++ char *p, *q;
++
++ n = 0;
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ p = (char *)adrs;
++ q = (char *)buf;
++ switch (size) {
++ case 2:
++ *(u16 *)q = *(u16 *)p;
++ break;
++ case 4:
++ *(u32 *)q = *(u32 *)p;
++ break;
++ case 8:
++ *(u64 *)q = *(u64 *)p;
++ break;
++ default:
++ for( ; n < size; ++n) {
++ *q++ = *p++;
++ sync();
++ }
++ }
++ sync();
++ /* wait a little while to see if we get a machine check */
++ __delay(200);
++ n = size;
++ }
++ catch_memory_errors = 0;
++ return n;
++}
++
++int
++mwrite(unsigned long adrs, void *buf, int size)
++{
++ volatile int n;
++ char *p, *q;
++
++ n = 0;
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ p = (char *) adrs;
++ q = (char *) buf;
++ switch (size) {
++ case 2:
++ *(u16 *)p = *(u16 *)q;
++ break;
++ case 4:
++ *(u32 *)p = *(u32 *)q;
++ break;
++ case 8:
++ *(u64 *)p = *(u64 *)q;
++ break;
++ default:
++ for ( ; n < size; ++n) {
++ *p++ = *q++;
++ sync();
++ }
++ }
++ sync();
++ /* wait a little while to see if we get a machine check */
++ __delay(200);
++ n = size;
++ } else {
++ printf("*** Error writing address %x\n", adrs + n);
++ }
++ catch_memory_errors = 0;
++ return n;
++}
++
++static int fault_type;
++static int fault_except;
++static char *fault_chars[] = { "--", "**", "##" };
++
++static int handle_fault(struct pt_regs *regs)
++{
++ fault_except = TRAP(regs);
++ switch (TRAP(regs)) {
++ case 0x200:
++ fault_type = 0;
++ break;
++ case 0x300:
++ case 0x380:
++ fault_type = 1;
++ break;
++ default:
++ fault_type = 2;
++ }
++
++ longjmp(bus_error_jmp, 1);
++
++ return 0;
++}
++
++#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
++
++void
++byterev(unsigned char *val, int size)
++{
++ int t;
++
++ switch (size) {
++ case 2:
++ SWAP(val[0], val[1], t);
++ break;
++ case 4:
++ SWAP(val[0], val[3], t);
++ SWAP(val[1], val[2], t);
++ break;
++ case 8: /* is there really any use for this? */
++ SWAP(val[0], val[7], t);
++ SWAP(val[1], val[6], t);
++ SWAP(val[2], val[5], t);
++ SWAP(val[3], val[4], t);
++ break;
++ }
++}
++
++static int brev;
++static int mnoread;
++
++static char *memex_help_string =
++ "Memory examine command usage:\n"
++ "m [addr] [flags] examine/change memory\n"
++ " addr is optional. will start where left off.\n"
++ " flags may include chars from this set:\n"
++ " b modify by bytes (default)\n"
++ " w modify by words (2 byte)\n"
++ " l modify by longs (4 byte)\n"
++ " d modify by doubleword (8 byte)\n"
++ " r toggle reverse byte order mode\n"
++ " n do not read memory (for i/o spaces)\n"
++ " . ok to read (default)\n"
++ "NOTE: flags are saved as defaults\n"
++ "";
++
++static char *memex_subcmd_help_string =
++ "Memory examine subcommands:\n"
++ " hexval write this val to current location\n"
++ " 'string' write chars from string to this location\n"
++ " ' increment address\n"
++ " ^ decrement address\n"
++ " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
++ " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
++ " ` clear no-read flag\n"
++ " ; stay at this addr\n"
++ " v change to byte mode\n"
++ " w change to word (2 byte) mode\n"
++ " l change to long (4 byte) mode\n"
++ " u change to doubleword (8 byte) mode\n"
++ " m addr change current addr\n"
++ " n toggle no-read flag\n"
++ " r toggle byte reverse flag\n"
++ " < count back up count bytes\n"
++ " > count skip forward count bytes\n"
++ " x exit this mode\n"
++ "";
++
++void
++memex(void)
++{
++ int cmd, inc, i, nslash;
++ unsigned long n;
++ unsigned char val[16];
++
++ scanhex((void *)&adrs);
++ cmd = skipbl();
++ if (cmd == '?') {
++ printf(memex_help_string);
++ return;
++ } else {
++ termch = cmd;
++ }
++ last_cmd = "m\n";
++ while ((cmd = skipbl()) != '\n') {
++ switch( cmd ){
++ case 'b': size = 1; break;
++ case 'w': size = 2; break;
++ case 'l': size = 4; break;
++ case 'd': size = 8; break;
++ case 'r': brev = !brev; break;
++ case 'n': mnoread = 1; break;
++ case '.': mnoread = 0; break;
++ }
++ }
++ if( size <= 0 )
++ size = 1;
++ else if( size > 8 )
++ size = 8;
++ for(;;){
++ if (!mnoread)
++ n = mread(adrs, val, size);
++ printf("%.16x%c", adrs, brev? 'r': ' ');
++ if (!mnoread) {
++ if (brev)
++ byterev(val, size);
++ putchar(' ');
++ for (i = 0; i < n; ++i)
++ printf("%.2x", val[i]);
++ for (; i < size; ++i)
++ printf("%s", fault_chars[fault_type]);
++ }
++ putchar(' ');
++ inc = size;
++ nslash = 0;
++ for(;;){
++ if( scanhex(&n) ){
++ for (i = 0; i < size; ++i)
++ val[i] = n >> (i * 8);
++ if (!brev)
++ byterev(val, size);
++ mwrite(adrs, val, size);
++ inc = size;
++ }
++ cmd = skipbl();
++ if (cmd == '\n')
++ break;
++ inc = 0;
++ switch (cmd) {
++ case '\'':
++ for(;;){
++ n = inchar();
++ if( n == '\\' )
++ n = bsesc();
++ else if( n == '\'' )
++ break;
++ for (i = 0; i < size; ++i)
++ val[i] = n >> (i * 8);
++ if (!brev)
++ byterev(val, size);
++ mwrite(adrs, val, size);
++ adrs += size;
++ }
++ adrs -= size;
++ inc = size;
++ break;
++ case ',':
++ adrs += size;
++ break;
++ case '.':
++ mnoread = 0;
++ break;
++ case ';':
++ break;
++ case 'x':
++ case EOF:
++ scannl();
++ return;
++ case 'b':
++ case 'v':
++ size = 1;
++ break;
++ case 'w':
++ size = 2;
++ break;
++ case 'l':
++ size = 4;
++ break;
++ case 'u':
++ size = 8;
++ break;
++ case '^':
++ adrs -= size;
++ break;
++ break;
++ case '/':
++ if (nslash > 0)
++ adrs -= 1 << nslash;
++ else
++ nslash = 0;
++ nslash += 4;
++ adrs += 1 << nslash;
++ break;
++ case '\\':
++ if (nslash < 0)
++ adrs += 1 << -nslash;
++ else
++ nslash = 0;
++ nslash -= 4;
++ adrs -= 1 << -nslash;
++ break;
++ case 'm':
++ scanhex((void *)&adrs);
++ break;
++ case 'n':
++ mnoread = 1;
++ break;
++ case 'r':
++ brev = !brev;
++ break;
++ case '<':
++ n = size;
++ scanhex(&n);
++ adrs -= n;
++ break;
++ case '>':
++ n = size;
++ scanhex(&n);
++ adrs += n;
++ break;
++ case '?':
++ printf(memex_subcmd_help_string);
++ break;
++ }
++ }
++ adrs += inc;
++ }
++}
++
++int
++bsesc(void)
++{
++ int c;
++
++ c = inchar();
++ switch( c ){
++ case 'n': c = '\n'; break;
++ case 'r': c = '\r'; break;
++ case 'b': c = '\b'; break;
++ case 't': c = '\t'; break;
++ }
++ return c;
++}
++
++#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
++ || ('a' <= (c) && (c) <= 'f') \
++ || ('A' <= (c) && (c) <= 'F'))
++void
++dump(void)
++{
++ int c;
++
++ c = inchar();
++ if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
++ termch = c;
++ scanhex((void *)&adrs);
++ if (termch != '\n')
++ termch = 0;
++ if (c == 'i') {
++ scanhex(&nidump);
++ if (nidump == 0)
++ nidump = 16;
++ else if (nidump > MAX_DUMP)
++ nidump = MAX_DUMP;
++ adrs += ppc_inst_dump(adrs, nidump, 1);
++ last_cmd = "di\n";
++ } else {
++ scanhex(&ndump);
++ if (ndump == 0)
++ ndump = 64;
++ else if (ndump > MAX_DUMP)
++ ndump = MAX_DUMP;
++ prdump(adrs, ndump);
++ adrs += ndump;
++ last_cmd = "d\n";
++ }
++}
++
++void
++prdump(unsigned long adrs, long ndump)
++{
++ long n, m, c, r, nr;
++ unsigned char temp[16];
++
++ for (n = ndump; n > 0;) {
++ printf(REG, adrs);
++ putchar(' ');
++ r = n < 16? n: 16;
++ nr = mread(adrs, temp, r);
++ adrs += nr;
++ for (m = 0; m < r; ++m) {
++ if ((m & 7) == 0 && m > 0)
++ putchar(' ');
++ if (m < nr)
++ printf("%.2x", temp[m]);
++ else
++ printf("%s", fault_chars[fault_type]);
++ }
++ if (m <= 8)
++ printf(" ");
++ for (; m < 16; ++m)
++ printf(" ");
++ printf(" |");
++ for (m = 0; m < r; ++m) {
++ if (m < nr) {
++ c = temp[m];
++ putchar(' ' <= c && c <= '~'? c: '.');
++ } else
++ putchar(' ');
++ }
++ n -= r;
++ for (; m < 16; ++m)
++ putchar(' ');
++ printf("|\n");
++ if (nr < r)
++ break;
++ }
++}
++
++int
++ppc_inst_dump(unsigned long adr, long count, int praddr)
++{
++ int nr, dotted;
++ unsigned long first_adr;
++ unsigned long inst, last_inst = 0;
++ unsigned char val[4];
++
++ dotted = 0;
++ for (first_adr = adr; count > 0; --count, adr += 4) {
++ nr = mread(adr, val, 4);
++ if (nr == 0) {
++ if (praddr) {
++ const char *x = fault_chars[fault_type];
++ printf(REG" %s%s%s%s\n", adr, x, x, x, x);
++ }
++ break;
++ }
++ inst = GETWORD(val);
++ if (adr > first_adr && inst == last_inst) {
++ if (!dotted) {
++ printf(" ...\n");
++ dotted = 1;
++ }
++ continue;
++ }
++ dotted = 0;
++ last_inst = inst;
++ if (praddr)
++ printf(REG" %.8x", adr, inst);
++ printf("\t");
++ print_insn_powerpc(inst, adr, 0); /* always returns 4 */
++ printf("\n");
++ }
++ return adr - first_adr;
++}
++
++void
++print_address(unsigned long addr)
++{
++ xmon_print_symbol(addr, "\t# ", "");
++}
++
++
++/*
++ * Memory operations - move, set, print differences
++ */
++static unsigned long mdest; /* destination address */
++static unsigned long msrc; /* source address */
++static unsigned long mval; /* byte value to set memory to */
++static unsigned long mcount; /* # bytes to affect */
++static unsigned long mdiffs; /* max # differences to print */
++
++void
++memops(int cmd)
++{
++ scanhex((void *)&mdest);
++ if( termch != '\n' )
++ termch = 0;
++ scanhex((void *)(cmd == 's'? &mval: &msrc));
++ if( termch != '\n' )
++ termch = 0;
++ scanhex((void *)&mcount);
++ switch( cmd ){
++ case 'm':
++ memmove((void *)mdest, (void *)msrc, mcount);
++ break;
++ case 's':
++ memset((void *)mdest, mval, mcount);
++ break;
++ case 'd':
++ if( termch != '\n' )
++ termch = 0;
++ scanhex((void *)&mdiffs);
++ memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
++ break;
++ }
++}
++
++void
++memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
++{
++ unsigned n, prt;
++
++ prt = 0;
++ for( n = nb; n > 0; --n )
++ if( *p1++ != *p2++ )
++ if( ++prt <= maxpr )
++ printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
++ p1[-1], p2 - 1, p2[-1]);
++ if( prt > maxpr )
++ printf("Total of %d differences\n", prt);
++}
++
++static unsigned mend;
++static unsigned mask;
++
++void
++memlocate(void)
++{
++ unsigned a, n;
++ unsigned char val[4];
++
++ last_cmd = "ml";
++ scanhex((void *)&mdest);
++ if (termch != '\n') {
++ termch = 0;
++ scanhex((void *)&mend);
++ if (termch != '\n') {
++ termch = 0;
++ scanhex((void *)&mval);
++ mask = ~0;
++ if (termch != '\n') termch = 0;
++ scanhex((void *)&mask);
++ }
++ }
++ n = 0;
++ for (a = mdest; a < mend; a += 4) {
++ if (mread(a, val, 4) == 4
++ && ((GETWORD(val) ^ mval) & mask) == 0) {
++ printf("%.16x: %.16x\n", a, GETWORD(val));
++ if (++n >= 10)
++ break;
++ }
++ }
++}
++
++static unsigned long mskip = 0x1000;
++static unsigned long mlim = 0xffffffff;
++
++void
++memzcan(void)
++{
++ unsigned char v;
++ unsigned a;
++ int ok, ook;
++
++ scanhex(&mdest);
++ if (termch != '\n') termch = 0;
++ scanhex(&mskip);
++ if (termch != '\n') termch = 0;
++ scanhex(&mlim);
++ ook = 0;
++ for (a = mdest; a < mlim; a += mskip) {
++ ok = mread(a, &v, 1);
++ if (ok && !ook) {
++ printf("%.8x .. ", a);
++ fflush(stdout);
++ } else if (!ok && ook)
++ printf("%.8x\n", a - mskip);
++ ook = ok;
++ if (a + mskip < a)
++ break;
++ }
++ if (ook)
++ printf("%.8x\n", a - mskip);
++}
++
++void proccall(void)
++{
++ unsigned long args[8];
++ unsigned long ret;
++ int i;
++ typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
++ unsigned long, unsigned long, unsigned long,
++ unsigned long, unsigned long, unsigned long);
++ callfunc_t func;
++
++ if (!scanhex(&adrs))
++ return;
++ if (termch != '\n')
++ termch = 0;
++ for (i = 0; i < 8; ++i)
++ args[i] = 0;
++ for (i = 0; i < 8; ++i) {
++ if (!scanhex(&args[i]) || termch == '\n')
++ break;
++ termch = 0;
++ }
++ func = (callfunc_t) adrs;
++ ret = 0;
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ ret = func(args[0], args[1], args[2], args[3],
++ args[4], args[5], args[6], args[7]);
++ sync();
++ printf("return value is %x\n", ret);
++ } else {
++ printf("*** %x exception occurred\n", fault_except);
++ }
++ catch_memory_errors = 0;
++}
++
++/* Input scanning routines */
++int
++skipbl(void)
++{
++ int c;
++
++ if( termch != 0 ){
++ c = termch;
++ termch = 0;
++ } else
++ c = inchar();
++ while( c == ' ' || c == '\t' )
++ c = inchar();
++ return c;
++}
++
++#define N_PTREGS 44
++static char *regnames[N_PTREGS] = {
++ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
++ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
++ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
++ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
++ "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
++#ifdef CONFIG_PPC64
++ "softe",
++#else
++ "mq",
++#endif
++ "trap", "dar", "dsisr", "res"
++};
++
++int
++scanhex(unsigned long *vp)
++{
++ int c, d;
++ unsigned long v;
++
++ c = skipbl();
++ if (c == '%') {
++ /* parse register name */
++ char regname[8];
++ int i;
++
++ for (i = 0; i < sizeof(regname) - 1; ++i) {
++ c = inchar();
++ if (!isalnum(c)) {
++ termch = c;
++ break;
++ }
++ regname[i] = c;
++ }
++ regname[i] = 0;
++ for (i = 0; i < N_PTREGS; ++i) {
++ if (strcmp(regnames[i], regname) == 0) {
++ if (xmon_regs == NULL) {
++ printf("regs not available\n");
++ return 0;
++ }
++ *vp = ((unsigned long *)xmon_regs)[i];
++ return 1;
++ }
++ }
++ printf("invalid register name '%%%s'\n", regname);
++ return 0;
++ }
++
++ /* skip leading "0x" if any */
++
++ if (c == '0') {
++ c = inchar();
++ if (c == 'x') {
++ c = inchar();
++ } else {
++ d = hexdigit(c);
++ if (d == EOF) {
++ termch = c;
++ *vp = 0;
++ return 1;
++ }
++ }
++ } else if (c == '$') {
++ int i;
++ for (i=0; i<63; i++) {
++ c = inchar();
++ if (isspace(c)) {
++ termch = c;
++ break;
++ }
++ tmpstr[i] = c;
++ }
++ tmpstr[i++] = 0;
++ *vp = 0;
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ *vp = kallsyms_lookup_name(tmpstr);
++ sync();
++ }
++ catch_memory_errors = 0;
++ if (!(*vp)) {
++ printf("unknown symbol '%s'\n", tmpstr);
++ return 0;
++ }
++ return 1;
++ }
++
++ d = hexdigit(c);
++ if (d == EOF) {
++ termch = c;
++ return 0;
++ }
++ v = 0;
++ do {
++ v = (v << 4) + d;
++ c = inchar();
++ d = hexdigit(c);
++ } while (d != EOF);
++ termch = c;
++ *vp = v;
++ return 1;
++}
++
++void
++scannl(void)
++{
++ int c;
++
++ c = termch;
++ termch = 0;
++ while( c != '\n' )
++ c = inchar();
++}
++
++int hexdigit(int c)
++{
++ if( '0' <= c && c <= '9' )
++ return c - '0';
++ if( 'A' <= c && c <= 'F' )
++ return c - ('A' - 10);
++ if( 'a' <= c && c <= 'f' )
++ return c - ('a' - 10);
++ return EOF;
++}
++
++void
++getstring(char *s, int size)
++{
++ int c;
++
++ c = skipbl();
++ do {
++ if( size > 1 ){
++ *s++ = c;
++ --size;
++ }
++ c = inchar();
++ } while( c != ' ' && c != '\t' && c != '\n' );
++ termch = c;
++ *s = 0;
++}
++
++static char line[256];
++static char *lineptr;
++
++void
++flush_input(void)
++{
++ lineptr = NULL;
++}
++
++int
++inchar(void)
++{
++ if (lineptr == NULL || *lineptr == 0) {
++ if (fgets(line, sizeof(line), stdin) == NULL) {
++ lineptr = NULL;
++ return EOF;
++ }
++ lineptr = line;
++ }
++ return *lineptr++;
++}
++
++void
++take_input(char *str)
++{
++ lineptr = str;
++}
++
++
++static void
++symbol_lookup(void)
++{
++ int type = inchar();
++ unsigned long addr;
++ static char tmp[64];
++
++ switch (type) {
++ case 'a':
++ if (scanhex(&addr))
++ xmon_print_symbol(addr, ": ", "\n");
++ termch = 0;
++ break;
++ case 's':
++ getstring(tmp, 64);
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ addr = kallsyms_lookup_name(tmp);
++ if (addr)
++ printf("%s: %lx\n", tmp, addr);
++ else
++ printf("Symbol '%s' not found.\n", tmp);
++ sync();
++ }
++ catch_memory_errors = 0;
++ termch = 0;
++ break;
++ }
++}
++
++
++/* Print an address in numeric and symbolic form (if possible) */
++static void xmon_print_symbol(unsigned long address, const char *mid,
++ const char *after)
++{
++ char *modname;
++ const char *name = NULL;
++ unsigned long offset, size;
++
++ printf(REG, address);
++ if (setjmp(bus_error_jmp) == 0) {
++ catch_memory_errors = 1;
++ sync();
++ name = kallsyms_lookup(address, &size, &offset, &modname,
++ tmpstr);
++ sync();
++ /* wait a little while to see if we get a machine check */
++ __delay(200);
++ }
++
++ catch_memory_errors = 0;
++
++ if (name) {
++ printf("%s%s+%#lx/%#lx", mid, name, offset, size);
++ if (modname)
++ printf(" [%s]", modname);
++ }
++ printf("%s", after);
++}
++
++#ifdef CONFIG_PPC64
++static void dump_slb(void)
++{
++ int i;
++ unsigned long tmp;
++
++ printf("SLB contents of cpu %x\n", smp_processor_id());
++
++ for (i = 0; i < SLB_NUM_ENTRIES; i++) {
++ asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
++ printf("%02d %016lx ", i, tmp);
++
++ asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
++ printf("%016lx\n", tmp);
++ }
++}
++
++static void dump_stab(void)
++{
++ int i;
++ unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
++
++ printf("Segment table contents of cpu %x\n", smp_processor_id());
++
++ for (i = 0; i < PAGE_SIZE/16; i++) {
++ unsigned long a, b;
++
++ a = *tmp++;
++ b = *tmp++;
++
++ if (a || b) {
++ printf("%03d %016lx ", i, a);
++ printf("%016lx\n", b);
++ }
++ }
++}
++
++void dump_segments(void)
++{
++ if (cpu_has_feature(CPU_FTR_SLB))
++ dump_slb();
++ else
++ dump_stab();
++}
++#endif
++
++#ifdef CONFIG_PPC_STD_MMU_32
++void dump_segments(void)
++{
++ int i;
++
++ printf("sr0-15 =");
++ for (i = 0; i < 16; ++i)
++ printf(" %x", mfsrin(i));
++ printf("\n");
++}
++#endif
++
++void xmon_init(int enable)
++{
++ if (enable) {
++ __debugger = xmon;
++ __debugger_ipi = xmon_ipi;
++ __debugger_bpt = xmon_bpt;
++ __debugger_sstep = xmon_sstep;
++ __debugger_iabr_match = xmon_iabr_match;
++ __debugger_dabr_match = xmon_dabr_match;
++ __debugger_fault_handler = xmon_fault_handler;
++ } else {
++ __debugger = NULL;
++ __debugger_ipi = NULL;
++ __debugger_bpt = NULL;
++ __debugger_sstep = NULL;
++ __debugger_iabr_match = NULL;
++ __debugger_dabr_match = NULL;
++ __debugger_fault_handler = NULL;
++ }
++}
+diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
+--- a/arch/ppc/8xx_io/commproc.c
++++ b/arch/ppc/8xx_io/commproc.c
+@@ -73,7 +73,7 @@ cpm_mask_irq(unsigned int irq)
+ {
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_vec);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) & ~(1 << cpm_vec));
+ }
+
+ static void
+@@ -81,7 +81,7 @@ cpm_unmask_irq(unsigned int irq)
+ {
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_vec);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) | (1 << cpm_vec));
+ }
+
+ static void
+@@ -95,7 +95,7 @@ cpm_eoi(unsigned int irq)
+ {
+ int cpm_vec = irq - CPM_IRQ_OFFSET;
+
+- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << cpm_vec);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr, (1 << cpm_vec));
+ }
+
+ struct hw_interrupt_type cpm_pic = {
+@@ -133,7 +133,7 @@ m8xx_cpm_reset(void)
+ * manual recommends it.
+ * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
+ */
+- imp->im_siu_conf.sc_sdcr = 1;
++ out_be32(&imp->im_siu_conf.sc_sdcr, 1),
+
+ /* Reclaim the DP memory for our use. */
+ m8xx_cpm_dpinit();
+@@ -178,10 +178,10 @@ cpm_interrupt_init(void)
+
+ /* Initialize the CPM interrupt controller.
+ */
+- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
++ out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr,
+ (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+- ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
+- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
++ ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, 0);
+
+ /* install the CPM interrupt controller routines for the CPM
+ * interrupt vectors
+@@ -198,7 +198,7 @@ cpm_interrupt_init(void)
+ if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction))
+ panic("Could not allocate CPM error IRQ!");
+
+- ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
++ out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr) | CICR_IEN);
+ }
+
+ /*
+@@ -212,8 +212,8 @@ cpm_get_irq(struct pt_regs *regs)
+ /* Get the vector by setting the ACK bit and then reading
+ * the register.
+ */
+- ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
+- cpm_vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
++ out_be16(&((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr, 1);
++ cpm_vec = in_be16(&((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr);
+ cpm_vec >>= 11;
+
+ return cpm_vec;
+diff --git a/arch/ppc/8xx_io/cs4218.h b/arch/ppc/8xx_io/cs4218.h
+--- a/arch/ppc/8xx_io/cs4218.h
++++ b/arch/ppc/8xx_io/cs4218.h
+@@ -78,7 +78,7 @@ typedef struct {
+ 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
+--- a/arch/ppc/8xx_io/cs4218_tdm.c
++++ b/arch/ppc/8xx_io/cs4218_tdm.c
+@@ -318,7 +318,7 @@ struct cs_sound_settings {
+
+ 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 @@ static TRANS transCSNormalRead = {
+
+ /*** 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/Kconfig b/arch/ppc/Kconfig
+--- a/arch/ppc/Kconfig
++++ b/arch/ppc/Kconfig
+@@ -568,6 +568,7 @@ config CHESTNUT
+
+ config SPRUCE
+ bool "IBM-Spruce"
++ select PPC_INDIRECT_PCI
+
+ config HDPU
+ bool "Sky-HDPU"
+@@ -588,27 +589,35 @@ config EV64260
+
+ config LOPEC
+ bool "Motorola-LoPEC"
++ select PPC_I8259
+
+ config MVME5100
+ bool "Motorola-MVME5100"
++ select PPC_INDIRECT_PCI
+
+ config PPLUS
+ bool "Motorola-PowerPlus"
++ select PPC_I8259
++ select PPC_INDIRECT_PCI
+
+ config PRPMC750
+ bool "Motorola-PrPMC750"
++ select PPC_INDIRECT_PCI
+
+ config PRPMC800
+ bool "Motorola-PrPMC800"
++ select PPC_INDIRECT_PCI
+
+ config SANDPOINT
+ bool "Motorola-Sandpoint"
++ select PPC_I8259
+ help
+ Select SANDPOINT if configuring for a Motorola Sandpoint X3
+ (any flavor).
+
+ config RADSTONE_PPC7D
+ bool "Radstone Technology PPC7D board"
++ select PPC_I8259
+
+ config PAL4
+ bool "SBS-Palomar4"
+@@ -616,6 +625,7 @@ config PAL4
+ config GEMINI
+ bool "Synergy-Gemini"
+ depends on BROKEN
++ select PPC_INDIRECT_PCI
+ help
+ Select Gemini if configuring for a Synergy Microsystems' Gemini
+ series Single Board Computer. More information is available at:
+@@ -747,13 +757,16 @@ config CPM2
+ on it (826x, 827x, 8560).
+
+ config PPC_CHRP
+- bool
++ bool " Common Hardware Reference Platform (CHRP) based machines"
+ depends on PPC_MULTIPLATFORM
++ select PPC_I8259
++ select PPC_INDIRECT_PCI
+ default y
+
+ config PPC_PMAC
+- bool
++ bool " Apple PowerMac based machines"
+ depends on PPC_MULTIPLATFORM
++ select PPC_INDIRECT_PCI
+ default y
+
+ config PPC_PMAC64
+@@ -762,8 +775,10 @@ config PPC_PMAC64
+ default y
+
+ config PPC_PREP
+- bool
++ bool " PowerPC Reference Platform (PReP) based machines"
+ depends on PPC_MULTIPLATFORM
++ select PPC_I8259
++ select PPC_INDIRECT_PCI
+ default y
+
+ config PPC_OF
+@@ -797,6 +812,7 @@ config MV64360 # Really MV64360 & MV644
+ config MV64X60
+ bool
+ depends on (GT64260 || MV64360)
++ select PPC_INDIRECT_PCI
+ default y
+
+ menu "Set bridge options"
+@@ -845,6 +861,7 @@ config EPIC_SERIAL_MODE
+ config MPC10X_BRIDGE
+ bool
+ depends on POWERPMC250 || LOPEC || SANDPOINT
++ select PPC_INDIRECT_PCI
+ default y
+
+ config MPC10X_OPENPIC
+@@ -870,6 +887,7 @@ config HARRIER_STORE_GATHERING
+ config MVME5100_IPMC761_PRESENT
+ bool "MVME5100 configured with an IPMC761"
+ depends on MVME5100
++ select PPC_I8259
+
+ config SPRUCE_BAUD_33M
+ bool "Spruce baud clock support"
+@@ -1127,6 +1145,7 @@ menu "Bus options"
+ config ISA
+ bool "Support for ISA-bus hardware"
+ depends on PPC_PREP || PPC_CHRP
++ select PPC_I8259
+ help
+ Find out whether you have ISA slots on your motherboard. ISA is the
+ name of a bus system, i.e. the way the CPU talks to the other stuff
+@@ -1139,6 +1158,17 @@ config GENERIC_ISA_DMA
+ depends on POWER3 || POWER4 || 6xx && !CPM2
+ default y
+
++config PPC_I8259
++ bool
++ default y if 85xx
++ default n
++
++config PPC_INDIRECT_PCI
++ bool
++ depends on PCI
++ default y if 40x || 44x || 85xx || 83xx
++ default n
++
+ config EISA
+ bool
+ help
+@@ -1175,6 +1205,7 @@ config MPC83xx_PCI2
+ config PCI_QSPAN
+ bool "QSpan PCI"
+ depends on !4xx && !CPM2 && 8xx
++ select PPC_I8259
+ help
+ Say Y here if you have a system based on a Motorola 8xx-series
+ embedded processor with a QSPAN PCI interface, otherwise say N.
+@@ -1182,6 +1213,7 @@ config PCI_QSPAN
+ config PCI_8260
+ bool
+ depends on PCI && 8260
++ select PPC_INDIRECT_PCI
+ default y
+
+ config 8260_PCI9
+@@ -1368,7 +1400,7 @@ endmenu
+
+ source "lib/Kconfig"
+
+-source "arch/ppc/oprofile/Kconfig"
++source "arch/powerpc/oprofile/Kconfig"
+
+ source "arch/ppc/Kconfig.debug"
+
+diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
+--- a/arch/ppc/Makefile
++++ b/arch/ppc/Makefile
+@@ -26,6 +26,10 @@ CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH
+ AFLAGS += -Iarch/$(ARCH)
+ CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \
+ -ffixed-r2 -mmultiple
++
++# No AltiVec instruction when building kernel
++CFLAGS += $(call cc-option, -mno-altivec)
++
+ CPP = $(CC) -E $(CFLAGS)
+ # Temporary hack until we have migrated to asm-powerpc
+ LINUXINCLUDE += -Iarch/$(ARCH)/include
+@@ -57,10 +61,12 @@ head-$(CONFIG_FSL_BOOKE) := arch/ppc/ker
+
+ head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o
+ head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o
+-head-$(CONFIG_PPC_FPU) += arch/ppc/kernel/fpu.o
++head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o
+
+-core-y += arch/ppc/kernel/ arch/ppc/platforms/ \
+- arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/
++core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \
++ arch/ppc/platforms/ \
++ arch/ppc/mm/ arch/ppc/lib/ \
++ arch/ppc/syslib/ arch/powerpc/sysdev/
+ core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/
+ core-$(CONFIG_83xx) += arch/ppc/platforms/83xx/
+ core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/
+@@ -71,7 +77,7 @@ drivers-$(CONFIG_8xx) += arch/ppc/8xx_i
+ drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/
+ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
+
+-drivers-$(CONFIG_OPROFILE) += arch/ppc/oprofile/
++drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
+
+ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
+
+diff --git a/arch/ppc/boot/of1275/claim.c b/arch/ppc/boot/of1275/claim.c
+--- a/arch/ppc/boot/of1275/claim.c
++++ b/arch/ppc/boot/of1275/claim.c
+@@ -29,6 +29,7 @@ claim(unsigned int virt, unsigned int si
+ args.virt = virt;
+ args.size = size;
+ args.align = align;
++ args.ret = (void *) 0;
+ (*of_prom_entry)(&args);
+ return args.ret;
+ }
+diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c
+--- a/arch/ppc/boot/openfirmware/chrpmain.c
++++ b/arch/ppc/boot/openfirmware/chrpmain.c
+@@ -78,7 +78,7 @@ boot(int a1, int a2, void *prom)
+ begin_avail = avail_high = avail_ram;
+ end_avail = scratch + sizeof(scratch);
+ printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
+- gunzip(dst, 0x400000, im, &len);
++ gunzip(dst, PROG_SIZE - PROG_START, im, &len);
+ printf("done %u bytes\n\r", len);
+ printf("%u bytes of heap consumed, max in use %u\n\r",
+ avail_high - begin_avail, heap_max);
+diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c
+--- a/arch/ppc/boot/openfirmware/coffmain.c
++++ b/arch/ppc/boot/openfirmware/coffmain.c
+@@ -38,7 +38,7 @@ static char heap[SCRATCH_SIZE];
+ static unsigned long ram_start = 0;
+ static unsigned long ram_end = 0x1000000;
+
+-static unsigned long prog_start = 0x900000;
++static unsigned long prog_start = 0x800000;
+ static unsigned long prog_size = 0x700000;
+
+ typedef void (*kernel_start_t)(int, int, void *);
+diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
+--- a/arch/ppc/kernel/Makefile
++++ b/arch/ppc/kernel/Makefile
+@@ -1,6 +1,7 @@
+ #
+ # Makefile for the linux kernel.
+ #
++ifneq ($(CONFIG_PPC_MERGE),y)
+
+ extra-$(CONFIG_PPC_STD_MMU) := head.o
+ extra-$(CONFIG_40x) := head_4xx.o
+@@ -9,13 +10,12 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_bo
+ extra-$(CONFIG_8xx) := head_8xx.o
+ extra-$(CONFIG_6xx) += idle_6xx.o
+ extra-$(CONFIG_POWER4) += idle_power4.o
+-extra-$(CONFIG_PPC_FPU) += fpu.o
+ extra-y += vmlinux.lds
+
+ obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
+- process.o signal.o ptrace.o align.o \
+- semaphore.o syscalls.o setup.o \
+- cputable.o ppc_htab.o perfmon.o
++ process.o align.o \
++ setup.o \
++ ppc_htab.o
+ obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
+ obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
+ obj-$(CONFIG_POWER4) += cpu_setup_power4.o
+@@ -25,7 +25,6 @@ obj-$(CONFIG_PCI) += pci.o
+ obj-$(CONFIG_KGDB) += ppc-stub.o
+ obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
+ obj-$(CONFIG_TAU) += temp.o
+-obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
+ ifndef CONFIG_E200
+ obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
+ endif
+@@ -35,3 +34,21 @@ ifndef CONFIG_MATH_EMULATION
+ obj-$(CONFIG_8xx) += softemu8xx.o
+ endif
+
++# These are here while we do the architecture merge
++
++else
++obj-y := irq.o idle.o \
++ align.o
++obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
++obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
++obj-$(CONFIG_MODULES) += module.o
++obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
++obj-$(CONFIG_PCI) += pci.o
++obj-$(CONFIG_KGDB) += ppc-stub.o
++obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
++obj-$(CONFIG_TAU) += temp.o
++ifndef CONFIG_E200
++obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
++endif
++obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
++endif
+diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
+--- a/arch/ppc/kernel/align.c
++++ b/arch/ppc/kernel/align.c
+@@ -375,7 +375,7 @@ fix_alignment(struct pt_regs *regs)
+ #ifdef CONFIG_PPC_FPU
+ preempt_disable();
+ enable_kernel_fp();
+- cvt_fd(&data.f, &data.d, ¤t->thread.fpscr);
++ cvt_fd(&data.f, &data.d, ¤t->thread);
+ preempt_enable();
+ #else
+ return 0;
+@@ -385,7 +385,7 @@ fix_alignment(struct pt_regs *regs)
+ #ifdef CONFIG_PPC_FPU
+ preempt_disable();
+ enable_kernel_fp();
+- cvt_df(&data.d, &data.f, ¤t->thread.fpscr);
++ cvt_df(&data.d, &data.f, ¤t->thread);
+ preempt_enable();
+ #else
+ return 0;
+diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
+--- a/arch/ppc/kernel/asm-offsets.c
++++ b/arch/ppc/kernel/asm-offsets.c
+@@ -130,10 +130,10 @@ main(void)
+ DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
+ DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
+
++ DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+- DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+
+@@ -141,6 +141,7 @@ main(void)
+ DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
+ DEFINE(pbe_next, offsetof(struct pbe, next));
+
++ DEFINE(TASK_SIZE, TASK_SIZE);
+ DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
+ return 0;
+ }
+diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
+--- a/arch/ppc/kernel/cpu_setup_6xx.S
++++ b/arch/ppc/kernel/cpu_setup_6xx.S
+@@ -17,8 +17,6 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/cache.h>
+
+-_GLOBAL(__setup_cpu_601)
+- blr
+ _GLOBAL(__setup_cpu_603)
+ b setup_common_caches
+ _GLOBAL(__setup_cpu_604)
+@@ -292,10 +290,10 @@ _GLOBAL(__init_fpu_registers)
+ #define CS_SIZE 32
+
+ .data
+- .balign L1_CACHE_LINE_SIZE
++ .balign L1_CACHE_BYTES
+ cpu_state_storage:
+ .space CS_SIZE
+- .balign L1_CACHE_LINE_SIZE,0
++ .balign L1_CACHE_BYTES,0
+ .text
+
+ /* Called in normal context to backup CPU 0 state. This
+diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S
+--- a/arch/ppc/kernel/cpu_setup_power4.S
++++ b/arch/ppc/kernel/cpu_setup_power4.S
+@@ -63,8 +63,6 @@ _GLOBAL(__970_cpu_preinit)
+ isync
+ blr
+
+-_GLOBAL(__setup_cpu_power4)
+- blr
+ _GLOBAL(__setup_cpu_ppc970)
+ mfspr r0,SPRN_HID0
+ li r11,5 /* clear DOZE and SLEEP */
+@@ -88,10 +86,10 @@ _GLOBAL(__setup_cpu_ppc970)
+ #define CS_SIZE 32
+
+ .data
+- .balign L1_CACHE_LINE_SIZE
++ .balign L1_CACHE_BYTES
+ cpu_state_storage:
+ .space CS_SIZE
+- .balign L1_CACHE_LINE_SIZE,0
++ .balign L1_CACHE_BYTES,0
+ .text
+
+ /* Called in normal context to backup CPU 0 state. This
+diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
+deleted file mode 100644
+--- a/arch/ppc/kernel/cputable.c
++++ /dev/null
+@@ -1,1041 +0,0 @@
+-/*
+- * arch/ppc/kernel/cputable.c
+- *
+- * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/string.h>
+-#include <linux/sched.h>
+-#include <linux/threads.h>
+-#include <linux/init.h>
+-#include <asm/cputable.h>
+-
+-struct cpu_spec* cur_cpu_spec[NR_CPUS];
+-
+-extern void __setup_cpu_601(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_603(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_604(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_750(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_750cx(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_750fx(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_7400(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_7410(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_745x(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_power3(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_power4(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_ppc970(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-
+-#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \
+- !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
+- !defined(CONFIG_BOOKE))
+-
+-/* This table only contains "desktop" CPUs, it need to be filled with embedded
+- * ones as well...
+- */
+-#define COMMON_PPC (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \
+- PPC_FEATURE_HAS_MMU)
+-
+-/* We only set the altivec features if the kernel was compiled with altivec
+- * support
+- */
+-#ifdef CONFIG_ALTIVEC
+-#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC
+-#define PPC_FEATURE_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC
+-#else
+-#define CPU_FTR_ALTIVEC_COMP 0
+-#define PPC_FEATURE_ALTIVEC_COMP 0
+-#endif
+-
+-/* We only set the spe features if the kernel was compiled with
+- * spe support
+- */
+-#ifdef CONFIG_SPE
+-#define PPC_FEATURE_SPE_COMP PPC_FEATURE_HAS_SPE
+-#else
+-#define PPC_FEATURE_SPE_COMP 0
+-#endif
+-
+-/* We need to mark all pages as being coherent if we're SMP or we
+- * have a 74[45]x and an MPC107 host bridge.
+- */
+-#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE)
+-#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT
+-#else
+-#define CPU_FTR_COMMON 0
+-#endif
+-
+-/* The powersave features NAP & DOZE seems to confuse BDI when
+- debugging. So if a BDI is used, disable theses
+- */
+-#ifndef CONFIG_BDI_SWITCH
+-#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE
+-#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP
+-#else
+-#define CPU_FTR_MAYBE_CAN_DOZE 0
+-#define CPU_FTR_MAYBE_CAN_NAP 0
+-#endif
+-
+-struct cpu_spec cpu_specs[] = {
+-#if CLASSIC_PPC
+- { /* 601 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00010000,
+- .cpu_name = "601",
+- .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 |
+- CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR |
+- PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_601
+- },
+- { /* 603 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00030000,
+- .cpu_name = "603",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_603
+- },
+- { /* 603e */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00060000,
+- .cpu_name = "603e",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_603
+- },
+- { /* 603ev */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00070000,
+- .cpu_name = "603ev",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_603
+- },
+- { /* 604 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00040000,
+- .cpu_name = "604",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 2,
+- .cpu_setup = __setup_cpu_604
+- },
+- { /* 604e */
+- .pvr_mask = 0xfffff000,
+- .pvr_value = 0x00090000,
+- .cpu_name = "604e",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_604
+- },
+- { /* 604r */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00090000,
+- .cpu_name = "604r",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_604
+- },
+- { /* 604ev */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x000a0000,
+- .cpu_name = "604ev",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_604
+- },
+- { /* 740/750 (0x4202, don't support TAU ?) */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x00084202,
+- .cpu_name = "740/750",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750
+- },
+- { /* 750CX (80100 and 8010x?) */
+- .pvr_mask = 0xfffffff0,
+- .pvr_value = 0x00080100,
+- .cpu_name = "750CX",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750cx
+- },
+- { /* 750CX (82201 and 82202) */
+- .pvr_mask = 0xfffffff0,
+- .pvr_value = 0x00082200,
+- .cpu_name = "750CX",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750cx
+- },
+- { /* 750CXe (82214) */
+- .pvr_mask = 0xfffffff0,
+- .pvr_value = 0x00082210,
+- .cpu_name = "750CXe",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750cx
+- },
+- { /* 750CXe "Gekko" (83214) */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x00083214,
+- .cpu_name = "750CXe",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750cx
+- },
+- { /* 745/755 */
+- .pvr_mask = 0xfffff000,
+- .pvr_value = 0x00083000,
+- .cpu_name = "745/755",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750
+- },
+- { /* 750FX rev 1.x */
+- .pvr_mask = 0xffffff00,
+- .pvr_value = 0x70000100,
+- .cpu_name = "750FX",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
+- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750
+- },
+- { /* 750FX rev 2.0 must disable HID0[DPM] */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x70000200,
+- .cpu_name = "750FX",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
+- CPU_FTR_NO_DPM,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750
+- },
+- { /* 750FX (All revs except 2.0) */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x70000000,
+- .cpu_name = "750FX",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
+- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750fx
+- },
+- { /* 750GX */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x70020000,
+- .cpu_name = "750GX",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+- CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_DUAL_PLL_750FX |
+- CPU_FTR_HAS_HIGH_BATS,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750fx
+- },
+- { /* 740/750 (L2CR bit need fixup for 740) */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00080000,
+- .cpu_name = "740/750",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_750
+- },
+- { /* 7400 rev 1.1 ? (no TAU) */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x000c1101,
+- .cpu_name = "7400 (1.1)",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_7400
+- },
+- { /* 7400 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x000c0000,
+- .cpu_name = "7400",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_7400
+- },
+- { /* 7410 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x800c0000,
+- .cpu_name = "7410",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- .cpu_setup = __setup_cpu_7410
+- },
+- { /* 7450 2.0 - no doze/nap */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x80000200,
+- .cpu_name = "7450",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7450 2.1 */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x80000201,
+- .cpu_name = "7450",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
+- CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7450 2.3 and newer */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x80000000,
+- .cpu_name = "7450",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7455 rev 1.x */
+- .pvr_mask = 0xffffff00,
+- .pvr_value = 0x80010100,
+- .cpu_name = "7455",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7455 rev 2.0 */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x80010200,
+- .cpu_name = "7455",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
+- CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7455 others */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x80010000,
+- .cpu_name = "7455",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+- CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7447/7457 Rev 1.0 */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x80020100,
+- .cpu_name = "7447/7457",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+- CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7447/7457 Rev 1.1 */
+- .pvr_mask = 0xffffffff,
+- .pvr_value = 0x80020101,
+- .cpu_name = "7447/7457",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+- CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7447/7457 Rev 1.2 and later */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x80020000,
+- .cpu_name = "7447/7457",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
+- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
+- CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7447A */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x80030000,
+- .cpu_name = "7447A",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+- CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 7448 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x80040000,
+- .cpu_name = "7448",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+- CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_745x
+- },
+- { /* 82xx (8240, 8245, 8260 are all 603e cores) */
+- .pvr_mask = 0x7fff0000,
+- .pvr_value = 0x00810000,
+- .cpu_name = "82xx",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_603
+- },
+- { /* All G2_LE (603e core, plus some) have the same pvr */
+- .pvr_mask = 0x7fff0000,
+- .pvr_value = 0x00820000,
+- .cpu_name = "G2_LE",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_603
+- },
+- { /* e300 (a 603e core, plus some) on 83xx */
+- .pvr_mask = 0x7fff0000,
+- .pvr_value = 0x00830000,
+- .cpu_name = "e300",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_603
+- },
+- { /* default match, we assume split I/D cache & TB (non-601)... */
+- .pvr_mask = 0x00000000,
+- .pvr_value = 0x00000000,
+- .cpu_name = "(generic PPC)",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .cpu_setup = __setup_cpu_generic
+- },
+-#endif /* CLASSIC_PPC */
+-#ifdef CONFIG_PPC64BRIDGE
+- { /* Power3 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00400000,
+- .cpu_name = "Power3 (630)",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3
+- },
+- { /* Power3+ */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00410000,
+- .cpu_name = "Power3 (630+)",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3
+- },
+- { /* I-star */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00360000,
+- .cpu_name = "I-star",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3
+- },
+- { /* S-star */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00370000,
+- .cpu_name = "S-star",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3
+- },
+-#endif /* CONFIG_PPC64BRIDGE */
+-#ifdef CONFIG_POWER4
+- { /* Power4 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00350000,
+- .cpu_name = "Power4",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power4
+- },
+- { /* PPC970 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00390000,
+- .cpu_name = "PPC970",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 |
+- PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_ppc970
+- },
+- { /* PPC970FX */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x003c0000,
+- .cpu_name = "PPC970FX",
+- .cpu_features = CPU_FTR_COMMON |
+- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+- CPU_FTR_HPTE_TABLE |
+- CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
+- .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 |
+- PPC_FEATURE_ALTIVEC_COMP,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_ppc970
+- },
+-#endif /* CONFIG_POWER4 */
+-#ifdef CONFIG_8xx
+- { /* 8xx */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00500000,
+- .cpu_name = "8xx",
+- /* CPU_FTR_MAYBE_CAN_DOZE is possible,
+- * if the 8xx code is there.... */
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 16,
+- .dcache_bsize = 16,
+- },
+-#endif /* CONFIG_8xx */
+-#ifdef CONFIG_40x
+- { /* 403GC */
+- .pvr_mask = 0xffffff00,
+- .pvr_value = 0x00200200,
+- .cpu_name = "403GC",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 16,
+- .dcache_bsize = 16,
+- },
+- { /* 403GCX */
+- .pvr_mask = 0xffffff00,
+- .pvr_value = 0x00201400,
+- .cpu_name = "403GCX",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
+- .icache_bsize = 16,
+- .dcache_bsize = 16,
+- },
+- { /* 403G ?? */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00200000,
+- .cpu_name = "403G ??",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 16,
+- .dcache_bsize = 16,
+- },
+- { /* 405GP */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x40110000,
+- .cpu_name = "405GP",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* STB 03xxx */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x40130000,
+- .cpu_name = "STB03xxx",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* STB 04xxx */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x41810000,
+- .cpu_name = "STB04xxx",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* NP405L */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x41610000,
+- .cpu_name = "NP405L",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* NP4GS3 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x40B10000,
+- .cpu_name = "NP4GS3",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* NP405H */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x41410000,
+- .cpu_name = "NP405H",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 405GPr */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x50910000,
+- .cpu_name = "405GPr",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* STBx25xx */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x51510000,
+- .cpu_name = "STBx25xx",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 405LP */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x41F10000,
+- .cpu_name = "405LP",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* Xilinx Virtex-II Pro */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x20010000,
+- .cpu_name = "Virtex-II Pro",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 405EP */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x51210000,
+- .cpu_name = "405EP",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+-
+-#endif /* CONFIG_40x */
+-#ifdef CONFIG_44x
+- {
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x40000850,
+- .cpu_name = "440EP Rev. A",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- {
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x400008d3,
+- .cpu_name = "440EP Rev. B",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 440GP Rev. B */
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x40000440,
+- .cpu_name = "440GP Rev. B",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 440GP Rev. C */
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x40000481,
+- .cpu_name = "440GP Rev. C",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 440GX Rev. A */
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x50000850,
+- .cpu_name = "440GX Rev. A",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 440GX Rev. B */
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x50000851,
+- .cpu_name = "440GX Rev. B",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 440GX Rev. C */
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x50000892,
+- .cpu_name = "440GX Rev. C",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 440GX Rev. F */
+- .pvr_mask = 0xf0000fff,
+- .pvr_value = 0x50000894,
+- .cpu_name = "440GX Rev. F",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+- { /* 440SP Rev. A */
+- .pvr_mask = 0xff000fff,
+- .pvr_value = 0x53000891,
+- .cpu_name = "440SP Rev. A",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- },
+-#endif /* CONFIG_44x */
+-#ifdef CONFIG_FSL_BOOKE
+- { /* e200z5 */
+- .pvr_mask = 0xfff00000,
+- .pvr_value = 0x81000000,
+- .cpu_name = "e200z5",
+- /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+- .cpu_features = CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE |
+- PPC_FEATURE_UNIFIED_CACHE,
+- .dcache_bsize = 32,
+- },
+- { /* e200z6 */
+- .pvr_mask = 0xfff00000,
+- .pvr_value = 0x81100000,
+- .cpu_name = "e200z6",
+- /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+- .cpu_features = CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+- PPC_FEATURE_HAS_EFP_SINGLE |
+- PPC_FEATURE_UNIFIED_CACHE,
+- .dcache_bsize = 32,
+- },
+- { /* e500 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x80200000,
+- .cpu_name = "e500",
+- /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+- PPC_FEATURE_HAS_EFP_SINGLE,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- },
+- { /* e500v2 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x80210000,
+- .cpu_name = "e500v2",
+- /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_BIG_PHYS,
+- .cpu_user_features = PPC_FEATURE_32 |
+- PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+- PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- .num_pmcs = 4,
+- },
+-#endif
+-#if !CLASSIC_PPC
+- { /* default match */
+- .pvr_mask = 0x00000000,
+- .pvr_value = 0x00000000,
+- .cpu_name = "(generic PPC)",
+- .cpu_features = CPU_FTR_COMMON,
+- .cpu_user_features = PPC_FEATURE_32,
+- .icache_bsize = 32,
+- .dcache_bsize = 32,
+- }
+-#endif /* !CLASSIC_PPC */
+-};
+diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
+--- a/arch/ppc/kernel/dma-mapping.c
++++ b/arch/ppc/kernel/dma-mapping.c
+@@ -115,7 +115,7 @@ static struct vm_region consistent_head
+ };
+
+ 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 @@ static struct vm_region *vm_region_find(
+ * 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 @@ static int __init dma_alloc_init(void)
+ 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 @@ static int __init dma_alloc_init(void)
+ }
+ 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 @@ static int __init dma_alloc_init(void)
+ consistent_pte = pte;
+ } while (0);
+
+- spin_unlock(&init_mm.page_table_lock);
+-
+ return ret;
+ }
+
+diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
+--- a/arch/ppc/kernel/entry.S
++++ b/arch/ppc/kernel/entry.S
+@@ -200,9 +200,8 @@ _GLOBAL(DoSyscall)
+ bl do_show_syscall
+ #endif /* SHOW_SYSCALLS */
+ rlwinm r10,r1,0,0,18 /* current_thread_info() */
+- lwz r11,TI_LOCAL_FLAGS(r10)
+- rlwinm r11,r11,0,~_TIFL_FORCE_NOERROR
+- stw r11,TI_LOCAL_FLAGS(r10)
++ li r11,0
++ stb r11,TI_SC_NOERR(r10)
+ lwz r11,TI_FLAGS(r10)
+ andi. r11,r11,_TIF_SYSCALL_T_OR_A
+ bne- syscall_dotrace
+@@ -227,8 +226,8 @@ ret_from_syscall:
+ cmplw 0,r3,r11
+ rlwinm r12,r1,0,0,18 /* current_thread_info() */
+ blt+ 30f
+- lwz r11,TI_LOCAL_FLAGS(r12)
+- andi. r11,r11,_TIFL_FORCE_NOERROR
++ lbz r11,TI_SC_NOERR(r12)
++ cmpwi r11,0
+ bne 30f
+ neg r3,r3
+ lwz r10,_CCR(r1) /* Set SO bit in CR */
+@@ -633,7 +632,8 @@ sigreturn_exit:
+ rlwinm r12,r1,0,0,18 /* current_thread_info() */
+ lwz r9,TI_FLAGS(r12)
+ andi. r0,r9,_TIF_SYSCALL_T_OR_A
+- bnel- do_syscall_trace_leave
++ beq+ ret_from_except_full
++ bl do_syscall_trace_leave
+ /* fall through */
+
+ .globl ret_from_except_full
+diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S
+deleted file mode 100644
+--- a/arch/ppc/kernel/fpu.S
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*
+- * FPU support code, moved here from head.S so that it can be used
+- * by chips which use other head-whatever.S files.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- */
+-
+-#include <linux/config.h>
+-#include <asm/processor.h>
+-#include <asm/page.h>
+-#include <asm/mmu.h>
+-#include <asm/pgtable.h>
+-#include <asm/cputable.h>
+-#include <asm/cache.h>
+-#include <asm/thread_info.h>
+-#include <asm/ppc_asm.h>
+-#include <asm/asm-offsets.h>
+-
+-/*
+- * This task wants to use the FPU now.
+- * On UP, disable FP for the task which had the FPU previously,
+- * and save its floating-point registers in its thread_struct.
+- * Load up this task's FP registers from its thread_struct,
+- * enable the FPU for the current task and return to the task.
+- */
+- .globl load_up_fpu
+-load_up_fpu:
+- mfmsr r5
+- ori r5,r5,MSR_FP
+-#ifdef CONFIG_PPC64BRIDGE
+- clrldi r5,r5,1 /* turn off 64-bit mode */
+-#endif /* CONFIG_PPC64BRIDGE */
+- SYNC
+- MTMSRD(r5) /* enable use of fpu now */
+- isync
+-/*
+- * For SMP, we don't do lazy FPU switching because it just gets too
+- * horrendously complex, especially when a task switches from one CPU
+- * to another. Instead we call giveup_fpu in switch_to.
+- */
+-#ifndef CONFIG_SMP
+- tophys(r6,0) /* get __pa constant */
+- addis r3,r6,last_task_used_math at ha
+- lwz r4,last_task_used_math at l(r3)
+- cmpwi 0,r4,0
+- beq 1f
+- add r4,r4,r6
+- addi r4,r4,THREAD /* want last_task_used_math->thread */
+- SAVE_32FPRS(0, r4)
+- mffs fr0
+- stfd fr0,THREAD_FPSCR-4(r4)
+- lwz r5,PT_REGS(r4)
+- add r5,r5,r6
+- lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+- li r10,MSR_FP|MSR_FE0|MSR_FE1
+- andc r4,r4,r10 /* disable FP for previous task */
+- stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+-1:
+-#endif /* CONFIG_SMP */
+- /* enable use of FP after return */
+- mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
+- lwz r4,THREAD_FPEXC_MODE(r5)
+- ori r9,r9,MSR_FP /* enable FP for current */
+- or r9,r9,r4
+- lfd fr0,THREAD_FPSCR-4(r5)
+- mtfsf 0xff,fr0
+- REST_32FPRS(0, r5)
+-#ifndef CONFIG_SMP
+- subi r4,r5,THREAD
+- sub r4,r4,r6
+- stw r4,last_task_used_math at l(r3)
+-#endif /* CONFIG_SMP */
+- /* restore registers and return */
+- /* we haven't used ctr or xer or lr */
+- b fast_exception_return
+-
+-/*
+- * FP unavailable trap from kernel - print a message, but let
+- * the task use FP in the kernel until it returns to user mode.
+- */
+- .globl KernelFP
+-KernelFP:
+- lwz r3,_MSR(r1)
+- ori r3,r3,MSR_FP
+- stw r3,_MSR(r1) /* enable use of FP after return */
+- lis r3,86f at h
+- ori r3,r3,86f at l
+- mr r4,r2 /* current */
+- lwz r5,_NIP(r1)
+- bl printk
+- b ret_from_except
+-86: .string "floating point used in kernel (task=%p, pc=%x)\n"
+- .align 4,0
+-
+-/*
+- * giveup_fpu(tsk)
+- * Disable FP for the task given as the argument,
+- * and save the floating-point registers in its thread_struct.
+- * Enables the FPU for use in the kernel on return.
+- */
+- .globl giveup_fpu
+-giveup_fpu:
+- mfmsr r5
+- ori r5,r5,MSR_FP
+- SYNC_601
+- ISYNC_601
+- MTMSRD(r5) /* enable use of fpu now */
+- SYNC_601
+- isync
+- cmpwi 0,r3,0
+- beqlr- /* if no previous owner, done */
+- addi r3,r3,THREAD /* want THREAD of task */
+- lwz r5,PT_REGS(r3)
+- cmpwi 0,r5,0
+- SAVE_32FPRS(0, r3)
+- mffs fr0
+- stfd fr0,THREAD_FPSCR-4(r3)
+- beq 1f
+- lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+- li r3,MSR_FP|MSR_FE0|MSR_FE1
+- andc r4,r4,r3 /* disable FP for previous task */
+- stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+-1:
+-#ifndef CONFIG_SMP
+- li r5,0
+- lis r4,last_task_used_math at ha
+- stw r5,last_task_used_math at l(r4)
+-#endif /* CONFIG_SMP */
+- blr
+diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
+--- a/arch/ppc/kernel/head.S
++++ b/arch/ppc/kernel/head.S
+@@ -349,12 +349,12 @@ i##n: \
+
+ /* System reset */
+ /* core99 pmac starts the seconary here by changing the vector, and
+- putting it back to what it was (UnknownException) when done. */
++ putting it back to what it was (unknown_exception) when done. */
+ #if defined(CONFIG_GEMINI) && defined(CONFIG_SMP)
+ . = 0x100
+ b __secondary_start_gemini
+ #else
+- EXCEPTION(0x100, Reset, UnknownException, EXC_XFER_STD)
++ EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
+ #endif
+
+ /* Machine check */
+@@ -389,7 +389,7 @@ i##n: \
+ cmpwi cr1,r4,0
+ bne cr1,1f
+ #endif
+- EXC_XFER_STD(0x200, MachineCheckException)
++ EXC_XFER_STD(0x200, machine_check_exception)
+ #ifdef CONFIG_PPC_CHRP
+ 1: b machine_check_in_rtas
+ #endif
+@@ -456,10 +456,10 @@ Alignment:
+ mfspr r5,SPRN_DSISR
+ stw r5,_DSISR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_EE(0x600, AlignmentException)
++ EXC_XFER_EE(0x600, alignment_exception)
+
+ /* Program check exception */
+- EXCEPTION(0x700, ProgramCheck, ProgramCheckException, EXC_XFER_STD)
++ EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
+
+ /* Floating-point unavailable */
+ . = 0x800
+@@ -467,13 +467,13 @@ FPUnavailable:
+ EXCEPTION_PROLOG
+ bne load_up_fpu /* if from user, just load it up */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_EE_LITE(0x800, KernelFP)
++ EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
+
+ /* Decrementer */
+ EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
+
+- EXCEPTION(0xa00, Trap_0a, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0xb00, Trap_0b, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
+
+ /* System call */
+ . = 0xc00
+@@ -482,8 +482,8 @@ SystemCall:
+ EXC_XFER_EE_LITE(0xc00, DoSyscall)
+
+ /* Single step - not used on 601 */
+- EXCEPTION(0xd00, SingleStep, SingleStepException, EXC_XFER_STD)
+- EXCEPTION(0xe00, Trap_0e, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
++ EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
+
+ /*
+ * The Altivec unavailable trap is at 0x0f20. Foo.
+@@ -502,7 +502,7 @@ SystemCall:
+ Trap_0f:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_EE(0xf00, UnknownException)
++ EXC_XFER_EE(0xf00, unknown_exception)
+
+ /*
+ * Handle TLB miss for instruction on 603/603e.
+@@ -702,44 +702,44 @@ DataStoreTLBMiss:
+ rfi
+
+ #ifndef CONFIG_ALTIVEC
+-#define AltivecAssistException UnknownException
++#define altivec_assist_exception unknown_exception
+ #endif
+
+- EXCEPTION(0x1300, Trap_13, InstructionBreakpoint, EXC_XFER_EE)
++ EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_EE)
+ EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
+- EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
+ #ifdef CONFIG_POWER4
+- EXCEPTION(0x1600, Trap_16, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1700, Trap_17, AltivecAssistException, EXC_XFER_EE)
++ EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1700, Trap_17, altivec_assist_exception, EXC_XFER_EE)
+ EXCEPTION(0x1800, Trap_18, TAUException, EXC_XFER_STD)
+ #else /* !CONFIG_POWER4 */
+- EXCEPTION(0x1600, Trap_16, AltivecAssistException, EXC_XFER_EE)
++ EXCEPTION(0x1600, Trap_16, altivec_assist_exception, EXC_XFER_EE)
+ EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
+- EXCEPTION(0x1800, Trap_18, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
+ #endif /* CONFIG_POWER4 */
+- EXCEPTION(0x1900, Trap_19, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1a00, Trap_1a, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1b00, Trap_1b, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1c00, Trap_1c, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1d00, Trap_1d, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1e00, Trap_1e, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1f00, Trap_1f, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
+ EXCEPTION(0x2000, RunMode, RunModeException, EXC_XFER_EE)
+- EXCEPTION(0x2100, Trap_21, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2200, Trap_22, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2300, Trap_23, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2400, Trap_24, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2500, Trap_25, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2600, Trap_26, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2700, Trap_27, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2800, Trap_28, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2900, Trap_29, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2a00, Trap_2a, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2b00, Trap_2b, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2c00, Trap_2c, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2d00, Trap_2d, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2e00, Trap_2e, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x2f00, MOLTrampoline, UnknownException, EXC_XFER_EE_LITE)
++ EXCEPTION(0x2100, Trap_21, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2200, Trap_22, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2300, Trap_23, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2400, Trap_24, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2500, Trap_25, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2600, Trap_26, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2700, Trap_27, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2800, Trap_28, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2900, Trap_29, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2a00, Trap_2a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2b00, Trap_2b, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2c00, Trap_2c, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2d00, Trap_2d, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2e00, Trap_2e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x2f00, MOLTrampoline, unknown_exception, EXC_XFER_EE_LITE)
+
+ .globl mol_trampoline
+ .set mol_trampoline, i0x2f00
+@@ -751,7 +751,7 @@ AltiVecUnavailable:
+ #ifdef CONFIG_ALTIVEC
+ bne load_up_altivec /* if from user, just load it up */
+ #endif /* CONFIG_ALTIVEC */
+- EXC_XFER_EE_LITE(0xf20, AltivecUnavailException)
++ EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
+
+ #ifdef CONFIG_PPC64BRIDGE
+ DataAccess:
+@@ -767,12 +767,12 @@ DataSegment:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ mfspr r4,SPRN_DAR
+ stw r4,_DAR(r11)
+- EXC_XFER_STD(0x380, UnknownException)
++ EXC_XFER_STD(0x380, unknown_exception)
+
+ InstructionSegment:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_STD(0x480, UnknownException)
++ EXC_XFER_STD(0x480, unknown_exception)
+ #endif /* CONFIG_PPC64BRIDGE */
+
+ #ifdef CONFIG_ALTIVEC
+@@ -804,7 +804,7 @@ load_up_altivec:
+ beq 1f
+ add r4,r4,r6
+ addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */
+- SAVE_32VR(0,r10,r4)
++ SAVE_32VRS(0,r10,r4)
+ mfvscr vr0
+ li r10,THREAD_VSCR
+ stvx vr0,r10,r4
+@@ -824,7 +824,7 @@ load_up_altivec:
+ stw r4,THREAD_USED_VR(r5)
+ lvx vr0,r10,r5
+ mtvscr vr0
+- REST_32VR(0,r10,r5)
++ REST_32VRS(0,r10,r5)
+ #ifndef CONFIG_SMP
+ subi r4,r5,THREAD
+ sub r4,r4,r6
+@@ -870,7 +870,7 @@ giveup_altivec:
+ addi r3,r3,THREAD /* want THREAD of task */
+ lwz r5,PT_REGS(r3)
+ cmpwi 0,r5,0
+- SAVE_32VR(0, r4, r3)
++ SAVE_32VRS(0, r4, r3)
+ mfvscr vr0
+ li r4,THREAD_VSCR
+ stvx vr0,r4,r3
+@@ -916,7 +916,7 @@ relocate_kernel:
+ copy_and_flush:
+ addi r5,r5,-4
+ addi r6,r6,-4
+-4: li r0,L1_CACHE_LINE_SIZE/4
++4: li r0,L1_CACHE_BYTES/4
+ mtctr r0
+ 3: addi r6,r6,4 /* copy a cache line */
+ lwzx r0,r6,r4
+@@ -1059,7 +1059,6 @@ __secondary_start:
+
+ lis r3,-KERNELBASE at h
+ mr r4,r24
+- bl identify_cpu
+ bl call_setup_cpu /* Call setup_cpu for this CPU */
+ #ifdef CONFIG_6xx
+ lis r3,-KERNELBASE at h
+@@ -1109,11 +1108,6 @@ __secondary_start:
+ * Those generic dummy functions are kept for CPUs not
+ * included in CONFIG_6xx
+ */
+-_GLOBAL(__setup_cpu_power3)
+- blr
+-_GLOBAL(__setup_cpu_generic)
+- blr
+-
+ #if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4)
+ _GLOBAL(__save_cpu_setup)
+ blr
+diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
+--- a/arch/ppc/kernel/head_44x.S
++++ b/arch/ppc/kernel/head_44x.S
+@@ -309,13 +309,13 @@ skpinv: addi r4,r4,1 /* Increment */
+
+ interrupt_base:
+ /* Critical Input Interrupt */
+- CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
++ CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
+
+ /* Machine Check Interrupt */
+ #ifdef CONFIG_440A
+- MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
++ MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
+ #else
+- CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
++ CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
+ #endif
+
+ /* Data Storage Interrupt */
+@@ -442,7 +442,7 @@ interrupt_base:
+ #ifdef CONFIG_PPC_FPU
+ FP_UNAVAILABLE_EXCEPTION
+ #else
+- EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
+ #endif
+
+ /* System Call Interrupt */
+@@ -451,21 +451,21 @@ interrupt_base:
+ EXC_XFER_EE_LITE(0x0c00, DoSyscall)
+
+ /* Auxillary Processor Unavailable Interrupt */
+- EXCEPTION(0x2020, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
+
+ /* Decrementer Interrupt */
+ DECREMENTER_EXCEPTION
+
+ /* Fixed Internal Timer Interrupt */
+ /* TODO: Add FIT support */
+- EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
+
+ /* Watchdog Timer Interrupt */
+ /* TODO: Add watchdog support */
+ #ifdef CONFIG_BOOKE_WDT
+ CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException)
+ #else
+- CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
++ CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception)
+ #endif
+
+ /* Data TLB Error Interrupt */
+@@ -743,14 +743,18 @@ _GLOBAL(set_context)
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
+ .data
+-_GLOBAL(sdata)
+-_GLOBAL(empty_zero_page)
++ .align 12
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
+ .space 4096
+
+ /*
+ * To support >32-bit physical addresses, we use an 8KB pgdir.
+ */
+-_GLOBAL(swapper_pg_dir)
++ .globl swapper_pg_dir
++swapper_pg_dir:
+ .space 8192
+
+ /* Reserved 4k for the critical exception stack & 4k for the machine
+@@ -759,13 +763,15 @@ _GLOBAL(swapper_pg_dir)
+ .align 12
+ exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE
+-_GLOBAL(exception_stack_top)
++ .globl exception_stack_top
++exception_stack_top:
+
+ /*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+-_GLOBAL(cmd_line)
++ .globl cmd_line
++cmd_line:
+ .space 512
+
+ /*
+@@ -774,5 +780,3 @@ _GLOBAL(cmd_line)
+ */
+ abatron_pteptrs:
+ .space 8
+-
+-
+diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
+--- a/arch/ppc/kernel/head_4xx.S
++++ b/arch/ppc/kernel/head_4xx.S
+@@ -245,12 +245,12 @@ label:
+ /*
+ * 0x0100 - Critical Interrupt Exception
+ */
+- CRITICAL_EXCEPTION(0x0100, CriticalInterrupt, UnknownException)
++ CRITICAL_EXCEPTION(0x0100, CriticalInterrupt, unknown_exception)
+
+ /*
+ * 0x0200 - Machine Check Exception
+ */
+- CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
++ CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
+
+ /*
+ * 0x0300 - Data Storage Exception
+@@ -405,7 +405,7 @@ label:
+ mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */
+ stw r4,_DEAR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_EE(0x600, AlignmentException)
++ EXC_XFER_EE(0x600, alignment_exception)
+
+ /* 0x0700 - Program Exception */
+ START_EXCEPTION(0x0700, ProgramCheck)
+@@ -413,21 +413,21 @@ label:
+ mfspr r4,SPRN_ESR /* Grab the ESR and save it */
+ stw r4,_ESR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_STD(0x700, ProgramCheckException)
++ EXC_XFER_STD(0x700, program_check_exception)
+
+- EXCEPTION(0x0800, Trap_08, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x0900, Trap_09, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x0A00, Trap_0A, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x0B00, Trap_0B, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x0800, Trap_08, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0900, Trap_09, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0A00, Trap_0A, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0B00, Trap_0B, unknown_exception, EXC_XFER_EE)
+
+ /* 0x0C00 - System Call Exception */
+ START_EXCEPTION(0x0C00, SystemCall)
+ NORMAL_EXCEPTION_PROLOG
+ EXC_XFER_EE_LITE(0xc00, DoSyscall)
+
+- EXCEPTION(0x0D00, Trap_0D, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x0E00, Trap_0E, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x0F00, Trap_0F, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_EE)
+
+ /* 0x1000 - Programmable Interval Timer (PIT) Exception */
+ START_EXCEPTION(0x1000, Decrementer)
+@@ -444,14 +444,14 @@ label:
+
+ /* 0x1010 - Fixed Interval Timer (FIT) Exception
+ */
+- STND_EXCEPTION(0x1010, FITException, UnknownException)
++ STND_EXCEPTION(0x1010, FITException, unknown_exception)
+
+ /* 0x1020 - Watchdog Timer (WDT) Exception
+ */
+ #ifdef CONFIG_BOOKE_WDT
+ CRITICAL_EXCEPTION(0x1020, WDTException, WatchdogException)
+ #else
+- CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
++ CRITICAL_EXCEPTION(0x1020, WDTException, unknown_exception)
+ #endif
+ #endif
+
+@@ -656,25 +656,25 @@ label:
+ mfspr r10, SPRN_SPRG0
+ b InstructionAccess
+
+- EXCEPTION(0x1300, Trap_13, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1400, Trap_14, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1600, Trap_16, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1300, Trap_13, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1400, Trap_14, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
+ #ifdef CONFIG_IBM405_ERR51
+ /* 405GP errata 51 */
+ START_EXCEPTION(0x1700, Trap_17)
+ b DTLBMiss
+ #else
+- EXCEPTION(0x1700, Trap_17, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_EE)
+ #endif
+- EXCEPTION(0x1800, Trap_18, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1900, Trap_19, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1A00, Trap_1A, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1B00, Trap_1B, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1C00, Trap_1C, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1D00, Trap_1D, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1E00, Trap_1E, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1F00, Trap_1F, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1A00, Trap_1A, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1B00, Trap_1B, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1C00, Trap_1C, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1D00, Trap_1D, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1E00, Trap_1E, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1F00, Trap_1F, unknown_exception, EXC_XFER_EE)
+
+ /* Check for a single step debug exception while in an exception
+ * handler before state has been saved. This is to catch the case
+@@ -988,10 +988,14 @@ _GLOBAL(set_context)
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
+ .data
+-_GLOBAL(sdata)
+-_GLOBAL(empty_zero_page)
++ .align 12
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
+ .space 4096
+-_GLOBAL(swapper_pg_dir)
++ .globl swapper_pg_dir
++swapper_pg_dir:
+ .space 4096
+
+
+@@ -1001,12 +1005,14 @@ _GLOBAL(swapper_pg_dir)
+ exception_stack_bottom:
+ .space 4096
+ critical_stack_top:
+-_GLOBAL(exception_stack_top)
++ .globl exception_stack_top
++exception_stack_top:
+
+ /* This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+-_GLOBAL(cmd_line)
++ .globl cmd_line
++cmd_line:
+ .space 512
+
+ /* Room for two PTE pointers, usually the kernel and current user pointers
+diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
+--- a/arch/ppc/kernel/head_8xx.S
++++ b/arch/ppc/kernel/head_8xx.S
+@@ -203,7 +203,7 @@ i##n: \
+ ret_from_except)
+
+ /* System reset */
+- EXCEPTION(0x100, Reset, UnknownException, EXC_XFER_STD)
++ EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
+
+ /* Machine check */
+ . = 0x200
+@@ -214,7 +214,7 @@ MachineCheck:
+ mfspr r5,SPRN_DSISR
+ stw r5,_DSISR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_STD(0x200, MachineCheckException)
++ EXC_XFER_STD(0x200, machine_check_exception)
+
+ /* Data access exception.
+ * This is "never generated" by the MPC8xx. We jump to it for other
+@@ -252,20 +252,20 @@ Alignment:
+ mfspr r5,SPRN_DSISR
+ stw r5,_DSISR(r11)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+- EXC_XFER_EE(0x600, AlignmentException)
++ EXC_XFER_EE(0x600, alignment_exception)
+
+ /* Program check exception */
+- EXCEPTION(0x700, ProgramCheck, ProgramCheckException, EXC_XFER_STD)
++ EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
+
+ /* No FPU on MPC8xx. This exception is not supposed to happen.
+ */
+- EXCEPTION(0x800, FPUnavailable, UnknownException, EXC_XFER_STD)
++ EXCEPTION(0x800, FPUnavailable, unknown_exception, EXC_XFER_STD)
+
+ /* Decrementer */
+ EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
+
+- EXCEPTION(0xa00, Trap_0a, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0xb00, Trap_0b, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
+
+ /* System call */
+ . = 0xc00
+@@ -274,9 +274,9 @@ SystemCall:
+ EXC_XFER_EE_LITE(0xc00, DoSyscall)
+
+ /* Single step - not used on 601 */
+- EXCEPTION(0xd00, SingleStep, SingleStepException, EXC_XFER_STD)
+- EXCEPTION(0xe00, Trap_0e, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0xf00, Trap_0f, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
++ EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0xf00, Trap_0f, unknown_exception, EXC_XFER_EE)
+
+ /* On the MPC8xx, this is a software emulation interrupt. It occurs
+ * for all unimplemented and illegal instructions.
+@@ -540,22 +540,22 @@ DataTLBError:
+ #endif
+ b DataAccess
+
+- EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1600, Trap_16, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1700, Trap_17, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1800, Trap_18, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1900, Trap_19, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1a00, Trap_1a, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1b00, Trap_1b, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1700, Trap_17, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
+
+ /* On the MPC8xx, these next four traps are used for development
+ * support of breakpoints and such. Someday I will get around to
+ * using them.
+ */
+- EXCEPTION(0x1c00, Trap_1c, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1d00, Trap_1d, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1e00, Trap_1e, UnknownException, EXC_XFER_EE)
+- EXCEPTION(0x1f00, Trap_1f, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x1c00, Trap_1c, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1d00, Trap_1d, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1e00, Trap_1e, unknown_exception, EXC_XFER_EE)
++ EXCEPTION(0x1f00, Trap_1f, unknown_exception, EXC_XFER_EE)
+
+ . = 0x2000
+
+diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
+--- a/arch/ppc/kernel/head_booke.h
++++ b/arch/ppc/kernel/head_booke.h
+@@ -335,7 +335,7 @@ label:
+ mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \
+ stw r4,_DEAR(r11); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+- EXC_XFER_EE(0x0600, AlignmentException)
++ EXC_XFER_EE(0x0600, alignment_exception)
+
+ #define PROGRAM_EXCEPTION \
+ START_EXCEPTION(Program) \
+@@ -343,7 +343,7 @@ label:
+ mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \
+ stw r4,_ESR(r11); \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+- EXC_XFER_STD(0x0700, ProgramCheckException)
++ EXC_XFER_STD(0x0700, program_check_exception)
+
+ #define DECREMENTER_EXCEPTION \
+ START_EXCEPTION(Decrementer) \
+diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
+--- a/arch/ppc/kernel/head_fsl_booke.S
++++ b/arch/ppc/kernel/head_fsl_booke.S
+@@ -426,14 +426,14 @@ skpinv: addi r6,r6,1 /* Increment */
+
+ interrupt_base:
+ /* Critical Input Interrupt */
+- CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
++ CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
+
+ /* Machine Check Interrupt */
+ #ifdef CONFIG_E200
+ /* no RFMCI, MCSRRs on E200 */
+- CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
++ CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
+ #else
+- MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
++ MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
+ #endif
+
+ /* Data Storage Interrupt */
+@@ -542,9 +542,9 @@ interrupt_base:
+ #else
+ #ifdef CONFIG_E200
+ /* E200 treats 'normal' floating point instructions as FP Unavail exception */
+- EXCEPTION(0x0800, FloatingPointUnavailable, ProgramCheckException, EXC_XFER_EE)
++ EXCEPTION(0x0800, FloatingPointUnavailable, program_check_exception, EXC_XFER_EE)
+ #else
+- EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x0800, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
+ #endif
+ #endif
+
+@@ -554,20 +554,20 @@ interrupt_base:
+ EXC_XFER_EE_LITE(0x0c00, DoSyscall)
+
+ /* Auxillary Processor Unavailable Interrupt */
+- EXCEPTION(0x2900, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x2900, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
+
+ /* Decrementer Interrupt */
+ DECREMENTER_EXCEPTION
+
+ /* Fixed Internal Timer Interrupt */
+ /* TODO: Add FIT support */
+- EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x3100, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
+
+ /* Watchdog Timer Interrupt */
+ #ifdef CONFIG_BOOKE_WDT
+ CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException)
+ #else
+- CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
++ CRITICAL_EXCEPTION(0x3200, WatchdogTimer, unknown_exception)
+ #endif
+
+ /* Data TLB Error Interrupt */
+@@ -696,21 +696,21 @@ interrupt_base:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE_LITE(0x2010, KernelSPE)
+ #else
+- EXCEPTION(0x2020, SPEUnavailable, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x2020, SPEUnavailable, unknown_exception, EXC_XFER_EE)
+ #endif /* CONFIG_SPE */
+
+ /* SPE Floating Point Data */
+ #ifdef CONFIG_SPE
+ EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
+ #else
+- EXCEPTION(0x2040, SPEFloatingPointData, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x2040, SPEFloatingPointData, unknown_exception, EXC_XFER_EE)
+ #endif /* CONFIG_SPE */
+
+ /* SPE Floating Point Round */
+- EXCEPTION(0x2050, SPEFloatingPointRound, UnknownException, EXC_XFER_EE)
++ EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception, EXC_XFER_EE)
+
+ /* Performance Monitor */
+- EXCEPTION(0x2060, PerformanceMonitor, PerformanceMonitorException, EXC_XFER_STD)
++ EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
+
+
+ /* Debug Interrupt */
+@@ -853,7 +853,7 @@ load_up_spe:
+ cmpi 0,r4,0
+ beq 1f
+ addi r4,r4,THREAD /* want THREAD of last_task_used_spe */
+- SAVE_32EVR(0,r10,r4)
++ SAVE_32EVRS(0,r10,r4)
+ evxor evr10, evr10, evr10 /* clear out evr10 */
+ evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */
+ li r5,THREAD_ACC
+@@ -873,7 +873,7 @@ load_up_spe:
+ stw r4,THREAD_USED_SPE(r5)
+ evlddx evr4,r10,r5
+ evmra evr4,evr4
+- REST_32EVR(0,r10,r5)
++ REST_32EVRS(0,r10,r5)
+ #ifndef CONFIG_SMP
+ subi r4,r5,THREAD
+ stw r4,last_task_used_spe at l(r3)
+@@ -963,7 +963,7 @@ _GLOBAL(giveup_spe)
+ addi r3,r3,THREAD /* want THREAD of task */
+ lwz r5,PT_REGS(r3)
+ cmpi 0,r5,0
+- SAVE_32EVR(0, r4, r3)
++ SAVE_32EVRS(0, r4, r3)
+ evxor evr6, evr6, evr6 /* clear out evr6 */
+ evmwumiaa evr6, evr6, evr6 /* evr6 <- ACC = 0 * 0 + ACC */
+ li r4,THREAD_ACC
+@@ -1028,10 +1028,14 @@ _GLOBAL(set_context)
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
+ .data
+-_GLOBAL(sdata)
+-_GLOBAL(empty_zero_page)
++ .align 12
++ .globl sdata
++sdata:
++ .globl empty_zero_page
++empty_zero_page:
+ .space 4096
+-_GLOBAL(swapper_pg_dir)
++ .globl swapper_pg_dir
++swapper_pg_dir:
+ .space 4096
+
+ /* Reserved 4k for the critical exception stack & 4k for the machine
+@@ -1040,13 +1044,15 @@ _GLOBAL(swapper_pg_dir)
+ .align 12
+ exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
+-_GLOBAL(exception_stack_top)
++ .globl exception_stack_top
++exception_stack_top:
+
+ /*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+-_GLOBAL(cmd_line)
++ .globl cmd_line
++cmd_line:
+ .space 512
+
+ /*
+@@ -1055,4 +1061,3 @@ _GLOBAL(cmd_line)
+ */
+ abatron_pteptrs:
+ .space 8
+-
+diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
+--- a/arch/ppc/kernel/idle.c
++++ b/arch/ppc/kernel/idle.c
+@@ -32,6 +32,7 @@
+ #include <asm/cache.h>
+ #include <asm/cputable.h>
+ #include <asm/machdep.h>
++#include <asm/smp.h>
+
+ void default_idle(void)
+ {
+@@ -74,7 +75,7 @@ void cpu_idle(void)
+ /*
+ * Register the sysctl to set/clear powersave_nap.
+ */
+-extern unsigned long powersave_nap;
++extern int powersave_nap;
+
+ static ctl_table powersave_nap_ctl_table[]={
+ {
+diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
+--- a/arch/ppc/kernel/irq.c
++++ b/arch/ppc/kernel/irq.c
+@@ -57,6 +57,7 @@
+ #include <asm/cache.h>
+ #include <asm/prom.h>
+ #include <asm/ptrace.h>
++#include <asm/machdep.h>
+
+ #define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+
+diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S
+--- a/arch/ppc/kernel/l2cr.S
++++ b/arch/ppc/kernel/l2cr.S
+@@ -203,7 +203,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
+ * L1 icache
+ */
+ b 20f
+- .balign L1_CACHE_LINE_SIZE
++ .balign L1_CACHE_BYTES
+ 22:
+ sync
+ mtspr SPRN_L2CR,r3
+diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
+--- a/arch/ppc/kernel/misc.S
++++ b/arch/ppc/kernel/misc.S
+@@ -125,9 +125,8 @@ _GLOBAL(identify_cpu)
+ 1:
+ addis r6,r3,cur_cpu_spec at ha
+ addi r6,r6,cur_cpu_spec at l
+- slwi r4,r4,2
+ sub r8,r8,r3
+- stwx r8,r4,r6
++ stw r8,0(r6)
+ blr
+
+ /*
+@@ -186,19 +185,18 @@ _GLOBAL(do_cpu_ftr_fixups)
+ *
+ * Setup function is called with:
+ * r3 = data offset
+- * r4 = CPU number
+- * r5 = ptr to CPU spec (relocated)
++ * r4 = ptr to CPU spec (relocated)
+ */
+ _GLOBAL(call_setup_cpu)
+- addis r5,r3,cur_cpu_spec at ha
+- addi r5,r5,cur_cpu_spec at l
+- slwi r4,r24,2
+- lwzx r5,r4,r5
++ addis r4,r3,cur_cpu_spec at ha
++ addi r4,r4,cur_cpu_spec at l
++ lwz r4,0(r4)
++ add r4,r4,r3
++ lwz r5,CPU_SPEC_SETUP(r4)
++ cmpi 0,r5,0
+ add r5,r5,r3
+- lwz r6,CPU_SPEC_SETUP(r5)
+- add r6,r6,r3
+- mtctr r6
+- mr r4,r24
++ beqlr
++ mtctr r5
+ bctr
+
+ #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)
+@@ -273,134 +271,6 @@ _GLOBAL(low_choose_7447a_dfs)
+
+ #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
+
+-/* void local_save_flags_ptr(unsigned long *flags) */
+-_GLOBAL(local_save_flags_ptr)
+- mfmsr r4
+- stw r4,0(r3)
+- blr
+- /*
+- * Need these nops here for taking over save/restore to
+- * handle lost intrs
+- * -- Cort
+- */
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+-_GLOBAL(local_save_flags_ptr_end)
+-
+-/* void local_irq_restore(unsigned long flags) */
+-_GLOBAL(local_irq_restore)
+-/*
+- * Just set/clear the MSR_EE bit through restore/flags but do not
+- * change anything else. This is needed by the RT system and makes
+- * sense anyway.
+- * -- Cort
+- */
+- mfmsr r4
+- /* Copy all except the MSR_EE bit from r4 (current MSR value)
+- to r3. This is the sort of thing the rlwimi instruction is
+- designed for. -- paulus. */
+- rlwimi r3,r4,0,17,15
+- /* Check if things are setup the way we want _already_. */
+- cmpw 0,r3,r4
+- beqlr
+-1: SYNC
+- mtmsr r3
+- SYNC
+- blr
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+-_GLOBAL(local_irq_restore_end)
+-
+-_GLOBAL(local_irq_disable)
+- mfmsr r0 /* Get current interrupt state */
+- rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */
+- rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
+- SYNC /* Some chip revs have problems here... */
+- mtmsr r0 /* Update machine state */
+- blr /* Done */
+- /*
+- * Need these nops here for taking over save/restore to
+- * handle lost intrs
+- * -- Cort
+- */
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+-_GLOBAL(local_irq_disable_end)
+-
+-_GLOBAL(local_irq_enable)
+- mfmsr r3 /* Get current state */
+- ori r3,r3,MSR_EE /* Turn on 'EE' bit */
+- SYNC /* Some chip revs have problems here... */
+- mtmsr r3 /* Update machine state */
+- blr
+- /*
+- * Need these nops here for taking over save/restore to
+- * handle lost intrs
+- * -- Cort
+- */
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+- nop
+-_GLOBAL(local_irq_enable_end)
+-
+ /*
+ * complement mask on the msr then "or" some values on.
+ * _nmask_and_or_msr(nmask, value_to_or)
+@@ -628,21 +498,21 @@ _GLOBAL(flush_icache_range)
+ BEGIN_FTR_SECTION
+ blr /* for 601, do nothing */
+ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+- li r5,L1_CACHE_LINE_SIZE-1
++ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+- srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
++ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+ mr r6,r3
+ 1: dcbst 0,r3
+- addi r3,r3,L1_CACHE_LINE_SIZE
++ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+ 2: icbi 0,r6
+- addi r6,r6,L1_CACHE_LINE_SIZE
++ addi r6,r6,L1_CACHE_BYTES
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+@@ -655,16 +525,16 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_C
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+ _GLOBAL(clean_dcache_range)
+- li r5,L1_CACHE_LINE_SIZE-1
++ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+- srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
++ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+
+ 1: dcbst 0,r3
+- addi r3,r3,L1_CACHE_LINE_SIZE
++ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+@@ -676,16 +546,16 @@ _GLOBAL(clean_dcache_range)
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+ _GLOBAL(flush_dcache_range)
+- li r5,L1_CACHE_LINE_SIZE-1
++ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+- srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
++ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+
+ 1: dcbf 0,r3
+- addi r3,r3,L1_CACHE_LINE_SIZE
++ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+@@ -698,16 +568,16 @@ _GLOBAL(flush_dcache_range)
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+ _GLOBAL(invalidate_dcache_range)
+- li r5,L1_CACHE_LINE_SIZE-1
++ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+- srwi. r4,r4,LG_L1_CACHE_LINE_SIZE
++ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+
+ 1: dcbi 0,r3
+- addi r3,r3,L1_CACHE_LINE_SIZE
++ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbi's to get to ram */
+ blr
+@@ -728,7 +598,7 @@ _GLOBAL(flush_dcache_all)
+ mtctr r4
+ lis r5, KERNELBASE at h
+ 1: lwz r3, 0(r5) /* Load one word from every line */
+- addi r5, r5, L1_CACHE_LINE_SIZE
++ addi r5, r5, L1_CACHE_BYTES
+ bdnz 1b
+ blr
+ #endif /* CONFIG_NOT_COHERENT_CACHE */
+@@ -746,16 +616,16 @@ BEGIN_FTR_SECTION
+ blr /* for 601, do nothing */
+ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+ rlwinm r3,r3,0,0,19 /* Get page base address */
+- li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
++ li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+ 0: dcbst 0,r3 /* Write line to ram */
+- addi r3,r3,L1_CACHE_LINE_SIZE
++ addi r3,r3,L1_CACHE_BYTES
+ bdnz 0b
+ sync
+ mtctr r4
+ 1: icbi 0,r6
+- addi r6,r6,L1_CACHE_LINE_SIZE
++ addi r6,r6,L1_CACHE_BYTES
+ bdnz 1b
+ sync
+ isync
+@@ -778,16 +648,16 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_C
+ mtmsr r0
+ isync
+ rlwinm r3,r3,0,0,19 /* Get page base address */
+- li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
++ li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+ 0: dcbst 0,r3 /* Write line to ram */
+- addi r3,r3,L1_CACHE_LINE_SIZE
++ addi r3,r3,L1_CACHE_BYTES
+ bdnz 0b
+ sync
+ mtctr r4
+ 1: icbi 0,r6
+- addi r6,r6,L1_CACHE_LINE_SIZE
++ addi r6,r6,L1_CACHE_BYTES
+ bdnz 1b
+ sync
+ mtmsr r10 /* restore DR */
+@@ -802,7 +672,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_C
+ * void clear_pages(void *page, int order) ;
+ */
+ _GLOBAL(clear_pages)
+- li r0,4096/L1_CACHE_LINE_SIZE
++ li r0,4096/L1_CACHE_BYTES
+ slw r0,r0,r4
+ mtctr r0
+ #ifdef CONFIG_8xx
+@@ -814,7 +684,7 @@ _GLOBAL(clear_pages)
+ #else
+ 1: dcbz 0,r3
+ #endif
+- addi r3,r3,L1_CACHE_LINE_SIZE
++ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ blr
+
+@@ -840,7 +710,7 @@ _GLOBAL(copy_page)
+
+ #ifdef CONFIG_8xx
+ /* don't use prefetch on 8xx */
+- li r0,4096/L1_CACHE_LINE_SIZE
++ li r0,4096/L1_CACHE_BYTES
+ mtctr r0
+ 1: COPY_16_BYTES
+ bdnz 1b
+@@ -854,13 +724,13 @@ _GLOBAL(copy_page)
+ li r11,4
+ mtctr r0
+ 11: dcbt r11,r4
+- addi r11,r11,L1_CACHE_LINE_SIZE
++ addi r11,r11,L1_CACHE_BYTES
+ bdnz 11b
+ #else /* MAX_COPY_PREFETCH == 1 */
+ dcbt r5,r4
+- li r11,L1_CACHE_LINE_SIZE+4
++ li r11,L1_CACHE_BYTES+4
+ #endif /* MAX_COPY_PREFETCH */
+- li r0,4096/L1_CACHE_LINE_SIZE - MAX_COPY_PREFETCH
++ li r0,4096/L1_CACHE_BYTES - MAX_COPY_PREFETCH
+ crclr 4*cr0+eq
+ 2:
+ mtctr r0
+@@ -868,12 +738,12 @@ _GLOBAL(copy_page)
+ dcbt r11,r4
+ dcbz r5,r3
+ COPY_16_BYTES
+-#if L1_CACHE_LINE_SIZE >= 32
++#if L1_CACHE_BYTES >= 32
+ COPY_16_BYTES
+-#if L1_CACHE_LINE_SIZE >= 64
++#if L1_CACHE_BYTES >= 64
+ COPY_16_BYTES
+ COPY_16_BYTES
+-#if L1_CACHE_LINE_SIZE >= 128
++#if L1_CACHE_BYTES >= 128
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+@@ -1098,33 +968,6 @@ _GLOBAL(_get_SP)
+ blr
+
+ /*
+- * These are used in the alignment trap handler when emulating
+- * single-precision loads and stores.
+- * We restore and save the fpscr so the task gets the same result
+- * and exceptions as if the cpu had performed the load or store.
+- */
+-
+-#ifdef CONFIG_PPC_FPU
+-_GLOBAL(cvt_fd)
+- lfd 0,-4(r5) /* load up fpscr value */
+- mtfsf 0xff,0
+- lfs 0,0(r3)
+- stfd 0,0(r4)
+- mffs 0 /* save new fpscr value */
+- stfd 0,-4(r5)
+- blr
+-
+-_GLOBAL(cvt_df)
+- lfd 0,-4(r5) /* load up fpscr value */
+- mtfsf 0xff,0
+- lfd 0,0(r3)
+- stfs 0,0(r4)
+- mffs 0 /* save new fpscr value */
+- stfd 0,-4(r5)
+- blr
+-#endif
+-
+-/*
+ * Create a kernel thread
+ * kernel_thread(fn, arg, flags)
+ */
+diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
+--- a/arch/ppc/kernel/pci.c
++++ b/arch/ppc/kernel/pci.c
+@@ -21,6 +21,7 @@
+ #include <asm/byteorder.h>
+ #include <asm/irq.h>
+ #include <asm/uaccess.h>
++#include <asm/machdep.h>
+
+ #undef DEBUG
+
+@@ -53,7 +54,7 @@ static u8* pci_to_OF_bus_map;
+ /* By default, we don't re-assign bus numbers. We do this only on
+ * some pmacs
+ */
+-int pci_assign_all_busses;
++int pci_assign_all_buses;
+
+ struct pci_controller* hose_head;
+ struct pci_controller** hose_tail = &hose_head;
+@@ -644,7 +645,7 @@ pcibios_alloc_controller(void)
+ /*
+ * Functions below are used on OpenFirmware machines.
+ */
+-static void __openfirmware
++static void
+ make_one_node_map(struct device_node* node, u8 pci_bus)
+ {
+ int *bus_range;
+@@ -678,7 +679,7 @@ make_one_node_map(struct device_node* no
+ }
+ }
+
+-void __openfirmware
++void
+ pcibios_make_OF_bus_map(void)
+ {
+ int i;
+@@ -720,7 +721,7 @@ pcibios_make_OF_bus_map(void)
+
+ typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
+
+-static struct device_node* __openfirmware
++static struct device_node*
+ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)
+ {
+ struct device_node* sub_node;
+@@ -761,7 +762,7 @@ scan_OF_pci_childs_iterator(struct devic
+ return 0;
+ }
+
+-static struct device_node* __openfirmware
++static struct device_node*
+ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+ {
+ u8 filter_data[2] = {bus, dev_fn};
+@@ -813,18 +814,20 @@ pci_busdev_to_OF_node(struct pci_bus *bu
+ /* Now, lookup childs of the hose */
+ return scan_OF_childs_for_device(node->child, busnr, devfn);
+ }
++EXPORT_SYMBOL(pci_busdev_to_OF_node);
+
+ struct device_node*
+ pci_device_to_OF_node(struct pci_dev *dev)
+ {
+ return pci_busdev_to_OF_node(dev->bus, dev->devfn);
+ }
++EXPORT_SYMBOL(pci_device_to_OF_node);
+
+ /* This routine is meant to be used early during boot, when the
+ * PCI bus numbers have not yet been assigned, and you need to
+ * issue PCI config cycles to an OF device.
+ * It could also be used to "fix" RTAS config cycles if you want
+- * to set pci_assign_all_busses to 1 and still use RTAS for PCI
++ * to set pci_assign_all_buses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+ struct pci_controller*
+@@ -842,7 +845,7 @@ pci_find_hose_for_OF_device(struct devic
+ return NULL;
+ }
+
+-static int __openfirmware
++static int
+ find_OF_pci_device_filter(struct device_node* node, void* data)
+ {
+ return ((void *)node == data);
+@@ -890,6 +893,7 @@ pci_device_from_OF_node(struct device_no
+ }
+ return -ENODEV;
+ }
++EXPORT_SYMBOL(pci_device_from_OF_node);
+
+ void __init
+ pci_process_bridge_OF_ranges(struct pci_controller *hose,
+@@ -1030,6 +1034,10 @@ static ssize_t pci_show_devspec(struct d
+ }
+ static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
+
++#else /* CONFIG_PPC_OF */
++void pcibios_make_OF_bus_map(void)
++{
++}
+ #endif /* CONFIG_PPC_OF */
+
+ /* Add sysfs properties */
+@@ -1262,12 +1270,12 @@ pcibios_init(void)
+
+ /* Scan all of the recorded PCI controllers. */
+ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+- if (pci_assign_all_busses)
++ if (pci_assign_all_buses)
+ hose->first_busno = next_busno;
+ hose->last_busno = 0xff;
+ bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
+ hose->last_busno = bus->subordinate;
+- if (pci_assign_all_busses || next_busno <= hose->last_busno)
++ if (pci_assign_all_buses || next_busno <= hose->last_busno)
+ next_busno = hose->last_busno + pcibios_assign_bus_offset;
+ }
+ pci_bus_count = next_busno;
+@@ -1276,7 +1284,7 @@ pcibios_init(void)
+ * numbers vs. kernel bus numbers since we may have to
+ * remap them.
+ */
+- if (pci_assign_all_busses && have_of)
++ if (pci_assign_all_buses && have_of)
+ pcibios_make_OF_bus_map();
+
+ /* Do machine dependent PCI interrupt routing */
+@@ -1586,16 +1594,17 @@ static pgprot_t __pci_mmap_set_pgprot(st
+ * above routine
+ */
+ pgprot_t pci_phys_mem_access_prot(struct file *file,
+- unsigned long offset,
++ unsigned long pfn,
+ unsigned long size,
+ pgprot_t protection)
+ {
+ struct pci_dev *pdev = NULL;
+ struct resource *found = NULL;
+ unsigned long prot = pgprot_val(protection);
++ unsigned long offset = pfn << PAGE_SHIFT;
+ int i;
+
+- if (page_is_ram(offset >> PAGE_SHIFT))
++ if (page_is_ram(pfn))
+ return prot;
+
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c
+deleted file mode 100644
+--- a/arch/ppc/kernel/perfmon.c
++++ /dev/null
+@@ -1,96 +0,0 @@
+-/* kernel/perfmon.c
+- * PPC 32 Performance Monitor Infrastructure
+- *
+- * Author: Andy Fleming
+- * Copyright (c) 2004 Freescale Semiconductor, Inc
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/user.h>
+-#include <linux/a.out.h>
+-#include <linux/interrupt.h>
+-#include <linux/config.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/prctl.h>
+-
+-#include <asm/pgtable.h>
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/reg.h>
+-#include <asm/xmon.h>
+-
+-/* A lock to regulate grabbing the interrupt */
+-DEFINE_SPINLOCK(perfmon_lock);
+-
+-#if defined (CONFIG_FSL_BOOKE) && !defined (CONFIG_E200)
+-static void dummy_perf(struct pt_regs *regs)
+-{
+- unsigned int pmgc0 = mfpmr(PMRN_PMGC0);
+-
+- pmgc0 &= ~PMGC0_PMIE;
+- mtpmr(PMRN_PMGC0, pmgc0);
+-}
+-
+-#elif defined(CONFIG_6xx)
+-/* Ensure exceptions are disabled */
+-static void dummy_perf(struct pt_regs *regs)
+-{
+- unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+-
+- mmcr0 &= ~MMCR0_PMXE;
+- mtspr(SPRN_MMCR0, mmcr0);
+-}
+-#else
+-static void dummy_perf(struct pt_regs *regs)
+-{
+-}
+-#endif
+-
+-void (*perf_irq)(struct pt_regs *) = dummy_perf;
+-
+-/* Grab the interrupt, if it's free.
+- * Returns 0 on success, -1 if the interrupt is taken already */
+-int request_perfmon_irq(void (*handler)(struct pt_regs *))
+-{
+- int err = 0;
+-
+- spin_lock(&perfmon_lock);
+-
+- if (perf_irq == dummy_perf)
+- perf_irq = handler;
+- else {
+- pr_info("perfmon irq already handled by %p\n", perf_irq);
+- err = -1;
+- }
+-
+- spin_unlock(&perfmon_lock);
+-
+- return err;
+-}
+-
+-void free_perfmon_irq(void)
+-{
+- spin_lock(&perfmon_lock);
+-
+- perf_irq = dummy_perf;
+-
+- spin_unlock(&perfmon_lock);
+-}
+-
+-EXPORT_SYMBOL(perf_irq);
+-EXPORT_SYMBOL(request_perfmon_irq);
+-EXPORT_SYMBOL(free_perfmon_irq);
+diff --git a/arch/ppc/kernel/perfmon_fsl_booke.c b/arch/ppc/kernel/perfmon_fsl_booke.c
+--- a/arch/ppc/kernel/perfmon_fsl_booke.c
++++ b/arch/ppc/kernel/perfmon_fsl_booke.c
+@@ -32,7 +32,7 @@
+ #include <asm/io.h>
+ #include <asm/reg.h>
+ #include <asm/xmon.h>
+-#include <asm/perfmon.h>
++#include <asm/pmc.h>
+
+ static inline u32 get_pmlca(int ctr);
+ static inline void set_pmlca(int ctr, u32 pmlca);
+diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
+--- a/arch/ppc/kernel/ppc_ksyms.c
++++ b/arch/ppc/kernel/ppc_ksyms.c
+@@ -53,10 +53,10 @@
+
+ extern void transfer_to_handler(void);
+ extern void do_IRQ(struct pt_regs *regs);
+-extern void MachineCheckException(struct pt_regs *regs);
+-extern void AlignmentException(struct pt_regs *regs);
+-extern void ProgramCheckException(struct pt_regs *regs);
+-extern void SingleStepException(struct pt_regs *regs);
++extern void machine_check_exception(struct pt_regs *regs);
++extern void alignment_exception(struct pt_regs *regs);
++extern void program_check_exception(struct pt_regs *regs);
++extern void single_step_exception(struct pt_regs *regs);
+ extern int do_signal(sigset_t *, struct pt_regs *);
+ extern int pmac_newworld;
+ extern int sys_sigreturn(struct pt_regs *regs);
+@@ -72,10 +72,10 @@ EXPORT_SYMBOL(clear_user_page);
+ EXPORT_SYMBOL(do_signal);
+ EXPORT_SYMBOL(transfer_to_handler);
+ EXPORT_SYMBOL(do_IRQ);
+-EXPORT_SYMBOL(MachineCheckException);
+-EXPORT_SYMBOL(AlignmentException);
+-EXPORT_SYMBOL(ProgramCheckException);
+-EXPORT_SYMBOL(SingleStepException);
++EXPORT_SYMBOL(machine_check_exception);
++EXPORT_SYMBOL(alignment_exception);
++EXPORT_SYMBOL(program_check_exception);
++EXPORT_SYMBOL(single_step_exception);
+ EXPORT_SYMBOL(sys_sigreturn);
+ EXPORT_SYMBOL(ppc_n_lost_interrupts);
+ EXPORT_SYMBOL(ppc_lost_interrupts);
+@@ -230,9 +230,6 @@ EXPORT_SYMBOL(find_all_nodes);
+ EXPORT_SYMBOL(get_property);
+ EXPORT_SYMBOL(request_OF_resource);
+ EXPORT_SYMBOL(release_OF_resource);
+-EXPORT_SYMBOL(pci_busdev_to_OF_node);
+-EXPORT_SYMBOL(pci_device_to_OF_node);
+-EXPORT_SYMBOL(pci_device_from_OF_node);
+ EXPORT_SYMBOL(of_find_node_by_name);
+ EXPORT_SYMBOL(of_find_node_by_type);
+ EXPORT_SYMBOL(of_find_compatible_node);
+@@ -272,16 +269,6 @@ EXPORT_SYMBOL(screen_info);
+ #endif
+
+ EXPORT_SYMBOL(__delay);
+-#ifndef INLINE_IRQS
+-EXPORT_SYMBOL(local_irq_enable);
+-EXPORT_SYMBOL(local_irq_enable_end);
+-EXPORT_SYMBOL(local_irq_disable);
+-EXPORT_SYMBOL(local_irq_disable_end);
+-EXPORT_SYMBOL(local_save_flags_ptr);
+-EXPORT_SYMBOL(local_save_flags_ptr_end);
+-EXPORT_SYMBOL(local_irq_restore);
+-EXPORT_SYMBOL(local_irq_restore_end);
+-#endif
+ EXPORT_SYMBOL(timer_interrupt);
+ EXPORT_SYMBOL(irq_desc);
+ EXPORT_SYMBOL(tb_ticks_per_jiffy);
+@@ -335,11 +322,6 @@ EXPORT_SYMBOL(mmu_hash_lock); /* For MOL
+ extern long *intercept_table;
+ EXPORT_SYMBOL(intercept_table);
+ #endif /* CONFIG_PPC_STD_MMU */
+-EXPORT_SYMBOL(cur_cpu_spec);
+-#ifdef CONFIG_PPC_PMAC
+-extern unsigned long agp_special_page;
+-EXPORT_SYMBOL(agp_special_page);
+-#endif
+ #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ EXPORT_SYMBOL(__mtdcr);
+ EXPORT_SYMBOL(__mfdcr);
+diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
+--- a/arch/ppc/kernel/process.c
++++ b/arch/ppc/kernel/process.c
+@@ -152,18 +152,66 @@ int check_stack(struct task_struct *tsk)
+ }
+ #endif /* defined(CHECK_STACK) */
+
+-#ifdef CONFIG_ALTIVEC
+-int
+-dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
++/*
++ * Make sure the floating-point register state in the
++ * the thread_struct is up to date for task tsk.
++ */
++void flush_fp_to_thread(struct task_struct *tsk)
+ {
+- if (regs->msr & MSR_VEC)
+- giveup_altivec(current);
+- memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs));
++ if (tsk->thread.regs) {
++ /*
++ * We need to disable preemption here because if we didn't,
++ * another process could get scheduled after the regs->msr
++ * test but before we have finished saving the FP registers
++ * to the thread_struct. That process could take over the
++ * FPU, and then when we get scheduled again we would store
++ * bogus values for the remaining FP registers.
++ */
++ preempt_disable();
++ if (tsk->thread.regs->msr & MSR_FP) {
++#ifdef CONFIG_SMP
++ /*
++ * This should only ever be called for current or
++ * for a stopped child process. Since we save away
++ * the FP register state on context switch on SMP,
++ * there is something wrong if a stopped child appears
++ * to still have its FP state in the CPU registers.
++ */
++ BUG_ON(tsk != current);
++#endif
++ giveup_fpu(current);
++ }
++ preempt_enable();
++ }
++}
++
++void enable_kernel_fp(void)
++{
++ WARN_ON(preemptible());
++
++#ifdef CONFIG_SMP
++ if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
++ giveup_fpu(current);
++ else
++ giveup_fpu(NULL); /* just enables FP for kernel */
++#else
++ giveup_fpu(last_task_used_math);
++#endif /* CONFIG_SMP */
++}
++EXPORT_SYMBOL(enable_kernel_fp);
++
++int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
++{
++ preempt_disable();
++ if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP))
++ giveup_fpu(tsk);
++ preempt_enable();
++ memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
+ return 1;
+ }
+
+-void
+-enable_kernel_altivec(void)
++#ifdef CONFIG_ALTIVEC
++void enable_kernel_altivec(void)
+ {
+ WARN_ON(preemptible());
+
+@@ -177,19 +225,35 @@ enable_kernel_altivec(void)
+ #endif /* __SMP __ */
+ }
+ EXPORT_SYMBOL(enable_kernel_altivec);
+-#endif /* CONFIG_ALTIVEC */
+
+-#ifdef CONFIG_SPE
+-int
+-dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
++/*
++ * Make sure the VMX/Altivec register state in the
++ * the thread_struct is up to date for task tsk.
++ */
++void flush_altivec_to_thread(struct task_struct *tsk)
+ {
+- if (regs->msr & MSR_SPE)
+- giveup_spe(current);
+- /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
+- memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35);
++ if (tsk->thread.regs) {
++ preempt_disable();
++ if (tsk->thread.regs->msr & MSR_VEC) {
++#ifdef CONFIG_SMP
++ BUG_ON(tsk != current);
++#endif
++ giveup_altivec(current);
++ }
++ preempt_enable();
++ }
++}
++
++int dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
++{
++ if (regs->msr & MSR_VEC)
++ giveup_altivec(current);
++ memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs));
+ return 1;
+ }
++#endif /* CONFIG_ALTIVEC */
+
++#ifdef CONFIG_SPE
+ void
+ enable_kernel_spe(void)
+ {
+@@ -205,34 +269,30 @@ enable_kernel_spe(void)
+ #endif /* __SMP __ */
+ }
+ EXPORT_SYMBOL(enable_kernel_spe);
+-#endif /* CONFIG_SPE */
+
+-void
+-enable_kernel_fp(void)
++void flush_spe_to_thread(struct task_struct *tsk)
+ {
+- WARN_ON(preemptible());
+-
++ if (tsk->thread.regs) {
++ preempt_disable();
++ if (tsk->thread.regs->msr & MSR_SPE) {
+ #ifdef CONFIG_SMP
+- if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
+- giveup_fpu(current);
+- else
+- giveup_fpu(NULL); /* just enables FP for kernel */
+-#else
+- giveup_fpu(last_task_used_math);
+-#endif /* CONFIG_SMP */
++ BUG_ON(tsk != current);
++#endif
++ giveup_spe(current);
++ }
++ preempt_enable();
++ }
+ }
+-EXPORT_SYMBOL(enable_kernel_fp);
+
+-int
+-dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
++int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
+ {
+- preempt_disable();
+- if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP))
+- giveup_fpu(tsk);
+- preempt_enable();
+- memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
++ if (regs->msr & MSR_SPE)
++ giveup_spe(current);
++ /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
++ memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35);
+ return 1;
+ }
++#endif /* CONFIG_SPE */
+
+ struct task_struct *__switch_to(struct task_struct *prev,
+ struct task_struct *new)
+@@ -287,11 +347,13 @@ struct task_struct *__switch_to(struct t
+ #endif /* CONFIG_SPE */
+ #endif /* CONFIG_SMP */
+
++#ifdef CONFIG_ALTIVEC
+ /* Avoid the trap. On smp this this never happens since
+ * we don't set last_task_used_altivec -- Cort
+ */
+ if (new->thread.regs && last_task_used_altivec == new)
+ new->thread.regs->msr |= MSR_VEC;
++#endif
+ #ifdef CONFIG_SPE
+ /* Avoid the trap. On smp this this never happens since
+ * we don't set last_task_used_spe
+@@ -482,7 +544,7 @@ void start_thread(struct pt_regs *regs,
+ last_task_used_spe = NULL;
+ #endif
+ memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
+- current->thread.fpscr = 0;
++ current->thread.fpscr.val = 0;
+ #ifdef CONFIG_ALTIVEC
+ memset(current->thread.vr, 0, sizeof(current->thread.vr));
+ memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr));
+@@ -557,14 +619,16 @@ int sys_clone(unsigned long clone_flags,
+ return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
+ }
+
+-int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
++int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5, unsigned long p6,
+ struct pt_regs *regs)
+ {
+ CHECK_FULL_REGS(regs);
+ return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
+ }
+
+-int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
++int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5, unsigned long p6,
+ struct pt_regs *regs)
+ {
+ CHECK_FULL_REGS(regs);
+diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
+deleted file mode 100644
+--- a/arch/ppc/kernel/ptrace.c
++++ /dev/null
+@@ -1,507 +0,0 @@
+-/*
+- * arch/ppc/kernel/ptrace.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Derived from "arch/m68k/kernel/ptrace.c"
+- * Copyright (C) 1994 by Hamish Macdonald
+- * Taken from linux/kernel/ptrace.c and modified for M680x0.
+- * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+- *
+- * Modified by Cort Dougan (cort at hq.fsmlabs.com)
+- * and Paul Mackerras (paulus at linuxcare.com.au).
+- *
+- * This file is subject to the terms and conditions of the GNU General
+- * Public License. See the file README.legal in the main directory of
+- * this archive for more details.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/errno.h>
+-#include <linux/ptrace.h>
+-#include <linux/user.h>
+-#include <linux/security.h>
+-#include <linux/signal.h>
+-#include <linux/seccomp.h>
+-#include <linux/audit.h>
+-#include <linux/module.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/system.h>
+-
+-/*
+- * Set of msr bits that gdb can change on behalf of a process.
+- */
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+-#define MSR_DEBUGCHANGE 0
+-#else
+-#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
+-#endif
+-
+-/*
+- * does not yet catch signals sent when the child dies.
+- * in exit.c or in signal.c.
+- */
+-
+-/*
+- * Get contents of register REGNO in task TASK.
+- */
+-static inline unsigned long get_reg(struct task_struct *task, int regno)
+-{
+- if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
+- && task->thread.regs != NULL)
+- return ((unsigned long *)task->thread.regs)[regno];
+- return (0);
+-}
+-
+-/*
+- * Write contents of register REGNO in task TASK.
+- */
+-static inline int put_reg(struct task_struct *task, int regno,
+- unsigned long data)
+-{
+- if (regno <= PT_MQ && task->thread.regs != NULL) {
+- if (regno == PT_MSR)
+- data = (data & MSR_DEBUGCHANGE)
+- | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+- ((unsigned long *)task->thread.regs)[regno] = data;
+- return 0;
+- }
+- return -EIO;
+-}
+-
+-#ifdef CONFIG_ALTIVEC
+-/*
+- * Get contents of AltiVec register state in task TASK
+- */
+-static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
+-{
+- int i, j;
+-
+- if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
+- return -EFAULT;
+-
+- /* copy AltiVec registers VR[0] .. VR[31] */
+- for (i = 0; i < 32; i++)
+- for (j = 0; j < 4; j++, data++)
+- if (__put_user(task->thread.vr[i].u[j], data))
+- return -EFAULT;
+-
+- /* copy VSCR */
+- for (i = 0; i < 4; i++, data++)
+- if (__put_user(task->thread.vscr.u[i], data))
+- return -EFAULT;
+-
+- /* copy VRSAVE */
+- if (__put_user(task->thread.vrsave, data))
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-/*
+- * Write contents of AltiVec register state into task TASK.
+- */
+-static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
+-{
+- int i, j;
+-
+- if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
+- return -EFAULT;
+-
+- /* copy AltiVec registers VR[0] .. VR[31] */
+- for (i = 0; i < 32; i++)
+- for (j = 0; j < 4; j++, data++)
+- if (__get_user(task->thread.vr[i].u[j], data))
+- return -EFAULT;
+-
+- /* copy VSCR */
+- for (i = 0; i < 4; i++, data++)
+- if (__get_user(task->thread.vscr.u[i], data))
+- return -EFAULT;
+-
+- /* copy VRSAVE */
+- if (__get_user(task->thread.vrsave, data))
+- return -EFAULT;
+-
+- return 0;
+-}
+-#endif
+-
+-#ifdef CONFIG_SPE
+-
+-/*
+- * For get_evrregs/set_evrregs functions 'data' has the following layout:
+- *
+- * struct {
+- * u32 evr[32];
+- * u64 acc;
+- * u32 spefscr;
+- * }
+- */
+-
+-/*
+- * Get contents of SPE register state in task TASK.
+- */
+-static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+-{
+- int i;
+-
+- if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
+- return -EFAULT;
+-
+- /* copy SPEFSCR */
+- if (__put_user(task->thread.spefscr, &data[34]))
+- return -EFAULT;
+-
+- /* copy SPE registers EVR[0] .. EVR[31] */
+- for (i = 0; i < 32; i++, data++)
+- if (__put_user(task->thread.evr[i], data))
+- return -EFAULT;
+-
+- /* copy ACC */
+- if (__put_user64(task->thread.acc, (unsigned long long *)data))
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-/*
+- * Write contents of SPE register state into task TASK.
+- */
+-static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+-{
+- int i;
+-
+- if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
+- return -EFAULT;
+-
+- /* copy SPEFSCR */
+- if (__get_user(task->thread.spefscr, &data[34]))
+- return -EFAULT;
+-
+- /* copy SPE registers EVR[0] .. EVR[31] */
+- for (i = 0; i < 32; i++, data++)
+- if (__get_user(task->thread.evr[i], data))
+- return -EFAULT;
+- /* copy ACC */
+- if (__get_user64(task->thread.acc, (unsigned long long*)data))
+- return -EFAULT;
+-
+- return 0;
+-}
+-#endif /* CONFIG_SPE */
+-
+-static inline void
+-set_single_step(struct task_struct *task)
+-{
+- struct pt_regs *regs = task->thread.regs;
+-
+- if (regs != NULL) {
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+- task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
+- regs->msr |= MSR_DE;
+-#else
+- regs->msr |= MSR_SE;
+-#endif
+- }
+-}
+-
+-static inline void
+-clear_single_step(struct task_struct *task)
+-{
+- struct pt_regs *regs = task->thread.regs;
+-
+- if (regs != NULL) {
+-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+- task->thread.dbcr0 = 0;
+- regs->msr &= ~MSR_DE;
+-#else
+- regs->msr &= ~MSR_SE;
+-#endif
+- }
+-}
+-
+-/*
+- * Called by kernel/ptrace.c when detaching..
+- *
+- * Make sure single step bits etc are not set.
+- */
+-void ptrace_disable(struct task_struct *child)
+-{
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+-}
+-
+-int sys_ptrace(long request, long pid, long addr, long data)
+-{
+- struct task_struct *child;
+- int ret = -EPERM;
+-
+- lock_kernel();
+- if (request == PTRACE_TRACEME) {
+- /* are we already being traced? */
+- if (current->ptrace & PT_PTRACED)
+- goto out;
+- ret = security_ptrace(current->parent, current);
+- if (ret)
+- goto out;
+- /* set the ptrace bit in the process flags. */
+- current->ptrace |= PT_PTRACED;
+- ret = 0;
+- goto out;
+- }
+- ret = -ESRCH;
+- read_lock(&tasklist_lock);
+- child = find_task_by_pid(pid);
+- if (child)
+- get_task_struct(child);
+- read_unlock(&tasklist_lock);
+- if (!child)
+- goto out;
+-
+- ret = -EPERM;
+- if (pid == 1) /* you may not mess with init */
+- goto out_tsk;
+-
+- if (request == PTRACE_ATTACH) {
+- ret = ptrace_attach(child);
+- goto out_tsk;
+- }
+-
+- ret = ptrace_check_attach(child, request == PTRACE_KILL);
+- if (ret < 0)
+- goto out_tsk;
+-
+- switch (request) {
+- /* when I and D space are separate, these will need to be fixed. */
+- case PTRACE_PEEKTEXT: /* read word at location addr. */
+- case PTRACE_PEEKDATA: {
+- unsigned long tmp;
+- int copied;
+-
+- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+- ret = -EIO;
+- if (copied != sizeof(tmp))
+- break;
+- ret = put_user(tmp,(unsigned long __user *) data);
+- break;
+- }
+-
+- /* read the word at location addr in the USER area. */
+- /* XXX this will need fixing for 64-bit */
+- case PTRACE_PEEKUSR: {
+- unsigned long index, tmp;
+-
+- ret = -EIO;
+- /* convert to index and check */
+- index = (unsigned long) addr >> 2;
+- if ((addr & 3) || index > PT_FPSCR
+- || child->thread.regs == NULL)
+- break;
+-
+- CHECK_FULL_REGS(child->thread.regs);
+- if (index < PT_FPR0) {
+- tmp = get_reg(child, (int) index);
+- } else {
+- preempt_disable();
+- if (child->thread.regs->msr & MSR_FP)
+- giveup_fpu(child);
+- preempt_enable();
+- tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
+- }
+- ret = put_user(tmp,(unsigned long __user *) data);
+- break;
+- }
+-
+- /* If I and D space are separate, this will have to be fixed. */
+- case PTRACE_POKETEXT: /* write the word at location addr. */
+- case PTRACE_POKEDATA:
+- ret = 0;
+- if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+- break;
+- ret = -EIO;
+- break;
+-
+- /* write the word at location addr in the USER area */
+- case PTRACE_POKEUSR: {
+- unsigned long index;
+-
+- ret = -EIO;
+- /* convert to index and check */
+- index = (unsigned long) addr >> 2;
+- if ((addr & 3) || index > PT_FPSCR
+- || child->thread.regs == NULL)
+- break;
+-
+- CHECK_FULL_REGS(child->thread.regs);
+- if (index == PT_ORIG_R3)
+- break;
+- if (index < PT_FPR0) {
+- ret = put_reg(child, index, data);
+- } else {
+- preempt_disable();
+- if (child->thread.regs->msr & MSR_FP)
+- giveup_fpu(child);
+- preempt_enable();
+- ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
+- ret = 0;
+- }
+- break;
+- }
+-
+- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+- case PTRACE_CONT: { /* restart after signal. */
+- ret = -EIO;
+- if (!valid_signal(data))
+- break;
+- if (request == PTRACE_SYSCALL) {
+- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- } else {
+- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- }
+- child->exit_code = data;
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+- wake_up_process(child);
+- ret = 0;
+- break;
+- }
+-
+-/*
+- * make the child exit. Best I can do is send it a sigkill.
+- * perhaps it should be put in the status that it wants to
+- * exit.
+- */
+- case PTRACE_KILL: {
+- ret = 0;
+- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+- break;
+- child->exit_code = SIGKILL;
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+- wake_up_process(child);
+- break;
+- }
+-
+- case PTRACE_SINGLESTEP: { /* set the trap flag. */
+- ret = -EIO;
+- if (!valid_signal(data))
+- break;
+- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- set_single_step(child);
+- child->exit_code = data;
+- /* give it a chance to run. */
+- wake_up_process(child);
+- ret = 0;
+- break;
+- }
+-
+- case PTRACE_DETACH:
+- ret = ptrace_detach(child, data);
+- break;
+-
+-#ifdef CONFIG_ALTIVEC
+- case PTRACE_GETVRREGS:
+- /* Get the child altivec register state. */
+- preempt_disable();
+- if (child->thread.regs->msr & MSR_VEC)
+- giveup_altivec(child);
+- preempt_enable();
+- ret = get_vrregs((unsigned long __user *)data, child);
+- break;
+-
+- case PTRACE_SETVRREGS:
+- /* Set the child altivec register state. */
+- /* this is to clear the MSR_VEC bit to force a reload
+- * of register state from memory */
+- preempt_disable();
+- if (child->thread.regs->msr & MSR_VEC)
+- giveup_altivec(child);
+- preempt_enable();
+- ret = set_vrregs(child, (unsigned long __user *)data);
+- break;
+-#endif
+-#ifdef CONFIG_SPE
+- case PTRACE_GETEVRREGS:
+- /* Get the child spe register state. */
+- if (child->thread.regs->msr & MSR_SPE)
+- giveup_spe(child);
+- ret = get_evrregs((unsigned long __user *)data, child);
+- break;
+-
+- case PTRACE_SETEVRREGS:
+- /* Set the child spe register state. */
+- /* this is to clear the MSR_SPE bit to force a reload
+- * of register state from memory */
+- if (child->thread.regs->msr & MSR_SPE)
+- giveup_spe(child);
+- ret = set_evrregs(child, (unsigned long __user *)data);
+- break;
+-#endif
+-
+- default:
+- ret = ptrace_request(child, request, addr, data);
+- break;
+- }
+-out_tsk:
+- put_task_struct(child);
+-out:
+- unlock_kernel();
+- return ret;
+-}
+-
+-static void do_syscall_trace(void)
+-{
+- /* the 0x80 provides a way for the tracing parent to distinguish
+- between a syscall stop and SIGTRAP delivery */
+- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+- ? 0x80 : 0));
+-
+- /*
+- * this isn't the same as continuing with a signal, but it will do
+- * for normal use. strace only continues with a signal if the
+- * stopping signal is not SIGTRAP. -brl
+- */
+- if (current->exit_code) {
+- send_sig(current->exit_code, current, 1);
+- current->exit_code = 0;
+- }
+-}
+-
+-void do_syscall_trace_enter(struct pt_regs *regs)
+-{
+- if (test_thread_flag(TIF_SYSCALL_TRACE)
+- && (current->ptrace & PT_PTRACED))
+- do_syscall_trace();
+-
+- if (unlikely(current->audit_context))
+- audit_syscall_entry(current, AUDIT_ARCH_PPC,
+- regs->gpr[0],
+- regs->gpr[3], regs->gpr[4],
+- regs->gpr[5], regs->gpr[6]);
+-}
+-
+-void do_syscall_trace_leave(struct pt_regs *regs)
+-{
+- secure_computing(regs->gpr[0]);
+-
+- if (unlikely(current->audit_context))
+- audit_syscall_exit(current,
+- (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+- regs->result);
+-
+- if ((test_thread_flag(TIF_SYSCALL_TRACE))
+- && (current->ptrace & PT_PTRACED))
+- do_syscall_trace();
+-}
+-
+-EXPORT_SYMBOL(do_syscall_trace_enter);
+-EXPORT_SYMBOL(do_syscall_trace_leave);
+diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
+--- a/arch/ppc/kernel/setup.c
++++ b/arch/ppc/kernel/setup.c
+@@ -71,7 +71,8 @@ struct ide_machdep_calls ppc_ide_md;
+ unsigned long boot_mem_size;
+
+ unsigned long ISA_DMA_THRESHOLD;
+-unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
++unsigned int DMA_MODE_READ;
++unsigned int DMA_MODE_WRITE;
+
+ #ifdef CONFIG_PPC_MULTIPLATFORM
+ int _machine = 0;
+@@ -82,8 +83,18 @@ extern void pmac_init(unsigned long r3,
+ unsigned long r5, unsigned long r6, unsigned long r7);
+ extern void chrp_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7);
++
++dev_t boot_dev;
+ #endif /* CONFIG_PPC_MULTIPLATFORM */
+
++int have_of;
++EXPORT_SYMBOL(have_of);
++
++#ifdef __DO_IRQ_CANON
++int ppc_do_canonicalize_irqs;
++EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
++#endif
++
+ #ifdef CONFIG_MAGIC_SYSRQ
+ unsigned long SYSRQ_KEY = 0x54;
+ #endif /* CONFIG_MAGIC_SYSRQ */
+@@ -185,18 +196,18 @@ int show_cpuinfo(struct seq_file *m, voi
+ seq_printf(m, "processor\t: %d\n", i);
+ seq_printf(m, "cpu\t\t: ");
+
+- if (cur_cpu_spec[i]->pvr_mask)
+- seq_printf(m, "%s", cur_cpu_spec[i]->cpu_name);
++ if (cur_cpu_spec->pvr_mask)
++ seq_printf(m, "%s", cur_cpu_spec->cpu_name);
+ else
+ seq_printf(m, "unknown (%08x)", pvr);
+ #ifdef CONFIG_ALTIVEC
+- if (cur_cpu_spec[i]->cpu_features & CPU_FTR_ALTIVEC)
++ if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+ seq_printf(m, ", altivec supported");
+ #endif
+ seq_printf(m, "\n");
+
+ #ifdef CONFIG_TAU
+- if (cur_cpu_spec[i]->cpu_features & CPU_FTR_TAU) {
++ if (cur_cpu_spec->cpu_features & CPU_FTR_TAU) {
+ #ifdef CONFIG_TAU_AVERAGE
+ /* more straightforward, but potentially misleading */
+ seq_printf(m, "temperature \t: %u C (uncalibrated)\n",
+@@ -339,7 +350,7 @@ early_init(int r3, int r4, int r5)
+ * Assume here that all clock rates are the same in a
+ * smp system. -- Cort
+ */
+-int __openfirmware
++int
+ of_show_percpuinfo(struct seq_file *m, int i)
+ {
+ struct device_node *cpu_node;
+@@ -404,11 +415,15 @@ platform_init(unsigned long r3, unsigned
+ _machine = _MACH_prep;
+ }
+
++#ifdef CONFIG_PPC_PREP
+ /* not much more to do here, if prep */
+ if (_machine == _MACH_prep) {
+ prep_init(r3, r4, r5, r6, r7);
+ return;
+ }
++#endif
++
++ have_of = 1;
+
+ /* prom_init has already been called from __start */
+ if (boot_infos)
+@@ -479,12 +494,16 @@ platform_init(unsigned long r3, unsigned
+ #endif /* CONFIG_ADB */
+
+ switch (_machine) {
++#ifdef CONFIG_PPC_PMAC
+ case _MACH_Pmac:
+ pmac_init(r3, r4, r5, r6, r7);
+ break;
++#endif
++#ifdef CONFIG_PPC_CHRP
+ case _MACH_chrp:
+ chrp_init(r3, r4, r5, r6, r7);
+ break;
++#endif
+ }
+ }
+
+@@ -721,7 +740,7 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+
+ #ifdef CONFIG_XMON
+- xmon_map_scc();
++ xmon_init(1);
+ if (strstr(cmd_line, "xmon"))
+ xmon(NULL);
+ #endif /* CONFIG_XMON */
+@@ -745,12 +764,12 @@ void __init setup_arch(char **cmdline_p)
+ * for a possibly more accurate value.
+ */
+ if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
+- dcache_bsize = cur_cpu_spec[0]->dcache_bsize;
+- icache_bsize = cur_cpu_spec[0]->icache_bsize;
++ dcache_bsize = cur_cpu_spec->dcache_bsize;
++ icache_bsize = cur_cpu_spec->icache_bsize;
+ ucache_bsize = 0;
+ } else
+ ucache_bsize = dcache_bsize = icache_bsize
+- = cur_cpu_spec[0]->dcache_bsize;
++ = cur_cpu_spec->dcache_bsize;
+
+ /* reboot on panic */
+ panic_timeout = 180;
+diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
+deleted file mode 100644
+--- a/arch/ppc/kernel/signal.c
++++ /dev/null
+@@ -1,771 +0,0 @@
+-/*
+- * arch/ppc/kernel/signal.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Derived from "arch/i386/kernel/signal.c"
+- * Copyright (C) 1991, 1992 Linus Torvalds
+- * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
+- *
+- * 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/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/kernel.h>
+-#include <linux/signal.h>
+-#include <linux/errno.h>
+-#include <linux/wait.h>
+-#include <linux/ptrace.h>
+-#include <linux/unistd.h>
+-#include <linux/stddef.h>
+-#include <linux/elf.h>
+-#include <linux/tty.h>
+-#include <linux/binfmts.h>
+-#include <linux/suspend.h>
+-#include <asm/ucontext.h>
+-#include <asm/uaccess.h>
+-#include <asm/pgtable.h>
+-#include <asm/cacheflush.h>
+-
+-#undef DEBUG_SIG
+-
+-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+-
+-extern void sigreturn_exit(struct pt_regs *);
+-
+-#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
+-
+-int do_signal(sigset_t *oldset, struct pt_regs *regs);
+-
+-/*
+- * Atomically swap in the new signal mask, and wait for a signal.
+- */
+-int
+-sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
+- struct pt_regs *regs)
+-{
+- sigset_t saveset;
+-
+- mask &= _BLOCKABLE;
+- spin_lock_irq(¤t->sighand->siglock);
+- saveset = current->blocked;
+- siginitset(¤t->blocked, mask);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+-
+- regs->result = -EINTR;
+- regs->gpr[3] = EINTR;
+- regs->ccr |= 0x10000000;
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal(&saveset, regs))
+- sigreturn_exit(regs);
+- }
+-}
+-
+-int
+-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
+- int p6, int p7, struct pt_regs *regs)
+-{
+- sigset_t saveset, newset;
+-
+- /* XXX: Don't preclude handling different sized sigset_t's. */
+- if (sigsetsize != sizeof(sigset_t))
+- return -EINVAL;
+-
+- if (copy_from_user(&newset, unewset, sizeof(newset)))
+- return -EFAULT;
+- sigdelsetmask(&newset, ~_BLOCKABLE);
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- saveset = current->blocked;
+- current->blocked = newset;
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+-
+- regs->result = -EINTR;
+- regs->gpr[3] = EINTR;
+- regs->ccr |= 0x10000000;
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal(&saveset, regs))
+- sigreturn_exit(regs);
+- }
+-}
+-
+-
+-int
+-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
+- int r6, int r7, int r8, struct pt_regs *regs)
+-{
+- return do_sigaltstack(uss, uoss, regs->gpr[1]);
+-}
+-
+-int
+-sys_sigaction(int sig, const struct old_sigaction __user *act,
+- struct old_sigaction __user *oact)
+-{
+- struct k_sigaction new_ka, old_ka;
+- int ret;
+-
+- if (act) {
+- old_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_restorer, &act->sa_restorer))
+- return -EFAULT;
+- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+- __get_user(mask, &act->sa_mask);
+- siginitset(&new_ka.sa.sa_mask, mask);
+- }
+-
+- 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_restorer, &oact->sa_restorer))
+- return -EFAULT;
+- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * When we have signals to deliver, we set up on the
+- * user stack, going down from the original stack pointer:
+- * a sigregs struct
+- * a sigcontext struct
+- * a gap of __SIGNAL_FRAMESIZE bytes
+- *
+- * Each of these things must be a multiple of 16 bytes in size.
+- *
+- */
+-struct sigregs {
+- struct mcontext mctx; /* all the register values */
+- /* Programs using the rs6000/xcoff abi can save up to 19 gp regs
+- and 18 fp regs below sp before decrementing it. */
+- int abigap[56];
+-};
+-
+-/* We use the mc_pad field for the signal return trampoline. */
+-#define tramp mc_pad
+-
+-/*
+- * When we have rt signals to deliver, we set up on the
+- * user stack, going down from the original stack pointer:
+- * one rt_sigframe struct (siginfo + ucontext + ABI gap)
+- * a gap of __SIGNAL_FRAMESIZE+16 bytes
+- * (the +16 is to get the siginfo and ucontext in the same
+- * positions as in older kernels).
+- *
+- * Each of these things must be a multiple of 16 bytes in size.
+- *
+- */
+-struct rt_sigframe
+-{
+- struct siginfo info;
+- struct ucontext uc;
+- /* Programs using the rs6000/xcoff abi can save up to 19 gp regs
+- and 18 fp regs below sp before decrementing it. */
+- int abigap[56];
+-};
+-
+-/*
+- * Save the current user registers on the user stack.
+- * We only save the altivec/spe registers if the process has used
+- * altivec/spe instructions at some point.
+- */
+-static int
+-save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, int sigret)
+-{
+- /* save general and floating-point registers */
+- CHECK_FULL_REGS(regs);
+- preempt_disable();
+- if (regs->msr & MSR_FP)
+- giveup_fpu(current);
+-#ifdef CONFIG_ALTIVEC
+- if (current->thread.used_vr && (regs->msr & MSR_VEC))
+- giveup_altivec(current);
+-#endif /* CONFIG_ALTIVEC */
+-#ifdef CONFIG_SPE
+- if (current->thread.used_spe && (regs->msr & MSR_SPE))
+- giveup_spe(current);
+-#endif /* CONFIG_ALTIVEC */
+- preempt_enable();
+-
+- if (__copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE)
+- || __copy_to_user(&frame->mc_fregs, current->thread.fpr,
+- ELF_NFPREG * sizeof(double)))
+- return 1;
+-
+- current->thread.fpscr = 0; /* turn off all fp exceptions */
+-
+-#ifdef CONFIG_ALTIVEC
+- /* save altivec registers */
+- if (current->thread.used_vr) {
+- if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
+- ELF_NVRREG * sizeof(vector128)))
+- return 1;
+- /* set MSR_VEC in the saved MSR value to indicate that
+- frame->mc_vregs contains valid data */
+- if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR]))
+- return 1;
+- }
+- /* else assert((regs->msr & MSR_VEC) == 0) */
+-
+- /* We always copy to/from vrsave, it's 0 if we don't have or don't
+- * use altivec. Since VSCR only contains 32 bits saved in the least
+- * significant bits of a vector, we "cheat" and stuff VRSAVE in the
+- * most significant bits of that same vector. --BenH
+- */
+- if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))
+- return 1;
+-#endif /* CONFIG_ALTIVEC */
+-
+-#ifdef CONFIG_SPE
+- /* save spe registers */
+- if (current->thread.used_spe) {
+- if (__copy_to_user(&frame->mc_vregs, current->thread.evr,
+- ELF_NEVRREG * sizeof(u32)))
+- return 1;
+- /* set MSR_SPE in the saved MSR value to indicate that
+- frame->mc_vregs contains valid data */
+- if (__put_user(regs->msr | MSR_SPE, &frame->mc_gregs[PT_MSR]))
+- return 1;
+- }
+- /* else assert((regs->msr & MSR_SPE) == 0) */
+-
+- /* We always copy to/from spefscr */
+- if (__put_user(current->thread.spefscr, (u32 *)&frame->mc_vregs + ELF_NEVRREG))
+- return 1;
+-#endif /* CONFIG_SPE */
+-
+- if (sigret) {
+- /* Set up the sigreturn trampoline: li r0,sigret; sc */
+- if (__put_user(0x38000000UL + sigret, &frame->tramp[0])
+- || __put_user(0x44000002UL, &frame->tramp[1]))
+- return 1;
+- flush_icache_range((unsigned long) &frame->tramp[0],
+- (unsigned long) &frame->tramp[2]);
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * Restore the current user register values from the user stack,
+- * (except for MSR).
+- */
+-static int
+-restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig)
+-{
+- unsigned long save_r2 = 0;
+-#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
+- unsigned long msr;
+-#endif
+-
+- /* backup/restore the TLS as we don't want it to be modified */
+- if (!sig)
+- save_r2 = regs->gpr[2];
+- /* copy up to but not including MSR */
+- if (__copy_from_user(regs, &sr->mc_gregs, PT_MSR * sizeof(elf_greg_t)))
+- return 1;
+- /* copy from orig_r3 (the word after the MSR) up to the end */
+- if (__copy_from_user(®s->orig_gpr3, &sr->mc_gregs[PT_ORIG_R3],
+- GP_REGS_SIZE - PT_ORIG_R3 * sizeof(elf_greg_t)))
+- return 1;
+- if (!sig)
+- regs->gpr[2] = save_r2;
+-
+- /* force the process to reload the FP registers from
+- current->thread when it next does FP instructions */
+- regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
+- if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
+- sizeof(sr->mc_fregs)))
+- return 1;
+-
+-#ifdef CONFIG_ALTIVEC
+- /* force the process to reload the altivec registers from
+- current->thread when it next does altivec instructions */
+- regs->msr &= ~MSR_VEC;
+- if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
+- /* restore altivec registers from the stack */
+- if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
+- sizeof(sr->mc_vregs)))
+- return 1;
+- } else if (current->thread.used_vr)
+- memset(¤t->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
+-
+- /* Always get VRSAVE back */
+- if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
+- return 1;
+-#endif /* CONFIG_ALTIVEC */
+-
+-#ifdef CONFIG_SPE
+- /* force the process to reload the spe registers from
+- current->thread when it next does spe instructions */
+- regs->msr &= ~MSR_SPE;
+- if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
+- /* restore spe registers from the stack */
+- if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
+- ELF_NEVRREG * sizeof(u32)))
+- return 1;
+- } else if (current->thread.used_spe)
+- memset(¤t->thread.evr, 0, ELF_NEVRREG * sizeof(u32));
+-
+- /* Always get SPEFSCR back */
+- if (__get_user(current->thread.spefscr, (u32 *)&sr->mc_vregs + ELF_NEVRREG))
+- return 1;
+-#endif /* CONFIG_SPE */
+-
+-#ifndef CONFIG_SMP
+- preempt_disable();
+- if (last_task_used_math == current)
+- last_task_used_math = NULL;
+- if (last_task_used_altivec == current)
+- last_task_used_altivec = NULL;
+- if (last_task_used_spe == current)
+- last_task_used_spe = NULL;
+- preempt_enable();
+-#endif
+- return 0;
+-}
+-
+-/*
+- * Restore the user process's signal mask
+- */
+-static void
+-restore_sigmask(sigset_t *set)
+-{
+- sigdelsetmask(set, ~_BLOCKABLE);
+- spin_lock_irq(¤t->sighand->siglock);
+- current->blocked = *set;
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+-}
+-
+-/*
+- * Set up a signal frame for a "real-time" signal handler
+- * (one which gets siginfo).
+- */
+-static void
+-handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
+- siginfo_t *info, sigset_t *oldset, struct pt_regs * regs,
+- unsigned long newsp)
+-{
+- struct rt_sigframe __user *rt_sf;
+- struct mcontext __user *frame;
+- unsigned long origsp = newsp;
+-
+- /* Set up Signal Frame */
+- /* Put a Real Time Context onto stack */
+- newsp -= sizeof(*rt_sf);
+- rt_sf = (struct rt_sigframe __user *) newsp;
+-
+- /* create a stack frame for the caller of the handler */
+- newsp -= __SIGNAL_FRAMESIZE + 16;
+-
+- if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+- goto badframe;
+-
+- /* Put the siginfo & fill in most of the ucontext */
+- if (copy_siginfo_to_user(&rt_sf->info, info)
+- || __put_user(0, &rt_sf->uc.uc_flags)
+- || __put_user(0, &rt_sf->uc.uc_link)
+- || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
+- || __put_user(sas_ss_flags(regs->gpr[1]),
+- &rt_sf->uc.uc_stack.ss_flags)
+- || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
+- || __put_user(&rt_sf->uc.uc_mcontext, &rt_sf->uc.uc_regs)
+- || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset)))
+- goto badframe;
+-
+- /* Save user registers on the stack */
+- frame = &rt_sf->uc.uc_mcontext;
+- if (save_user_regs(regs, frame, __NR_rt_sigreturn))
+- goto badframe;
+-
+- if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+- goto badframe;
+- regs->gpr[1] = newsp;
+- regs->gpr[3] = sig;
+- regs->gpr[4] = (unsigned long) &rt_sf->info;
+- regs->gpr[5] = (unsigned long) &rt_sf->uc;
+- regs->gpr[6] = (unsigned long) rt_sf;
+- regs->nip = (unsigned long) ka->sa.sa_handler;
+- regs->link = (unsigned long) frame->tramp;
+- regs->trap = 0;
+-
+- return;
+-
+-badframe:
+-#ifdef DEBUG_SIG
+- printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
+- regs, frame, newsp);
+-#endif
+- force_sigsegv(sig, current);
+-}
+-
+-static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
+-{
+- sigset_t set;
+- struct mcontext __user *mcp;
+-
+- if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(set))
+- || __get_user(mcp, &ucp->uc_regs))
+- return -EFAULT;
+- restore_sigmask(&set);
+- if (restore_user_regs(regs, mcp, sig))
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-int sys_swapcontext(struct ucontext __user *old_ctx,
+- struct ucontext __user *new_ctx,
+- int ctx_size, int r6, int r7, int r8, struct pt_regs *regs)
+-{
+- unsigned char tmp;
+-
+- /* Context size is for future use. Right now, we only make sure
+- * we are passed something we understand
+- */
+- if (ctx_size < sizeof(struct ucontext))
+- return -EINVAL;
+-
+- if (old_ctx != NULL) {
+- if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
+- || save_user_regs(regs, &old_ctx->uc_mcontext, 0)
+- || __copy_to_user(&old_ctx->uc_sigmask,
+- ¤t->blocked, sizeof(sigset_t))
+- || __put_user(&old_ctx->uc_mcontext, &old_ctx->uc_regs))
+- return -EFAULT;
+- }
+- if (new_ctx == NULL)
+- return 0;
+- if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
+- || __get_user(tmp, (u8 __user *) new_ctx)
+- || __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
+- return -EFAULT;
+-
+- /*
+- * If we get a fault copying the context into the kernel's
+- * image of the user's registers, we can't just return -EFAULT
+- * because the user's registers will be corrupted. For instance
+- * the NIP value may have been updated but not some of the
+- * other registers. Given that we have done the access_ok
+- * and successfully read the first and last bytes of the region
+- * above, this should only happen in an out-of-memory situation
+- * or if another thread unmaps the region containing the context.
+- * We kill the task with a SIGSEGV in this situation.
+- */
+- if (do_setcontext(new_ctx, regs, 0))
+- do_exit(SIGSEGV);
+- sigreturn_exit(regs);
+- /* doesn't actually return back to here */
+- return 0;
+-}
+-
+-int sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
+- struct pt_regs *regs)
+-{
+- struct rt_sigframe __user *rt_sf;
+-
+- /* Always make any pending restarted system calls return -EINTR */
+- current_thread_info()->restart_block.fn = do_no_restart_syscall;
+-
+- rt_sf = (struct rt_sigframe __user *)
+- (regs->gpr[1] + __SIGNAL_FRAMESIZE + 16);
+- if (!access_ok(VERIFY_READ, rt_sf, sizeof(struct rt_sigframe)))
+- goto bad;
+- if (do_setcontext(&rt_sf->uc, regs, 1))
+- goto bad;
+-
+- /*
+- * It's not clear whether or why it is desirable to save the
+- * sigaltstack setting on signal delivery and restore it on
+- * signal return. But other architectures do this and we have
+- * always done it up until now so it is probably better not to
+- * change it. -- paulus
+- */
+- do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]);
+-
+- sigreturn_exit(regs); /* doesn't return here */
+- return 0;
+-
+- bad:
+- force_sig(SIGSEGV, current);
+- return 0;
+-}
+-
+-int sys_debug_setcontext(struct ucontext __user *ctx,
+- int ndbg, struct sig_dbg_op __user *dbg,
+- int r6, int r7, int r8,
+- struct pt_regs *regs)
+-{
+- struct sig_dbg_op op;
+- int i;
+- unsigned long new_msr = regs->msr;
+-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+- unsigned long new_dbcr0 = current->thread.dbcr0;
+-#endif
+-
+- for (i=0; i<ndbg; i++) {
+- if (__copy_from_user(&op, dbg, sizeof(op)))
+- return -EFAULT;
+- switch (op.dbg_type) {
+- case SIG_DBG_SINGLE_STEPPING:
+-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+- if (op.dbg_value) {
+- new_msr |= MSR_DE;
+- new_dbcr0 |= (DBCR0_IDM | DBCR0_IC);
+- } else {
+- new_msr &= ~MSR_DE;
+- new_dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
+- }
+-#else
+- if (op.dbg_value)
+- new_msr |= MSR_SE;
+- else
+- new_msr &= ~MSR_SE;
+-#endif
+- break;
+- case SIG_DBG_BRANCH_TRACING:
+-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+- return -EINVAL;
+-#else
+- if (op.dbg_value)
+- new_msr |= MSR_BE;
+- else
+- new_msr &= ~MSR_BE;
+-#endif
+- break;
+-
+- default:
+- return -EINVAL;
+- }
+- }
+-
+- /* We wait until here to actually install the values in the
+- registers so if we fail in the above loop, it will not
+- affect the contents of these registers. After this point,
+- failure is a problem, anyway, and it's very unlikely unless
+- the user is really doing something wrong. */
+- regs->msr = new_msr;
+-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+- current->thread.dbcr0 = new_dbcr0;
+-#endif
+-
+- /*
+- * If we get a fault copying the context into the kernel's
+- * image of the user's registers, we can't just return -EFAULT
+- * because the user's registers will be corrupted. For instance
+- * the NIP value may have been updated but not some of the
+- * other registers. Given that we have done the access_ok
+- * and successfully read the first and last bytes of the region
+- * above, this should only happen in an out-of-memory situation
+- * or if another thread unmaps the region containing the context.
+- * We kill the task with a SIGSEGV in this situation.
+- */
+- if (do_setcontext(ctx, regs, 1)) {
+- force_sig(SIGSEGV, current);
+- goto out;
+- }
+-
+- /*
+- * It's not clear whether or why it is desirable to save the
+- * sigaltstack setting on signal delivery and restore it on
+- * signal return. But other architectures do this and we have
+- * always done it up until now so it is probably better not to
+- * change it. -- paulus
+- */
+- do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]);
+-
+- sigreturn_exit(regs);
+- /* doesn't actually return back to here */
+-
+- out:
+- return 0;
+-}
+-
+-/*
+- * OK, we're invoking a handler
+- */
+-static void
+-handle_signal(unsigned long sig, struct k_sigaction *ka,
+- siginfo_t *info, sigset_t *oldset, struct pt_regs * regs,
+- unsigned long newsp)
+-{
+- struct sigcontext __user *sc;
+- struct sigregs __user *frame;
+- unsigned long origsp = newsp;
+-
+- /* Set up Signal Frame */
+- newsp -= sizeof(struct sigregs);
+- frame = (struct sigregs __user *) newsp;
+-
+- /* Put a sigcontext on the stack */
+- newsp -= sizeof(*sc);
+- sc = (struct sigcontext __user *) newsp;
+-
+- /* create a stack frame for the caller of the handler */
+- newsp -= __SIGNAL_FRAMESIZE;
+-
+- if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+- goto badframe;
+-
+-#if _NSIG != 64
+-#error "Please adjust handle_signal()"
+-#endif
+- if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
+- || __put_user(oldset->sig[0], &sc->oldmask)
+- || __put_user(oldset->sig[1], &sc->_unused[3])
+- || __put_user((struct pt_regs __user *)frame, &sc->regs)
+- || __put_user(sig, &sc->signal))
+- goto badframe;
+-
+- if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
+- goto badframe;
+-
+- if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+- goto badframe;
+- regs->gpr[1] = newsp;
+- regs->gpr[3] = sig;
+- regs->gpr[4] = (unsigned long) sc;
+- regs->nip = (unsigned long) ka->sa.sa_handler;
+- regs->link = (unsigned long) frame->mctx.tramp;
+- regs->trap = 0;
+-
+- return;
+-
+-badframe:
+-#ifdef DEBUG_SIG
+- printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
+- regs, frame, newsp);
+-#endif
+- force_sigsegv(sig, current);
+-}
+-
+-/*
+- * Do a signal return; undo the signal stack.
+- */
+-int sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
+- struct pt_regs *regs)
+-{
+- struct sigcontext __user *sc;
+- struct sigcontext sigctx;
+- struct mcontext __user *sr;
+- sigset_t set;
+-
+- /* Always make any pending restarted system calls return -EINTR */
+- current_thread_info()->restart_block.fn = do_no_restart_syscall;
+-
+- sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+- if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
+- goto badframe;
+-
+- set.sig[0] = sigctx.oldmask;
+- set.sig[1] = sigctx._unused[3];
+- restore_sigmask(&set);
+-
+- sr = (struct mcontext __user *) sigctx.regs;
+- if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
+- || restore_user_regs(regs, sr, 1))
+- goto badframe;
+-
+- sigreturn_exit(regs); /* doesn't return */
+- return 0;
+-
+-badframe:
+- force_sig(SIGSEGV, current);
+- return 0;
+-}
+-
+-/*
+- * Note that 'init' is a special process: it doesn't get signals it doesn't
+- * want to handle. Thus you cannot kill init even with a SIGKILL even by
+- * mistake.
+- */
+-int do_signal(sigset_t *oldset, struct pt_regs *regs)
+-{
+- siginfo_t info;
+- struct k_sigaction ka;
+- unsigned long frame, newsp;
+- int signr, ret;
+-
+- if (try_to_freeze()) {
+- signr = 0;
+- if (!signal_pending(current))
+- goto no_signal;
+- }
+-
+- if (!oldset)
+- oldset = ¤t->blocked;
+-
+- newsp = frame = 0;
+-
+- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+- no_signal:
+- if (TRAP(regs) == 0x0C00 /* System Call! */
+- && regs->ccr & 0x10000000 /* error signalled */
+- && ((ret = regs->gpr[3]) == ERESTARTSYS
+- || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
+- || ret == ERESTART_RESTARTBLOCK)) {
+-
+- if (signr > 0
+- && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
+- || (ret == ERESTARTSYS
+- && !(ka.sa.sa_flags & SA_RESTART)))) {
+- /* make the system call return an EINTR error */
+- regs->result = -EINTR;
+- regs->gpr[3] = EINTR;
+- /* note that the cr0.SO bit is already set */
+- } else {
+- regs->nip -= 4; /* Back up & retry system call */
+- regs->result = 0;
+- regs->trap = 0;
+- if (ret == ERESTART_RESTARTBLOCK)
+- regs->gpr[0] = __NR_restart_syscall;
+- else
+- regs->gpr[3] = regs->orig_gpr3;
+- }
+- }
+-
+- if (signr == 0)
+- return 0; /* no signals delivered */
+-
+- if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+- && !on_sig_stack(regs->gpr[1]))
+- newsp = current->sas_ss_sp + current->sas_ss_size;
+- else
+- newsp = regs->gpr[1];
+- newsp &= ~0xfUL;
+-
+- /* Whee! Actually deliver the signal. */
+- if (ka.sa.sa_flags & SA_SIGINFO)
+- handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
+- else
+- handle_signal(signr, &ka, &info, oldset, regs, newsp);
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask);
+- if (!(ka.sa.sa_flags & SA_NODEFER))
+- sigaddset(¤t->blocked, signr);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+-
+- return 1;
+-}
+-
+diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
+--- a/arch/ppc/kernel/smp.c
++++ b/arch/ppc/kernel/smp.c
+@@ -34,11 +34,11 @@
+ #include <asm/thread_info.h>
+ #include <asm/tlbflush.h>
+ #include <asm/xmon.h>
++#include <asm/machdep.h>
+
+ volatile int smp_commenced;
+ int smp_tb_synchronized;
+ struct cpuinfo_PPC cpu_data[NR_CPUS];
+-struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
+ atomic_t ipi_recv;
+ atomic_t ipi_sent;
+ cpumask_t cpu_online_map;
+@@ -51,7 +51,7 @@ EXPORT_SYMBOL(cpu_online_map);
+ EXPORT_SYMBOL(cpu_possible_map);
+
+ /* SMP operations for this machine */
+-static struct smp_ops_t *smp_ops;
++struct smp_ops_t *smp_ops;
+
+ /* all cpu mappings are 1-1 -- Cort */
+ volatile unsigned long cpu_callin_map[NR_CPUS];
+@@ -74,11 +74,11 @@ extern void __save_cpu_setup(void);
+ #define PPC_MSG_XMON_BREAK 3
+
+ static inline void
+-smp_message_pass(int target, int msg, unsigned long data, int wait)
++smp_message_pass(int target, int msg)
+ {
+- if (smp_ops){
++ if (smp_ops) {
+ atomic_inc(&ipi_sent);
+- smp_ops->message_pass(target,msg,data,wait);
++ smp_ops->message_pass(target, msg);
+ }
+ }
+
+@@ -119,7 +119,7 @@ void smp_message_recv(int msg, struct pt
+ void smp_send_tlb_invalidate(int cpu)
+ {
+ if ( PVR_VER(mfspr(SPRN_PVR)) == 8 )
+- smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB, 0, 0);
++ smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB);
+ }
+
+ void smp_send_reschedule(int cpu)
+@@ -135,13 +135,13 @@ void smp_send_reschedule(int cpu)
+ */
+ /* This is only used if `cpu' is running an idle task,
+ so it will reschedule itself anyway... */
+- smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0);
++ smp_message_pass(cpu, PPC_MSG_RESCHEDULE);
+ }
+
+ #ifdef CONFIG_XMON
+ void smp_send_xmon_break(int cpu)
+ {
+- smp_message_pass(cpu, PPC_MSG_XMON_BREAK, 0, 0);
++ smp_message_pass(cpu, PPC_MSG_XMON_BREAK);
+ }
+ #endif /* CONFIG_XMON */
+
+@@ -224,7 +224,7 @@ static int __smp_call_function(void (*fu
+ spin_lock(&call_lock);
+ call_data = &data;
+ /* Send a message to all other CPUs and wait for them to respond */
+- smp_message_pass(target, PPC_MSG_CALL_FUNCTION, 0, 0);
++ smp_message_pass(target, PPC_MSG_CALL_FUNCTION);
+
+ /* Wait for response */
+ timeout = 1000000;
+@@ -294,7 +294,6 @@ void __init smp_prepare_cpus(unsigned in
+ smp_store_cpu_info(smp_processor_id());
+ cpu_callin_map[smp_processor_id()] = 1;
+
+- smp_ops = ppc_md.smp_ops;
+ if (smp_ops == NULL) {
+ printk("SMP not supported on this machine.\n");
+ return;
+@@ -308,9 +307,6 @@ void __init smp_prepare_cpus(unsigned in
+ /* Backup CPU 0 state */
+ __save_cpu_setup();
+
+- if (smp_ops->space_timers)
+- smp_ops->space_timers(num_cpus);
+-
+ for_each_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
+deleted file mode 100644
+--- a/arch/ppc/kernel/syscalls.c
++++ /dev/null
+@@ -1,268 +0,0 @@
+-/*
+- * arch/ppc/kernel/sys_ppc.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Derived from "arch/i386/kernel/sys_i386.c"
+- * Adapted from the i386 version by Gary Thomas
+- * Modified by Cort Dougan (cort at cs.nmt.edu)
+- * and Paul Mackerras (paulus at cs.anu.edu.au).
+- *
+- * This file contains various random system calls that
+- * have a non-standard calling sequence on the Linux/PPC
+- * platform.
+- *
+- * 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/errno.h>
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/sem.h>
+-#include <linux/msg.h>
+-#include <linux/shm.h>
+-#include <linux/stat.h>
+-#include <linux/syscalls.h>
+-#include <linux/mman.h>
+-#include <linux/sys.h>
+-#include <linux/ipc.h>
+-#include <linux/utsname.h>
+-#include <linux/file.h>
+-#include <linux/unistd.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/ipc.h>
+-#include <asm/semaphore.h>
+-
+-
+-/*
+- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+- *
+- * This is really horribly ugly.
+- */
+-int
+-sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth)
+-{
+- int version, ret;
+-
+- version = call >> 16; /* hack for backward compatibility */
+- call &= 0xffff;
+-
+- ret = -ENOSYS;
+- switch (call) {
+- case SEMOP:
+- ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+- second, NULL);
+- break;
+- case SEMTIMEDOP:
+- ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+- second, (const struct timespec __user *) fifth);
+- break;
+- case SEMGET:
+- ret = sys_semget (first, second, third);
+- break;
+- case SEMCTL: {
+- union semun fourth;
+-
+- if (!ptr)
+- break;
+- if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
+- || (ret = get_user(fourth.__pad, (void __user *__user *)ptr)))
+- break;
+- ret = sys_semctl (first, second, third, fourth);
+- break;
+- }
+- case MSGSND:
+- ret = sys_msgsnd (first, (struct msgbuf __user *) ptr, second, third);
+- break;
+- case MSGRCV:
+- switch (version) {
+- case 0: {
+- struct ipc_kludge tmp;
+-
+- if (!ptr)
+- break;
+- if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
+- || (ret = copy_from_user(&tmp,
+- (struct ipc_kludge __user *) ptr,
+- sizeof (tmp)) ? -EFAULT : 0))
+- break;
+- ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
+- third);
+- break;
+- }
+- default:
+- ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
+- second, fifth, third);
+- break;
+- }
+- break;
+- case MSGGET:
+- ret = sys_msgget ((key_t) first, second);
+- break;
+- case MSGCTL:
+- ret = sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
+- break;
+- case SHMAT: {
+- ulong raddr;
+-
+- if ((ret = access_ok(VERIFY_WRITE, (ulong __user *) third,
+- sizeof(ulong)) ? 0 : -EFAULT))
+- break;
+- ret = do_shmat (first, (char __user *) ptr, second, &raddr);
+- if (ret)
+- break;
+- ret = put_user (raddr, (ulong __user *) third);
+- break;
+- }
+- case SHMDT:
+- ret = sys_shmdt ((char __user *)ptr);
+- break;
+- case SHMGET:
+- ret = sys_shmget (first, second, third);
+- break;
+- case SHMCTL:
+- ret = sys_shmctl (first, second, (struct shmid_ds __user *) ptr);
+- break;
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * sys_pipe() is the normal C calling standard for creating
+- * a pipe. It's not the way unix traditionally does this, though.
+- */
+-int sys_pipe(int __user *fildes)
+-{
+- int fd[2];
+- int error;
+-
+- error = do_pipe(fd);
+- if (!error) {
+- if (copy_to_user(fildes, fd, 2*sizeof(int)))
+- error = -EFAULT;
+- }
+- return error;
+-}
+-
+-static inline unsigned long
+-do_mmap2(unsigned long addr, size_t len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, unsigned long pgoff)
+-{
+- struct file * file = NULL;
+- int ret = -EBADF;
+-
+- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+- if (!(flags & MAP_ANONYMOUS)) {
+- if (!(file = fget(fd)))
+- goto out;
+- }
+-
+- down_write(¤t->mm->mmap_sem);
+- ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+- up_write(¤t->mm->mmap_sem);
+- if (file)
+- fput(file);
+-out:
+- return ret;
+-}
+-
+-unsigned long sys_mmap2(unsigned long addr, size_t len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, unsigned long pgoff)
+-{
+- return do_mmap2(addr, len, prot, flags, fd, pgoff);
+-}
+-
+-unsigned long sys_mmap(unsigned long addr, size_t len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, off_t offset)
+-{
+- int err = -EINVAL;
+-
+- if (offset & ~PAGE_MASK)
+- goto out;
+-
+- err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+-out:
+- return err;
+-}
+-
+-/*
+- * Due to some executables calling the wrong select we sometimes
+- * get wrong args. This determines how the args are being passed
+- * (a single ptr to them all args passed) then calls
+- * sys_select() with the appropriate args. -- Cort
+- */
+-int
+-ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
+-{
+- if ( (unsigned long)n >= 4096 )
+- {
+- unsigned long __user *buffer = (unsigned long __user *)n;
+- if (!access_ok(VERIFY_READ, buffer, 5*sizeof(unsigned long))
+- || __get_user(n, buffer)
+- || __get_user(inp, ((fd_set __user * __user *)(buffer+1)))
+- || __get_user(outp, ((fd_set __user * __user *)(buffer+2)))
+- || __get_user(exp, ((fd_set __user * __user *)(buffer+3)))
+- || __get_user(tvp, ((struct timeval __user * __user *)(buffer+4))))
+- return -EFAULT;
+- }
+- return sys_select(n, inp, outp, exp, tvp);
+-}
+-
+-int sys_uname(struct old_utsname __user * name)
+-{
+- int err = -EFAULT;
+-
+- down_read(&uts_sem);
+- if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+- err = 0;
+- up_read(&uts_sem);
+- return err;
+-}
+-
+-int sys_olduname(struct oldold_utsname __user * name)
+-{
+- int error;
+-
+- if (!name)
+- return -EFAULT;
+- if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+- return -EFAULT;
+-
+- down_read(&uts_sem);
+- error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+- error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
+- error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+- error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
+- error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+- error -= __put_user(0,name->release+__OLD_UTS_LEN);
+- error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+- error -= __put_user(0,name->version+__OLD_UTS_LEN);
+- error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+- error = __put_user(0,name->machine+__OLD_UTS_LEN);
+- up_read(&uts_sem);
+-
+- error = error ? -EFAULT : 0;
+- return error;
+-}
+-
+-/*
+- * We put the arguments in a different order so we only use 6
+- * registers for arguments, rather than 7 as sys_fadvise64_64 needs
+- * (because `offset' goes in r5/r6).
+- */
+-long ppc_fadvise64_64(int fd, int advice, loff_t offset, loff_t len)
+-{
+- return sys_fadvise64_64(fd, offset, len, advice);
+-}
+diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
+--- 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;
+@@ -121,6 +116,15 @@ unsigned long profile_pc(struct pt_regs
+ EXPORT_SYMBOL(profile_pc);
+ #endif
+
++void wakeup_decrementer(void)
++{
++ set_dec(tb_ticks_per_jiffy);
++ /* No currently-supported powerbook has a 601,
++ * so use get_tbl, not native
++ */
++ last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
++}
++
+ /*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
+--- a/arch/ppc/kernel/traps.c
++++ b/arch/ppc/kernel/traps.c
+@@ -41,9 +41,14 @@
+ #ifdef CONFIG_PMAC_BACKLIGHT
+ #include <asm/backlight.h>
+ #endif
+-#include <asm/perfmon.h>
++#include <asm/pmc.h>
+
+ #ifdef CONFIG_XMON
++extern int xmon_bpt(struct pt_regs *regs);
++extern int xmon_sstep(struct pt_regs *regs);
++extern int xmon_iabr_match(struct pt_regs *regs);
++extern int xmon_dabr_match(struct pt_regs *regs);
++
+ void (*debugger)(struct pt_regs *regs) = xmon;
+ int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt;
+ int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep;
+@@ -74,7 +79,7 @@ void (*debugger_fault_handler)(struct pt
+
+ DEFINE_SPINLOCK(die_lock);
+
+-void die(const char * str, struct pt_regs * fp, long err)
++int die(const char * str, struct pt_regs * fp, long err)
+ {
+ static int die_counter;
+ int nl = 0;
+@@ -232,7 +237,7 @@ platform_machine_check(struct pt_regs *r
+ {
+ }
+
+-void MachineCheckException(struct pt_regs *regs)
++void machine_check_exception(struct pt_regs *regs)
+ {
+ unsigned long reason = get_mc_reason(regs);
+
+@@ -393,14 +398,14 @@ void SMIException(struct pt_regs *regs)
+ #endif
+ }
+
+-void UnknownException(struct pt_regs *regs)
++void unknown_exception(struct pt_regs *regs)
+ {
+ printk("Bad trap at PC: %lx, MSR: %lx, vector=%lx %s\n",
+ regs->nip, regs->msr, regs->trap, print_tainted());
+ _exception(SIGTRAP, regs, 0, 0);
+ }
+
+-void InstructionBreakpoint(struct pt_regs *regs)
++void instruction_breakpoint_exception(struct pt_regs *regs)
+ {
+ if (debugger_iabr_match(regs))
+ return;
+@@ -575,7 +580,7 @@ extern struct bug_entry __start___bug_ta
+ #define module_find_bug(x) NULL
+ #endif
+
+-static struct bug_entry *find_bug(unsigned long bugaddr)
++struct bug_entry *find_bug(unsigned long bugaddr)
+ {
+ struct bug_entry *bug;
+
+@@ -622,7 +627,7 @@ int check_bug_trap(struct pt_regs *regs)
+ return 0;
+ }
+
+-void ProgramCheckException(struct pt_regs *regs)
++void program_check_exception(struct pt_regs *regs)
+ {
+ unsigned int reason = get_reason(regs);
+ extern int do_mathemu(struct pt_regs *regs);
+@@ -654,7 +659,7 @@ void ProgramCheckException(struct pt_reg
+ giveup_fpu(current);
+ preempt_enable();
+
+- fpscr = current->thread.fpscr;
++ fpscr = current->thread.fpscr.val;
+ fpscr &= fpscr << 22; /* mask summary bits with enables */
+ if (fpscr & FPSCR_VX)
+ code = FPE_FLTINV;
+@@ -701,7 +706,7 @@ void ProgramCheckException(struct pt_reg
+ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+ }
+
+-void SingleStepException(struct pt_regs *regs)
++void single_step_exception(struct pt_regs *regs)
+ {
+ regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */
+ if (debugger_sstep(regs))
+@@ -709,7 +714,7 @@ void SingleStepException(struct pt_regs
+ _exception(SIGTRAP, regs, TRAP_TRACE, 0);
+ }
+
+-void AlignmentException(struct pt_regs *regs)
++void alignment_exception(struct pt_regs *regs)
+ {
+ int fixed;
+
+@@ -814,7 +819,18 @@ void TAUException(struct pt_regs *regs)
+ }
+ #endif /* CONFIG_INT_TAU */
+
+-void AltivecUnavailException(struct pt_regs *regs)
++/*
++ * FP unavailable trap from kernel - print a message, but let
++ * the task use FP in the kernel until it returns to user mode.
++ */
++void kernel_fp_unavailable_exception(struct pt_regs *regs)
++{
++ regs->msr |= MSR_FP;
++ printk(KERN_ERR "floating point used in kernel (task=%p, pc=%lx)\n",
++ current, regs->nip);
++}
++
++void altivec_unavailable_exception(struct pt_regs *regs)
+ {
+ static int kernel_altivec_count;
+
+@@ -835,7 +851,7 @@ void AltivecUnavailException(struct pt_r
+ }
+
+ #ifdef CONFIG_ALTIVEC
+-void AltivecAssistException(struct pt_regs *regs)
++void altivec_assist_exception(struct pt_regs *regs)
+ {
+ int err;
+
+@@ -872,7 +888,7 @@ void AltivecAssistException(struct pt_re
+ #endif /* CONFIG_ALTIVEC */
+
+ #ifdef CONFIG_E500
+-void PerformanceMonitorException(struct pt_regs *regs)
++void performance_monitor_exception(struct pt_regs *regs)
+ {
+ perf_irq(regs);
+ }
+diff --git a/arch/ppc/kernel/vecemu.c b/arch/ppc/kernel/vecemu.c
+deleted file mode 100644
+--- a/arch/ppc/kernel/vecemu.c
++++ /dev/null
+@@ -1,345 +0,0 @@
+-/*
+- * Routines to emulate some Altivec/VMX instructions, specifically
+- * those that can trap when given denormalized operands in Java mode.
+- */
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <asm/ptrace.h>
+-#include <asm/processor.h>
+-#include <asm/uaccess.h>
+-
+-/* Functions in vector.S */
+-extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
+-extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b);
+-extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+-extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+-extern void vrefp(vector128 *dst, vector128 *src);
+-extern void vrsqrtefp(vector128 *dst, vector128 *src);
+-extern void vexptep(vector128 *dst, vector128 *src);
+-
+-static unsigned int exp2s[8] = {
+- 0x800000,
+- 0x8b95c2,
+- 0x9837f0,
+- 0xa5fed7,
+- 0xb504f3,
+- 0xc5672a,
+- 0xd744fd,
+- 0xeac0c7
+-};
+-
+-/*
+- * Computes an estimate of 2^x. The `s' argument is the 32-bit
+- * single-precision floating-point representation of x.
+- */
+-static unsigned int eexp2(unsigned int s)
+-{
+- int exp, pwr;
+- unsigned int mant, frac;
+-
+- /* extract exponent field from input */
+- exp = ((s >> 23) & 0xff) - 127;
+- if (exp > 7) {
+- /* check for NaN input */
+- if (exp == 128 && (s & 0x7fffff) != 0)
+- return s | 0x400000; /* return QNaN */
+- /* 2^-big = 0, 2^+big = +Inf */
+- return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */
+- }
+- if (exp < -23)
+- return 0x3f800000; /* 1.0 */
+-
+- /* convert to fixed point integer in 9.23 representation */
+- pwr = (s & 0x7fffff) | 0x800000;
+- if (exp > 0)
+- pwr <<= exp;
+- else
+- pwr >>= -exp;
+- if (s & 0x80000000)
+- pwr = -pwr;
+-
+- /* extract integer part, which becomes exponent part of result */
+- exp = (pwr >> 23) + 126;
+- if (exp >= 254)
+- return 0x7f800000;
+- if (exp < -23)
+- return 0;
+-
+- /* table lookup on top 3 bits of fraction to get mantissa */
+- mant = exp2s[(pwr >> 20) & 7];
+-
+- /* linear interpolation using remaining 20 bits of fraction */
+- asm("mulhwu %0,%1,%2" : "=r" (frac)
+- : "r" (pwr << 12), "r" (0x172b83ff));
+- asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant));
+- mant += frac;
+-
+- if (exp >= 0)
+- return mant + (exp << 23);
+-
+- /* denormalized result */
+- exp = -exp;
+- mant += 1 << (exp - 1);
+- return mant >> exp;
+-}
+-
+-/*
+- * Computes an estimate of log_2(x). The `s' argument is the 32-bit
+- * single-precision floating-point representation of x.
+- */
+-static unsigned int elog2(unsigned int s)
+-{
+- int exp, mant, lz, frac;
+-
+- exp = s & 0x7f800000;
+- mant = s & 0x7fffff;
+- if (exp == 0x7f800000) { /* Inf or NaN */
+- if (mant != 0)
+- s |= 0x400000; /* turn NaN into QNaN */
+- return s;
+- }
+- if ((exp | mant) == 0) /* +0 or -0 */
+- return 0xff800000; /* return -Inf */
+-
+- if (exp == 0) {
+- /* denormalized */
+- asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant));
+- mant <<= lz - 8;
+- exp = (-118 - lz) << 23;
+- } else {
+- mant |= 0x800000;
+- exp -= 127 << 23;
+- }
+-
+- if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */
+- exp |= 0x400000; /* 0.5 * 2^23 */
+- asm("mulhwu %0,%1,%2" : "=r" (mant)
+- : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */
+- }
+- if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */
+- exp |= 0x200000; /* 0.25 * 2^23 */
+- asm("mulhwu %0,%1,%2" : "=r" (mant)
+- : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */
+- }
+- if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */
+- exp |= 0x100000; /* 0.125 * 2^23 */
+- asm("mulhwu %0,%1,%2" : "=r" (mant)
+- : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */
+- }
+- if (mant > 0x800000) { /* 1.0 * 2^23 */
+- /* calculate (mant - 1) * 1.381097463 */
+- /* 1.381097463 == 0.125 / (2^0.125 - 1) */
+- asm("mulhwu %0,%1,%2" : "=r" (frac)
+- : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a));
+- exp += frac;
+- }
+- s = exp & 0x80000000;
+- if (exp != 0) {
+- if (s)
+- exp = -exp;
+- asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp));
+- lz = 8 - lz;
+- if (lz > 0)
+- exp >>= lz;
+- else if (lz < 0)
+- exp <<= -lz;
+- s += ((lz + 126) << 23) + exp;
+- }
+- return s;
+-}
+-
+-#define VSCR_SAT 1
+-
+-static int ctsxs(unsigned int x, int scale, unsigned int *vscrp)
+-{
+- int exp, mant;
+-
+- exp = (x >> 23) & 0xff;
+- mant = x & 0x7fffff;
+- if (exp == 255 && mant != 0)
+- return 0; /* NaN -> 0 */
+- exp = exp - 127 + scale;
+- if (exp < 0)
+- return 0; /* round towards zero */
+- if (exp >= 31) {
+- /* saturate, unless the result would be -2^31 */
+- if (x + (scale << 23) != 0xcf000000)
+- *vscrp |= VSCR_SAT;
+- return (x & 0x80000000)? 0x80000000: 0x7fffffff;
+- }
+- mant |= 0x800000;
+- mant = (mant << 7) >> (30 - exp);
+- return (x & 0x80000000)? -mant: mant;
+-}
+-
+-static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp)
+-{
+- int exp;
+- unsigned int mant;
+-
+- exp = (x >> 23) & 0xff;
+- mant = x & 0x7fffff;
+- if (exp == 255 && mant != 0)
+- return 0; /* NaN -> 0 */
+- exp = exp - 127 + scale;
+- if (exp < 0)
+- return 0; /* round towards zero */
+- if (x & 0x80000000) {
+- /* negative => saturate to 0 */
+- *vscrp |= VSCR_SAT;
+- return 0;
+- }
+- if (exp >= 32) {
+- /* saturate */
+- *vscrp |= VSCR_SAT;
+- return 0xffffffff;
+- }
+- mant |= 0x800000;
+- mant = (mant << 8) >> (31 - exp);
+- return mant;
+-}
+-
+-/* Round to floating integer, towards 0 */
+-static unsigned int rfiz(unsigned int x)
+-{
+- int exp;
+-
+- exp = ((x >> 23) & 0xff) - 127;
+- if (exp == 128 && (x & 0x7fffff) != 0)
+- return x | 0x400000; /* NaN -> make it a QNaN */
+- if (exp >= 23)
+- return x; /* it's an integer already (or Inf) */
+- if (exp < 0)
+- return x & 0x80000000; /* |x| < 1.0 rounds to 0 */
+- return x & ~(0x7fffff >> exp);
+-}
+-
+-/* Round to floating integer, towards +/- Inf */
+-static unsigned int rfii(unsigned int x)
+-{
+- int exp, mask;
+-
+- exp = ((x >> 23) & 0xff) - 127;
+- if (exp == 128 && (x & 0x7fffff) != 0)
+- return x | 0x400000; /* NaN -> make it a QNaN */
+- if (exp >= 23)
+- return x; /* it's an integer already (or Inf) */
+- if ((x & 0x7fffffff) == 0)
+- return x; /* +/-0 -> +/-0 */
+- if (exp < 0)
+- /* 0 < |x| < 1.0 rounds to +/- 1.0 */
+- return (x & 0x80000000) | 0x3f800000;
+- mask = 0x7fffff >> exp;
+- /* mantissa overflows into exponent - that's OK,
+- it can't overflow into the sign bit */
+- return (x + mask) & ~mask;
+-}
+-
+-/* Round to floating integer, to nearest */
+-static unsigned int rfin(unsigned int x)
+-{
+- int exp, half;
+-
+- exp = ((x >> 23) & 0xff) - 127;
+- if (exp == 128 && (x & 0x7fffff) != 0)
+- return x | 0x400000; /* NaN -> make it a QNaN */
+- if (exp >= 23)
+- return x; /* it's an integer already (or Inf) */
+- if (exp < -1)
+- return x & 0x80000000; /* |x| < 0.5 -> +/-0 */
+- if (exp == -1)
+- /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */
+- return (x & 0x80000000) | 0x3f800000;
+- half = 0x400000 >> exp;
+- /* add 0.5 to the magnitude and chop off the fraction bits */
+- return (x + half) & ~(0x7fffff >> exp);
+-}
+-
+-int emulate_altivec(struct pt_regs *regs)
+-{
+- unsigned int instr, i;
+- unsigned int va, vb, vc, vd;
+- vector128 *vrs;
+-
+- if (get_user(instr, (unsigned int __user *) regs->nip))
+- return -EFAULT;
+- if ((instr >> 26) != 4)
+- return -EINVAL; /* not an altivec instruction */
+- vd = (instr >> 21) & 0x1f;
+- va = (instr >> 16) & 0x1f;
+- vb = (instr >> 11) & 0x1f;
+- vc = (instr >> 6) & 0x1f;
+-
+- vrs = current->thread.vr;
+- switch (instr & 0x3f) {
+- case 10:
+- switch (vc) {
+- case 0: /* vaddfp */
+- vaddfp(&vrs[vd], &vrs[va], &vrs[vb]);
+- break;
+- case 1: /* vsubfp */
+- vsubfp(&vrs[vd], &vrs[va], &vrs[vb]);
+- break;
+- case 4: /* vrefp */
+- vrefp(&vrs[vd], &vrs[vb]);
+- break;
+- case 5: /* vrsqrtefp */
+- vrsqrtefp(&vrs[vd], &vrs[vb]);
+- break;
+- case 6: /* vexptefp */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = eexp2(vrs[vb].u[i]);
+- break;
+- case 7: /* vlogefp */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = elog2(vrs[vb].u[i]);
+- break;
+- case 8: /* vrfin */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = rfin(vrs[vb].u[i]);
+- break;
+- case 9: /* vrfiz */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = rfiz(vrs[vb].u[i]);
+- break;
+- case 10: /* vrfip */
+- for (i = 0; i < 4; ++i) {
+- u32 x = vrs[vb].u[i];
+- x = (x & 0x80000000)? rfiz(x): rfii(x);
+- vrs[vd].u[i] = x;
+- }
+- break;
+- case 11: /* vrfim */
+- for (i = 0; i < 4; ++i) {
+- u32 x = vrs[vb].u[i];
+- x = (x & 0x80000000)? rfii(x): rfiz(x);
+- vrs[vd].u[i] = x;
+- }
+- break;
+- case 14: /* vctuxs */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
+- ¤t->thread.vscr.u[3]);
+- break;
+- case 15: /* vctsxs */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
+- ¤t->thread.vscr.u[3]);
+- break;
+- default:
+- return -EINVAL;
+- }
+- break;
+- case 46: /* vmaddfp */
+- vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+- break;
+- case 47: /* vnmsubfp */
+- vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- return 0;
+-}
+diff --git a/arch/ppc/kernel/vector.S b/arch/ppc/kernel/vector.S
+deleted file mode 100644
+--- a/arch/ppc/kernel/vector.S
++++ /dev/null
+@@ -1,217 +0,0 @@
+-#include <asm/ppc_asm.h>
+-#include <asm/processor.h>
+-
+-/*
+- * The routines below are in assembler so we can closely control the
+- * usage of floating-point registers. These routines must be called
+- * with preempt disabled.
+- */
+- .data
+-fpzero:
+- .long 0
+-fpone:
+- .long 0x3f800000 /* 1.0 in single-precision FP */
+-fphalf:
+- .long 0x3f000000 /* 0.5 in single-precision FP */
+-
+- .text
+-/*
+- * Internal routine to enable floating point and set FPSCR to 0.
+- * Don't call it from C; it doesn't use the normal calling convention.
+- */
+-fpenable:
+- mfmsr r10
+- ori r11,r10,MSR_FP
+- mtmsr r11
+- isync
+- stfd fr0,24(r1)
+- stfd fr1,16(r1)
+- stfd fr31,8(r1)
+- lis r11,fpzero at ha
+- mffs fr31
+- lfs fr1,fpzero at l(r11)
+- mtfsf 0xff,fr1
+- blr
+-
+-fpdisable:
+- mtfsf 0xff,fr31
+- lfd fr31,8(r1)
+- lfd fr1,16(r1)
+- lfd fr0,24(r1)
+- mtmsr r10
+- isync
+- blr
+-
+-/*
+- * Vector add, floating point.
+- */
+- .globl vaddfp
+-vaddfp:
+- stwu r1,-32(r1)
+- mflr r0
+- stw r0,36(r1)
+- bl fpenable
+- li r0,4
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- lfsx fr1,r5,r6
+- fadds fr0,fr0,fr1
+- stfsx fr0,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- bl fpdisable
+- lwz r0,36(r1)
+- mtlr r0
+- addi r1,r1,32
+- blr
+-
+-/*
+- * Vector subtract, floating point.
+- */
+- .globl vsubfp
+-vsubfp:
+- stwu r1,-32(r1)
+- mflr r0
+- stw r0,36(r1)
+- bl fpenable
+- li r0,4
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- lfsx fr1,r5,r6
+- fsubs fr0,fr0,fr1
+- stfsx fr0,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- bl fpdisable
+- lwz r0,36(r1)
+- mtlr r0
+- addi r1,r1,32
+- blr
+-
+-/*
+- * Vector multiply and add, floating point.
+- */
+- .globl vmaddfp
+-vmaddfp:
+- stwu r1,-48(r1)
+- mflr r0
+- stw r0,52(r1)
+- bl fpenable
+- stfd fr2,32(r1)
+- li r0,4
+- mtctr r0
+- li r7,0
+-1: lfsx fr0,r4,r7
+- lfsx fr1,r5,r7
+- lfsx fr2,r6,r7
+- fmadds fr0,fr0,fr2,fr1
+- stfsx fr0,r3,r7
+- addi r7,r7,4
+- bdnz 1b
+- lfd fr2,32(r1)
+- bl fpdisable
+- lwz r0,52(r1)
+- mtlr r0
+- addi r1,r1,48
+- blr
+-
+-/*
+- * Vector negative multiply and subtract, floating point.
+- */
+- .globl vnmsubfp
+-vnmsubfp:
+- stwu r1,-48(r1)
+- mflr r0
+- stw r0,52(r1)
+- bl fpenable
+- stfd fr2,32(r1)
+- li r0,4
+- mtctr r0
+- li r7,0
+-1: lfsx fr0,r4,r7
+- lfsx fr1,r5,r7
+- lfsx fr2,r6,r7
+- fnmsubs fr0,fr0,fr2,fr1
+- stfsx fr0,r3,r7
+- addi r7,r7,4
+- bdnz 1b
+- lfd fr2,32(r1)
+- bl fpdisable
+- lwz r0,52(r1)
+- mtlr r0
+- addi r1,r1,48
+- blr
+-
+-/*
+- * Vector reciprocal estimate. We just compute 1.0/x.
+- * r3 -> destination, r4 -> source.
+- */
+- .globl vrefp
+-vrefp:
+- stwu r1,-32(r1)
+- mflr r0
+- stw r0,36(r1)
+- bl fpenable
+- lis r9,fpone at ha
+- li r0,4
+- lfs fr1,fpone at l(r9)
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- fdivs fr0,fr1,fr0
+- stfsx fr0,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- bl fpdisable
+- lwz r0,36(r1)
+- mtlr r0
+- addi r1,r1,32
+- blr
+-
+-/*
+- * Vector reciprocal square-root estimate, floating point.
+- * We use the frsqrte instruction for the initial estimate followed
+- * by 2 iterations of Newton-Raphson to get sufficient accuracy.
+- * r3 -> destination, r4 -> source.
+- */
+- .globl vrsqrtefp
+-vrsqrtefp:
+- stwu r1,-48(r1)
+- mflr r0
+- stw r0,52(r1)
+- bl fpenable
+- stfd fr2,32(r1)
+- stfd fr3,40(r1)
+- stfd fr4,48(r1)
+- stfd fr5,56(r1)
+- lis r9,fpone at ha
+- lis r8,fphalf at ha
+- li r0,4
+- lfs fr4,fpone at l(r9)
+- lfs fr5,fphalf at l(r8)
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- frsqrte fr1,fr0 /* r = frsqrte(s) */
+- fmuls fr3,fr1,fr0 /* r * s */
+- fmuls fr2,fr1,fr5 /* r * 0.5 */
+- fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
+- fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
+- fmuls fr3,fr1,fr0 /* r * s */
+- fmuls fr2,fr1,fr5 /* r * 0.5 */
+- fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
+- fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
+- stfsx fr1,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- lfd fr5,56(r1)
+- lfd fr4,48(r1)
+- lfd fr3,40(r1)
+- lfd fr2,32(r1)
+- bl fpdisable
+- lwz r0,36(r1)
+- mtlr r0
+- addi r1,r1,32
+- blr
+diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
+--- a/arch/ppc/kernel/vmlinux.lds.S
++++ b/arch/ppc/kernel/vmlinux.lds.S
+@@ -149,32 +149,6 @@ SECTIONS
+
+ . = ALIGN(4096);
+ _sextratext = .;
+- __pmac_begin = .;
+- .pmac.text : { *(.pmac.text) }
+- .pmac.data : { *(.pmac.data) }
+- . = ALIGN(4096);
+- __pmac_end = .;
+-
+- . = ALIGN(4096);
+- __prep_begin = .;
+- .prep.text : { *(.prep.text) }
+- .prep.data : { *(.prep.data) }
+- . = ALIGN(4096);
+- __prep_end = .;
+-
+- . = ALIGN(4096);
+- __chrp_begin = .;
+- .chrp.text : { *(.chrp.text) }
+- .chrp.data : { *(.chrp.data) }
+- . = ALIGN(4096);
+- __chrp_end = .;
+-
+- . = ALIGN(4096);
+- __openfirmware_begin = .;
+- .openfirmware.text : { *(.openfirmware.text) }
+- .openfirmware.data : { *(.openfirmware.data) }
+- . = ALIGN(4096);
+- __openfirmware_end = .;
+ _eextratext = .;
+
+ __bss_start = .;
+diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
+--- a/arch/ppc/lib/string.S
++++ b/arch/ppc/lib/string.S
+@@ -65,9 +65,9 @@
+ .stabs "arch/ppc/lib/",N_SO,0,0,0f
+ .stabs "string.S",N_SO,0,0,0f
+
+-CACHELINE_BYTES = L1_CACHE_LINE_SIZE
+-LG_CACHELINE_BYTES = LG_L1_CACHE_LINE_SIZE
+-CACHELINE_MASK = (L1_CACHE_LINE_SIZE-1)
++CACHELINE_BYTES = L1_CACHE_BYTES
++LG_CACHELINE_BYTES = L1_CACHE_SHIFT
++CACHELINE_MASK = (L1_CACHE_BYTES-1)
+
+ _GLOBAL(strcpy)
+ addi r5,r3,-1
+@@ -265,12 +265,12 @@ _GLOBAL(cacheable_memcpy)
+ dcbz r11,r6
+ #endif
+ COPY_16_BYTES
+-#if L1_CACHE_LINE_SIZE >= 32
++#if L1_CACHE_BYTES >= 32
+ COPY_16_BYTES
+-#if L1_CACHE_LINE_SIZE >= 64
++#if L1_CACHE_BYTES >= 64
+ COPY_16_BYTES
+ COPY_16_BYTES
+-#if L1_CACHE_LINE_SIZE >= 128
++#if L1_CACHE_BYTES >= 128
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+@@ -485,12 +485,12 @@ _GLOBAL(__copy_tofrom_user)
+ .text
+ /* the main body of the cacheline loop */
+ COPY_16_BYTES_WITHEX(0)
+-#if L1_CACHE_LINE_SIZE >= 32
++#if L1_CACHE_BYTES >= 32
+ COPY_16_BYTES_WITHEX(1)
+-#if L1_CACHE_LINE_SIZE >= 64
++#if L1_CACHE_BYTES >= 64
+ COPY_16_BYTES_WITHEX(2)
+ COPY_16_BYTES_WITHEX(3)
+-#if L1_CACHE_LINE_SIZE >= 128
++#if L1_CACHE_BYTES >= 128
+ COPY_16_BYTES_WITHEX(4)
+ COPY_16_BYTES_WITHEX(5)
+ COPY_16_BYTES_WITHEX(6)
+@@ -544,12 +544,12 @@ _GLOBAL(__copy_tofrom_user)
+ * 104f (if in read part) or 105f (if in write part), after updating r5
+ */
+ COPY_16_BYTES_EXCODE(0)
+-#if L1_CACHE_LINE_SIZE >= 32
++#if L1_CACHE_BYTES >= 32
+ COPY_16_BYTES_EXCODE(1)
+-#if L1_CACHE_LINE_SIZE >= 64
++#if L1_CACHE_BYTES >= 64
+ COPY_16_BYTES_EXCODE(2)
+ COPY_16_BYTES_EXCODE(3)
+-#if L1_CACHE_LINE_SIZE >= 128
++#if L1_CACHE_BYTES >= 128
+ COPY_16_BYTES_EXCODE(4)
+ COPY_16_BYTES_EXCODE(5)
+ COPY_16_BYTES_EXCODE(6)
+diff --git a/arch/ppc/math-emu/sfp-machine.h b/arch/ppc/math-emu/sfp-machine.h
+--- a/arch/ppc/math-emu/sfp-machine.h
++++ b/arch/ppc/math-emu/sfp-machine.h
+@@ -166,7 +166,7 @@ extern int fp_pack_ds(void *, long, uns
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+
+-#define __FPU_FPSCR (current->thread.fpscr)
++#define __FPU_FPSCR (current->thread.fpscr.val)
+
+ /* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
+--- a/arch/ppc/mm/4xx_mmu.c
++++ b/arch/ppc/mm/4xx_mmu.c
+@@ -110,13 +110,11 @@ unsigned long __init mmu_mapin_ram(void)
+ 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 @@ unsigned long __init mmu_mapin_ram(void)
+ 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/init.c b/arch/ppc/mm/init.c
+--- a/arch/ppc/mm/init.c
++++ b/arch/ppc/mm/init.c
+@@ -69,15 +69,12 @@ int init_bootmem_done;
+ int boot_mapsize;
+ #ifdef CONFIG_PPC_PMAC
+ unsigned long agp_special_page;
++EXPORT_SYMBOL(agp_special_page);
+ #endif
+
+ extern char _end[];
+ extern char etext[], _stext[];
+ extern char __init_begin, __init_end;
+-extern char __prep_begin, __prep_end;
+-extern char __chrp_begin, __chrp_end;
+-extern char __pmac_begin, __pmac_end;
+-extern char __openfirmware_begin, __openfirmware_end;
+
+ #ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+@@ -167,14 +164,6 @@ void free_initmem(void)
+
+ printk ("Freeing unused kernel memory:");
+ FREESEC(init);
+- if (_machine != _MACH_Pmac)
+- FREESEC(pmac);
+- if (_machine != _MACH_chrp)
+- FREESEC(chrp);
+- if (_machine != _MACH_prep)
+- FREESEC(prep);
+- if (!have_of)
+- FREESEC(openfirmware);
+ printk("\n");
+ ppc_md.progress = NULL;
+ #undef FREESEC
+@@ -648,18 +637,16 @@ void update_mmu_cache(struct vm_area_str
+ */
+ int page_is_ram(unsigned long pfn)
+ {
+- unsigned long paddr = (pfn << PAGE_SHIFT);
+-
+- return paddr < __pa(high_memory);
++ return pfn < max_pfn;
+ }
+
+-pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ unsigned long size, pgprot_t vma_prot)
+ {
+ if (ppc_md.phys_mem_access_prot)
+- return ppc_md.phys_mem_access_prot(file, addr, size, vma_prot);
++ return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
+
+- if (!page_is_ram(addr >> PAGE_SHIFT))
++ if (!page_is_ram(pfn))
+ vma_prot = __pgprot(pgprot_val(vma_prot)
+ | _PAGE_GUARDED | _PAGE_NO_CACHE);
+ return vma_prot;
+diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
+--- a/arch/ppc/mm/pgtable.c
++++ b/arch/ppc/mm/pgtable.c
+@@ -114,9 +114,9 @@ struct page *pte_alloc_one(struct mm_str
+ 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 @@ map_page(unsigned long va, phys_addr_t p
+ 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/oprofile/Kconfig b/arch/ppc/oprofile/Kconfig
+deleted file mode 100644
+--- a/arch/ppc/oprofile/Kconfig
++++ /dev/null
+@@ -1,23 +0,0 @@
+-
+-menu "Profiling support"
+- depends on EXPERIMENTAL
+-
+-config PROFILING
+- bool "Profiling support (EXPERIMENTAL)"
+- help
+- Say Y here to enable the extended profiling support mechanisms used
+- by profilers such as OProfile.
+-
+-
+-config OPROFILE
+- tristate "OProfile system profiling (EXPERIMENTAL)"
+- depends on PROFILING
+- help
+- OProfile is a profiling system capable of profiling the
+- whole system, include the kernel, kernel modules, libraries,
+- and applications.
+-
+- If unsure, say N.
+-
+-endmenu
+-
+diff --git a/arch/ppc/oprofile/Makefile b/arch/ppc/oprofile/Makefile
+deleted file mode 100644
+--- a/arch/ppc/oprofile/Makefile
++++ /dev/null
+@@ -1,14 +0,0 @@
+-obj-$(CONFIG_OPROFILE) += oprofile.o
+-
+-DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
+- oprof.o cpu_buffer.o buffer_sync.o \
+- event_buffer.o oprofile_files.o \
+- oprofilefs.o oprofile_stats.o \
+- timer_int.o )
+-
+-oprofile-y := $(DRIVER_OBJS) common.o
+-
+-ifeq ($(CONFIG_FSL_BOOKE),y)
+- oprofile-y += op_model_fsl_booke.o
+-endif
+-
+diff --git a/arch/ppc/oprofile/common.c b/arch/ppc/oprofile/common.c
+deleted file mode 100644
+--- a/arch/ppc/oprofile/common.c
++++ /dev/null
+@@ -1,161 +0,0 @@
+-/*
+- * PPC 32 oprofile support
+- * Based on PPC64 oprofile support
+- * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * Copyright (C) Freescale Semiconductor, Inc 2004
+- *
+- * Author: Andy Fleming
+- *
+- * 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/oprofile.h>
+-#include <linux/slab.h>
+-#include <linux/init.h>
+-#include <linux/smp.h>
+-#include <linux/errno.h>
+-#include <asm/ptrace.h>
+-#include <asm/system.h>
+-#include <asm/perfmon.h>
+-#include <asm/cputable.h>
+-
+-#include "op_impl.h"
+-
+-static struct op_ppc32_model *model;
+-
+-static struct op_counter_config ctr[OP_MAX_COUNTER];
+-static struct op_system_config sys;
+-
+-static void op_handle_interrupt(struct pt_regs *regs)
+-{
+- model->handle_interrupt(regs, ctr);
+-}
+-
+-static int op_ppc32_setup(void)
+-{
+- /* Install our interrupt handler into the existing hook. */
+- if(request_perfmon_irq(&op_handle_interrupt))
+- return -EBUSY;
+-
+- mb();
+-
+- /* Pre-compute the values to stuff in the hardware registers. */
+- model->reg_setup(ctr, &sys, model->num_counters);
+-
+-#if 0
+- /* FIXME: Make multi-cpu work */
+- /* Configure the registers on all cpus. */
+- on_each_cpu(model->reg_setup, NULL, 0, 1);
+-#endif
+-
+- return 0;
+-}
+-
+-static void op_ppc32_shutdown(void)
+-{
+- mb();
+-
+- /* Remove our interrupt handler. We may be removing this module. */
+- free_perfmon_irq();
+-}
+-
+-static void op_ppc32_cpu_start(void *dummy)
+-{
+- model->start(ctr);
+-}
+-
+-static int op_ppc32_start(void)
+-{
+- on_each_cpu(op_ppc32_cpu_start, NULL, 0, 1);
+- return 0;
+-}
+-
+-static inline void op_ppc32_cpu_stop(void *dummy)
+-{
+- model->stop();
+-}
+-
+-static void op_ppc32_stop(void)
+-{
+- on_each_cpu(op_ppc32_cpu_stop, NULL, 0, 1);
+-}
+-
+-static int op_ppc32_create_files(struct super_block *sb, struct dentry *root)
+-{
+- int i;
+-
+- for (i = 0; i < model->num_counters; ++i) {
+- struct dentry *dir;
+- char buf[3];
+-
+- snprintf(buf, sizeof buf, "%d", i);
+- dir = oprofilefs_mkdir(sb, root, buf);
+-
+- 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);
+- oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
+- oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
+-
+- /* FIXME: Not sure if this is used */
+- oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
+- }
+-
+- oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
+- oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
+-
+- /* Default to tracing both kernel and user */
+- sys.enable_kernel = 1;
+- sys.enable_user = 1;
+-
+- return 0;
+-}
+-
+-static struct oprofile_operations oprof_ppc32_ops = {
+- .create_files = op_ppc32_create_files,
+- .setup = op_ppc32_setup,
+- .shutdown = op_ppc32_shutdown,
+- .start = op_ppc32_start,
+- .stop = op_ppc32_stop,
+- .cpu_type = NULL /* To be filled in below. */
+-};
+-
+-int __init oprofile_arch_init(struct oprofile_operations *ops)
+-{
+- char *name;
+- int cpu_id = smp_processor_id();
+-
+-#ifdef CONFIG_FSL_BOOKE
+- model = &op_model_fsl_booke;
+-#else
+- return -ENODEV;
+-#endif
+-
+- name = kmalloc(32, GFP_KERNEL);
+-
+- if (NULL == name)
+- return -ENOMEM;
+-
+- sprintf(name, "ppc/%s", cur_cpu_spec[cpu_id]->cpu_name);
+-
+- oprof_ppc32_ops.cpu_type = name;
+-
+- model->num_counters = cur_cpu_spec[cpu_id]->num_pmcs;
+-
+- *ops = oprof_ppc32_ops;
+-
+- printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
+- oprof_ppc32_ops.cpu_type);
+-
+- return 0;
+-}
+-
+-void oprofile_arch_exit(void)
+-{
+- kfree(oprof_ppc32_ops.cpu_type);
+- oprof_ppc32_ops.cpu_type = NULL;
+-}
+diff --git a/arch/ppc/oprofile/op_impl.h b/arch/ppc/oprofile/op_impl.h
+deleted file mode 100644
+--- a/arch/ppc/oprofile/op_impl.h
++++ /dev/null
+@@ -1,45 +0,0 @@
+-/*
+- * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * Based on alpha version.
+- *
+- * 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 OP_IMPL_H
+-#define OP_IMPL_H 1
+-
+-#define OP_MAX_COUNTER 8
+-
+-/* Per-counter configuration as set via oprofilefs. */
+-struct op_counter_config {
+- unsigned long enabled;
+- unsigned long event;
+- unsigned long count;
+- unsigned long kernel;
+- unsigned long user;
+- unsigned long unit_mask;
+-};
+-
+-/* System-wide configuration as set via oprofilefs. */
+-struct op_system_config {
+- unsigned long enable_kernel;
+- unsigned long enable_user;
+-};
+-
+-/* Per-arch configuration */
+-struct op_ppc32_model {
+- void (*reg_setup) (struct op_counter_config *,
+- struct op_system_config *,
+- int num_counters);
+- void (*start) (struct op_counter_config *);
+- void (*stop) (void);
+- void (*handle_interrupt) (struct pt_regs *,
+- struct op_counter_config *);
+- int num_counters;
+-};
+-
+-#endif /* OP_IMPL_H */
+diff --git a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c
+deleted file mode 100644
+--- a/arch/ppc/oprofile/op_model_fsl_booke.c
++++ /dev/null
+@@ -1,184 +0,0 @@
+-/*
+- * oprofile/op_model_e500.c
+- *
+- * Freescale Book-E oprofile support, based on ppc64 oprofile support
+- * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * Copyright (c) 2004 Freescale Semiconductor, Inc
+- *
+- * Author: Andy Fleming
+- * Maintainer: Kumar Gala <Kumar.Gala at freescale.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/oprofile.h>
+-#include <linux/init.h>
+-#include <linux/smp.h>
+-#include <asm/ptrace.h>
+-#include <asm/system.h>
+-#include <asm/processor.h>
+-#include <asm/cputable.h>
+-#include <asm/reg_booke.h>
+-#include <asm/page.h>
+-#include <asm/perfmon.h>
+-
+-#include "op_impl.h"
+-
+-static unsigned long reset_value[OP_MAX_COUNTER];
+-
+-static int num_counters;
+-static int oprofile_running;
+-
+-static inline unsigned int ctr_read(unsigned int i)
+-{
+- switch(i) {
+- case 0:
+- return mfpmr(PMRN_PMC0);
+- case 1:
+- return mfpmr(PMRN_PMC1);
+- case 2:
+- return mfpmr(PMRN_PMC2);
+- case 3:
+- return mfpmr(PMRN_PMC3);
+- default:
+- return 0;
+- }
+-}
+-
+-static inline void ctr_write(unsigned int i, unsigned int val)
+-{
+- switch(i) {
+- case 0:
+- mtpmr(PMRN_PMC0, val);
+- break;
+- case 1:
+- mtpmr(PMRN_PMC1, val);
+- break;
+- case 2:
+- mtpmr(PMRN_PMC2, val);
+- break;
+- case 3:
+- mtpmr(PMRN_PMC3, val);
+- break;
+- default:
+- break;
+- }
+-}
+-
+-
+-static void fsl_booke_reg_setup(struct op_counter_config *ctr,
+- struct op_system_config *sys,
+- int num_ctrs)
+-{
+- int i;
+-
+- num_counters = num_ctrs;
+-
+- /* freeze all counters */
+- pmc_stop_ctrs();
+-
+- /* Our counters count up, and "count" refers to
+- * how much before the next interrupt, and we interrupt
+- * on overflow. So we calculate the starting value
+- * which will give us "count" until overflow.
+- * Then we set the events on the enabled counters */
+- for (i = 0; i < num_counters; ++i) {
+- reset_value[i] = 0x80000000UL - ctr[i].count;
+-
+- init_pmc_stop(i);
+-
+- set_pmc_event(i, ctr[i].event);
+-
+- set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel);
+- }
+-}
+-
+-static void fsl_booke_start(struct op_counter_config *ctr)
+-{
+- int i;
+-
+- mtmsr(mfmsr() | MSR_PMM);
+-
+- for (i = 0; i < num_counters; ++i) {
+- if (ctr[i].enabled) {
+- ctr_write(i, reset_value[i]);
+- /* Set Each enabled counterd to only
+- * count when the Mark bit is not set */
+- set_pmc_marked(i, 1, 0);
+- pmc_start_ctr(i, 1);
+- } else {
+- ctr_write(i, 0);
+-
+- /* Set the ctr to be stopped */
+- pmc_start_ctr(i, 0);
+- }
+- }
+-
+- /* Clear the freeze bit, and enable the interrupt.
+- * The counters won't actually start until the rfi clears
+- * the PMM bit */
+- pmc_start_ctrs(1);
+-
+- oprofile_running = 1;
+-
+- pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(),
+- mfpmr(PMRN_PMGC0));
+-}
+-
+-static void fsl_booke_stop(void)
+-{
+- /* freeze counters */
+- pmc_stop_ctrs();
+-
+- oprofile_running = 0;
+-
+- pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(),
+- mfpmr(PMRN_PMGC0));
+-
+- mb();
+-}
+-
+-
+-static void fsl_booke_handle_interrupt(struct pt_regs *regs,
+- struct op_counter_config *ctr)
+-{
+- unsigned long pc;
+- int is_kernel;
+- int val;
+- int i;
+-
+- /* set the PMM bit (see comment below) */
+- mtmsr(mfmsr() | MSR_PMM);
+-
+- pc = regs->nip;
+- is_kernel = (pc >= KERNELBASE);
+-
+- for (i = 0; i < num_counters; ++i) {
+- val = ctr_read(i);
+- if (val < 0) {
+- if (oprofile_running && ctr[i].enabled) {
+- oprofile_add_pc(pc, is_kernel, i);
+- ctr_write(i, reset_value[i]);
+- } else {
+- ctr_write(i, 0);
+- }
+- }
+- }
+-
+- /* The freeze bit was set by the interrupt. */
+- /* Clear the freeze bit, and reenable the interrupt.
+- * The counters won't actually start until the rfi clears
+- * the PMM bit */
+- pmc_start_ctrs(1);
+-}
+-
+-struct op_ppc32_model op_model_fsl_booke = {
+- .reg_setup = fsl_booke_reg_setup,
+- .start = fsl_booke_start,
+- .stop = fsl_booke_stop,
+- .handle_interrupt = fsl_booke_handle_interrupt,
+-};
+diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c
+--- a/arch/ppc/platforms/4xx/bamboo.c
++++ b/arch/ppc/platforms/4xx/bamboo.c
+@@ -51,7 +51,7 @@
+ #include <syslib/gen550.h>
+ #include <syslib/ibm440gx_common.h>
+
+-bd_t __res;
++extern bd_t __res;
+
+ static struct ibm44x_clocks clocks __initdata;
+
+@@ -425,17 +425,7 @@ bamboo_setup_arch(void)
+ void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+ {
+- parse_bootinfo(find_bootinfo());
+-
+- /*
+- * If we were passed in a board information, copy it into the
+- * residual data area.
+- */
+- if (r3)
+- __res = *(bd_t *)(r3 + KERNELBASE);
+-
+-
+- ibm44x_platform_init();
++ ibm44x_platform_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = bamboo_setup_arch;
+ ppc_md.show_cpuinfo = bamboo_show_cpuinfo;
+diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
+--- a/arch/ppc/platforms/4xx/ebony.c
++++ b/arch/ppc/platforms/4xx/ebony.c
+@@ -54,7 +54,7 @@
+ #include <syslib/gen550.h>
+ #include <syslib/ibm440gp_common.h>
+
+-bd_t __res;
++extern bd_t __res;
+
+ static struct ibm44x_clocks clocks __initdata;
+
+@@ -90,7 +90,7 @@ ebony_calibrate_decr(void)
+ * on Rev. C silicon then errata forces us to
+ * use the internal clock.
+ */
+- if (strcmp(cur_cpu_spec[0]->cpu_name, "440GP Rev. B") == 0)
++ if (strcmp(cur_cpu_spec->cpu_name, "440GP Rev. B") == 0)
+ freq = EBONY_440GP_RB_SYSCLK;
+ else
+ freq = EBONY_440GP_RC_SYSCLK;
+@@ -317,16 +317,7 @@ ebony_setup_arch(void)
+ void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+ {
+- parse_bootinfo(find_bootinfo());
+-
+- /*
+- * If we were passed in a board information, copy it into the
+- * residual data area.
+- */
+- if (r3)
+- __res = *(bd_t *)(r3 + KERNELBASE);
+-
+- ibm44x_platform_init();
++ ibm44x_platform_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = ebony_setup_arch;
+ ppc_md.show_cpuinfo = ebony_show_cpuinfo;
+diff --git a/arch/ppc/platforms/4xx/ibm440ep.c b/arch/ppc/platforms/4xx/ibm440ep.c
+--- a/arch/ppc/platforms/4xx/ibm440ep.c
++++ b/arch/ppc/platforms/4xx/ibm440ep.c
+@@ -14,6 +14,7 @@
+ */
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/platform_device.h>
+ #include <platforms/4xx/ibm440ep.h>
+ #include <asm/ocp.h>
+ #include <asm/ppc4xx_pic.h>
+diff --git a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c
+--- a/arch/ppc/platforms/4xx/ibmstb4.c
++++ b/arch/ppc/platforms/4xx/ibmstb4.c
+@@ -10,6 +10,7 @@
+ */
+
+ #include <linux/init.h>
++#include <linux/platform_device.h>
+ #include <asm/ocp.h>
+ #include <asm/ppc4xx_pic.h>
+ #include <platforms/4xx/ibmstb4.h>
+diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
+--- a/arch/ppc/platforms/4xx/luan.c
++++ b/arch/ppc/platforms/4xx/luan.c
+@@ -52,7 +52,7 @@
+ #include <syslib/ibm440gx_common.h>
+ #include <syslib/ibm440sp_common.h>
+
+-bd_t __res;
++extern bd_t __res;
+
+ static struct ibm44x_clocks clocks __initdata;
+
+@@ -355,16 +355,7 @@ luan_setup_arch(void)
+ void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+ {
+- parse_bootinfo(find_bootinfo());
+-
+- /*
+- * If we were passed in a board information, copy it into the
+- * residual data area.
+- */
+- if (r3)
+- __res = *(bd_t *)(r3 + KERNELBASE);
+-
+- ibm44x_platform_init();
++ ibm44x_platform_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = luan_setup_arch;
+ ppc_md.show_cpuinfo = luan_show_cpuinfo;
+diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
+--- a/arch/ppc/platforms/4xx/ocotea.c
++++ b/arch/ppc/platforms/4xx/ocotea.c
+@@ -52,7 +52,7 @@
+ #include <syslib/gen550.h>
+ #include <syslib/ibm440gx_common.h>
+
+-bd_t __res;
++extern bd_t __res;
+
+ static struct ibm44x_clocks clocks __initdata;
+
+@@ -286,6 +286,15 @@ ocotea_setup_arch(void)
+
+ ibm440gx_tah_enable();
+
++ /*
++ * Determine various clocks.
++ * To be completely correct we should get SysClk
++ * from FPGA, because it can be changed by on-board switches
++ * --ebs
++ */
++ ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
++ ocp_sys_info.opb_bus_freq = clocks.opb;
++
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_DS1743,
+ 0,
+@@ -324,25 +333,7 @@ static void __init ocotea_init(void)
+ void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+ {
+- parse_bootinfo(find_bootinfo());
+-
+- /*
+- * If we were passed in a board information, copy it into the
+- * residual data area.
+- */
+- if (r3)
+- __res = *(bd_t *)(r3 + KERNELBASE);
+-
+- /*
+- * Determine various clocks.
+- * To be completely correct we should get SysClk
+- * from FPGA, because it can be changed by on-board switches
+- * --ebs
+- */
+- ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+- ocp_sys_info.opb_bus_freq = clocks.opb;
+-
+- ibm44x_platform_init();
++ ibm44x_platform_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = ocotea_setup_arch;
+ ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
+diff --git a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c
+--- a/arch/ppc/platforms/4xx/redwood5.c
++++ b/arch/ppc/platforms/4xx/redwood5.c
+@@ -14,7 +14,7 @@
+ #include <linux/config.h>
+ #include <linux/init.h>
+ #include <linux/pagemap.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/ioport.h>
+ #include <asm/io.h>
+ #include <asm/machdep.h>
+diff --git a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c
+--- a/arch/ppc/platforms/4xx/redwood6.c
++++ b/arch/ppc/platforms/4xx/redwood6.c
+@@ -12,7 +12,7 @@
+ #include <linux/config.h>
+ #include <linux/init.h>
+ #include <linux/pagemap.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/ioport.h>
+ #include <asm/io.h>
+ #include <asm/ppc4xx_pic.h>
+diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
+--- a/arch/ppc/platforms/83xx/mpc834x_sys.h
++++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
+@@ -19,7 +19,6 @@
+
+ #include <linux/config.h>
+ #include <linux/init.h>
+-#include <linux/seq_file.h>
+ #include <syslib/ppc83xx_setup.h>
+ #include <asm/ppcboot.h>
+
+diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
+--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
++++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
+@@ -52,6 +52,10 @@
+
+ #include <syslib/ppc85xx_setup.h>
+
++static const char *GFAR_PHY_0 = "phy0:0";
++static const char *GFAR_PHY_1 = "phy0:1";
++static const char *GFAR_PHY_3 = "phy0:3";
++
+ /* ************************************************************************
+ *
+ * Setup the architecture
+@@ -63,6 +67,7 @@ mpc8540ads_setup_arch(void)
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
++ struct gianfar_mdio_data *mdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+@@ -89,34 +94,35 @@ mpc8540ads_setup_arch(void)
+ invalidate_tlbcam_entry(num_tlbcam_entries - 1);
+ #endif
+
++ /* setup the board related info for the MDIO bus */
++ mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC85xx_MDIO);
++
++ mdata->irq[0] = MPC85xx_IRQ_EXT5;
++ mdata->irq[1] = MPC85xx_IRQ_EXT5;
++ mdata->irq[2] = -1;
++ mdata->irq[3] = MPC85xx_IRQ_EXT5;
++ mdata->irq[31] = -1;
++ mdata->paddr += binfo->bi_immr_base;
++
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 0;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_0;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 1;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_1;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
+ if (pdata) {
+ pdata->board_flags = 0;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 3;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_3;
+ memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+ }
+
+diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
+--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
++++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
+@@ -56,6 +56,10 @@
+ #include <syslib/ppc85xx_setup.h>
+
+
++static const char *GFAR_PHY_0 = "phy0:0";
++static const char *GFAR_PHY_1 = "phy0:1";
++static const char *GFAR_PHY_3 = "phy0:3";
++
+ /* ************************************************************************
+ *
+ * Setup the architecture
+@@ -68,6 +72,7 @@ mpc8560ads_setup_arch(void)
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
++ struct gianfar_mdio_data *mdata;
+
+ cpm2_reset();
+
+@@ -86,24 +91,28 @@ mpc8560ads_setup_arch(void)
+ mpc85xx_setup_hose();
+ #endif
+
++ /* setup the board related info for the MDIO bus */
++ mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC85xx_MDIO);
++
++ mdata->irq[0] = MPC85xx_IRQ_EXT5;
++ mdata->irq[1] = MPC85xx_IRQ_EXT5;
++ mdata->irq[2] = -1;
++ mdata->irq[3] = MPC85xx_IRQ_EXT5;
++ mdata->irq[31] = -1;
++ mdata->paddr += binfo->bi_immr_base;
++
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 0;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_0;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 1;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_1;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
+--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
++++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
+@@ -19,7 +19,6 @@
+
+ #include <linux/config.h>
+ #include <linux/init.h>
+-#include <linux/seq_file.h>
+ #include <asm/ppcboot.h>
+
+ #define BOARD_CCSRBAR ((uint)0xe0000000)
+diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
++++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+@@ -173,10 +173,7 @@ mpc85xx_cds_init_IRQ(void)
+ #ifdef CONFIG_PCI
+ openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq);
+
+- for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+- irq_desc[i].handler = &i8259_pic;
+-
+- i8259_init(0);
++ i8259_init(0, 0);
+ #endif
+
+ #ifdef CONFIG_CPM2
+@@ -394,6 +391,9 @@ mpc85xx_cds_pcibios_fixup(void)
+
+ TODC_ALLOC();
+
++static const char *GFAR_PHY_0 = "phy0:0";
++static const char *GFAR_PHY_1 = "phy0:1";
++
+ /* ************************************************************************
+ *
+ * Setup the architecture
+@@ -405,6 +405,7 @@ mpc85xx_cds_setup_arch(void)
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
++ struct gianfar_mdio_data *mdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+@@ -448,44 +449,42 @@ mpc85xx_cds_setup_arch(void)
+ invalidate_tlbcam_entry(num_tlbcam_entries - 1);
+ #endif
+
++ /* setup the board related info for the MDIO bus */
++ mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC85xx_MDIO);
++
++ mdata->irq[0] = MPC85xx_IRQ_EXT5;
++ mdata->irq[1] = MPC85xx_IRQ_EXT5;
++ mdata->irq[2] = -1;
++ mdata->irq[3] = -1;
++ mdata->irq[31] = -1;
++ mdata->paddr += binfo->bi_immr_base;
++
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 0;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_0;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 1;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_1;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 0;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_0;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 1;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_1;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
+--- a/arch/ppc/platforms/85xx/sbc8560.c
++++ b/arch/ppc/platforms/85xx/sbc8560.c
+@@ -91,6 +91,9 @@ sbc8560_early_serial_map(void)
+ }
+ #endif
+
++static const char *GFAR_PHY_25 = "phy0:25";
++static const char *GFAR_PHY_26 = "phy0:26";
++
+ /* ************************************************************************
+ *
+ * Setup the architecture
+@@ -102,6 +105,7 @@ sbc8560_setup_arch(void)
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
++ struct gianfar_mdio_data *mdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+@@ -126,24 +130,26 @@ sbc8560_setup_arch(void)
+ invalidate_tlbcam_entry(num_tlbcam_entries - 1);
+ #endif
+
++ /* setup the board related info for the MDIO bus */
++ mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC85xx_MDIO);
++
++ mdata->irq[25] = MPC85xx_IRQ_EXT6;
++ mdata->irq[26] = MPC85xx_IRQ_EXT7;
++ mdata->irq[31] = -1;
++ mdata->paddr += binfo->bi_immr_base;
++
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT6;
+- pdata->phyid = 25;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_25;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+- pdata->interruptPHY = MPC85xx_IRQ_EXT7;
+- pdata->phyid = 26;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_26;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
+--- a/arch/ppc/platforms/85xx/stx_gp3.c
++++ b/arch/ppc/platforms/85xx/stx_gp3.c
+@@ -91,6 +91,9 @@ static u8 gp3_openpic_initsenses[] __ini
+ 0x0, /* External 11: */
+ };
+
++static const char *GFAR_PHY_2 = "phy0:2";
++static const char *GFAR_PHY_4 = "phy0:4";
++
+ /*
+ * Setup the architecture
+ */
+@@ -100,6 +103,7 @@ gp3_setup_arch(void)
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
++ struct gianfar_mdio_data *mdata;
+
+ cpm2_reset();
+
+@@ -118,23 +122,26 @@ gp3_setup_arch(void)
+ mpc85xx_setup_hose();
+ #endif
+
++ /* setup the board related info for the MDIO bus */
++ mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC85xx_MDIO);
++
++ mdata->irq[2] = MPC85xx_IRQ_EXT5;
++ mdata->irq[4] = MPC85xx_IRQ_EXT5;
++ mdata->irq[31] = -1;
++ mdata->paddr += binfo->bi_immr_base;
++
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ if (pdata) {
+ /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 2;
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_2;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ if (pdata) {
+ /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+- pdata->phyid = 4;
+- /* fixup phy address */
+- pdata->phy_reg_addr += binfo->bi_immr_base;
++ pdata->bus_id = GFAR_PHY_4;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h
+--- a/arch/ppc/platforms/85xx/stx_gp3.h
++++ b/arch/ppc/platforms/85xx/stx_gp3.h
+@@ -21,7 +21,6 @@
+
+ #include <linux/config.h>
+ #include <linux/init.h>
+-#include <linux/seq_file.h>
+ #include <asm/ppcboot.h>
+
+ #define BOARD_CCSRBAR ((uint)0xe0000000)
+diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
+--- a/arch/ppc/platforms/Makefile
++++ b/arch/ppc/platforms/Makefile
+@@ -14,6 +14,9 @@ obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pm
+ pmac_low_i2c.o pmac_cache.o
+ obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \
+ chrp_pegasos_eth.o
++ifeq ($(CONFIG_PPC_CHRP),y)
++obj-$(CONFIG_NVRAM) += chrp_nvram.o
++endif
+ obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o
+ ifeq ($(CONFIG_PPC_PMAC),y)
+ obj-$(CONFIG_NVRAM) += pmac_nvram.o
+diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
+--- a/arch/ppc/platforms/chestnut.c
++++ b/arch/ppc/platforms/chestnut.c
+@@ -541,7 +541,6 @@ platform_init(unsigned long r3, unsigned
+
+ ppc_md.setup_arch = chestnut_setup_arch;
+ ppc_md.show_cpuinfo = chestnut_show_cpuinfo;
+- ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = mv64360_init_irq;
+ ppc_md.get_irq = mv64360_get_irq;
+ ppc_md.init = NULL;
+diff --git a/arch/ppc/platforms/chrp_nvram.c b/arch/ppc/platforms/chrp_nvram.c
+new file mode 100644
+--- /dev/null
++++ b/arch/ppc/platforms/chrp_nvram.c
+@@ -0,0 +1,83 @@
++/*
++ * c 2001 PPC 64 Team, IBM Corp
++ *
++ * 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.
++ *
++ * /dev/nvram driver for PPC
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <asm/uaccess.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++
++static unsigned int nvram_size;
++static unsigned char nvram_buf[4];
++static DEFINE_SPINLOCK(nvram_lock);
++
++static unsigned char chrp_nvram_read(int addr)
++{
++ unsigned long done, flags;
++ unsigned char ret;
++
++ if (addr >= nvram_size) {
++ printk(KERN_DEBUG "%s: read addr %d > nvram_size %u\n",
++ current->comm, addr, nvram_size);
++ return 0xff;
++ }
++ spin_lock_irqsave(&nvram_lock, flags);
++ if ((call_rtas("nvram-fetch", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
++ ret = 0xff;
++ else
++ ret = nvram_buf[0];
++ spin_unlock_irqrestore(&nvram_lock, flags);
++
++ return ret;
++}
++
++static void chrp_nvram_write(int addr, unsigned char val)
++{
++ unsigned long done, flags;
++
++ if (addr >= nvram_size) {
++ printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n",
++ current->comm, addr, nvram_size);
++ return;
++ }
++ spin_lock_irqsave(&nvram_lock, flags);
++ nvram_buf[0] = val;
++ if ((call_rtas("nvram-store", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
++ printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr);
++ spin_unlock_irqrestore(&nvram_lock, flags);
++}
++
++void __init chrp_nvram_init(void)
++{
++ struct device_node *nvram;
++ unsigned int *nbytes_p, proplen;
++
++ nvram = of_find_node_by_type(NULL, "nvram");
++ if (nvram == NULL)
++ return;
++
++ nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
++ if (nbytes_p == NULL || proplen != sizeof(unsigned int))
++ return;
++
++ nvram_size = *nbytes_p;
++
++ printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size);
++ of_node_put(nvram);
++
++ ppc_md.nvram_read_val = chrp_nvram_read;
++ ppc_md.nvram_write_val = chrp_nvram_write;
++
++ return;
++}
+diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
+--- a/arch/ppc/platforms/chrp_pci.c
++++ b/arch/ppc/platforms/chrp_pci.c
+@@ -29,7 +29,7 @@ void __iomem *gg2_pci_config_base;
+ * limit the bus number to 3 bits
+ */
+
+-int __chrp gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
++int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
+ int len, u32 *val)
+ {
+ volatile void __iomem *cfg_data;
+@@ -56,7 +56,7 @@ int __chrp gg2_read_config(struct pci_bu
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+-int __chrp gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
++int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
+ int len, u32 val)
+ {
+ volatile void __iomem *cfg_data;
+@@ -92,7 +92,7 @@ static struct pci_ops gg2_pci_ops =
+ /*
+ * Access functions for PCI config space using RTAS calls.
+ */
+-int __chrp
++int
+ rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+ {
+@@ -108,7 +108,7 @@ rtas_read_config(struct pci_bus *bus, un
+ return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
+ }
+
+-int __chrp
++int
+ rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+ {
+@@ -203,7 +203,7 @@ static void __init setup_peg2(struct pci
+ printk ("RTAS supporting Pegasos OF not found, please upgrade"
+ " your firmware\n");
+ }
+- pci_assign_all_busses = 1;
++ pci_assign_all_buses = 1;
+ }
+
+ void __init
+diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c
+--- a/arch/ppc/platforms/chrp_pegasos_eth.c
++++ b/arch/ppc/platforms/chrp_pegasos_eth.c
+@@ -13,11 +13,24 @@
+ #include <linux/types.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/mv643xx.h>
+ #include <linux/pci.h>
+
+-/* Pegasos 2 specific Marvell MV 64361 gigabit ethernet port setup */
++#define PEGASOS2_MARVELL_REGBASE (0xf1000000)
++#define PEGASOS2_MARVELL_REGSIZE (0x00004000)
++#define PEGASOS2_SRAM_BASE (0xf2000000)
++#define PEGASOS2_SRAM_SIZE (256*1024)
++
++#define PEGASOS2_SRAM_BASE_ETH0 (PEGASOS2_SRAM_BASE)
++#define PEGASOS2_SRAM_BASE_ETH1 (PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) )
++
++
++#define PEGASOS2_SRAM_RXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
++#define PEGASOS2_SRAM_TXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
++
++#undef BE_VERBOSE
++
+ static struct resource mv643xx_eth_shared_resources[] = {
+ [0] = {
+ .name = "ethernet shared base",
+@@ -44,7 +57,16 @@ static struct resource mv643xx_eth0_reso
+ },
+ };
+
+-static struct mv643xx_eth_platform_data eth0_pd;
++
++static struct mv643xx_eth_platform_data eth0_pd = {
++ .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
++ .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
++ .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
++
++ .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH0 + PEGASOS2_SRAM_TXRING_SIZE,
++ .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
++ .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
++};
+
+ static struct platform_device eth0_device = {
+ .name = MV643XX_ETH_NAME,
+@@ -65,7 +87,15 @@ static struct resource mv643xx_eth1_reso
+ },
+ };
+
+-static struct mv643xx_eth_platform_data eth1_pd;
++static struct mv643xx_eth_platform_data eth1_pd = {
++ .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
++ .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
++ .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
++
++ .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH1 + PEGASOS2_SRAM_TXRING_SIZE,
++ .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
++ .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
++};
+
+ static struct platform_device eth1_device = {
+ .name = MV643XX_ETH_NAME,
+@@ -83,9 +113,62 @@ static struct platform_device *mv643xx_e
+ ð1_device,
+ };
+
++/***********/
++/***********/
++#define MV_READ(offset,val) { val = readl(mv643xx_reg_base + offset); }
++#define MV_WRITE(offset,data) writel(data, mv643xx_reg_base + offset)
++
++static void __iomem *mv643xx_reg_base;
++
++static int Enable_SRAM(void)
++{
++ u32 ALong;
++
++ if (mv643xx_reg_base == NULL)
++ mv643xx_reg_base = ioremap(PEGASOS2_MARVELL_REGBASE,
++ PEGASOS2_MARVELL_REGSIZE);
++
++ if (mv643xx_reg_base == NULL)
++ return -ENOMEM;
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: register remapped from %p to %p\n",
++ (void *)PEGASOS2_MARVELL_REGBASE, (void *)mv643xx_reg_base);
++#endif
++
++ MV_WRITE(MV64340_SRAM_CONFIG, 0);
+
+-int
+-mv643xx_eth_add_pds(void)
++ MV_WRITE(MV64340_INTEGRATED_SRAM_BASE_ADDR, PEGASOS2_SRAM_BASE >> 16);
++
++ MV_READ(MV64340_BASE_ADDR_ENABLE, ALong);
++ ALong &= ~(1 << 19);
++ MV_WRITE(MV64340_BASE_ADDR_ENABLE, ALong);
++
++ ALong = 0x02;
++ ALong |= PEGASOS2_SRAM_BASE & 0xffff0000;
++ MV_WRITE(MV643XX_ETH_BAR_4, ALong);
++
++ MV_WRITE(MV643XX_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
++
++ MV_READ(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
++ ALong &= ~(1 << 4);
++ MV_WRITE(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: register unmapped\n");
++ printk("Pegasos II/Marvell MV64361: SRAM at %p, size=%x\n", (void*) PEGASOS2_SRAM_BASE, PEGASOS2_SRAM_SIZE);
++#endif
++
++ iounmap(mv643xx_reg_base);
++ mv643xx_reg_base = NULL;
++
++ return 1;
++}
++
++
++/***********/
++/***********/
++int mv643xx_eth_add_pds(void)
+ {
+ int ret = 0;
+ static struct pci_device_id pci_marvell_mv64360[] = {
+@@ -93,9 +176,38 @@ mv643xx_eth_add_pds(void)
+ { }
+ };
+
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: init\n");
++#endif
++
+ if (pci_dev_present(pci_marvell_mv64360)) {
+- ret = platform_add_devices(mv643xx_eth_pd_devs, ARRAY_SIZE(mv643xx_eth_pd_devs));
++ ret = platform_add_devices(mv643xx_eth_pd_devs,
++ ARRAY_SIZE(mv643xx_eth_pd_devs));
++
++ if ( Enable_SRAM() < 0)
++ {
++ eth0_pd.tx_sram_addr = 0;
++ eth0_pd.tx_sram_size = 0;
++ eth0_pd.rx_sram_addr = 0;
++ eth0_pd.rx_sram_size = 0;
++
++ eth1_pd.tx_sram_addr = 0;
++ eth1_pd.tx_sram_size = 0;
++ eth1_pd.rx_sram_addr = 0;
++ eth1_pd.rx_sram_size = 0;
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: Can't enable the "
++ "SRAM\n");
++#endif
++ }
+ }
++
++#ifdef BE_VERBOSE
++ printk("Pegasos II/Marvell MV64361: init is over\n");
++#endif
++
+ return ret;
+ }
++
+ device_initcall(mv643xx_eth_add_pds);
+diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
+--- a/arch/ppc/platforms/chrp_setup.c
++++ b/arch/ppc/platforms/chrp_setup.c
+@@ -104,7 +104,7 @@ static const char *gg2_cachemodes[4] = {
+ "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
+ };
+
+-int __chrp
++int
+ chrp_show_cpuinfo(struct seq_file *m)
+ {
+ int i, sdramen;
+@@ -302,7 +302,7 @@ void __init chrp_setup_arch(void)
+ pci_create_OF_bus_map();
+ }
+
+-void __chrp
++void
+ chrp_event_scan(void)
+ {
+ unsigned char log[1024];
+@@ -313,7 +313,7 @@ chrp_event_scan(void)
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+ }
+
+-void __chrp
++void
+ chrp_restart(char *cmd)
+ {
+ printk("RTAS system-reboot returned %d\n",
+@@ -321,7 +321,7 @@ chrp_restart(char *cmd)
+ for (;;);
+ }
+
+-void __chrp
++void
+ chrp_power_off(void)
+ {
+ /* allow power on only with power button press */
+@@ -330,20 +330,12 @@ chrp_power_off(void)
+ for (;;);
+ }
+
+-void __chrp
++void
+ chrp_halt(void)
+ {
+ chrp_power_off();
+ }
+
+-u_int __chrp
+-chrp_irq_canonicalize(u_int irq)
+-{
+- if (irq == 2)
+- return 9;
+- return irq;
+-}
+-
+ /*
+ * Finds the open-pic node and sets OpenPIC_Addr based on its reg property.
+ * Then checks if it has an interrupt-ranges property. If it does then
+@@ -444,9 +436,7 @@ void __init chrp_init_IRQ(void)
+ i8259_irq);
+
+ }
+- for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+- irq_desc[i].handler = &i8259_pic;
+- i8259_init(chrp_int_ack);
++ i8259_init(chrp_int_ack, 0);
+
+ #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+ /* see if there is a keyboard in the device tree
+@@ -464,8 +454,7 @@ void __init
+ chrp_init2(void)
+ {
+ #ifdef CONFIG_NVRAM
+-// XX replace this in a more saner way
+-// pmac_nvram_init();
++ chrp_nvram_init();
+ #endif
+
+ request_region(0x20,0x20,"pic1");
+@@ -499,6 +488,7 @@ chrp_init(unsigned long r3, unsigned lon
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+ isa_io_base = CHRP_ISA_IO_BASE; /* default value */
++ ppc_do_canonicalize_irqs = 1;
+
+ if (root)
+ machine = get_property(root, "model", NULL);
+@@ -517,7 +507,6 @@ chrp_init(unsigned long r3, unsigned lon
+ ppc_md.show_percpuinfo = of_show_percpuinfo;
+ ppc_md.show_cpuinfo = chrp_show_cpuinfo;
+
+- ppc_md.irq_canonicalize = chrp_irq_canonicalize;
+ ppc_md.init_IRQ = chrp_init_IRQ;
+ if (_chrp_type == _CHRP_Pegasos)
+ ppc_md.get_irq = i8259_irq;
+@@ -561,7 +550,7 @@ chrp_init(unsigned long r3, unsigned lon
+ #endif
+
+ #ifdef CONFIG_SMP
+- ppc_md.smp_ops = &chrp_smp_ops;
++ smp_ops = &chrp_smp_ops;
+ #endif /* CONFIG_SMP */
+
+ /*
+@@ -571,7 +560,7 @@ chrp_init(unsigned long r3, unsigned lon
+ if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
+ }
+
+-void __chrp
++void
+ rtas_display_progress(char *s, unsigned short hex)
+ {
+ int width;
+@@ -598,7 +587,7 @@ rtas_display_progress(char *s, unsigned
+ call_rtas( "display-character", 1, 1, NULL, ' ' );
+ }
+
+-void __chrp
++void
+ rtas_indicator_progress(char *s, unsigned short hex)
+ {
+ call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
+diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
+--- a/arch/ppc/platforms/chrp_smp.c
++++ b/arch/ppc/platforms/chrp_smp.c
+@@ -31,6 +31,7 @@
+ #include <asm/residual.h>
+ #include <asm/time.h>
+ #include <asm/open_pic.h>
++#include <asm/machdep.h>
+
+ extern unsigned long smp_chrp_cpu_nr;
+
+@@ -88,7 +89,7 @@ smp_chrp_take_timebase(void)
+ }
+
+ /* CHRP with openpic */
+-struct smp_ops_t chrp_smp_ops __chrpdata = {
++struct smp_ops_t chrp_smp_ops = {
+ .message_pass = smp_openpic_message_pass,
+ .probe = smp_chrp_probe,
+ .kick_cpu = smp_chrp_kick_cpu,
+diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
+--- a/arch/ppc/platforms/chrp_time.c
++++ b/arch/ppc/platforms/chrp_time.c
+@@ -52,7 +52,7 @@ long __init chrp_time_init(void)
+ return 0;
+ }
+
+-int __chrp chrp_cmos_clock_read(int addr)
++int chrp_cmos_clock_read(int addr)
+ {
+ if (nvram_as1 != 0)
+ outb(addr>>8, nvram_as1);
+@@ -60,7 +60,7 @@ int __chrp chrp_cmos_clock_read(int addr
+ return (inb(nvram_data));
+ }
+
+-void __chrp chrp_cmos_clock_write(unsigned long val, int addr)
++void chrp_cmos_clock_write(unsigned long val, int addr)
+ {
+ if (nvram_as1 != 0)
+ outb(addr>>8, nvram_as1);
+@@ -72,7 +72,7 @@ void __chrp chrp_cmos_clock_write(unsign
+ /*
+ * Set the hardware clock. -- Cort
+ */
+-int __chrp chrp_set_rtc_time(unsigned long nowtime)
++int chrp_set_rtc_time(unsigned long nowtime)
+ {
+ unsigned char save_control, save_freq_select;
+ struct rtc_time tm;
+@@ -118,7 +118,7 @@ int __chrp chrp_set_rtc_time(unsigned lo
+ return 0;
+ }
+
+-unsigned long __chrp chrp_get_rtc_time(void)
++unsigned long chrp_get_rtc_time(void)
+ {
+ unsigned int year, mon, day, hour, min, sec;
+ int uip, i;
+diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c
+--- a/arch/ppc/platforms/cpci690.c
++++ b/arch/ppc/platforms/cpci690.c
+@@ -21,6 +21,7 @@
+ #include <linux/initrd.h>
+ #include <linux/root_dev.h>
+ #include <linux/mv643xx.h>
++#include <linux/platform_device.h>
+ #include <asm/bootinfo.h>
+ #include <asm/machdep.h>
+ #include <asm/todc.h>
+diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
+--- a/arch/ppc/platforms/ev64260.c
++++ b/arch/ppc/platforms/ev64260.c
+@@ -33,6 +33,7 @@
+ #include <linux/console.h>
+ #include <linux/initrd.h>
+ #include <linux/root_dev.h>
++#include <linux/platform_device.h>
+ #if !defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
+--- a/arch/ppc/platforms/ev64360.c
++++ b/arch/ppc/platforms/ev64360.c
+@@ -25,6 +25,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/mtd/physmap.h>
+ #include <linux/mv643xx.h>
++#include <linux/platform_device.h>
+ #ifdef CONFIG_BOOTIMG
+ #include <linux/bootimg.h>
+ #endif
+@@ -35,6 +36,7 @@
+ #include <asm/bootinfo.h>
+ #include <asm/ppcboot.h>
+ #include <asm/mv64x60.h>
++#include <asm/machdep.h>
+ #include <platforms/ev64360.h>
+
+ #define BOARD_VENDOR "Marvell"
+diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
+--- a/arch/ppc/platforms/fads.h
++++ b/arch/ppc/platforms/fads.h
+@@ -25,6 +25,8 @@
+
+ #if defined(CONFIG_MPC86XADS)
+
++#define BOARD_CHIP_NAME "MPC86X"
++
+ /* U-Boot maps BCSR to 0xff080000 */
+ #define BCSR_ADDR ((uint)0xff080000)
+
+diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c
+--- a/arch/ppc/platforms/gemini_setup.c
++++ b/arch/ppc/platforms/gemini_setup.c
+@@ -35,6 +35,7 @@
+ #include <asm/time.h>
+ #include <asm/open_pic.h>
+ #include <asm/bootinfo.h>
++#include <asm/machdep.h>
+
+ void gemini_find_bridges(void);
+ static int gemini_get_clock_speed(void);
+@@ -555,7 +556,6 @@ void __init platform_init(unsigned long
+
+ ppc_md.setup_arch = gemini_setup_arch;
+ ppc_md.show_cpuinfo = gemini_show_cpuinfo;
+- ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = gemini_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+ ppc_md.init = NULL;
+@@ -575,6 +575,6 @@ void __init platform_init(unsigned long
+ ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
+
+ #ifdef CONFIG_SMP
+- ppc_md.smp_ops = &gemini_smp_ops;
++ smp_ops = &gemini_smp_ops;
+ #endif /* CONFIG_SMP */
+ }
+diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
+--- a/arch/ppc/platforms/hdpu.c
++++ b/arch/ppc/platforms/hdpu.c
+@@ -22,6 +22,7 @@
+ #include <linux/irq.h>
+ #include <linux/ide.h>
+ #include <linux/seq_file.h>
++#include <linux/platform_device.h>
+
+ #include <linux/initrd.h>
+ #include <linux/root_dev.h>
+@@ -609,11 +610,6 @@ static void parse_bootinfo(unsigned long
+ }
+
+ #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)
+ {
+@@ -753,7 +749,7 @@ static int smp_hdpu_probe(void)
+ }
+
+ static void
+-smp_hdpu_message_pass(int target, int msg, unsigned long data, int wait)
++smp_hdpu_message_pass(int target, int msg)
+ {
+ if (msg > 0x3) {
+ printk("SMP %d: smp_message_pass: unknown msg %d\n",
+@@ -949,7 +945,7 @@ platform_init(unsigned long r3, unsigned
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+ #ifdef CONFIG_SMP
+- ppc_md.smp_ops = &hdpu_smp_ops;
++ smp_ops = &hdpu_smp_ops;
+ #endif /* CONFIG_SMP */
+
+ #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
+--- a/arch/ppc/platforms/katana.c
++++ b/arch/ppc/platforms/katana.c
+@@ -29,6 +29,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/mtd/physmap.h>
+ #include <linux/mv643xx.h>
++#include <linux/platform_device.h>
+ #ifdef CONFIG_BOOTIMG
+ #include <linux/bootimg.h>
+ #endif
+@@ -42,6 +43,7 @@
+ #include <asm/ppcboot.h>
+ #include <asm/mv64x60.h>
+ #include <platforms/katana.h>
++#include <asm/machdep.h>
+
+ static struct mv64x60_handle bh;
+ static katana_id_t katana_id;
+@@ -520,7 +522,7 @@ katana_fixup_resources(struct pci_dev *d
+ {
+ u16 v16;
+
+- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_LINE_SIZE>>2);
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES>>2);
+
+ pci_read_config_word(dev, PCI_COMMAND, &v16);
+ v16 |= PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK;
+diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
+--- a/arch/ppc/platforms/lite5200.c
++++ b/arch/ppc/platforms/lite5200.c
+@@ -35,6 +35,7 @@
+ #include <asm/io.h>
+ #include <asm/mpc52xx.h>
+ #include <asm/ppc_sys.h>
++#include <asm/machdep.h>
+
+ #include <syslib/mpc52xx_pci.h>
+
+diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
+--- a/arch/ppc/platforms/lopec.c
++++ b/arch/ppc/platforms/lopec.c
+@@ -144,15 +144,6 @@ lopec_show_cpuinfo(struct seq_file *m)
+ return 0;
+ }
+
+-static u32
+-lopec_irq_canonicalize(u32 irq)
+-{
+- if (irq == 2)
+- return 9;
+- else
+- return irq;
+-}
+-
+ static void
+ lopec_restart(char *cmd)
+ {
+@@ -276,15 +267,11 @@ lopec_init_IRQ(void)
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ &i8259_irq);
+
+- /* Map i8259 interrupts */
+- for(i = 0; i < NUM_8259_INTERRUPTS; i++)
+- irq_desc[i].handler = &i8259_pic;
+-
+ /*
+ * The EPIC allows for a read in the range of 0xFEF00000 ->
+ * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+ */
+- i8259_init(0xfef00000);
++ i8259_init(0xfef00000, 0);
+ }
+
+ static int __init
+@@ -379,10 +366,10 @@ platform_init(unsigned long r3, unsigned
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
++ ppc_do_canonicalize_irqs = 1;
+
+ ppc_md.setup_arch = lopec_setup_arch;
+ ppc_md.show_cpuinfo = lopec_show_cpuinfo;
+- ppc_md.irq_canonicalize = lopec_irq_canonicalize;
+ ppc_md.init_IRQ = lopec_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+diff --git a/arch/ppc/platforms/mpc885ads.h b/arch/ppc/platforms/mpc885ads.h
+--- a/arch/ppc/platforms/mpc885ads.h
++++ b/arch/ppc/platforms/mpc885ads.h
+@@ -88,5 +88,7 @@
+ #define SICR_ENET_MASK ((uint)0x00ff0000)
+ #define SICR_ENET_CLKRT ((uint)0x002c0000)
+
++#define BOARD_CHIP_NAME "MPC885"
++
+ #endif /* __ASM_MPC885ADS_H__ */
+ #endif /* __KERNEL__ */
+diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
+--- a/arch/ppc/platforms/mvme5100.c
++++ b/arch/ppc/platforms/mvme5100.c
+@@ -223,11 +223,7 @@ mvme5100_init_IRQ(void)
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ &i8259_irq);
+
+- /* Map i8259 interrupts. */
+- for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+- irq_desc[i].handler = &i8259_pic;
+-
+- i8259_init(0);
++ i8259_init(0, 0);
+ #else
+ openpic_init(0);
+ #endif
+diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c
+--- a/arch/ppc/platforms/pal4_setup.c
++++ b/arch/ppc/platforms/pal4_setup.c
+@@ -28,6 +28,7 @@
+ #include <asm/io.h>
+ #include <asm/todc.h>
+ #include <asm/bootinfo.h>
++#include <asm/machdep.h>
+
+ #include <syslib/cpc700.h>
+
+diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c
+--- a/arch/ppc/platforms/pmac_backlight.c
++++ b/arch/ppc/platforms/pmac_backlight.c
+@@ -37,7 +37,7 @@ static int backlight_req_enable = -1;
+ static void backlight_callback(void *);
+ static DECLARE_WORK(backlight_work, backlight_callback, NULL);
+
+-void __pmac register_backlight_controller(struct backlight_controller *ctrler,
++void register_backlight_controller(struct backlight_controller *ctrler,
+ void *data, char *type)
+ {
+ struct device_node* bk_node;
+@@ -99,7 +99,7 @@ void __pmac register_backlight_controlle
+ }
+ EXPORT_SYMBOL(register_backlight_controller);
+
+-void __pmac unregister_backlight_controller(struct backlight_controller
++void unregister_backlight_controller(struct backlight_controller
+ *ctrler, void *data)
+ {
+ /* We keep the current backlight level (for now) */
+@@ -108,7 +108,7 @@ void __pmac unregister_backlight_control
+ }
+ EXPORT_SYMBOL(unregister_backlight_controller);
+
+-static int __pmac __set_backlight_enable(int enable)
++static int __set_backlight_enable(int enable)
+ {
+ int rc;
+
+@@ -122,7 +122,7 @@ static int __pmac __set_backlight_enable
+ release_console_sem();
+ return rc;
+ }
+-int __pmac set_backlight_enable(int enable)
++int set_backlight_enable(int enable)
+ {
+ if (!backlighter)
+ return -ENODEV;
+@@ -133,7 +133,7 @@ int __pmac set_backlight_enable(int enab
+
+ EXPORT_SYMBOL(set_backlight_enable);
+
+-int __pmac get_backlight_enable(void)
++int get_backlight_enable(void)
+ {
+ if (!backlighter)
+ return -ENODEV;
+@@ -141,7 +141,7 @@ int __pmac get_backlight_enable(void)
+ }
+ EXPORT_SYMBOL(get_backlight_enable);
+
+-static int __pmac __set_backlight_level(int level)
++static int __set_backlight_level(int level)
+ {
+ int rc = 0;
+
+@@ -165,7 +165,7 @@ static int __pmac __set_backlight_level(
+ }
+ return rc;
+ }
+-int __pmac set_backlight_level(int level)
++int set_backlight_level(int level)
+ {
+ if (!backlighter)
+ return -ENODEV;
+@@ -176,7 +176,7 @@ int __pmac set_backlight_level(int level
+
+ EXPORT_SYMBOL(set_backlight_level);
+
+-int __pmac get_backlight_level(void)
++int get_backlight_level(void)
+ {
+ if (!backlighter)
+ return -ENODEV;
+diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
+--- a/arch/ppc/platforms/pmac_cpufreq.c
++++ b/arch/ppc/platforms/pmac_cpufreq.c
+@@ -136,7 +136,7 @@ static inline void debug_calc_bogomips(v
+
+ /* Switch CPU speed under 750FX CPU control
+ */
+-static int __pmac cpu_750fx_cpu_speed(int low_speed)
++static int cpu_750fx_cpu_speed(int low_speed)
+ {
+ u32 hid2;
+
+@@ -172,7 +172,7 @@ static int __pmac cpu_750fx_cpu_speed(in
+ return 0;
+ }
+
+-static unsigned int __pmac cpu_750fx_get_cpu_speed(void)
++static unsigned int cpu_750fx_get_cpu_speed(void)
+ {
+ if (mfspr(SPRN_HID1) & HID1_PS)
+ return low_freq;
+@@ -181,7 +181,7 @@ static unsigned int __pmac cpu_750fx_get
+ }
+
+ /* Switch CPU speed using DFS */
+-static int __pmac dfs_set_cpu_speed(int low_speed)
++static int dfs_set_cpu_speed(int low_speed)
+ {
+ if (low_speed == 0) {
+ /* ramping up, set voltage first */
+@@ -205,7 +205,7 @@ static int __pmac dfs_set_cpu_speed(int
+ return 0;
+ }
+
+-static unsigned int __pmac dfs_get_cpu_speed(void)
++static unsigned int dfs_get_cpu_speed(void)
+ {
+ if (mfspr(SPRN_HID1) & HID1_DFS)
+ return low_freq;
+@@ -216,7 +216,7 @@ static unsigned int __pmac dfs_get_cpu_s
+
+ /* Switch CPU speed using slewing GPIOs
+ */
+-static int __pmac gpios_set_cpu_speed(int low_speed)
++static int gpios_set_cpu_speed(int low_speed)
+ {
+ int gpio, timeout = 0;
+
+@@ -258,7 +258,7 @@ static int __pmac gpios_set_cpu_speed(in
+
+ /* Switch CPU speed under PMU control
+ */
+-static int __pmac pmu_set_cpu_speed(int low_speed)
++static int pmu_set_cpu_speed(int low_speed)
+ {
+ struct adb_request req;
+ unsigned long save_l2cr;
+@@ -354,7 +354,7 @@ static int __pmac pmu_set_cpu_speed(int
+ return 0;
+ }
+
+-static int __pmac do_set_cpu_speed(int speed_mode, int notify)
++static int do_set_cpu_speed(int speed_mode, int notify)
+ {
+ struct cpufreq_freqs freqs;
+ unsigned long l3cr;
+@@ -391,17 +391,17 @@ static int __pmac do_set_cpu_speed(int s
+ return 0;
+ }
+
+-static unsigned int __pmac pmac_cpufreq_get_speed(unsigned int cpu)
++static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)
+ {
+ return cur_freq;
+ }
+
+-static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy)
++static int pmac_cpufreq_verify(struct cpufreq_policy *policy)
+ {
+ return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
+ }
+
+-static int __pmac pmac_cpufreq_target( struct cpufreq_policy *policy,
++static int pmac_cpufreq_target( struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+ {
+@@ -414,13 +414,13 @@ static int __pmac pmac_cpufreq_target( s
+ return do_set_cpu_speed(newstate, 1);
+ }
+
+-unsigned int __pmac pmac_get_one_cpufreq(int i)
++unsigned int pmac_get_one_cpufreq(int i)
+ {
+ /* Supports only one CPU for now */
+ return (i == 0) ? cur_freq : 0;
+ }
+
+-static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
++static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
+ {
+ if (policy->cpu != 0)
+ return -ENODEV;
+@@ -433,7 +433,7 @@ static int __pmac pmac_cpufreq_cpu_init(
+ return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
+ }
+
+-static u32 __pmac read_gpio(struct device_node *np)
++static u32 read_gpio(struct device_node *np)
+ {
+ u32 *reg = (u32 *)get_property(np, "reg", NULL);
+ u32 offset;
+@@ -452,7 +452,7 @@ static u32 __pmac read_gpio(struct devic
+ return offset;
+ }
+
+-static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
++static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
+ {
+ /* Ok, this could be made a bit smarter, but let's be robust for now. We
+ * always force a speed change to high speed before sleep, to make sure
+@@ -468,7 +468,7 @@ static int __pmac pmac_cpufreq_suspend(s
+ return 0;
+ }
+
+-static int __pmac pmac_cpufreq_resume(struct cpufreq_policy *policy)
++static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
+ {
+ /* If we resume, first check if we have a get() function */
+ if (get_speed_proc)
+@@ -501,7 +501,7 @@ static struct cpufreq_driver pmac_cpufre
+ };
+
+
+-static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
++static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
+ {
+ struct device_node *volt_gpio_np = of_find_node_by_name(NULL,
+ "voltage-gpio");
+@@ -593,7 +593,7 @@ static int __pmac pmac_cpufreq_init_MacR
+ return 0;
+ }
+
+-static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode)
++static int pmac_cpufreq_init_7447A(struct device_node *cpunode)
+ {
+ struct device_node *volt_gpio_np;
+
+@@ -620,7 +620,7 @@ static int __pmac pmac_cpufreq_init_7447
+ return 0;
+ }
+
+-static int __pmac pmac_cpufreq_init_750FX(struct device_node *cpunode)
++static int pmac_cpufreq_init_750FX(struct device_node *cpunode)
+ {
+ struct device_node *volt_gpio_np;
+ u32 pvr, *value;
+diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
+--- a/arch/ppc/platforms/pmac_feature.c
++++ b/arch/ppc/platforms/pmac_feature.c
+@@ -63,7 +63,7 @@ extern struct device_node *k2_skiplist[2
+ * We use a single global lock to protect accesses. Each driver has
+ * to take care of its own locking
+ */
+-static DEFINE_SPINLOCK(feature_lock __pmacdata);
++static DEFINE_SPINLOCK(feature_lock);
+
+ #define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
+ #define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
+@@ -72,9 +72,9 @@ static DEFINE_SPINLOCK(feature_lock __p
+ /*
+ * Instance of some macio stuffs
+ */
+-struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata;
++struct macio_chip macio_chips[MAX_MACIO_CHIPS];
+
+-struct macio_chip* __pmac macio_find(struct device_node* child, int type)
++struct macio_chip* macio_find(struct device_node* child, int type)
+ {
+ while(child) {
+ int i;
+@@ -89,7 +89,7 @@ struct macio_chip* __pmac macio_find(str
+ }
+ EXPORT_SYMBOL_GPL(macio_find);
+
+-static const char* macio_names[] __pmacdata =
++static const char* macio_names[] =
+ {
+ "Unknown",
+ "Grand Central",
+@@ -116,10 +116,10 @@ static const char* macio_names[] __pmacd
+ #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
+ #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
+
+-static struct device_node* uninorth_node __pmacdata;
+-static u32 __iomem * uninorth_base __pmacdata;
+-static u32 uninorth_rev __pmacdata;
+-static int uninorth_u3 __pmacdata;
++static struct device_node* uninorth_node;
++static u32 __iomem * uninorth_base;
++static u32 uninorth_rev;
++static int uninorth_u3;
+ static void __iomem *u3_ht;
+
+ /*
+@@ -142,13 +142,13 @@ struct pmac_mb_def
+ struct feature_table_entry* features;
+ unsigned long board_flags;
+ };
+-static struct pmac_mb_def pmac_mb __pmacdata;
++static struct pmac_mb_def pmac_mb;
+
+ /*
+ * Here are the chip specific feature functions
+ */
+
+-static inline int __pmac
++static inline int
+ simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value)
+ {
+ struct macio_chip* macio;
+@@ -170,7 +170,7 @@ simple_feature_tweak(struct device_node*
+
+ #ifndef CONFIG_POWER4
+
+-static long __pmac
++static long
+ ohare_htw_scc_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -263,21 +263,21 @@ ohare_htw_scc_enable(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ ohare_floppy_enable(struct device_node* node, long param, long value)
+ {
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_FLOPPY_ENABLE, value);
+ }
+
+-static long __pmac
++static long
+ ohare_mesh_enable(struct device_node* node, long param, long value)
+ {
+ return simple_feature_tweak(node, macio_ohare,
+ OHARE_FCR, OH_MESH_ENABLE, value);
+ }
+
+-static long __pmac
++static long
+ ohare_ide_enable(struct device_node* node, long param, long value)
+ {
+ switch(param) {
+@@ -298,7 +298,7 @@ ohare_ide_enable(struct device_node* nod
+ }
+ }
+
+-static long __pmac
++static long
+ ohare_ide_reset(struct device_node* node, long param, long value)
+ {
+ switch(param) {
+@@ -313,7 +313,7 @@ ohare_ide_reset(struct device_node* node
+ }
+ }
+
+-static long __pmac
++static long
+ ohare_sleep_state(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio = &macio_chips[0];
+@@ -329,7 +329,7 @@ ohare_sleep_state(struct device_node* no
+ return 0;
+ }
+
+-static long __pmac
++static long
+ heathrow_modem_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -373,7 +373,7 @@ heathrow_modem_enable(struct device_node
+ return 0;
+ }
+
+-static long __pmac
++static long
+ heathrow_floppy_enable(struct device_node* node, long param, long value)
+ {
+ return simple_feature_tweak(node, macio_unknown,
+@@ -382,7 +382,7 @@ heathrow_floppy_enable(struct device_nod
+ value);
+ }
+
+-static long __pmac
++static long
+ heathrow_mesh_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -411,7 +411,7 @@ heathrow_mesh_enable(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ heathrow_ide_enable(struct device_node* node, long param, long value)
+ {
+ switch(param) {
+@@ -426,7 +426,7 @@ heathrow_ide_enable(struct device_node*
+ }
+ }
+
+-static long __pmac
++static long
+ heathrow_ide_reset(struct device_node* node, long param, long value)
+ {
+ switch(param) {
+@@ -441,7 +441,7 @@ heathrow_ide_reset(struct device_node* n
+ }
+ }
+
+-static long __pmac
++static long
+ heathrow_bmac_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -470,7 +470,7 @@ heathrow_bmac_enable(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ heathrow_sound_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -501,16 +501,16 @@ heathrow_sound_enable(struct device_node
+ return 0;
+ }
+
+-static u32 save_fcr[6] __pmacdata;
+-static u32 save_mbcr __pmacdata;
+-static u32 save_gpio_levels[2] __pmacdata;
+-static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata;
+-static u8 save_gpio_normal[KEYLARGO_GPIO_CNT] __pmacdata;
+-static u32 save_unin_clock_ctl __pmacdata;
+-static struct dbdma_regs save_dbdma[13] __pmacdata;
+-static struct dbdma_regs save_alt_dbdma[13] __pmacdata;
++static u32 save_fcr[6];
++static u32 save_mbcr;
++static u32 save_gpio_levels[2];
++static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
++static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
++static u32 save_unin_clock_ctl;
++static struct dbdma_regs save_dbdma[13];
++static struct dbdma_regs save_alt_dbdma[13];
+
+-static void __pmac
++static void
+ dbdma_save(struct macio_chip* macio, struct dbdma_regs* save)
+ {
+ int i;
+@@ -527,7 +527,7 @@ dbdma_save(struct macio_chip* macio, str
+ }
+ }
+
+-static void __pmac
++static void
+ dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save)
+ {
+ int i;
+@@ -547,7 +547,7 @@ dbdma_restore(struct macio_chip* macio,
+ }
+ }
+
+-static void __pmac
++static void
+ heathrow_sleep(struct macio_chip* macio, int secondary)
+ {
+ if (secondary) {
+@@ -580,7 +580,7 @@ heathrow_sleep(struct macio_chip* macio,
+ (void)MACIO_IN32(HEATHROW_FCR);
+ }
+
+-static void __pmac
++static void
+ heathrow_wakeup(struct macio_chip* macio, int secondary)
+ {
+ if (secondary) {
+@@ -605,7 +605,7 @@ heathrow_wakeup(struct macio_chip* macio
+ }
+ }
+
+-static long __pmac
++static long
+ heathrow_sleep_state(struct device_node* node, long param, long value)
+ {
+ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+@@ -622,7 +622,7 @@ heathrow_sleep_state(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_scc_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -723,7 +723,7 @@ core99_scc_enable(struct device_node* no
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_modem_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -775,7 +775,7 @@ core99_modem_enable(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ pangea_modem_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -830,7 +830,7 @@ pangea_modem_enable(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_ata100_enable(struct device_node* node, long value)
+ {
+ unsigned long flags;
+@@ -860,7 +860,7 @@ core99_ata100_enable(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_ide_enable(struct device_node* node, long param, long value)
+ {
+ /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
+@@ -883,7 +883,7 @@ core99_ide_enable(struct device_node* no
+ }
+ }
+
+-static long __pmac
++static long
+ core99_ide_reset(struct device_node* node, long param, long value)
+ {
+ switch(param) {
+@@ -901,7 +901,7 @@ core99_ide_reset(struct device_node* nod
+ }
+ }
+
+-static long __pmac
++static long
+ core99_gmac_enable(struct device_node* node, long param, long value)
+ {
+ unsigned long flags;
+@@ -918,7 +918,7 @@ core99_gmac_enable(struct device_node* n
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_gmac_phy_reset(struct device_node* node, long param, long value)
+ {
+ unsigned long flags;
+@@ -943,7 +943,7 @@ core99_gmac_phy_reset(struct device_node
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_sound_chip_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -973,7 +973,7 @@ core99_sound_chip_enable(struct device_n
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_airport_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -1060,7 +1060,7 @@ core99_airport_enable(struct device_node
+ }
+
+ #ifdef CONFIG_SMP
+-static long __pmac
++static long
+ core99_reset_cpu(struct device_node* node, long param, long value)
+ {
+ unsigned int reset_io = 0;
+@@ -1104,7 +1104,7 @@ core99_reset_cpu(struct device_node* nod
+ }
+ #endif /* CONFIG_SMP */
+
+-static long __pmac
++static long
+ core99_usb_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio;
+@@ -1257,7 +1257,7 @@ core99_usb_enable(struct device_node* no
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_firewire_enable(struct device_node* node, long param, long value)
+ {
+ unsigned long flags;
+@@ -1284,7 +1284,7 @@ core99_firewire_enable(struct device_nod
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_firewire_cable_power(struct device_node* node, long param, long value)
+ {
+ unsigned long flags;
+@@ -1315,7 +1315,7 @@ core99_firewire_cable_power(struct devic
+ return 0;
+ }
+
+-static long __pmac
++static long
+ intrepid_aack_delay_enable(struct device_node* node, long param, long value)
+ {
+ unsigned long flags;
+@@ -1336,7 +1336,7 @@ intrepid_aack_delay_enable(struct device
+
+ #endif /* CONFIG_POWER4 */
+
+-static long __pmac
++static long
+ core99_read_gpio(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio = &macio_chips[0];
+@@ -1345,7 +1345,7 @@ core99_read_gpio(struct device_node* nod
+ }
+
+
+-static long __pmac
++static long
+ core99_write_gpio(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio = &macio_chips[0];
+@@ -1356,7 +1356,7 @@ core99_write_gpio(struct device_node* no
+
+ #ifdef CONFIG_POWER4
+
+-static long __pmac
++static long
+ g5_gmac_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio = &macio_chips[0];
+@@ -1380,7 +1380,7 @@ g5_gmac_enable(struct device_node* node,
+ return 0;
+ }
+
+-static long __pmac
++static long
+ g5_fw_enable(struct device_node* node, long param, long value)
+ {
+ struct macio_chip* macio = &macio_chips[0];
+@@ -1403,7 +1403,7 @@ g5_fw_enable(struct device_node* node, l
+ return 0;
+ }
+
+-static long __pmac
++static long
+ g5_mpic_enable(struct device_node* node, long param, long value)
+ {
+ unsigned long flags;
+@@ -1419,7 +1419,7 @@ g5_mpic_enable(struct device_node* node,
+ }
+
+ #ifdef CONFIG_SMP
+-static long __pmac
++static long
+ g5_reset_cpu(struct device_node* node, long param, long value)
+ {
+ unsigned int reset_io = 0;
+@@ -1465,7 +1465,7 @@ g5_reset_cpu(struct device_node* node, l
+ * This takes the second CPU off the bus on dual CPU machines
+ * running UP
+ */
+-void __pmac g5_phy_disable_cpu1(void)
++void g5_phy_disable_cpu1(void)
+ {
+ UN_OUT(U3_API_PHY_CONFIG_1, 0);
+ }
+@@ -1474,7 +1474,7 @@ void __pmac g5_phy_disable_cpu1(void)
+
+ #ifndef CONFIG_POWER4
+
+-static void __pmac
++static void
+ keylargo_shutdown(struct macio_chip* macio, int sleep_mode)
+ {
+ u32 temp;
+@@ -1528,7 +1528,7 @@ keylargo_shutdown(struct macio_chip* mac
+ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
+ }
+
+-static void __pmac
++static void
+ pangea_shutdown(struct macio_chip* macio, int sleep_mode)
+ {
+ u32 temp;
+@@ -1562,7 +1562,7 @@ pangea_shutdown(struct macio_chip* macio
+ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
+ }
+
+-static void __pmac
++static void
+ intrepid_shutdown(struct macio_chip* macio, int sleep_mode)
+ {
+ u32 temp;
+@@ -1591,7 +1591,7 @@ intrepid_shutdown(struct macio_chip* mac
+ }
+
+
+-void __pmac pmac_tweak_clock_spreading(int enable)
++void pmac_tweak_clock_spreading(int enable)
+ {
+ struct macio_chip* macio = &macio_chips[0];
+
+@@ -1698,7 +1698,7 @@ void __pmac pmac_tweak_clock_spreading(i
+ }
+
+
+-static int __pmac
++static int
+ core99_sleep(void)
+ {
+ struct macio_chip* macio;
+@@ -1791,7 +1791,7 @@ core99_sleep(void)
+ return 0;
+ }
+
+-static int __pmac
++static int
+ core99_wake_up(void)
+ {
+ struct macio_chip* macio;
+@@ -1854,7 +1854,7 @@ core99_wake_up(void)
+ return 0;
+ }
+
+-static long __pmac
++static long
+ core99_sleep_state(struct device_node* node, long param, long value)
+ {
+ /* Param == 1 means to enter the "fake sleep" mode that is
+@@ -1884,7 +1884,7 @@ core99_sleep_state(struct device_node* n
+
+ #endif /* CONFIG_POWER4 */
+
+-static long __pmac
++static long
+ generic_dev_can_wake(struct device_node* node, long param, long value)
+ {
+ /* Todo: eventually check we are really dealing with on-board
+@@ -1896,7 +1896,7 @@ generic_dev_can_wake(struct device_node*
+ return 0;
+ }
+
+-static long __pmac
++static long
+ generic_get_mb_info(struct device_node* node, long param, long value)
+ {
+ switch(param) {
+@@ -1919,7 +1919,7 @@ generic_get_mb_info(struct device_node*
+
+ /* Used on any machine
+ */
+-static struct feature_table_entry any_features[] __pmacdata = {
++static struct feature_table_entry any_features[] = {
+ { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },
+ { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake },
+ { 0, NULL }
+@@ -1931,7 +1931,7 @@ static struct feature_table_entry any_fe
+ * 2400,3400 and 3500 series powerbooks. Some older desktops seem
+ * to have issues with turning on/off those asic cells
+ */
+-static struct feature_table_entry ohare_features[] __pmacdata = {
++static struct feature_table_entry ohare_features[] = {
+ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
+ { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable },
+ { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable },
+@@ -1945,7 +1945,7 @@ static struct feature_table_entry ohare_
+ * Separated as some features couldn't be properly tested
+ * and the serial port control bits appear to confuse it.
+ */
+-static struct feature_table_entry heathrow_desktop_features[] __pmacdata = {
++static struct feature_table_entry heathrow_desktop_features[] = {
+ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
+ { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
+ { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
+@@ -1957,7 +1957,7 @@ static struct feature_table_entry heathr
+ /* Heathrow based laptop, that is the Wallstreet and mainstreet
+ * powerbooks.
+ */
+-static struct feature_table_entry heathrow_laptop_features[] __pmacdata = {
++static struct feature_table_entry heathrow_laptop_features[] = {
+ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
+ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
+@@ -1973,7 +1973,7 @@ static struct feature_table_entry heathr
+ /* Paddington based machines
+ * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
+ */
+-static struct feature_table_entry paddington_features[] __pmacdata = {
++static struct feature_table_entry paddington_features[] = {
+ { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
+ { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
+@@ -1991,7 +1991,7 @@ static struct feature_table_entry paddin
+ * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
+ * used on iBook2 & iMac "flow power".
+ */
+-static struct feature_table_entry core99_features[] __pmacdata = {
++static struct feature_table_entry core99_features[] = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, core99_modem_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+@@ -2014,7 +2014,7 @@ static struct feature_table_entry core99
+
+ /* RackMac
+ */
+-static struct feature_table_entry rackmac_features[] __pmacdata = {
++static struct feature_table_entry rackmac_features[] = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+ { PMAC_FTR_IDE_RESET, core99_ide_reset },
+@@ -2034,7 +2034,7 @@ static struct feature_table_entry rackma
+
+ /* Pangea features
+ */
+-static struct feature_table_entry pangea_features[] __pmacdata = {
++static struct feature_table_entry pangea_features[] = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+@@ -2054,7 +2054,7 @@ static struct feature_table_entry pangea
+
+ /* Intrepid features
+ */
+-static struct feature_table_entry intrepid_features[] __pmacdata = {
++static struct feature_table_entry intrepid_features[] = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+@@ -2077,7 +2077,7 @@ static struct feature_table_entry intrep
+
+ /* G5 features
+ */
+-static struct feature_table_entry g5_features[] __pmacdata = {
++static struct feature_table_entry g5_features[] = {
+ { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },
+ { PMAC_FTR_1394_ENABLE, g5_fw_enable },
+ { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
+@@ -2091,7 +2091,7 @@ static struct feature_table_entry g5_fea
+
+ #endif /* CONFIG_POWER4 */
+
+-static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
++static struct pmac_mb_def pmac_mb_defs[] = {
+ #ifndef CONFIG_POWER4
+ /*
+ * Desktops
+@@ -2356,7 +2356,7 @@ static struct pmac_mb_def pmac_mb_defs[]
+ /*
+ * The toplevel feature_call callback
+ */
+-long __pmac
++long
+ pmac_do_feature_call(unsigned int selector, ...)
+ {
+ struct device_node* node;
+@@ -2939,8 +2939,8 @@ void __init pmac_check_ht_link(void)
+ * Early video resume hook
+ */
+
+-static void (*pmac_early_vresume_proc)(void *data) __pmacdata;
+-static void *pmac_early_vresume_data __pmacdata;
++static void (*pmac_early_vresume_proc)(void *data);
++static void *pmac_early_vresume_data;
+
+ void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
+ {
+@@ -2953,7 +2953,7 @@ void pmac_set_early_video_resume(void (*
+ }
+ EXPORT_SYMBOL(pmac_set_early_video_resume);
+
+-void __pmac pmac_call_early_video_resume(void)
++void pmac_call_early_video_resume(void)
+ {
+ if (pmac_early_vresume_proc)
+ pmac_early_vresume_proc(pmac_early_vresume_data);
+@@ -2963,11 +2963,11 @@ void __pmac pmac_call_early_video_resume
+ * AGP related suspend/resume code
+ */
+
+-static struct pci_dev *pmac_agp_bridge __pmacdata;
+-static int (*pmac_agp_suspend)(struct pci_dev *bridge) __pmacdata;
+-static int (*pmac_agp_resume)(struct pci_dev *bridge) __pmacdata;
++static struct pci_dev *pmac_agp_bridge;
++static int (*pmac_agp_suspend)(struct pci_dev *bridge);
++static int (*pmac_agp_resume)(struct pci_dev *bridge);
+
+-void __pmac pmac_register_agp_pm(struct pci_dev *bridge,
++void pmac_register_agp_pm(struct pci_dev *bridge,
+ int (*suspend)(struct pci_dev *bridge),
+ int (*resume)(struct pci_dev *bridge))
+ {
+@@ -2984,7 +2984,7 @@ void __pmac pmac_register_agp_pm(struct
+ }
+ EXPORT_SYMBOL(pmac_register_agp_pm);
+
+-void __pmac pmac_suspend_agp_for_card(struct pci_dev *dev)
++void pmac_suspend_agp_for_card(struct pci_dev *dev)
+ {
+ if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
+ return;
+@@ -2994,7 +2994,7 @@ void __pmac pmac_suspend_agp_for_card(st
+ }
+ EXPORT_SYMBOL(pmac_suspend_agp_for_card);
+
+-void __pmac pmac_resume_agp_for_card(struct pci_dev *dev)
++void pmac_resume_agp_for_card(struct pci_dev *dev)
+ {
+ if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
+ return;
+diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c
+--- a/arch/ppc/platforms/pmac_nvram.c
++++ b/arch/ppc/platforms/pmac_nvram.c
+@@ -88,17 +88,17 @@ extern int system_running;
+ static int (*core99_write_bank)(int bank, u8* datas);
+ static int (*core99_erase_bank)(int bank);
+
+-static char *nvram_image __pmacdata;
++static char *nvram_image;
+
+
+-static unsigned char __pmac core99_nvram_read_byte(int addr)
++static unsigned char core99_nvram_read_byte(int addr)
+ {
+ if (nvram_image == NULL)
+ return 0xff;
+ return nvram_image[addr];
+ }
+
+-static void __pmac core99_nvram_write_byte(int addr, unsigned char val)
++static void core99_nvram_write_byte(int addr, unsigned char val)
+ {
+ if (nvram_image == NULL)
+ return;
+@@ -106,18 +106,18 @@ static void __pmac core99_nvram_write_by
+ }
+
+
+-static unsigned char __openfirmware direct_nvram_read_byte(int addr)
++static unsigned char direct_nvram_read_byte(int addr)
+ {
+ return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
+ }
+
+-static void __openfirmware direct_nvram_write_byte(int addr, unsigned char val)
++static void direct_nvram_write_byte(int addr, unsigned char val)
+ {
+ out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
+ }
+
+
+-static unsigned char __pmac indirect_nvram_read_byte(int addr)
++static unsigned char indirect_nvram_read_byte(int addr)
+ {
+ unsigned char val;
+ unsigned long flags;
+@@ -130,7 +130,7 @@ static unsigned char __pmac indirect_nvr
+ return val;
+ }
+
+-static void __pmac indirect_nvram_write_byte(int addr, unsigned char val)
++static void indirect_nvram_write_byte(int addr, unsigned char val)
+ {
+ unsigned long flags;
+
+@@ -143,13 +143,13 @@ static void __pmac indirect_nvram_write_
+
+ #ifdef CONFIG_ADB_PMU
+
+-static void __pmac pmu_nvram_complete(struct adb_request *req)
++static void pmu_nvram_complete(struct adb_request *req)
+ {
+ if (req->arg)
+ complete((struct completion *)req->arg);
+ }
+
+-static unsigned char __pmac pmu_nvram_read_byte(int addr)
++static unsigned char pmu_nvram_read_byte(int addr)
+ {
+ struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+@@ -165,7 +165,7 @@ static unsigned char __pmac pmu_nvram_re
+ return req.reply[0];
+ }
+
+-static void __pmac pmu_nvram_write_byte(int addr, unsigned char val)
++static void pmu_nvram_write_byte(int addr, unsigned char val)
+ {
+ struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+@@ -183,7 +183,7 @@ static void __pmac pmu_nvram_write_byte(
+ #endif /* CONFIG_ADB_PMU */
+
+
+-static u8 __pmac chrp_checksum(struct chrp_header* hdr)
++static u8 chrp_checksum(struct chrp_header* hdr)
+ {
+ u8 *ptr;
+ u16 sum = hdr->signature;
+@@ -194,7 +194,7 @@ static u8 __pmac chrp_checksum(struct ch
+ return sum;
+ }
+
+-static u32 __pmac core99_calc_adler(u8 *buffer)
++static u32 core99_calc_adler(u8 *buffer)
+ {
+ int cnt;
+ u32 low, high;
+@@ -216,7 +216,7 @@ static u32 __pmac core99_calc_adler(u8 *
+ return (high << 16) | low;
+ }
+
+-static u32 __pmac core99_check(u8* datas)
++static u32 core99_check(u8* datas)
+ {
+ struct core99_header* hdr99 = (struct core99_header*)datas;
+
+@@ -235,7 +235,7 @@ static u32 __pmac core99_check(u8* datas
+ return hdr99->generation;
+ }
+
+-static int __pmac sm_erase_bank(int bank)
++static int sm_erase_bank(int bank)
+ {
+ int stat, i;
+ unsigned long timeout;
+@@ -267,7 +267,7 @@ static int __pmac sm_erase_bank(int bank
+ return 0;
+ }
+
+-static int __pmac sm_write_bank(int bank, u8* datas)
++static int sm_write_bank(int bank, u8* datas)
+ {
+ int i, stat = 0;
+ unsigned long timeout;
+@@ -302,7 +302,7 @@ static int __pmac sm_write_bank(int bank
+ return 0;
+ }
+
+-static int __pmac amd_erase_bank(int bank)
++static int amd_erase_bank(int bank)
+ {
+ int i, stat = 0;
+ unsigned long timeout;
+@@ -349,7 +349,7 @@ static int __pmac amd_erase_bank(int ban
+ return 0;
+ }
+
+-static int __pmac amd_write_bank(int bank, u8* datas)
++static int amd_write_bank(int bank, u8* datas)
+ {
+ int i, stat = 0;
+ unsigned long timeout;
+@@ -430,7 +430,7 @@ static void __init lookup_partitions(voi
+ DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
+ }
+
+-static void __pmac core99_nvram_sync(void)
++static void core99_nvram_sync(void)
+ {
+ struct core99_header* hdr99;
+ unsigned long flags;
+@@ -554,12 +554,12 @@ void __init pmac_nvram_init(void)
+ lookup_partitions();
+ }
+
+-int __pmac pmac_get_partition(int partition)
++int pmac_get_partition(int partition)
+ {
+ return nvram_partitions[partition];
+ }
+
+-u8 __pmac pmac_xpram_read(int xpaddr)
++u8 pmac_xpram_read(int xpaddr)
+ {
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+@@ -569,7 +569,7 @@ u8 __pmac pmac_xpram_read(int xpaddr)
+ return ppc_md.nvram_read_val(xpaddr + offset);
+ }
+
+-void __pmac pmac_xpram_write(int xpaddr, u8 data)
++void pmac_xpram_write(int xpaddr, u8 data)
+ {
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
+--- a/arch/ppc/platforms/pmac_pci.c
++++ b/arch/ppc/platforms/pmac_pci.c
+@@ -141,7 +141,7 @@ fixup_bus_range(struct device_node *brid
+ |(((unsigned long)(off)) & 0xFCUL) \
+ |1UL)
+
+-static void volatile __iomem * __pmac
++static void volatile __iomem *
+ macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
+ {
+ unsigned int caddr;
+@@ -162,7 +162,7 @@ macrisc_cfg_access(struct pci_controller
+ return hose->cfg_data + offset;
+ }
+
+-static int __pmac
++static int
+ macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+ {
+@@ -190,7 +190,7 @@ macrisc_read_config(struct pci_bus *bus,
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+-static int __pmac
++static int
+ macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+ {
+@@ -230,7 +230,7 @@ static struct pci_ops macrisc_pci_ops =
+ /*
+ * Verifiy that a specific (bus, dev_fn) exists on chaos
+ */
+-static int __pmac
++static int
+ chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
+ {
+ struct device_node *np;
+@@ -252,7 +252,7 @@ chaos_validate_dev(struct pci_bus *bus,
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+-static int __pmac
++static int
+ chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+ {
+@@ -264,7 +264,7 @@ chaos_read_config(struct pci_bus *bus, u
+ return macrisc_read_config(bus, devfn, offset, len, val);
+ }
+
+-static int __pmac
++static int
+ chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+ {
+@@ -294,7 +294,7 @@ static struct pci_ops chaos_pci_ops =
+ + (((unsigned long)bus) << 16) \
+ + 0x01000000UL)
+
+-static void volatile __iomem * __pmac
++static void volatile __iomem *
+ u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset)
+ {
+ if (bus == hose->first_busno) {
+@@ -307,7 +307,7 @@ u3_ht_cfg_access(struct pci_controller*
+ return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
+ }
+
+-static int __pmac
++static int
+ u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+ {
+@@ -357,7 +357,7 @@ u3_ht_read_config(struct pci_bus *bus, u
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+-static int __pmac
++static int
+ u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+ {
+@@ -575,7 +575,7 @@ pmac_find_bridges(void)
+ * some offset between bus number and domains for now when we
+ * assign all busses should help for now
+ */
+- if (pci_assign_all_busses)
++ if (pci_assign_all_buses)
+ pcibios_assign_bus_offset = 0x10;
+
+ #ifdef CONFIG_POWER4
+@@ -643,7 +643,7 @@ static inline void grackle_set_loop_snoo
+ static int __init
+ setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
+ {
+- pci_assign_all_busses = 1;
++ pci_assign_all_buses = 1;
+ has_uninorth = 1;
+ hose->ops = ¯isc_pci_ops;
+ hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+@@ -677,7 +677,7 @@ setup_u3_agp(struct pci_controller* hose
+ {
+ /* On G5, we move AGP up to high bus number so we don't need
+ * to reassign bus numbers for HT. If we ever have P2P bridges
+- * on AGP, we'll have to move pci_assign_all_busses to the
++ * on AGP, we'll have to move pci_assign_all_buses to the
+ * pci_controller structure so we enable it for AGP and not for
+ * HT childs.
+ * We hard code the address because of the different size of
+@@ -899,7 +899,7 @@ pmac_pcibios_fixup(void)
+ pcibios_fixup_OF_interrupts();
+ }
+
+-int __pmac
++int
+ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+ {
+ struct device_node* node;
+@@ -1096,7 +1096,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_
+ * Disable second function on K2-SATA, it's broken
+ * and disable IO BARs on first one
+ */
+-void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev)
++void pmac_pci_fixup_k2_sata(struct pci_dev* dev)
+ {
+ int i;
+ u16 cmd;
+diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c
+--- a/arch/ppc/platforms/pmac_pic.c
++++ b/arch/ppc/platforms/pmac_pic.c
+@@ -35,6 +35,7 @@
+ #include <asm/open_pic.h>
+ #include <asm/xmon.h>
+ #include <asm/pmac_feature.h>
++#include <asm/machdep.h>
+
+ #include "pmac_pic.h"
+
+@@ -53,7 +54,7 @@ struct pmac_irq_hw {
+ };
+
+ /* Default addresses */
+-static volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmacdata = {
++static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
+ (struct pmac_irq_hw *) 0xf3000020,
+ (struct pmac_irq_hw *) 0xf3000010,
+ (struct pmac_irq_hw *) 0xf4000020,
+@@ -64,22 +65,22 @@ static volatile struct pmac_irq_hw *pmac
+ #define OHARE_LEVEL_MASK 0x1ff00000
+ #define HEATHROW_LEVEL_MASK 0x1ff00000
+
+-static int max_irqs __pmacdata;
+-static int max_real_irqs __pmacdata;
+-static u32 level_mask[4] __pmacdata;
++static int max_irqs;
++static int max_real_irqs;
++static u32 level_mask[4];
+
+-static DEFINE_SPINLOCK(pmac_pic_lock __pmacdata);
++static DEFINE_SPINLOCK(pmac_pic_lock);
+
+
+ #define GATWICK_IRQ_POOL_SIZE 10
+-static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE] __pmacdata;
++static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
+
+ /*
+ * Mark an irq as "lost". This is only used on the pmac
+ * since it can lose interrupts (see pmac_set_irq_mask).
+ * -- Cort
+ */
+-void __pmac
++void
+ __set_lost(unsigned long irq_nr, int nokick)
+ {
+ if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
+@@ -89,7 +90,7 @@ __set_lost(unsigned long irq_nr, int nok
+ }
+ }
+
+-static void __pmac
++static void
+ pmac_mask_and_ack_irq(unsigned int irq_nr)
+ {
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+@@ -114,7 +115,7 @@ pmac_mask_and_ack_irq(unsigned int irq_n
+ spin_unlock_irqrestore(&pmac_pic_lock, flags);
+ }
+
+-static void __pmac pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
++static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
+ {
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+@@ -147,7 +148,7 @@ static void __pmac pmac_set_irq_mask(uns
+ /* When an irq gets requested for the first client, if it's an
+ * edge interrupt, we clear any previous one on the controller
+ */
+-static unsigned int __pmac pmac_startup_irq(unsigned int irq_nr)
++static unsigned int pmac_startup_irq(unsigned int irq_nr)
+ {
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+@@ -160,20 +161,20 @@ static unsigned int __pmac pmac_startup_
+ return 0;
+ }
+
+-static void __pmac pmac_mask_irq(unsigned int irq_nr)
++static void pmac_mask_irq(unsigned int irq_nr)
+ {
+ clear_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr, 0);
+ mb();
+ }
+
+-static void __pmac pmac_unmask_irq(unsigned int irq_nr)
++static void pmac_unmask_irq(unsigned int irq_nr)
+ {
+ set_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr, 0);
+ }
+
+-static void __pmac pmac_end_irq(unsigned int irq_nr)
++static void pmac_end_irq(unsigned int irq_nr)
+ {
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+ && irq_desc[irq_nr].action) {
+diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
+--- a/arch/ppc/platforms/pmac_setup.c
++++ b/arch/ppc/platforms/pmac_setup.c
+@@ -122,7 +122,7 @@ extern struct smp_ops_t psurge_smp_ops;
+ extern struct smp_ops_t core99_smp_ops;
+ #endif /* CONFIG_SMP */
+
+-static int __pmac
++static int
+ pmac_show_cpuinfo(struct seq_file *m)
+ {
+ struct device_node *np;
+@@ -226,7 +226,7 @@ pmac_show_cpuinfo(struct seq_file *m)
+ return 0;
+ }
+
+-static int __openfirmware
++static int
+ pmac_show_percpuinfo(struct seq_file *m, int i)
+ {
+ #ifdef CONFIG_CPU_FREQ_PMAC
+@@ -330,9 +330,9 @@ pmac_setup_arch(void)
+ #ifdef CONFIG_SMP
+ /* Check for Core99 */
+ if (find_devices("uni-n") || find_devices("u3"))
+- ppc_md.smp_ops = &core99_smp_ops;
++ smp_ops = &core99_smp_ops;
+ else
+- ppc_md.smp_ops = &psurge_smp_ops;
++ smp_ops = &psurge_smp_ops;
+ #endif /* CONFIG_SMP */
+
+ pci_create_OF_bus_map();
+@@ -447,7 +447,7 @@ static int pmac_pm_enter(suspend_state_t
+ enable_kernel_fp();
+
+ #ifdef CONFIG_ALTIVEC
+- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
++ if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+ enable_kernel_altivec();
+ #endif /* CONFIG_ALTIVEC */
+
+@@ -485,7 +485,7 @@ static int pmac_late_init(void)
+ late_initcall(pmac_late_init);
+
+ /* can't be __init - can be called whenever a disk is first accessed */
+-void __pmac
++void
+ note_bootable_part(dev_t dev, int part, int goodness)
+ {
+ static int found_boot = 0;
+@@ -511,7 +511,7 @@ note_bootable_part(dev_t dev, int part,
+ }
+ }
+
+-static void __pmac
++static void
+ pmac_restart(char *cmd)
+ {
+ #ifdef CONFIG_ADB_CUDA
+@@ -536,7 +536,7 @@ pmac_restart(char *cmd)
+ }
+ }
+
+-static void __pmac
++static void
+ pmac_power_off(void)
+ {
+ #ifdef CONFIG_ADB_CUDA
+@@ -561,7 +561,7 @@ pmac_power_off(void)
+ }
+ }
+
+-static void __pmac
++static void
+ pmac_halt(void)
+ {
+ pmac_power_off();
+@@ -661,7 +661,6 @@ pmac_init(unsigned long r3, unsigned lon
+ ppc_md.setup_arch = pmac_setup_arch;
+ ppc_md.show_cpuinfo = pmac_show_cpuinfo;
+ ppc_md.show_percpuinfo = pmac_show_percpuinfo;
+- ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = pmac_pic_init;
+ ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */
+
+diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S
+--- a/arch/ppc/platforms/pmac_sleep.S
++++ b/arch/ppc/platforms/pmac_sleep.S
+@@ -387,10 +387,10 @@ turn_on_mmu:
+ #endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
+
+ .section .data
+- .balign L1_CACHE_LINE_SIZE
++ .balign L1_CACHE_BYTES
+ sleep_storage:
+ .long 0
+- .balign L1_CACHE_LINE_SIZE, 0
++ .balign L1_CACHE_BYTES, 0
+
+ #endif /* CONFIG_6xx */
+ .section .text
+diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
+--- a/arch/ppc/platforms/pmac_smp.c
++++ b/arch/ppc/platforms/pmac_smp.c
+@@ -186,7 +186,7 @@ static inline void psurge_clr_ipi(int cp
+ */
+ static unsigned long psurge_smp_message[NR_CPUS];
+
+-void __pmac psurge_smp_message_recv(struct pt_regs *regs)
++void psurge_smp_message_recv(struct pt_regs *regs)
+ {
+ int cpu = smp_processor_id();
+ int msg;
+@@ -203,14 +203,13 @@ void __pmac psurge_smp_message_recv(stru
+ smp_message_recv(msg, regs);
+ }
+
+-irqreturn_t __pmac psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
++irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
+ {
+ psurge_smp_message_recv(regs);
+ return IRQ_HANDLED;
+ }
+
+-static void __pmac smp_psurge_message_pass(int target, int msg, unsigned long data,
+- int wait)
++static void smp_psurge_message_pass(int target, int msg)
+ {
+ int i;
+
+@@ -629,7 +628,7 @@ void smp_core99_give_timebase(void)
+
+
+ /* PowerSurge-style Macs */
+-struct smp_ops_t psurge_smp_ops __pmacdata = {
++struct smp_ops_t psurge_smp_ops = {
+ .message_pass = smp_psurge_message_pass,
+ .probe = smp_psurge_probe,
+ .kick_cpu = smp_psurge_kick_cpu,
+@@ -639,7 +638,7 @@ struct smp_ops_t psurge_smp_ops __pmacda
+ };
+
+ /* Core99 Macs (dual G4s) */
+-struct smp_ops_t core99_smp_ops __pmacdata = {
++struct smp_ops_t core99_smp_ops = {
+ .message_pass = smp_openpic_message_pass,
+ .probe = smp_core99_probe,
+ .kick_cpu = smp_core99_kick_cpu,
+diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c
+--- a/arch/ppc/platforms/pmac_time.c
++++ b/arch/ppc/platforms/pmac_time.c
+@@ -77,7 +77,7 @@ pmac_time_init(void)
+ #endif
+ }
+
+-unsigned long __pmac
++unsigned long
+ pmac_get_rtc_time(void)
+ {
+ #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+@@ -118,7 +118,7 @@ pmac_get_rtc_time(void)
+ return 0;
+ }
+
+-int __pmac
++int
+ pmac_set_rtc_time(unsigned long nowtime)
+ {
+ #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+@@ -210,7 +210,7 @@ via_calibrate_decr(void)
+ /*
+ * Reset the time after a sleep.
+ */
+-static int __pmac
++static int
+ time_sleep_notify(struct pmu_sleep_notifier *self, int when)
+ {
+ static unsigned long time_diff;
+@@ -235,7 +235,7 @@ time_sleep_notify(struct pmu_sleep_notif
+ return PBOOK_SLEEP_OK;
+ }
+
+-static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = {
++static struct pmu_sleep_notifier time_sleep_notifier = {
+ time_sleep_notify, SLEEP_LEVEL_MISC,
+ };
+ #endif /* CONFIG_PM */
+diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
+--- a/arch/ppc/platforms/pplus.c
++++ b/arch/ppc/platforms/pplus.c
+@@ -646,14 +646,6 @@ static void pplus_power_off(void)
+ pplus_halt();
+ }
+
+-static unsigned int pplus_irq_canonicalize(u_int irq)
+-{
+- if (irq == 2)
+- return 9;
+- else
+- return irq;
+-}
+-
+ static void __init pplus_init_IRQ(void)
+ {
+ int i;
+@@ -673,10 +665,7 @@ static void __init pplus_init_IRQ(void)
+ ppc_md.get_irq = openpic_get_irq;
+ }
+
+- for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+- irq_desc[i].handler = &i8259_pic;
+-
+- i8259_init(0);
++ i8259_init(0, 0);
+
+ if (ppc_md.progress)
+ ppc_md.progress("init_irq: exit", 0);
+@@ -872,10 +861,10 @@ platform_init(unsigned long r3, unsigned
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
++ ppc_do_canonicalize_irqs = 1;
+
+ ppc_md.setup_arch = pplus_setup_arch;
+ ppc_md.show_cpuinfo = pplus_show_cpuinfo;
+- ppc_md.irq_canonicalize = pplus_irq_canonicalize;
+ ppc_md.init_IRQ = pplus_init_IRQ;
+ /* this gets changed later on if we have an OpenPIC -- Cort */
+ ppc_md.get_irq = i8259_irq;
+@@ -911,6 +900,6 @@ platform_init(unsigned long r3, unsigned
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+ #endif
+ #ifdef CONFIG_SMP
+- ppc_md.smp_ops = &pplus_smp_ops;
++ smp_ops = &pplus_smp_ops;
+ #endif /* CONFIG_SMP */
+ }
+diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c
+--- a/arch/ppc/platforms/prep_pci.c
++++ b/arch/ppc/platforms/prep_pci.c
+@@ -43,7 +43,7 @@ static unsigned long *ProcInfo;
+ /* Tables for known hardware */
+
+ /* Motorola PowerStackII - Utah */
+-static char Utah_pci_IRQ_map[23] __prepdata =
++static char Utah_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -72,7 +72,7 @@ static char Utah_pci_IRQ_map[23] __prepd
+ 0, /* Slot 22 - unused */
+ };
+
+-static char Utah_pci_IRQ_routes[] __prepdata =
++static char Utah_pci_IRQ_routes[] =
+ {
+ 0, /* Line 0 - Unused */
+ 9, /* Line 1 */
+@@ -84,7 +84,7 @@ static char Utah_pci_IRQ_routes[] __prep
+
+ /* Motorola PowerStackII - Omaha */
+ /* no integrated SCSI or ethernet */
+-static char Omaha_pci_IRQ_map[23] __prepdata =
++static char Omaha_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -111,7 +111,7 @@ static char Omaha_pci_IRQ_map[23] __prep
+ 0,
+ };
+
+-static char Omaha_pci_IRQ_routes[] __prepdata =
++static char Omaha_pci_IRQ_routes[] =
+ {
+ 0, /* Line 0 - Unused */
+ 9, /* Line 1 */
+@@ -121,7 +121,7 @@ static char Omaha_pci_IRQ_routes[] __pre
+ };
+
+ /* Motorola PowerStack */
+-static char Blackhawk_pci_IRQ_map[19] __prepdata =
++static char Blackhawk_pci_IRQ_map[19] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -144,7 +144,7 @@ static char Blackhawk_pci_IRQ_map[19] __
+ 3, /* Slot P5 */
+ };
+
+-static char Blackhawk_pci_IRQ_routes[] __prepdata =
++static char Blackhawk_pci_IRQ_routes[] =
+ {
+ 0, /* Line 0 - Unused */
+ 9, /* Line 1 */
+@@ -154,7 +154,7 @@ static char Blackhawk_pci_IRQ_routes[] _
+ };
+
+ /* Motorola Mesquite */
+-static char Mesquite_pci_IRQ_map[23] __prepdata =
++static char Mesquite_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -182,7 +182,7 @@ static char Mesquite_pci_IRQ_map[23] __p
+ };
+
+ /* Motorola Sitka */
+-static char Sitka_pci_IRQ_map[21] __prepdata =
++static char Sitka_pci_IRQ_map[21] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -208,7 +208,7 @@ static char Sitka_pci_IRQ_map[21] __prep
+ };
+
+ /* Motorola MTX */
+-static char MTX_pci_IRQ_map[23] __prepdata =
++static char MTX_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -237,7 +237,7 @@ static char MTX_pci_IRQ_map[23] __prepda
+
+ /* Motorola MTX Plus */
+ /* Secondary bus interrupt routing is not supported yet */
+-static char MTXplus_pci_IRQ_map[23] __prepdata =
++static char MTXplus_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -264,13 +264,13 @@ static char MTXplus_pci_IRQ_map[23] __pr
+ 0, /* Slot 22 - unused */
+ };
+
+-static char Raven_pci_IRQ_routes[] __prepdata =
++static char Raven_pci_IRQ_routes[] =
+ {
+ 0, /* This is a dummy structure */
+ };
+
+ /* Motorola MVME16xx */
+-static char Genesis_pci_IRQ_map[16] __prepdata =
++static char Genesis_pci_IRQ_map[16] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -290,7 +290,7 @@ static char Genesis_pci_IRQ_map[16] __pr
+ 0, /* Slot 15 - unused */
+ };
+
+-static char Genesis_pci_IRQ_routes[] __prepdata =
++static char Genesis_pci_IRQ_routes[] =
+ {
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+@@ -299,7 +299,7 @@ static char Genesis_pci_IRQ_routes[] __p
+ 15 /* Line 4 */
+ };
+
+-static char Genesis2_pci_IRQ_map[23] __prepdata =
++static char Genesis2_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -327,7 +327,7 @@ static char Genesis2_pci_IRQ_map[23] __p
+ };
+
+ /* Motorola Series-E */
+-static char Comet_pci_IRQ_map[23] __prepdata =
++static char Comet_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -354,7 +354,7 @@ static char Comet_pci_IRQ_map[23] __prep
+ 0,
+ };
+
+-static char Comet_pci_IRQ_routes[] __prepdata =
++static char Comet_pci_IRQ_routes[] =
+ {
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+@@ -364,7 +364,7 @@ static char Comet_pci_IRQ_routes[] __pre
+ };
+
+ /* Motorola Series-EX */
+-static char Comet2_pci_IRQ_map[23] __prepdata =
++static char Comet2_pci_IRQ_map[23] =
+ {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+@@ -391,7 +391,7 @@ static char Comet2_pci_IRQ_map[23] __pre
+ 0,
+ };
+
+-static char Comet2_pci_IRQ_routes[] __prepdata =
++static char Comet2_pci_IRQ_routes[] =
+ {
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+@@ -405,7 +405,7 @@ static char Comet2_pci_IRQ_routes[] __pr
+ * This is actually based on the Carolina motherboard
+ * -- Cort
+ */
+-static char ibm8xx_pci_IRQ_map[23] __prepdata = {
++static char ibm8xx_pci_IRQ_map[23] = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+@@ -431,7 +431,7 @@ static char ibm8xx_pci_IRQ_map[23] __pre
+ 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+ };
+
+-static char ibm8xx_pci_IRQ_routes[] __prepdata = {
++static char ibm8xx_pci_IRQ_routes[] = {
+ 0, /* Line 0 - unused */
+ 15, /* Line 1 */
+ 15, /* Line 2 */
+@@ -443,7 +443,7 @@ static char ibm8xx_pci_IRQ_routes[] __pr
+ * a 6015 ibm board
+ * -- Cort
+ */
+-static char ibm6015_pci_IRQ_map[23] __prepdata = {
++static char ibm6015_pci_IRQ_map[23] = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+@@ -469,7 +469,7 @@ static char ibm6015_pci_IRQ_map[23] __pr
+ 2, /* Slot 22 - */
+ };
+
+-static char ibm6015_pci_IRQ_routes[] __prepdata = {
++static char ibm6015_pci_IRQ_routes[] = {
+ 0, /* Line 0 - unused */
+ 13, /* Line 1 */
+ 15, /* Line 2 */
+@@ -479,7 +479,7 @@ static char ibm6015_pci_IRQ_routes[] __p
+
+
+ /* IBM Nobis and Thinkpad 850 */
+-static char Nobis_pci_IRQ_map[23] __prepdata ={
++static char Nobis_pci_IRQ_map[23] ={
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+@@ -498,7 +498,7 @@ static char Nobis_pci_IRQ_map[23] __prep
+ 0, /* Slot 15 - unused */
+ };
+
+-static char Nobis_pci_IRQ_routes[] __prepdata = {
++static char Nobis_pci_IRQ_routes[] = {
+ 0, /* Line 0 - Unused */
+ 13, /* Line 1 */
+ 13, /* Line 2 */
+@@ -510,7 +510,7 @@ static char Nobis_pci_IRQ_routes[] __pre
+ * IBM RS/6000 43p/140 -- paulus
+ * XXX we should get all this from the residual data
+ */
+-static char ibm43p_pci_IRQ_map[23] __prepdata = {
++static char ibm43p_pci_IRQ_map[23] = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+@@ -536,7 +536,7 @@ static char ibm43p_pci_IRQ_map[23] __pre
+ 1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+ };
+
+-static char ibm43p_pci_IRQ_routes[] __prepdata = {
++static char ibm43p_pci_IRQ_routes[] = {
+ 0, /* Line 0 - unused */
+ 15, /* Line 1 */
+ 15, /* Line 2 */
+@@ -559,7 +559,7 @@ struct powerplus_irq_list
+ * are routed to OpenPIC inputs 5-8. These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+-struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
++struct powerplus_irq_list Powerplus_pci_IRQ_list =
+ {
+ {25, 26, 27, 28},
+ {21, 22, 23, 24}
+@@ -572,7 +572,7 @@ struct powerplus_irq_list Powerplus_pci_
+ * are routed to OpenPIC inputs 12-15. These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+-struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
++struct powerplus_irq_list Mesquite_pci_IRQ_list =
+ {
+ {24, 25, 26, 27},
+ {28, 29, 30, 31}
+@@ -582,7 +582,7 @@ struct powerplus_irq_list Mesquite_pci_I
+ * This table represents the standard PCI swizzle defined in the
+ * PCI bus specification.
+ */
+-static unsigned char prep_pci_intpins[4][4] __prepdata =
++static unsigned char prep_pci_intpins[4][4] =
+ {
+ { 1, 2, 3, 4}, /* Buses 0, 4, 8, ... */
+ { 2, 3, 4, 1}, /* Buses 1, 5, 9, ... */
+@@ -622,7 +622,7 @@ static unsigned char prep_pci_intpins[4]
+ #define MIN_DEVNR 11
+ #define MAX_DEVNR 22
+
+-static int __prep
++static int
+ prep_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+ {
+@@ -652,7 +652,7 @@ prep_read_config(struct pci_bus *bus, un
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+-static int __prep
++static int
+ prep_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+ {
+@@ -804,7 +804,7 @@ struct mot_info {
+ void (*map_non0_bus)(struct pci_dev *); /* For boards with more than bus 0 devices. */
+ struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */
+ unsigned char secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */
+-} mot_info[] __prepdata = {
++} mot_info[] = {
+ {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+ {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+ {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes, NULL, NULL, 0x00},
+diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
+--- a/arch/ppc/platforms/prep_setup.c
++++ b/arch/ppc/platforms/prep_setup.c
+@@ -89,9 +89,6 @@ extern void prep_tiger1_setup_pci(char *
+ #define cached_21 (((char *)(ppc_cached_irq_mask))[3])
+ #define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
+
+-/* for the mac fs */
+-dev_t boot_dev;
+-
+ #ifdef CONFIG_SOUND_CS4232
+ long ppc_cs4232_dma, ppc_cs4232_dma2;
+ #endif
+@@ -173,7 +170,7 @@ prep_carolina_enable_l2(void)
+ }
+
+ /* cpuinfo code common to all IBM PReP */
+-static void __prep
++static void
+ prep_ibm_cpuinfo(struct seq_file *m)
+ {
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+@@ -209,14 +206,14 @@ prep_ibm_cpuinfo(struct seq_file *m)
+ }
+ }
+
+-static int __prep
++static int
+ prep_gen_cpuinfo(struct seq_file *m)
+ {
+ prep_ibm_cpuinfo(m);
+ return 0;
+ }
+
+-static int __prep
++static int
+ prep_sandalfoot_cpuinfo(struct seq_file *m)
+ {
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+@@ -243,7 +240,7 @@ prep_sandalfoot_cpuinfo(struct seq_file
+ return 0;
+ }
+
+-static int __prep
++static int
+ prep_thinkpad_cpuinfo(struct seq_file *m)
+ {
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+@@ -314,7 +311,7 @@ prep_thinkpad_cpuinfo(struct seq_file *m
+ return 0;
+ }
+
+-static int __prep
++static int
+ prep_carolina_cpuinfo(struct seq_file *m)
+ {
+ unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
+@@ -350,7 +347,7 @@ prep_carolina_cpuinfo(struct seq_file *m
+ return 0;
+ }
+
+-static int __prep
++static int
+ prep_tiger1_cpuinfo(struct seq_file *m)
+ {
+ unsigned int l2_reg = inb(PREP_IBM_L2INFO);
+@@ -393,7 +390,7 @@ prep_tiger1_cpuinfo(struct seq_file *m)
+
+
+ /* Used by all Motorola PReP */
+-static int __prep
++static int
+ prep_mot_cpuinfo(struct seq_file *m)
+ {
+ unsigned int cachew = *((unsigned char *)CACHECRBA);
+@@ -454,7 +451,7 @@ no_l2:
+ return 0;
+ }
+
+-static void __prep
++static void
+ prep_restart(char *cmd)
+ {
+ #define PREP_SP92 0x92 /* Special Port 92 */
+@@ -473,7 +470,7 @@ prep_restart(char *cmd)
+ #undef PREP_SP92
+ }
+
+-static void __prep
++static void
+ prep_halt(void)
+ {
+ local_irq_disable(); /* no interrupts */
+@@ -488,7 +485,7 @@ prep_halt(void)
+ /* Carrera is the power manager in the Thinkpads. Unfortunately not much is
+ * known about it, so we can't power down.
+ */
+-static void __prep
++static void
+ prep_carrera_poweroff(void)
+ {
+ prep_halt();
+@@ -501,7 +498,7 @@ prep_carrera_poweroff(void)
+ * somewhat in the IBM Carolina Technical Specification.
+ * -Hollis
+ */
+-static void __prep
++static void
+ utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
+ {
+ /*
+@@ -539,7 +536,7 @@ utah_sig87c750_setbit(unsigned int byten
+ udelay(100); /* important: let controller recover */
+ }
+
+-static void __prep
++static void
+ prep_sig750_poweroff(void)
+ {
+ /* tweak the power manager found in most IBM PRePs (except Thinkpads) */
+@@ -554,7 +551,7 @@ prep_sig750_poweroff(void)
+ /* not reached */
+ }
+
+-static int __prep
++static int
+ prep_show_percpuinfo(struct seq_file *m, int i)
+ {
+ /* PREP's without residual data will give incorrect values here */
+@@ -700,12 +697,12 @@ prep_set_bat(void)
+ /*
+ * IBM 3-digit status LED
+ */
+-static unsigned int ibm_statusled_base __prepdata;
++static unsigned int ibm_statusled_base;
+
+-static void __prep
++static void
+ ibm_statusled_progress(char *s, unsigned short hex);
+
+-static int __prep
++static int
+ ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2,
+ void * dummy3)
+ {
+@@ -713,13 +710,13 @@ ibm_statusled_panic(struct notifier_bloc
+ return NOTIFY_DONE;
+ }
+
+-static struct notifier_block ibm_statusled_block __prepdata = {
++static struct notifier_block ibm_statusled_block = {
+ ibm_statusled_panic,
+ NULL,
+ INT_MAX /* try to do it first */
+ };
+
+-static void __prep
++static void
+ ibm_statusled_progress(char *s, unsigned short hex)
+ {
+ static int notifier_installed;
+@@ -945,19 +942,6 @@ prep_calibrate_decr(void)
+ todc_calibrate_decr();
+ }
+
+-static unsigned int __prep
+-prep_irq_canonicalize(u_int irq)
+-{
+- if (irq == 2)
+- {
+- return 9;
+- }
+- else
+- {
+- return irq;
+- }
+-}
+-
+ static void __init
+ prep_init_IRQ(void)
+ {
+@@ -970,11 +954,9 @@ prep_init_IRQ(void)
+ openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ i8259_irq);
+ }
+- for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
+- irq_desc[i].handler = &i8259_pic;
+
+ if (have_residual_data) {
+- i8259_init(residual_isapic_addr());
++ i8259_init(residual_isapic_addr(), 0);
+ return;
+ }
+
+@@ -985,18 +967,18 @@ prep_init_IRQ(void)
+ if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA)
+ && ((pci_did == PCI_DEVICE_ID_MOTOROLA_RAVEN)
+ || (pci_did == PCI_DEVICE_ID_MOTOROLA_HAWK)))
+- i8259_init(0);
++ i8259_init(0, 0);
+ else
+ /* PCI interrupt ack address given in section 6.1.8 of the
+ * PReP specification. */
+- i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR);
++ i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR, 0);
+ }
+
+ #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ /*
+ * IDE stuff.
+ */
+-static int __prep
++static int
+ prep_ide_default_irq(unsigned long base)
+ {
+ switch (base) {
+@@ -1010,7 +992,7 @@ prep_ide_default_irq(unsigned long base)
+ }
+ }
+
+-static unsigned long __prep
++static unsigned long
+ prep_ide_default_io_base(int index)
+ {
+ switch (index) {
+@@ -1055,7 +1037,7 @@ smp_prep_setup_cpu(int cpu_nr)
+ do_openpic_setup_cpu();
+ }
+
+-static struct smp_ops_t prep_smp_ops __prepdata = {
++static struct smp_ops_t prep_smp_ops = {
+ smp_openpic_message_pass,
+ smp_prep_probe,
+ smp_prep_kick_cpu,
+@@ -1113,6 +1095,7 @@ prep_init(unsigned long r3, unsigned lon
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
++ ppc_do_canonicalize_irqs = 1;
+
+ /* figure out what kind of prep workstation we are */
+ if (have_residual_data) {
+@@ -1139,7 +1122,6 @@ prep_init(unsigned long r3, unsigned lon
+ ppc_md.setup_arch = prep_setup_arch;
+ ppc_md.show_percpuinfo = prep_show_percpuinfo;
+ ppc_md.show_cpuinfo = NULL; /* set in prep_setup_arch() */
+- ppc_md.irq_canonicalize = prep_irq_canonicalize;
+ ppc_md.init_IRQ = prep_init_IRQ;
+ /* this gets changed later on if we have an OpenPIC -- Cort */
+ ppc_md.get_irq = i8259_irq;
+@@ -1176,6 +1158,6 @@ prep_init(unsigned long r3, unsigned lon
+ #endif
+
+ #ifdef CONFIG_SMP
+- ppc_md.smp_ops = &prep_smp_ops;
++ smp_ops = &prep_smp_ops;
+ #endif /* CONFIG_SMP */
+ }
+diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
+--- a/arch/ppc/platforms/radstone_ppc7d.c
++++ b/arch/ppc/platforms/radstone_ppc7d.c
+@@ -40,6 +40,7 @@
+ #include <linux/serial_core.h>
+ #include <linux/mv643xx.h>
+ #include <linux/netdevice.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -514,13 +515,9 @@ static void __init ppc7d_init_irq(void)
+ int irq;
+
+ pr_debug("%s\n", __FUNCTION__);
+- i8259_init(0);
++ i8259_init(0, 0);
+ mv64360_init_irq();
+
+- /* IRQ 0..15 are handled by the cascaded 8259's of the Ali1535 */
+- for (irq = 0; irq < 16; irq++) {
+- irq_desc[irq].handler = &i8259_pic;
+- }
+ /* IRQs 5,6,9,10,11,14,15 are level sensitive */
+ irq_desc[5].status |= IRQ_LEVEL;
+ irq_desc[6].status |= IRQ_LEVEL;
+@@ -1183,18 +1180,18 @@ static void __init ppc7d_setup_arch(void
+ ROOT_DEV = Root_HDA1;
+ #endif
+
+- if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) ||
+- (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
++ if ((cur_cpu_spec->cpu_features & CPU_FTR_SPEC7450) ||
++ (cur_cpu_spec->cpu_features & CPU_FTR_L3CR))
+ /* 745x is different. We only want to pass along enable. */
+ _set_L2CR(L2CR_L2E);
+- else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
++ else if (cur_cpu_spec->cpu_features & CPU_FTR_L2CR)
+ /* All modules have 1MB of L2. We also assume that an
+ * L2 divisor of 3 will work.
+ */
+ _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+ | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+
+- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR)
++ if (cur_cpu_spec->cpu_features & CPU_FTR_L3CR)
+ /* No L3 cache */
+ _set_L3CR(0);
+
+@@ -1424,6 +1421,7 @@ void __init platform_init(unsigned long
+ ppc_md.setup_arch = ppc7d_setup_arch;
+ ppc_md.init = ppc7d_init2;
+ ppc_md.show_cpuinfo = ppc7d_show_cpuinfo;
++ /* XXX this is broken... */
+ ppc_md.irq_canonicalize = ppc7d_irq_canonicalize;
+ ppc_md.init_IRQ = ppc7d_init_irq;
+ ppc_md.get_irq = ppc7d_get_irq;
+diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
+--- a/arch/ppc/platforms/residual.c
++++ b/arch/ppc/platforms/residual.c
+@@ -47,7 +47,7 @@
+ #include <asm/ide.h>
+
+
+-unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
++unsigned char __res[sizeof(RESIDUAL)] = {0,};
+ RESIDUAL *res = (RESIDUAL *)&__res;
+
+ char * PnP_BASE_TYPES[] __initdata = {
+diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
+--- a/arch/ppc/platforms/sandpoint.c
++++ b/arch/ppc/platforms/sandpoint.c
+@@ -494,27 +494,10 @@ sandpoint_init_IRQ(void)
+ i8259_irq);
+
+ /*
+- * openpic_init() has set up irq_desc[16-31] to be openpic
+- * interrupts. We need to set irq_desc[0-15] to be i8259
+- * interrupts.
+- */
+- for(i=0; i < NUM_8259_INTERRUPTS; i++)
+- irq_desc[i].handler = &i8259_pic;
+-
+- /*
+ * The EPIC allows for a read in the range of 0xFEF00000 ->
+ * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+ */
+- i8259_init(0xfef00000);
+-}
+-
+-static u32
+-sandpoint_irq_canonicalize(u32 irq)
+-{
+- if (irq == 2)
+- return 9;
+- else
+- return irq;
++ i8259_init(0xfef00000, 0);
+ }
+
+ static unsigned long __init
+@@ -727,10 +710,10 @@ platform_init(unsigned long r3, unsigned
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
++ ppc_do_canonicalize_irqs = 1;
+
+ ppc_md.setup_arch = sandpoint_setup_arch;
+ ppc_md.show_cpuinfo = sandpoint_show_cpuinfo;
+- ppc_md.irq_canonicalize = sandpoint_irq_canonicalize;
+ ppc_md.init_IRQ = sandpoint_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
+--- a/arch/ppc/syslib/Makefile
++++ b/arch/ppc/syslib/Makefile
+@@ -31,52 +31,49 @@ obj-$(CONFIG_GEN_RTC) += todc_time.o
+ obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o
+ obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o
+ ifeq ($(CONFIG_40x),y)
+-obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o
++obj-$(CONFIG_PCI) += pci_auto.o ppc405_pci.o
+ endif
+ endif
+ obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
+ ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
+-ifeq ($(CONFIG_8xx),y)
+-obj-$(CONFIG_PCI) += qspan_pci.o i8259.o
+-endif
+-obj-$(CONFIG_PPC_OF) += prom_init.o prom.o of_device.o
+-obj-$(CONFIG_PPC_PMAC) += open_pic.o indirect_pci.o
++obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o
++obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
++obj-$(CONFIG_PPC_PMAC) += open_pic.o
+ obj-$(CONFIG_POWER4) += open_pic2.o
+-obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o
+-obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o
+-obj-$(CONFIG_BAMBOO) += indirect_pci.o pci_auto.o todc_time.o
++obj-$(CONFIG_PPC_CHRP) += open_pic.o
++obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o
++obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
+ obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
+-obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o
++obj-$(CONFIG_EBONY) += pci_auto.o todc_time.o
+ obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o
+ obj-$(CONFIG_CHESTNUT) += mv64360_pic.o pci_auto.o
+-obj-$(CONFIG_GEMINI) += open_pic.o indirect_pci.o
++obj-$(CONFIG_GEMINI) += open_pic.o
+ obj-$(CONFIG_GT64260) += gt64260_pic.o
+-obj-$(CONFIG_LOPEC) += i8259.o pci_auto.o todc_time.o
++obj-$(CONFIG_LOPEC) += pci_auto.o todc_time.o
+ obj-$(CONFIG_HDPU) += pci_auto.o
+-obj-$(CONFIG_LUAN) += indirect_pci.o pci_auto.o todc_time.o
++obj-$(CONFIG_LUAN) += pci_auto.o todc_time.o
+ obj-$(CONFIG_KATANA) += pci_auto.o
+ obj-$(CONFIG_MV64360) += mv64360_pic.o
+-obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o indirect_pci.o
+-obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \
++obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o
++obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o \
+ pci_auto.o hawk_common.o
+-obj-$(CONFIG_MVME5100_IPMC761_PRESENT) += i8259.o
+-obj-$(CONFIG_OCOTEA) += indirect_pci.o pci_auto.o todc_time.o
++obj-$(CONFIG_OCOTEA) += pci_auto.o todc_time.o
+ obj-$(CONFIG_PAL4) += cpc700_pic.o
+ obj-$(CONFIG_POWERPMC250) += pci_auto.o
+-obj-$(CONFIG_PPLUS) += hawk_common.o open_pic.o i8259.o \
+- indirect_pci.o todc_time.o pci_auto.o
+-obj-$(CONFIG_PRPMC750) += open_pic.o indirect_pci.o pci_auto.o \
++obj-$(CONFIG_PPLUS) += hawk_common.o open_pic.o \
++ todc_time.o pci_auto.o
++obj-$(CONFIG_PRPMC750) += open_pic.o pci_auto.o \
+ hawk_common.o
+ obj-$(CONFIG_HARRIER) += harrier.o
+-obj-$(CONFIG_PRPMC800) += open_pic.o indirect_pci.o pci_auto.o
+-obj-$(CONFIG_RADSTONE_PPC7D) += i8259.o pci_auto.o
+-obj-$(CONFIG_SANDPOINT) += i8259.o pci_auto.o todc_time.o
++obj-$(CONFIG_PRPMC800) += open_pic.o pci_auto.o
++obj-$(CONFIG_RADSTONE_PPC7D) += pci_auto.o
++obj-$(CONFIG_SANDPOINT) += pci_auto.o todc_time.o
+ obj-$(CONFIG_SBC82xx) += todc_time.o
+-obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
++obj-$(CONFIG_SPRUCE) += cpc700_pic.o pci_auto.o \
+ todc_time.o
+ obj-$(CONFIG_8260) += m8260_setup.o pq2_devices.o pq2_sys.o \
+ ppc_sys.o
+-obj-$(CONFIG_PCI_8260) += m82xx_pci.o indirect_pci.o pci_auto.o
++obj-$(CONFIG_PCI_8260) += m82xx_pci.o pci_auto.o
+ obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
+ obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
+ ifeq ($(CONFIG_PPC_GEN550),y)
+@@ -87,20 +84,18 @@ ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y)
+ obj-$(CONFIG_SERIAL_TEXT_DEBUG) += mv64x60_dbg.o
+ endif
+ obj-$(CONFIG_BOOTX_TEXT) += btext.o
+-obj-$(CONFIG_MPC10X_BRIDGE) += mpc10x_common.o indirect_pci.o ppc_sys.o
++obj-$(CONFIG_MPC10X_BRIDGE) += mpc10x_common.o ppc_sys.o
+ obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o
+-obj-$(CONFIG_40x) += dcr.o
+-obj-$(CONFIG_BOOKE) += dcr.o
+ obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
+- ppc_sys.o i8259.o mpc85xx_sys.o \
++ ppc_sys.o mpc85xx_sys.o \
+ mpc85xx_devices.o
+ ifeq ($(CONFIG_85xx),y)
+-obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
++obj-$(CONFIG_PCI) += pci_auto.o
+ endif
+ obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \
+ mpc83xx_sys.o mpc83xx_devices.o
+ ifeq ($(CONFIG_83xx),y)
+-obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
++obj-$(CONFIG_PCI) += pci_auto.o
+ endif
+ obj-$(CONFIG_MPC8548_CDS) += todc_time.o
+ obj-$(CONFIG_MPC8555_CDS) += todc_time.o
+diff --git a/arch/ppc/syslib/btext.c b/arch/ppc/syslib/btext.c
+--- a/arch/ppc/syslib/btext.c
++++ b/arch/ppc/syslib/btext.c
+@@ -53,8 +53,8 @@ extern char *klimit;
+ * chrp only uses it during early boot.
+ */
+ #ifdef CONFIG_XMON
+-#define BTEXT __pmac
+-#define BTDATA __pmacdata
++#define BTEXT
++#define BTDATA
+ #else
+ #define BTEXT __init
+ #define BTDATA __initdata
+@@ -187,7 +187,7 @@ btext_setup_display(int width, int heigh
+ * changes.
+ */
+
+-void __openfirmware
++void
+ map_boot_text(void)
+ {
+ unsigned long base, offset, size;
+diff --git a/arch/ppc/syslib/dcr.S b/arch/ppc/syslib/dcr.S
+deleted file mode 100644
+--- a/arch/ppc/syslib/dcr.S
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/*
+- * arch/ppc/syslib/dcr.S
+- *
+- * "Indirect" DCR access
+- *
+- * Copyright (c) 2004 Eugene Surovegin <ebs at 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 <asm/ppc_asm.h>
+-#include <asm/processor.h>
+-
+-#define DCR_ACCESS_PROLOG(table) \
+- rlwinm r3,r3,4,18,27; \
+- lis r5,table at h; \
+- ori r5,r5,table at l; \
+- add r3,r3,r5; \
+- mtctr r3; \
+- bctr
+-
+-_GLOBAL(__mfdcr)
+- DCR_ACCESS_PROLOG(__mfdcr_table)
+-
+-_GLOBAL(__mtdcr)
+- DCR_ACCESS_PROLOG(__mtdcr_table)
+-
+-__mfdcr_table:
+- mfdcr r3,0; blr
+-__mtdcr_table:
+- mtdcr 0,r4; blr
+-
+-dcr = 1
+- .rept 1023
+- mfdcr r3,dcr; blr
+- mtdcr dcr,r4; blr
+- dcr = dcr + 1
+- .endr
+diff --git a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c
+--- a/arch/ppc/syslib/gt64260_pic.c
++++ b/arch/ppc/syslib/gt64260_pic.c
+@@ -45,6 +45,7 @@
+ #include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/mv64x60.h>
++#include <asm/machdep.h>
+
+ #define CPU_INTR_STR "gt64260 cpu interface error"
+ #define PCI0_INTR_STR "gt64260 pci 0 error"
+diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c
+deleted file mode 100644
+--- a/arch/ppc/syslib/i8259.c
++++ /dev/null
+@@ -1,208 +0,0 @@
+-#include <linux/init.h>
+-#include <linux/ioport.h>
+-#include <linux/interrupt.h>
+-#include <asm/io.h>
+-#include <asm/i8259.h>
+-
+-static volatile unsigned char *pci_intack; /* RO, gives us the irq vector */
+-
+-unsigned char cached_8259[2] = { 0xff, 0xff };
+-#define cached_A1 (cached_8259[0])
+-#define cached_21 (cached_8259[1])
+-
+-static DEFINE_SPINLOCK(i8259_lock);
+-
+-int i8259_pic_irq_offset;
+-
+-/*
+- * Acknowledge the IRQ using either the PCI host bridge's interrupt
+- * acknowledge feature or poll. How i8259_init() is called determines
+- * which is called. It should be noted that polling is broken on some
+- * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
+- */
+-int
+-i8259_irq(struct pt_regs *regs)
+-{
+- int irq;
+-
+- spin_lock(&i8259_lock);
+-
+- /* Either int-ack or poll for the IRQ */
+- if (pci_intack)
+- irq = *pci_intack;
+- else {
+- /* Perform an interrupt acknowledge cycle on controller 1. */
+- outb(0x0C, 0x20); /* prepare for poll */
+- irq = inb(0x20) & 7;
+- if (irq == 2 ) {
+- /*
+- * Interrupt is cascaded so perform interrupt
+- * acknowledge on controller 2.
+- */
+- outb(0x0C, 0xA0); /* prepare for poll */
+- irq = (inb(0xA0) & 7) + 8;
+- }
+- }
+-
+- if (irq == 7) {
+- /*
+- * This may be a spurious interrupt.
+- *
+- * Read the interrupt status register (ISR). If the most
+- * significant bit is not set then there is no valid
+- * interrupt.
+- */
+- if (!pci_intack)
+- outb(0x0B, 0x20); /* ISR register */
+- if(~inb(0x20) & 0x80)
+- irq = -1;
+- }
+-
+- spin_unlock(&i8259_lock);
+- return irq;
+-}
+-
+-static void i8259_mask_and_ack_irq(unsigned int irq_nr)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- if ( irq_nr >= i8259_pic_irq_offset )
+- irq_nr -= i8259_pic_irq_offset;
+-
+- if (irq_nr > 7) {
+- cached_A1 |= 1 << (irq_nr-8);
+- inb(0xA1); /* DUMMY */
+- outb(cached_A1,0xA1);
+- outb(0x20,0xA0); /* Non-specific EOI */
+- outb(0x20,0x20); /* Non-specific EOI to cascade */
+- } else {
+- cached_21 |= 1 << irq_nr;
+- inb(0x21); /* DUMMY */
+- outb(cached_21,0x21);
+- outb(0x20,0x20); /* Non-specific EOI */
+- }
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-}
+-
+-static void i8259_set_irq_mask(int irq_nr)
+-{
+- outb(cached_A1,0xA1);
+- outb(cached_21,0x21);
+-}
+-
+-static void i8259_mask_irq(unsigned int irq_nr)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- if ( irq_nr >= i8259_pic_irq_offset )
+- irq_nr -= i8259_pic_irq_offset;
+- if ( irq_nr < 8 )
+- cached_21 |= 1 << irq_nr;
+- else
+- cached_A1 |= 1 << (irq_nr-8);
+- i8259_set_irq_mask(irq_nr);
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-}
+-
+-static void i8259_unmask_irq(unsigned int irq_nr)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- if ( irq_nr >= i8259_pic_irq_offset )
+- irq_nr -= i8259_pic_irq_offset;
+- if ( irq_nr < 8 )
+- cached_21 &= ~(1 << irq_nr);
+- else
+- cached_A1 &= ~(1 << (irq_nr-8));
+- i8259_set_irq_mask(irq_nr);
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-}
+-
+-static void i8259_end_irq(unsigned int irq)
+-{
+- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+- && irq_desc[irq].action)
+- i8259_unmask_irq(irq);
+-}
+-
+-struct hw_interrupt_type i8259_pic = {
+- .typename = " i8259 ",
+- .enable = i8259_unmask_irq,
+- .disable = i8259_mask_irq,
+- .ack = i8259_mask_and_ack_irq,
+- .end = i8259_end_irq,
+-};
+-
+-static struct resource pic1_iores = {
+- .name = "8259 (master)",
+- .start = 0x20,
+- .end = 0x21,
+- .flags = IORESOURCE_BUSY,
+-};
+-
+-static struct resource pic2_iores = {
+- .name = "8259 (slave)",
+- .start = 0xa0,
+- .end = 0xa1,
+- .flags = IORESOURCE_BUSY,
+-};
+-
+-static struct resource pic_edgectrl_iores = {
+- .name = "8259 edge control",
+- .start = 0x4d0,
+- .end = 0x4d1,
+- .flags = IORESOURCE_BUSY,
+-};
+-
+-static struct irqaction i8259_irqaction = {
+- .handler = no_action,
+- .flags = SA_INTERRUPT,
+- .mask = CPU_MASK_NONE,
+- .name = "82c59 secondary cascade",
+-};
+-
+-/*
+- * i8259_init()
+- * intack_addr - PCI interrupt acknowledge (real) address which will return
+- * the active irq from the 8259
+- */
+-void __init
+-i8259_init(long intack_addr)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- /* init master interrupt controller */
+- outb(0x11, 0x20); /* Start init sequence */
+- outb(0x00, 0x21); /* Vector base */
+- outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+- outb(0x01, 0x21); /* Select 8086 mode */
+-
+- /* init slave interrupt controller */
+- outb(0x11, 0xA0); /* Start init sequence */
+- outb(0x08, 0xA1); /* Vector base */
+- outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+- outb(0x01, 0xA1); /* Select 8086 mode */
+-
+- /* always read ISR */
+- outb(0x0B, 0x20);
+- outb(0x0B, 0xA0);
+-
+- /* Mask all interrupts */
+- outb(cached_A1, 0xA1);
+- outb(cached_21, 0x21);
+-
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-
+- /* reserve our resources */
+- setup_irq( i8259_pic_irq_offset + 2, &i8259_irqaction);
+- request_resource(&ioport_resource, &pic1_iores);
+- request_resource(&ioport_resource, &pic2_iores);
+- request_resource(&ioport_resource, &pic_edgectrl_iores);
+-
+- if (intack_addr != 0)
+- pci_intack = ioremap(intack_addr, 1);
+-}
+diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
+--- a/arch/ppc/syslib/ibm440gx_common.c
++++ b/arch/ppc/syslib/ibm440gx_common.c
+@@ -236,9 +236,9 @@ void __init ibm440gx_l2c_setup(struct ib
+ /* Disable L2C on rev.A, rev.B and 800MHz version of rev.C,
+ enable it on all other revisions
+ */
+- if (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. A") == 0 ||
+- strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. B") == 0
+- || (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. C")
++ if (strcmp(cur_cpu_spec->cpu_name, "440GX Rev. A") == 0 ||
++ strcmp(cur_cpu_spec->cpu_name, "440GX Rev. B") == 0
++ || (strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C")
+ == 0 && p->cpu > 667000000))
+ ibm440gx_l2c_disable();
+ else
+diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
+--- a/arch/ppc/syslib/ibm44x_common.c
++++ b/arch/ppc/syslib/ibm44x_common.c
+@@ -27,9 +27,14 @@
+ #include <asm/time.h>
+ #include <asm/ppc4xx_pic.h>
+ #include <asm/param.h>
++#include <asm/bootinfo.h>
++#include <asm/ppcboot.h>
+
+ #include <syslib/gen550.h>
+
++/* Global Variables */
++bd_t __res;
++
+ phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
+ {
+ phys_addr_t page_4gb = 0;
+@@ -150,8 +155,36 @@ static unsigned long __init ibm44x_find_
+ return mem_size;
+ }
+
+-void __init ibm44x_platform_init(void)
++void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++ unsigned long r6, unsigned long r7)
+ {
++ parse_bootinfo(find_bootinfo());
++
++ /*
++ * If we were passed in a board information, copy it into the
++ * residual data area.
++ */
++ if (r3)
++ __res = *(bd_t *)(r3 + KERNELBASE);
++
++#if defined(CONFIG_BLK_DEV_INITRD)
++ /*
++ * If the init RAM disk has been configured in, and there's a valid
++ * starting address for it, set it up.
++ */
++ if (r4) {
++ initrd_start = r4 + KERNELBASE;
++ initrd_end = r5 + KERNELBASE;
++ }
++#endif /* CONFIG_BLK_DEV_INITRD */
++
++ /* Copy the kernel command line arguments to a safe place. */
++
++ if (r6) {
++ *(char *) (r7 + KERNELBASE) = 0;
++ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
++ }
++
+ ppc_md.init_IRQ = ppc4xx_pic_init;
+ ppc_md.find_end_of_memory = ibm44x_find_end_of_memory;
+ ppc_md.restart = ibm44x_restart;
+@@ -178,7 +211,7 @@ void __init ibm44x_platform_init(void)
+ #endif
+ }
+
+-/* Called from MachineCheckException */
++/* Called from machine_check_exception */
+ void platform_machine_check(struct pt_regs *regs)
+ {
+ printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x\n",
+diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h
+--- a/arch/ppc/syslib/ibm44x_common.h
++++ b/arch/ppc/syslib/ibm44x_common.h
+@@ -36,7 +36,8 @@ struct ibm44x_clocks {
+ };
+
+ /* common 44x platform init */
+-void ibm44x_platform_init(void) __init;
++void ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++ unsigned long r6, unsigned long r7) __init;
+
+ /* initialize decrementer and tick-related variables */
+ void ibm44x_calibrate_decr(unsigned int freq) __init;
+diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
+deleted file mode 100644
+--- a/arch/ppc/syslib/indirect_pci.c
++++ /dev/null
+@@ -1,134 +0,0 @@
+-/*
+- * Support for indirect PCI bridges.
+- *
+- * Copyright (C) 1998 Gabriel Paubert.
+- *
+- * 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/kernel.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/machdep.h>
+-
+-#ifdef CONFIG_PPC_INDIRECT_PCI_BE
+-#define PCI_CFG_OUT out_be32
+-#else
+-#define PCI_CFG_OUT out_le32
+-#endif
+-
+-static int
+-indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+- int len, u32 *val)
+-{
+- struct pci_controller *hose = bus->sysdata;
+- volatile void __iomem *cfg_data;
+- u8 cfg_type = 0;
+-
+- if (ppc_md.pci_exclude_device)
+- if (ppc_md.pci_exclude_device(bus->number, devfn))
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- if (hose->set_cfg_type)
+- if (bus->number != hose->first_busno)
+- cfg_type = 1;
+-
+- PCI_CFG_OUT(hose->cfg_addr,
+- (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+- | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+-
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- cfg_data = hose->cfg_data + (offset & 3);
+- switch (len) {
+- case 1:
+- *val = in_8(cfg_data);
+- break;
+- case 2:
+- *val = in_le16(cfg_data);
+- break;
+- default:
+- *val = in_le32(cfg_data);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static int
+-indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+- int len, u32 val)
+-{
+- struct pci_controller *hose = bus->sysdata;
+- volatile void __iomem *cfg_data;
+- u8 cfg_type = 0;
+-
+- if (ppc_md.pci_exclude_device)
+- if (ppc_md.pci_exclude_device(bus->number, devfn))
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- if (hose->set_cfg_type)
+- if (bus->number != hose->first_busno)
+- cfg_type = 1;
+-
+- PCI_CFG_OUT(hose->cfg_addr,
+- (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+- | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+-
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- cfg_data = hose->cfg_data + (offset & 3);
+- switch (len) {
+- case 1:
+- out_8(cfg_data, val);
+- break;
+- case 2:
+- out_le16(cfg_data, val);
+- break;
+- default:
+- out_le32(cfg_data, val);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops indirect_pci_ops =
+-{
+- indirect_read_config,
+- indirect_write_config
+-};
+-
+-void __init
+-setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+- void __iomem * cfg_data)
+-{
+- hose->cfg_addr = cfg_addr;
+- hose->cfg_data = cfg_data;
+- hose->ops = &indirect_pci_ops;
+-}
+-
+-void __init
+-setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+-{
+- unsigned long base = cfg_addr & PAGE_MASK;
+- void __iomem *mbase, *addr, *data;
+-
+- mbase = ioremap(base, PAGE_SIZE);
+- addr = mbase + (cfg_addr & ~PAGE_MASK);
+- if ((cfg_data & PAGE_MASK) != base)
+- mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+- data = mbase + (cfg_data & ~PAGE_MASK);
+- setup_indirect_pci_nomap(hose, addr, data);
+-}
+diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
+--- a/arch/ppc/syslib/m8260_setup.c
++++ b/arch/ppc/syslib/m8260_setup.c
+@@ -62,6 +62,10 @@ m8260_setup_arch(void)
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ #endif
++
++ identify_ppc_sys_by_name_and_id(BOARD_CHIP_NAME,
++ in_be32(CPM_MAP_ADDR + CPM_IMMR_OFFSET));
++
+ m82xx_board_setup();
+ }
+
+diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c
+--- a/arch/ppc/syslib/m82xx_pci.c
++++ b/arch/ppc/syslib/m82xx_pci.c
+@@ -302,11 +302,11 @@ pq2ads_setup_pci(struct pci_controller *
+
+ void __init pq2_find_bridges(void)
+ {
+- extern int pci_assign_all_busses;
++ extern int pci_assign_all_buses;
+ struct pci_controller * hose;
+ int host_bridge;
+
+- pci_assign_all_busses = 1;
++ pci_assign_all_buses = 1;
+
+ hose = pcibios_alloc_controller();
+
+diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
+--- a/arch/ppc/syslib/m8xx_setup.c
++++ b/arch/ppc/syslib/m8xx_setup.c
+@@ -144,12 +144,12 @@ void __init m8xx_calibrate_decr(void)
+ int freq, fp, divisor;
+
+ /* Unlock the SCCR. */
+- ((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = ~KAPWR_KEY;
+- ((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = KAPWR_KEY;
++ out_be32(&((immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk, ~KAPWR_KEY);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk, KAPWR_KEY);
+
+ /* Force all 8xx processors to use divide by 16 processor clock. */
+- ((volatile immap_t *)IMAP_ADDR)->im_clkrst.car_sccr |= 0x02000000;
+-
++ out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr,
++ in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr)|0x02000000);
+ /* Processor frequency is MHz.
+ * The value 'fp' is the number of decrementer ticks per second.
+ */
+@@ -175,28 +175,24 @@ void __init m8xx_calibrate_decr(void)
+ * we guarantee the registers are locked, then we unlock them
+ * for our use.
+ */
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = ~KAPWR_KEY;
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = ~KAPWR_KEY;
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = ~KAPWR_KEY;
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk = KAPWR_KEY;
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk, ~KAPWR_KEY);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck, ~KAPWR_KEY);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, ~KAPWR_KEY);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk, KAPWR_KEY);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck, KAPWR_KEY);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, KAPWR_KEY);
+
+ /* Disable the RTC one second and alarm interrupts. */
+- ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
+- ~(RTCSC_SIE | RTCSC_ALE);
++ out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE));
+ /* Enable the RTC */
+- ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc |=
+- (RTCSC_RTF | RTCSC_RTE);
++ out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE));
+
+ /* Enabling the decrementer also enables the timebase interrupts
+ * (or from the other point of view, to get decrementer interrupts
+ * we have to enable the timebase). The decrementer interrupt
+ * is wired into the vector table, nothing to do here for that.
+ */
+- ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
+- ((mk_int_int_mask(DEC_INTERRUPT) << 8) |
+- (TBSCR_TBF | TBSCR_TBE));
++ out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_tbscr, (mk_int_int_mask(DEC_INTERRUPT) << 8) | (TBSCR_TBF | TBSCR_TBE));
+
+ if (setup_irq(DEC_INTERRUPT, &tbint_irqaction))
+ panic("Could not allocate timer IRQ!");
+@@ -216,9 +212,9 @@ void __init m8xx_calibrate_decr(void)
+ static int
+ m8xx_set_rtc_time(unsigned long time)
+ {
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
+- ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
+- ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck, KAPWR_KEY);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtc, time);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck, ~KAPWR_KEY);
+ return(0);
+ }
+
+@@ -226,7 +222,7 @@ static unsigned long
+ m8xx_get_rtc_time(void)
+ {
+ /* Get time from the RTC. */
+- return((unsigned long)(((immap_t *)IMAP_ADDR)->im_sit.sit_rtc));
++ return (unsigned long) in_be32(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtc);
+ }
+
+ static void
+@@ -235,13 +231,13 @@ m8xx_restart(char *cmd)
+ __volatile__ unsigned char dummy;
+
+ local_irq_disable();
+- ((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080;
++ out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr) | 0x00000080);
+
+ /* Clear the ME bit in MSR to cause checkstop on machine check
+ */
+ mtmsr(mfmsr() & ~0x1000);
+
+- dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
++ dummy = in_8(&((immap_t *)IMAP_ADDR)->im_clkrst.res[0]);
+ printk("Restart failed\n");
+ while(1);
+ }
+@@ -306,8 +302,7 @@ m8xx_init_IRQ(void)
+ i8259_init(0);
+
+ /* The i8259 cascade interrupt must be level sensitive. */
+- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel &=
+- ~(0x80000000 >> ISA_BRIDGE_INT);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, in_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel & ~(0x80000000 >> ISA_BRIDGE_INT)));
+
+ if (setup_irq(ISA_BRIDGE_INT, &mbx_i8259_irqaction))
+ enable_irq(ISA_BRIDGE_INT);
+@@ -404,9 +399,10 @@ platform_init(unsigned long r3, unsigned
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
++ identify_ppc_sys_by_name(BOARD_CHIP_NAME);
++
+ ppc_md.setup_arch = m8xx_setup_arch;
+ ppc_md.show_percpuinfo = m8xx_show_percpuinfo;
+- ppc_md.irq_canonicalize = NULL;
+ ppc_md.init_IRQ = m8xx_init_IRQ;
+ ppc_md.get_irq = m8xx_get_irq;
+ ppc_md.init = NULL;
+diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
+--- a/arch/ppc/syslib/m8xx_wdt.c
++++ b/arch/ppc/syslib/m8xx_wdt.c
+@@ -29,8 +29,8 @@ void m8xx_wdt_reset(void)
+ {
+ volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+
+- imap->im_siu_conf.sc_swsr = 0x556c; /* write magic1 */
+- imap->im_siu_conf.sc_swsr = 0xaa39; /* write magic2 */
++ out_be16(imap->im_siu_conf.sc_swsr, 0x556c); /* write magic1 */
++ out_be16(imap->im_siu_conf.sc_swsr, 0xaa39); /* write magic2 */
+ }
+
+ static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs)
+@@ -39,7 +39,7 @@ static irqreturn_t m8xx_wdt_interrupt(in
+
+ m8xx_wdt_reset();
+
+- imap->im_sit.sit_piscr |= PISCR_PS; /* clear irq */
++ out_be16(imap->im_sit.sit_piscr, in_be16(imap->im_sit.sit_piscr | PISCR_PS)); /* clear irq */
+
+ return IRQ_HANDLED;
+ }
+@@ -51,7 +51,7 @@ void __init m8xx_wdt_handler_install(bd_
+ u32 sypcr;
+ u32 pitrtclk;
+
+- sypcr = imap->im_siu_conf.sc_sypcr;
++ sypcr = in_be32(imap->im_siu_conf.sc_sypcr);
+
+ if (!(sypcr & 0x04)) {
+ printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
+@@ -87,9 +87,9 @@ void __init m8xx_wdt_handler_install(bd_
+ else
+ pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2;
+
+- imap->im_sit.sit_pitc = pitc << 16;
+- imap->im_sit.sit_piscr =
+- (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE;
++ out_be32(imap->im_sit.sit_pitc, pitc << 16);
++
++ out_be16(imap->im_sit.sit_piscr, (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE);
+
+ if (setup_irq(PIT_INTERRUPT, &m8xx_wdt_irqaction))
+ panic("m8xx_wdt: error setting up the watchdog irq!");
+diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c
+--- a/arch/ppc/syslib/mpc52xx_devices.c
++++ b/arch/ppc/syslib/mpc52xx_devices.c
+@@ -15,6 +15,7 @@
+
+ #include <linux/fsl_devices.h>
+ #include <linux/resource.h>
++#include <linux/platform_device.h>
+ #include <asm/mpc52xx.h>
+ #include <asm/ppc_sys.h>
+
+diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
+--- a/arch/ppc/syslib/mpc52xx_pci.c
++++ b/arch/ppc/syslib/mpc52xx_pci.c
+@@ -21,6 +21,7 @@
+ #include "mpc52xx_pci.h"
+
+ #include <asm/delay.h>
++#include <asm/machdep.h>
+
+
+ static int
+@@ -181,7 +182,7 @@ mpc52xx_find_bridges(void)
+ struct mpc52xx_pci __iomem *pci_regs;
+ struct pci_controller *hose;
+
+- pci_assign_all_busses = 1;
++ pci_assign_all_buses = 1;
+
+ pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
+ if (!pci_regs)
+diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
+--- a/arch/ppc/syslib/mpc83xx_devices.c
++++ b/arch/ppc/syslib/mpc83xx_devices.c
+@@ -21,6 +21,7 @@
+ #include <asm/mpc83xx.h>
+ #include <asm/irq.h>
+ #include <asm/ppc_sys.h>
++#include <asm/machdep.h>
+
+ /* We use offsets for IORESOURCE_MEM since we do not know at compile time
+ * what IMMRBAR is, will get fixed up by mach_mpc83xx_fixup
+diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
+--- a/arch/ppc/syslib/mpc85xx_devices.c
++++ b/arch/ppc/syslib/mpc85xx_devices.c
+@@ -25,19 +25,20 @@
+ /* We use offsets for IORESOURCE_MEM since we do not know at compile time
+ * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
+ */
++struct gianfar_mdio_data mpc85xx_mdio_pdata = {
++ .paddr = MPC85xx_MIIM_OFFSET,
++};
+
+ static struct gianfar_platform_data mpc85xx_tsec1_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+- .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+ };
+
+ static struct gianfar_platform_data mpc85xx_tsec2_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+- .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+ };
+
+ static struct gianfar_platform_data mpc85xx_etsec1_pdata = {
+@@ -46,7 +47,6 @@ static struct gianfar_platform_data mpc8
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+- .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+ };
+
+ static struct gianfar_platform_data mpc85xx_etsec2_pdata = {
+@@ -55,7 +55,6 @@ static struct gianfar_platform_data mpc8
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+- .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+ };
+
+ static struct gianfar_platform_data mpc85xx_etsec3_pdata = {
+@@ -64,7 +63,6 @@ static struct gianfar_platform_data mpc8
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+- .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+ };
+
+ static struct gianfar_platform_data mpc85xx_etsec4_pdata = {
+@@ -73,11 +71,10 @@ static struct gianfar_platform_data mpc8
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+- .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+ };
+
+ static struct gianfar_platform_data mpc85xx_fec_pdata = {
+- .phy_reg_addr = MPC85xx_ENET1_OFFSET,
++ .device_flags = 0,
+ };
+
+ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c_pdata = {
+@@ -719,6 +716,12 @@ struct platform_device ppc_sys_platform_
+ },
+ },
+ },
++ [MPC85xx_MDIO] = {
++ .name = "fsl-gianfar_mdio",
++ .id = 0,
++ .dev.platform_data = &mpc85xx_mdio_pdata,
++ .num_resources = 0,
++ },
+ };
+
+ static int __init mach_mpc85xx_fixup(struct platform_device *pdev)
+diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c
+--- a/arch/ppc/syslib/mpc85xx_sys.c
++++ b/arch/ppc/syslib/mpc85xx_sys.c
+@@ -24,19 +24,19 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ .ppc_sys_name = "8540",
+ .mask = 0xFFFF0000,
+ .value = 0x80300000,
+- .num_devices = 10,
++ .num_devices = 11,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_FEC, MPC85xx_IIC1,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+- MPC85xx_PERFMON, MPC85xx_DUART,
++ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8560",
+ .mask = 0xFFFF0000,
+ .value = 0x80700000,
+- .num_devices = 19,
++ .num_devices = 20,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+@@ -45,14 +45,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
+ MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3, MPC85xx_CPM_SCC4,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+- MPC85xx_CPM_MCC1, MPC85xx_CPM_MCC2,
++ MPC85xx_CPM_MCC1, MPC85xx_CPM_MCC2, MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8541",
+ .mask = 0xFFFF0000,
+ .value = 0x80720000,
+- .num_devices = 13,
++ .num_devices = 14,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+@@ -60,13 +60,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8541E",
+ .mask = 0xFFFF0000,
+ .value = 0x807A0000,
+- .num_devices = 14,
++ .num_devices = 15,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+@@ -74,13 +75,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+ MPC85xx_CPM_SPI, MPC85xx_CPM_I2C,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8555",
+ .mask = 0xFFFF0000,
+ .value = 0x80710000,
+- .num_devices = 19,
++ .num_devices = 20,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+@@ -91,13 +93,14 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+ MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
+ MPC85xx_CPM_USB,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8555E",
+ .mask = 0xFFFF0000,
+ .value = 0x80790000,
+- .num_devices = 20,
++ .num_devices = 21,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
+@@ -108,6 +111,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+ MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
+ MPC85xx_CPM_USB,
++ MPC85xx_MDIO,
+ },
+ },
+ /* SVRs on 8548 rev1.0 matches for 8548/8547/8545 */
+@@ -115,104 +119,112 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ .ppc_sys_name = "8548E",
+ .mask = 0xFFFF00F0,
+ .value = 0x80390010,
+- .num_devices = 13,
++ .num_devices = 14,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8548",
+ .mask = 0xFFFF00F0,
+ .value = 0x80310010,
+- .num_devices = 12,
++ .num_devices = 13,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8547E",
+ .mask = 0xFFFF00F0,
+ .value = 0x80390010,
+- .num_devices = 13,
++ .num_devices = 14,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8547",
+ .mask = 0xFFFF00F0,
+ .value = 0x80310010,
+- .num_devices = 12,
++ .num_devices = 13,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8545E",
+ .mask = 0xFFFF00F0,
+ .value = 0x80390010,
+- .num_devices = 11,
++ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8545",
+ .mask = 0xFFFF00F0,
+ .value = 0x80310010,
+- .num_devices = 10,
++ .num_devices = 11,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8543E",
+ .mask = 0xFFFF00F0,
+ .value = 0x803A0010,
+- .num_devices = 11,
++ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
++ MPC85xx_MDIO,
+ },
+ },
+ {
+ .ppc_sys_name = "8543",
+ .mask = 0xFFFF00F0,
+ .value = 0x80320010,
+- .num_devices = 10,
++ .num_devices = 11,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
++ MPC85xx_MDIO,
+ },
+ },
+ { /* default match */
+diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c
+--- a/arch/ppc/syslib/mpc8xx_sys.c
++++ b/arch/ppc/syslib/mpc8xx_sys.c
+@@ -24,7 +24,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ .ppc_sys_name = "MPC86X",
+ .mask = 0xFFFFFFFF,
+ .value = 0x00000000,
+- .num_devices = 2,
++ .num_devices = 7,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC8xx_CPM_FEC1,
+@@ -40,7 +40,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+ .ppc_sys_name = "MPC885",
+ .mask = 0xFFFFFFFF,
+ .value = 0x00000000,
+- .num_devices = 3,
++ .num_devices = 8,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC8xx_CPM_FEC1,
+diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c
+--- a/arch/ppc/syslib/mv64360_pic.c
++++ b/arch/ppc/syslib/mv64360_pic.c
+@@ -48,6 +48,7 @@
+ #include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/mv64x60.h>
++#include <asm/machdep.h>
+
+ #ifdef CONFIG_IRQ_ALL_CPUS
+ #error "The mv64360 does not support distribution of IRQs on all CPUs"
+diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
+--- a/arch/ppc/syslib/mv64x60.c
++++ b/arch/ppc/syslib/mv64x60.c
+@@ -19,6 +19,7 @@
+ #include <linux/string.h>
+ #include <linux/spinlock.h>
+ #include <linux/mv643xx.h>
++#include <linux/platform_device.h>
+
+ #include <asm/byteorder.h>
+ #include <asm/io.h>
+@@ -1304,7 +1305,7 @@ mv64x60_config_pci_params(struct pci_con
+ early_write_config_word(hose, 0, devfn, PCI_COMMAND, u16_val);
+
+ /* Set latency timer, cache line size, clear BIST */
+- u16_val = (pi->latency_timer << 8) | (L1_CACHE_LINE_SIZE >> 2);
++ u16_val = (pi->latency_timer << 8) | (L1_CACHE_BYTES >> 2);
+ early_write_config_word(hose, 0, devfn, PCI_CACHE_LINE_SIZE, u16_val);
+
+ mv64x60_pci_exclude_bridge = save_exclude;
+diff --git a/arch/ppc/syslib/mv64x60_dbg.c b/arch/ppc/syslib/mv64x60_dbg.c
+--- a/arch/ppc/syslib/mv64x60_dbg.c
++++ b/arch/ppc/syslib/mv64x60_dbg.c
+@@ -24,6 +24,7 @@
+ #include <linux/irq.h>
+ #include <asm/delay.h>
+ #include <asm/mv64x60.h>
++#include <asm/machdep.h>
+
+
+ #if defined(CONFIG_SERIAL_TEXT_DEBUG)
+diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c
+deleted file mode 100644
+--- a/arch/ppc/syslib/of_device.c
++++ /dev/null
+@@ -1,276 +0,0 @@
+-#include <linux/config.h>
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/mod_devicetable.h>
+-#include <asm/errno.h>
+-#include <asm/of_device.h>
+-
+-/**
+- * of_match_device - Tell if an of_device structure has a matching
+- * of_match structure
+- * @ids: array of of device match structures to search in
+- * @dev: the of device structure to match against
+- *
+- * Used by a driver to check whether an of_device present in the
+- * system is in its list of supported devices.
+- */
+-const struct of_device_id * of_match_device(const struct of_device_id *matches,
+- const struct of_device *dev)
+-{
+- if (!dev->node)
+- return NULL;
+- while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+- int match = 1;
+- if (matches->name[0])
+- match &= dev->node->name
+- && !strcmp(matches->name, dev->node->name);
+- if (matches->type[0])
+- match &= dev->node->type
+- && !strcmp(matches->type, dev->node->type);
+- if (matches->compatible[0])
+- match &= device_is_compatible(dev->node,
+- matches->compatible);
+- if (match)
+- return matches;
+- matches++;
+- }
+- return NULL;
+-}
+-
+-static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+- const struct of_device_id * matches = of_drv->match_table;
+-
+- if (!matches)
+- return 0;
+-
+- return of_match_device(matches, of_dev) != NULL;
+-}
+-
+-struct of_device *of_dev_get(struct of_device *dev)
+-{
+- struct device *tmp;
+-
+- if (!dev)
+- return NULL;
+- tmp = get_device(&dev->dev);
+- if (tmp)
+- return to_of_device(tmp);
+- else
+- return NULL;
+-}
+-
+-void of_dev_put(struct of_device *dev)
+-{
+- if (dev)
+- put_device(&dev->dev);
+-}
+-
+-
+-static int of_device_probe(struct device *dev)
+-{
+- int error = -ENODEV;
+- struct of_platform_driver *drv;
+- struct of_device *of_dev;
+- const struct of_device_id *match;
+-
+- drv = to_of_platform_driver(dev->driver);
+- of_dev = to_of_device(dev);
+-
+- if (!drv->probe)
+- return error;
+-
+- of_dev_get(of_dev);
+-
+- match = of_match_device(drv->match_table, of_dev);
+- if (match)
+- error = drv->probe(of_dev, match);
+- if (error)
+- of_dev_put(of_dev);
+-
+- return error;
+-}
+-
+-static int of_device_remove(struct device *dev)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+-
+- if (dev->driver && drv->remove)
+- drv->remove(of_dev);
+- return 0;
+-}
+-
+-static int of_device_suspend(struct device *dev, pm_message_t state)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+- int error = 0;
+-
+- if (dev->driver && drv->suspend)
+- error = drv->suspend(of_dev, state);
+- return error;
+-}
+-
+-static int of_device_resume(struct device * dev)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+- int error = 0;
+-
+- if (dev->driver && drv->resume)
+- error = drv->resume(of_dev);
+- return error;
+-}
+-
+-struct bus_type of_platform_bus_type = {
+- .name = "of_platform",
+- .match = of_platform_bus_match,
+- .suspend = of_device_suspend,
+- .resume = of_device_resume,
+-};
+-
+-static int __init of_bus_driver_init(void)
+-{
+- return bus_register(&of_platform_bus_type);
+-}
+-
+-postcore_initcall(of_bus_driver_init);
+-
+-int of_register_driver(struct of_platform_driver *drv)
+-{
+- int count = 0;
+-
+- /* initialize common driver fields */
+- drv->driver.name = drv->name;
+- drv->driver.bus = &of_platform_bus_type;
+- drv->driver.probe = of_device_probe;
+- drv->driver.remove = of_device_remove;
+-
+- /* register with core */
+- count = driver_register(&drv->driver);
+- return count ? count : 1;
+-}
+-
+-void of_unregister_driver(struct of_platform_driver *drv)
+-{
+- driver_unregister(&drv->driver);
+-}
+-
+-
+-static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct of_device *ofdev;
+-
+- ofdev = to_of_device(dev);
+- return sprintf(buf, "%s", ofdev->node->full_name);
+-}
+-
+-static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+-
+-/**
+- * of_release_dev - free an of device structure when all users of it are finished.
+- * @dev: device that's been disconnected
+- *
+- * Will be called only by the device core when all users of this of device are
+- * done.
+- */
+-void of_release_dev(struct device *dev)
+-{
+- struct of_device *ofdev;
+-
+- ofdev = to_of_device(dev);
+- of_node_put(ofdev->node);
+- kfree(ofdev);
+-}
+-
+-int of_device_register(struct of_device *ofdev)
+-{
+- int rc;
+- struct of_device **odprop;
+-
+- BUG_ON(ofdev->node == NULL);
+-
+- odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
+- if (!odprop) {
+- struct property *new_prop;
+-
+- new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
+- GFP_KERNEL);
+- if (new_prop == NULL)
+- return -ENOMEM;
+- new_prop->name = "linux,device";
+- new_prop->length = sizeof(sizeof(struct of_device *));
+- new_prop->value = (unsigned char *)&new_prop[1];
+- odprop = (struct of_device **)new_prop->value;
+- *odprop = NULL;
+- prom_add_property(ofdev->node, new_prop);
+- }
+- *odprop = ofdev;
+-
+- rc = device_register(&ofdev->dev);
+- if (rc)
+- return rc;
+-
+- device_create_file(&ofdev->dev, &dev_attr_devspec);
+-
+- return 0;
+-}
+-
+-void of_device_unregister(struct of_device *ofdev)
+-{
+- struct of_device **odprop;
+-
+- device_remove_file(&ofdev->dev, &dev_attr_devspec);
+-
+- odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
+- if (odprop)
+- *odprop = NULL;
+-
+- device_unregister(&ofdev->dev);
+-}
+-
+-struct of_device* of_platform_device_create(struct device_node *np,
+- const char *bus_id,
+- struct device *parent)
+-{
+- struct of_device *dev;
+- u32 *reg;
+-
+- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+- if (!dev)
+- return NULL;
+- memset(dev, 0, sizeof(*dev));
+-
+- dev->node = of_node_get(np);
+- dev->dma_mask = 0xffffffffUL;
+- dev->dev.dma_mask = &dev->dma_mask;
+- dev->dev.parent = parent;
+- dev->dev.bus = &of_platform_bus_type;
+- dev->dev.release = of_release_dev;
+-
+- reg = (u32 *)get_property(np, "reg", NULL);
+- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+-
+- if (of_device_register(dev) != 0) {
+- kfree(dev);
+- return NULL;
+- }
+-
+- return dev;
+-}
+-
+-EXPORT_SYMBOL(of_match_device);
+-EXPORT_SYMBOL(of_platform_bus_type);
+-EXPORT_SYMBOL(of_register_driver);
+-EXPORT_SYMBOL(of_unregister_driver);
+-EXPORT_SYMBOL(of_device_register);
+-EXPORT_SYMBOL(of_device_unregister);
+-EXPORT_SYMBOL(of_dev_get);
+-EXPORT_SYMBOL(of_dev_put);
+-EXPORT_SYMBOL(of_platform_device_create);
+-EXPORT_SYMBOL(of_release_dev);
+diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
+--- a/arch/ppc/syslib/open_pic.c
++++ b/arch/ppc/syslib/open_pic.c
+@@ -23,6 +23,7 @@
+ #include <asm/sections.h>
+ #include <asm/open_pic.h>
+ #include <asm/i8259.h>
++#include <asm/machdep.h>
+
+ #include "open_pic_defs.h"
+
+@@ -889,7 +890,7 @@ openpic_get_irq(struct pt_regs *regs)
+
+ #ifdef CONFIG_SMP
+ void
+-smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
++smp_openpic_message_pass(int target, int msg)
+ {
+ cpumask_t mask = CPU_MASK_ALL;
+ /* make sure we're sending something that translates to an IPI */
+diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
+--- a/arch/ppc/syslib/open_pic2.c
++++ b/arch/ppc/syslib/open_pic2.c
+@@ -27,6 +27,7 @@
+ #include <asm/sections.h>
+ #include <asm/open_pic.h>
+ #include <asm/i8259.h>
++#include <asm/machdep.h>
+
+ #include "open_pic_defs.h"
+
+diff --git a/arch/ppc/syslib/ppc403_pic.c b/arch/ppc/syslib/ppc403_pic.c
+--- a/arch/ppc/syslib/ppc403_pic.c
++++ b/arch/ppc/syslib/ppc403_pic.c
+@@ -26,6 +26,7 @@
+ #include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/ppc4xx_pic.h>
++#include <asm/machdep.h>
+
+ /* Function Prototypes */
+
+diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
+--- a/arch/ppc/syslib/ppc4xx_pic.c
++++ b/arch/ppc/syslib/ppc4xx_pic.c
+@@ -25,6 +25,7 @@
+ #include <asm/system.h>
+ #include <asm/irq.h>
+ #include <asm/ppc4xx_pic.h>
++#include <asm/machdep.h>
+
+ /* See comment in include/arch-ppc/ppc4xx_pic.h
+ * for more info about these two variables
+diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
+--- a/arch/ppc/syslib/ppc4xx_setup.c
++++ b/arch/ppc/syslib/ppc4xx_setup.c
+@@ -278,7 +278,7 @@ ppc4xx_init(unsigned long r3, unsigned l
+ #endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */
+ }
+
+-/* Called from MachineCheckException */
++/* Called from machine_check_exception */
+ void platform_machine_check(struct pt_regs *regs)
+ {
+ #if defined(DCRN_PLB0_BEAR)
+diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
+--- a/arch/ppc/syslib/ppc83xx_setup.c
++++ b/arch/ppc/syslib/ppc83xx_setup.c
+@@ -40,6 +40,7 @@
+ #include <asm/ppc_sys.h>
+ #include <asm/kgdb.h>
+ #include <asm/delay.h>
++#include <asm/machdep.h>
+
+ #include <syslib/ppc83xx_setup.h>
+ #if defined(CONFIG_PCI)
+diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
+--- a/arch/ppc/syslib/ppc85xx_setup.c
++++ b/arch/ppc/syslib/ppc85xx_setup.c
+@@ -29,6 +29,7 @@
+ #include <asm/mmu.h>
+ #include <asm/ppc_sys.h>
+ #include <asm/kgdb.h>
++#include <asm/machdep.h>
+
+ #include <syslib/ppc85xx_setup.h>
+
+diff --git a/arch/ppc/syslib/ppc8xx_pic.c b/arch/ppc/syslib/ppc8xx_pic.c
+--- a/arch/ppc/syslib/ppc8xx_pic.c
++++ b/arch/ppc/syslib/ppc8xx_pic.c
+@@ -6,6 +6,7 @@
+ #include <linux/signal.h>
+ #include <linux/interrupt.h>
+ #include <asm/irq.h>
++#include <asm/io.h>
+ #include <asm/8xx_immap.h>
+ #include <asm/mpc8xx.h>
+ #include "ppc8xx_pic.h"
+@@ -29,8 +30,7 @@ static void m8xx_mask_irq(unsigned int i
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
+- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+- ppc_cached_irq_mask[word];
++ out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]);
+ }
+
+ static void m8xx_unmask_irq(unsigned int irq_nr)
+@@ -41,8 +41,7 @@ static void m8xx_unmask_irq(unsigned int
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] |= (1 << (31-bit));
+- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+- ppc_cached_irq_mask[word];
++ out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]);
+ }
+
+ static void m8xx_end_irq(unsigned int irq_nr)
+@@ -55,8 +54,7 @@ static void m8xx_end_irq(unsigned int ir
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] |= (1 << (31-bit));
+- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+- ppc_cached_irq_mask[word];
++ out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]);
+ }
+ }
+
+@@ -69,9 +67,8 @@ static void m8xx_mask_and_ack(unsigned i
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
+- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+- ppc_cached_irq_mask[word];
+- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]);
++ out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend, 1 << (31-bit));
+ }
+
+ struct hw_interrupt_type ppc8xx_pic = {
+@@ -93,7 +90,7 @@ m8xx_get_irq(struct pt_regs *regs)
+ /* For MPC8xx, read the SIVEC register and shift the bits down
+ * to get the irq number.
+ */
+- irq = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26;
++ irq = in_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec) >> 26;
+
+ /*
+ * When we read the sivec without an interrupt to process, we will
+diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
+--- a/arch/ppc/syslib/ppc_sys.c
++++ b/arch/ppc/syslib/ppc_sys.c
+@@ -69,6 +69,9 @@ static int __init find_chip_by_name_and_
+ matched[j++] = i;
+ i++;
+ }
++
++ ret = i;
++
+ if (j != 0) {
+ for (i = 0; i < j; i++) {
+ if ((ppc_sys_specs[matched[i]].mask & id) ==
+diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c
+--- a/arch/ppc/syslib/pq2_devices.c
++++ b/arch/ppc/syslib/pq2_devices.c
+@@ -13,11 +13,12 @@
+
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/ioport.h>
+ #include <asm/cpm2.h>
+ #include <asm/irq.h>
+ #include <asm/ppc_sys.h>
++#include <asm/machdep.h>
+
+ struct platform_device ppc_sys_platform_devices[] = {
+ [MPC82xx_CPM_FCC1] = {
+diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c
+--- a/arch/ppc/syslib/prep_nvram.c
++++ b/arch/ppc/syslib/prep_nvram.c
+@@ -22,14 +22,14 @@
+ static char nvramData[MAX_PREP_NVRAM];
+ static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
+
+-unsigned char __prep prep_nvram_read_val(int addr)
++unsigned char prep_nvram_read_val(int addr)
+ {
+ outb(addr, PREP_NVRAM_AS0);
+ outb(addr>>8, PREP_NVRAM_AS1);
+ return inb(PREP_NVRAM_DATA);
+ }
+
+-void __prep prep_nvram_write_val(int addr,
++void prep_nvram_write_val(int addr,
+ unsigned char val)
+ {
+ outb(addr, PREP_NVRAM_AS0);
+@@ -81,8 +81,7 @@ void __init init_prep_nvram(void)
+ }
+ }
+
+-__prep
+-char __prep *prep_nvram_get_var(const char *name)
++char *prep_nvram_get_var(const char *name)
+ {
+ char *cp;
+ int namelen;
+@@ -101,8 +100,7 @@ char __prep *prep_nvram_get_var(const ch
+ return NULL;
+ }
+
+-__prep
+-char __prep *prep_nvram_first_var(void)
++char *prep_nvram_first_var(void)
+ {
+ if (nvram->Header.GELength == 0) {
+ return NULL;
+@@ -112,8 +110,7 @@ char __prep *prep_nvram_first_var(void)
+ }
+ }
+
+-__prep
+-char __prep *prep_nvram_next_var(char *name)
++char *prep_nvram_next_var(char *name)
+ {
+ char *cp;
+
+diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
+--- a/arch/ppc/syslib/prom.c
++++ b/arch/ppc/syslib/prom.c
+@@ -89,7 +89,7 @@ extern char cmd_line[512]; /* XXX */
+ extern boot_infos_t *boot_infos;
+ unsigned long dev_tree_size;
+
+-void __openfirmware
++void
+ phys_call_rtas(int service, int nargs, int nret, ...)
+ {
+ va_list list;
+@@ -862,7 +862,7 @@ find_type_devices(const char *type)
+ /*
+ * Returns all nodes linked together
+ */
+-struct device_node * __openfirmware
++struct device_node *
+ find_all_nodes(void)
+ {
+ struct device_node *head, **prevp, *np;
+@@ -1165,7 +1165,7 @@ get_property(struct device_node *np, con
+ /*
+ * Add a property to a node
+ */
+-void __openfirmware
++void
+ prom_add_property(struct device_node* np, struct property* prop)
+ {
+ struct property **next = &np->properties;
+@@ -1177,7 +1177,7 @@ prom_add_property(struct device_node* np
+ }
+
+ /* I quickly hacked that one, check against spec ! */
+-static inline unsigned long __openfirmware
++static inline unsigned long
+ bus_space_to_resource_flags(unsigned int bus_space)
+ {
+ u8 space = (bus_space >> 24) & 0xf;
+@@ -1194,7 +1194,7 @@ bus_space_to_resource_flags(unsigned int
+ }
+ }
+
+-static struct resource* __openfirmware
++static struct resource*
+ find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
+ {
+ unsigned long mask;
+@@ -1224,7 +1224,7 @@ find_parent_pci_resource(struct pci_dev*
+ * or other nodes attached to the root node. Ultimately, put some
+ * link to resources in the OF node.
+ */
+-struct resource* __openfirmware
++struct resource*
+ request_OF_resource(struct device_node* node, int index, const char* name_postfix)
+ {
+ struct pci_dev* pcidev;
+@@ -1280,7 +1280,7 @@ fail:
+ return NULL;
+ }
+
+-int __openfirmware
++int
+ release_OF_resource(struct device_node* node, int index)
+ {
+ struct pci_dev* pcidev;
+@@ -1346,7 +1346,7 @@ release_OF_resource(struct device_node*
+ }
+
+ #if 0
+-void __openfirmware
++void
+ print_properties(struct device_node *np)
+ {
+ struct property *pp;
+@@ -1400,7 +1400,7 @@ print_properties(struct device_node *np)
+ static DEFINE_SPINLOCK(rtas_lock);
+
+ /* this can be called after setup -- Cort */
+-int __openfirmware
++int
+ call_rtas(const char *service, int nargs, int nret,
+ unsigned long *outputs, ...)
+ {
+diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c
+--- a/arch/ppc/syslib/xilinx_pic.c
++++ b/arch/ppc/syslib/xilinx_pic.c
+@@ -17,6 +17,7 @@
+ #include <asm/io.h>
+ #include <asm/xparameters.h>
+ #include <asm/ibm4xx.h>
++#include <asm/machdep.h>
+
+ /* No one else should require these constants, so define them locally here. */
+ #define ISR 0 /* Interrupt Status Register */
+diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
+--- a/arch/ppc/xmon/start.c
++++ b/arch/ppc/xmon/start.c
+@@ -478,8 +478,9 @@ void *xmon_stdout;
+ void *xmon_stderr;
+
+ void
+-xmon_init(void)
++xmon_init(int arg)
+ {
++ xmon_map_scc();
+ }
+
+ int
+diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
+--- a/arch/ppc/xmon/xmon.c
++++ b/arch/ppc/xmon/xmon.c
+@@ -148,9 +148,14 @@ Commands:\n\
+ r print registers\n\
+ S print special registers\n\
+ t print backtrace\n\
+- la lookup address in system.map\n\
+- ls lookup symbol in system.map\n\
++ la lookup address\n\
++ ls lookup symbol\n\
++ C checksum\n\
++ p call function with arguments\n\
++ T print time\n\
+ x exit monitor\n\
++ zr reboot\n\
++ zh halt\n\
+ ";
+
+ static int xmon_trace[NR_CPUS];
+diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
+--- a/arch/ppc64/Kconfig
++++ b/arch/ppc64/Kconfig
+@@ -10,6 +10,9 @@ config MMU
+ bool
+ default y
+
++config PPC_STD_MMU
++ def_bool y
++
+ config UID16
+ bool
+
+@@ -120,6 +123,11 @@ config MPIC
+ bool
+ default y
+
++config PPC_I8259
++ depends on PPC_PSERIES
++ bool
++ default y
++
+ config BPA_IIC
+ depends on PPC_BPA
+ bool
+@@ -186,6 +194,12 @@ config BOOTX_TEXT
+ Say Y here to see progress messages from the boot firmware in text
+ mode. Requires an Open Firmware compatible video card.
+
++config POWER4
++ def_bool y
++
++config PPC_FPU
++ def_bool y
++
+ config POWER4_ONLY
+ bool "Optimize for POWER4"
+ default n
+@@ -234,6 +248,10 @@ config HMT
+ This option enables hardware multithreading on RS64 cpus.
+ pSeries systems p620 and p660 have such a cpu type.
+
++config NUMA
++ bool "NUMA support"
++ default y if SMP && PPC_PSERIES
++
+ config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+
+@@ -249,9 +267,6 @@ config ARCH_DISCONTIGMEM_DEFAULT
+ def_bool y
+ depends on ARCH_DISCONTIGMEM_ENABLE
+
+-config ARCH_FLATMEM_ENABLE
+- def_bool y
+-
+ config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ depends on ARCH_DISCONTIGMEM_ENABLE
+@@ -274,10 +289,6 @@ config NODES_SPAN_OTHER_NODES
+ def_bool y
+ depends on NEED_MULTIPLE_NODES
+
+-config NUMA
+- bool "NUMA support"
+- default y if DISCONTIGMEM || SPARSEMEM
+-
+ config SCHED_SMT
+ bool "SMT (Hyperthreading) scheduler support"
+ depends on SMP
+@@ -307,6 +318,11 @@ config PPC_RTAS
+ depends on PPC_PSERIES || PPC_BPA
+ default y
+
++config RTAS_ERROR_LOGGING
++ bool
++ depends on PPC_RTAS
++ default y
++
+ config RTAS_PROC
+ bool "Proc interface to RTAS"
+ depends on PPC_RTAS
+@@ -357,7 +373,6 @@ config HOTPLUG_CPU
+
+ config PROC_DEVICETREE
+ bool "Support for Open Firmware device tree in /proc"
+- depends on !PPC_ISERIES
+ help
+ This option adds a device-tree directory under /proc which contains
+ an image of the device tree that the kernel copies from Open
+@@ -461,7 +476,7 @@ config VIOPATH
+ depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH
+ default y
+
+-source "arch/ppc64/oprofile/Kconfig"
++source "arch/powerpc/oprofile/Kconfig"
+
+ source "arch/ppc64/Kconfig.debug"
+
+diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
+--- a/arch/ppc64/Makefile
++++ b/arch/ppc64/Makefile
+@@ -75,17 +75,25 @@ else
+ CFLAGS += $(call cc-option,-mtune=power4)
+ endif
+
++# No AltiVec instruction when building kernel
++CFLAGS += $(call cc-option, -mno-altivec)
++
+ # Enable unit-at-a-time mode when possible. It shrinks the
+ # kernel considerably.
+ CFLAGS += $(call cc-option,-funit-at-a-time)
+
+ head-y := arch/ppc64/kernel/head.o
++head-y += arch/powerpc/kernel/fpu.o
++head-y += arch/powerpc/kernel/entry_64.o
+
+ libs-y += arch/ppc64/lib/
+-core-y += arch/ppc64/kernel/
+-core-y += arch/ppc64/mm/
+-core-$(CONFIG_XMON) += arch/ppc64/xmon/
+-drivers-$(CONFIG_OPROFILE) += arch/ppc64/oprofile/
++core-y += arch/ppc64/kernel/ arch/powerpc/kernel/
++core-y += arch/powerpc/mm/
++core-y += arch/powerpc/sysdev/
++core-y += arch/powerpc/platforms/
++core-y += arch/powerpc/lib/
++core-$(CONFIG_XMON) += arch/powerpc/xmon/
++drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
+
+ boot := arch/ppc64/boot
+
+@@ -100,7 +108,7 @@ $(boottargets-y): vmlinux
+ bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage
+ bootimage-$(CONFIG_PPC_PMAC) := vmlinux
+ bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage
+-bootimage-$(CONFIG_PPC_BPA) := zImage
++bootimage-$(CONFIG_PPC_BPA) := $(boot)/zImage
+ bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
+ BOOTIMAGE := $(bootimage-y)
+ install: vmlinux
+diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
+--- a/arch/ppc64/boot/Makefile
++++ b/arch/ppc64/boot/Makefile
+@@ -22,15 +22,46 @@
+
+
+ HOSTCC := gcc
+-BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem $(shell $(CROSS32CC) -print-file-name=include)
++BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem $(shell $(CROSS32CC) -print-file-name=include) -fPIC
+ BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
+-BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
++BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds
+ OBJCOPYFLAGS := contents,alloc,load,readonly,data
+
+-src-boot := crt0.S string.S prom.c main.c zlib.c imagesize.c div64.S
++zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
++zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
++zliblinuxheader := zlib.h zconf.h zutil.h
++
++$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
++#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
++
++src-boot := string.S prom.c main.c div64.S crt0.S
++src-boot += $(zlib)
+ src-boot := $(addprefix $(obj)/, $(src-boot))
+ obj-boot := $(addsuffix .o, $(basename $(src-boot)))
+
++BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj)
++
++quiet_cmd_copy_zlib = COPY $@
++ cmd_copy_zlib = sed "s at __attribute_used__@@;s@<linux/\([^>]\+\).*@\"\1\"@" $< > $@
++
++quiet_cmd_copy_zlibheader = COPY $@
++ cmd_copy_zlibheader = sed "s@<linux/\([^>]\+\).*@\"\1\"@" $< > $@
++# stddef.h for NULL
++quiet_cmd_copy_zliblinuxheader = COPY $@
++ cmd_copy_zliblinuxheader = sed "s@<linux/string.h>@\"string.h\"@;s@<linux/kernel.h>@<stddef.h>@;s@<linux/\([^>]\+\).*@\"\1\"@" $< > $@
++
++$(addprefix $(obj)/,$(zlib)): $(obj)/%: $(srctree)/lib/zlib_inflate/%
++ $(call cmd,copy_zlib)
++
++$(addprefix $(obj)/,$(zlibheader)): $(obj)/%: $(srctree)/lib/zlib_inflate/%
++ $(call cmd,copy_zlibheader)
++
++$(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/%
++ $(call cmd,copy_zliblinuxheader)
++
++clean-files := $(zlib) $(zlibheader) $(zliblinuxheader)
++
++
+ quiet_cmd_bootcc = BOOTCC $@
+ cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
+
+@@ -56,7 +87,7 @@ src-sec = $(foreach section, $(1), $(pat
+ gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
+
+ hostprogs-y := addnote addRamDisk
+-targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd imagesize.c \
++targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
+ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
+ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
+ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
+@@ -69,9 +100,9 @@ quiet_cmd_ramdisk = RAMDISK $@
+ quiet_cmd_stripvm = STRIP $@
+ cmd_stripvm = $(STRIP) -s $< -o $@
+
+-vmlinux.strip: vmlinux FORCE
++vmlinux.strip: vmlinux
+ $(call if_changed,stripvm)
+-$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
++$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz
+ $(call if_changed,ramdisk)
+
+ quiet_cmd_addsection = ADDSEC $@
+@@ -79,48 +110,38 @@ quiet_cmd_addsection = ADDSEC $@
+ --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(patsubst %.o,%.gz, $@) \
+ --set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(OBJCOPYFLAGS)
+
+-quiet_cmd_imagesize = GENSIZE $@
+- cmd_imagesize = ls -l vmlinux.strip | \
+- awk '{printf "/* generated -- do not edit! */\n" "unsigned long vmlinux_filesize = %d;\n", $$5}' \
+- > $(obj)/imagesize.c && \
+- $(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
+- awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' >> $(obj)/imagesize.c
+-
+ quiet_cmd_addnote = ADDNOTE $@
+ cmd_addnote = $(obj)/addnote $@
+
+-$(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE
++$(call gz-sec, $(required)): $(obj)/kernel-%.gz: %
+ $(call if_changed,gzip)
+
+ $(obj)/kernel-initrd.gz: $(obj)/ramdisk.image.gz
+ cp -f $(obj)/ramdisk.image.gz $@
+
+-$(call src-sec, $(required) $(initrd)): $(obj)/kernel-%.c: $(obj)/kernel-%.gz FORCE
++$(call src-sec, $(required) $(initrd)): $(obj)/kernel-%.c: $(obj)/kernel-%.gz
+ @touch $@
+
+-$(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c FORCE
++$(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c
+ $(call if_changed_dep,bootcc)
+ $(call cmd,addsection)
+
+ $(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required))
+-$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) FORCE
++$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds
+ $(call cmd,bootld,$(obj-boot))
+
+ $(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd))
+-$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) FORCE
++$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
+ $(call cmd,bootld,$(obj-boot))
+
+-$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote FORCE
++$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote
+ @cp -f $< $@
+ $(call if_changed,addnote)
+
+-$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote FORCE
++$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote
+ @cp -f $< $@
+ $(call if_changed,addnote)
+
+-$(obj)/imagesize.c: vmlinux.strip
+- $(call cmd,imagesize)
+-
+ install: $(CONFIGURE) $(BOOTIMAGE)
+ sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
+
+diff --git a/arch/ppc64/boot/crt0.S b/arch/ppc64/boot/crt0.S
+--- a/arch/ppc64/boot/crt0.S
++++ b/arch/ppc64/boot/crt0.S
+@@ -12,11 +12,40 @@
+ #include "ppc_asm.h"
+
+ .text
+- .globl _start
+-_start:
++ .globl _zimage_start
++_zimage_start:
++ bl reloc_offset
++
++reloc_offset:
++ mflr r0
++ lis r9,reloc_offset at ha
++ addi r9,r9,reloc_offset at l
++ subf. r0,r9,r0
++ beq clear_caches
++
++reloc_got2:
++ lis r9,__got2_start at ha
++ addi r9,r9,__got2_start at l
++ lis r8,__got2_end at ha
++ addi r8,r8,__got2_end at l
++ subf. r8,r9,r8
++ beq clear_caches
++ srwi. r8,r8,2
++ mtctr r8
++ add r9,r0,r9
++reloc_got2_loop:
++ lwz r8,0(r9)
++ add r8,r8,r0
++ stw r8,0(r9)
++ addi r9,r9,4
++ bdnz reloc_got2_loop
++
++clear_caches:
+ lis r9,_start at h
++ add r9,r0,r9
+ lis r8,_etext at ha
+ addi r8,r8,_etext at l
++ add r8,r0,r8
+ 1: dcbf r0,r9
+ icbi r0,r9
+ addi r9,r9,0x20
+@@ -25,24 +54,6 @@ _start:
+ sync
+ isync
+
+- ## Clear out the BSS as per ANSI C requirements
+-
+- lis r7,_end at ha
+- addi r7,r7,_end at l # r7 = &_end
+- lis r8,__bss_start at ha #
+- addi r8,r8,__bss_start at l # r8 = &_bss_start
+-
+- ## Determine how large an area, in number of words, to clear
+-
+- subf r7,r8,r7 # r7 = &_end - &_bss_start + 1
+- addi r7,r7,3 # r7 += 3
+- srwi. r7,r7,2 # r7 = size in words.
+- beq 3f # If the size is zero, don't bother
+- addi r8,r8,-4 # r8 -= 4
+- mtctr r7 # SPRN_CTR = number of words to clear
+- li r0,0 # r0 = 0
+-2: stwu r0,4(r8) # Clear out a word
+- bdnz 2b # Keep clearing until done
+-3:
++ mr r6,r1
+ b start
+
+diff --git a/arch/ppc64/boot/install.sh b/arch/ppc64/boot/install.sh
+--- a/arch/ppc64/boot/install.sh
++++ b/arch/ppc64/boot/install.sh
+@@ -28,7 +28,7 @@ if [ -x /sbin/${CROSS_COMPILE}installker
+ # Default install
+
+ # this should work for both the pSeries zImage and the iSeries vmlinux.sm
+-image_name=`basename $5`
++image_name=`basename $2`
+
+ if [ -f $4/$image_name ]; then
+ mv $4/$image_name $4/$image_name.old
+diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
+--- a/arch/ppc64/boot/main.c
++++ b/arch/ppc64/boot/main.c
+@@ -17,7 +17,6 @@
+ #include "prom.h"
+ #include "zlib.h"
+
+-static void gunzip(void *, int, unsigned char *, int *);
+ extern void flush_cache(void *, unsigned long);
+
+
+@@ -26,31 +25,26 @@ extern void flush_cache(void *, unsigned
+ #define RAM_END (512<<20) // Fixme: use OF */
+ #define ONE_MB 0x100000
+
+-static char *avail_ram;
+-static char *begin_avail, *end_avail;
+-static char *avail_high;
+-static unsigned int heap_use;
+-static unsigned int heap_max;
+-
+ extern char _start[];
++extern char __bss_start[];
+ extern char _end[];
+ extern char _vmlinux_start[];
+ extern char _vmlinux_end[];
+ extern char _initrd_start[];
+ extern char _initrd_end[];
+-extern unsigned long vmlinux_filesize;
+-extern unsigned long vmlinux_memsize;
+
+ struct addr_range {
+ unsigned long addr;
+ unsigned long size;
+ unsigned long memsize;
+ };
+-static struct addr_range vmlinux = {0, 0, 0};
+-static struct addr_range vmlinuz = {0, 0, 0};
+-static struct addr_range initrd = {0, 0, 0};
++static struct addr_range vmlinux;
++static struct addr_range vmlinuz;
++static struct addr_range initrd;
++
++static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */
++static char elfheader[256];
+
+-static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
+
+ typedef void (*kernel_entry_t)( unsigned long,
+ unsigned long,
+@@ -62,6 +56,63 @@ typedef void (*kernel_entry_t)( unsigned
+
+ static unsigned long claim_base;
+
++#define HEAD_CRC 2
++#define EXTRA_FIELD 4
++#define ORIG_NAME 8
++#define COMMENT 0x10
++#define RESERVED 0xe0
++
++static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
++{
++ z_stream s;
++ int r, i, flags;
++
++ /* skip header */
++ i = 10;
++ flags = src[3];
++ if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
++ printf("bad gzipped data\n\r");
++ exit();
++ }
++ if ((flags & EXTRA_FIELD) != 0)
++ i = 12 + src[10] + (src[11] << 8);
++ if ((flags & ORIG_NAME) != 0)
++ while (src[i++] != 0)
++ ;
++ if ((flags & COMMENT) != 0)
++ while (src[i++] != 0)
++ ;
++ if ((flags & HEAD_CRC) != 0)
++ i += 2;
++ if (i >= *lenp) {
++ printf("gunzip: ran out of data in header\n\r");
++ exit();
++ }
++
++ if (zlib_inflate_workspacesize() > sizeof(scratch)) {
++ printf("gunzip needs more mem\n");
++ exit();
++ }
++ memset(&s, 0, sizeof(s));
++ s.workspace = scratch;
++ r = zlib_inflateInit2(&s, -MAX_WBITS);
++ if (r != Z_OK) {
++ printf("inflateInit2 returned %d\n\r", r);
++ exit();
++ }
++ s.next_in = src + i;
++ s.avail_in = *lenp - i;
++ s.next_out = dst;
++ s.avail_out = dstlen;
++ r = zlib_inflate(&s, Z_FULL_FLUSH);
++ if (r != Z_OK && r != Z_STREAM_END) {
++ printf("inflate returned %d msg: %s\n\r", r, s.msg);
++ exit();
++ }
++ *lenp = s.next_out - (unsigned char *) dst;
++ zlib_inflateEnd(&s);
++}
++
+ static unsigned long try_claim(unsigned long size)
+ {
+ unsigned long addr = 0;
+@@ -80,13 +131,16 @@ static unsigned long try_claim(unsigned
+ return addr;
+ }
+
+-void start(unsigned long a1, unsigned long a2, void *promptr)
++void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+ {
+ unsigned long i;
++ int len;
+ kernel_entry_t kernel_entry;
+ Elf64_Ehdr *elf64;
+ Elf64_Phdr *elf64ph;
+
++ memset(__bss_start, 0, _end - __bss_start);
++
+ prom = (int (*)(void *)) promptr;
+ chosen_handle = finddevice("/chosen");
+ if (chosen_handle == (void *) -1)
+@@ -97,7 +151,7 @@ void start(unsigned long a1, unsigned lo
+ if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
+ exit();
+
+- printf("\n\rzImage starting: loaded at 0x%lx\n\r", (unsigned long) _start);
++ printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
+
+ /*
+ * The first available claim_base must be above the end of the
+@@ -118,25 +172,45 @@ void start(unsigned long a1, unsigned lo
+ claim_base = PROG_START;
+ #endif
+
+- /*
+- * Now we try to claim some memory for the kernel itself
+- * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what
+- * our Makefile stuffs in is an image containing all sort of junk including
+- * an ELF header. We need to do some calculations here to find the right
+- * size... In practice we add 1Mb, that is enough, but we should really
+- * consider fixing the Makefile to put a _raw_ kernel in there !
+- */
+- vmlinux_memsize += ONE_MB;
+- printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
+- vmlinux.addr = try_claim(vmlinux_memsize);
++ vmlinuz.addr = (unsigned long)_vmlinux_start;
++ vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
++
++ /* gunzip the ELF header of the kernel */
++ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
++ len = vmlinuz.size;
++ gunzip(elfheader, sizeof(elfheader),
++ (unsigned char *)vmlinuz.addr, &len);
++ } else
++ memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
++
++ elf64 = (Elf64_Ehdr *)elfheader;
++ if ( elf64->e_ident[EI_MAG0] != ELFMAG0 ||
++ elf64->e_ident[EI_MAG1] != ELFMAG1 ||
++ elf64->e_ident[EI_MAG2] != ELFMAG2 ||
++ elf64->e_ident[EI_MAG3] != ELFMAG3 ||
++ elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
++ elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
++ elf64->e_type != ET_EXEC ||
++ elf64->e_machine != EM_PPC64 )
++ {
++ printf("Error: not a valid PPC64 ELF file!\n\r");
++ exit();
++ }
++
++ elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
++ (unsigned long)elf64->e_phoff);
++ for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) {
++ if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
++ break;
++ }
++ vmlinux.size = (unsigned long)elf64ph->p_filesz;
++ vmlinux.memsize = (unsigned long)elf64ph->p_memsz;
++ printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
++ vmlinux.addr = try_claim(vmlinux.memsize);
+ if (vmlinux.addr == 0) {
+ printf("Can't allocate memory for kernel image !\n\r");
+ exit();
+ }
+- vmlinuz.addr = (unsigned long)_vmlinux_start;
+- vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
+- vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
+- vmlinux.memsize = vmlinux_memsize;
+
+ /*
+ * Now we try to claim memory for the initrd (and copy it there)
+@@ -160,49 +234,22 @@ void start(unsigned long a1, unsigned lo
+
+ /* Eventually gunzip the kernel */
+ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
+- int len;
+- avail_ram = scratch;
+- begin_avail = avail_high = avail_ram;
+- end_avail = scratch + sizeof(scratch);
+ printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
+ vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
+ len = vmlinuz.size;
+- gunzip((void *)vmlinux.addr, vmlinux.size,
++ gunzip((void *)vmlinux.addr, vmlinux.memsize,
+ (unsigned char *)vmlinuz.addr, &len);
+ printf("done 0x%lx bytes\n\r", len);
+- printf("0x%x bytes of heap consumed, max in use 0x%x\n\r",
+- (unsigned)(avail_high - begin_avail), heap_max);
+ } else {
+ memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
+ }
+
+ /* Skip over the ELF header */
+- elf64 = (Elf64_Ehdr *)vmlinux.addr;
+- if ( elf64->e_ident[EI_MAG0] != ELFMAG0 ||
+- elf64->e_ident[EI_MAG1] != ELFMAG1 ||
+- elf64->e_ident[EI_MAG2] != ELFMAG2 ||
+- elf64->e_ident[EI_MAG3] != ELFMAG3 ||
+- elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
+- elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
+- elf64->e_type != ET_EXEC ||
+- elf64->e_machine != EM_PPC64 )
+- {
+- printf("Error: not a valid PPC64 ELF file!\n\r");
+- exit();
+- }
+-
+- elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
+- (unsigned long)elf64->e_phoff);
+- for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) {
+- if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
+- break;
+- }
+ #ifdef DEBUG
+ printf("... skipping 0x%lx bytes of ELF header\n\r",
+ (unsigned long)elf64ph->p_offset);
+ #endif
+ vmlinux.addr += (unsigned long)elf64ph->p_offset;
+- vmlinux.size -= (unsigned long)elf64ph->p_offset;
+
+ flush_cache((void *)vmlinux.addr, vmlinux.size);
+
+@@ -225,108 +272,3 @@ void start(unsigned long a1, unsigned lo
+ exit();
+ }
+
+-struct memchunk {
+- unsigned int size;
+- unsigned int pad;
+- struct memchunk *next;
+-};
+-
+-static struct memchunk *freechunks;
+-
+-void *zalloc(void *x, unsigned items, unsigned size)
+-{
+- void *p;
+- struct memchunk **mpp, *mp;
+-
+- size *= items;
+- size = _ALIGN(size, sizeof(struct memchunk));
+- heap_use += size;
+- if (heap_use > heap_max)
+- heap_max = heap_use;
+- for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+- if (mp->size == size) {
+- *mpp = mp->next;
+- return mp;
+- }
+- }
+- p = avail_ram;
+- avail_ram += size;
+- if (avail_ram > avail_high)
+- avail_high = avail_ram;
+- if (avail_ram > end_avail) {
+- printf("oops... out of memory\n\r");
+- pause();
+- }
+- return p;
+-}
+-
+-void zfree(void *x, void *addr, unsigned nb)
+-{
+- struct memchunk *mp = addr;
+-
+- nb = _ALIGN(nb, sizeof(struct memchunk));
+- heap_use -= nb;
+- if (avail_ram == addr + nb) {
+- avail_ram = addr;
+- return;
+- }
+- mp->size = nb;
+- mp->next = freechunks;
+- freechunks = mp;
+-}
+-
+-#define HEAD_CRC 2
+-#define EXTRA_FIELD 4
+-#define ORIG_NAME 8
+-#define COMMENT 0x10
+-#define RESERVED 0xe0
+-
+-#define DEFLATED 8
+-
+-static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+-{
+- z_stream s;
+- int r, i, flags;
+-
+- /* skip header */
+- i = 10;
+- flags = src[3];
+- if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+- printf("bad gzipped data\n\r");
+- exit();
+- }
+- if ((flags & EXTRA_FIELD) != 0)
+- i = 12 + src[10] + (src[11] << 8);
+- if ((flags & ORIG_NAME) != 0)
+- while (src[i++] != 0)
+- ;
+- if ((flags & COMMENT) != 0)
+- while (src[i++] != 0)
+- ;
+- if ((flags & HEAD_CRC) != 0)
+- i += 2;
+- if (i >= *lenp) {
+- printf("gunzip: ran out of data in header\n\r");
+- exit();
+- }
+-
+- s.zalloc = zalloc;
+- s.zfree = zfree;
+- r = inflateInit2(&s, -MAX_WBITS);
+- if (r != Z_OK) {
+- printf("inflateInit2 returned %d\n\r", r);
+- exit();
+- }
+- s.next_in = src + i;
+- s.avail_in = *lenp - i;
+- s.next_out = dst;
+- s.avail_out = dstlen;
+- r = inflate(&s, Z_FINISH);
+- if (r != Z_OK && r != Z_STREAM_END) {
+- printf("inflate returned %d msg: %s\n\r", r, s.msg);
+- exit();
+- }
+- *lenp = s.next_out - (unsigned char *) dst;
+- inflateEnd(&s);
+-}
+-
+diff --git a/arch/ppc64/boot/string.S b/arch/ppc64/boot/string.S
+--- a/arch/ppc64/boot/string.S
++++ b/arch/ppc64/boot/string.S
+@@ -104,7 +104,7 @@ memmove:
+
+ .globl memcpy
+ memcpy:
+- rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
++ rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+@@ -146,7 +146,7 @@ memcpy:
+
+ .globl backwards_memcpy
+ backwards_memcpy:
+- rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
++ rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
+ add r6,r3,r5
+ add r4,r4,r5
+ beq 2f
+diff --git a/arch/ppc64/boot/string.h b/arch/ppc64/boot/string.h
+--- a/arch/ppc64/boot/string.h
++++ b/arch/ppc64/boot/string.h
+@@ -1,5 +1,6 @@
+ #ifndef _PPC_BOOT_STRING_H_
+ #define _PPC_BOOT_STRING_H_
++#include <stddef.h>
+
+ extern char *strcpy(char *dest, const char *src);
+ extern char *strncpy(char *dest, const char *src, size_t n);
+diff --git a/arch/ppc64/boot/zImage.lds b/arch/ppc64/boot/zImage.lds
+--- a/arch/ppc64/boot/zImage.lds
++++ b/arch/ppc64/boot/zImage.lds
+@@ -1,62 +1,24 @@
+ OUTPUT_ARCH(powerpc:common)
+-SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+-/* Do we need any of these for elf?
+- __DYNAMIC = 0; */
++ENTRY(_zimage_start)
+ SECTIONS
+ {
+- /* Read-only sections, merged into text segment: */
+- . = + SIZEOF_HEADERS;
+- .interp : { *(.interp) }
+- .hash : { *(.hash) }
+- .dynsym : { *(.dynsym) }
+- .dynstr : { *(.dynstr) }
+- .rel.text : { *(.rel.text) }
+- .rela.text : { *(.rela.text) }
+- .rel.data : { *(.rel.data) }
+- .rela.data : { *(.rela.data) }
+- .rel.rodata : { *(.rel.rodata) }
+- .rela.rodata : { *(.rela.rodata) }
+- .rel.got : { *(.rel.got) }
+- .rela.got : { *(.rela.got) }
+- .rel.ctors : { *(.rel.ctors) }
+- .rela.ctors : { *(.rela.ctors) }
+- .rel.dtors : { *(.rel.dtors) }
+- .rela.dtors : { *(.rela.dtors) }
+- .rel.bss : { *(.rel.bss) }
+- .rela.bss : { *(.rela.bss) }
+- .rel.plt : { *(.rel.plt) }
+- .rela.plt : { *(.rela.plt) }
+- .plt : { *(.plt) }
++ . = (4*1024*1024);
++ _start = .;
+ .text :
+ {
+ *(.text)
+ *(.fixup)
+- *(.got1)
+ }
+- . = ALIGN(4096);
+ _etext = .;
+- PROVIDE (etext = .);
+- .rodata :
+- {
+- *(.rodata)
+- *(.rodata1)
+- }
+- .kstrtab : { *(.kstrtab) }
+- __vermagic : { *(__vermagic) }
+- .fini : { *(.fini) } =0
+- .ctors : { *(.ctors) }
+- .dtors : { *(.dtors) }
+- /* Read-write section, merged into data segment: */
+ . = ALIGN(4096);
+ .data :
+ {
+- *(.data)
+- *(.data1)
+- *(.sdata)
+- *(.sdata2)
+- *(.got.plt) *(.got)
+- *(.dynamic)
+- CONSTRUCTORS
++ *(.rodata*)
++ *(.data*)
++ *(.sdata*)
++ __got2_start = .;
++ *(.got2)
++ __got2_end = .;
+ }
+
+ . = ALIGN(4096);
+@@ -71,20 +33,14 @@ SECTIONS
+
+ . = ALIGN(4096);
+ _edata = .;
+- PROVIDE (edata = .);
+-
+- .fixup : { *(.fixup) }
+
+ . = ALIGN(4096);
+ __bss_start = .;
+ .bss :
+ {
+- *(.sbss) *(.scommon)
+- *(.dynbss)
++ *(.sbss)
+ *(.bss)
+- *(COMMON)
+ }
+ . = ALIGN(4096);
+ _end = . ;
+- PROVIDE (end = .);
+ }
+diff --git a/arch/ppc64/boot/zlib.c b/arch/ppc64/boot/zlib.c
+deleted file mode 100644
+--- a/arch/ppc64/boot/zlib.c
++++ /dev/null
+@@ -1,2195 +0,0 @@
+-/*
+- * This file is derived from various .h and .c files from the zlib-0.95
+- * distribution by Jean-loup Gailly and Mark Adler, with some additions
+- * by Paul Mackerras to aid in implementing Deflate compression and
+- * decompression for PPP packets. See zlib.h for conditions of
+- * distribution and use.
+- *
+- * Changes that have been made include:
+- * - changed functions not used outside this file to "local"
+- * - added minCompression parameter to deflateInit2
+- * - added Z_PACKET_FLUSH (see zlib.h for details)
+- * - added inflateIncomp
+- *
+- Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+-
+- This software is provided 'as-is', without any express or implied
+- warranty. In no event will the authors be held liable for any damages
+- arising from the use of this software.
+-
+- Permission is granted to anyone to use this software for any purpose,
+- including commercial applications, and to alter it and redistribute it
+- freely, subject to the following restrictions:
+-
+- 1. The origin of this software must not be misrepresented; you must not
+- claim that you wrote the original software. If you use this software
+- in a product, an acknowledgment in the product documentation would be
+- appreciated but is not required.
+- 2. Altered source versions must be plainly marked as such, and must not be
+- misrepresented as being the original software.
+- 3. This notice may not be removed or altered from any source distribution.
+-
+- Jean-loup Gailly Mark Adler
+- gzip at prep.ai.mit.edu madler at alumni.caltech.edu
+-
+- *
+- *
+- */
+-
+-/*+++++*/
+-/* zutil.h -- internal interface and configuration of the compression library
+- * Copyright (C) 1995 Jean-loup Gailly.
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* WARNING: this file should *not* be used by applications. It is
+- part of the implementation of the compression library and is
+- subject to change. Applications should only use zlib.h.
+- */
+-
+-/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
+-
+-#define _Z_UTIL_H
+-
+-#include "zlib.h"
+-
+-#ifndef local
+-# define local static
+-#endif
+-/* compile with -Dlocal if your debugger can't find static symbols */
+-
+-#define FAR
+-
+-typedef unsigned char uch;
+-typedef uch FAR uchf;
+-typedef unsigned short ush;
+-typedef ush FAR ushf;
+-typedef unsigned long ulg;
+-
+-extern char *z_errmsg[]; /* indexed by 1-zlib_error */
+-
+-#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
+-/* To be used only when the state is known to be valid */
+-
+-#ifndef NULL
+-#define NULL ((void *) 0)
+-#endif
+-
+- /* common constants */
+-
+-#define DEFLATED 8
+-
+-#ifndef DEF_WBITS
+-# define DEF_WBITS MAX_WBITS
+-#endif
+-/* default windowBits for decompression. MAX_WBITS is for compression only */
+-
+-#if MAX_MEM_LEVEL >= 8
+-# define DEF_MEM_LEVEL 8
+-#else
+-# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+-#endif
+-/* default memLevel */
+-
+-#define STORED_BLOCK 0
+-#define STATIC_TREES 1
+-#define DYN_TREES 2
+-/* The three kinds of block type */
+-
+-#define MIN_MATCH 3
+-#define MAX_MATCH 258
+-/* The minimum and maximum match lengths */
+-
+- /* functions */
+-
+-extern void *memcpy(void *, const void *, unsigned long);
+-#define zmemcpy memcpy
+-
+-/* Diagnostic functions */
+-#ifdef DEBUG_ZLIB
+-# include "stdio.h"
+-# ifndef verbose
+-# define verbose 0
+-# endif
+-# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+-# define Trace(x) fprintf x
+-# define Tracev(x) {if (verbose) fprintf x ;}
+-# define Tracevv(x) {if (verbose>1) fprintf x ;}
+-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+-#else
+-# define Assert(cond,msg)
+-# define Trace(x)
+-# define Tracev(x)
+-# define Tracevv(x)
+-# define Tracec(c,x)
+-# define Tracecv(c,x)
+-#endif
+-
+-
+-typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
+-
+-/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
+-/* void zcfree OF((voidpf opaque, voidpf ptr)); */
+-
+-#define ZALLOC(strm, items, size) \
+- (*((strm)->zalloc))((strm)->opaque, (items), (size))
+-#define ZFREE(strm, addr, size) \
+- (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
+-#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
+-
+-/* deflate.h -- internal compression state
+- * Copyright (C) 1995 Jean-loup Gailly
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* WARNING: this file should *not* be used by applications. It is
+- part of the implementation of the compression library and is
+- subject to change. Applications should only use zlib.h.
+- */
+-
+-/*+++++*/
+-/* infblock.h -- header to use infblock.c
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* WARNING: this file should *not* be used by applications. It is
+- part of the implementation of the compression library and is
+- subject to change. Applications should only use zlib.h.
+- */
+-
+-struct inflate_blocks_state;
+-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+-
+-local inflate_blocks_statef * inflate_blocks_new OF((
+- z_stream *z,
+- check_func c, /* check function */
+- uInt w)); /* window size */
+-
+-local int inflate_blocks OF((
+- inflate_blocks_statef *,
+- z_stream *,
+- int)); /* initial return code */
+-
+-local void inflate_blocks_reset OF((
+- inflate_blocks_statef *,
+- z_stream *,
+- uLongf *)); /* check value on output */
+-
+-local int inflate_blocks_free OF((
+- inflate_blocks_statef *,
+- z_stream *,
+- uLongf *)); /* check value on output */
+-
+-local int inflate_addhistory OF((
+- inflate_blocks_statef *,
+- z_stream *));
+-
+-local int inflate_packet_flush OF((
+- inflate_blocks_statef *));
+-
+-/*+++++*/
+-/* inftrees.h -- header to use inftrees.c
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* WARNING: this file should *not* be used by applications. It is
+- part of the implementation of the compression library and is
+- subject to change. Applications should only use zlib.h.
+- */
+-
+-/* Huffman code lookup table entry--this entry is four bytes for machines
+- that have 16-bit pointers (e.g. PC's in the small or medium model). */
+-
+-typedef struct inflate_huft_s FAR inflate_huft;
+-
+-struct inflate_huft_s {
+- union {
+- struct {
+- Byte Exop; /* number of extra bits or operation */
+- Byte Bits; /* number of bits in this code or subcode */
+- } what;
+- uInt Nalloc; /* number of these allocated here */
+- Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
+- } word; /* 16-bit, 8 bytes for 32-bit machines) */
+- union {
+- uInt Base; /* literal, length base, or distance base */
+- inflate_huft *Next; /* pointer to next level of table */
+- } more;
+-};
+-
+-#ifdef DEBUG_ZLIB
+- local uInt inflate_hufts;
+-#endif
+-
+-local int inflate_trees_bits OF((
+- uIntf *, /* 19 code lengths */
+- uIntf *, /* bits tree desired/actual depth */
+- inflate_huft * FAR *, /* bits tree result */
+- z_stream *)); /* for zalloc, zfree functions */
+-
+-local int inflate_trees_dynamic OF((
+- uInt, /* number of literal/length codes */
+- uInt, /* number of distance codes */
+- uIntf *, /* that many (total) code lengths */
+- uIntf *, /* literal desired/actual bit depth */
+- uIntf *, /* distance desired/actual bit depth */
+- inflate_huft * FAR *, /* literal/length tree result */
+- inflate_huft * FAR *, /* distance tree result */
+- z_stream *)); /* for zalloc, zfree functions */
+-
+-local int inflate_trees_fixed OF((
+- uIntf *, /* literal desired/actual bit depth */
+- uIntf *, /* distance desired/actual bit depth */
+- inflate_huft * FAR *, /* literal/length tree result */
+- inflate_huft * FAR *)); /* distance tree result */
+-
+-local int inflate_trees_free OF((
+- inflate_huft *, /* tables to free */
+- z_stream *)); /* for zfree function */
+-
+-
+-/*+++++*/
+-/* infcodes.h -- header to use infcodes.c
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* WARNING: this file should *not* be used by applications. It is
+- part of the implementation of the compression library and is
+- subject to change. Applications should only use zlib.h.
+- */
+-
+-struct inflate_codes_state;
+-typedef struct inflate_codes_state FAR inflate_codes_statef;
+-
+-local inflate_codes_statef *inflate_codes_new OF((
+- uInt, uInt,
+- inflate_huft *, inflate_huft *,
+- z_stream *));
+-
+-local int inflate_codes OF((
+- inflate_blocks_statef *,
+- z_stream *,
+- int));
+-
+-local void inflate_codes_free OF((
+- inflate_codes_statef *,
+- z_stream *));
+-
+-
+-/*+++++*/
+-/* inflate.c -- zlib interface to inflate modules
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* inflate private state */
+-struct internal_state {
+-
+- /* mode */
+- enum {
+- METHOD, /* waiting for method byte */
+- FLAG, /* waiting for flag byte */
+- BLOCKS, /* decompressing blocks */
+- CHECK4, /* four check bytes to go */
+- CHECK3, /* three check bytes to go */
+- CHECK2, /* two check bytes to go */
+- CHECK1, /* one check byte to go */
+- DONE, /* finished check, done */
+- BAD} /* got an error--stay here */
+- mode; /* current inflate mode */
+-
+- /* mode dependent information */
+- union {
+- uInt method; /* if FLAGS, method byte */
+- struct {
+- uLong was; /* computed check value */
+- uLong need; /* stream check value */
+- } check; /* if CHECK, check values to compare */
+- uInt marker; /* if BAD, inflateSync's marker bytes count */
+- } sub; /* submode */
+-
+- /* mode independent information */
+- int nowrap; /* flag for no wrapper */
+- uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+- inflate_blocks_statef
+- *blocks; /* current inflate_blocks state */
+-
+-};
+-
+-
+-int inflateReset(
+- z_stream *z
+-)
+-{
+- uLong c;
+-
+- if (z == Z_NULL || z->state == Z_NULL)
+- return Z_STREAM_ERROR;
+- z->total_in = z->total_out = 0;
+- z->msg = Z_NULL;
+- z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+- inflate_blocks_reset(z->state->blocks, z, &c);
+- Trace((stderr, "inflate: reset\n"));
+- return Z_OK;
+-}
+-
+-
+-int inflateEnd(
+- z_stream *z
+-)
+-{
+- uLong c;
+-
+- if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+- return Z_STREAM_ERROR;
+- if (z->state->blocks != Z_NULL)
+- inflate_blocks_free(z->state->blocks, z, &c);
+- ZFREE(z, z->state, sizeof(struct internal_state));
+- z->state = Z_NULL;
+- Trace((stderr, "inflate: end\n"));
+- return Z_OK;
+-}
+-
+-
+-int inflateInit2(
+- z_stream *z,
+- int w
+-)
+-{
+- /* initialize state */
+- if (z == Z_NULL)
+- return Z_STREAM_ERROR;
+-/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
+-/* if (z->zfree == Z_NULL) z->zfree = zcfree; */
+- if ((z->state = (struct internal_state FAR *)
+- ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+- return Z_MEM_ERROR;
+- z->state->blocks = Z_NULL;
+-
+- /* handle undocumented nowrap option (no zlib header or check) */
+- z->state->nowrap = 0;
+- if (w < 0)
+- {
+- w = - w;
+- z->state->nowrap = 1;
+- }
+-
+- /* set window size */
+- if (w < 8 || w > 15)
+- {
+- inflateEnd(z);
+- return Z_STREAM_ERROR;
+- }
+- z->state->wbits = (uInt)w;
+-
+- /* create inflate_blocks state */
+- if ((z->state->blocks =
+- inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
+- == Z_NULL)
+- {
+- inflateEnd(z);
+- return Z_MEM_ERROR;
+- }
+- Trace((stderr, "inflate: allocated\n"));
+-
+- /* reset state */
+- inflateReset(z);
+- return Z_OK;
+-}
+-
+-
+-int inflateInit(
+- z_stream *z
+-)
+-{
+- return inflateInit2(z, DEF_WBITS);
+-}
+-
+-
+-#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
+-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+-
+-int inflate(
+- z_stream *z,
+- int f
+-)
+-{
+- int r;
+- uInt b;
+-
+- if (z == Z_NULL || z->next_in == Z_NULL)
+- return Z_STREAM_ERROR;
+- r = Z_BUF_ERROR;
+- while (1) switch (z->state->mode)
+- {
+- case METHOD:
+- NEEDBYTE
+- if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
+- {
+- z->state->mode = BAD;
+- z->msg = "unknown compression method";
+- z->state->sub.marker = 5; /* can't try inflateSync */
+- break;
+- }
+- if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+- {
+- z->state->mode = BAD;
+- z->msg = "invalid window size";
+- z->state->sub.marker = 5; /* can't try inflateSync */
+- break;
+- }
+- z->state->mode = FLAG;
+- case FLAG:
+- NEEDBYTE
+- if ((b = NEXTBYTE) & 0x20)
+- {
+- z->state->mode = BAD;
+- z->msg = "invalid reserved bit";
+- z->state->sub.marker = 5; /* can't try inflateSync */
+- break;
+- }
+- if (((z->state->sub.method << 8) + b) % 31)
+- {
+- z->state->mode = BAD;
+- z->msg = "incorrect header check";
+- z->state->sub.marker = 5; /* can't try inflateSync */
+- break;
+- }
+- Trace((stderr, "inflate: zlib header ok\n"));
+- z->state->mode = BLOCKS;
+- case BLOCKS:
+- r = inflate_blocks(z->state->blocks, z, r);
+- if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
+- r = inflate_packet_flush(z->state->blocks);
+- if (r == Z_DATA_ERROR)
+- {
+- z->state->mode = BAD;
+- z->state->sub.marker = 0; /* can try inflateSync */
+- break;
+- }
+- if (r != Z_STREAM_END)
+- return r;
+- r = Z_OK;
+- inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+- if (z->state->nowrap)
+- {
+- z->state->mode = DONE;
+- break;
+- }
+- z->state->mode = CHECK4;
+- case CHECK4:
+- NEEDBYTE
+- z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+- z->state->mode = CHECK3;
+- case CHECK3:
+- NEEDBYTE
+- z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+- z->state->mode = CHECK2;
+- case CHECK2:
+- NEEDBYTE
+- z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+- z->state->mode = CHECK1;
+- case CHECK1:
+- NEEDBYTE
+- z->state->sub.check.need += (uLong)NEXTBYTE;
+-
+- if (z->state->sub.check.was != z->state->sub.check.need)
+- {
+- z->state->mode = BAD;
+- z->msg = "incorrect data check";
+- z->state->sub.marker = 5; /* can't try inflateSync */
+- break;
+- }
+- Trace((stderr, "inflate: zlib check ok\n"));
+- z->state->mode = DONE;
+- case DONE:
+- return Z_STREAM_END;
+- case BAD:
+- return Z_DATA_ERROR;
+- default:
+- return Z_STREAM_ERROR;
+- }
+-
+- empty:
+- if (f != Z_PACKET_FLUSH)
+- return r;
+- z->state->mode = BAD;
+- z->state->sub.marker = 0; /* can try inflateSync */
+- return Z_DATA_ERROR;
+-}
+-
+-/*
+- * This subroutine adds the data at next_in/avail_in to the output history
+- * without performing any output. The output buffer must be "caught up";
+- * i.e. no pending output (hence s->read equals s->write), and the state must
+- * be BLOCKS (i.e. we should be willing to see the start of a series of
+- * BLOCKS). On exit, the output will also be caught up, and the checksum
+- * will have been updated if need be.
+- */
+-
+-int inflateIncomp(
+- z_stream *z
+-)
+-{
+- if (z->state->mode != BLOCKS)
+- return Z_DATA_ERROR;
+- return inflate_addhistory(z->state->blocks, z);
+-}
+-
+-
+-int inflateSync(
+- z_stream *z
+-)
+-{
+- uInt n; /* number of bytes to look at */
+- Bytef *p; /* pointer to bytes */
+- uInt m; /* number of marker bytes found in a row */
+- uLong r, w; /* temporaries to save total_in and total_out */
+-
+- /* set up */
+- if (z == Z_NULL || z->state == Z_NULL)
+- return Z_STREAM_ERROR;
+- if (z->state->mode != BAD)
+- {
+- z->state->mode = BAD;
+- z->state->sub.marker = 0;
+- }
+- if ((n = z->avail_in) == 0)
+- return Z_BUF_ERROR;
+- p = z->next_in;
+- m = z->state->sub.marker;
+-
+- /* search */
+- while (n && m < 4)
+- {
+- if (*p == (Byte)(m < 2 ? 0 : 0xff))
+- m++;
+- else if (*p)
+- m = 0;
+- else
+- m = 4 - m;
+- p++, n--;
+- }
+-
+- /* restore */
+- z->total_in += p - z->next_in;
+- z->next_in = p;
+- z->avail_in = n;
+- z->state->sub.marker = m;
+-
+- /* return no joy or set up to restart on a new block */
+- if (m != 4)
+- return Z_DATA_ERROR;
+- r = z->total_in; w = z->total_out;
+- inflateReset(z);
+- z->total_in = r; z->total_out = w;
+- z->state->mode = BLOCKS;
+- return Z_OK;
+-}
+-
+-#undef NEEDBYTE
+-#undef NEXTBYTE
+-
+-/*+++++*/
+-/* infutil.h -- types and macros common to blocks and codes
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* WARNING: this file should *not* be used by applications. It is
+- part of the implementation of the compression library and is
+- subject to change. Applications should only use zlib.h.
+- */
+-
+-/* inflate blocks semi-private state */
+-struct inflate_blocks_state {
+-
+- /* mode */
+- enum {
+- TYPE, /* get type bits (3, including end bit) */
+- LENS, /* get lengths for stored */
+- STORED, /* processing stored block */
+- TABLE, /* get table lengths */
+- BTREE, /* get bit lengths tree for a dynamic block */
+- DTREE, /* get length, distance trees for a dynamic block */
+- CODES, /* processing fixed or dynamic block */
+- DRY, /* output remaining window bytes */
+- DONEB, /* finished last block, done */
+- BADB} /* got a data error--stuck here */
+- mode; /* current inflate_block mode */
+-
+- /* mode dependent information */
+- union {
+- uInt left; /* if STORED, bytes left to copy */
+- struct {
+- uInt table; /* table lengths (14 bits) */
+- uInt index; /* index into blens (or border) */
+- uIntf *blens; /* bit lengths of codes */
+- uInt bb; /* bit length tree depth */
+- inflate_huft *tb; /* bit length decoding tree */
+- int nblens; /* # elements allocated at blens */
+- } trees; /* if DTREE, decoding info for trees */
+- struct {
+- inflate_huft *tl, *td; /* trees to free */
+- inflate_codes_statef
+- *codes;
+- } decode; /* if CODES, current state */
+- } sub; /* submode */
+- uInt last; /* true if this block is the last block */
+-
+- /* mode independent information */
+- uInt bitk; /* bits in bit buffer */
+- uLong bitb; /* bit buffer */
+- Bytef *window; /* sliding window */
+- Bytef *end; /* one byte after sliding window */
+- Bytef *read; /* window read pointer */
+- Bytef *write; /* window write pointer */
+- check_func checkfn; /* check function */
+- uLong check; /* check on output */
+-
+-};
+-
+-
+-/* defines for inflate input/output */
+-/* update pointers and return */
+-#define UPDBITS {s->bitb=b;s->bitk=k;}
+-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+-#define UPDOUT {s->write=q;}
+-#define UPDATE {UPDBITS UPDIN UPDOUT}
+-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+-/* get bytes and bits */
+-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+-#define NEXTBYTE (n--,*p++)
+-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+-#define DUMPBITS(j) {b>>=(j);k-=(j);}
+-/* output bytes */
+-#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
+-#define LOADOUT {q=s->write;m=WAVAIL;}
+-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
+-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+-/* load local pointers */
+-#define LOAD {LOADIN LOADOUT}
+-
+-/* And'ing with mask[n] masks the lower n bits */
+-local uInt inflate_mask[] = {
+- 0x0000,
+- 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+-};
+-
+-/* copy as much as possible from the sliding window to the output area */
+-local int inflate_flush OF((
+- inflate_blocks_statef *,
+- z_stream *,
+- int));
+-
+-/*+++++*/
+-/* inffast.h -- header to use inffast.c
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* WARNING: this file should *not* be used by applications. It is
+- part of the implementation of the compression library and is
+- subject to change. Applications should only use zlib.h.
+- */
+-
+-local int inflate_fast OF((
+- uInt,
+- uInt,
+- inflate_huft *,
+- inflate_huft *,
+- inflate_blocks_statef *,
+- z_stream *));
+-
+-
+-/*+++++*/
+-/* infblock.c -- interpret and process block types to last block
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* Table for deflate from PKZIP's appnote.txt. */
+-local uInt border[] = { /* Order of the bit length code lengths */
+- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+-
+-/*
+- Notes beyond the 1.93a appnote.txt:
+-
+- 1. Distance pointers never point before the beginning of the output
+- stream.
+- 2. Distance pointers can point back across blocks, up to 32k away.
+- 3. There is an implied maximum of 7 bits for the bit length table and
+- 15 bits for the actual data.
+- 4. If only one code exists, then it is encoded using one bit. (Zero
+- would be more efficient, but perhaps a little confusing.) If two
+- codes exist, they are coded using one bit each (0 and 1).
+- 5. There is no way of sending zero distance codes--a dummy must be
+- sent if there are none. (History: a pre 2.0 version of PKZIP would
+- store blocks with no distance codes, but this was discovered to be
+- too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+- zero distance codes, which is sent as one code of zero bits in
+- length.
+- 6. There are up to 286 literal/length codes. Code 256 represents the
+- end-of-block. Note however that the static length tree defines
+- 288 codes just to fill out the Huffman codes. Codes 286 and 287
+- cannot be used though, since there is no length base or extra bits
+- defined for them. Similarily, there are up to 30 distance codes.
+- However, static trees define 32 codes (all 5 bits) to fill out the
+- Huffman codes, but the last two had better not show up in the data.
+- 7. Unzip can check dynamic Huffman blocks for complete code sets.
+- The exception is that a single code would not be complete (see #4).
+- 8. The five bits following the block type is really the number of
+- literal codes sent minus 257.
+- 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+- (1+6+6). Therefore, to output three times the length, you output
+- three codes (1+1+1), whereas to output four times the same length,
+- you only need two codes (1+3). Hmm.
+- 10. In the tree reconstruction algorithm, Code = Code + Increment
+- only if BitLength(i) is not zero. (Pretty obvious.)
+- 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+- 12. Note: length code 284 can represent 227-258, but length code 285
+- really is 258. The last length deserves its own, short code
+- since it gets used a lot in very redundant files. The length
+- 258 is special since 258 - 3 (the min match length) is 255.
+- 13. The literal/length and distance code bit lengths are read as a
+- single stream of lengths. It is possible (and advantageous) for
+- a repeat code (16, 17, or 18) to go across the boundary between
+- the two sets of lengths.
+- */
+-
+-
+-local void inflate_blocks_reset(
+- inflate_blocks_statef *s,
+- z_stream *z,
+- uLongf *c
+-)
+-{
+- if (s->checkfn != Z_NULL)
+- *c = s->check;
+- if (s->mode == BTREE || s->mode == DTREE)
+- ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+- if (s->mode == CODES)
+- {
+- inflate_codes_free(s->sub.decode.codes, z);
+- inflate_trees_free(s->sub.decode.td, z);
+- inflate_trees_free(s->sub.decode.tl, z);
+- }
+- s->mode = TYPE;
+- s->bitk = 0;
+- s->bitb = 0;
+- s->read = s->write = s->window;
+- if (s->checkfn != Z_NULL)
+- s->check = (*s->checkfn)(0L, Z_NULL, 0);
+- Trace((stderr, "inflate: blocks reset\n"));
+-}
+-
+-
+-local inflate_blocks_statef *inflate_blocks_new(
+- z_stream *z,
+- check_func c,
+- uInt w
+-)
+-{
+- inflate_blocks_statef *s;
+-
+- if ((s = (inflate_blocks_statef *)ZALLOC
+- (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+- return s;
+- if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+- {
+- ZFREE(z, s, sizeof(struct inflate_blocks_state));
+- return Z_NULL;
+- }
+- s->end = s->window + w;
+- s->checkfn = c;
+- s->mode = TYPE;
+- Trace((stderr, "inflate: blocks allocated\n"));
+- inflate_blocks_reset(s, z, &s->check);
+- return s;
+-}
+-
+-
+-local int inflate_blocks(
+- inflate_blocks_statef *s,
+- z_stream *z,
+- int r
+-)
+-{
+- uInt t; /* temporary storage */
+- uLong b; /* bit buffer */
+- uInt k; /* bits in bit buffer */
+- Bytef *p; /* input data pointer */
+- uInt n; /* bytes available there */
+- Bytef *q; /* output window write pointer */
+- uInt m; /* bytes to end of window or read pointer */
+-
+- /* copy input/output information to locals (UPDATE macro restores) */
+- LOAD
+-
+- /* process input based on current state */
+- while (1) switch (s->mode)
+- {
+- case TYPE:
+- NEEDBITS(3)
+- t = (uInt)b & 7;
+- s->last = t & 1;
+- switch (t >> 1)
+- {
+- case 0: /* stored */
+- Trace((stderr, "inflate: stored block%s\n",
+- s->last ? " (last)" : ""));
+- DUMPBITS(3)
+- t = k & 7; /* go to byte boundary */
+- DUMPBITS(t)
+- s->mode = LENS; /* get length of stored block */
+- break;
+- case 1: /* fixed */
+- Trace((stderr, "inflate: fixed codes block%s\n",
+- s->last ? " (last)" : ""));
+- {
+- uInt bl, bd;
+- inflate_huft *tl, *td;
+-
+- inflate_trees_fixed(&bl, &bd, &tl, &td);
+- s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+- if (s->sub.decode.codes == Z_NULL)
+- {
+- r = Z_MEM_ERROR;
+- LEAVE
+- }
+- s->sub.decode.tl = Z_NULL; /* don't try to free these */
+- s->sub.decode.td = Z_NULL;
+- }
+- DUMPBITS(3)
+- s->mode = CODES;
+- break;
+- case 2: /* dynamic */
+- Trace((stderr, "inflate: dynamic codes block%s\n",
+- s->last ? " (last)" : ""));
+- DUMPBITS(3)
+- s->mode = TABLE;
+- break;
+- case 3: /* illegal */
+- DUMPBITS(3)
+- s->mode = BADB;
+- z->msg = "invalid block type";
+- r = Z_DATA_ERROR;
+- LEAVE
+- }
+- break;
+- case LENS:
+- NEEDBITS(32)
+- if (((~b) >> 16) != (b & 0xffff))
+- {
+- s->mode = BADB;
+- z->msg = "invalid stored block lengths";
+- r = Z_DATA_ERROR;
+- LEAVE
+- }
+- s->sub.left = (uInt)b & 0xffff;
+- b = k = 0; /* dump bits */
+- Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+- s->mode = s->sub.left ? STORED : TYPE;
+- break;
+- case STORED:
+- if (n == 0)
+- LEAVE
+- NEEDOUT
+- t = s->sub.left;
+- if (t > n) t = n;
+- if (t > m) t = m;
+- zmemcpy(q, p, t);
+- p += t; n -= t;
+- q += t; m -= t;
+- if ((s->sub.left -= t) != 0)
+- break;
+- Tracev((stderr, "inflate: stored end, %lu total out\n",
+- z->total_out + (q >= s->read ? q - s->read :
+- (s->end - s->read) + (q - s->window))));
+- s->mode = s->last ? DRY : TYPE;
+- break;
+- case TABLE:
+- NEEDBITS(14)
+- s->sub.trees.table = t = (uInt)b & 0x3fff;
+-#ifndef PKZIP_BUG_WORKAROUND
+- if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+- {
+- s->mode = BADB;
+- z->msg = "too many length or distance symbols";
+- r = Z_DATA_ERROR;
+- LEAVE
+- }
+-#endif
+- t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+- if (t < 19)
+- t = 19;
+- if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+- {
+- r = Z_MEM_ERROR;
+- LEAVE
+- }
+- s->sub.trees.nblens = t;
+- DUMPBITS(14)
+- s->sub.trees.index = 0;
+- Tracev((stderr, "inflate: table sizes ok\n"));
+- s->mode = BTREE;
+- case BTREE:
+- while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+- {
+- NEEDBITS(3)
+- s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+- DUMPBITS(3)
+- }
+- while (s->sub.trees.index < 19)
+- s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+- s->sub.trees.bb = 7;
+- t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+- &s->sub.trees.tb, z);
+- if (t != Z_OK)
+- {
+- r = t;
+- if (r == Z_DATA_ERROR)
+- s->mode = BADB;
+- LEAVE
+- }
+- s->sub.trees.index = 0;
+- Tracev((stderr, "inflate: bits tree ok\n"));
+- s->mode = DTREE;
+- case DTREE:
+- while (t = s->sub.trees.table,
+- s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+- {
+- inflate_huft *h;
+- uInt i, j, c;
+-
+- t = s->sub.trees.bb;
+- NEEDBITS(t)
+- h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+- t = h->word.what.Bits;
+- c = h->more.Base;
+- if (c < 16)
+- {
+- DUMPBITS(t)
+- s->sub.trees.blens[s->sub.trees.index++] = c;
+- }
+- else /* c == 16..18 */
+- {
+- i = c == 18 ? 7 : c - 14;
+- j = c == 18 ? 11 : 3;
+- NEEDBITS(t + i)
+- DUMPBITS(t)
+- j += (uInt)b & inflate_mask[i];
+- DUMPBITS(i)
+- i = s->sub.trees.index;
+- t = s->sub.trees.table;
+- if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+- (c == 16 && i < 1))
+- {
+- s->mode = BADB;
+- z->msg = "invalid bit length repeat";
+- r = Z_DATA_ERROR;
+- LEAVE
+- }
+- c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+- do {
+- s->sub.trees.blens[i++] = c;
+- } while (--j);
+- s->sub.trees.index = i;
+- }
+- }
+- inflate_trees_free(s->sub.trees.tb, z);
+- s->sub.trees.tb = Z_NULL;
+- {
+- uInt bl, bd;
+- inflate_huft *tl, *td;
+- inflate_codes_statef *c;
+-
+- bl = 9; /* must be <= 9 for lookahead assumptions */
+- bd = 6; /* must be <= 9 for lookahead assumptions */
+- t = s->sub.trees.table;
+- t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+- s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+- if (t != Z_OK)
+- {
+- if (t == (uInt)Z_DATA_ERROR)
+- s->mode = BADB;
+- r = t;
+- LEAVE
+- }
+- Tracev((stderr, "inflate: trees ok\n"));
+- if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+- {
+- inflate_trees_free(td, z);
+- inflate_trees_free(tl, z);
+- r = Z_MEM_ERROR;
+- LEAVE
+- }
+- ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+- s->sub.decode.codes = c;
+- s->sub.decode.tl = tl;
+- s->sub.decode.td = td;
+- }
+- s->mode = CODES;
+- case CODES:
+- UPDATE
+- if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+- return inflate_flush(s, z, r);
+- r = Z_OK;
+- inflate_codes_free(s->sub.decode.codes, z);
+- inflate_trees_free(s->sub.decode.td, z);
+- inflate_trees_free(s->sub.decode.tl, z);
+- LOAD
+- Tracev((stderr, "inflate: codes end, %lu total out\n",
+- z->total_out + (q >= s->read ? q - s->read :
+- (s->end - s->read) + (q - s->window))));
+- if (!s->last)
+- {
+- s->mode = TYPE;
+- break;
+- }
+- if (k > 7) /* return unused byte, if any */
+- {
+- Assert(k < 16, "inflate_codes grabbed too many bytes")
+- k -= 8;
+- n++;
+- p--; /* can always return one */
+- }
+- s->mode = DRY;
+- case DRY:
+- FLUSH
+- if (s->read != s->write)
+- LEAVE
+- s->mode = DONEB;
+- case DONEB:
+- r = Z_STREAM_END;
+- LEAVE
+- case BADB:
+- r = Z_DATA_ERROR;
+- LEAVE
+- default:
+- r = Z_STREAM_ERROR;
+- LEAVE
+- }
+-}
+-
+-
+-local int inflate_blocks_free(
+- inflate_blocks_statef *s,
+- z_stream *z,
+- uLongf *c
+-)
+-{
+- inflate_blocks_reset(s, z, c);
+- ZFREE(z, s->window, s->end - s->window);
+- ZFREE(z, s, sizeof(struct inflate_blocks_state));
+- Trace((stderr, "inflate: blocks freed\n"));
+- return Z_OK;
+-}
+-
+-/*
+- * This subroutine adds the data at next_in/avail_in to the output history
+- * without performing any output. The output buffer must be "caught up";
+- * i.e. no pending output (hence s->read equals s->write), and the state must
+- * be BLOCKS (i.e. we should be willing to see the start of a series of
+- * BLOCKS). On exit, the output will also be caught up, and the checksum
+- * will have been updated if need be.
+- */
+-local int inflate_addhistory(
+- inflate_blocks_statef *s,
+- z_stream *z
+-)
+-{
+- uLong b; /* bit buffer */ /* NOT USED HERE */
+- uInt k; /* bits in bit buffer */ /* NOT USED HERE */
+- uInt t; /* temporary storage */
+- Bytef *p; /* input data pointer */
+- uInt n; /* bytes available there */
+- Bytef *q; /* output window write pointer */
+- uInt m; /* bytes to end of window or read pointer */
+-
+- if (s->read != s->write)
+- return Z_STREAM_ERROR;
+- if (s->mode != TYPE)
+- return Z_DATA_ERROR;
+-
+- /* we're ready to rock */
+- LOAD
+- /* while there is input ready, copy to output buffer, moving
+- * pointers as needed.
+- */
+- while (n) {
+- t = n; /* how many to do */
+- /* is there room until end of buffer? */
+- if (t > m) t = m;
+- /* update check information */
+- if (s->checkfn != Z_NULL)
+- s->check = (*s->checkfn)(s->check, q, t);
+- zmemcpy(q, p, t);
+- q += t;
+- p += t;
+- n -= t;
+- z->total_out += t;
+- s->read = q; /* drag read pointer forward */
+-/* WRAP */ /* expand WRAP macro by hand to handle s->read */
+- if (q == s->end) {
+- s->read = q = s->window;
+- m = WAVAIL;
+- }
+- }
+- UPDATE
+- return Z_OK;
+-}
+-
+-
+-/*
+- * At the end of a Deflate-compressed PPP packet, we expect to have seen
+- * a `stored' block type value but not the (zero) length bytes.
+- */
+-local int inflate_packet_flush(
+- inflate_blocks_statef *s
+-)
+-{
+- if (s->mode != LENS)
+- return Z_DATA_ERROR;
+- s->mode = TYPE;
+- return Z_OK;
+-}
+-
+-
+-/*+++++*/
+-/* inftrees.c -- generate Huffman trees for efficient decoding
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* simplify the use of the inflate_huft type with some defines */
+-#define base more.Base
+-#define next more.Next
+-#define exop word.what.Exop
+-#define bits word.what.Bits
+-
+-
+-local int huft_build OF((
+- uIntf *, /* code lengths in bits */
+- uInt, /* number of codes */
+- uInt, /* number of "simple" codes */
+- uIntf *, /* list of base values for non-simple codes */
+- uIntf *, /* list of extra bits for non-simple codes */
+- inflate_huft * FAR*,/* result: starting table */
+- uIntf *, /* maximum lookup bits (returns actual) */
+- z_stream *)); /* for zalloc function */
+-
+-local voidpf falloc OF((
+- voidpf, /* opaque pointer (not used) */
+- uInt, /* number of items */
+- uInt)); /* size of item */
+-
+-local void ffree OF((
+- voidpf q, /* opaque pointer (not used) */
+- voidpf p, /* what to free (not used) */
+- uInt n)); /* number of bytes (not used) */
+-
+-/* Tables for deflate from PKZIP's appnote.txt. */
+-local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
+- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+- /* actually lengths - 2; also see note #13 above about 258 */
+-local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
+- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
+-local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
+- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+- 8193, 12289, 16385, 24577};
+-local uInt cpdext[] = { /* Extra bits for distance codes */
+- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+- 12, 12, 13, 13};
+-
+-/*
+- Huffman code decoding is performed using a multi-level table lookup.
+- The fastest way to decode is to simply build a lookup table whose
+- size is determined by the longest code. However, the time it takes
+- to build this table can also be a factor if the data being decoded
+- is not very long. The most common codes are necessarily the
+- shortest codes, so those codes dominate the decoding time, and hence
+- the speed. The idea is you can have a shorter table that decodes the
+- shorter, more probable codes, and then point to subsidiary tables for
+- the longer codes. The time it costs to decode the longer codes is
+- then traded against the time it takes to make longer tables.
+-
+- This results of this trade are in the variables lbits and dbits
+- below. lbits is the number of bits the first level table for literal/
+- length codes can decode in one step, and dbits is the same thing for
+- the distance codes. Subsequent tables are also less than or equal to
+- those sizes. These values may be adjusted either when all of the
+- codes are shorter than that, in which case the longest code length in
+- bits is used, or when the shortest code is *longer* than the requested
+- table size, in which case the length of the shortest code in bits is
+- used.
+-
+- There are two different values for the two tables, since they code a
+- different number of possibilities each. The literal/length table
+- codes 286 possible values, or in a flat code, a little over eight
+- bits. The distance table codes 30 possible values, or a little less
+- than five bits, flat. The optimum values for speed end up being
+- about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+- The optimum values may differ though from machine to machine, and
+- possibly even between compilers. Your mileage may vary.
+- */
+-
+-
+-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+-#define BMAX 15 /* maximum bit length of any code */
+-#define N_MAX 288 /* maximum number of codes in any set */
+-
+-#ifdef DEBUG_ZLIB
+- uInt inflate_hufts;
+-#endif
+-
+-local int huft_build(
+- uIntf *b, /* code lengths in bits (all assumed <= BMAX) */
+- uInt n, /* number of codes (assumed <= N_MAX) */
+- uInt s, /* number of simple-valued codes (0..s-1) */
+- uIntf *d, /* list of base values for non-simple codes */
+- uIntf *e, /* list of extra bits for non-simple codes */
+- inflate_huft * FAR *t, /* result: starting table */
+- uIntf *m, /* maximum lookup bits, returns actual */
+- z_stream *zs /* for zalloc function */
+-)
+-/* Given a list of code lengths and a maximum table size, make a set of
+- tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+- if the given code set is incomplete (the tables are still built in this
+- case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
+- over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
+-{
+-
+- uInt a; /* counter for codes of length k */
+- uInt c[BMAX+1]; /* bit length count table */
+- uInt f; /* i repeats in table every f entries */
+- int g; /* maximum code length */
+- int h; /* table level */
+- register uInt i; /* counter, current code */
+- register uInt j; /* counter */
+- register int k; /* number of bits in current code */
+- int l; /* bits per table (returned in m) */
+- register uIntf *p; /* pointer into c[], b[], or v[] */
+- inflate_huft *q; /* points to current table */
+- struct inflate_huft_s r; /* table entry for structure assignment */
+- inflate_huft *u[BMAX]; /* table stack */
+- uInt v[N_MAX]; /* values in order of bit length */
+- register int w; /* bits before this table == (l * h) */
+- uInt x[BMAX+1]; /* bit offsets, then code stack */
+- uIntf *xp; /* pointer into x */
+- int y; /* number of dummy codes added */
+- uInt z; /* number of entries in current table */
+-
+-
+- /* Generate counts for each bit length */
+- p = c;
+-#define C0 *p++ = 0;
+-#define C2 C0 C0 C0 C0
+-#define C4 C2 C2 C2 C2
+- C4 /* clear c[]--assume BMAX+1 is 16 */
+- p = b; i = n;
+- do {
+- c[*p++]++; /* assume all entries <= BMAX */
+- } while (--i);
+- if (c[0] == n) /* null input--all zero length codes */
+- {
+- *t = (inflate_huft *)Z_NULL;
+- *m = 0;
+- return Z_DATA_ERROR;
+- }
+-
+-
+- /* Find minimum and maximum length, bound *m by those */
+- l = *m;
+- for (j = 1; j <= BMAX; j++)
+- if (c[j])
+- break;
+- k = j; /* minimum code length */
+- if ((uInt)l < j)
+- l = j;
+- for (i = BMAX; i; i--)
+- if (c[i])
+- break;
+- g = i; /* maximum code length */
+- if ((uInt)l > i)
+- l = i;
+- *m = l;
+-
+-
+- /* Adjust last length count to fill out codes, if needed */
+- for (y = 1 << j; j < i; j++, y <<= 1)
+- if ((y -= c[j]) < 0)
+- return Z_DATA_ERROR;
+- if ((y -= c[i]) < 0)
+- return Z_DATA_ERROR;
+- c[i] += y;
+-
+-
+- /* Generate starting offsets into the value table for each length */
+- x[1] = j = 0;
+- p = c + 1; xp = x + 2;
+- while (--i) { /* note that i == g from above */
+- *xp++ = (j += *p++);
+- }
+-
+-
+- /* Make a table of values in order of bit lengths */
+- p = b; i = 0;
+- do {
+- if ((j = *p++) != 0)
+- v[x[j]++] = i;
+- } while (++i < n);
+- n = x[g]; /* set n to length of v */
+-
+-
+- /* Generate the Huffman codes and for each, make the table entries */
+- x[0] = i = 0; /* first Huffman code is zero */
+- p = v; /* grab values in bit order */
+- h = -1; /* no tables yet--level -1 */
+- w = -l; /* bits decoded == (l * h) */
+- u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+- q = (inflate_huft *)Z_NULL; /* ditto */
+- z = 0; /* ditto */
+-
+- /* go through the bit lengths (k already is bits in shortest code) */
+- for (; k <= g; k++)
+- {
+- a = c[k];
+- while (a--)
+- {
+- /* here i is the Huffman code of length k bits for value *p */
+- /* make tables up to required level */
+- while (k > w + l)
+- {
+- h++;
+- w += l; /* previous table always l bits */
+-
+- /* compute minimum size table less than or equal to l bits */
+- z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */
+- if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+- { /* too few codes for k-w bit table */
+- f -= a + 1; /* deduct codes from patterns left */
+- xp = c + k;
+- if (j < z)
+- while (++j < z) /* try smaller tables up to z bits */
+- {
+- if ((f <<= 1) <= *++xp)
+- break; /* enough codes to use up j bits */
+- f -= *xp; /* else deduct codes from patterns */
+- }
+- }
+- z = 1 << j; /* table entries for j-bit table */
+-
+- /* allocate and link in new table */
+- if ((q = (inflate_huft *)ZALLOC
+- (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+- {
+- if (h)
+- inflate_trees_free(u[0], zs);
+- return Z_MEM_ERROR; /* not enough memory */
+- }
+- q->word.Nalloc = z + 1;
+-#ifdef DEBUG_ZLIB
+- inflate_hufts += z + 1;
+-#endif
+- *t = q + 1; /* link to list for huft_free() */
+- *(t = &(q->next)) = Z_NULL;
+- u[h] = ++q; /* table starts after link */
+-
+- /* connect to last table, if there is one */
+- if (h)
+- {
+- x[h] = i; /* save pattern for backing up */
+- r.bits = (Byte)l; /* bits to dump before this table */
+- r.exop = (Byte)j; /* bits in this table */
+- r.next = q; /* pointer to this table */
+- j = i >> (w - l); /* (get around Turbo C bug) */
+- u[h-1][j] = r; /* connect to last table */
+- }
+- }
+-
+- /* set up table entry in r */
+- r.bits = (Byte)(k - w);
+- if (p >= v + n)
+- r.exop = 128 + 64; /* out of values--invalid code */
+- else if (*p < s)
+- {
+- r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+- r.base = *p++; /* simple code is just the value */
+- }
+- else
+- {
+- r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
+- r.base = d[*p++ - s];
+- }
+-
+- /* fill code-like entries with r */
+- f = 1 << (k - w);
+- for (j = i >> w; j < z; j += f)
+- q[j] = r;
+-
+- /* backwards increment the k-bit code i */
+- for (j = 1 << (k - 1); i & j; j >>= 1)
+- i ^= j;
+- i ^= j;
+-
+- /* backup over finished tables */
+- while ((i & ((1 << w) - 1)) != x[h])
+- {
+- h--; /* don't need to update q */
+- w -= l;
+- }
+- }
+- }
+-
+-
+- /* Return Z_BUF_ERROR if we were given an incomplete table */
+- return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+-}
+-
+-
+-local int inflate_trees_bits(
+- uIntf *c, /* 19 code lengths */
+- uIntf *bb, /* bits tree desired/actual depth */
+- inflate_huft * FAR *tb, /* bits tree result */
+- z_stream *z /* for zfree function */
+-)
+-{
+- int r;
+-
+- r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+- if (r == Z_DATA_ERROR)
+- z->msg = "oversubscribed dynamic bit lengths tree";
+- else if (r == Z_BUF_ERROR)
+- {
+- inflate_trees_free(*tb, z);
+- z->msg = "incomplete dynamic bit lengths tree";
+- r = Z_DATA_ERROR;
+- }
+- return r;
+-}
+-
+-
+-local int inflate_trees_dynamic(
+- uInt nl, /* number of literal/length codes */
+- uInt nd, /* number of distance codes */
+- uIntf *c, /* that many (total) code lengths */
+- uIntf *bl, /* literal desired/actual bit depth */
+- uIntf *bd, /* distance desired/actual bit depth */
+- inflate_huft * FAR *tl, /* literal/length tree result */
+- inflate_huft * FAR *td, /* distance tree result */
+- z_stream *z /* for zfree function */
+-)
+-{
+- int r;
+-
+- /* build literal/length tree */
+- if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
+- {
+- if (r == Z_DATA_ERROR)
+- z->msg = "oversubscribed literal/length tree";
+- else if (r == Z_BUF_ERROR)
+- {
+- inflate_trees_free(*tl, z);
+- z->msg = "incomplete literal/length tree";
+- r = Z_DATA_ERROR;
+- }
+- return r;
+- }
+-
+- /* build distance tree */
+- if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
+- {
+- if (r == Z_DATA_ERROR)
+- z->msg = "oversubscribed literal/length tree";
+- else if (r == Z_BUF_ERROR) {
+-#ifdef PKZIP_BUG_WORKAROUND
+- r = Z_OK;
+- }
+-#else
+- inflate_trees_free(*td, z);
+- z->msg = "incomplete literal/length tree";
+- r = Z_DATA_ERROR;
+- }
+- inflate_trees_free(*tl, z);
+- return r;
+-#endif
+- }
+-
+- /* done */
+- return Z_OK;
+-}
+-
+-
+-/* build fixed tables only once--keep them here */
+-local int fixed_lock = 0;
+-local int fixed_built = 0;
+-#define FIXEDH 530 /* number of hufts used by fixed tables */
+-local uInt fixed_left = FIXEDH;
+-local inflate_huft fixed_mem[FIXEDH];
+-local uInt fixed_bl;
+-local uInt fixed_bd;
+-local inflate_huft *fixed_tl;
+-local inflate_huft *fixed_td;
+-
+-
+-local voidpf falloc(
+- voidpf q, /* opaque pointer (not used) */
+- uInt n, /* number of items */
+- uInt s /* size of item */
+-)
+-{
+- Assert(s == sizeof(inflate_huft) && n <= fixed_left,
+- "inflate_trees falloc overflow");
+- if (q) s++; /* to make some compilers happy */
+- fixed_left -= n;
+- return (voidpf)(fixed_mem + fixed_left);
+-}
+-
+-
+-local void ffree(
+- voidpf q,
+- voidpf p,
+- uInt n
+-)
+-{
+- Assert(0, "inflate_trees ffree called!");
+- if (q) q = p; /* to make some compilers happy */
+-}
+-
+-
+-local int inflate_trees_fixed(
+- uIntf *bl, /* literal desired/actual bit depth */
+- uIntf *bd, /* distance desired/actual bit depth */
+- inflate_huft * FAR *tl, /* literal/length tree result */
+- inflate_huft * FAR *td /* distance tree result */
+-)
+-{
+- /* build fixed tables if not built already--lock out other instances */
+- while (++fixed_lock > 1)
+- fixed_lock--;
+- if (!fixed_built)
+- {
+- int k; /* temporary variable */
+- unsigned c[288]; /* length list for huft_build */
+- z_stream z; /* for falloc function */
+-
+- /* set up fake z_stream for memory routines */
+- z.zalloc = falloc;
+- z.zfree = ffree;
+- z.opaque = Z_NULL;
+-
+- /* literal table */
+- for (k = 0; k < 144; k++)
+- c[k] = 8;
+- for (; k < 256; k++)
+- c[k] = 9;
+- for (; k < 280; k++)
+- c[k] = 7;
+- for (; k < 288; k++)
+- c[k] = 8;
+- fixed_bl = 7;
+- huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+-
+- /* distance table */
+- for (k = 0; k < 30; k++)
+- c[k] = 5;
+- fixed_bd = 5;
+- huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+-
+- /* done */
+- fixed_built = 1;
+- }
+- fixed_lock--;
+- *bl = fixed_bl;
+- *bd = fixed_bd;
+- *tl = fixed_tl;
+- *td = fixed_td;
+- return Z_OK;
+-}
+-
+-
+-local int inflate_trees_free(
+- inflate_huft *t, /* table to free */
+- z_stream *z /* for zfree function */
+-)
+-/* Free the malloc'ed tables built by huft_build(), which makes a linked
+- list of the tables it made, with the links in a dummy first entry of
+- each table. */
+-{
+- register inflate_huft *p, *q;
+-
+- /* Go through linked list, freeing from the malloced (t[-1]) address. */
+- p = t;
+- while (p != Z_NULL)
+- {
+- q = (--p)->next;
+- ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
+- p = q;
+- }
+- return Z_OK;
+-}
+-
+-/*+++++*/
+-/* infcodes.c -- process literals and length/distance pairs
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* simplify the use of the inflate_huft type with some defines */
+-#define base more.Base
+-#define next more.Next
+-#define exop word.what.Exop
+-#define bits word.what.Bits
+-
+-/* inflate codes private state */
+-struct inflate_codes_state {
+-
+- /* mode */
+- enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+- START, /* x: set up for LEN */
+- LEN, /* i: get length/literal/eob next */
+- LENEXT, /* i: getting length extra (have base) */
+- DIST, /* i: get distance next */
+- DISTEXT, /* i: getting distance extra */
+- COPY, /* o: copying bytes in window, waiting for space */
+- LIT, /* o: got literal, waiting for output space */
+- WASH, /* o: got eob, possibly still output waiting */
+- END, /* x: got eob and all data flushed */
+- BADCODE} /* x: got error */
+- mode; /* current inflate_codes mode */
+-
+- /* mode dependent information */
+- uInt len;
+- union {
+- struct {
+- inflate_huft *tree; /* pointer into tree */
+- uInt need; /* bits needed */
+- } code; /* if LEN or DIST, where in tree */
+- uInt lit; /* if LIT, literal */
+- struct {
+- uInt get; /* bits to get for extra */
+- uInt dist; /* distance back to copy from */
+- } copy; /* if EXT or COPY, where and how much */
+- } sub; /* submode */
+-
+- /* mode independent information */
+- Byte lbits; /* ltree bits decoded per branch */
+- Byte dbits; /* dtree bits decoder per branch */
+- inflate_huft *ltree; /* literal/length/eob tree */
+- inflate_huft *dtree; /* distance tree */
+-
+-};
+-
+-
+-local inflate_codes_statef *inflate_codes_new(
+- uInt bl,
+- uInt bd,
+- inflate_huft *tl,
+- inflate_huft *td,
+- z_stream *z
+-)
+-{
+- inflate_codes_statef *c;
+-
+- if ((c = (inflate_codes_statef *)
+- ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+- {
+- c->mode = START;
+- c->lbits = (Byte)bl;
+- c->dbits = (Byte)bd;
+- c->ltree = tl;
+- c->dtree = td;
+- Tracev((stderr, "inflate: codes new\n"));
+- }
+- return c;
+-}
+-
+-
+-local int inflate_codes(
+- inflate_blocks_statef *s,
+- z_stream *z,
+- int r
+-)
+-{
+- uInt j; /* temporary storage */
+- inflate_huft *t; /* temporary pointer */
+- uInt e; /* extra bits or operation */
+- uLong b; /* bit buffer */
+- uInt k; /* bits in bit buffer */
+- Bytef *p; /* input data pointer */
+- uInt n; /* bytes available there */
+- Bytef *q; /* output window write pointer */
+- uInt m; /* bytes to end of window or read pointer */
+- Bytef *f; /* pointer to copy strings from */
+- inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+-
+- /* copy input/output information to locals (UPDATE macro restores) */
+- LOAD
+-
+- /* process input and output based on current state */
+- while (1) switch (c->mode)
+- { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+- case START: /* x: set up for LEN */
+-#ifndef SLOW
+- if (m >= 258 && n >= 10)
+- {
+- UPDATE
+- r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+- LOAD
+- if (r != Z_OK)
+- {
+- c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+- break;
+- }
+- }
+-#endif /* !SLOW */
+- c->sub.code.need = c->lbits;
+- c->sub.code.tree = c->ltree;
+- c->mode = LEN;
+- case LEN: /* i: get length/literal/eob next */
+- j = c->sub.code.need;
+- NEEDBITS(j)
+- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+- DUMPBITS(t->bits)
+- e = (uInt)(t->exop);
+- if (e == 0) /* literal */
+- {
+- c->sub.lit = t->base;
+- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+- "inflate: literal '%c'\n" :
+- "inflate: literal 0x%02x\n", t->base));
+- c->mode = LIT;
+- break;
+- }
+- if (e & 16) /* length */
+- {
+- c->sub.copy.get = e & 15;
+- c->len = t->base;
+- c->mode = LENEXT;
+- break;
+- }
+- if ((e & 64) == 0) /* next table */
+- {
+- c->sub.code.need = e;
+- c->sub.code.tree = t->next;
+- break;
+- }
+- if (e & 32) /* end of block */
+- {
+- Tracevv((stderr, "inflate: end of block\n"));
+- c->mode = WASH;
+- break;
+- }
+- c->mode = BADCODE; /* invalid code */
+- z->msg = "invalid literal/length code";
+- r = Z_DATA_ERROR;
+- LEAVE
+- case LENEXT: /* i: getting length extra (have base) */
+- j = c->sub.copy.get;
+- NEEDBITS(j)
+- c->len += (uInt)b & inflate_mask[j];
+- DUMPBITS(j)
+- c->sub.code.need = c->dbits;
+- c->sub.code.tree = c->dtree;
+- Tracevv((stderr, "inflate: length %u\n", c->len));
+- c->mode = DIST;
+- case DIST: /* i: get distance next */
+- j = c->sub.code.need;
+- NEEDBITS(j)
+- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+- DUMPBITS(t->bits)
+- e = (uInt)(t->exop);
+- if (e & 16) /* distance */
+- {
+- c->sub.copy.get = e & 15;
+- c->sub.copy.dist = t->base;
+- c->mode = DISTEXT;
+- break;
+- }
+- if ((e & 64) == 0) /* next table */
+- {
+- c->sub.code.need = e;
+- c->sub.code.tree = t->next;
+- break;
+- }
+- c->mode = BADCODE; /* invalid code */
+- z->msg = "invalid distance code";
+- r = Z_DATA_ERROR;
+- LEAVE
+- case DISTEXT: /* i: getting distance extra */
+- j = c->sub.copy.get;
+- NEEDBITS(j)
+- c->sub.copy.dist += (uInt)b & inflate_mask[j];
+- DUMPBITS(j)
+- Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+- c->mode = COPY;
+- case COPY: /* o: copying bytes in window, waiting for space */
+-#ifndef __TURBOC__ /* Turbo C bug for following expression */
+- f = (uInt)(q - s->window) < c->sub.copy.dist ?
+- s->end - (c->sub.copy.dist - (q - s->window)) :
+- q - c->sub.copy.dist;
+-#else
+- f = q - c->sub.copy.dist;
+- if ((uInt)(q - s->window) < c->sub.copy.dist)
+- f = s->end - (c->sub.copy.dist - (q - s->window));
+-#endif
+- while (c->len)
+- {
+- NEEDOUT
+- OUTBYTE(*f++)
+- if (f == s->end)
+- f = s->window;
+- c->len--;
+- }
+- c->mode = START;
+- break;
+- case LIT: /* o: got literal, waiting for output space */
+- NEEDOUT
+- OUTBYTE(c->sub.lit)
+- c->mode = START;
+- break;
+- case WASH: /* o: got eob, possibly more output */
+- FLUSH
+- if (s->read != s->write)
+- LEAVE
+- c->mode = END;
+- case END:
+- r = Z_STREAM_END;
+- LEAVE
+- case BADCODE: /* x: got error */
+- r = Z_DATA_ERROR;
+- LEAVE
+- default:
+- r = Z_STREAM_ERROR;
+- LEAVE
+- }
+-}
+-
+-
+-local void inflate_codes_free(
+- inflate_codes_statef *c,
+- z_stream *z
+-)
+-{
+- ZFREE(z, c, sizeof(struct inflate_codes_state));
+- Tracev((stderr, "inflate: codes free\n"));
+-}
+-
+-/*+++++*/
+-/* inflate_util.c -- data and routines common to blocks and codes
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* copy as much as possible from the sliding window to the output area */
+-local int inflate_flush(
+- inflate_blocks_statef *s,
+- z_stream *z,
+- int r
+-)
+-{
+- uInt n;
+- Bytef *p, *q;
+-
+- /* local copies of source and destination pointers */
+- p = z->next_out;
+- q = s->read;
+-
+- /* compute number of bytes to copy as far as end of window */
+- n = (uInt)((q <= s->write ? s->write : s->end) - q);
+- if (n > z->avail_out) n = z->avail_out;
+- if (n && r == Z_BUF_ERROR) r = Z_OK;
+-
+- /* update counters */
+- z->avail_out -= n;
+- z->total_out += n;
+-
+- /* update check information */
+- if (s->checkfn != Z_NULL)
+- s->check = (*s->checkfn)(s->check, q, n);
+-
+- /* copy as far as end of window */
+- zmemcpy(p, q, n);
+- p += n;
+- q += n;
+-
+- /* see if more to copy at beginning of window */
+- if (q == s->end)
+- {
+- /* wrap pointers */
+- q = s->window;
+- if (s->write == s->end)
+- s->write = s->window;
+-
+- /* compute bytes to copy */
+- n = (uInt)(s->write - q);
+- if (n > z->avail_out) n = z->avail_out;
+- if (n && r == Z_BUF_ERROR) r = Z_OK;
+-
+- /* update counters */
+- z->avail_out -= n;
+- z->total_out += n;
+-
+- /* update check information */
+- if (s->checkfn != Z_NULL)
+- s->check = (*s->checkfn)(s->check, q, n);
+-
+- /* copy */
+- zmemcpy(p, q, n);
+- p += n;
+- q += n;
+- }
+-
+- /* update pointers */
+- z->next_out = p;
+- s->read = q;
+-
+- /* done */
+- return r;
+-}
+-
+-
+-/*+++++*/
+-/* inffast.c -- process literals and length/distance pairs fast
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* simplify the use of the inflate_huft type with some defines */
+-#define base more.Base
+-#define next more.Next
+-#define exop word.what.Exop
+-#define bits word.what.Bits
+-
+-/* macros for bit input with no checking and for returning unused bytes */
+-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+-#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
+-
+-/* Called with number of bytes left to write in window at least 258
+- (the maximum string length) and number of input bytes available
+- at least ten. The ten bytes are six bytes for the longest length/
+- distance pair plus four bytes for overloading the bit buffer. */
+-
+-local int inflate_fast(
+- uInt bl,
+- uInt bd,
+- inflate_huft *tl,
+- inflate_huft *td,
+- inflate_blocks_statef *s,
+- z_stream *z
+-)
+-{
+- inflate_huft *t; /* temporary pointer */
+- uInt e; /* extra bits or operation */
+- uLong b; /* bit buffer */
+- uInt k; /* bits in bit buffer */
+- Bytef *p; /* input data pointer */
+- uInt n; /* bytes available there */
+- Bytef *q; /* output window write pointer */
+- uInt m; /* bytes to end of window or read pointer */
+- uInt ml; /* mask for literal/length tree */
+- uInt md; /* mask for distance tree */
+- uInt c; /* bytes to copy */
+- uInt d; /* distance back to copy from */
+- Bytef *r; /* copy source pointer */
+-
+- /* load input, output, bit values */
+- LOAD
+-
+- /* initialize masks */
+- ml = inflate_mask[bl];
+- md = inflate_mask[bd];
+-
+- /* do until not enough input or output space for fast loop */
+- do { /* assume called with m >= 258 && n >= 10 */
+- /* get literal/length code */
+- GRABBITS(20) /* max bits for literal/length code */
+- if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+- {
+- DUMPBITS(t->bits)
+- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+- "inflate: * literal '%c'\n" :
+- "inflate: * literal 0x%02x\n", t->base));
+- *q++ = (Byte)t->base;
+- m--;
+- continue;
+- }
+- do {
+- DUMPBITS(t->bits)
+- if (e & 16)
+- {
+- /* get extra bits for length */
+- e &= 15;
+- c = t->base + ((uInt)b & inflate_mask[e]);
+- DUMPBITS(e)
+- Tracevv((stderr, "inflate: * length %u\n", c));
+-
+- /* decode distance base of block to copy */
+- GRABBITS(15); /* max bits for distance code */
+- e = (t = td + ((uInt)b & md))->exop;
+- do {
+- DUMPBITS(t->bits)
+- if (e & 16)
+- {
+- /* get extra bits to add to distance base */
+- e &= 15;
+- GRABBITS(e) /* get extra bits (up to 13) */
+- d = t->base + ((uInt)b & inflate_mask[e]);
+- DUMPBITS(e)
+- Tracevv((stderr, "inflate: * distance %u\n", d));
+-
+- /* do the copy */
+- m -= c;
+- if ((uInt)(q - s->window) >= d) /* offset before dest */
+- { /* just copy */
+- r = q - d;
+- *q++ = *r++; c--; /* minimum count is three, */
+- *q++ = *r++; c--; /* so unroll loop a little */
+- }
+- else /* else offset after destination */
+- {
+- e = d - (q - s->window); /* bytes from offset to end */
+- r = s->end - e; /* pointer to offset */
+- if (c > e) /* if source crosses, */
+- {
+- c -= e; /* copy to end of window */
+- do {
+- *q++ = *r++;
+- } while (--e);
+- r = s->window; /* copy rest from start of window */
+- }
+- }
+- do { /* copy all or what's left */
+- *q++ = *r++;
+- } while (--c);
+- break;
+- }
+- else if ((e & 64) == 0)
+- e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+- else
+- {
+- z->msg = "invalid distance code";
+- UNGRAB
+- UPDATE
+- return Z_DATA_ERROR;
+- }
+- } while (1);
+- break;
+- }
+- if ((e & 64) == 0)
+- {
+- if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+- {
+- DUMPBITS(t->bits)
+- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+- "inflate: * literal '%c'\n" :
+- "inflate: * literal 0x%02x\n", t->base));
+- *q++ = (Byte)t->base;
+- m--;
+- break;
+- }
+- }
+- else if (e & 32)
+- {
+- Tracevv((stderr, "inflate: * end of block\n"));
+- UNGRAB
+- UPDATE
+- return Z_STREAM_END;
+- }
+- else
+- {
+- z->msg = "invalid literal/length code";
+- UNGRAB
+- UPDATE
+- return Z_DATA_ERROR;
+- }
+- } while (1);
+- } while (m >= 258 && n >= 10);
+-
+- /* not enough input or output--restore pointers and return */
+- UNGRAB
+- UPDATE
+- return Z_OK;
+-}
+-
+-
+-/*+++++*/
+-/* zutil.c -- target dependent utility functions for the compression library
+- * Copyright (C) 1995 Jean-loup Gailly.
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
+-
+-char *zlib_version = ZLIB_VERSION;
+-
+-char *z_errmsg[] = {
+-"stream end", /* Z_STREAM_END 1 */
+-"", /* Z_OK 0 */
+-"file error", /* Z_ERRNO (-1) */
+-"stream error", /* Z_STREAM_ERROR (-2) */
+-"data error", /* Z_DATA_ERROR (-3) */
+-"insufficient memory", /* Z_MEM_ERROR (-4) */
+-"buffer error", /* Z_BUF_ERROR (-5) */
+-""};
+-
+-
+-/*+++++*/
+-/* adler32.c -- compute the Adler-32 checksum of a data stream
+- * Copyright (C) 1995 Mark Adler
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
+-
+-#define BASE 65521L /* largest prime smaller than 65536 */
+-#define NMAX 5552
+-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+-
+-#define DO1(buf) {s1 += *buf++; s2 += s1;}
+-#define DO2(buf) DO1(buf); DO1(buf);
+-#define DO4(buf) DO2(buf); DO2(buf);
+-#define DO8(buf) DO4(buf); DO4(buf);
+-#define DO16(buf) DO8(buf); DO8(buf);
+-
+-/* ========================================================================= */
+-uLong adler32(
+- uLong adler,
+- Bytef *buf,
+- uInt len
+-)
+-{
+- unsigned long s1 = adler & 0xffff;
+- unsigned long s2 = (adler >> 16) & 0xffff;
+- int k;
+-
+- if (buf == Z_NULL) return 1L;
+-
+- while (len > 0) {
+- k = len < NMAX ? len : NMAX;
+- len -= k;
+- while (k >= 16) {
+- DO16(buf);
+- k -= 16;
+- }
+- if (k != 0) do {
+- DO1(buf);
+- } while (--k);
+- s1 %= BASE;
+- s2 %= BASE;
+- }
+- return (s2 << 16) | s1;
+-}
+diff --git a/arch/ppc64/boot/zlib.h b/arch/ppc64/boot/zlib.h
+deleted file mode 100644
+--- a/arch/ppc64/boot/zlib.h
++++ /dev/null
+@@ -1,432 +0,0 @@
+-/* */
+-
+-/*
+- * This file is derived from zlib.h and zconf.h from the zlib-0.95
+- * distribution by Jean-loup Gailly and Mark Adler, with some additions
+- * by Paul Mackerras to aid in implementing Deflate compression and
+- * decompression for PPP packets.
+- */
+-
+-/*
+- * ==FILEVERSION 960122==
+- *
+- * This marker is used by the Linux installation script to determine
+- * whether an up-to-date version of this file is already installed.
+- */
+-
+-/* zlib.h -- interface of the 'zlib' general purpose compression library
+- version 0.95, Aug 16th, 1995.
+-
+- Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+-
+- This software is provided 'as-is', without any express or implied
+- warranty. In no event will the authors be held liable for any damages
+- arising from the use of this software.
+-
+- Permission is granted to anyone to use this software for any purpose,
+- including commercial applications, and to alter it and redistribute it
+- freely, subject to the following restrictions:
+-
+- 1. The origin of this software must not be misrepresented; you must not
+- claim that you wrote the original software. If you use this software
+- in a product, an acknowledgment in the product documentation would be
+- appreciated but is not required.
+- 2. Altered source versions must be plainly marked as such, and must not be
+- misrepresented as being the original software.
+- 3. This notice may not be removed or altered from any source distribution.
+-
+- Jean-loup Gailly Mark Adler
+- gzip at prep.ai.mit.edu madler at alumni.caltech.edu
+- */
+-
+-#ifndef _ZLIB_H
+-#define _ZLIB_H
+-
+-/* #include "zconf.h" */ /* included directly here */
+-
+-/* zconf.h -- configuration of the zlib compression library
+- * Copyright (C) 1995 Jean-loup Gailly.
+- * For conditions of distribution and use, see copyright notice in zlib.h
+- */
+-
+-/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
+-
+-/*
+- The library does not install any signal handler. It is recommended to
+- add at least a handler for SIGSEGV when decompressing; the library checks
+- the consistency of the input data whenever possible but may go nuts
+- for some forms of corrupted input.
+- */
+-
+-/*
+- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+- * than 64k bytes at a time (needed on systems with 16-bit int).
+- * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
+- * at addresses which are not a multiple of their size.
+- * Under DOS, -DFAR=far or -DFAR=__far may be needed.
+- */
+-
+-#ifndef STDC
+-# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
+-# define STDC
+-# endif
+-#endif
+-
+-#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
+-# include <unix.h>
+-#endif
+-
+-/* Maximum value for memLevel in deflateInit2 */
+-#ifndef MAX_MEM_LEVEL
+-# ifdef MAXSEG_64K
+-# define MAX_MEM_LEVEL 8
+-# else
+-# define MAX_MEM_LEVEL 9
+-# endif
+-#endif
+-
+-#ifndef FAR
+-# define FAR
+-#endif
+-
+-/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+-#ifndef MAX_WBITS
+-# define MAX_WBITS 15 /* 32K LZ77 window */
+-#endif
+-
+-/* The memory requirements for deflate are (in bytes):
+- 1 << (windowBits+2) + 1 << (memLevel+9)
+- that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+- plus a few kilobytes for small objects. For example, if you want to reduce
+- the default memory requirements from 256K to 128K, compile with
+- make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+- Of course this will generally degrade compression (there's no free lunch).
+-
+- The memory requirements for inflate are (in bytes) 1 << windowBits
+- that is, 32K for windowBits=15 (default value) plus a few kilobytes
+- for small objects.
+-*/
+-
+- /* Type declarations */
+-
+-#ifndef OF /* function prototypes */
+-# ifdef STDC
+-# define OF(args) args
+-# else
+-# define OF(args) ()
+-# endif
+-#endif
+-
+-typedef unsigned char Byte; /* 8 bits */
+-typedef unsigned int uInt; /* 16 bits or more */
+-typedef unsigned long uLong; /* 32 bits or more */
+-
+-typedef Byte FAR Bytef;
+-typedef char FAR charf;
+-typedef int FAR intf;
+-typedef uInt FAR uIntf;
+-typedef uLong FAR uLongf;
+-
+-#ifdef STDC
+- typedef void FAR *voidpf;
+- typedef void *voidp;
+-#else
+- typedef Byte FAR *voidpf;
+- typedef Byte *voidp;
+-#endif
+-
+-/* end of original zconf.h */
+-
+-#define ZLIB_VERSION "0.95P"
+-
+-/*
+- The 'zlib' compression library provides in-memory compression and
+- decompression functions, including integrity checks of the uncompressed
+- data. This version of the library supports only one compression method
+- (deflation) but other algorithms may be added later and will have the same
+- stream interface.
+-
+- For compression the application must provide the output buffer and
+- may optionally provide the input buffer for optimization. For decompression,
+- the application must provide the input buffer and may optionally provide
+- the output buffer for optimization.
+-
+- Compression can be done in a single step if the buffers are large
+- enough (for example if an input file is mmap'ed), or can be done by
+- repeated calls of the compression function. In the latter case, the
+- application must provide more input and/or consume the output
+- (providing more output space) before each call.
+-*/
+-
+-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+-typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
+-
+-struct internal_state;
+-
+-typedef struct z_stream_s {
+- Bytef *next_in; /* next input byte */
+- uInt avail_in; /* number of bytes available at next_in */
+- uLong total_in; /* total nb of input bytes read so far */
+-
+- Bytef *next_out; /* next output byte should be put there */
+- uInt avail_out; /* remaining free space at next_out */
+- uLong total_out; /* total nb of bytes output so far */
+-
+- char *msg; /* last error message, NULL if no error */
+- struct internal_state FAR *state; /* not visible by applications */
+-
+- alloc_func zalloc; /* used to allocate the internal state */
+- free_func zfree; /* used to free the internal state */
+- voidp opaque; /* private data object passed to zalloc and zfree */
+-
+- Byte data_type; /* best guess about the data type: ascii or binary */
+-
+-} z_stream;
+-
+-/*
+- The application must update next_in and avail_in when avail_in has
+- dropped to zero. It must update next_out and avail_out when avail_out
+- has dropped to zero. The application must initialize zalloc, zfree and
+- opaque before calling the init function. All other fields are set by the
+- compression library and must not be updated by the application.
+-
+- The opaque value provided by the application will be passed as the first
+- parameter for calls of zalloc and zfree. This can be useful for custom
+- memory management. The compression library attaches no meaning to the
+- opaque value.
+-
+- zalloc must return Z_NULL if there is not enough memory for the object.
+- On 16-bit systems, the functions zalloc and zfree must be able to allocate
+- exactly 65536 bytes, but will not be required to allocate more than this
+- if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+- pointers returned by zalloc for objects of exactly 65536 bytes *must*
+- have their offset normalized to zero. The default allocation function
+- provided by this library ensures this (see zutil.c). To reduce memory
+- requirements and avoid any allocation of 64K objects, at the expense of
+- compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+-
+- The fields total_in and total_out can be used for statistics or
+- progress reports. After compression, total_in holds the total size of
+- the uncompressed data and may be saved for use in the decompressor
+- (particularly if the decompressor wants to decompress everything in
+- a single step).
+-*/
+-
+- /* constants */
+-
+-#define Z_NO_FLUSH 0
+-#define Z_PARTIAL_FLUSH 1
+-#define Z_FULL_FLUSH 2
+-#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
+-#define Z_FINISH 4
+-#define Z_PACKET_FLUSH 5
+-/* See deflate() below for the usage of these constants */
+-
+-#define Z_OK 0
+-#define Z_STREAM_END 1
+-#define Z_ERRNO (-1)
+-#define Z_STREAM_ERROR (-2)
+-#define Z_DATA_ERROR (-3)
+-#define Z_MEM_ERROR (-4)
+-#define Z_BUF_ERROR (-5)
+-/* error codes for the compression/decompression functions */
+-
+-#define Z_BEST_SPEED 1
+-#define Z_BEST_COMPRESSION 9
+-#define Z_DEFAULT_COMPRESSION (-1)
+-/* compression levels */
+-
+-#define Z_FILTERED 1
+-#define Z_HUFFMAN_ONLY 2
+-#define Z_DEFAULT_STRATEGY 0
+-
+-#define Z_BINARY 0
+-#define Z_ASCII 1
+-#define Z_UNKNOWN 2
+-/* Used to set the data_type field */
+-
+-#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+-
+-extern char *zlib_version;
+-/* The application can compare zlib_version and ZLIB_VERSION for consistency.
+- If the first character differs, the library code actually used is
+- not compatible with the zlib.h header file used by the application.
+- */
+-
+- /* basic functions */
+-
+-extern int inflateInit OF((z_stream *strm));
+-/*
+- Initializes the internal stream state for decompression. The fields
+- zalloc and zfree must be initialized before by the caller. If zalloc and
+- zfree are set to Z_NULL, inflateInit updates them to use default allocation
+- functions.
+-
+- inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+- enough memory. msg is set to null if there is no error message.
+- inflateInit does not perform any decompression: this will be done by
+- inflate().
+-*/
+-
+-
+-extern int inflate OF((z_stream *strm, int flush));
+-/*
+- Performs one or both of the following actions:
+-
+- - Decompress more input starting at next_in and update next_in and avail_in
+- accordingly. If not all input can be processed (because there is not
+- enough room in the output buffer), next_in is updated and processing
+- will resume at this point for the next call of inflate().
+-
+- - Provide more output starting at next_out and update next_out and avail_out
+- accordingly. inflate() always provides as much output as possible
+- (until there is no more input data or no more space in the output buffer).
+-
+- Before the call of inflate(), the application should ensure that at least
+- one of the actions is possible, by providing more input and/or consuming
+- more output, and updating the next_* and avail_* values accordingly.
+- The application can consume the uncompressed output when it wants, for
+- example when the output buffer is full (avail_out == 0), or after each
+- call of inflate().
+-
+- If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
+- inflate flushes as much output as possible to the output buffer. The
+- flushing behavior of inflate is not specified for values of the flush
+- parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
+- current implementation actually flushes as much output as possible
+- anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
+- has been consumed, it is expecting to see the length field of a stored
+- block; if not, it returns Z_DATA_ERROR.
+-
+- inflate() should normally be called until it returns Z_STREAM_END or an
+- error. However if all decompression is to be performed in a single step
+- (a single call of inflate), the parameter flush should be set to
+- Z_FINISH. In this case all pending input is processed and all pending
+- output is flushed; avail_out must be large enough to hold all the
+- uncompressed data. (The size of the uncompressed data may have been saved
+- by the compressor for this purpose.) The next operation on this stream must
+- be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+- is never required, but can be used to inform inflate that a faster routine
+- may be used for the single inflate() call.
+-
+- inflate() returns Z_OK if some progress has been made (more input
+- processed or more output produced), Z_STREAM_END if the end of the
+- compressed data has been reached and all uncompressed output has been
+- produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
+- the stream structure was inconsistent (for example if next_in or next_out
+- was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
+- progress is possible or if there was not enough room in the output buffer
+- when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
+- call inflateSync to look for a good compression block. */
+-
+-
+-extern int inflateEnd OF((z_stream *strm));
+-/*
+- All dynamically allocated data structures for this stream are freed.
+- This function discards any unprocessed input and does not flush any
+- pending output.
+-
+- inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+- was inconsistent. In the error case, msg may be set but then points to a
+- static string (which must not be deallocated).
+-*/
+-
+- /* advanced functions */
+-
+-extern int inflateInit2 OF((z_stream *strm,
+- int windowBits));
+-/*
+- This is another version of inflateInit with more compression options. The
+- fields next_out, zalloc and zfree must be initialized before by the caller.
+-
+- The windowBits parameter is the base two logarithm of the maximum window
+- size (the size of the history buffer). It should be in the range 8..15 for
+- this version of the library (the value 16 will be allowed soon). The
+- default value is 15 if inflateInit is used instead. If a compressed stream
+- with a larger window size is given as input, inflate() will return with
+- the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+-
+- If next_out is not null, the library will use this buffer for the history
+- buffer; the buffer must either be large enough to hold the entire output
+- data, or have at least 1<<windowBits bytes. If next_out is null, the
+- library will allocate its own buffer (and leave next_out null). next_in
+- need not be provided here but must be provided by the application for the
+- next call of inflate().
+-
+- If the history buffer is provided by the application, next_out must
+- never be changed by the application since the decompressor maintains
+- history information inside this buffer from call to call; the application
+- can only reset next_out to the beginning of the history buffer when
+- avail_out is zero and all output has been consumed.
+-
+- inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+- not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+- windowBits < 8). msg is set to null if there is no error message.
+- inflateInit2 does not perform any decompression: this will be done by
+- inflate().
+-*/
+-
+-extern int inflateSync OF((z_stream *strm));
+-/*
+- Skips invalid compressed data until the special marker (see deflate()
+- above) can be found, or until all available input is skipped. No output
+- is provided.
+-
+- inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+- if no more input was provided, Z_DATA_ERROR if no marker has been found,
+- or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+- case, the application may save the current current value of total_in which
+- indicates where valid compressed data was found. In the error case, the
+- application may repeatedly call inflateSync, providing more input each time,
+- until success or end of the input data.
+-*/
+-
+-extern int inflateReset OF((z_stream *strm));
+-/*
+- This function is equivalent to inflateEnd followed by inflateInit,
+- but does not free and reallocate all the internal decompression state.
+- The stream will keep attributes that may have been set by inflateInit2.
+-
+- inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+- stream state was inconsistent (such as zalloc or state being NULL).
+-*/
+-
+-extern int inflateIncomp OF((z_stream *strm));
+-/*
+- This function adds the data at next_in (avail_in bytes) to the output
+- history without performing any output. There must be no pending output,
+- and the decompressor must be expecting to see the start of a block.
+- Calling this function is equivalent to decompressing a stored block
+- containing the data at next_in (except that the data is not output).
+-*/
+-
+- /* checksum functions */
+-
+-/*
+- This function is not related to compression but is exported
+- anyway because it might be useful in applications using the
+- compression library.
+-*/
+-
+-extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
+-
+-/*
+- Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+- return the updated checksum. If buf is NULL, this function returns
+- the required initial value for the checksum.
+- An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+- much faster. Usage example:
+-
+- uLong adler = adler32(0L, Z_NULL, 0);
+-
+- while (read_buffer(buffer, length) != EOF) {
+- adler = adler32(adler, buffer, length);
+- }
+- if (adler != original_adler) error();
+-*/
+-
+-#ifndef _Z_UTIL_H
+- struct internal_state {int dummy;}; /* hack for buggy compilers */
+-#endif
+-
+-#endif /* _ZLIB_H */
+diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig
+--- a/arch/ppc64/defconfig
++++ b/arch/ppc64/defconfig
+@@ -1318,7 +1318,7 @@ CONFIG_MSDOS_PARTITION=y
+ #
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=m
++CONFIG_NLS_CODEPAGE_437=y
+ CONFIG_NLS_CODEPAGE_737=m
+ CONFIG_NLS_CODEPAGE_775=m
+ CONFIG_NLS_CODEPAGE_850=m
+@@ -1342,7 +1342,7 @@ 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_1=y
+ CONFIG_NLS_ISO8859_2=m
+ CONFIG_NLS_ISO8859_3=m
+ CONFIG_NLS_ISO8859_4=m
+diff --git a/arch/ppc64/kernel/HvCall.c b/arch/ppc64/kernel/HvCall.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/HvCall.c
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+- * HvCall.c
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- */
+-
+-#include <asm/page.h>
+-#include <asm/abs_addr.h>
+-#include <asm/iSeries/HvCall.h>
+-#include <asm/iSeries/HvCallSc.h>
+-#include <asm/iSeries/HvTypes.h>
+-
+-
+-void HvCall_writeLogBuffer(const void *buffer, u64 len)
+-{
+- struct HvLpBufferList hv_buf;
+- u64 left_this_page;
+- u64 cur = virt_to_abs(buffer);
+-
+- while (len) {
+- hv_buf.addr = cur;
+- left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur;
+- if (left_this_page > len)
+- left_this_page = len;
+- hv_buf.len = left_this_page;
+- len -= left_this_page;
+- HvCall2(HvCallBaseWriteLogBuffer,
+- virt_to_abs(&hv_buf),
+- left_this_page);
+- cur = (cur & PAGE_MASK) + PAGE_SIZE;
+- }
+-}
+diff --git a/arch/ppc64/kernel/HvLpConfig.c b/arch/ppc64/kernel/HvLpConfig.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/HvLpConfig.c
++++ /dev/null
+@@ -1,27 +0,0 @@
+-/*
+- * HvLpConfig.c
+- * Copyright (C) 2001 Kyle A. Lucke, IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#include <linux/module.h>
+-#include <asm/iSeries/HvLpConfig.h>
+-
+-HvLpIndex HvLpConfig_getLpIndex_outline(void)
+-{
+- return HvLpConfig_getLpIndex();
+-}
+-EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline);
+diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/HvLpEvent.c
++++ /dev/null
+@@ -1,88 +0,0 @@
+-/*
+- * Copyright 2001 Mike Corrigan IBM Corp
+- *
+- * 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/stddef.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <asm/system.h>
+-#include <asm/iSeries/HvLpEvent.h>
+-#include <asm/iSeries/HvCallEvent.h>
+-#include <asm/iSeries/ItLpNaca.h>
+-
+-/* Array of LpEvent handler functions */
+-LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
+-unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes];
+-
+-/* Register a handler for an LpEvent type */
+-
+-int HvLpEvent_registerHandler( HvLpEvent_Type eventType, LpEventHandler handler )
+-{
+- int rc = 1;
+- if ( eventType < HvLpEvent_Type_NumTypes ) {
+- lpEventHandler[eventType] = handler;
+- rc = 0;
+- }
+- return rc;
+-
+-}
+-
+-int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType )
+-{
+- int rc = 1;
+-
+- might_sleep();
+-
+- if ( eventType < HvLpEvent_Type_NumTypes ) {
+- if ( !lpEventHandlerPaths[eventType] ) {
+- lpEventHandler[eventType] = NULL;
+- rc = 0;
+-
+- /* We now sleep until all other CPUs have scheduled. This ensures that
+- * the deletion is seen by all other CPUs, and that the deleted handler
+- * isn't still running on another CPU when we return. */
+- synchronize_rcu();
+- }
+- }
+- return rc;
+-}
+-EXPORT_SYMBOL(HvLpEvent_registerHandler);
+-EXPORT_SYMBOL(HvLpEvent_unregisterHandler);
+-
+-/* (lpIndex is the partition index of the target partition.
+- * needed only for VirtualIo, VirtualLan and SessionMgr. Zero
+- * indicates to use our partition index - for the other types)
+- */
+-int HvLpEvent_openPath( HvLpEvent_Type eventType, HvLpIndex lpIndex )
+-{
+- int rc = 1;
+- if ( eventType < HvLpEvent_Type_NumTypes &&
+- lpEventHandler[eventType] ) {
+- if ( lpIndex == 0 )
+- lpIndex = itLpNaca.xLpIndex;
+- HvCallEvent_openLpEventPath( lpIndex, eventType );
+- ++lpEventHandlerPaths[eventType];
+- rc = 0;
+- }
+- return rc;
+-}
+-
+-int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex )
+-{
+- int rc = 1;
+- if ( eventType < HvLpEvent_Type_NumTypes &&
+- lpEventHandler[eventType] &&
+- lpEventHandlerPaths[eventType] ) {
+- if ( lpIndex == 0 )
+- lpIndex = itLpNaca.xLpIndex;
+- HvCallEvent_closeLpEventPath( lpIndex, eventType );
+- --lpEventHandlerPaths[eventType];
+- rc = 0;
+- }
+- return rc;
+-}
+-
+diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/ItLpQueue.c
++++ /dev/null
+@@ -1,262 +0,0 @@
+-/*
+- * ItLpQueue.c
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- */
+-
+-#include <linux/stddef.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/seq_file.h>
+-#include <linux/proc_fs.h>
+-#include <asm/system.h>
+-#include <asm/paca.h>
+-#include <asm/iSeries/ItLpQueue.h>
+-#include <asm/iSeries/HvLpEvent.h>
+-#include <asm/iSeries/HvCallEvent.h>
+-
+-/*
+- * The LpQueue is used to pass event data from the hypervisor to
+- * the partition. This is where I/O interrupt events are communicated.
+- *
+- * It is written to by the hypervisor so cannot end up in the BSS.
+- */
+-struct hvlpevent_queue hvlpevent_queue __attribute__((__section__(".data")));
+-
+-DEFINE_PER_CPU(unsigned long[HvLpEvent_Type_NumTypes], hvlpevent_counts);
+-
+-static char *event_types[HvLpEvent_Type_NumTypes] = {
+- "Hypervisor",
+- "Machine Facilities",
+- "Session Manager",
+- "SPD I/O",
+- "Virtual Bus",
+- "PCI I/O",
+- "RIO I/O",
+- "Virtual Lan",
+- "Virtual I/O"
+-};
+-
+-/* Array of LpEvent handler functions */
+-extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
+-
+-static struct HvLpEvent * get_next_hvlpevent(void)
+-{
+- struct HvLpEvent * event;
+- event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
+-
+- if (event->xFlags.xValid) {
+- /* rmb() needed only for weakly consistent machines (regatta) */
+- rmb();
+- /* Set pointer to next potential event */
+- hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 +
+- LpEventAlign) / LpEventAlign) * LpEventAlign;
+-
+- /* Wrap to beginning if no room at end */
+- if (hvlpevent_queue.xSlicCurEventPtr >
+- hvlpevent_queue.xSlicLastValidEventPtr) {
+- hvlpevent_queue.xSlicCurEventPtr =
+- hvlpevent_queue.xSlicEventStackPtr;
+- }
+- } else {
+- event = NULL;
+- }
+-
+- return event;
+-}
+-
+-static unsigned long spread_lpevents = NR_CPUS;
+-
+-int hvlpevent_is_pending(void)
+-{
+- struct HvLpEvent *next_event;
+-
+- if (smp_processor_id() >= spread_lpevents)
+- return 0;
+-
+- next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
+-
+- return next_event->xFlags.xValid |
+- hvlpevent_queue.xPlicOverflowIntPending;
+-}
+-
+-static void hvlpevent_clear_valid(struct HvLpEvent * event)
+-{
+- /* Tell the Hypervisor that we're done with this event.
+- * Also clear bits within this event that might look like valid bits.
+- * ie. on 64-byte boundaries.
+- */
+- struct HvLpEvent *tmp;
+- unsigned extra = ((event->xSizeMinus1 + LpEventAlign) /
+- LpEventAlign) - 1;
+-
+- switch (extra) {
+- case 3:
+- tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);
+- tmp->xFlags.xValid = 0;
+- case 2:
+- tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);
+- tmp->xFlags.xValid = 0;
+- case 1:
+- tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);
+- tmp->xFlags.xValid = 0;
+- }
+-
+- mb();
+-
+- event->xFlags.xValid = 0;
+-}
+-
+-void process_hvlpevents(struct pt_regs *regs)
+-{
+- struct HvLpEvent * event;
+-
+- /* If we have recursed, just return */
+- if (!spin_trylock(&hvlpevent_queue.lock))
+- return;
+-
+- for (;;) {
+- event = get_next_hvlpevent();
+- if (event) {
+- /* Call appropriate handler here, passing
+- * a pointer to the LpEvent. The handler
+- * must make a copy of the LpEvent if it
+- * needs it in a bottom half. (perhaps for
+- * an ACK)
+- *
+- * Handlers are responsible for ACK processing
+- *
+- * The Hypervisor guarantees that LpEvents will
+- * only be delivered with types that we have
+- * registered for, so no type check is necessary
+- * here!
+- */
+- if (event->xType < HvLpEvent_Type_NumTypes)
+- __get_cpu_var(hvlpevent_counts)[event->xType]++;
+- if (event->xType < HvLpEvent_Type_NumTypes &&
+- lpEventHandler[event->xType])
+- lpEventHandler[event->xType](event, regs);
+- else
+- printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
+-
+- hvlpevent_clear_valid(event);
+- } else if (hvlpevent_queue.xPlicOverflowIntPending)
+- /*
+- * No more valid events. If overflow events are
+- * pending process them
+- */
+- HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex);
+- else
+- break;
+- }
+-
+- spin_unlock(&hvlpevent_queue.lock);
+-}
+-
+-static int set_spread_lpevents(char *str)
+-{
+- unsigned long val = simple_strtoul(str, NULL, 0);
+-
+- /*
+- * The parameter is the number of processors to share in processing
+- * lp events.
+- */
+- if (( val > 0) && (val <= NR_CPUS)) {
+- spread_lpevents = val;
+- printk("lpevent processing spread over %ld processors\n", val);
+- } else {
+- printk("invalid spread_lpevents %ld\n", val);
+- }
+-
+- return 1;
+-}
+-__setup("spread_lpevents=", set_spread_lpevents);
+-
+-void setup_hvlpevent_queue(void)
+-{
+- void *eventStack;
+-
+- /*
+- * Allocate a page for the Event Stack. The Hypervisor needs the
+- * absolute real address, so we subtract out the KERNELBASE and add
+- * in the absolute real address of the kernel load area.
+- */
+- eventStack = alloc_bootmem_pages(LpEventStackSize);
+- memset(eventStack, 0, LpEventStackSize);
+-
+- /* Invoke the hypervisor to initialize the event stack */
+- HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);
+-
+- hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack;
+- hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack;
+- hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack +
+- (LpEventStackSize - LpEventMaxSize);
+- hvlpevent_queue.xIndex = 0;
+-}
+-
+-static int proc_lpevents_show(struct seq_file *m, void *v)
+-{
+- int cpu, i;
+- unsigned long sum;
+- static unsigned long cpu_totals[NR_CPUS];
+-
+- /* FIXME: do we care that there's no locking here? */
+- sum = 0;
+- for_each_online_cpu(cpu) {
+- cpu_totals[cpu] = 0;
+- for (i = 0; i < HvLpEvent_Type_NumTypes; i++) {
+- cpu_totals[cpu] += per_cpu(hvlpevent_counts, cpu)[i];
+- }
+- sum += cpu_totals[cpu];
+- }
+-
+- seq_printf(m, "LpEventQueue 0\n");
+- seq_printf(m, " events processed:\t%lu\n", sum);
+-
+- for (i = 0; i < HvLpEvent_Type_NumTypes; ++i) {
+- sum = 0;
+- for_each_online_cpu(cpu) {
+- sum += per_cpu(hvlpevent_counts, cpu)[i];
+- }
+-
+- seq_printf(m, " %-20s %10lu\n", event_types[i], sum);
+- }
+-
+- seq_printf(m, "\n events processed by processor:\n");
+-
+- for_each_online_cpu(cpu) {
+- seq_printf(m, " CPU%02d %10lu\n", cpu, cpu_totals[cpu]);
+- }
+-
+- return 0;
+-}
+-
+-static int proc_lpevents_open(struct inode *inode, struct file *file)
+-{
+- return single_open(file, proc_lpevents_show, NULL);
+-}
+-
+-static struct file_operations proc_lpevents_operations = {
+- .open = proc_lpevents_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = single_release,
+-};
+-
+-static int __init proc_lpevents_init(void)
+-{
+- struct proc_dir_entry *e;
+-
+- e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
+- if (e)
+- e->proc_fops = &proc_lpevents_operations;
+-
+- return 0;
+-}
+-__initcall(proc_lpevents_init);
+-
+diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/LparData.c
++++ /dev/null
+@@ -1,227 +0,0 @@
+-/*
+- * Copyright 2001 Mike Corrigan, IBM Corp
+- *
+- * 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/types.h>
+-#include <linux/threads.h>
+-#include <linux/module.h>
+-#include <linux/bitops.h>
+-#include <asm/processor.h>
+-#include <asm/ptrace.h>
+-#include <asm/naca.h>
+-#include <asm/abs_addr.h>
+-#include <asm/iSeries/ItLpNaca.h>
+-#include <asm/lppaca.h>
+-#include <asm/iSeries/ItLpRegSave.h>
+-#include <asm/paca.h>
+-#include <asm/iSeries/HvReleaseData.h>
+-#include <asm/iSeries/LparMap.h>
+-#include <asm/iSeries/ItVpdAreas.h>
+-#include <asm/iSeries/ItIplParmsReal.h>
+-#include <asm/iSeries/ItExtVpdPanel.h>
+-#include <asm/iSeries/ItLpQueue.h>
+-#include <asm/iSeries/IoHriProcessorVpd.h>
+-#include <asm/iSeries/ItSpCommArea.h>
+-
+-
+-/* The HvReleaseData is the root of the information shared between
+- * the hypervisor and Linux.
+- */
+-struct HvReleaseData hvReleaseData = {
+- .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */
+- .xSize = sizeof(struct HvReleaseData),
+- .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
+- .xSlicNacaAddr = &naca, /* 64-bit Naca address */
+- .xMsNucDataOffset = LPARMAP_PHYS,
+- .xFlags = HVREL_TAGSINACTIVE /* tags inactive */
+- /* 64 bit */
+- /* shared processors */
+- /* HMT allowed */
+- | 6, /* TEMP: This allows non-GA driver */
+- .xVrmIndex = 4, /* We are v5r2m0 */
+- .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */
+- .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */
+- .xVrmName = { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4.64" ebcdic */
+- 0xa7, 0x40, 0xf2, 0x4b,
+- 0xf4, 0x4b, 0xf6, 0xf4 },
+-};
+-
+-/*
+- * The NACA. The first dword of the naca is required by the iSeries
+- * hypervisor to point to itVpdAreas. The hypervisor finds the NACA
+- * through the pointer in hvReleaseData.
+- */
+-struct naca_struct naca = {
+- .xItVpdAreas = &itVpdAreas,
+- .xRamDisk = 0,
+- .xRamDiskSize = 0,
+-};
+-
+-extern void system_reset_iSeries(void);
+-extern void machine_check_iSeries(void);
+-extern void data_access_iSeries(void);
+-extern void instruction_access_iSeries(void);
+-extern void hardware_interrupt_iSeries(void);
+-extern void alignment_iSeries(void);
+-extern void program_check_iSeries(void);
+-extern void fp_unavailable_iSeries(void);
+-extern void decrementer_iSeries(void);
+-extern void trap_0a_iSeries(void);
+-extern void trap_0b_iSeries(void);
+-extern void system_call_iSeries(void);
+-extern void single_step_iSeries(void);
+-extern void trap_0e_iSeries(void);
+-extern void performance_monitor_iSeries(void);
+-extern void data_access_slb_iSeries(void);
+-extern void instruction_access_slb_iSeries(void);
+-
+-struct ItLpNaca itLpNaca = {
+- .xDesc = 0xd397d581, /* "LpNa" ebcdic */
+- .xSize = 0x0400, /* size of ItLpNaca */
+- .xIntHdlrOffset = 0x0300, /* offset to int array */
+- .xMaxIntHdlrEntries = 19, /* # ents */
+- .xPrimaryLpIndex = 0, /* Part # of primary */
+- .xServiceLpIndex = 0, /* Part # of serv */
+- .xLpIndex = 0, /* Part # of me */
+- .xMaxLpQueues = 0, /* # of LP queues */
+- .xLpQueueOffset = 0x100, /* offset of start of LP queues */
+- .xPirEnvironMode = 0, /* Piranha stuff */
+- .xPirConsoleMode = 0,
+- .xPirDasdMode = 0,
+- .xLparInstalled = 0,
+- .xSysPartitioned = 0,
+- .xHwSyncedTBs = 0,
+- .xIntProcUtilHmt = 0,
+- .xSpVpdFormat = 0,
+- .xIntProcRatio = 0,
+- .xPlicVrmIndex = 0, /* VRM index of PLIC */
+- .xMinSupportedSlicVrmInd = 0, /* min supported SLIC */
+- .xMinCompatableSlicVrmInd = 0, /* min compat SLIC */
+- .xLoadAreaAddr = 0, /* 64-bit addr of load area */
+- .xLoadAreaChunks = 0, /* chunks for load area */
+- .xPaseSysCallCRMask = 0, /* PASE mask */
+- .xSlicSegmentTablePtr = 0, /* seg table */
+- .xOldLpQueue = { 0 }, /* Old LP Queue */
+- .xInterruptHdlr = {
+- (u64)system_reset_iSeries, /* 0x100 System Reset */
+- (u64)machine_check_iSeries, /* 0x200 Machine Check */
+- (u64)data_access_iSeries, /* 0x300 Data Access */
+- (u64)instruction_access_iSeries, /* 0x400 Instruction Access */
+- (u64)hardware_interrupt_iSeries, /* 0x500 External */
+- (u64)alignment_iSeries, /* 0x600 Alignment */
+- (u64)program_check_iSeries, /* 0x700 Program Check */
+- (u64)fp_unavailable_iSeries, /* 0x800 FP Unavailable */
+- (u64)decrementer_iSeries, /* 0x900 Decrementer */
+- (u64)trap_0a_iSeries, /* 0xa00 Trap 0A */
+- (u64)trap_0b_iSeries, /* 0xb00 Trap 0B */
+- (u64)system_call_iSeries, /* 0xc00 System Call */
+- (u64)single_step_iSeries, /* 0xd00 Single Step */
+- (u64)trap_0e_iSeries, /* 0xe00 Trap 0E */
+- (u64)performance_monitor_iSeries,/* 0xf00 Performance Monitor */
+- 0, /* int 0x1000 */
+- 0, /* int 0x1010 */
+- 0, /* int 0x1020 CPU ctls */
+- (u64)hardware_interrupt_iSeries, /* SC Ret Hdlr */
+- (u64)data_access_slb_iSeries, /* 0x380 D-SLB */
+- (u64)instruction_access_slb_iSeries /* 0x480 I-SLB */
+- }
+-};
+-EXPORT_SYMBOL(itLpNaca);
+-
+-/* May be filled in by the hypervisor so cannot end up in the BSS */
+-struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
+-
+-/* May be filled in by the hypervisor so cannot end up in the BSS */
+-struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data")));
+-EXPORT_SYMBOL(xItExtVpdPanel);
+-
+-#define maxPhysicalProcessors 32
+-
+-struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
+- {
+- .xInstCacheOperandSize = 32,
+- .xDataCacheOperandSize = 32,
+- .xProcFreq = 50000000,
+- .xTimeBaseFreq = 50000000,
+- .xPVR = 0x3600
+- }
+-};
+-
+-/* Space for Main Store Vpd 27,200 bytes */
+-/* May be filled in by the hypervisor so cannot end up in the BSS */
+-u64 xMsVpd[3400] __attribute__((__section__(".data")));
+-
+-/* Space for Recovery Log Buffer */
+-/* May be filled in by the hypervisor so cannot end up in the BSS */
+-u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
+-
+-struct SpCommArea xSpCommArea = {
+- .xDesc = 0xE2D7C3C2,
+- .xFormat = 1,
+-};
+-
+-/* The LparMap data is now located at offset 0x6000 in head.S
+- * It was put there so that the HvReleaseData could address it
+- * with a 32-bit offset as required by the iSeries hypervisor
+- *
+- * The Naca has a pointer to the ItVpdAreas. The hypervisor finds
+- * the Naca via the HvReleaseData area. The HvReleaseData has the
+- * offset into the Naca of the pointer to the ItVpdAreas.
+- */
+-struct ItVpdAreas itVpdAreas = {
+- .xSlicDesc = 0xc9a3e5c1, /* "ItVA" */
+- .xSlicSize = sizeof(struct ItVpdAreas),
+- .xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */
+- .xSlicDmaEntries = ItDmaMaxEntries, /* # DMA array entries */
+- .xSlicMaxLogicalProcs = NR_CPUS * 2, /* Max logical procs */
+- .xSlicMaxPhysicalProcs = maxPhysicalProcessors, /* Max physical procs */
+- .xSlicDmaToksOffset = offsetof(struct ItVpdAreas, xPlicDmaToks),
+- .xSlicVpdAdrsOffset = offsetof(struct ItVpdAreas, xSlicVpdAdrs),
+- .xSlicDmaLensOffset = offsetof(struct ItVpdAreas, xPlicDmaLens),
+- .xSlicVpdLensOffset = offsetof(struct ItVpdAreas, xSlicVpdLens),
+- .xSlicMaxSlotLabels = 0, /* max slot labels */
+- .xSlicMaxLpQueues = 1, /* max LP queues */
+- .xPlicDmaLens = { 0 }, /* DMA lengths */
+- .xPlicDmaToks = { 0 }, /* DMA tokens */
+- .xSlicVpdLens = { /* VPD lengths */
+- 0,0,0, /* 0 - 2 */
+- sizeof(xItExtVpdPanel), /* 3 Extended VPD */
+- sizeof(struct paca_struct), /* 4 length of Paca */
+- 0, /* 5 */
+- sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
+- 26992, /* 7 length of MS VPD */
+- 0, /* 8 */
+- sizeof(struct ItLpNaca),/* 9 length of LP Naca */
+- 0, /* 10 */
+- 256, /* 11 length of Recovery Log Buf */
+- sizeof(struct SpCommArea), /* 12 length of SP Comm Area */
+- 0,0,0, /* 13 - 15 */
+- sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */
+- 0,0,0,0,0,0, /* 17 - 22 */
+- sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */
+- 0,0 /* 24 - 25 */
+- },
+- .xSlicVpdAdrs = { /* VPD addresses */
+- 0,0,0, /* 0 - 2 */
+- &xItExtVpdPanel, /* 3 Extended VPD */
+- &paca[0], /* 4 first Paca */
+- 0, /* 5 */
+- &xItIplParmsReal, /* 6 IPL parms */
+- &xMsVpd, /* 7 MS Vpd */
+- 0, /* 8 */
+- &itLpNaca, /* 9 LpNaca */
+- 0, /* 10 */
+- &xRecoveryLogBuffer, /* 11 Recovery Log Buffer */
+- &xSpCommArea, /* 12 SP Comm Area */
+- 0,0,0, /* 13 - 15 */
+- &xIoHriProcessorVpd, /* 16 Proc Vpd */
+- 0,0,0,0,0,0, /* 17 - 22 */
+- &hvlpevent_queue, /* 23 Lp Queue */
+- 0,0
+- }
+-};
+diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
+--- a/arch/ppc64/kernel/Makefile
++++ b/arch/ppc64/kernel/Makefile
+@@ -2,36 +2,34 @@
+ # Makefile for the linux ppc64 kernel.
+ #
+
++ifneq ($(CONFIG_PPC_MERGE),y)
++
+ EXTRA_CFLAGS += -mno-minimal-toc
+ extra-y := head.o vmlinux.lds
+
+-obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
+- time.o process.o signal.o syscalls.o misc.o ptrace.o \
+- align.o semaphore.o bitops.o pacaData.o \
+- udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
+- ptrace32.o signal32.o rtc.o init_task.o \
+- lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
+- iommu.o sysfs.o vdso.o pmc.o firmware.o
+-obj-y += vdso32/ vdso64/
++obj-y := misc.o prom.o
++
++endif
+
+-obj-$(CONFIG_PPC_OF) += of_device.o
++obj-y += irq.o idle.o dma.o \
++ signal.o \
++ align.o bitops.o pacaData.o \
++ udbg.o ioctl32.o \
++ rtc.o \
++ cpu_setup_power4.o \
++ iommu.o sysfs.o vdso.o firmware.o
++obj-y += vdso32/ vdso64/
+
+-pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_irq.o \
+- iSeries_VpdInfo.o
+ pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o
+
+ obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y)
+
+-obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
+- iSeries_setup.o ItLpQueue.o hvCall.o \
+- mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
+- iSeries_iommu.o
+-
+-obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o
+-
+-obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
+- pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
+- pSeries_setup.o pSeries_iommu.o udbg_16550.o
++obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o
++ifneq ($(CONFIG_PPC_MERGE),y)
++obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
++endif
++
++obj-$(CONFIG_PPC_PSERIES) += rtasd.o udbg_16550.o
+
+ obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \
+ bpa_iic.o spider-pic.o
+@@ -41,45 +39,36 @@ obj-$(CONFIG_EEH) += eeh.o
+ obj-$(CONFIG_PROC_FS) += proc_ppc64.o
+ obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
+ obj-$(CONFIG_SMP) += smp.o
+-obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
+-obj-$(CONFIG_PPC_RTAS) += rtas.o rtas_pci.o
++obj-$(CONFIG_MODULES) += module.o
++ifneq ($(CONFIG_PPC_MERGE),y)
++obj-$(CONFIG_MODULES) += ppc_ksyms.o
++endif
++obj-$(CONFIG_PPC_RTAS) += rtas_pci.o
+ obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
+ obj-$(CONFIG_SCANLOG) += scanlog.o
+-obj-$(CONFIG_VIOPATH) += viopath.o
+ obj-$(CONFIG_LPARCFG) += lparcfg.o
+ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
++ifneq ($(CONFIG_PPC_MERGE),y)
+ obj-$(CONFIG_BOOTX_TEXT) += btext.o
++endif
+ obj-$(CONFIG_HVCS) += hvcserver.o
+
+-vio-obj-$(CONFIG_PPC_PSERIES) += pSeries_vio.o
+-vio-obj-$(CONFIG_PPC_ISERIES) += iSeries_vio.o
+-obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y)
+-obj-$(CONFIG_XICS) += xics.o
+-obj-$(CONFIG_MPIC) += mpic.o
+-
+-obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \
+- pmac_time.o pmac_nvram.o pmac_low_i2c.o \
+- udbg_scc.o
++obj-$(CONFIG_PPC_PMAC) += udbg_scc.o
+
+-obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \
+- udbg_16550.o
+-
+-obj-$(CONFIG_U3_DART) += u3_iommu.o
++obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
+
+ ifdef CONFIG_SMP
+-obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o
+-obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o
+-obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o
+-obj-$(CONFIG_PPC_BPA) += pSeries_smp.o
++obj-$(CONFIG_PPC_PMAC) += smp-tbsync.o
+ obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o
+ endif
+
+-obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
+
+ CFLAGS_ioctl32.o += -Ifs/
+
++ifneq ($(CONFIG_PPC_MERGE),y)
+ ifeq ($(CONFIG_PPC_ISERIES),y)
+-arch/ppc64/kernel/head.o: arch/ppc64/kernel/lparmap.s
+-AFLAGS_head.o += -Iarch/ppc64/kernel
++arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s
++AFLAGS_head.o += -Iarch/powerpc/kernel
++endif
+ endif
+diff --git a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c
+--- a/arch/ppc64/kernel/align.c
++++ b/arch/ppc64/kernel/align.c
+@@ -313,7 +313,7 @@ fix_alignment(struct pt_regs *regs)
+ /* Doing stfs, have to convert to single */
+ preempt_disable();
+ enable_kernel_fp();
+- cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr);
++ cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread);
+ disable_kernel_fp();
+ preempt_enable();
+ }
+@@ -349,7 +349,7 @@ fix_alignment(struct pt_regs *regs)
+ /* Doing lfs, have to convert to double */
+ preempt_disable();
+ enable_kernel_fp();
+- cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr);
++ cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread);
+ disable_kernel_fp();
+ preempt_enable();
+ }
+diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
+--- a/arch/ppc64/kernel/asm-offsets.c
++++ b/arch/ppc64/kernel/asm-offsets.c
+@@ -46,8 +46,6 @@
+ int main(void)
+ {
+ /* thread struct on stack */
+- DEFINE(THREAD_SHIFT, THREAD_SHIFT);
+- DEFINE(THREAD_SIZE, THREAD_SIZE);
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
+@@ -77,6 +75,7 @@ int main(void)
+ DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
+ DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
+ DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
++ DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
+
+ /* paca */
+ DEFINE(PACA_SIZE, sizeof(struct paca_struct));
+diff --git a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/binfmt_elf32.c
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/*
+- * binfmt_elf32.c: Support 32-bit PPC ELF binaries on Power3 and followons.
+- * based on the SPARC64 version.
+- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem at redhat.com)
+- * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj at ultra.linux.cz)
+- *
+- * Copyright (C) 2000,2001 Ken Aaker (kdaaker at rchland.vnet.ibm.com), IBM Corp
+- * Copyright (C) 2001 Anton Blanchard (anton at au.ibm.com), IBM
+- *
+- * 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.
+- */
+-
+-#define ELF_ARCH EM_PPC
+-#define ELF_CLASS ELFCLASS32
+-#define ELF_DATA ELFDATA2MSB;
+-
+-#include <asm/processor.h>
+-#include <linux/module.h>
+-#include <linux/config.h>
+-#include <linux/elfcore.h>
+-#include <linux/compat.h>
+-
+-#define elf_prstatus elf_prstatus32
+-struct elf_prstatus32
+-{
+- struct elf_siginfo pr_info; /* Info associated with signal */
+- short pr_cursig; /* Current signal */
+- unsigned int pr_sigpend; /* Set of pending signals */
+- unsigned int pr_sighold; /* Set of held signals */
+- pid_t pr_pid;
+- pid_t pr_ppid;
+- pid_t pr_pgrp;
+- pid_t pr_sid;
+- struct compat_timeval pr_utime; /* User time */
+- struct compat_timeval pr_stime; /* System time */
+- struct compat_timeval pr_cutime; /* Cumulative user time */
+- struct compat_timeval pr_cstime; /* Cumulative system time */
+- elf_gregset_t pr_reg; /* General purpose registers. */
+- int pr_fpvalid; /* True if math co-processor being used. */
+-};
+-
+-#define elf_prpsinfo elf_prpsinfo32
+-struct elf_prpsinfo32
+-{
+- char pr_state; /* numeric process state */
+- char pr_sname; /* char for pr_state */
+- char pr_zomb; /* zombie */
+- char pr_nice; /* nice val */
+- unsigned int pr_flag; /* flags */
+- u32 pr_uid;
+- u32 pr_gid;
+- pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+- /* Lots missing */
+- char pr_fname[16]; /* filename of executable */
+- char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
+-};
+-
+-#include <linux/time.h>
+-
+-#undef cputime_to_timeval
+-#define cputime_to_timeval cputime_to_compat_timeval
+-static __inline__ void
+-cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
+-{
+- unsigned long jiffies = cputime_to_jiffies(cputime);
+- value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
+- value->tv_sec = jiffies / HZ;
+-}
+-
+-extern void start_thread32(struct pt_regs *, unsigned long, unsigned long);
+-#undef start_thread
+-#define start_thread start_thread32
+-#define init_elf_binfmt init_elf32_binfmt
+-
+-#include "../../../fs/binfmt_elf.c"
+diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c
+--- a/arch/ppc64/kernel/bpa_iommu.c
++++ b/arch/ppc64/kernel/bpa_iommu.c
+@@ -39,8 +39,8 @@
+ #include <asm/pmac_feature.h>
+ #include <asm/abs_addr.h>
+ #include <asm/system.h>
++#include <asm/ppc-pci.h>
+
+-#include "pci.h"
+ #include "bpa_iommu.h"
+
+ static inline unsigned long
+diff --git a/arch/ppc64/kernel/bpa_setup.c b/arch/ppc64/kernel/bpa_setup.c
+--- a/arch/ppc64/kernel/bpa_setup.c
++++ b/arch/ppc64/kernel/bpa_setup.c
+@@ -43,8 +43,9 @@
+ #include <asm/time.h>
+ #include <asm/nvram.h>
+ #include <asm/cputable.h>
++#include <asm/ppc-pci.h>
++#include <asm/irq.h>
+
+-#include "pci.h"
+ #include "bpa_iic.h"
+ #include "bpa_iommu.h"
+
+@@ -54,7 +55,7 @@
+ #define DBG(fmt...)
+ #endif
+
+-void bpa_get_cpuinfo(struct seq_file *m)
++void bpa_show_cpuinfo(struct seq_file *m)
+ {
+ struct device_node *root;
+ const char *model = "";
+@@ -128,7 +129,7 @@ struct machdep_calls __initdata bpa_md =
+ .probe = bpa_probe,
+ .setup_arch = bpa_setup_arch,
+ .init_early = bpa_init_early,
+- .get_cpuinfo = bpa_get_cpuinfo,
++ .show_cpuinfo = bpa_show_cpuinfo,
+ .restart = rtas_restart,
+ .power_off = rtas_power_off,
+ .halt = rtas_halt,
+diff --git a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c
+--- a/arch/ppc64/kernel/btext.c
++++ b/arch/ppc64/kernel/btext.c
+@@ -18,6 +18,7 @@
+ #include <asm/io.h>
+ #include <asm/lmb.h>
+ #include <asm/processor.h>
++#include <asm/udbg.h>
+
+ #undef NO_SCROLL
+
+@@ -131,6 +132,47 @@ int btext_initialize(struct device_node
+ return 0;
+ }
+
++static void btext_putc(unsigned char c)
++{
++ btext_drawchar(c);
++}
++
++void __init init_boot_display(void)
++{
++ char *name;
++ struct device_node *np = NULL;
++ int rc = -ENODEV;
++
++ printk("trying to initialize btext ...\n");
++
++ name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
++ if (name != NULL) {
++ np = of_find_node_by_path(name);
++ if (np != NULL) {
++ if (strcmp(np->type, "display") != 0) {
++ printk("boot stdout isn't a display !\n");
++ of_node_put(np);
++ np = NULL;
++ }
++ }
++ }
++ if (np)
++ rc = btext_initialize(np);
++ if (rc) {
++ for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
++ if (get_property(np, "linux,opened", NULL)) {
++ printk("trying %s ...\n", np->full_name);
++ rc = btext_initialize(np);
++ printk("result: %d\n", rc);
++ }
++ if (rc == 0)
++ break;
++ }
++ }
++ if (rc == 0 && udbg_putc == NULL)
++ udbg_putc = btext_putc;
++}
++
+
+ /* Calc the base address of a given point (x,y) */
+ static unsigned char * calc_base(int x, int y)
+diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/cputable.c
++++ /dev/null
+@@ -1,308 +0,0 @@
+-/*
+- * arch/ppc64/kernel/cputable.c
+- *
+- * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * Modifications for ppc64:
+- * Copyright (C) 2003 Dave Engebretsen <engebret at us.ibm.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/string.h>
+-#include <linux/sched.h>
+-#include <linux/threads.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-
+-#include <asm/oprofile_impl.h>
+-#include <asm/cputable.h>
+-
+-struct cpu_spec* cur_cpu_spec = NULL;
+-EXPORT_SYMBOL(cur_cpu_spec);
+-
+-/* NOTE:
+- * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's
+- * the responsibility of the appropriate CPU save/restore functions to
+- * eventually copy these settings over. Those save/restore aren't yet
+- * part of the cputable though. That has to be fixed for both ppc32
+- * and ppc64
+- */
+-extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);
+-extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);
+-extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
+-extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
+-
+-
+-/* We only set the altivec features if the kernel was compiled with altivec
+- * support
+- */
+-#ifdef CONFIG_ALTIVEC
+-#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC
+-#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC
+-#else
+-#define CPU_FTR_ALTIVEC_COMP 0
+-#define PPC_FEATURE_HAS_ALTIVEC_COMP 0
+-#endif
+-
+-struct cpu_spec cpu_specs[] = {
+- { /* Power3 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00400000,
+- .cpu_name = "POWER3 (630)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/power3",
+- .oprofile_model = &op_model_rs64,
+-#endif
+- },
+- { /* Power3+ */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00410000,
+- .cpu_name = "POWER3 (630+)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/power3",
+- .oprofile_model = &op_model_rs64,
+-#endif
+- },
+- { /* Northstar */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00330000,
+- .cpu_name = "RS64-II (northstar)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+- CPU_FTR_MMCRA | CPU_FTR_CTRL,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/rs64",
+- .oprofile_model = &op_model_rs64,
+-#endif
+- },
+- { /* Pulsar */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00340000,
+- .cpu_name = "RS64-III (pulsar)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+- CPU_FTR_MMCRA | CPU_FTR_CTRL,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/rs64",
+- .oprofile_model = &op_model_rs64,
+-#endif
+- },
+- { /* I-star */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00360000,
+- .cpu_name = "RS64-III (icestar)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+- CPU_FTR_MMCRA | CPU_FTR_CTRL,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/rs64",
+- .oprofile_model = &op_model_rs64,
+-#endif
+- },
+- { /* S-star */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00370000,
+- .cpu_name = "RS64-IV (sstar)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+- CPU_FTR_MMCRA | CPU_FTR_CTRL,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power3,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/rs64",
+- .oprofile_model = &op_model_rs64,
+-#endif
+- },
+- { /* Power4 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00350000,
+- .cpu_name = "POWER4 (gp)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power4,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/power4",
+- .oprofile_model = &op_model_rs64,
+-#endif
+- },
+- { /* Power4+ */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00380000,
+- .cpu_name = "POWER4+ (gq)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_power4,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/power4",
+- .oprofile_model = &op_model_power4,
+-#endif
+- },
+- { /* PPC970 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00390000,
+- .cpu_name = "PPC970",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+- CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
+- .cpu_user_features = COMMON_USER_PPC64 |
+- PPC_FEATURE_HAS_ALTIVEC_COMP,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_ppc970,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/970",
+- .oprofile_model = &op_model_power4,
+-#endif
+- },
+- { /* PPC970FX */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x003c0000,
+- .cpu_name = "PPC970FX",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+- CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
+- .cpu_user_features = COMMON_USER_PPC64 |
+- PPC_FEATURE_HAS_ALTIVEC_COMP,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 8,
+- .cpu_setup = __setup_cpu_ppc970,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/970",
+- .oprofile_model = &op_model_power4,
+-#endif
+- },
+- { /* PPC970MP */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00440000,
+- .cpu_name = "PPC970MP",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+- CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
+- .cpu_user_features = COMMON_USER_PPC64 |
+- PPC_FEATURE_HAS_ALTIVEC_COMP,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .cpu_setup = __setup_cpu_ppc970,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/970",
+- .oprofile_model = &op_model_power4,
+-#endif
+- },
+- { /* Power5 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x003a0000,
+- .cpu_name = "POWER5 (gr)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
+- CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
+- CPU_FTR_MMCRA_SIHV,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_power4,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/power5",
+- .oprofile_model = &op_model_power4,
+-#endif
+- },
+- { /* Power5 */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x003b0000,
+- .cpu_name = "POWER5 (gs)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
+- CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
+- CPU_FTR_MMCRA_SIHV,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_power4,
+-#ifdef CONFIG_OPROFILE
+- .oprofile_cpu_type = "ppc64/power5",
+- .oprofile_model = &op_model_power4,
+-#endif
+- },
+- { /* BE DD1.x */
+- .pvr_mask = 0xffff0000,
+- .pvr_value = 0x00700000,
+- .cpu_name = "Broadband Engine",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+- CPU_FTR_SMT,
+- .cpu_user_features = COMMON_USER_PPC64 |
+- PPC_FEATURE_HAS_ALTIVEC_COMP,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .cpu_setup = __setup_cpu_be,
+- },
+- { /* default match */
+- .pvr_mask = 0x00000000,
+- .pvr_value = 0x00000000,
+- .cpu_name = "POWER4 (compatible)",
+- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+- CPU_FTR_PPCAS_ARCH_V2,
+- .cpu_user_features = COMMON_USER_PPC64,
+- .icache_bsize = 128,
+- .dcache_bsize = 128,
+- .num_pmcs = 6,
+- .cpu_setup = __setup_cpu_power4,
+- }
+-};
+diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
+--- a/arch/ppc64/kernel/eeh.c
++++ b/arch/ppc64/kernel/eeh.c
+@@ -33,7 +33,7 @@
+ #include <asm/rtas.h>
+ #include <asm/atomic.h>
+ #include <asm/systemcfg.h>
+-#include "pci.h"
++#include <asm/ppc-pci.h>
+
+ #undef DEBUG
+
+diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
+deleted file mode 100644
+--- a/arch/ppc64/kernel/entry.S
++++ /dev/null
+@@ -1,845 +0,0 @@
+-/*
+- * arch/ppc64/kernel/entry.S
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- * Rewritten by Cort Dougan (cort at cs.nmt.edu) for PReP
+- * Copyright (C) 1996 Cort Dougan <cort at cs.nmt.edu>
+- * Adapted for Power Macintosh by Paul Mackerras.
+- * Low-level exception handlers and MMU support
+- * rewritten by Paul Mackerras.
+- * Copyright (C) 1996 Paul Mackerras.
+- * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek at jlc.net).
+- *
+- * This file contains the system call entry code, context switch
+- * code, and exception/interrupt return code for PowerPC.
+- *
+- * 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/errno.h>
+-#include <asm/unistd.h>
+-#include <asm/processor.h>
+-#include <asm/page.h>
+-#include <asm/mmu.h>
+-#include <asm/thread_info.h>
+-#include <asm/ppc_asm.h>
+-#include <asm/asm-offsets.h>
+-#include <asm/cputable.h>
+-
+-#ifdef CONFIG_PPC_ISERIES
+-#define DO_SOFT_DISABLE
+-#endif
+-
+-/*
+- * System calls.
+- */
+- .section ".toc","aw"
+-.SYS_CALL_TABLE:
+- .tc .sys_call_table[TC],.sys_call_table
+-
+-.SYS_CALL_TABLE32:
+- .tc .sys_call_table32[TC],.sys_call_table32
+-
+-/* This value is used to mark exception frames on the stack. */
+-exception_marker:
+- .tc ID_72656773_68657265[TC],0x7265677368657265
+-
+- .section ".text"
+- .align 7
+-
+-#undef SHOW_SYSCALLS
+-
+- .globl system_call_common
+-system_call_common:
+- andi. r10,r12,MSR_PR
+- mr r10,r1
+- addi r1,r1,-INT_FRAME_SIZE
+- beq- 1f
+- ld r1,PACAKSAVE(r13)
+-1: std r10,0(r1)
+- std r11,_NIP(r1)
+- std r12,_MSR(r1)
+- std r0,GPR0(r1)
+- std r10,GPR1(r1)
+- std r2,GPR2(r1)
+- std r3,GPR3(r1)
+- std r4,GPR4(r1)
+- std r5,GPR5(r1)
+- std r6,GPR6(r1)
+- std r7,GPR7(r1)
+- std r8,GPR8(r1)
+- li r11,0
+- std r11,GPR9(r1)
+- std r11,GPR10(r1)
+- std r11,GPR11(r1)
+- std r11,GPR12(r1)
+- std r9,GPR13(r1)
+- crclr so
+- mfcr r9
+- mflr r10
+- li r11,0xc01
+- std r9,_CCR(r1)
+- std r10,_LINK(r1)
+- std r11,_TRAP(r1)
+- mfxer r9
+- mfctr r10
+- std r9,_XER(r1)
+- std r10,_CTR(r1)
+- std r3,ORIG_GPR3(r1)
+- ld r2,PACATOC(r13)
+- addi r9,r1,STACK_FRAME_OVERHEAD
+- ld r11,exception_marker at toc(r2)
+- std r11,-16(r9) /* "regshere" marker */
+-#ifdef CONFIG_PPC_ISERIES
+- /* Hack for handling interrupts when soft-enabling on iSeries */
+- cmpdi cr1,r0,0x5555 /* syscall 0x5555 */
+- andi. r10,r12,MSR_PR /* from kernel */
+- crand 4*cr0+eq,4*cr1+eq,4*cr0+eq
+- beq hardware_interrupt_entry
+- lbz r10,PACAPROCENABLED(r13)
+- std r10,SOFTE(r1)
+-#endif
+- mfmsr r11
+- ori r11,r11,MSR_EE
+- mtmsrd r11,1
+-
+-#ifdef SHOW_SYSCALLS
+- bl .do_show_syscall
+- REST_GPR(0,r1)
+- REST_4GPRS(3,r1)
+- REST_2GPRS(7,r1)
+- addi r9,r1,STACK_FRAME_OVERHEAD
+-#endif
+- clrrdi r11,r1,THREAD_SHIFT
+- li r12,0
+- ld r10,TI_FLAGS(r11)
+- stb r12,TI_SC_NOERR(r11)
+- andi. r11,r10,_TIF_SYSCALL_T_OR_A
+- bne- syscall_dotrace
+-syscall_dotrace_cont:
+- cmpldi 0,r0,NR_syscalls
+- bge- syscall_enosys
+-
+-system_call: /* label this so stack traces look sane */
+-/*
+- * Need to vector to 32 Bit or default sys_call_table here,
+- * based on caller's run-mode / personality.
+- */
+- ld r11,.SYS_CALL_TABLE at toc(2)
+- andi. r10,r10,_TIF_32BIT
+- beq 15f
+- ld r11,.SYS_CALL_TABLE32 at toc(2)
+- clrldi r3,r3,32
+- clrldi r4,r4,32
+- clrldi r5,r5,32
+- clrldi r6,r6,32
+- clrldi r7,r7,32
+- clrldi r8,r8,32
+-15:
+- slwi r0,r0,3
+- ldx r10,r11,r0 /* Fetch system call handler [ptr] */
+- mtctr r10
+- bctrl /* Call handler */
+-
+-syscall_exit:
+-#ifdef SHOW_SYSCALLS
+- std r3,GPR3(r1)
+- bl .do_show_syscall_exit
+- ld r3,GPR3(r1)
+-#endif
+- std r3,RESULT(r1)
+- ld r5,_CCR(r1)
+- li r10,-_LAST_ERRNO
+- cmpld r3,r10
+- clrrdi r12,r1,THREAD_SHIFT
+- bge- syscall_error
+-syscall_error_cont:
+-
+- /* check for syscall tracing or audit */
+- ld r9,TI_FLAGS(r12)
+- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
+- bne- syscall_exit_trace
+-syscall_exit_trace_cont:
+-
+- /* disable interrupts so current_thread_info()->flags can't change,
+- and so that we don't get interrupted after loading SRR0/1. */
+- ld r8,_MSR(r1)
+- andi. r10,r8,MSR_RI
+- beq- unrecov_restore
+- mfmsr r10
+- rldicl r10,r10,48,1
+- rotldi r10,r10,16
+- mtmsrd r10,1
+- ld r9,TI_FLAGS(r12)
+- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+- bne- syscall_exit_work
+- ld r7,_NIP(r1)
+- stdcx. r0,0,r1 /* to clear the reservation */
+- andi. r6,r8,MSR_PR
+- ld r4,_LINK(r1)
+- beq- 1f /* only restore r13 if */
+- ld r13,GPR13(r1) /* returning to usermode */
+-1: ld r2,GPR2(r1)
+- li r12,MSR_RI
+- andc r10,r10,r12
+- mtmsrd r10,1 /* clear MSR.RI */
+- ld r1,GPR1(r1)
+- mtlr r4
+- mtcr r5
+- mtspr SRR0,r7
+- mtspr SRR1,r8
+- rfid
+- b . /* prevent speculative execution */
+-
+-syscall_enosys:
+- li r3,-ENOSYS
+- std r3,RESULT(r1)
+- clrrdi r12,r1,THREAD_SHIFT
+- ld r5,_CCR(r1)
+-
+-syscall_error:
+- lbz r11,TI_SC_NOERR(r12)
+- cmpwi 0,r11,0
+- bne- syscall_error_cont
+- neg r3,r3
+- oris r5,r5,0x1000 /* Set SO bit in CR */
+- std r5,_CCR(r1)
+- b syscall_error_cont
+-
+-/* Traced system call support */
+-syscall_dotrace:
+- bl .save_nvgprs
+- addi r3,r1,STACK_FRAME_OVERHEAD
+- bl .do_syscall_trace_enter
+- ld r0,GPR0(r1) /* Restore original registers */
+- ld r3,GPR3(r1)
+- ld r4,GPR4(r1)
+- ld r5,GPR5(r1)
+- ld r6,GPR6(r1)
+- ld r7,GPR7(r1)
+- ld r8,GPR8(r1)
+- addi r9,r1,STACK_FRAME_OVERHEAD
+- clrrdi r10,r1,THREAD_SHIFT
+- ld r10,TI_FLAGS(r10)
+- b syscall_dotrace_cont
+-
+-syscall_exit_trace:
+- std r3,GPR3(r1)
+- bl .save_nvgprs
+- addi r3,r1,STACK_FRAME_OVERHEAD
+- bl .do_syscall_trace_leave
+- REST_NVGPRS(r1)
+- ld r3,GPR3(r1)
+- ld r5,_CCR(r1)
+- clrrdi r12,r1,THREAD_SHIFT
+- b syscall_exit_trace_cont
+-
+-/* Stuff to do on exit from a system call. */
+-syscall_exit_work:
+- std r3,GPR3(r1)
+- std r5,_CCR(r1)
+- b .ret_from_except_lite
+-
+-/* Save non-volatile GPRs, if not already saved. */
+-_GLOBAL(save_nvgprs)
+- ld r11,_TRAP(r1)
+- andi. r0,r11,1
+- beqlr-
+- SAVE_NVGPRS(r1)
+- clrrdi r0,r11,1
+- std r0,_TRAP(r1)
+- blr
+-
+-/*
+- * The sigsuspend and rt_sigsuspend system calls can call do_signal
+- * and thus put the process into the stopped state where we might
+- * want to examine its user state with ptrace. Therefore we need
+- * to save all the nonvolatile registers (r14 - r31) before calling
+- * the C code. Similarly, fork, vfork and clone need the full
+- * register state on the stack so that it can be copied to the child.
+- */
+-_GLOBAL(ppc32_sigsuspend)
+- bl .save_nvgprs
+- bl .sys32_sigsuspend
+- b 70f
+-
+-_GLOBAL(ppc64_rt_sigsuspend)
+- bl .save_nvgprs
+- bl .sys_rt_sigsuspend
+- b 70f
+-
+-_GLOBAL(ppc32_rt_sigsuspend)
+- bl .save_nvgprs
+- bl .sys32_rt_sigsuspend
+-70: cmpdi 0,r3,0
+- /* If it returned an error, we need to return via syscall_exit to set
+- the SO bit in cr0 and potentially stop for ptrace. */
+- bne syscall_exit
+- /* If sigsuspend() returns zero, we are going into a signal handler. We
+- may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
+-#ifdef CONFIG_AUDIT
+- ld r3,PACACURRENT(r13)
+- ld r4,AUDITCONTEXT(r3)
+- cmpdi 0,r4,0
+- beq .ret_from_except /* No audit_context: Leave immediately. */
+- li r4, 2 /* AUDITSC_FAILURE */
+- li r5,-4 /* It's always -EINTR */
+- bl .audit_syscall_exit
+-#endif
+- b .ret_from_except
+-
+-_GLOBAL(ppc_fork)
+- bl .save_nvgprs
+- bl .sys_fork
+- b syscall_exit
+-
+-_GLOBAL(ppc_vfork)
+- bl .save_nvgprs
+- bl .sys_vfork
+- b syscall_exit
+-
+-_GLOBAL(ppc_clone)
+- bl .save_nvgprs
+- bl .sys_clone
+- b syscall_exit
+-
+-_GLOBAL(ppc32_swapcontext)
+- bl .save_nvgprs
+- bl .sys32_swapcontext
+- b 80f
+-
+-_GLOBAL(ppc64_swapcontext)
+- bl .save_nvgprs
+- bl .sys_swapcontext
+- b 80f
+-
+-_GLOBAL(ppc32_sigreturn)
+- bl .sys32_sigreturn
+- b 80f
+-
+-_GLOBAL(ppc32_rt_sigreturn)
+- bl .sys32_rt_sigreturn
+- b 80f
+-
+-_GLOBAL(ppc64_rt_sigreturn)
+- bl .sys_rt_sigreturn
+-
+-80: cmpdi 0,r3,0
+- blt syscall_exit
+- clrrdi r4,r1,THREAD_SHIFT
+- ld r4,TI_FLAGS(r4)
+- andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
+- beq+ 81f
+- addi r3,r1,STACK_FRAME_OVERHEAD
+- bl .do_syscall_trace_leave
+-81: b .ret_from_except
+-
+-_GLOBAL(ret_from_fork)
+- bl .schedule_tail
+- REST_NVGPRS(r1)
+- li r3,0
+- b syscall_exit
+-
+-/*
+- * This routine switches between two different tasks. The process
+- * state of one is saved on its kernel stack. Then the state
+- * of the other is restored from its kernel stack. The memory
+- * management hardware is updated to the second process's state.
+- * Finally, we can return to the second process, via ret_from_except.
+- * On entry, r3 points to the THREAD for the current task, r4
+- * points to the THREAD for the new task.
+- *
+- * Note: there are two ways to get to the "going out" portion
+- * of this code; either by coming in via the entry (_switch)
+- * or via "fork" which must set up an environment equivalent
+- * to the "_switch" path. If you change this you'll have to change
+- * the fork code also.
+- *
+- * The code which creates the new task context is in 'copy_thread'
+- * in arch/ppc64/kernel/process.c
+- */
+- .align 7
+-_GLOBAL(_switch)
+- mflr r0
+- std r0,16(r1)
+- stdu r1,-SWITCH_FRAME_SIZE(r1)
+- /* r3-r13 are caller saved -- Cort */
+- SAVE_8GPRS(14, r1)
+- SAVE_10GPRS(22, r1)
+- mflr r20 /* Return to switch caller */
+- mfmsr r22
+- li r0, MSR_FP
+-#ifdef CONFIG_ALTIVEC
+-BEGIN_FTR_SECTION
+- oris r0,r0,MSR_VEC at h /* Disable altivec */
+- mfspr r24,SPRN_VRSAVE /* save vrsave register value */
+- std r24,THREAD_VRSAVE(r3)
+-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+-#endif /* CONFIG_ALTIVEC */
+- and. r0,r0,r22
+- beq+ 1f
+- andc r22,r22,r0
+- mtmsrd r22
+- isync
+-1: std r20,_NIP(r1)
+- mfcr r23
+- std r23,_CCR(r1)
+- std r1,KSP(r3) /* Set old stack pointer */
+-
+-#ifdef CONFIG_SMP
+- /* We need a sync somewhere here to make sure that if the
+- * previous task gets rescheduled on another CPU, it sees all
+- * stores it has performed on this one.
+- */
+- sync
+-#endif /* CONFIG_SMP */
+-
+- addi r6,r4,-THREAD /* Convert THREAD to 'current' */
+- std r6,PACACURRENT(r13) /* Set new 'current' */
+-
+- ld r8,KSP(r4) /* new stack pointer */
+-BEGIN_FTR_SECTION
+- clrrdi r6,r8,28 /* get its ESID */
+- clrrdi r9,r1,28 /* get current sp ESID */
+- clrldi. r0,r6,2 /* is new ESID c00000000? */
+- cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */
+- cror eq,4*cr1+eq,eq
+- beq 2f /* if yes, don't slbie it */
+-
+- /* Bolt in the new stack SLB entry */
+- ld r7,KSP_VSID(r4) /* Get new stack's VSID */
+- oris r0,r6,(SLB_ESID_V)@h
+- ori r0,r0,(SLB_NUM_BOLTED-1)@l
+- slbie r6
+- slbie r6 /* Workaround POWER5 < DD2.1 issue */
+- slbmte r7,r0
+- isync
+-
+-2:
+-END_FTR_SECTION_IFSET(CPU_FTR_SLB)
+- clrrdi r7,r8,THREAD_SHIFT /* base of new stack */
+- /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
+- because we don't need to leave the 288-byte ABI gap at the
+- top of the kernel stack. */
+- addi r7,r7,THREAD_SIZE-SWITCH_FRAME_SIZE
+-
+- mr r1,r8 /* start using new stack pointer */
+- std r7,PACAKSAVE(r13)
+-
+- ld r6,_CCR(r1)
+- mtcrf 0xFF,r6
+-
+-#ifdef CONFIG_ALTIVEC
+-BEGIN_FTR_SECTION
+- ld r0,THREAD_VRSAVE(r4)
+- mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
+-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+-#endif /* CONFIG_ALTIVEC */
+-
+- /* r3-r13 are destroyed -- Cort */
+- REST_8GPRS(14, r1)
+- REST_10GPRS(22, r1)
+-
+- /* convert old thread to its task_struct for return value */
+- addi r3,r3,-THREAD
+- ld r7,_NIP(r1) /* Return to _switch caller in new task */
+- mtlr r7
+- addi r1,r1,SWITCH_FRAME_SIZE
+- blr
+-
+- .align 7
+-_GLOBAL(ret_from_except)
+- ld r11,_TRAP(r1)
+- andi. r0,r11,1
+- bne .ret_from_except_lite
+- REST_NVGPRS(r1)
+-
+-_GLOBAL(ret_from_except_lite)
+- /*
+- * Disable interrupts so that current_thread_info()->flags
+- * can't change between when we test it and when we return
+- * from the interrupt.
+- */
+- mfmsr r10 /* Get current interrupt state */
+- rldicl r9,r10,48,1 /* clear MSR_EE */
+- rotldi r9,r9,16
+- mtmsrd r9,1 /* Update machine state */
+-
+-#ifdef CONFIG_PREEMPT
+- clrrdi r9,r1,THREAD_SHIFT /* current_thread_info() */
+- li r0,_TIF_NEED_RESCHED /* bits to check */
+- ld r3,_MSR(r1)
+- ld r4,TI_FLAGS(r9)
+- /* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */
+- rlwimi r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING
+- and. r0,r4,r0 /* check NEED_RESCHED and maybe SIGPENDING */
+- bne do_work
+-
+-#else /* !CONFIG_PREEMPT */
+- ld r3,_MSR(r1) /* Returning to user mode? */
+- andi. r3,r3,MSR_PR
+- beq restore /* if not, just restore regs and return */
+-
+- /* Check current_thread_info()->flags */
+- clrrdi r9,r1,THREAD_SHIFT
+- ld r4,TI_FLAGS(r9)
+- andi. r0,r4,_TIF_USER_WORK_MASK
+- bne do_work
+-#endif
+-
+-restore:
+-#ifdef CONFIG_PPC_ISERIES
+- ld r5,SOFTE(r1)
+- cmpdi 0,r5,0
+- beq 4f
+- /* Check for pending interrupts (iSeries) */
+- ld r3,PACALPPACA+LPPACAANYINT(r13)
+- cmpdi r3,0
+- beq+ 4f /* skip do_IRQ if no interrupts */
+-
+- li r3,0
+- stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */
+- ori r10,r10,MSR_EE
+- mtmsrd r10 /* hard-enable again */
+- addi r3,r1,STACK_FRAME_OVERHEAD
+- bl .do_IRQ
+- b .ret_from_except_lite /* loop back and handle more */
+-
+-4: stb r5,PACAPROCENABLED(r13)
+-#endif
+-
+- ld r3,_MSR(r1)
+- andi. r0,r3,MSR_RI
+- beq- unrecov_restore
+-
+- andi. r0,r3,MSR_PR
+-
+- /*
+- * r13 is our per cpu area, only restore it if we are returning to
+- * userspace
+- */
+- beq 1f
+- REST_GPR(13, r1)
+-1:
+- ld r3,_CTR(r1)
+- ld r0,_LINK(r1)
+- mtctr r3
+- mtlr r0
+- ld r3,_XER(r1)
+- mtspr XER,r3
+-
+- REST_8GPRS(5, r1)
+-
+- stdcx. r0,0,r1 /* to clear the reservation */
+-
+- mfmsr r0
+- li r2, MSR_RI
+- andc r0,r0,r2
+- mtmsrd r0,1
+-
+- ld r0,_MSR(r1)
+- mtspr SRR1,r0
+-
+- ld r2,_CCR(r1)
+- mtcrf 0xFF,r2
+- ld r2,_NIP(r1)
+- mtspr SRR0,r2
+-
+- ld r0,GPR0(r1)
+- ld r2,GPR2(r1)
+- ld r3,GPR3(r1)
+- ld r4,GPR4(r1)
+- ld r1,GPR1(r1)
+-
+- rfid
+- b . /* prevent speculative execution */
+-
+-/* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */
+-do_work:
+-#ifdef CONFIG_PREEMPT
+- andi. r0,r3,MSR_PR /* Returning to user mode? */
+- bne user_work
+- /* Check that preempt_count() == 0 and interrupts are enabled */
+- lwz r8,TI_PREEMPT(r9)
+- cmpwi cr1,r8,0
+-#ifdef CONFIG_PPC_ISERIES
+- ld r0,SOFTE(r1)
+- cmpdi r0,0
+-#else
+- andi. r0,r3,MSR_EE
+-#endif
+- crandc eq,cr1*4+eq,eq
+- bne restore
+- /* here we are preempting the current task */
+-1:
+-#ifdef CONFIG_PPC_ISERIES
+- li r0,1
+- stb r0,PACAPROCENABLED(r13)
+-#endif
+- ori r10,r10,MSR_EE
+- mtmsrd r10,1 /* reenable interrupts */
+- bl .preempt_schedule
+- mfmsr r10
+- clrrdi r9,r1,THREAD_SHIFT
+- rldicl r10,r10,48,1 /* disable interrupts again */
+- rotldi r10,r10,16
+- mtmsrd r10,1
+- ld r4,TI_FLAGS(r9)
+- andi. r0,r4,_TIF_NEED_RESCHED
+- bne 1b
+- b restore
+-
+-user_work:
+-#endif
+- /* Enable interrupts */
+- ori r10,r10,MSR_EE
+- mtmsrd r10,1
+-
+- andi. r0,r4,_TIF_NEED_RESCHED
+- beq 1f
+- bl .schedule
+- b .ret_from_except_lite
+-
+-1: bl .save_nvgprs
+- li r3,0
+- addi r4,r1,STACK_FRAME_OVERHEAD
+- bl .do_signal
+- b .ret_from_except
+-
+-unrecov_restore:
+- addi r3,r1,STACK_FRAME_OVERHEAD
+- bl .unrecoverable_exception
+- b unrecov_restore
+-
+-#ifdef CONFIG_PPC_RTAS
+-/*
+- * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
+- * called with the MMU off.
+- *
+- * In addition, we need to be in 32b mode, at least for now.
+- *
+- * Note: r3 is an input parameter to rtas, so don't trash it...
+- */
+-_GLOBAL(enter_rtas)
+- mflr r0
+- std r0,16(r1)
+- stdu r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */
+-
+- /* Because RTAS is running in 32b mode, it clobbers the high order half
+- * of all registers that it saves. We therefore save those registers
+- * RTAS might touch to the stack. (r0, r3-r13 are caller saved)
+- */
+- SAVE_GPR(2, r1) /* Save the TOC */
+- SAVE_GPR(13, r1) /* Save paca */
+- SAVE_8GPRS(14, r1) /* Save the non-volatiles */
+- SAVE_10GPRS(22, r1) /* ditto */
+-
+- mfcr r4
+- std r4,_CCR(r1)
+- mfctr r5
+- std r5,_CTR(r1)
+- mfspr r6,XER
+- std r6,_XER(r1)
+- mfdar r7
+- std r7,_DAR(r1)
+- mfdsisr r8
+- std r8,_DSISR(r1)
+- mfsrr0 r9
+- std r9,_SRR0(r1)
+- mfsrr1 r10
+- std r10,_SRR1(r1)
+-
+- /* There is no way it is acceptable to get here with interrupts enabled,
+- * check it with the asm equivalent of WARN_ON
+- */
+- mfmsr r6
+- andi. r0,r6,MSR_EE
+-1: tdnei r0,0
+-.section __bug_table,"a"
+- .llong 1b,__LINE__ + 0x1000000, 1f, 2f
+-.previous
+-.section .rodata,"a"
+-1: .asciz __FILE__
+-2: .asciz "enter_rtas"
+-.previous
+-
+- /* Unfortunately, the stack pointer and the MSR are also clobbered,
+- * so they are saved in the PACA which allows us to restore
+- * our original state after RTAS returns.
+- */
+- std r1,PACAR1(r13)
+- std r6,PACASAVEDMSR(r13)
+-
+- /* Setup our real return addr */
+- SET_REG_TO_LABEL(r4,.rtas_return_loc)
+- SET_REG_TO_CONST(r9,KERNELBASE)
+- sub r4,r4,r9
+- mtlr r4
+-
+- li r0,0
+- ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_RI
+- andc r0,r6,r0
+-
+- li r9,1
+- rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
+- ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP
+- andc r6,r0,r9
+- ori r6,r6,MSR_RI
+- sync /* disable interrupts so SRR0/1 */
+- mtmsrd r0 /* don't get trashed */
+-
+- SET_REG_TO_LABEL(r4,rtas)
+- ld r5,RTASENTRY(r4) /* get the rtas->entry value */
+- ld r4,RTASBASE(r4) /* get the rtas->base value */
+-
+- mtspr SRR0,r5
+- mtspr SRR1,r6
+- rfid
+- b . /* prevent speculative execution */
+-
+-_STATIC(rtas_return_loc)
+- /* relocation is off at this point */
+- mfspr r4,SPRG3 /* Get PACA */
+- SET_REG_TO_CONST(r5, KERNELBASE)
+- sub r4,r4,r5 /* RELOC the PACA base pointer */
+-
+- mfmsr r6
+- li r0,MSR_RI
+- andc r6,r6,r0
+- sync
+- mtmsrd r6
+-
+- ld r1,PACAR1(r4) /* Restore our SP */
+- LOADADDR(r3,.rtas_restore_regs)
+- ld r4,PACASAVEDMSR(r4) /* Restore our MSR */
+-
+- mtspr SRR0,r3
+- mtspr SRR1,r4
+- rfid
+- b . /* prevent speculative execution */
+-
+-_STATIC(rtas_restore_regs)
+- /* relocation is on at this point */
+- REST_GPR(2, r1) /* Restore the TOC */
+- REST_GPR(13, r1) /* Restore paca */
+- REST_8GPRS(14, r1) /* Restore the non-volatiles */
+- REST_10GPRS(22, r1) /* ditto */
+-
+- mfspr r13,SPRG3
+-
+- ld r4,_CCR(r1)
+- mtcr r4
+- ld r5,_CTR(r1)
+- mtctr r5
+- ld r6,_XER(r1)
+- mtspr XER,r6
+- ld r7,_DAR(r1)
+- mtdar r7
+- ld r8,_DSISR(r1)
+- mtdsisr r8
+- ld r9,_SRR0(r1)
+- mtsrr0 r9
+- ld r10,_SRR1(r1)
+- mtsrr1 r10
+-
+- addi r1,r1,RTAS_FRAME_SIZE /* Unstack our frame */
+- ld r0,16(r1) /* get return address */
+-
+- mtlr r0
+- blr /* return to caller */
+-
+-#endif /* CONFIG_PPC_RTAS */
+-
+-#ifdef CONFIG_PPC_MULTIPLATFORM
+-
+-_GLOBAL(enter_prom)
+- mflr r0
+- std r0,16(r1)
+- stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+-
+- /* Because PROM is running in 32b mode, it clobbers the high order half
+- * of all registers that it saves. We therefore save those registers
+- * PROM might touch to the stack. (r0, r3-r13 are caller saved)
+- */
+- SAVE_8GPRS(2, r1)
+- SAVE_GPR(13, r1)
+- SAVE_8GPRS(14, r1)
+- SAVE_10GPRS(22, r1)
+- mfcr r4
+- std r4,_CCR(r1)
+- mfctr r5
+- std r5,_CTR(r1)
+- mfspr r6,XER
+- std r6,_XER(r1)
+- mfdar r7
+- std r7,_DAR(r1)
+- mfdsisr r8
+- std r8,_DSISR(r1)
+- mfsrr0 r9
+- std r9,_SRR0(r1)
+- mfsrr1 r10
+- std r10,_SRR1(r1)
+- mfmsr r11
+- std r11,_MSR(r1)
+-
+- /* Get the PROM entrypoint */
+- ld r0,GPR4(r1)
+- mtlr r0
+-
+- /* Switch MSR to 32 bits mode
+- */
+- mfmsr r11
+- li r12,1
+- rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+- andc r11,r11,r12
+- li r12,1
+- rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+- andc r11,r11,r12
+- mtmsrd r11
+- isync
+-
+- /* Restore arguments & enter PROM here... */
+- ld r3,GPR3(r1)
+- blrl
+-
+- /* Just make sure that r1 top 32 bits didn't get
+- * corrupt by OF
+- */
+- rldicl r1,r1,0,32
+-
+- /* Restore the MSR (back to 64 bits) */
+- ld r0,_MSR(r1)
+- mtmsrd r0
+- isync
+-
+- /* Restore other registers */
+- REST_GPR(2, r1)
+- REST_GPR(13, r1)
+- REST_8GPRS(14, r1)
+- REST_10GPRS(22, r1)
+- ld r4,_CCR(r1)
+- mtcr r4
+- ld r5,_CTR(r1)
+- mtctr r5
+- ld r6,_XER(r1)
+- mtspr XER,r6
+- ld r7,_DAR(r1)
+- mtdar r7
+- ld r8,_DSISR(r1)
+- mtdsisr r8
+- ld r9,_SRR0(r1)
+- mtsrr0 r9
+- ld r10,_SRR1(r1)
+- mtsrr1 r10
+-
+- addi r1,r1,PROM_FRAME_SIZE
+- ld r0,16(r1)
+- mtlr r0
+- blr
+-
+-#endif /* CONFIG_PPC_MULTIPLATFORM */
+diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
+--- a/arch/ppc64/kernel/head.S
++++ b/arch/ppc64/kernel/head.S
+@@ -36,6 +36,7 @@
+ #include <asm/setup.h>
+ #include <asm/hvcall.h>
+ #include <asm/iSeries/LparMap.h>
++#include <asm/thread_info.h>
+
+ #ifdef CONFIG_PPC_ISERIES
+ #define DO_SOFT_DISABLE
+@@ -80,7 +81,7 @@ _stext:
+ _GLOBAL(__start)
+ /* NOP this out unconditionally */
+ BEGIN_FTR_SECTION
+- b .__start_initialization_multiplatform
++ b .__start_initialization_multiplatform
+ END_FTR_SECTION(0, 1)
+ #endif /* CONFIG_PPC_MULTIPLATFORM */
+
+@@ -201,22 +202,22 @@ exception_marker:
+ #define EX_CCR 60
+
+ #define EXCEPTION_PROLOG_PSERIES(area, label) \
+- mfspr r13,SPRG3; /* get paca address into r13 */ \
++ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
+ std r9,area+EX_R9(r13); /* save r9 - r12 */ \
+ std r10,area+EX_R10(r13); \
+ std r11,area+EX_R11(r13); \
+ std r12,area+EX_R12(r13); \
+- mfspr r9,SPRG1; \
++ mfspr r9,SPRN_SPRG1; \
+ std r9,area+EX_R13(r13); \
+ mfcr r9; \
+ clrrdi r12,r13,32; /* get high part of &label */ \
+ mfmsr r10; \
+- mfspr r11,SRR0; /* save SRR0 */ \
++ mfspr r11,SPRN_SRR0; /* save SRR0 */ \
+ ori r12,r12,(label)@l; /* virt addr of handler */ \
+ ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
+- mtspr SRR0,r12; \
+- mfspr r12,SRR1; /* and SRR1 */ \
+- mtspr SRR1,r10; \
++ mtspr SPRN_SRR0,r12; \
++ mfspr r12,SPRN_SRR1; /* and SRR1 */ \
++ mtspr SPRN_SRR1,r10; \
+ rfid; \
+ b . /* prevent speculative execution */
+
+@@ -225,12 +226,12 @@ exception_marker:
+ * This code runs with relocation on.
+ */
+ #define EXCEPTION_PROLOG_ISERIES_1(area) \
+- mfspr r13,SPRG3; /* get paca address into r13 */ \
++ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
+ std r9,area+EX_R9(r13); /* save r9 - r12 */ \
+ std r10,area+EX_R10(r13); \
+ std r11,area+EX_R11(r13); \
+ std r12,area+EX_R12(r13); \
+- mfspr r9,SPRG1; \
++ mfspr r9,SPRN_SPRG1; \
+ std r9,area+EX_R13(r13); \
+ mfcr r9
+
+@@ -283,7 +284,7 @@ exception_marker:
+ std r9,_LINK(r1); \
+ mfctr r10; /* save CTR in stackframe */ \
+ std r10,_CTR(r1); \
+- mfspr r11,XER; /* save XER in stackframe */ \
++ mfspr r11,SPRN_XER; /* save XER in stackframe */ \
+ std r11,_XER(r1); \
+ li r9,(n)+1; \
+ std r9,_TRAP(r1); /* set trap number */ \
+@@ -300,7 +301,7 @@ exception_marker:
+ .globl label##_pSeries; \
+ label##_pSeries: \
+ HMT_MEDIUM; \
+- mtspr SPRG1,r13; /* save r13 */ \
++ mtspr SPRN_SPRG1,r13; /* save r13 */ \
+ RUNLATCH_ON(r13); \
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+
+@@ -308,7 +309,7 @@ label##_pSeries: \
+ .globl label##_iSeries; \
+ label##_iSeries: \
+ HMT_MEDIUM; \
+- mtspr SPRG1,r13; /* save r13 */ \
++ mtspr SPRN_SPRG1,r13; /* save r13 */ \
+ RUNLATCH_ON(r13); \
+ EXCEPTION_PROLOG_ISERIES_1(area); \
+ EXCEPTION_PROLOG_ISERIES_2; \
+@@ -318,7 +319,7 @@ label##_iSeries: \
+ .globl label##_iSeries; \
+ label##_iSeries: \
+ HMT_MEDIUM; \
+- mtspr SPRG1,r13; /* save r13 */ \
++ mtspr SPRN_SPRG1,r13; /* save r13 */ \
+ RUNLATCH_ON(r13); \
+ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \
+ lbz r10,PACAPROCENABLED(r13); \
+@@ -388,7 +389,7 @@ __start_interrupts:
+ . = 0x200
+ _machine_check_pSeries:
+ HMT_MEDIUM
+- mtspr SPRG1,r13 /* save r13 */
++ mtspr SPRN_SPRG1,r13 /* save r13 */
+ RUNLATCH_ON(r13)
+ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+
+@@ -396,18 +397,18 @@ _machine_check_pSeries:
+ .globl data_access_pSeries
+ data_access_pSeries:
+ HMT_MEDIUM
+- mtspr SPRG1,r13
++ mtspr SPRN_SPRG1,r13
+ BEGIN_FTR_SECTION
+- mtspr SPRG2,r12
+- mfspr r13,DAR
+- mfspr r12,DSISR
++ mtspr SPRN_SPRG2,r12
++ mfspr r13,SPRN_DAR
++ mfspr r12,SPRN_DSISR
+ srdi r13,r13,60
+ rlwimi r13,r12,16,0x20
+ mfcr r12
+ cmpwi r13,0x2c
+ beq .do_stab_bolted_pSeries
+ mtcrf 0x80,r12
+- mfspr r12,SPRG2
++ mfspr r12,SPRN_SPRG2
+ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common)
+
+@@ -415,19 +416,19 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ .globl data_access_slb_pSeries
+ data_access_slb_pSeries:
+ HMT_MEDIUM
+- mtspr SPRG1,r13
++ mtspr SPRN_SPRG1,r13
+ RUNLATCH_ON(r13)
+- mfspr r13,SPRG3 /* get paca address into r13 */
++ mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
+ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
+ std r10,PACA_EXSLB+EX_R10(r13)
+ std r11,PACA_EXSLB+EX_R11(r13)
+ std r12,PACA_EXSLB+EX_R12(r13)
+ std r3,PACA_EXSLB+EX_R3(r13)
+- mfspr r9,SPRG1
++ mfspr r9,SPRN_SPRG1
+ std r9,PACA_EXSLB+EX_R13(r13)
+ mfcr r9
+- mfspr r12,SRR1 /* and SRR1 */
+- mfspr r3,DAR
++ mfspr r12,SPRN_SRR1 /* and SRR1 */
++ mfspr r3,SPRN_DAR
+ b .do_slb_miss /* Rel. branch works in real mode */
+
+ STD_EXCEPTION_PSERIES(0x400, instruction_access)
+@@ -436,19 +437,19 @@ data_access_slb_pSeries:
+ .globl instruction_access_slb_pSeries
+ instruction_access_slb_pSeries:
+ HMT_MEDIUM
+- mtspr SPRG1,r13
++ mtspr SPRN_SPRG1,r13
+ RUNLATCH_ON(r13)
+- mfspr r13,SPRG3 /* get paca address into r13 */
++ mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
+ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
+ std r10,PACA_EXSLB+EX_R10(r13)
+ std r11,PACA_EXSLB+EX_R11(r13)
+ std r12,PACA_EXSLB+EX_R12(r13)
+ std r3,PACA_EXSLB+EX_R3(r13)
+- mfspr r9,SPRG1
++ mfspr r9,SPRN_SPRG1
+ std r9,PACA_EXSLB+EX_R13(r13)
+ mfcr r9
+- mfspr r12,SRR1 /* and SRR1 */
+- mfspr r3,SRR0 /* SRR0 is faulting address */
++ mfspr r12,SPRN_SRR1 /* and SRR1 */
++ mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
+ b .do_slb_miss /* Rel. branch works in real mode */
+
+ STD_EXCEPTION_PSERIES(0x500, hardware_interrupt)
+@@ -466,15 +467,15 @@ system_call_pSeries:
+ RUNLATCH_ON(r9)
+ mr r9,r13
+ mfmsr r10
+- mfspr r13,SPRG3
+- mfspr r11,SRR0
++ mfspr r13,SPRN_SPRG3
++ mfspr r11,SPRN_SRR0
+ clrrdi r12,r13,32
+ oris r12,r12,system_call_common at h
+ ori r12,r12,system_call_common at l
+- mtspr SRR0,r12
++ mtspr SPRN_SRR0,r12
+ ori r10,r10,MSR_IR|MSR_DR|MSR_RI
+- mfspr r12,SRR1
+- mtspr SRR1,r10
++ mfspr r12,SPRN_SRR1
++ mtspr SPRN_SRR1,r10
+ rfid
+ b . /* prevent speculative execution */
+
+@@ -504,25 +505,25 @@ system_call_pSeries:
+ .align 7
+ _GLOBAL(do_stab_bolted_pSeries)
+ mtcrf 0x80,r12
+- mfspr r12,SPRG2
++ mfspr r12,SPRN_SPRG2
+ EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
+
+ /*
+ * Vectors for the FWNMI option. Share common code.
+ */
+- .globl system_reset_fwnmi
++ .globl system_reset_fwnmi
+ system_reset_fwnmi:
+- HMT_MEDIUM
+- mtspr SPRG1,r13 /* save r13 */
+- RUNLATCH_ON(r13)
+- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13 /* save r13 */
++ RUNLATCH_ON(r13)
++ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+
+- .globl machine_check_fwnmi
++ .globl machine_check_fwnmi
+ machine_check_fwnmi:
+- HMT_MEDIUM
+- mtspr SPRG1,r13 /* save r13 */
+- RUNLATCH_ON(r13)
+- EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
++ HMT_MEDIUM
++ mtspr SPRN_SPRG1,r13 /* save r13 */
++ RUNLATCH_ON(r13)
++ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+
+ #ifdef CONFIG_PPC_ISERIES
+ /*** ISeries-LPAR interrupt handlers ***/
+@@ -531,18 +532,18 @@ machine_check_fwnmi:
+
+ .globl data_access_iSeries
+ data_access_iSeries:
+- mtspr SPRG1,r13
++ mtspr SPRN_SPRG1,r13
+ BEGIN_FTR_SECTION
+- mtspr SPRG2,r12
+- mfspr r13,DAR
+- mfspr r12,DSISR
++ mtspr SPRN_SPRG2,r12
++ mfspr r13,SPRN_DAR
++ mfspr r12,SPRN_DSISR
+ srdi r13,r13,60
+ rlwimi r13,r12,16,0x20
+ mfcr r12
+ cmpwi r13,0x2c
+ beq .do_stab_bolted_iSeries
+ mtcrf 0x80,r12
+- mfspr r12,SPRG2
++ mfspr r12,SPRN_SPRG2
+ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN)
+ EXCEPTION_PROLOG_ISERIES_2
+@@ -550,25 +551,25 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+
+ .do_stab_bolted_iSeries:
+ mtcrf 0x80,r12
+- mfspr r12,SPRG2
++ mfspr r12,SPRN_SPRG2
+ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
+ EXCEPTION_PROLOG_ISERIES_2
+ b .do_stab_bolted
+
+ .globl data_access_slb_iSeries
+ data_access_slb_iSeries:
+- mtspr SPRG1,r13 /* save r13 */
++ mtspr SPRN_SPRG1,r13 /* save r13 */
+ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
+ std r3,PACA_EXSLB+EX_R3(r13)
+ ld r12,PACALPPACA+LPPACASRR1(r13)
+- mfspr r3,DAR
++ mfspr r3,SPRN_DAR
+ b .do_slb_miss
+
+ STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN)
+
+ .globl instruction_access_slb_iSeries
+ instruction_access_slb_iSeries:
+- mtspr SPRG1,r13 /* save r13 */
++ mtspr SPRN_SPRG1,r13 /* save r13 */
+ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
+ std r3,PACA_EXSLB+EX_R3(r13)
+ ld r12,PACALPPACA+LPPACASRR1(r13)
+@@ -586,7 +587,7 @@ instruction_access_slb_iSeries:
+ .globl system_call_iSeries
+ system_call_iSeries:
+ mr r9,r13
+- mfspr r13,SPRG3
++ mfspr r13,SPRN_SPRG3
+ EXCEPTION_PROLOG_ISERIES_2
+ b system_call_common
+
+@@ -596,7 +597,7 @@ system_call_iSeries:
+
+ .globl system_reset_iSeries
+ system_reset_iSeries:
+- mfspr r13,SPRG3 /* Get paca address */
++ mfspr r13,SPRN_SPRG3 /* Get paca address */
+ mfmsr r24
+ ori r24,r24,MSR_RI
+ mtmsrd r24 /* RI on */
+@@ -639,7 +640,7 @@ iSeries_secondary_smp_loop:
+ #endif /* CONFIG_SMP */
+ li r0,-1 /* r0=-1 indicates a Hypervisor call */
+ sc /* Invoke the hypervisor via a system call */
+- mfspr r13,SPRG3 /* Put r13 back ???? */
++ mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */
+ b 1b /* If SMP not configured, secondaries
+ * loop forever */
+
+@@ -656,8 +657,8 @@ hardware_interrupt_iSeries_masked:
+ mtcrf 0x80,r9 /* Restore regs */
+ ld r11,PACALPPACA+LPPACASRR0(r13)
+ ld r12,PACALPPACA+LPPACASRR1(r13)
+- mtspr SRR0,r11
+- mtspr SRR1,r12
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r12
+ ld r9,PACA_EXGEN+EX_R9(r13)
+ ld r10,PACA_EXGEN+EX_R10(r13)
+ ld r11,PACA_EXGEN+EX_R11(r13)
+@@ -713,8 +714,8 @@ bad_stack:
+ std r10,GPR1(r1)
+ std r11,_NIP(r1)
+ std r12,_MSR(r1)
+- mfspr r11,DAR
+- mfspr r12,DSISR
++ mfspr r11,SPRN_DAR
++ mfspr r12,SPRN_DSISR
+ std r11,_DAR(r1)
+ std r12,_DSISR(r1)
+ mflr r10
+@@ -746,6 +747,7 @@ bad_stack:
+ * any task or sent any task a signal, you should use
+ * ret_from_except or ret_from_except_lite instead of this.
+ */
++ .globl fast_exception_return
+ fast_exception_return:
+ ld r12,_MSR(r1)
+ ld r11,_NIP(r1)
+@@ -766,8 +768,8 @@ fast_exception_return:
+ clrrdi r10,r10,2 /* clear RI (LE is 0 already) */
+ mtmsrd r10,1
+
+- mtspr SRR1,r12
+- mtspr SRR0,r11
++ mtspr SPRN_SRR1,r12
++ mtspr SPRN_SRR0,r11
+ REST_4GPRS(10, r1)
+ ld r1,GPR1(r1)
+ rfid
+@@ -788,9 +790,9 @@ unrecov_fer:
+ .globl data_access_common
+ data_access_common:
+ RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */
+- mfspr r10,DAR
++ mfspr r10,SPRN_DAR
+ std r10,PACA_EXGEN+EX_DAR(r13)
+- mfspr r10,DSISR
++ mfspr r10,SPRN_DSISR
+ stw r10,PACA_EXGEN+EX_DSISR(r13)
+ EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
+ ld r3,PACA_EXGEN+EX_DAR(r13)
+@@ -821,9 +823,9 @@ hardware_interrupt_entry:
+ .align 7
+ .globl alignment_common
+ alignment_common:
+- mfspr r10,DAR
++ mfspr r10,SPRN_DAR
+ std r10,PACA_EXGEN+EX_DAR(r13)
+- mfspr r10,DSISR
++ mfspr r10,SPRN_DSISR
+ stw r10,PACA_EXGEN+EX_DSISR(r13)
+ EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)
+ ld r3,PACA_EXGEN+EX_DAR(r13)
+@@ -857,62 +859,6 @@ fp_unavailable_common:
+ bl .kernel_fp_unavailable_exception
+ BUG_OPCODE
+
+-/*
+- * load_up_fpu(unused, unused, tsk)
+- * Disable FP for the task which had the FPU previously,
+- * and save its floating-point registers in its thread_struct.
+- * Enables the FPU for use in the kernel on return.
+- * On SMP we know the fpu is free, since we give it up every
+- * switch (ie, no lazy save of the FP registers).
+- * On entry: r13 == 'current' && last_task_used_math != 'current'
+- */
+-_STATIC(load_up_fpu)
+- mfmsr r5 /* grab the current MSR */
+- ori r5,r5,MSR_FP
+- mtmsrd r5 /* enable use of fpu now */
+- isync
+-/*
+- * For SMP, we don't do lazy FPU switching because it just gets too
+- * horrendously complex, especially when a task switches from one CPU
+- * to another. Instead we call giveup_fpu in switch_to.
+- *
+- */
+-#ifndef CONFIG_SMP
+- ld r3,last_task_used_math at got(r2)
+- ld r4,0(r3)
+- cmpdi 0,r4,0
+- beq 1f
+- /* Save FP state to last_task_used_math's THREAD struct */
+- addi r4,r4,THREAD
+- SAVE_32FPRS(0, r4)
+- mffs fr0
+- stfd fr0,THREAD_FPSCR(r4)
+- /* Disable FP for last_task_used_math */
+- ld r5,PT_REGS(r4)
+- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+- li r6,MSR_FP|MSR_FE0|MSR_FE1
+- andc r4,r4,r6
+- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+-1:
+-#endif /* CONFIG_SMP */
+- /* enable use of FP after return */
+- ld r4,PACACURRENT(r13)
+- addi r5,r4,THREAD /* Get THREAD */
+- ld r4,THREAD_FPEXC_MODE(r5)
+- ori r12,r12,MSR_FP
+- or r12,r12,r4
+- std r12,_MSR(r1)
+- lfd fr0,THREAD_FPSCR(r5)
+- mtfsf 0xff,fr0
+- REST_32FPRS(0, r5)
+-#ifndef CONFIG_SMP
+- /* Update last_task_used_math to 'current' */
+- subi r4,r5,THREAD /* Back to 'current' */
+- std r4,0(r3)
+-#endif /* CONFIG_SMP */
+- /* restore registers and return */
+- b fast_exception_return
+-
+ .align 7
+ .globl altivec_unavailable_common
+ altivec_unavailable_common:
+@@ -1120,7 +1066,7 @@ _GLOBAL(do_stab_bolted)
+
+ /* Hash to the primary group */
+ ld r10,PACASTABVIRT(r13)
+- mfspr r11,DAR
++ mfspr r11,SPRN_DAR
+ srdi r11,r11,28
+ rldimi r10,r11,7,52 /* r10 = first ste of the group */
+
+@@ -1162,7 +1108,7 @@ _GLOBAL(do_stab_bolted)
+ 2: std r9,8(r10) /* Store the vsid part of the ste */
+ eieio
+
+- mfspr r11,DAR /* Get the new esid */
++ mfspr r11,SPRN_DAR /* Get the new esid */
+ clrrdi r11,r11,28 /* Permits a full 32b of ESID */
+ ori r11,r11,0x90 /* Turn on valid and kp */
+ std r11,0(r10) /* Put new entry back into the stab */
+@@ -1182,8 +1128,8 @@ _GLOBAL(do_stab_bolted)
+ clrrdi r10,r10,2
+ mtmsrd r10,1
+
+- mtspr SRR0,r11
+- mtspr SRR1,r12
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r12
+ ld r9,PACA_EXSLB+EX_R9(r13)
+ ld r10,PACA_EXSLB+EX_R10(r13)
+ ld r11,PACA_EXSLB+EX_R11(r13)
+@@ -1229,8 +1175,8 @@ _GLOBAL(do_slb_miss)
+ .machine pop
+
+ #ifdef CONFIG_PPC_ISERIES
+- mtspr SRR0,r11
+- mtspr SRR1,r12
++ mtspr SPRN_SRR0,r11
++ mtspr SPRN_SRR1,r12
+ #endif /* CONFIG_PPC_ISERIES */
+ ld r9,PACA_EXSLB+EX_R9(r13)
+ ld r10,PACA_EXSLB+EX_R10(r13)
+@@ -1253,7 +1199,7 @@ unrecov_slb:
+ *
+ * On iSeries, the hypervisor must fill in at least one entry before
+ * we get control (with relocate on). The address is give to the hv
+- * as a page number (see xLparMap in LparData.c), so this must be at a
++ * as a page number (see xLparMap in lpardata.c), so this must be at a
+ * fixed address (the linker can't compute (u64)&initial_stab >>
+ * PAGE_SHIFT).
+ */
+@@ -1316,7 +1262,7 @@ _GLOBAL(pSeries_secondary_smp_init)
+ mr r3,r24 /* not found, copy phys to r3 */
+ b .kexec_wait /* next kernel might do better */
+
+-2: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
++2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
+ /* From now on, r24 is expected to be logical cpuid */
+ mr r24,r5
+ 3: HMT_LOW
+@@ -1364,6 +1310,7 @@ _STATIC(__start_initialization_iSeries)
+ addi r2,r2,0x4000
+
+ bl .iSeries_early_setup
++ bl .early_setup
+
+ /* relocation is on at this point */
+
+@@ -1554,20 +1501,17 @@ copy_to_here:
+ .section ".text";
+ .align 2 ;
+
+- .globl pmac_secondary_start_1
+-pmac_secondary_start_1:
+- li r24, 1
+- b .pmac_secondary_start
+-
+- .globl pmac_secondary_start_2
+-pmac_secondary_start_2:
+- li r24, 2
+- b .pmac_secondary_start
+-
+- .globl pmac_secondary_start_3
+-pmac_secondary_start_3:
+- li r24, 3
+- b .pmac_secondary_start
++ .globl __secondary_start_pmac_0
++__secondary_start_pmac_0:
++ /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
++ li r24,0
++ b 1f
++ li r24,1
++ b 1f
++ li r24,2
++ b 1f
++ li r24,3
++1:
+
+ _GLOBAL(pmac_secondary_start)
+ /* turn on 64-bit mode */
+@@ -1586,7 +1530,7 @@ _GLOBAL(pmac_secondary_start)
+ LOADADDR(r4, paca) /* Get base vaddr of paca array */
+ mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
+ add r13,r13,r4 /* for this processor. */
+- mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
++ mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
+
+ /* Create a temp kernel stack for use before relocation is on. */
+ ld r1,PACAEMERGSP(r13)
+@@ -1621,7 +1565,7 @@ _GLOBAL(__secondary_start)
+ /* Initialize the page table pointer register. */
+ LOADADDR(r6,_SDR1)
+ ld r6,0(r6) /* get the value of _SDR1 */
+- mtspr SDR1,r6 /* set the htab location */
++ mtspr SPRN_SDR1,r6 /* set the htab location */
+ #endif
+ /* Initialize the first segment table (or SLB) entry */
+ ld r3,PACASTABVIRT(r13) /* get addr of segment table */
+@@ -1650,7 +1594,7 @@ _GLOBAL(__secondary_start)
+ lwz r3,PLATFORM(r3) /* r3 = platform flags */
+ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
+ beq 98f /* branch if result is 0 */
+- mfspr r3,PVR
++ mfspr r3,SPRN_PVR
+ srwi r3,r3,16
+ cmpwi r3,0x37 /* SStar */
+ beq 97f
+@@ -1674,8 +1618,8 @@ _GLOBAL(__secondary_start)
+ #ifdef DO_SOFT_DISABLE
+ ori r4,r4,MSR_EE
+ #endif
+- mtspr SRR0,r3
+- mtspr SRR1,r4
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
+ rfid
+ b . /* prevent speculative execution */
+
+@@ -1737,7 +1681,7 @@ _STATIC(start_here_multiplatform)
+
+ #ifdef CONFIG_HMT
+ /* Start up the second thread on cpu 0 */
+- mfspr r3,PVR
++ mfspr r3,SPRN_PVR
+ srwi r3,r3,16
+ cmpwi r3,0x34 /* Pulsar */
+ beq 90f
+@@ -1797,7 +1741,7 @@ _STATIC(start_here_multiplatform)
+ mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
+ add r13,r13,r24 /* for this processor. */
+ sub r13,r13,r26 /* convert to physical addr */
+- mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */
++ mtspr SPRN_SPRG3,r13 /* PPPBBB: Temp... -Peter */
+
+ /* Do very early kernel initializations, including initial hash table,
+ * stab and slb setup before we turn on relocation. */
+@@ -1814,7 +1758,7 @@ _STATIC(start_here_multiplatform)
+ lwz r3,PLATFORM(r3) /* r3 = platform flags */
+ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
+ beq 98f /* branch if result is 0 */
+- mfspr r3,PVR
++ mfspr r3,SPRN_PVR
+ srwi r3,r3,16
+ cmpwi r3,0x37 /* SStar */
+ beq 97f
+@@ -1838,12 +1782,12 @@ _STATIC(start_here_multiplatform)
+ LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
+ sub r6,r6,r26
+ ld r6,0(r6) /* get the value of _SDR1 */
+- mtspr SDR1,r6 /* set the htab location */
++ mtspr SPRN_SDR1,r6 /* set the htab location */
+ 98:
+ LOADADDR(r3,.start_here_common)
+ SET_REG_TO_CONST(r4, MSR_KERNEL)
+- mtspr SRR0,r3
+- mtspr SRR1,r4
++ mtspr SPRN_SRR0,r3
++ mtspr SPRN_SRR1,r4
+ rfid
+ b . /* prevent speculative execution */
+ #endif /* CONFIG_PPC_MULTIPLATFORM */
+@@ -1874,7 +1818,7 @@ _STATIC(start_here_common)
+ LOADADDR(r24, paca) /* Get base vaddr of paca array */
+ mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */
+ add r13,r13,r24 /* for this processor. */
+- mtspr SPRG3,r13
++ mtspr SPRN_SPRG3,r13
+
+ /* ptr to current */
+ LOADADDR(r4,init_task)
+@@ -1901,7 +1845,7 @@ _STATIC(start_here_common)
+ _GLOBAL(hmt_init)
+ #ifdef CONFIG_HMT
+ LOADADDR(r5, hmt_thread_data)
+- mfspr r7,PVR
++ mfspr r7,SPRN_PVR
+ srwi r7,r7,16
+ cmpwi r7,0x34 /* Pulsar */
+ beq 90f
+@@ -1910,10 +1854,10 @@ _GLOBAL(hmt_init)
+ cmpwi r7,0x37 /* SStar */
+ beq 91f
+ b 101f
+-90: mfspr r6,PIR
++90: mfspr r6,SPRN_PIR
+ andi. r6,r6,0x1f
+ b 92f
+-91: mfspr r6,PIR
++91: mfspr r6,SPRN_PIR
+ andi. r6,r6,0x3ff
+ 92: sldi r4,r24,3
+ stwx r6,r5,r4
+@@ -1924,8 +1868,8 @@ __hmt_secondary_hold:
+ LOADADDR(r5, hmt_thread_data)
+ clrldi r5,r5,4
+ li r7,0
+- mfspr r6,PIR
+- mfspr r8,PVR
++ mfspr r6,SPRN_PIR
++ mfspr r8,SPRN_PVR
+ srwi r8,r8,16
+ cmpwi r8,0x34
+ bne 93f
+@@ -1951,39 +1895,41 @@ __hmt_secondary_hold:
+ _GLOBAL(hmt_start_secondary)
+ LOADADDR(r4,__hmt_secondary_hold)
+ clrldi r4,r4,4
+- mtspr NIADORM, r4
+- mfspr r4, MSRDORM
++ mtspr SPRN_NIADORM, r4
++ mfspr r4, SPRN_MSRDORM
+ li r5, -65
+ and r4, r4, r5
+- mtspr MSRDORM, r4
++ mtspr SPRN_MSRDORM, r4
+ lis r4,0xffef
+ ori r4,r4,0x7403
+- mtspr TSC, r4
++ mtspr SPRN_TSC, r4
+ li r4,0x1f4
+- mtspr TST, r4
+- mfspr r4, HID0
++ mtspr SPRN_TST, r4
++ mfspr r4, SPRN_HID0
+ ori r4, r4, 0x1
+- mtspr HID0, r4
++ mtspr SPRN_HID0, r4
+ mfspr r4, SPRN_CTRLF
+ oris r4, r4, 0x40
+ mtspr SPRN_CTRLT, r4
+ blr
+ #endif
+
+-#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES))
++#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP)
+ _GLOBAL(smp_release_cpus)
+ /* All secondary cpus are spinning on a common
+ * spinloop, release them all now so they can start
+ * to spin on their individual paca spinloops.
+ * For non SMP kernels, the secondary cpus never
+ * get out of the common spinloop.
++ * XXX This does nothing useful on iSeries, secondaries are
++ * already waiting on their paca.
+ */
+ li r3,1
+ LOADADDR(r5,__secondary_hold_spinloop)
+ std r3,0(r5)
+ sync
+ blr
+-#endif /* CONFIG_SMP && !CONFIG_PPC_ISERIES */
++#endif /* CONFIG_SMP */
+
+
+ /*
+@@ -1992,7 +1938,7 @@ _GLOBAL(smp_release_cpus)
+ */
+ .section ".bss"
+
+- .align 12
++ .align PAGE_SHIFT
+
+ .globl empty_zero_page
+ empty_zero_page:
+diff --git a/arch/ppc64/kernel/hvCall.S b/arch/ppc64/kernel/hvCall.S
+deleted file mode 100644
+--- a/arch/ppc64/kernel/hvCall.S
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/*
+- * arch/ppc64/kernel/hvCall.S
+- *
+- *
+- * This file contains the code to perform calls to the
+- * iSeries LPAR hypervisor
+- *
+- * 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 <asm/ppc_asm.h>
+-#include <asm/processor.h>
+-
+- .text
+-
+-/*
+- * Hypervisor call
+- *
+- * Invoke the iSeries hypervisor via the System Call instruction
+- * Parameters are passed to this routine in registers r3 - r10
+- *
+- * r3 contains the HV function to be called
+- * r4-r10 contain the operands to the hypervisor function
+- *
+- */
+-
+-_GLOBAL(HvCall)
+-_GLOBAL(HvCall0)
+-_GLOBAL(HvCall1)
+-_GLOBAL(HvCall2)
+-_GLOBAL(HvCall3)
+-_GLOBAL(HvCall4)
+-_GLOBAL(HvCall5)
+-_GLOBAL(HvCall6)
+-_GLOBAL(HvCall7)
+-
+-
+- mfcr r0
+- std r0,-8(r1)
+- stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1)
+-
+- /* r0 = 0xffffffffffffffff indicates a hypervisor call */
+-
+- li r0,-1
+-
+- /* Invoke the hypervisor */
+-
+- sc
+-
+- ld r1,0(r1)
+- ld r0,-8(r1)
+- mtcrf 0xff,r0
+-
+- /* return to caller, return value in r3 */
+-
+- blr
+-
+-_GLOBAL(HvCall0Ret16)
+-_GLOBAL(HvCall1Ret16)
+-_GLOBAL(HvCall2Ret16)
+-_GLOBAL(HvCall3Ret16)
+-_GLOBAL(HvCall4Ret16)
+-_GLOBAL(HvCall5Ret16)
+-_GLOBAL(HvCall6Ret16)
+-_GLOBAL(HvCall7Ret16)
+-
+- mfcr r0
+- std r0,-8(r1)
+- std r31,-16(r1)
+- stdu r1,-(STACK_FRAME_OVERHEAD+32)(r1)
+-
+- mr r31,r4
+- li r0,-1
+- mr r4,r5
+- mr r5,r6
+- mr r6,r7
+- mr r7,r8
+- mr r8,r9
+- mr r9,r10
+-
+- sc
+-
+- std r3,0(r31)
+- std r4,8(r31)
+-
+- mr r3,r5
+-
+- ld r1,0(r1)
+- ld r0,-8(r1)
+- mtcrf 0xff,r0
+- ld r31,-16(r1)
+-
+- blr
+-
+-
+diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/ppc64/kernel/hvcserver.c
+--- 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/i8259.c b/arch/ppc64/kernel/i8259.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/i8259.c
++++ /dev/null
+@@ -1,177 +0,0 @@
+-/*
+- * c 2001 PPC64 Team, IBM Corp
+- *
+- * 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/stddef.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/signal.h>
+-#include <linux/cache.h>
+-#include <linux/irq.h>
+-#include <linux/interrupt.h>
+-#include <asm/io.h>
+-#include <asm/ppcdebug.h>
+-#include "i8259.h"
+-
+-unsigned char cached_8259[2] = { 0xff, 0xff };
+-#define cached_A1 (cached_8259[0])
+-#define cached_21 (cached_8259[1])
+-
+-static __cacheline_aligned_in_smp DEFINE_SPINLOCK(i8259_lock);
+-
+-static int i8259_pic_irq_offset;
+-static int i8259_present;
+-
+-int i8259_irq(int cpu)
+-{
+- int irq;
+-
+- spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
+- /*
+- * Perform an interrupt acknowledge cycle on controller 1
+- */
+- outb(0x0C, 0x20);
+- irq = inb(0x20) & 7;
+- if (irq == 2)
+- {
+- /*
+- * Interrupt is cascaded so perform interrupt
+- * acknowledge on controller 2
+- */
+- outb(0x0C, 0xA0);
+- irq = (inb(0xA0) & 7) + 8;
+- }
+- else if (irq==7)
+- {
+- /*
+- * This may be a spurious interrupt
+- *
+- * Read the interrupt status register. If the most
+- * significant bit is not set then there is no valid
+- * interrupt
+- */
+- outb(0x0b, 0x20);
+- if(~inb(0x20)&0x80) {
+- spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
+- return -1;
+- }
+- }
+- spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
+- return irq;
+-}
+-
+-static void i8259_mask_and_ack_irq(unsigned int irq_nr)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- if ( irq_nr >= i8259_pic_irq_offset )
+- irq_nr -= i8259_pic_irq_offset;
+-
+- if (irq_nr > 7) {
+- cached_A1 |= 1 << (irq_nr-8);
+- inb(0xA1); /* DUMMY */
+- outb(cached_A1,0xA1);
+- outb(0x20,0xA0); /* Non-specific EOI */
+- outb(0x20,0x20); /* Non-specific EOI to cascade */
+- } else {
+- cached_21 |= 1 << irq_nr;
+- inb(0x21); /* DUMMY */
+- outb(cached_21,0x21);
+- outb(0x20,0x20); /* Non-specific EOI */
+- }
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-}
+-
+-static void i8259_set_irq_mask(int irq_nr)
+-{
+- outb(cached_A1,0xA1);
+- outb(cached_21,0x21);
+-}
+-
+-static void i8259_mask_irq(unsigned int irq_nr)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- if ( irq_nr >= i8259_pic_irq_offset )
+- irq_nr -= i8259_pic_irq_offset;
+- if ( irq_nr < 8 )
+- cached_21 |= 1 << irq_nr;
+- else
+- cached_A1 |= 1 << (irq_nr-8);
+- i8259_set_irq_mask(irq_nr);
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-}
+-
+-static void i8259_unmask_irq(unsigned int irq_nr)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- if ( irq_nr >= i8259_pic_irq_offset )
+- irq_nr -= i8259_pic_irq_offset;
+- if ( irq_nr < 8 )
+- cached_21 &= ~(1 << irq_nr);
+- else
+- cached_A1 &= ~(1 << (irq_nr-8));
+- i8259_set_irq_mask(irq_nr);
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-}
+-
+-static void i8259_end_irq(unsigned int irq)
+-{
+- if (!(get_irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
+- get_irq_desc(irq)->action)
+- i8259_unmask_irq(irq);
+-}
+-
+-struct hw_interrupt_type i8259_pic = {
+- .typename = " i8259 ",
+- .enable = i8259_unmask_irq,
+- .disable = i8259_mask_irq,
+- .ack = i8259_mask_and_ack_irq,
+- .end = i8259_end_irq,
+-};
+-
+-void __init i8259_init(int offset)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&i8259_lock, flags);
+- i8259_pic_irq_offset = offset;
+- i8259_present = 1;
+- /* init master interrupt controller */
+- outb(0x11, 0x20); /* Start init sequence */
+- outb(0x00, 0x21); /* Vector base */
+- outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+- outb(0x01, 0x21); /* Select 8086 mode */
+- outb(0xFF, 0x21); /* Mask all */
+- /* init slave interrupt controller */
+- outb(0x11, 0xA0); /* Start init sequence */
+- outb(0x08, 0xA1); /* Vector base */
+- outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+- outb(0x01, 0xA1); /* Select 8086 mode */
+- outb(0xFF, 0xA1); /* Mask all */
+- outb(cached_A1, 0xA1);
+- outb(cached_21, 0x21);
+- spin_unlock_irqrestore(&i8259_lock, flags);
+-
+-}
+-
+-static int i8259_request_cascade(void)
+-{
+- if (!i8259_present)
+- return -ENODEV;
+-
+- request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
+- "82c59 secondary cascade", NULL );
+-
+- return 0;
+-}
+-
+-arch_initcall(i8259_request_cascade);
+diff --git a/arch/ppc64/kernel/i8259.h b/arch/ppc64/kernel/i8259.h
+deleted file mode 100644
+--- a/arch/ppc64/kernel/i8259.h
++++ /dev/null
+@@ -1,17 +0,0 @@
+-/*
+- * c 2001 PPC 64 Team, IBM Corp
+- *
+- * 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 _PPC_KERNEL_i8259_H
+-#define _PPC_KERNEL_i8259_H
+-
+-extern struct hw_interrupt_type i8259_pic;
+-
+-extern void i8259_init(int offset);
+-extern int i8259_irq(int);
+-
+-#endif /* _PPC_KERNEL_i8259_H */
+diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_VpdInfo.c
++++ /dev/null
+@@ -1,268 +0,0 @@
+-/*
+- * File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001.
+- *
+- * This code gets the card location of the hardware
+- * Copyright (C) 2001 <Allan H Trautman> <IBM Corp>
+- * Copyright (C) 2005 Stephen Rothwel, IBM Corp
+- *
+- * 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
+- *
+- * Change Activity:
+- * Created, Feb 2, 2001
+- * Ported to ppc64, August 20, 2001
+- * End Change Activity
+- */
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/pci.h>
+-#include <asm/types.h>
+-#include <asm/resource.h>
+-
+-#include <asm/iSeries/HvCallPci.h>
+-#include <asm/iSeries/HvTypes.h>
+-#include <asm/iSeries/iSeries_pci.h>
+-
+-/*
+- * Size of Bus VPD data
+- */
+-#define BUS_VPDSIZE 1024
+-
+-/*
+- * Bus Vpd Tags
+- */
+-#define VpdEndOfAreaTag 0x79
+-#define VpdIdStringTag 0x82
+-#define VpdVendorAreaTag 0x84
+-
+-/*
+- * Mfg Area Tags
+- */
+-#define VpdFruFrameId 0x4649 // "FI"
+-#define VpdSlotMapFormat 0x4D46 // "MF"
+-#define VpdSlotMap 0x534D // "SM"
+-
+-/*
+- * Structures of the areas
+- */
+-struct MfgVpdAreaStruct {
+- u16 Tag;
+- u8 TagLength;
+- u8 AreaData1;
+- u8 AreaData2;
+-};
+-typedef struct MfgVpdAreaStruct MfgArea;
+-#define MFG_ENTRY_SIZE 3
+-
+-struct SlotMapStruct {
+- u8 AgentId;
+- u8 SecondaryAgentId;
+- u8 PhbId;
+- char CardLocation[3];
+- char Parms[8];
+- char Reserved[2];
+-};
+-typedef struct SlotMapStruct SlotMap;
+-#define SLOT_ENTRY_SIZE 16
+-
+-/*
+- * Parse the Slot Area
+- */
+-static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
+- HvAgentId agent, u8 *PhbId, char card[4])
+-{
+- int SlotMapLen = MapLen;
+- SlotMap *SlotMapPtr = MapPtr;
+-
+- /*
+- * Parse Slot label until we find the one requested
+- */
+- while (SlotMapLen > 0) {
+- if (SlotMapPtr->AgentId == agent) {
+- /*
+- * If Phb wasn't found, grab the entry first one found.
+- */
+- if (*PhbId == 0xff)
+- *PhbId = SlotMapPtr->PhbId;
+- /* Found it, extract the data. */
+- if (SlotMapPtr->PhbId == *PhbId) {
+- memcpy(card, &SlotMapPtr->CardLocation, 3);
+- card[3] = 0;
+- break;
+- }
+- }
+- /* Point to the next Slot */
+- SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE);
+- SlotMapLen -= SLOT_ENTRY_SIZE;
+- }
+-}
+-
+-/*
+- * Parse the Mfg Area
+- */
+-static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
+- HvAgentId agent, u8 *PhbId,
+- u8 *frame, char card[4])
+-{
+- MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
+- int MfgAreaLen = AreaLen;
+- u16 SlotMapFmt = 0;
+-
+- /* Parse Mfg Data */
+- while (MfgAreaLen > 0) {
+- int MfgTagLen = MfgAreaPtr->TagLength;
+- /* Frame ID (FI 4649020310 ) */
+- if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */
+- *frame = MfgAreaPtr->AreaData1;
+- /* Slot Map Format (MF 4D46020004 ) */
+- else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */
+- SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
+- + MfgAreaPtr->AreaData2;
+- /* Slot Map (SM 534D90 */
+- else if (MfgAreaPtr->Tag == VpdSlotMap) { /* SM */
+- SlotMap *SlotMapPtr;
+-
+- if (SlotMapFmt == 0x1004)
+- SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
+- + MFG_ENTRY_SIZE + 1);
+- else
+- SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
+- + MFG_ENTRY_SIZE);
+- iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
+- agent, PhbId, card);
+- }
+- /*
+- * Point to the next Mfg Area
+- * Use defined size, sizeof give wrong answer
+- */
+- MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
+- + MFG_ENTRY_SIZE);
+- MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
+- }
+-}
+-
+-/*
+- * Look for "BUS".. Data is not Null terminated.
+- * PHBID of 0xFF indicates PHB was not found in VPD Data.
+- */
+-static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
+-{
+- u8 *PhbPtr = AreaPtr;
+- int DataLen = AreaLength;
+- char PhbId = 0xFF;
+-
+- while (DataLen > 0) {
+- if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
+- && (*(PhbPtr + 2) == 'S')) {
+- PhbPtr += 3;
+- while (*PhbPtr == ' ')
+- ++PhbPtr;
+- PhbId = (*PhbPtr & 0x0F);
+- break;
+- }
+- ++PhbPtr;
+- --DataLen;
+- }
+- return PhbId;
+-}
+-
+-/*
+- * Parse out the VPD Areas
+- */
+-static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
+- HvAgentId agent, u8 *frame, char card[4])
+-{
+- u8 *TagPtr = VpdData;
+- int DataLen = VpdDataLen - 3;
+- u8 PhbId;
+-
+- while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
+- int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
+- u8 *AreaData = TagPtr + 3;
+-
+- if (*TagPtr == VpdIdStringTag)
+- PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
+- else if (*TagPtr == VpdVendorAreaTag)
+- iSeries_Parse_MfgArea(AreaData, AreaLen,
+- agent, &PhbId, frame, card);
+- /* Point to next Area. */
+- TagPtr = AreaData + AreaLen;
+- DataLen -= AreaLen;
+- }
+-}
+-
+-static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
+- u8 *frame, char card[4])
+-{
+- int BusVpdLen = 0;
+- u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+-
+- if (BusVpdPtr == NULL) {
+- printk("PCI: Bus VPD Buffer allocation failure.\n");
+- return;
+- }
+- BusVpdLen = HvCallPci_getBusVpd(bus, ISERIES_HV_ADDR(BusVpdPtr),
+- BUS_VPDSIZE);
+- if (BusVpdLen == 0) {
+- printk("PCI: Bus VPD Buffer zero length.\n");
+- goto out_free;
+- }
+- /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
+- /* Make sure this is what I think it is */
+- if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */
+- printk("PCI: Bus VPD Buffer missing starting tag.\n");
+- goto out_free;
+- }
+- iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
+-out_free:
+- kfree(BusVpdPtr);
+-}
+-
+-/*
+- * Prints the device information.
+- * - Pass in pci_dev* pointer to the device.
+- * - Pass in the device count
+- *
+- * Format:
+- * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
+- * controller
+- */
+-void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
+-{
+- struct iSeries_Device_Node *DevNode = PciDev->sysdata;
+- u16 bus;
+- u8 frame;
+- char card[4];
+- HvSubBusNumber subbus;
+- HvAgentId agent;
+-
+- if (DevNode == NULL) {
+- printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
+- count);
+- return;
+- }
+-
+- bus = ISERIES_BUS(DevNode);
+- subbus = ISERIES_SUBBUS(DevNode);
+- agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
+- ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
+- iSeries_Get_Location_Code(bus, agent, &frame, card);
+-
+- printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s ",
+- count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor,
+- frame, card);
+- printk("0x%04X\n", (int)(PciDev->class >> 8));
+-}
+diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_htab.c
++++ /dev/null
+@@ -1,236 +0,0 @@
+-/*
+- * iSeries hashtable management.
+- * Derived from pSeries_htab.c
+- *
+- * SMP scalability work:
+- * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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 <asm/machdep.h>
+-#include <asm/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/iSeries/HvCallHpt.h>
+-#include <asm/abs_addr.h>
+-#include <linux/spinlock.h>
+-
+-static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp = { [0 ... 63] = SPIN_LOCK_UNLOCKED};
+-
+-/*
+- * Very primitive algorithm for picking up a lock
+- */
+-static inline void iSeries_hlock(unsigned long slot)
+-{
+- if (slot & 0x8)
+- slot = ~slot;
+- spin_lock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
+-}
+-
+-static inline void iSeries_hunlock(unsigned long slot)
+-{
+- if (slot & 0x8)
+- slot = ~slot;
+- spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
+-}
+-
+-static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
+- unsigned long prpn, unsigned long vflags,
+- unsigned long rflags)
+-{
+- unsigned long arpn;
+- long slot;
+- hpte_t lhpte;
+- int secondary = 0;
+-
+- /*
+- * The hypervisor tries both primary and secondary.
+- * If we are being called to insert in the secondary,
+- * it means we have already tried both primary and secondary,
+- * so we return failure immediately.
+- */
+- if (vflags & HPTE_V_SECONDARY)
+- return -1;
+-
+- iSeries_hlock(hpte_group);
+-
+- slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
+- BUG_ON(lhpte.v & HPTE_V_VALID);
+-
+- if (slot == -1) { /* No available entry found in either group */
+- iSeries_hunlock(hpte_group);
+- return -1;
+- }
+-
+- if (slot < 0) { /* MSB set means secondary group */
+- vflags |= HPTE_V_SECONDARY;
+- secondary = 1;
+- slot &= 0x7fffffffffffffff;
+- }
+-
+- arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT;
+-
+- lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
+- lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
+-
+- /* Now fill in the actual HPTE */
+- HvCallHpt_addValidate(slot, secondary, &lhpte);
+-
+- iSeries_hunlock(hpte_group);
+-
+- return (secondary << 3) | (slot & 7);
+-}
+-
+-static unsigned long iSeries_hpte_getword0(unsigned long slot)
+-{
+- hpte_t hpte;
+-
+- HvCallHpt_get(&hpte, slot);
+- return hpte.v;
+-}
+-
+-static long iSeries_hpte_remove(unsigned long hpte_group)
+-{
+- unsigned long slot_offset;
+- int i;
+- unsigned long hpte_v;
+-
+- /* Pick a random slot to start at */
+- slot_offset = mftb() & 0x7;
+-
+- iSeries_hlock(hpte_group);
+-
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+- hpte_v = iSeries_hpte_getword0(hpte_group + slot_offset);
+-
+- if (! (hpte_v & HPTE_V_BOLTED)) {
+- HvCallHpt_invalidateSetSwBitsGet(hpte_group +
+- slot_offset, 0, 0);
+- iSeries_hunlock(hpte_group);
+- return i;
+- }
+-
+- slot_offset++;
+- slot_offset &= 0x7;
+- }
+-
+- iSeries_hunlock(hpte_group);
+-
+- return -1;
+-}
+-
+-/*
+- * The HyperVisor expects the "flags" argument in this form:
+- * bits 0..59 : reserved
+- * bit 60 : N
+- * bits 61..63 : PP2,PP1,PP0
+- */
+-static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
+- unsigned long va, int large, int local)
+-{
+- hpte_t hpte;
+- unsigned long avpn = va >> 23;
+-
+- iSeries_hlock(slot);
+-
+- HvCallHpt_get(&hpte, slot);
+- if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) {
+- /*
+- * Hypervisor expects bits as NPPP, which is
+- * different from how they are mapped in our PP.
+- */
+- HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1));
+- iSeries_hunlock(slot);
+- return 0;
+- }
+- iSeries_hunlock(slot);
+-
+- return -1;
+-}
+-
+-/*
+- * Functions used to find the PTE for a particular virtual address.
+- * Only used during boot when bolting pages.
+- *
+- * Input : vpn : virtual page number
+- * Output: PTE index within the page table of the entry
+- * -1 on failure
+- */
+-static long iSeries_hpte_find(unsigned long vpn)
+-{
+- hpte_t hpte;
+- long slot;
+-
+- /*
+- * The HvCallHpt_findValid interface is as follows:
+- * 0xffffffffffffffff : No entry found.
+- * 0x00000000xxxxxxxx : Entry found in primary group, slot x
+- * 0x80000000xxxxxxxx : Entry found in secondary group, slot x
+- */
+- slot = HvCallHpt_findValid(&hpte, vpn);
+- if (hpte.v & HPTE_V_VALID) {
+- if (slot < 0) {
+- slot &= 0x7fffffffffffffff;
+- slot = -slot;
+- }
+- } else
+- slot = -1;
+- return slot;
+-}
+-
+-/*
+- * Update the page protection bits. Intended to be used to create
+- * guard pages for kernel data structures on pages which are bolted
+- * in the HPT. Assumes pages being operated on will not be stolen.
+- * Does not work on large pages.
+- *
+- * No need to lock here because we should be the only user.
+- */
+-static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
+-{
+- unsigned long vsid,va,vpn;
+- long slot;
+-
+- vsid = get_kernel_vsid(ea);
+- va = (vsid << 28) | (ea & 0x0fffffff);
+- vpn = va >> PAGE_SHIFT;
+- slot = iSeries_hpte_find(vpn);
+- if (slot == -1)
+- panic("updateboltedpp: Could not find page to bolt\n");
+- HvCallHpt_setPp(slot, newpp);
+-}
+-
+-static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
+- int large, int local)
+-{
+- unsigned long hpte_v;
+- unsigned long avpn = va >> 23;
+- unsigned long flags;
+-
+- local_irq_save(flags);
+-
+- iSeries_hlock(slot);
+-
+- hpte_v = iSeries_hpte_getword0(slot);
+-
+- if ((HPTE_V_AVPN_VAL(hpte_v) == avpn) && (hpte_v & HPTE_V_VALID))
+- HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0);
+-
+- iSeries_hunlock(slot);
+-
+- local_irq_restore(flags);
+-}
+-
+-void hpte_init_iSeries(void)
+-{
+- ppc_md.hpte_invalidate = iSeries_hpte_invalidate;
+- ppc_md.hpte_updatepp = iSeries_hpte_updatepp;
+- ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
+- ppc_md.hpte_insert = iSeries_hpte_insert;
+- ppc_md.hpte_remove = iSeries_hpte_remove;
+-
+- htab_finish_init();
+-}
+diff --git a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_iommu.c
++++ /dev/null
+@@ -1,176 +0,0 @@
+-/*
+- * arch/ppc64/kernel/iSeries_iommu.c
+- *
+- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+- *
+- * Rewrite, cleanup:
+- *
+- * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
+- *
+- * Dynamic DMA mapping support, iSeries-specific parts.
+- *
+- *
+- * 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/types.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/list.h>
+-
+-#include <asm/iommu.h>
+-#include <asm/machdep.h>
+-#include <asm/iSeries/HvCallXm.h>
+-#include <asm/iSeries/iSeries_pci.h>
+-
+-extern struct list_head iSeries_Global_Device_List;
+-
+-
+-static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
+- unsigned long uaddr, enum dma_data_direction direction)
+-{
+- u64 rc;
+- union tce_entry tce;
+-
+- while (npages--) {
+- tce.te_word = 0;
+- tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
+-
+- if (tbl->it_type == TCE_VB) {
+- /* Virtual Bus */
+- tce.te_bits.tb_valid = 1;
+- tce.te_bits.tb_allio = 1;
+- if (direction != DMA_TO_DEVICE)
+- tce.te_bits.tb_rdwr = 1;
+- } else {
+- /* PCI Bus */
+- tce.te_bits.tb_rdwr = 1; /* Read allowed */
+- if (direction != DMA_TO_DEVICE)
+- tce.te_bits.tb_pciwr = 1;
+- }
+-
+- rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
+- tce.te_word);
+- if (rc)
+- panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
+- rc);
+- index++;
+- uaddr += PAGE_SIZE;
+- }
+-}
+-
+-static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
+-{
+- u64 rc;
+-
+- while (npages--) {
+- rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0);
+- if (rc)
+- panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
+- rc);
+- index++;
+- }
+-}
+-
+-#ifdef CONFIG_PCI
+-/*
+- * This function compares the known tables to find an iommu_table
+- * that has already been built for hardware TCEs.
+- */
+-static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
+-{
+- struct iSeries_Device_Node *dp;
+-
+- list_for_each_entry(dp, &iSeries_Global_Device_List, Device_List) {
+- if ((dp->iommu_table != NULL) &&
+- (dp->iommu_table->it_type == TCE_PCI) &&
+- (dp->iommu_table->it_offset == tbl->it_offset) &&
+- (dp->iommu_table->it_index == tbl->it_index) &&
+- (dp->iommu_table->it_size == tbl->it_size))
+- return dp->iommu_table;
+- }
+- return NULL;
+-}
+-
+-/*
+- * Call Hv with the architected data structure to get TCE table info.
+- * info. Put the returned data into the Linux representation of the
+- * TCE table data.
+- * The Hardware Tce table comes in three flavors.
+- * 1. TCE table shared between Buses.
+- * 2. TCE table per Bus.
+- * 3. TCE Table per IOA.
+- */
+-static void iommu_table_getparms(struct iSeries_Device_Node* dn,
+- struct iommu_table* tbl)
+-{
+- struct iommu_table_cb *parms;
+-
+- parms = kmalloc(sizeof(*parms), GFP_KERNEL);
+- if (parms == NULL)
+- panic("PCI_DMA: TCE Table Allocation failed.");
+-
+- memset(parms, 0, sizeof(*parms));
+-
+- parms->itc_busno = ISERIES_BUS(dn);
+- parms->itc_slotno = dn->LogicalSlot;
+- parms->itc_virtbus = 0;
+-
+- HvCallXm_getTceTableParms(ISERIES_HV_ADDR(parms));
+-
+- if (parms->itc_size == 0)
+- panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms);
+-
+- /* itc_size is in pages worth of table, it_size is in # of entries */
+- tbl->it_size = (parms->itc_size * PAGE_SIZE) / sizeof(union tce_entry);
+- tbl->it_busno = parms->itc_busno;
+- tbl->it_offset = parms->itc_offset;
+- tbl->it_index = parms->itc_index;
+- tbl->it_blocksize = 1;
+- tbl->it_type = TCE_PCI;
+-
+- kfree(parms);
+-}
+-
+-
+-void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
+-{
+- struct iommu_table *tbl;
+-
+- tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+-
+- iommu_table_getparms(dn, tbl);
+-
+- /* Look for existing tce table */
+- dn->iommu_table = iommu_table_find(tbl);
+- if (dn->iommu_table == NULL)
+- dn->iommu_table = iommu_init_table(tbl);
+- else
+- kfree(tbl);
+-}
+-#endif
+-
+-static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
+-static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
+-
+-void iommu_init_early_iSeries(void)
+-{
+- ppc_md.tce_build = tce_build_iSeries;
+- ppc_md.tce_free = tce_free_iSeries;
+-
+- ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries;
+- ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries;
+-
+- pci_iommu_init();
+-}
+diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_irq.c
++++ /dev/null
+@@ -1,353 +0,0 @@
+-/*
+- * This module supports the iSeries PCI bus interrupt handling
+- * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
+- * Copyright (C) 2004-2005 IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the:
+- * Free Software Foundation, Inc.,
+- * 59 Temple Place, Suite 330,
+- * Boston, MA 02111-1307 USA
+- *
+- * Change Activity:
+- * Created, December 13, 2000 by Wayne Holm
+- * End Change Activity
+- */
+-#include <linux/config.h>
+-#include <linux/pci.h>
+-#include <linux/init.h>
+-#include <linux/threads.h>
+-#include <linux/smp.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/bootmem.h>
+-#include <linux/ide.h>
+-#include <linux/irq.h>
+-#include <linux/spinlock.h>
+-
+-#include <asm/ppcdebug.h>
+-#include <asm/iSeries/HvTypes.h>
+-#include <asm/iSeries/HvLpEvent.h>
+-#include <asm/iSeries/HvCallPci.h>
+-#include <asm/iSeries/HvCallXm.h>
+-#include <asm/iSeries/iSeries_irq.h>
+-
+-/* This maps virtual irq numbers to real irqs */
+-unsigned int virt_irq_to_real_map[NR_IRQS];
+-
+-/* The next available virtual irq number */
+-/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */
+-static int next_virtual_irq = 2;
+-
+-static long Pci_Interrupt_Count;
+-static long Pci_Event_Count;
+-
+-enum XmPciLpEvent_Subtype {
+- XmPciLpEvent_BusCreated = 0, // PHB has been created
+- XmPciLpEvent_BusError = 1, // PHB has failed
+- XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
+- XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
+- XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
+- XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
+- XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
+- XmPciLpEvent_BridgeError = 21, // Bridge Error
+- XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
+-};
+-
+-struct XmPciLpEvent_BusInterrupt {
+- HvBusNumber busNumber;
+- HvSubBusNumber subBusNumber;
+-};
+-
+-struct XmPciLpEvent_NodeInterrupt {
+- HvBusNumber busNumber;
+- HvSubBusNumber subBusNumber;
+- HvAgentId deviceId;
+-};
+-
+-struct XmPciLpEvent {
+- struct HvLpEvent hvLpEvent;
+-
+- union {
+- u64 alignData; // Align on an 8-byte boundary
+-
+- struct {
+- u32 fisr;
+- HvBusNumber busNumber;
+- HvSubBusNumber subBusNumber;
+- HvAgentId deviceId;
+- } slotInterrupt;
+-
+- struct XmPciLpEvent_BusInterrupt busFailed;
+- struct XmPciLpEvent_BusInterrupt busRecovered;
+- struct XmPciLpEvent_BusInterrupt busCreated;
+-
+- struct XmPciLpEvent_NodeInterrupt nodeFailed;
+- struct XmPciLpEvent_NodeInterrupt nodeRecovered;
+-
+- } eventData;
+-
+-};
+-
+-static void intReceived(struct XmPciLpEvent *eventParm,
+- struct pt_regs *regsParm)
+-{
+- int irq;
+-
+- ++Pci_Interrupt_Count;
+-
+- switch (eventParm->hvLpEvent.xSubtype) {
+- case XmPciLpEvent_SlotInterrupt:
+- irq = eventParm->hvLpEvent.xCorrelationToken;
+- /* Dispatch the interrupt handlers for this irq */
+- ppc_irq_dispatch_handler(regsParm, irq);
+- HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
+- eventParm->eventData.slotInterrupt.subBusNumber,
+- eventParm->eventData.slotInterrupt.deviceId);
+- break;
+- /* Ignore error recovery events for now */
+- case XmPciLpEvent_BusCreated:
+- printk(KERN_INFO "intReceived: system bus %d created\n",
+- eventParm->eventData.busCreated.busNumber);
+- break;
+- case XmPciLpEvent_BusError:
+- case XmPciLpEvent_BusFailed:
+- printk(KERN_INFO "intReceived: system bus %d failed\n",
+- eventParm->eventData.busFailed.busNumber);
+- break;
+- case XmPciLpEvent_BusRecovered:
+- case XmPciLpEvent_UnQuiesceBus:
+- printk(KERN_INFO "intReceived: system bus %d recovered\n",
+- eventParm->eventData.busRecovered.busNumber);
+- break;
+- case XmPciLpEvent_NodeFailed:
+- case XmPciLpEvent_BridgeError:
+- printk(KERN_INFO
+- "intReceived: multi-adapter bridge %d/%d/%d failed\n",
+- eventParm->eventData.nodeFailed.busNumber,
+- eventParm->eventData.nodeFailed.subBusNumber,
+- eventParm->eventData.nodeFailed.deviceId);
+- break;
+- case XmPciLpEvent_NodeRecovered:
+- printk(KERN_INFO
+- "intReceived: multi-adapter bridge %d/%d/%d recovered\n",
+- eventParm->eventData.nodeRecovered.busNumber,
+- eventParm->eventData.nodeRecovered.subBusNumber,
+- eventParm->eventData.nodeRecovered.deviceId);
+- break;
+- default:
+- printk(KERN_ERR
+- "intReceived: unrecognized event subtype 0x%x\n",
+- eventParm->hvLpEvent.xSubtype);
+- break;
+- }
+-}
+-
+-static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
+- struct pt_regs *regsParm)
+-{
+-#ifdef CONFIG_PCI
+- ++Pci_Event_Count;
+-
+- if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
+- switch (eventParm->xFlags.xFunction) {
+- case HvLpEvent_Function_Int:
+- intReceived((struct XmPciLpEvent *)eventParm, regsParm);
+- break;
+- case HvLpEvent_Function_Ack:
+- printk(KERN_ERR
+- "XmPciLpEvent_handler: unexpected ack received\n");
+- break;
+- default:
+- printk(KERN_ERR
+- "XmPciLpEvent_handler: unexpected event function %d\n",
+- (int)eventParm->xFlags.xFunction);
+- break;
+- }
+- } else if (eventParm)
+- printk(KERN_ERR
+- "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n",
+- (int)eventParm->xType);
+- else
+- printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n");
+-#endif
+-}
+-
+-/*
+- * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
+- * It must be called before the bus walk.
+- */
+-void __init iSeries_init_IRQ(void)
+-{
+- /* Register PCI event handler and open an event path */
+- int xRc;
+-
+- xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
+- &XmPciLpEvent_handler);
+- if (xRc == 0) {
+- xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+- if (xRc != 0)
+- printk(KERN_ERR "iSeries_init_IRQ: open event path "
+- "failed with rc 0x%x\n", xRc);
+- } else
+- printk(KERN_ERR "iSeries_init_IRQ: register handler "
+- "failed with rc 0x%x\n", xRc);
+-}
+-
+-#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
+-#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
+-#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
+-
+-/*
+- * This will be called by device drivers (via enable_IRQ)
+- * to enable INTA in the bridge interrupt status register.
+- */
+-static void iSeries_enable_IRQ(unsigned int irq)
+-{
+- u32 bus, deviceId, function, mask;
+- const u32 subBus = 0;
+- unsigned int rirq = virt_irq_to_real_map[irq];
+-
+- /* The IRQ has already been locked by the caller */
+- bus = REAL_IRQ_TO_BUS(rirq);
+- function = REAL_IRQ_TO_FUNC(rirq);
+- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+-
+- /* Unmask secondary INTA */
+- mask = 0x80000000;
+- HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
+- PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
+- bus, subBus, deviceId, irq);
+-}
+-
+-/* This is called by iSeries_activate_IRQs */
+-static unsigned int iSeries_startup_IRQ(unsigned int irq)
+-{
+- u32 bus, deviceId, function, mask;
+- const u32 subBus = 0;
+- unsigned int rirq = virt_irq_to_real_map[irq];
+-
+- bus = REAL_IRQ_TO_BUS(rirq);
+- function = REAL_IRQ_TO_FUNC(rirq);
+- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+-
+- /* Link the IRQ number to the bridge */
+- HvCallXm_connectBusUnit(bus, subBus, deviceId, irq);
+-
+- /* Unmask bridge interrupts in the FISR */
+- mask = 0x01010000 << function;
+- HvCallPci_unmaskFisr(bus, subBus, deviceId, mask);
+- iSeries_enable_IRQ(irq);
+- return 0;
+-}
+-
+-/*
+- * This is called out of iSeries_fixup to activate interrupt
+- * generation for usable slots
+- */
+-void __init iSeries_activate_IRQs()
+-{
+- int irq;
+- unsigned long flags;
+-
+- for_each_irq (irq) {
+- irq_desc_t *desc = get_irq_desc(irq);
+-
+- if (desc && desc->handler && desc->handler->startup) {
+- spin_lock_irqsave(&desc->lock, flags);
+- desc->handler->startup(irq);
+- spin_unlock_irqrestore(&desc->lock, flags);
+- }
+- }
+-}
+-
+-/* this is not called anywhere currently */
+-static void iSeries_shutdown_IRQ(unsigned int irq)
+-{
+- u32 bus, deviceId, function, mask;
+- const u32 subBus = 0;
+- unsigned int rirq = virt_irq_to_real_map[irq];
+-
+- /* irq should be locked by the caller */
+- bus = REAL_IRQ_TO_BUS(rirq);
+- function = REAL_IRQ_TO_FUNC(rirq);
+- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+-
+- /* Invalidate the IRQ number in the bridge */
+- HvCallXm_connectBusUnit(bus, subBus, deviceId, 0);
+-
+- /* Mask bridge interrupts in the FISR */
+- mask = 0x01010000 << function;
+- HvCallPci_maskFisr(bus, subBus, deviceId, mask);
+-}
+-
+-/*
+- * This will be called by device drivers (via disable_IRQ)
+- * to disable INTA in the bridge interrupt status register.
+- */
+-static void iSeries_disable_IRQ(unsigned int irq)
+-{
+- u32 bus, deviceId, function, mask;
+- const u32 subBus = 0;
+- unsigned int rirq = virt_irq_to_real_map[irq];
+-
+- /* The IRQ has already been locked by the caller */
+- bus = REAL_IRQ_TO_BUS(rirq);
+- function = REAL_IRQ_TO_FUNC(rirq);
+- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+-
+- /* Mask secondary INTA */
+- mask = 0x80000000;
+- HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
+- PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
+- bus, subBus, deviceId, irq);
+-}
+-
+-/*
+- * Need to define this so ppc_irq_dispatch_handler will NOT call
+- * enable_IRQ at the end of interrupt handling. However, this does
+- * nothing because there is not enough information provided to do
+- * the EOI HvCall. This is done by XmPciLpEvent.c
+- */
+-static void iSeries_end_IRQ(unsigned int irq)
+-{
+-}
+-
+-static hw_irq_controller iSeries_IRQ_handler = {
+- .typename = "iSeries irq controller",
+- .startup = iSeries_startup_IRQ,
+- .shutdown = iSeries_shutdown_IRQ,
+- .enable = iSeries_enable_IRQ,
+- .disable = iSeries_disable_IRQ,
+- .end = iSeries_end_IRQ
+-};
+-
+-/*
+- * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
+- * It calculates the irq value for the slot.
+- * Note that subBusNumber is always 0 (at the moment at least).
+- */
+-int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
+- HvSubBusNumber subBusNumber, HvAgentId deviceId)
+-{
+- unsigned int realirq, virtirq;
+- u8 idsel = (deviceId >> 4);
+- u8 function = deviceId & 7;
+-
+- virtirq = next_virtual_irq++;
+- realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
+- virt_irq_to_real_map[virtirq] = realirq;
+-
+- irq_desc[virtirq].handler = &iSeries_IRQ_handler;
+- return virtirq;
+-}
+diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_pci.c
++++ /dev/null
+@@ -1,905 +0,0 @@
+-/*
+- * iSeries_pci.c
+- *
+- * Copyright (C) 2001 Allan Trautman, IBM Corporation
+- *
+- * iSeries specific routines for PCI.
+- *
+- * Based on code from pci.c and iSeries_pci.c 32bit
+- *
+- * 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/list.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/ide.h>
+-#include <linux/pci.h>
+-
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/iommu.h>
+-
+-#include <asm/iSeries/HvCallPci.h>
+-#include <asm/iSeries/HvCallXm.h>
+-#include <asm/iSeries/iSeries_irq.h>
+-#include <asm/iSeries/iSeries_pci.h>
+-#include <asm/iSeries/mf.h>
+-
+-#include "pci.h"
+-
+-extern unsigned long io_page_mask;
+-
+-/*
+- * Forward declares of prototypes.
+- */
+-static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn);
+-static void scan_PHB_slots(struct pci_controller *Phb);
+-static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
+-static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
+-
+-LIST_HEAD(iSeries_Global_Device_List);
+-
+-static int DeviceCount;
+-
+-/* Counters and control flags. */
+-static long Pci_Io_Read_Count;
+-static long Pci_Io_Write_Count;
+-#if 0
+-static long Pci_Cfg_Read_Count;
+-static long Pci_Cfg_Write_Count;
+-#endif
+-static long Pci_Error_Count;
+-
+-static int Pci_Retry_Max = 3; /* Only retry 3 times */
+-static int Pci_Error_Flag = 1; /* Set Retry Error on. */
+-
+-static struct pci_ops iSeries_pci_ops;
+-
+-/*
+- * Table defines
+- * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
+- */
+-#define IOMM_TABLE_MAX_ENTRIES 1024
+-#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL
+-#define BASE_IO_MEMORY 0xE000000000000000UL
+-
+-static unsigned long max_io_memory = 0xE000000000000000UL;
+-static long current_iomm_table_entry;
+-
+-/*
+- * Lookup Tables.
+- */
+-static struct iSeries_Device_Node **iomm_table;
+-static u8 *iobar_table;
+-
+-/*
+- * Static and Global variables
+- */
+-static char *pci_io_text = "iSeries PCI I/O";
+-static DEFINE_SPINLOCK(iomm_table_lock);
+-
+-/*
+- * iomm_table_initialize
+- *
+- * Allocates and initalizes the Address Translation Table and Bar
+- * Tables to get them ready for use. Must be called before any
+- * I/O space is handed out to the device BARs.
+- */
+-static void iomm_table_initialize(void)
+-{
+- spin_lock(&iomm_table_lock);
+- iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
+- GFP_KERNEL);
+- iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
+- GFP_KERNEL);
+- spin_unlock(&iomm_table_lock);
+- if ((iomm_table == NULL) || (iobar_table == NULL))
+- panic("PCI: I/O tables allocation failed.\n");
+-}
+-
+-/*
+- * iomm_table_allocate_entry
+- *
+- * Adds pci_dev entry in address translation table
+- *
+- * - Allocates the number of entries required in table base on BAR
+- * size.
+- * - Allocates starting at BASE_IO_MEMORY and increases.
+- * - The size is round up to be a multiple of entry size.
+- * - CurrentIndex is incremented to keep track of the last entry.
+- * - Builds the resource entry for allocated BARs.
+- */
+-static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
+-{
+- struct resource *bar_res = &dev->resource[bar_num];
+- long bar_size = pci_resource_len(dev, bar_num);
+-
+- /*
+- * No space to allocate, quick exit, skip Allocation.
+- */
+- if (bar_size == 0)
+- return;
+- /*
+- * Set Resource values.
+- */
+- spin_lock(&iomm_table_lock);
+- bar_res->name = pci_io_text;
+- bar_res->start =
+- IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
+- bar_res->start += BASE_IO_MEMORY;
+- bar_res->end = bar_res->start + bar_size - 1;
+- /*
+- * Allocate the number of table entries needed for BAR.
+- */
+- while (bar_size > 0 ) {
+- iomm_table[current_iomm_table_entry] = dev->sysdata;
+- iobar_table[current_iomm_table_entry] = bar_num;
+- bar_size -= IOMM_TABLE_ENTRY_SIZE;
+- ++current_iomm_table_entry;
+- }
+- max_io_memory = BASE_IO_MEMORY +
+- (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry);
+- spin_unlock(&iomm_table_lock);
+-}
+-
+-/*
+- * allocate_device_bars
+- *
+- * - Allocates ALL pci_dev BAR's and updates the resources with the
+- * BAR value. BARS with zero length will have the resources
+- * The HvCallPci_getBarParms is used to get the size of the BAR
+- * space. It calls iomm_table_allocate_entry to allocate
+- * each entry.
+- * - Loops through The Bar resources(0 - 5) including the ROM
+- * is resource(6).
+- */
+-static void allocate_device_bars(struct pci_dev *dev)
+-{
+- struct resource *bar_res;
+- int bar_num;
+-
+- for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) {
+- bar_res = &dev->resource[bar_num];
+- iomm_table_allocate_entry(dev, bar_num);
+- }
+-}
+-
+-/*
+- * Log error information to system console.
+- * Filter out the device not there errors.
+- * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx
+- * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
+- * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
+- */
+-static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
+- int AgentId, int HvRc)
+-{
+- if (HvRc == 0x0302)
+- return;
+- printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
+- Error_Text, Bus, SubBus, AgentId, HvRc);
+-}
+-
+-/*
+- * build_device_node(u16 Bus, int SubBus, u8 DevFn)
+- */
+-static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus,
+- HvSubBusNumber SubBus, int AgentId, int Function)
+-{
+- struct iSeries_Device_Node *node;
+-
+- PPCDBG(PPCDBG_BUSWALK,
+- "-build_device_node 0x%02X.%02X.%02X Function: %02X\n",
+- Bus, SubBus, AgentId, Function);
+-
+- node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL);
+- if (node == NULL)
+- return NULL;
+-
+- memset(node, 0, sizeof(struct iSeries_Device_Node));
+- list_add_tail(&node->Device_List, &iSeries_Global_Device_List);
+-#if 0
+- node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32);
+-#endif
+- node->DsaAddr.DsaAddr = 0;
+- node->DsaAddr.Dsa.busNumber = Bus;
+- node->DsaAddr.Dsa.subBusNumber = SubBus;
+- node->DsaAddr.Dsa.deviceId = 0x10;
+- node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
+- return node;
+-}
+-
+-/*
+- * unsigned long __init find_and_init_phbs(void)
+- *
+- * Description:
+- * This function checks for all possible system PCI host bridges that connect
+- * PCI buses. The system hypervisor is queried as to the guest partition
+- * ownership status. A pci_controller is built for any bus which is partially
+- * owned or fully owned by this guest partition.
+- */
+-unsigned long __init find_and_init_phbs(void)
+-{
+- struct pci_controller *phb;
+- HvBusNumber bus;
+-
+- PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n");
+-
+- /* Check all possible buses. */
+- for (bus = 0; bus < 256; bus++) {
+- int ret = HvCallXm_testBus(bus);
+- if (ret == 0) {
+- printk("bus %d appears to exist\n", bus);
+-
+- phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+- if (phb == NULL)
+- return -ENOMEM;
+- pci_setup_pci_controller(phb);
+-
+- phb->pci_mem_offset = phb->local_number = bus;
+- phb->first_busno = bus;
+- phb->last_busno = bus;
+- phb->ops = &iSeries_pci_ops;
+-
+- PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",
+- phb, bus);
+-
+- /* Find and connect the devices. */
+- scan_PHB_slots(phb);
+- }
+- /*
+- * Check for Unexpected Return code, a clue that something
+- * has gone wrong.
+- */
+- else if (ret != 0x0301)
+- printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
+- bus, ret);
+- }
+- return 0;
+-}
+-
+-/*
+- * iSeries_pcibios_init
+- *
+- * Chance to initialize and structures or variable before PCI Bus walk.
+- */
+-void iSeries_pcibios_init(void)
+-{
+- PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n");
+- iomm_table_initialize();
+- find_and_init_phbs();
+- io_page_mask = -1;
+- PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n");
+-}
+-
+-/*
+- * iSeries_pci_final_fixup(void)
+- */
+-void __init iSeries_pci_final_fixup(void)
+-{
+- struct pci_dev *pdev = NULL;
+- struct iSeries_Device_Node *node;
+- int DeviceCount = 0;
+-
+- PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n");
+-
+- /* Fix up at the device node and pci_dev relationship */
+- mf_display_src(0xC9000100);
+-
+- printk("pcibios_final_fixup\n");
+- for_each_pci_dev(pdev) {
+- node = find_Device_Node(pdev->bus->number, pdev->devfn);
+- printk("pci dev %p (%x.%x), node %p\n", pdev,
+- pdev->bus->number, pdev->devfn, node);
+-
+- if (node != NULL) {
+- ++DeviceCount;
+- pdev->sysdata = (void *)node;
+- node->PciDev = pdev;
+- PPCDBG(PPCDBG_BUSWALK,
+- "pdev 0x%p <==> DevNode 0x%p\n",
+- pdev, node);
+- allocate_device_bars(pdev);
+- iSeries_Device_Information(pdev, DeviceCount);
+- iommu_devnode_init_iSeries(node);
+- } else
+- printk("PCI: Device Tree not found for 0x%016lX\n",
+- (unsigned long)pdev);
+- pdev->irq = node->Irq;
+- }
+- iSeries_activate_IRQs();
+- mf_display_src(0xC9000200);
+-}
+-
+-void pcibios_fixup_bus(struct pci_bus *PciBus)
+-{
+- PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",
+- PciBus->number);
+-}
+-
+-void pcibios_fixup_resources(struct pci_dev *pdev)
+-{
+- PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev);
+-}
+-
+-/*
+- * Loop through each node function to find usable EADs bridges.
+- */
+-static void scan_PHB_slots(struct pci_controller *Phb)
+-{
+- struct HvCallPci_DeviceInfo *DevInfo;
+- HvBusNumber bus = Phb->local_number; /* System Bus */
+- const HvSubBusNumber SubBus = 0; /* EADs is always 0. */
+- int HvRc = 0;
+- int IdSel;
+- const int MaxAgents = 8;
+-
+- DevInfo = (struct HvCallPci_DeviceInfo*)
+- kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
+- if (DevInfo == NULL)
+- return;
+-
+- /*
+- * Probe for EADs Bridges
+- */
+- for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
+- HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
+- ISERIES_HV_ADDR(DevInfo),
+- sizeof(struct HvCallPci_DeviceInfo));
+- if (HvRc == 0) {
+- if (DevInfo->deviceType == HvCallPci_NodeDevice)
+- scan_EADS_bridge(bus, SubBus, IdSel);
+- else
+- printk("PCI: Invalid System Configuration(0x%02X)"
+- " for bus 0x%02x id 0x%02x.\n",
+- DevInfo->deviceType, bus, IdSel);
+- }
+- else
+- pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
+- }
+- kfree(DevInfo);
+-}
+-
+-static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
+- int IdSel)
+-{
+- struct HvCallPci_BridgeInfo *BridgeInfo;
+- HvAgentId AgentId;
+- int Function;
+- int HvRc;
+-
+- BridgeInfo = (struct HvCallPci_BridgeInfo *)
+- kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
+- if (BridgeInfo == NULL)
+- return;
+-
+- /* Note: hvSubBus and irq is always be 0 at this level! */
+- for (Function = 0; Function < 8; ++Function) {
+- AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
+- HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
+- if (HvRc == 0) {
+- printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
+- bus, IdSel, Function, AgentId);
+- /* Connect EADs: 0x18.00.12 = 0x00 */
+- PPCDBG(PPCDBG_BUSWALK,
+- "PCI:Connect EADs: 0x%02X.%02X.%02X\n",
+- bus, SubBus, AgentId);
+- HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
+- ISERIES_HV_ADDR(BridgeInfo),
+- sizeof(struct HvCallPci_BridgeInfo));
+- if (HvRc == 0) {
+- printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
+- BridgeInfo->busUnitInfo.deviceType,
+- BridgeInfo->subBusNumber,
+- BridgeInfo->maxAgents,
+- BridgeInfo->maxSubBusNumber,
+- BridgeInfo->logicalSlotNumber);
+- PPCDBG(PPCDBG_BUSWALK,
+- "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
+- BridgeInfo->busUnitInfo.deviceType,
+- BridgeInfo->subBusNumber,
+- BridgeInfo->maxAgents,
+- BridgeInfo->maxSubBusNumber,
+- BridgeInfo->logicalSlotNumber);
+-
+- if (BridgeInfo->busUnitInfo.deviceType ==
+- HvCallPci_BridgeDevice) {
+- /* Scan_Bridge_Slot...: 0x18.00.12 */
+- scan_bridge_slot(bus, BridgeInfo);
+- } else
+- printk("PCI: Invalid Bridge Configuration(0x%02X)",
+- BridgeInfo->busUnitInfo.deviceType);
+- }
+- } else if (HvRc != 0x000B)
+- pci_Log_Error("EADs Connect",
+- bus, SubBus, AgentId, HvRc);
+- }
+- kfree(BridgeInfo);
+-}
+-
+-/*
+- * This assumes that the node slot is always on the primary bus!
+- */
+-static int scan_bridge_slot(HvBusNumber Bus,
+- struct HvCallPci_BridgeInfo *BridgeInfo)
+-{
+- struct iSeries_Device_Node *node;
+- HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
+- u16 VendorId = 0;
+- int HvRc = 0;
+- u8 Irq = 0;
+- int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
+- int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
+- HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
+-
+- /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
+- Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
+- PPCDBG(PPCDBG_BUSWALK,
+- "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",
+- Bus, 0, EADsIdSel, Irq);
+-
+- /*
+- * Connect all functions of any device found.
+- */
+- for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
+- for (Function = 0; Function < 8; ++Function) {
+- HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
+- HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
+- AgentId, Irq);
+- if (HvRc != 0) {
+- pci_Log_Error("Connect Bus Unit",
+- Bus, SubBus, AgentId, HvRc);
+- continue;
+- }
+-
+- HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
+- PCI_VENDOR_ID, &VendorId);
+- if (HvRc != 0) {
+- pci_Log_Error("Read Vendor",
+- Bus, SubBus, AgentId, HvRc);
+- continue;
+- }
+- printk("read vendor ID: %x\n", VendorId);
+-
+- /* FoundDevice: 0x18.28.10 = 0x12AE */
+- PPCDBG(PPCDBG_BUSWALK,
+- "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n",
+- Bus, SubBus, AgentId, VendorId, Irq);
+- HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
+- PCI_INTERRUPT_LINE, Irq);
+- if (HvRc != 0)
+- pci_Log_Error("PciCfgStore Irq Failed!",
+- Bus, SubBus, AgentId, HvRc);
+-
+- ++DeviceCount;
+- node = build_device_node(Bus, SubBus, EADsIdSel, Function);
+- node->Irq = Irq;
+- node->LogicalSlot = BridgeInfo->logicalSlotNumber;
+-
+- } /* for (Function = 0; Function < 8; ++Function) */
+- } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
+- return HvRc;
+-}
+-
+-/*
+- * I/0 Memory copy MUST use mmio commands on iSeries
+- * To do; For performance, include the hv call directly
+- */
+-void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
+-{
+- u8 ByteValue = c;
+- long NumberOfBytes = Count;
+-
+- while (NumberOfBytes > 0) {
+- iSeries_Write_Byte(ByteValue, dest++);
+- -- NumberOfBytes;
+- }
+-}
+-EXPORT_SYMBOL(iSeries_memset_io);
+-
+-void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
+-{
+- char *src = source;
+- long NumberOfBytes = count;
+-
+- while (NumberOfBytes > 0) {
+- iSeries_Write_Byte(*src++, dest++);
+- -- NumberOfBytes;
+- }
+-}
+-EXPORT_SYMBOL(iSeries_memcpy_toio);
+-
+-void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
+-{
+- char *dst = dest;
+- long NumberOfBytes = count;
+-
+- while (NumberOfBytes > 0) {
+- *dst++ = iSeries_Read_Byte(src++);
+- -- NumberOfBytes;
+- }
+-}
+-EXPORT_SYMBOL(iSeries_memcpy_fromio);
+-
+-/*
+- * Look down the chain to find the matching Device Device
+- */
+-static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn)
+-{
+- struct list_head *pos;
+-
+- list_for_each(pos, &iSeries_Global_Device_List) {
+- struct iSeries_Device_Node *node =
+- list_entry(pos, struct iSeries_Device_Node, Device_List);
+-
+- if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn))
+- return node;
+- }
+- return NULL;
+-}
+-
+-#if 0
+-/*
+- * Returns the device node for the passed pci_dev
+- * Sanity Check Node PciDev to passed pci_dev
+- * If none is found, returns a NULL which the client must handle.
+- */
+-static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev)
+-{
+- struct iSeries_Device_Node *node;
+-
+- node = pdev->sysdata;
+- if (node == NULL || node->PciDev != pdev)
+- node = find_Device_Node(pdev->bus->number, pdev->devfn);
+- return node;
+-}
+-#endif
+-
+-/*
+- * Config space read and write functions.
+- * For now at least, we look for the device node for the bus and devfn
+- * that we are asked to access. It may be possible to translate the devfn
+- * to a subbus and deviceid more directly.
+- */
+-static u64 hv_cfg_read_func[4] = {
+- HvCallPciConfigLoad8, HvCallPciConfigLoad16,
+- HvCallPciConfigLoad32, HvCallPciConfigLoad32
+-};
+-
+-static u64 hv_cfg_write_func[4] = {
+- HvCallPciConfigStore8, HvCallPciConfigStore16,
+- HvCallPciConfigStore32, HvCallPciConfigStore32
+-};
+-
+-/*
+- * Read PCI config space
+- */
+-static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int size, u32 *val)
+-{
+- struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn);
+- u64 fn;
+- struct HvCallPci_LoadReturn ret;
+-
+- if (node == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- if (offset > 255) {
+- *val = ~0;
+- return PCIBIOS_BAD_REGISTER_NUMBER;
+- }
+-
+- fn = hv_cfg_read_func[(size - 1) & 3];
+- HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0);
+-
+- if (ret.rc != 0) {
+- *val = ~0;
+- return PCIBIOS_DEVICE_NOT_FOUND; /* or something */
+- }
+-
+- *val = ret.value;
+- return 0;
+-}
+-
+-/*
+- * Write PCI config space
+- */
+-
+-static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int size, u32 val)
+-{
+- struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn);
+- u64 fn;
+- u64 ret;
+-
+- if (node == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- if (offset > 255)
+- return PCIBIOS_BAD_REGISTER_NUMBER;
+-
+- fn = hv_cfg_write_func[(size - 1) & 3];
+- ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0);
+-
+- if (ret != 0)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- return 0;
+-}
+-
+-static struct pci_ops iSeries_pci_ops = {
+- .read = iSeries_pci_read_config,
+- .write = iSeries_pci_write_config
+-};
+-
+-/*
+- * Check Return Code
+- * -> On Failure, print and log information.
+- * Increment Retry Count, if exceeds max, panic partition.
+- *
+- * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
+- * PCI: Device 23.90 ReadL Retry( 1)
+- * PCI: Device 23.90 ReadL Retry Successful(1)
+- */
+-static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
+- int *retry, u64 ret)
+-{
+- if (ret != 0) {
+- ++Pci_Error_Count;
+- (*retry)++;
+- printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
+- TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
+- *retry, (int)ret);
+- /*
+- * Bump the retry and check for retry count exceeded.
+- * If, Exceeded, panic the system.
+- */
+- if (((*retry) > Pci_Retry_Max) &&
+- (Pci_Error_Flag > 0)) {
+- mf_display_src(0xB6000103);
+- panic_timeout = 0;
+- panic("PCI: Hardware I/O Error, SRC B6000103, "
+- "Automatic Reboot Disabled.\n");
+- }
+- return -1; /* Retry Try */
+- }
+- return 0;
+-}
+-
+-/*
+- * Translate the I/O Address into a device node, bar, and bar offset.
+- * Note: Make sure the passed variable end up on the stack to avoid
+- * the exposure of being device global.
+- */
+-static inline struct iSeries_Device_Node *xlate_iomm_address(
+- const volatile void __iomem *IoAddress,
+- u64 *dsaptr, u64 *BarOffsetPtr)
+-{
+- unsigned long OrigIoAddr;
+- unsigned long BaseIoAddr;
+- unsigned long TableIndex;
+- struct iSeries_Device_Node *DevNode;
+-
+- OrigIoAddr = (unsigned long __force)IoAddress;
+- if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory))
+- return NULL;
+- BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY;
+- TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE;
+- DevNode = iomm_table[TableIndex];
+-
+- if (DevNode != NULL) {
+- int barnum = iobar_table[TableIndex];
+- *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24);
+- *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE;
+- } else
+- panic("PCI: Invalid PCI IoAddress detected!\n");
+- return DevNode;
+-}
+-
+-/*
+- * Read MM I/O Instructions for the iSeries
+- * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
+- * else, data is returned in big Endian format.
+- *
+- * iSeries_Read_Byte = Read Byte ( 8 bit)
+- * iSeries_Read_Word = Read Word (16 bit)
+- * iSeries_Read_Long = Read Long (32 bit)
+- */
+-u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
+-{
+- u64 BarOffset;
+- u64 dsa;
+- int retry = 0;
+- struct HvCallPci_LoadReturn ret;
+- struct iSeries_Device_Node *DevNode =
+- xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+-
+- if (DevNode == NULL) {
+- static unsigned long last_jiffies;
+- static int num_printed;
+-
+- if ((jiffies - last_jiffies) > 60 * HZ) {
+- last_jiffies = jiffies;
+- num_printed = 0;
+- }
+- if (num_printed++ < 10)
+- printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress);
+- return 0xff;
+- }
+- do {
+- ++Pci_Io_Read_Count;
+- HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
+- } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
+-
+- return (u8)ret.value;
+-}
+-EXPORT_SYMBOL(iSeries_Read_Byte);
+-
+-u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
+-{
+- u64 BarOffset;
+- u64 dsa;
+- int retry = 0;
+- struct HvCallPci_LoadReturn ret;
+- struct iSeries_Device_Node *DevNode =
+- xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+-
+- if (DevNode == NULL) {
+- static unsigned long last_jiffies;
+- static int num_printed;
+-
+- if ((jiffies - last_jiffies) > 60 * HZ) {
+- last_jiffies = jiffies;
+- num_printed = 0;
+- }
+- if (num_printed++ < 10)
+- printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress);
+- return 0xffff;
+- }
+- do {
+- ++Pci_Io_Read_Count;
+- HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
+- BarOffset, 0);
+- } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
+-
+- return swab16((u16)ret.value);
+-}
+-EXPORT_SYMBOL(iSeries_Read_Word);
+-
+-u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
+-{
+- u64 BarOffset;
+- u64 dsa;
+- int retry = 0;
+- struct HvCallPci_LoadReturn ret;
+- struct iSeries_Device_Node *DevNode =
+- xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+-
+- if (DevNode == NULL) {
+- static unsigned long last_jiffies;
+- static int num_printed;
+-
+- if ((jiffies - last_jiffies) > 60 * HZ) {
+- last_jiffies = jiffies;
+- num_printed = 0;
+- }
+- if (num_printed++ < 10)
+- printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress);
+- return 0xffffffff;
+- }
+- do {
+- ++Pci_Io_Read_Count;
+- HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
+- BarOffset, 0);
+- } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
+-
+- return swab32((u32)ret.value);
+-}
+-EXPORT_SYMBOL(iSeries_Read_Long);
+-
+-/*
+- * Write MM I/O Instructions for the iSeries
+- *
+- * iSeries_Write_Byte = Write Byte (8 bit)
+- * iSeries_Write_Word = Write Word(16 bit)
+- * iSeries_Write_Long = Write Long(32 bit)
+- */
+-void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
+-{
+- u64 BarOffset;
+- u64 dsa;
+- int retry = 0;
+- u64 rc;
+- struct iSeries_Device_Node *DevNode =
+- xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+-
+- if (DevNode == NULL) {
+- static unsigned long last_jiffies;
+- static int num_printed;
+-
+- if ((jiffies - last_jiffies) > 60 * HZ) {
+- last_jiffies = jiffies;
+- num_printed = 0;
+- }
+- if (num_printed++ < 10)
+- printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress);
+- return;
+- }
+- do {
+- ++Pci_Io_Write_Count;
+- rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
+- } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
+-}
+-EXPORT_SYMBOL(iSeries_Write_Byte);
+-
+-void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
+-{
+- u64 BarOffset;
+- u64 dsa;
+- int retry = 0;
+- u64 rc;
+- struct iSeries_Device_Node *DevNode =
+- xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+-
+- if (DevNode == NULL) {
+- static unsigned long last_jiffies;
+- static int num_printed;
+-
+- if ((jiffies - last_jiffies) > 60 * HZ) {
+- last_jiffies = jiffies;
+- num_printed = 0;
+- }
+- if (num_printed++ < 10)
+- printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress);
+- return;
+- }
+- do {
+- ++Pci_Io_Write_Count;
+- rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
+- } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
+-}
+-EXPORT_SYMBOL(iSeries_Write_Word);
+-
+-void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
+-{
+- u64 BarOffset;
+- u64 dsa;
+- int retry = 0;
+- u64 rc;
+- struct iSeries_Device_Node *DevNode =
+- xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+-
+- if (DevNode == NULL) {
+- static unsigned long last_jiffies;
+- static int num_printed;
+-
+- if ((jiffies - last_jiffies) > 60 * HZ) {
+- last_jiffies = jiffies;
+- num_printed = 0;
+- }
+- if (num_printed++ < 10)
+- printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress);
+- return;
+- }
+- do {
+- ++Pci_Io_Write_Count;
+- rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
+- } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
+-}
+-EXPORT_SYMBOL(iSeries_Write_Long);
+diff --git a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_proc.c
++++ /dev/null
+@@ -1,113 +0,0 @@
+-/*
+- * iSeries_proc.c
+- * Copyright (C) 2001 Kyle A. Lucke IBM Corporation
+- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#include <linux/init.h>
+-#include <linux/proc_fs.h>
+-#include <linux/seq_file.h>
+-#include <linux/param.h> /* for HZ */
+-#include <asm/paca.h>
+-#include <asm/processor.h>
+-#include <asm/time.h>
+-#include <asm/lppaca.h>
+-#include <asm/iSeries/ItLpQueue.h>
+-#include <asm/iSeries/HvCallXm.h>
+-#include <asm/iSeries/IoHriMainStore.h>
+-#include <asm/iSeries/IoHriProcessorVpd.h>
+-
+-static int __init iseries_proc_create(void)
+-{
+- struct proc_dir_entry *e = proc_mkdir("iSeries", 0);
+- if (!e)
+- return 1;
+-
+- return 0;
+-}
+-core_initcall(iseries_proc_create);
+-
+-static unsigned long startTitan = 0;
+-static unsigned long startTb = 0;
+-
+-static int proc_titantod_show(struct seq_file *m, void *v)
+-{
+- unsigned long tb0, titan_tod;
+-
+- tb0 = get_tb();
+- titan_tod = HvCallXm_loadTod();
+-
+- seq_printf(m, "Titan\n" );
+- seq_printf(m, " time base = %016lx\n", tb0);
+- seq_printf(m, " titan tod = %016lx\n", titan_tod);
+- seq_printf(m, " xProcFreq = %016x\n",
+- xIoHriProcessorVpd[0].xProcFreq);
+- seq_printf(m, " xTimeBaseFreq = %016x\n",
+- xIoHriProcessorVpd[0].xTimeBaseFreq);
+- seq_printf(m, " tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy);
+- seq_printf(m, " tb_ticks_per_usec = %lu\n", tb_ticks_per_usec);
+-
+- if (!startTitan) {
+- startTitan = titan_tod;
+- startTb = tb0;
+- } else {
+- unsigned long titan_usec = (titan_tod - startTitan) >> 12;
+- unsigned long tb_ticks = (tb0 - startTb);
+- unsigned long titan_jiffies = titan_usec / (1000000/HZ);
+- unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ);
+- unsigned long titan_jiff_rem_usec = titan_usec - titan_jiff_usec;
+- unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy;
+- unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy;
+- unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks;
+- unsigned long tb_jiff_rem_usec = tb_jiff_rem_ticks / tb_ticks_per_usec;
+- unsigned long new_tb_ticks_per_jiffy = (tb_ticks * (1000000/HZ))/titan_usec;
+-
+- seq_printf(m, " titan elapsed = %lu uSec\n", titan_usec);
+- seq_printf(m, " tb elapsed = %lu ticks\n", tb_ticks);
+- seq_printf(m, " titan jiffies = %lu.%04lu \n", titan_jiffies,
+- titan_jiff_rem_usec);
+- seq_printf(m, " tb jiffies = %lu.%04lu\n", tb_jiffies,
+- tb_jiff_rem_usec);
+- seq_printf(m, " new tb_ticks_per_jiffy = %lu\n",
+- new_tb_ticks_per_jiffy);
+- }
+-
+- return 0;
+-}
+-
+-static int proc_titantod_open(struct inode *inode, struct file *file)
+-{
+- return single_open(file, proc_titantod_show, NULL);
+-}
+-
+-static struct file_operations proc_titantod_operations = {
+- .open = proc_titantod_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = single_release,
+-};
+-
+-static int __init iseries_proc_init(void)
+-{
+- struct proc_dir_entry *e;
+-
+- e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
+- if (e)
+- e->proc_fops = &proc_titantod_operations;
+-
+- return 0;
+-}
+-__initcall(iseries_proc_init);
+diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_setup.c
++++ /dev/null
+@@ -1,977 +0,0 @@
+-/*
+- * Copyright (c) 2000 Mike Corrigan <mikejc at us.ibm.com>
+- * Copyright (c) 1999-2000 Grant Erickson <grant at lcse.umn.edu>
+- *
+- * Module name: iSeries_setup.c
+- *
+- * Description:
+- * Architecture- / platform-specific boot-time initialization code for
+- * the IBM iSeries LPAR. Adapted from original code by Grant Erickson and
+- * code by Gary Thomas, Cort Dougan <cort at fsmlabs.com>, and Dan Malek
+- * <dan at net4x.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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/init.h>
+-#include <linux/threads.h>
+-#include <linux/smp.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/initrd.h>
+-#include <linux/seq_file.h>
+-#include <linux/kdev_t.h>
+-#include <linux/major.h>
+-#include <linux/root_dev.h>
+-
+-#include <asm/processor.h>
+-#include <asm/machdep.h>
+-#include <asm/page.h>
+-#include <asm/mmu.h>
+-#include <asm/pgtable.h>
+-#include <asm/mmu_context.h>
+-#include <asm/cputable.h>
+-#include <asm/sections.h>
+-#include <asm/iommu.h>
+-#include <asm/firmware.h>
+-
+-#include <asm/time.h>
+-#include "iSeries_setup.h"
+-#include <asm/naca.h>
+-#include <asm/paca.h>
+-#include <asm/cache.h>
+-#include <asm/sections.h>
+-#include <asm/abs_addr.h>
+-#include <asm/iSeries/HvCallHpt.h>
+-#include <asm/iSeries/HvLpConfig.h>
+-#include <asm/iSeries/HvCallEvent.h>
+-#include <asm/iSeries/HvCallSm.h>
+-#include <asm/iSeries/HvCallXm.h>
+-#include <asm/iSeries/ItLpQueue.h>
+-#include <asm/iSeries/IoHriMainStore.h>
+-#include <asm/iSeries/mf.h>
+-#include <asm/iSeries/HvLpEvent.h>
+-#include <asm/iSeries/iSeries_irq.h>
+-#include <asm/iSeries/IoHriProcessorVpd.h>
+-#include <asm/iSeries/ItVpdAreas.h>
+-#include <asm/iSeries/LparMap.h>
+-
+-extern void hvlog(char *fmt, ...);
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) hvlog(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/* Function Prototypes */
+-extern void ppcdbg_initialize(void);
+-
+-static void build_iSeries_Memory_Map(void);
+-static void setup_iSeries_cache_sizes(void);
+-static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
+-#ifdef CONFIG_PCI
+-extern void iSeries_pci_final_fixup(void);
+-#else
+-static void iSeries_pci_final_fixup(void) { }
+-#endif
+-
+-/* Global Variables */
+-static unsigned long procFreqHz;
+-static unsigned long procFreqMhz;
+-static unsigned long procFreqMhzHundreths;
+-
+-static unsigned long tbFreqHz;
+-static unsigned long tbFreqMhz;
+-static unsigned long tbFreqMhzHundreths;
+-
+-int piranha_simulator;
+-
+-extern int rd_size; /* Defined in drivers/block/rd.c */
+-extern unsigned long klimit;
+-extern unsigned long embedded_sysmap_start;
+-extern unsigned long embedded_sysmap_end;
+-
+-extern unsigned long iSeries_recal_tb;
+-extern unsigned long iSeries_recal_titan;
+-
+-static int mf_initialized;
+-
+-struct MemoryBlock {
+- unsigned long absStart;
+- unsigned long absEnd;
+- unsigned long logicalStart;
+- unsigned long logicalEnd;
+-};
+-
+-/*
+- * Process the main store vpd to determine where the holes in memory are
+- * and return the number of physical blocks and fill in the array of
+- * block data.
+- */
+-static unsigned long iSeries_process_Condor_mainstore_vpd(
+- struct MemoryBlock *mb_array, unsigned long max_entries)
+-{
+- unsigned long holeFirstChunk, holeSizeChunks;
+- unsigned long numMemoryBlocks = 1;
+- struct IoHriMainStoreSegment4 *msVpd =
+- (struct IoHriMainStoreSegment4 *)xMsVpd;
+- unsigned long holeStart = msVpd->nonInterleavedBlocksStartAdr;
+- unsigned long holeEnd = msVpd->nonInterleavedBlocksEndAdr;
+- unsigned long holeSize = holeEnd - holeStart;
+-
+- printk("Mainstore_VPD: Condor\n");
+- /*
+- * Determine if absolute memory has any
+- * holes so that we can interpret the
+- * access map we get back from the hypervisor
+- * correctly.
+- */
+- mb_array[0].logicalStart = 0;
+- mb_array[0].logicalEnd = 0x100000000;
+- mb_array[0].absStart = 0;
+- mb_array[0].absEnd = 0x100000000;
+-
+- if (holeSize) {
+- numMemoryBlocks = 2;
+- holeStart = holeStart & 0x000fffffffffffff;
+- holeStart = addr_to_chunk(holeStart);
+- holeFirstChunk = holeStart;
+- holeSize = addr_to_chunk(holeSize);
+- holeSizeChunks = holeSize;
+- printk( "Main store hole: start chunk = %0lx, size = %0lx chunks\n",
+- holeFirstChunk, holeSizeChunks );
+- mb_array[0].logicalEnd = holeFirstChunk;
+- mb_array[0].absEnd = holeFirstChunk;
+- mb_array[1].logicalStart = holeFirstChunk;
+- mb_array[1].logicalEnd = 0x100000000 - holeSizeChunks;
+- mb_array[1].absStart = holeFirstChunk + holeSizeChunks;
+- mb_array[1].absEnd = 0x100000000;
+- }
+- return numMemoryBlocks;
+-}
+-
+-#define MaxSegmentAreas 32
+-#define MaxSegmentAdrRangeBlocks 128
+-#define MaxAreaRangeBlocks 4
+-
+-static unsigned long iSeries_process_Regatta_mainstore_vpd(
+- struct MemoryBlock *mb_array, unsigned long max_entries)
+-{
+- struct IoHriMainStoreSegment5 *msVpdP =
+- (struct IoHriMainStoreSegment5 *)xMsVpd;
+- unsigned long numSegmentBlocks = 0;
+- u32 existsBits = msVpdP->msAreaExists;
+- unsigned long area_num;
+-
+- printk("Mainstore_VPD: Regatta\n");
+-
+- for (area_num = 0; area_num < MaxSegmentAreas; ++area_num ) {
+- unsigned long numAreaBlocks;
+- struct IoHriMainStoreArea4 *currentArea;
+-
+- if (existsBits & 0x80000000) {
+- unsigned long block_num;
+-
+- currentArea = &msVpdP->msAreaArray[area_num];
+- numAreaBlocks = currentArea->numAdrRangeBlocks;
+- printk("ms_vpd: processing area %2ld blocks=%ld",
+- area_num, numAreaBlocks);
+- for (block_num = 0; block_num < numAreaBlocks;
+- ++block_num ) {
+- /* Process an address range block */
+- struct MemoryBlock tempBlock;
+- unsigned long i;
+-
+- tempBlock.absStart =
+- (unsigned long)currentArea->xAdrRangeBlock[block_num].blockStart;
+- tempBlock.absEnd =
+- (unsigned long)currentArea->xAdrRangeBlock[block_num].blockEnd;
+- tempBlock.logicalStart = 0;
+- tempBlock.logicalEnd = 0;
+- printk("\n block %ld absStart=%016lx absEnd=%016lx",
+- block_num, tempBlock.absStart,
+- tempBlock.absEnd);
+-
+- for (i = 0; i < numSegmentBlocks; ++i) {
+- if (mb_array[i].absStart ==
+- tempBlock.absStart)
+- break;
+- }
+- if (i == numSegmentBlocks) {
+- if (numSegmentBlocks == max_entries)
+- panic("iSeries_process_mainstore_vpd: too many memory blocks");
+- mb_array[numSegmentBlocks] = tempBlock;
+- ++numSegmentBlocks;
+- } else
+- printk(" (duplicate)");
+- }
+- printk("\n");
+- }
+- existsBits <<= 1;
+- }
+- /* Now sort the blocks found into ascending sequence */
+- if (numSegmentBlocks > 1) {
+- unsigned long m, n;
+-
+- for (m = 0; m < numSegmentBlocks - 1; ++m) {
+- for (n = numSegmentBlocks - 1; m < n; --n) {
+- if (mb_array[n].absStart <
+- mb_array[n-1].absStart) {
+- struct MemoryBlock tempBlock;
+-
+- tempBlock = mb_array[n];
+- mb_array[n] = mb_array[n-1];
+- mb_array[n-1] = tempBlock;
+- }
+- }
+- }
+- }
+- /*
+- * Assign "logical" addresses to each block. These
+- * addresses correspond to the hypervisor "bitmap" space.
+- * Convert all addresses into units of 256K chunks.
+- */
+- {
+- unsigned long i, nextBitmapAddress;
+-
+- printk("ms_vpd: %ld sorted memory blocks\n", numSegmentBlocks);
+- nextBitmapAddress = 0;
+- for (i = 0; i < numSegmentBlocks; ++i) {
+- unsigned long length = mb_array[i].absEnd -
+- mb_array[i].absStart;
+-
+- mb_array[i].logicalStart = nextBitmapAddress;
+- mb_array[i].logicalEnd = nextBitmapAddress + length;
+- nextBitmapAddress += length;
+- printk(" Bitmap range: %016lx - %016lx\n"
+- " Absolute range: %016lx - %016lx\n",
+- mb_array[i].logicalStart,
+- mb_array[i].logicalEnd,
+- mb_array[i].absStart, mb_array[i].absEnd);
+- mb_array[i].absStart = addr_to_chunk(mb_array[i].absStart &
+- 0x000fffffffffffff);
+- mb_array[i].absEnd = addr_to_chunk(mb_array[i].absEnd &
+- 0x000fffffffffffff);
+- mb_array[i].logicalStart =
+- addr_to_chunk(mb_array[i].logicalStart);
+- mb_array[i].logicalEnd = addr_to_chunk(mb_array[i].logicalEnd);
+- }
+- }
+-
+- return numSegmentBlocks;
+-}
+-
+-static unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
+- unsigned long max_entries)
+-{
+- unsigned long i;
+- unsigned long mem_blocks = 0;
+-
+- if (cpu_has_feature(CPU_FTR_SLB))
+- mem_blocks = iSeries_process_Regatta_mainstore_vpd(mb_array,
+- max_entries);
+- else
+- mem_blocks = iSeries_process_Condor_mainstore_vpd(mb_array,
+- max_entries);
+-
+- printk("Mainstore_VPD: numMemoryBlocks = %ld \n", mem_blocks);
+- for (i = 0; i < mem_blocks; ++i) {
+- printk("Mainstore_VPD: block %3ld logical chunks %016lx - %016lx\n"
+- " abs chunks %016lx - %016lx\n",
+- i, mb_array[i].logicalStart, mb_array[i].logicalEnd,
+- mb_array[i].absStart, mb_array[i].absEnd);
+- }
+- return mem_blocks;
+-}
+-
+-static void __init iSeries_get_cmdline(void)
+-{
+- char *p, *q;
+-
+- /* copy the command line parameter from the primary VSP */
+- HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
+- HvLpDma_Direction_RemoteToLocal);
+-
+- p = cmd_line;
+- q = cmd_line + 255;
+- while(p < q) {
+- if (!*p || *p == '\n')
+- break;
+- ++p;
+- }
+- *p = 0;
+-}
+-
+-static void __init iSeries_init_early(void)
+-{
+- extern unsigned long memory_limit;
+-
+- DBG(" -> iSeries_init_early()\n");
+-
+- ppc64_firmware_features = FW_FEATURE_ISERIES;
+-
+- ppcdbg_initialize();
+-
+-#if defined(CONFIG_BLK_DEV_INITRD)
+- /*
+- * If the init RAM disk has been configured and there is
+- * a non-zero starting address for it, set it up
+- */
+- if (naca.xRamDisk) {
+- initrd_start = (unsigned long)__va(naca.xRamDisk);
+- initrd_end = initrd_start + naca.xRamDiskSize * PAGE_SIZE;
+- initrd_below_start_ok = 1; // ramdisk in kernel space
+- ROOT_DEV = Root_RAM0;
+- if (((rd_size * 1024) / PAGE_SIZE) < naca.xRamDiskSize)
+- rd_size = (naca.xRamDiskSize * PAGE_SIZE) / 1024;
+- } else
+-#endif /* CONFIG_BLK_DEV_INITRD */
+- {
+- /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */
+- }
+-
+- iSeries_recal_tb = get_tb();
+- iSeries_recal_titan = HvCallXm_loadTod();
+-
+- /*
+- * Cache sizes must be initialized before hpte_init_iSeries is called
+- * as the later need them for flush_icache_range()
+- */
+- setup_iSeries_cache_sizes();
+-
+- /*
+- * Initialize the hash table management pointers
+- */
+- hpte_init_iSeries();
+-
+- /*
+- * Initialize the DMA/TCE management
+- */
+- iommu_init_early_iSeries();
+-
+- /*
+- * Initialize the table which translate Linux physical addresses to
+- * AS/400 absolute addresses
+- */
+- build_iSeries_Memory_Map();
+-
+- iSeries_get_cmdline();
+-
+- /* Save unparsed command line copy for /proc/cmdline */
+- strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+-
+- /* Parse early parameters, in particular mem=x */
+- parse_early_param();
+-
+- if (memory_limit) {
+- if (memory_limit < systemcfg->physicalMemorySize)
+- systemcfg->physicalMemorySize = memory_limit;
+- else {
+- printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
+- memory_limit = 0;
+- }
+- }
+-
+- /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
+- iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
+-
+- lmb_init();
+- lmb_add(0, systemcfg->physicalMemorySize);
+- lmb_analyze();
+- lmb_reserve(0, __pa(klimit));
+-
+- /* Initialize machine-dependency vectors */
+-#ifdef CONFIG_SMP
+- smp_init_iSeries();
+-#endif
+- if (itLpNaca.xPirEnvironMode == 0)
+- piranha_simulator = 1;
+-
+- /* Associate Lp Event Queue 0 with processor 0 */
+- HvCallEvent_setLpEventQueueInterruptProc(0, 0);
+-
+- mf_init();
+- mf_initialized = 1;
+- mb();
+-
+- /* If we were passed an initrd, set the ROOT_DEV properly if the values
+- * look sensible. If not, clear initrd reference.
+- */
+-#ifdef CONFIG_BLK_DEV_INITRD
+- if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
+- initrd_end > initrd_start)
+- ROOT_DEV = Root_RAM0;
+- else
+- initrd_start = initrd_end = 0;
+-#endif /* CONFIG_BLK_DEV_INITRD */
+-
+- DBG(" <- iSeries_init_early()\n");
+-}
+-
+-struct mschunks_map mschunks_map = {
+- /* XXX We don't use these, but Piranha might need them. */
+- .chunk_size = MSCHUNKS_CHUNK_SIZE,
+- .chunk_shift = MSCHUNKS_CHUNK_SHIFT,
+- .chunk_mask = MSCHUNKS_OFFSET_MASK,
+-};
+-EXPORT_SYMBOL(mschunks_map);
+-
+-void mschunks_alloc(unsigned long num_chunks)
+-{
+- klimit = _ALIGN(klimit, sizeof(u32));
+- mschunks_map.mapping = (u32 *)klimit;
+- klimit += num_chunks * sizeof(u32);
+- mschunks_map.num_chunks = num_chunks;
+-}
+-
+-/*
+- * The iSeries may have very large memories ( > 128 GB ) and a partition
+- * may get memory in "chunks" that may be anywhere in the 2**52 real
+- * address space. The chunks are 256K in size. To map this to the
+- * memory model Linux expects, the AS/400 specific code builds a
+- * translation table to translate what Linux thinks are "physical"
+- * addresses to the actual real addresses. This allows us to make
+- * it appear to Linux that we have contiguous memory starting at
+- * physical address zero while in fact this could be far from the truth.
+- * To avoid confusion, I'll let the words physical and/or real address
+- * apply to the Linux addresses while I'll use "absolute address" to
+- * refer to the actual hardware real address.
+- *
+- * build_iSeries_Memory_Map gets information from the Hypervisor and
+- * looks at the Main Store VPD to determine the absolute addresses
+- * of the memory that has been assigned to our partition and builds
+- * a table used to translate Linux's physical addresses to these
+- * absolute addresses. Absolute addresses are needed when
+- * communicating with the hypervisor (e.g. to build HPT entries)
+- */
+-
+-static void __init build_iSeries_Memory_Map(void)
+-{
+- u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize;
+- u32 nextPhysChunk;
+- u32 hptFirstChunk, hptLastChunk, hptSizeChunks, hptSizePages;
+- u32 num_ptegs;
+- u32 totalChunks,moreChunks;
+- u32 currChunk, thisChunk, absChunk;
+- u32 currDword;
+- u32 chunkBit;
+- u64 map;
+- struct MemoryBlock mb[32];
+- unsigned long numMemoryBlocks, curBlock;
+-
+- /* Chunk size on iSeries is 256K bytes */
+- totalChunks = (u32)HvLpConfig_getMsChunks();
+- mschunks_alloc(totalChunks);
+-
+- /*
+- * Get absolute address of our load area
+- * and map it to physical address 0
+- * This guarantees that the loadarea ends up at physical 0
+- * otherwise, it might not be returned by PLIC as the first
+- * chunks
+- */
+-
+- loadAreaFirstChunk = (u32)addr_to_chunk(itLpNaca.xLoadAreaAddr);
+- loadAreaSize = itLpNaca.xLoadAreaChunks;
+-
+- /*
+- * Only add the pages already mapped here.
+- * Otherwise we might add the hpt pages
+- * The rest of the pages of the load area
+- * aren't in the HPT yet and can still
+- * be assigned an arbitrary physical address
+- */
+- if ((loadAreaSize * 64) > HvPagesToMap)
+- loadAreaSize = HvPagesToMap / 64;
+-
+- loadAreaLastChunk = loadAreaFirstChunk + loadAreaSize - 1;
+-
+- /*
+- * TODO Do we need to do something if the HPT is in the 64MB load area?
+- * This would be required if the itLpNaca.xLoadAreaChunks includes
+- * the HPT size
+- */
+-
+- printk("Mapping load area - physical addr = 0000000000000000\n"
+- " absolute addr = %016lx\n",
+- chunk_to_addr(loadAreaFirstChunk));
+- printk("Load area size %dK\n", loadAreaSize * 256);
+-
+- for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)
+- mschunks_map.mapping[nextPhysChunk] =
+- loadAreaFirstChunk + nextPhysChunk;
+-
+- /*
+- * Get absolute address of our HPT and remember it so
+- * we won't map it to any physical address
+- */
+- hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
+- hptSizePages = (u32)HvCallHpt_getHptPages();
+- hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT);
+- hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
+-
+- printk("HPT absolute addr = %016lx, size = %dK\n",
+- chunk_to_addr(hptFirstChunk), hptSizeChunks * 256);
+-
+- /* Fill in the hashed page table hash mask */
+- num_ptegs = hptSizePages *
+- (PAGE_SIZE / (sizeof(hpte_t) * HPTES_PER_GROUP));
+- htab_hash_mask = num_ptegs - 1;
+-
+- /*
+- * The actual hashed page table is in the hypervisor,
+- * we have no direct access
+- */
+- htab_address = NULL;
+-
+- /*
+- * Determine if absolute memory has any
+- * holes so that we can interpret the
+- * access map we get back from the hypervisor
+- * correctly.
+- */
+- numMemoryBlocks = iSeries_process_mainstore_vpd(mb, 32);
+-
+- /*
+- * Process the main store access map from the hypervisor
+- * to build up our physical -> absolute translation table
+- */
+- curBlock = 0;
+- currChunk = 0;
+- currDword = 0;
+- moreChunks = totalChunks;
+-
+- while (moreChunks) {
+- map = HvCallSm_get64BitsOfAccessMap(itLpNaca.xLpIndex,
+- currDword);
+- thisChunk = currChunk;
+- while (map) {
+- chunkBit = map >> 63;
+- map <<= 1;
+- if (chunkBit) {
+- --moreChunks;
+- while (thisChunk >= mb[curBlock].logicalEnd) {
+- ++curBlock;
+- if (curBlock >= numMemoryBlocks)
+- panic("out of memory blocks");
+- }
+- if (thisChunk < mb[curBlock].logicalStart)
+- panic("memory block error");
+-
+- absChunk = mb[curBlock].absStart +
+- (thisChunk - mb[curBlock].logicalStart);
+- if (((absChunk < hptFirstChunk) ||
+- (absChunk > hptLastChunk)) &&
+- ((absChunk < loadAreaFirstChunk) ||
+- (absChunk > loadAreaLastChunk))) {
+- mschunks_map.mapping[nextPhysChunk] =
+- absChunk;
+- ++nextPhysChunk;
+- }
+- }
+- ++thisChunk;
+- }
+- ++currDword;
+- currChunk += 64;
+- }
+-
+- /*
+- * main store size (in chunks) is
+- * totalChunks - hptSizeChunks
+- * which should be equal to
+- * nextPhysChunk
+- */
+- systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
+-}
+-
+-/*
+- * Set up the variables that describe the cache line sizes
+- * for this machine.
+- */
+-static void __init setup_iSeries_cache_sizes(void)
+-{
+- unsigned int i, n;
+- unsigned int procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
+-
+- systemcfg->icache_size =
+- ppc64_caches.isize = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024;
+- systemcfg->icache_line_size =
+- ppc64_caches.iline_size =
+- xIoHriProcessorVpd[procIx].xInstCacheOperandSize;
+- systemcfg->dcache_size =
+- ppc64_caches.dsize =
+- xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024;
+- systemcfg->dcache_line_size =
+- ppc64_caches.dline_size =
+- xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
+- ppc64_caches.ilines_per_page = PAGE_SIZE / ppc64_caches.iline_size;
+- ppc64_caches.dlines_per_page = PAGE_SIZE / ppc64_caches.dline_size;
+-
+- i = ppc64_caches.iline_size;
+- n = 0;
+- while ((i = (i / 2)))
+- ++n;
+- ppc64_caches.log_iline_size = n;
+-
+- i = ppc64_caches.dline_size;
+- n = 0;
+- while ((i = (i / 2)))
+- ++n;
+- ppc64_caches.log_dline_size = n;
+-
+- printk("D-cache line size = %d\n",
+- (unsigned int)ppc64_caches.dline_size);
+- printk("I-cache line size = %d\n",
+- (unsigned int)ppc64_caches.iline_size);
+-}
+-
+-/*
+- * Create a pte. Used during initialization only.
+- */
+-static void iSeries_make_pte(unsigned long va, unsigned long pa,
+- int mode)
+-{
+- hpte_t local_hpte, rhpte;
+- unsigned long hash, vpn;
+- long slot;
+-
+- vpn = va >> PAGE_SHIFT;
+- hash = hpt_hash(vpn, 0);
+-
+- local_hpte.r = pa | mode;
+- local_hpte.v = ((va >> 23) << HPTE_V_AVPN_SHIFT)
+- | HPTE_V_BOLTED | HPTE_V_VALID;
+-
+- slot = HvCallHpt_findValid(&rhpte, vpn);
+- if (slot < 0) {
+- /* Must find space in primary group */
+- panic("hash_page: hpte already exists\n");
+- }
+- HvCallHpt_addValidate(slot, 0, &local_hpte);
+-}
+-
+-/*
+- * Bolt the kernel addr space into the HPT
+- */
+-static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
+-{
+- unsigned long pa;
+- unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
+- hpte_t hpte;
+-
+- for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
+- unsigned long ea = (unsigned long)__va(pa);
+- unsigned long vsid = get_kernel_vsid(ea);
+- unsigned long va = (vsid << 28) | (pa & 0xfffffff);
+- unsigned long vpn = va >> PAGE_SHIFT;
+- unsigned long slot = HvCallHpt_findValid(&hpte, vpn);
+-
+- /* Make non-kernel text non-executable */
+- if (!in_kernel_text(ea))
+- mode_rw |= HW_NO_EXEC;
+-
+- if (hpte.v & HPTE_V_VALID) {
+- /* HPTE exists, so just bolt it */
+- HvCallHpt_setSwBits(slot, 0x10, 0);
+- /* And make sure the pp bits are correct */
+- HvCallHpt_setPp(slot, PP_RWXX);
+- } else
+- /* No HPTE exists, so create a new bolted one */
+- iSeries_make_pte(va, phys_to_abs(pa), mode_rw);
+- }
+-}
+-
+-/*
+- * Document me.
+- */
+-static void __init iSeries_setup_arch(void)
+-{
+- unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
+-
+- /* Add an eye catcher and the systemcfg layout version number */
+- strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
+- systemcfg->version.major = SYSTEMCFG_MAJOR;
+- systemcfg->version.minor = SYSTEMCFG_MINOR;
+-
+- /* Setup the Lp Event Queue */
+- setup_hvlpevent_queue();
+-
+- /* Compute processor frequency */
+- procFreqHz = ((1UL << 34) * 1000000) /
+- xIoHriProcessorVpd[procIx].xProcFreq;
+- procFreqMhz = procFreqHz / 1000000;
+- procFreqMhzHundreths = (procFreqHz / 10000) - (procFreqMhz * 100);
+- ppc_proc_freq = procFreqHz;
+-
+- /* Compute time base frequency */
+- tbFreqHz = ((1UL << 32) * 1000000) /
+- xIoHriProcessorVpd[procIx].xTimeBaseFreq;
+- tbFreqMhz = tbFreqHz / 1000000;
+- tbFreqMhzHundreths = (tbFreqHz / 10000) - (tbFreqMhz * 100);
+- ppc_tb_freq = tbFreqHz;
+-
+- printk("Max logical processors = %d\n",
+- itVpdAreas.xSlicMaxLogicalProcs);
+- printk("Max physical processors = %d\n",
+- itVpdAreas.xSlicMaxPhysicalProcs);
+- printk("Processor frequency = %lu.%02lu\n", procFreqMhz,
+- procFreqMhzHundreths);
+- printk("Time base frequency = %lu.%02lu\n", tbFreqMhz,
+- tbFreqMhzHundreths);
+- systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
+- printk("Processor version = %x\n", systemcfg->processor);
+-}
+-
+-static void iSeries_get_cpuinfo(struct seq_file *m)
+-{
+- seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
+-}
+-
+-/*
+- * Document me.
+- * and Implement me.
+- */
+-static int iSeries_get_irq(struct pt_regs *regs)
+-{
+- /* -2 means ignore this interrupt */
+- return -2;
+-}
+-
+-/*
+- * Document me.
+- */
+-static void iSeries_restart(char *cmd)
+-{
+- mf_reboot();
+-}
+-
+-/*
+- * Document me.
+- */
+-static void iSeries_power_off(void)
+-{
+- mf_power_off();
+-}
+-
+-/*
+- * Document me.
+- */
+-static void iSeries_halt(void)
+-{
+- mf_power_off();
+-}
+-
+-/*
+- * void __init iSeries_calibrate_decr()
+- *
+- * Description:
+- * This routine retrieves the internal processor frequency from the VPD,
+- * and sets up the kernel timer decrementer based on that value.
+- *
+- */
+-static void __init iSeries_calibrate_decr(void)
+-{
+- unsigned long cyclesPerUsec;
+- struct div_result divres;
+-
+- /* Compute decrementer (and TB) frequency in cycles/sec */
+- cyclesPerUsec = ppc_tb_freq / 1000000;
+-
+- /*
+- * Set the amount to refresh the decrementer by. This
+- * is the number of decrementer ticks it takes for
+- * 1/HZ seconds.
+- */
+- tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+-
+-#if 0
+- /* TEST CODE FOR ADJTIME */
+- tb_ticks_per_jiffy += tb_ticks_per_jiffy / 5000;
+- /* END OF TEST CODE */
+-#endif
+-
+- /*
+- * tb_ticks_per_sec = freq; would give better accuracy
+- * but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures
+- * that jiffies (and xtime) will match the time returned
+- * by do_gettimeofday.
+- */
+- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+- tb_ticks_per_usec = cyclesPerUsec;
+- tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
+- div128_by_32(1024 * 1024, 0, tb_ticks_per_sec, &divres);
+- tb_to_xs = divres.result_low;
+- setup_default_decr();
+-}
+-
+-static void __init iSeries_progress(char * st, unsigned short code)
+-{
+- printk("Progress: [%04x] - %s\n", (unsigned)code, st);
+- if (!piranha_simulator && mf_initialized) {
+- if (code != 0xffff)
+- mf_display_progress(code);
+- else
+- mf_clear_src();
+- }
+-}
+-
+-static void __init iSeries_fixup_klimit(void)
+-{
+- /*
+- * Change klimit to take into account any ram disk
+- * that may be included
+- */
+- if (naca.xRamDisk)
+- klimit = KERNELBASE + (u64)naca.xRamDisk +
+- (naca.xRamDiskSize * PAGE_SIZE);
+- else {
+- /*
+- * No ram disk was included - check and see if there
+- * was an embedded system map. Change klimit to take
+- * into account any embedded system map
+- */
+- if (embedded_sysmap_end)
+- klimit = KERNELBASE + ((embedded_sysmap_end + 4095) &
+- 0xfffffffffffff000);
+- }
+-}
+-
+-static int __init iSeries_src_init(void)
+-{
+- /* clear the progress line */
+- ppc_md.progress(" ", 0xffff);
+- return 0;
+-}
+-
+-late_initcall(iSeries_src_init);
+-
+-static inline void process_iSeries_events(void)
+-{
+- asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
+-}
+-
+-static void yield_shared_processor(void)
+-{
+- unsigned long tb;
+-
+- HvCall_setEnabledInterrupts(HvCall_MaskIPI |
+- HvCall_MaskLpEvent |
+- HvCall_MaskLpProd |
+- HvCall_MaskTimeout);
+-
+- tb = get_tb();
+- /* Compute future tb value when yield should expire */
+- HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
+-
+- /*
+- * The decrementer stops during the yield. Force a fake decrementer
+- * here and let the timer_interrupt code sort out the actual time.
+- */
+- get_paca()->lppaca.int_dword.fields.decr_int = 1;
+- process_iSeries_events();
+-}
+-
+-static int iseries_shared_idle(void)
+-{
+- while (1) {
+- while (!need_resched() && !hvlpevent_is_pending()) {
+- local_irq_disable();
+- ppc64_runlatch_off();
+-
+- /* Recheck with irqs off */
+- if (!need_resched() && !hvlpevent_is_pending())
+- yield_shared_processor();
+-
+- HMT_medium();
+- local_irq_enable();
+- }
+-
+- ppc64_runlatch_on();
+-
+- if (hvlpevent_is_pending())
+- process_iSeries_events();
+-
+- schedule();
+- }
+-
+- return 0;
+-}
+-
+-static int iseries_dedicated_idle(void)
+-{
+- long oldval;
+-
+- while (1) {
+- oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+-
+- if (!oldval) {
+- set_thread_flag(TIF_POLLING_NRFLAG);
+-
+- while (!need_resched()) {
+- ppc64_runlatch_off();
+- HMT_low();
+-
+- if (hvlpevent_is_pending()) {
+- HMT_medium();
+- ppc64_runlatch_on();
+- process_iSeries_events();
+- }
+- }
+-
+- HMT_medium();
+- clear_thread_flag(TIF_POLLING_NRFLAG);
+- } else {
+- set_need_resched();
+- }
+-
+- ppc64_runlatch_on();
+- schedule();
+- }
+-
+- return 0;
+-}
+-
+-#ifndef CONFIG_PCI
+-void __init iSeries_init_IRQ(void) { }
+-#endif
+-
+-void __init iSeries_early_setup(void)
+-{
+- iSeries_fixup_klimit();
+-
+- ppc_md.setup_arch = iSeries_setup_arch;
+- ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
+- ppc_md.init_IRQ = iSeries_init_IRQ;
+- ppc_md.get_irq = iSeries_get_irq;
+- ppc_md.init_early = iSeries_init_early,
+-
+- ppc_md.pcibios_fixup = iSeries_pci_final_fixup;
+-
+- ppc_md.restart = iSeries_restart;
+- ppc_md.power_off = iSeries_power_off;
+- ppc_md.halt = iSeries_halt;
+-
+- ppc_md.get_boot_time = iSeries_get_boot_time;
+- ppc_md.set_rtc_time = iSeries_set_rtc_time;
+- ppc_md.get_rtc_time = iSeries_get_rtc_time;
+- ppc_md.calibrate_decr = iSeries_calibrate_decr;
+- ppc_md.progress = iSeries_progress;
+-
+- /* XXX Implement enable_pmcs for iSeries */
+-
+- if (get_paca()->lppaca.shared_proc) {
+- ppc_md.idle_loop = iseries_shared_idle;
+- printk(KERN_INFO "Using shared processor idle loop\n");
+- } else {
+- ppc_md.idle_loop = iseries_dedicated_idle;
+- printk(KERN_INFO "Using dedicated idle loop\n");
+- }
+-}
+-
+diff --git a/arch/ppc64/kernel/iSeries_setup.h b/arch/ppc64/kernel/iSeries_setup.h
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_setup.h
++++ /dev/null
+@@ -1,26 +0,0 @@
+-/*
+- * Copyright (c) 2000 Mike Corrigan <mikejc at us.ibm.com>
+- * Copyright (c) 1999-2000 Grant Erickson <grant at lcse.umn.edu>
+- *
+- * Module name: as400_setup.h
+- *
+- * Description:
+- * Architecture- / platform-specific boot-time initialization code for
+- * the IBM AS/400 LPAR. Adapted from original code by Grant Erickson and
+- * code by Gary Thomas, Cort Dougan <cort at cs.nmt.edu>, and Dan Malek
+- * <dan at netx4.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 __ISERIES_SETUP_H__
+-#define __ISERIES_SETUP_H__
+-
+-extern void iSeries_get_boot_time(struct rtc_time *tm);
+-extern int iSeries_set_rtc_time(struct rtc_time *tm);
+-extern void iSeries_get_rtc_time(struct rtc_time *tm);
+-
+-#endif /* __ISERIES_SETUP_H__ */
+diff --git a/arch/ppc64/kernel/iSeries_smp.c b/arch/ppc64/kernel/iSeries_smp.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_smp.c
++++ /dev/null
+@@ -1,149 +0,0 @@
+-/*
+- * SMP support for iSeries machines.
+- *
+- * Dave Engebretsen, Peter Bergner, and
+- * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+- *
+- * Plus various changes from other IBM teams...
+- *
+- * 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/interrupt.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/spinlock.h>
+-#include <linux/cache.h>
+-#include <linux/err.h>
+-#include <linux/sysdev.h>
+-#include <linux/cpu.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/atomic.h>
+-#include <asm/irq.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/io.h>
+-#include <asm/smp.h>
+-#include <asm/paca.h>
+-#include <asm/iSeries/HvCall.h>
+-#include <asm/time.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/machdep.h>
+-#include <asm/cputable.h>
+-#include <asm/system.h>
+-
+-static unsigned long iSeries_smp_message[NR_CPUS];
+-
+-void iSeries_smp_message_recv( struct pt_regs * regs )
+-{
+- int cpu = smp_processor_id();
+- int msg;
+-
+- if ( num_online_cpus() < 2 )
+- return;
+-
+- for ( msg = 0; msg < 4; ++msg )
+- if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) )
+- smp_message_recv( msg, regs );
+-}
+-
+-static inline void smp_iSeries_do_message(int cpu, int msg)
+-{
+- set_bit(msg, &iSeries_smp_message[cpu]);
+- HvCall_sendIPI(&(paca[cpu]));
+-}
+-
+-static void smp_iSeries_message_pass(int target, int msg)
+-{
+- int i;
+-
+- if (target < NR_CPUS)
+- smp_iSeries_do_message(target, msg);
+- else {
+- for_each_online_cpu(i) {
+- if (target == MSG_ALL_BUT_SELF
+- && i == smp_processor_id())
+- continue;
+- smp_iSeries_do_message(i, msg);
+- }
+- }
+-}
+-
+-static int smp_iSeries_numProcs(void)
+-{
+- unsigned np, i;
+-
+- np = 0;
+- for (i=0; i < NR_CPUS; ++i) {
+- if (paca[i].lppaca.dyn_proc_status < 2) {
+- cpu_set(i, cpu_possible_map);
+- cpu_set(i, cpu_present_map);
+- cpu_set(i, cpu_sibling_map[i]);
+- ++np;
+- }
+- }
+- return np;
+-}
+-
+-static int smp_iSeries_probe(void)
+-{
+- unsigned i;
+- unsigned np = 0;
+-
+- for (i=0; i < NR_CPUS; ++i) {
+- if (paca[i].lppaca.dyn_proc_status < 2) {
+- /*paca[i].active = 1;*/
+- ++np;
+- }
+- }
+-
+- return np;
+-}
+-
+-static void smp_iSeries_kick_cpu(int nr)
+-{
+- BUG_ON(nr < 0 || nr >= NR_CPUS);
+-
+- /* Verify that our partition has a processor nr */
+- if (paca[nr].lppaca.dyn_proc_status >= 2)
+- return;
+-
+- /* The processor is currently spinning, waiting
+- * for the cpu_start field to become non-zero
+- * After we set cpu_start, the processor will
+- * continue on to secondary_start in iSeries_head.S
+- */
+- paca[nr].cpu_start = 1;
+-}
+-
+-static void __devinit smp_iSeries_setup_cpu(int nr)
+-{
+-}
+-
+-static struct smp_ops_t iSeries_smp_ops = {
+- .message_pass = smp_iSeries_message_pass,
+- .probe = smp_iSeries_probe,
+- .kick_cpu = smp_iSeries_kick_cpu,
+- .setup_cpu = smp_iSeries_setup_cpu,
+-};
+-
+-/* This is called very early. */
+-void __init smp_init_iSeries(void)
+-{
+- smp_ops = &iSeries_smp_ops;
+- systemcfg->processorCount = smp_iSeries_numProcs();
+-}
+-
+diff --git a/arch/ppc64/kernel/iSeries_vio.c b/arch/ppc64/kernel/iSeries_vio.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/iSeries_vio.c
++++ /dev/null
+@@ -1,155 +0,0 @@
+-/*
+- * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
+- *
+- * Copyright (c) 2005 Stephen Rothwell, IBM Corp.
+- *
+- * 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/device.h>
+-#include <linux/init.h>
+-
+-#include <asm/vio.h>
+-#include <asm/iommu.h>
+-#include <asm/abs_addr.h>
+-#include <asm/page.h>
+-#include <asm/iSeries/vio.h>
+-#include <asm/iSeries/HvTypes.h>
+-#include <asm/iSeries/HvLpConfig.h>
+-#include <asm/iSeries/HvCallXm.h>
+-
+-struct device *iSeries_vio_dev = &vio_bus_device.dev;
+-EXPORT_SYMBOL(iSeries_vio_dev);
+-
+-static struct iommu_table veth_iommu_table;
+-static struct iommu_table vio_iommu_table;
+-
+-static void __init iommu_vio_init(void)
+-{
+- struct iommu_table *t;
+- struct iommu_table_cb cb;
+- unsigned long cbp;
+- unsigned long itc_entries;
+-
+- cb.itc_busno = 255; /* Bus 255 is the virtual bus */
+- cb.itc_virtbus = 0xff; /* Ask for virtual bus */
+-
+- cbp = virt_to_abs(&cb);
+- HvCallXm_getTceTableParms(cbp);
+-
+- itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
+- veth_iommu_table.it_size = itc_entries / 2;
+- veth_iommu_table.it_busno = cb.itc_busno;
+- veth_iommu_table.it_offset = cb.itc_offset;
+- veth_iommu_table.it_index = cb.itc_index;
+- veth_iommu_table.it_type = TCE_VB;
+- veth_iommu_table.it_blocksize = 1;
+-
+- t = iommu_init_table(&veth_iommu_table);
+-
+- if (!t)
+- printk("Virtual Bus VETH TCE table failed.\n");
+-
+- vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
+- vio_iommu_table.it_busno = cb.itc_busno;
+- vio_iommu_table.it_offset = cb.itc_offset +
+- veth_iommu_table.it_size;
+- vio_iommu_table.it_index = cb.itc_index;
+- vio_iommu_table.it_type = TCE_VB;
+- vio_iommu_table.it_blocksize = 1;
+-
+- t = iommu_init_table(&vio_iommu_table);
+-
+- if (!t)
+- printk("Virtual Bus VIO TCE table failed.\n");
+-}
+-
+-/**
+- * vio_register_device_iseries: - Register a new iSeries vio device.
+- * @voidev: The device to register.
+- */
+-static struct vio_dev *__init vio_register_device_iseries(char *type,
+- uint32_t unit_num)
+-{
+- struct vio_dev *viodev;
+-
+- /* allocate a vio_dev for this device */
+- viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
+- if (!viodev)
+- return NULL;
+- memset(viodev, 0, sizeof(struct vio_dev));
+-
+- snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
+-
+- viodev->name = viodev->dev.bus_id;
+- viodev->type = type;
+- viodev->unit_address = unit_num;
+- viodev->iommu_table = &vio_iommu_table;
+- if (vio_register_device(viodev) == NULL) {
+- kfree(viodev);
+- return NULL;
+- }
+- return viodev;
+-}
+-
+-void __init probe_bus_iseries(void)
+-{
+- HvLpIndexMap vlan_map;
+- struct vio_dev *viodev;
+- int i;
+-
+- /* there is only one of each of these */
+- vio_register_device_iseries("viocons", 0);
+- vio_register_device_iseries("vscsi", 0);
+-
+- vlan_map = HvLpConfig_getVirtualLanIndexMap();
+- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+- if ((vlan_map & (0x8000 >> i)) == 0)
+- continue;
+- viodev = vio_register_device_iseries("vlan", i);
+- /* veth is special and has it own iommu_table */
+- viodev->iommu_table = &veth_iommu_table;
+- }
+- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
+- vio_register_device_iseries("viodasd", i);
+- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
+- vio_register_device_iseries("viocd", i);
+- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
+- vio_register_device_iseries("viotape", i);
+-}
+-
+-/**
+- * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
+- * vio_device_id
+- */
+-static int vio_match_device_iseries(const struct vio_device_id *id,
+- const struct vio_dev *dev)
+-{
+- return strncmp(dev->type, id->type, strlen(id->type)) == 0;
+-}
+-
+-static struct vio_bus_ops vio_bus_ops_iseries = {
+- .match = vio_match_device_iseries,
+-};
+-
+-/**
+- * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
+- */
+-static int __init vio_bus_init_iseries(void)
+-{
+- int err;
+-
+- err = vio_bus_init(&vio_bus_ops_iseries);
+- if (err == 0) {
+- iommu_vio_init();
+- vio_bus_device.iommu_table = &vio_iommu_table;
+- iSeries_vio_dev = &vio_bus_device.dev;
+- probe_bus_iseries();
+- }
+- return err;
+-}
+-
+-__initcall(vio_bus_init_iseries);
+diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
+--- a/arch/ppc64/kernel/idle.c
++++ b/arch/ppc64/kernel/idle.c
+@@ -31,7 +31,7 @@
+
+ extern void power4_idle(void);
+
+-int default_idle(void)
++void default_idle(void)
+ {
+ long oldval;
+ unsigned int cpu = smp_processor_id();
+@@ -64,11 +64,9 @@ int default_idle(void)
+ if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+ cpu_die();
+ }
+-
+- return 0;
+ }
+
+-int native_idle(void)
++void native_idle(void)
+ {
+ while (1) {
+ ppc64_runlatch_off();
+@@ -85,8 +83,6 @@ int native_idle(void)
+ system_state == SYSTEM_RUNNING)
+ cpu_die();
+ }
+-
+- return 0;
+ }
+
+ void cpu_idle(void)
+diff --git a/arch/ppc64/kernel/idle_power4.S b/arch/ppc64/kernel/idle_power4.S
+deleted file mode 100644
+--- a/arch/ppc64/kernel/idle_power4.S
++++ /dev/null
+@@ -1,79 +0,0 @@
+-/*
+- * This file contains the power_save function for 6xx & 7xxx CPUs
+- * rewritten in assembler
+- *
+- * Warning ! This code assumes that if your machine has a 750fx
+- * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
+- * if this is not the case some additional changes will have to
+- * be done to check a runtime var (a bit like powersave-nap)
+- *
+- * 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/threads.h>
+-#include <asm/processor.h>
+-#include <asm/page.h>
+-#include <asm/cputable.h>
+-#include <asm/thread_info.h>
+-#include <asm/ppc_asm.h>
+-#include <asm/asm-offsets.h>
+-
+-#undef DEBUG
+-
+- .text
+-
+-/*
+- * Here is the power_save_6xx function. This could eventually be
+- * split into several functions & changing the function pointer
+- * depending on the various features.
+- */
+-_GLOBAL(power4_idle)
+-BEGIN_FTR_SECTION
+- blr
+-END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
+- /* We must dynamically check for the NAP feature as it
+- * can be cleared by CPU init after the fixups are done
+- */
+- LOADBASE(r3,cur_cpu_spec)
+- ld r4,cur_cpu_spec at l(r3)
+- ld r4,CPU_SPEC_FEATURES(r4)
+- andi. r0,r4,CPU_FTR_CAN_NAP
+- beqlr
+- /* Now check if user or arch enabled NAP mode */
+- LOADBASE(r3,powersave_nap)
+- lwz r4,powersave_nap at l(r3)
+- cmpwi 0,r4,0
+- beqlr
+-
+- /* Clear MSR:EE */
+- mfmsr r7
+- li r4,0
+- ori r4,r4,MSR_EE
+- andc r0,r7,r4
+- mtmsrd r0
+-
+- /* Check current_thread_info()->flags */
+- clrrdi r4,r1,THREAD_SHIFT
+- ld r4,TI_FLAGS(r4)
+- andi. r0,r4,_TIF_NEED_RESCHED
+- beq 1f
+- mtmsrd r7 /* out of line this ? */
+- blr
+-1:
+- /* Go to NAP now */
+-BEGIN_FTR_SECTION
+- DSSALL
+- sync
+-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+- oris r7,r7,MSR_POW at h
+- sync
+- isync
+- mtmsrd r7
+- isync
+- sync
+- blr
+-
+diff --git a/arch/ppc64/kernel/init_task.c b/arch/ppc64/kernel/init_task.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/init_task.c
++++ /dev/null
+@@ -1,36 +0,0 @@
+-#include <linux/mm.h>
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/init_task.h>
+-#include <linux/fs.h>
+-#include <linux/mqueue.h>
+-#include <asm/uaccess.h>
+-
+-static struct fs_struct init_fs = INIT_FS;
+-static struct files_struct init_files = INIT_FILES;
+-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+-struct mm_struct init_mm = INIT_MM(init_mm);
+-
+-EXPORT_SYMBOL(init_mm);
+-
+-/*
+- * Initial thread structure.
+- *
+- * We need to make sure that this is 16384-byte aligned due to the
+- * way process stacks are handled. This is done by having a special
+- * "init_task" linker map entry..
+- */
+-union thread_union init_thread_union
+- __attribute__((__section__(".data.init_task"))) =
+- { INIT_THREAD_INFO(init_task) };
+-
+-/*
+- * Initial task structure.
+- *
+- * All other task structs will be allocated on slabs in fork.c
+- */
+-struct task_struct init_task = INIT_TASK(init_task);
+-
+-EXPORT_SYMBOL(init_task);
+diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
+--- a/arch/ppc64/kernel/ioctl32.c
++++ b/arch/ppc64/kernel/ioctl32.c
+@@ -39,9 +39,7 @@ IOCTL_TABLE_START
+ #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/kprobes.c b/arch/ppc64/kernel/kprobes.c
+--- a/arch/ppc64/kernel/kprobes.c
++++ b/arch/ppc64/kernel/kprobes.c
+@@ -395,7 +395,6 @@ int __kprobes kprobe_exceptions_notify(s
+ if (post_kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+- case DIE_GPF:
+ case DIE_PAGE_FAULT:
+ if (kprobe_running() &&
+ kprobe_fault_handler(args->regs, args->trapnr))
+diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/lmb.c
++++ /dev/null
+@@ -1,299 +0,0 @@
+-/*
+- * Procedures for interfacing to Open Firmware.
+- *
+- * Peter Bergner, IBM Corp. June 2001.
+- * Copyright (C) 2001 Peter Bergner.
+- *
+- * 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/init.h>
+-#include <linux/bitops.h>
+-#include <asm/types.h>
+-#include <asm/page.h>
+-#include <asm/prom.h>
+-#include <asm/lmb.h>
+-#include <asm/abs_addr.h>
+-
+-struct lmb lmb;
+-
+-#undef DEBUG
+-
+-void lmb_dump_all(void)
+-{
+-#ifdef DEBUG
+- unsigned long i;
+-
+- udbg_printf("lmb_dump_all:\n");
+- udbg_printf(" memory.cnt = 0x%lx\n",
+- lmb.memory.cnt);
+- udbg_printf(" memory.size = 0x%lx\n",
+- lmb.memory.size);
+- for (i=0; i < lmb.memory.cnt ;i++) {
+- udbg_printf(" memory.region[0x%x].base = 0x%lx\n",
+- i, lmb.memory.region[i].base);
+- udbg_printf(" .size = 0x%lx\n",
+- lmb.memory.region[i].size);
+- }
+-
+- udbg_printf("\n reserved.cnt = 0x%lx\n",
+- lmb.reserved.cnt);
+- udbg_printf(" reserved.size = 0x%lx\n",
+- lmb.reserved.size);
+- for (i=0; i < lmb.reserved.cnt ;i++) {
+- udbg_printf(" reserved.region[0x%x].base = 0x%lx\n",
+- i, lmb.reserved.region[i].base);
+- udbg_printf(" .size = 0x%lx\n",
+- lmb.reserved.region[i].size);
+- }
+-#endif /* DEBUG */
+-}
+-
+-static unsigned long __init
+-lmb_addrs_overlap(unsigned long base1, unsigned long size1,
+- unsigned long base2, unsigned long size2)
+-{
+- return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
+-}
+-
+-static long __init
+-lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
+- unsigned long base2, unsigned long size2)
+-{
+- if (base2 == base1 + size1)
+- return 1;
+- else if (base1 == base2 + size2)
+- return -1;
+-
+- return 0;
+-}
+-
+-static long __init
+-lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
+-{
+- unsigned long base1 = rgn->region[r1].base;
+- unsigned long size1 = rgn->region[r1].size;
+- unsigned long base2 = rgn->region[r2].base;
+- unsigned long size2 = rgn->region[r2].size;
+-
+- return lmb_addrs_adjacent(base1, size1, base2, size2);
+-}
+-
+-/* Assumption: base addr of region 1 < base addr of region 2 */
+-static void __init
+-lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
+-{
+- unsigned long i;
+-
+- rgn->region[r1].size += rgn->region[r2].size;
+- for (i=r2; i < rgn->cnt-1; i++) {
+- rgn->region[i].base = rgn->region[i+1].base;
+- rgn->region[i].size = rgn->region[i+1].size;
+- }
+- rgn->cnt--;
+-}
+-
+-/* This routine called with relocation disabled. */
+-void __init
+-lmb_init(void)
+-{
+- /* Create a dummy zero size LMB which will get coalesced away later.
+- * This simplifies the lmb_add() code below...
+- */
+- lmb.memory.region[0].base = 0;
+- lmb.memory.region[0].size = 0;
+- lmb.memory.cnt = 1;
+-
+- /* Ditto. */
+- lmb.reserved.region[0].base = 0;
+- lmb.reserved.region[0].size = 0;
+- lmb.reserved.cnt = 1;
+-}
+-
+-/* This routine called with relocation disabled. */
+-void __init
+-lmb_analyze(void)
+-{
+- int i;
+-
+- lmb.memory.size = 0;
+-
+- for (i = 0; i < lmb.memory.cnt; i++)
+- lmb.memory.size += lmb.memory.region[i].size;
+-}
+-
+-/* This routine called with relocation disabled. */
+-static long __init
+-lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
+-{
+- unsigned long i, coalesced = 0;
+- long adjacent;
+-
+- /* First try and coalesce this LMB with another. */
+- for (i=0; i < rgn->cnt; i++) {
+- unsigned long rgnbase = rgn->region[i].base;
+- unsigned long rgnsize = rgn->region[i].size;
+-
+- adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
+- if ( adjacent > 0 ) {
+- rgn->region[i].base -= size;
+- rgn->region[i].size += size;
+- coalesced++;
+- break;
+- }
+- else if ( adjacent < 0 ) {
+- rgn->region[i].size += size;
+- coalesced++;
+- break;
+- }
+- }
+-
+- if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) {
+- lmb_coalesce_regions(rgn, i, i+1);
+- coalesced++;
+- }
+-
+- if ( coalesced ) {
+- return coalesced;
+- } else if ( rgn->cnt >= MAX_LMB_REGIONS ) {
+- return -1;
+- }
+-
+- /* Couldn't coalesce the LMB, so add it to the sorted table. */
+- for (i=rgn->cnt-1; i >= 0; i--) {
+- if (base < rgn->region[i].base) {
+- rgn->region[i+1].base = rgn->region[i].base;
+- rgn->region[i+1].size = rgn->region[i].size;
+- } else {
+- rgn->region[i+1].base = base;
+- rgn->region[i+1].size = size;
+- break;
+- }
+- }
+- rgn->cnt++;
+-
+- return 0;
+-}
+-
+-/* This routine called with relocation disabled. */
+-long __init
+-lmb_add(unsigned long base, unsigned long size)
+-{
+- struct lmb_region *_rgn = &(lmb.memory);
+-
+- /* On pSeries LPAR systems, the first LMB is our RMO region. */
+- if ( base == 0 )
+- lmb.rmo_size = size;
+-
+- return lmb_add_region(_rgn, base, size);
+-
+-}
+-
+-long __init
+-lmb_reserve(unsigned long base, unsigned long size)
+-{
+- struct lmb_region *_rgn = &(lmb.reserved);
+-
+- return lmb_add_region(_rgn, base, size);
+-}
+-
+-long __init
+-lmb_overlaps_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
+-{
+- unsigned long i;
+-
+- for (i=0; i < rgn->cnt; i++) {
+- unsigned long rgnbase = rgn->region[i].base;
+- unsigned long rgnsize = rgn->region[i].size;
+- if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) {
+- break;
+- }
+- }
+-
+- return (i < rgn->cnt) ? i : -1;
+-}
+-
+-unsigned long __init
+-lmb_alloc(unsigned long size, unsigned long align)
+-{
+- return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
+-}
+-
+-unsigned long __init
+-lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
+-{
+- long i, j;
+- unsigned long base = 0;
+-
+- for (i=lmb.memory.cnt-1; i >= 0; i--) {
+- unsigned long lmbbase = lmb.memory.region[i].base;
+- unsigned long lmbsize = lmb.memory.region[i].size;
+-
+- if ( max_addr == LMB_ALLOC_ANYWHERE )
+- base = _ALIGN_DOWN(lmbbase+lmbsize-size, align);
+- else if ( lmbbase < max_addr )
+- base = _ALIGN_DOWN(min(lmbbase+lmbsize,max_addr)-size, align);
+- else
+- continue;
+-
+- while ( (lmbbase <= base) &&
+- ((j = lmb_overlaps_region(&lmb.reserved,base,size)) >= 0) ) {
+- base = _ALIGN_DOWN(lmb.reserved.region[j].base-size, align);
+- }
+-
+- if ( (base != 0) && (lmbbase <= base) )
+- break;
+- }
+-
+- if ( i < 0 )
+- return 0;
+-
+- lmb_add_region(&lmb.reserved, base, size);
+-
+- return base;
+-}
+-
+-/* You must call lmb_analyze() before this. */
+-unsigned long __init
+-lmb_phys_mem_size(void)
+-{
+- return lmb.memory.size;
+-}
+-
+-unsigned long __init
+-lmb_end_of_DRAM(void)
+-{
+- int idx = lmb.memory.cnt - 1;
+-
+- return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
+-}
+-
+-/*
+- * Truncate the lmb list to memory_limit if it's set
+- * You must call lmb_analyze() after this.
+- */
+-void __init lmb_enforce_memory_limit(void)
+-{
+- extern unsigned long memory_limit;
+- unsigned long i, limit;
+-
+- if (! memory_limit)
+- return;
+-
+- limit = memory_limit;
+- for (i = 0; i < lmb.memory.cnt; i++) {
+- if (limit > lmb.memory.region[i].size) {
+- limit -= lmb.memory.region[i].size;
+- continue;
+- }
+-
+- lmb.memory.region[i].size = limit;
+- lmb.memory.cnt = i + 1;
+- break;
+- }
+-}
+diff --git a/arch/ppc64/kernel/lparmap.c b/arch/ppc64/kernel/lparmap.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/lparmap.c
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * Copyright (C) 2005 Stephen Rothwell IBM Corp.
+- *
+- * 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 <asm/mmu.h>
+-#include <asm/page.h>
+-#include <asm/iSeries/LparMap.h>
+-
+-const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
+- .xNumberEsids = HvEsidsToMap,
+- .xNumberRanges = HvRangesToMap,
+- .xSegmentTableOffs = STAB0_PAGE,
+-
+- .xEsids = {
+- { .xKernelEsid = GET_ESID(KERNELBASE),
+- .xKernelVsid = KERNEL_VSID(KERNELBASE), },
+- { .xKernelEsid = GET_ESID(VMALLOCBASE),
+- .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
+- },
+-
+- .xRanges = {
+- { .xPages = HvPagesToMap,
+- .xOffset = 0,
+- .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT),
+- },
+- },
+-};
+diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/maple_pci.c
++++ /dev/null
+@@ -1,521 +0,0 @@
+-/*
+- * Copyright (C) 2004 Benjamin Herrenschmuidt (benh at kernel.crashing.org),
+- * IBM Corp.
+- *
+- * 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.
+- */
+-
+-#define DEBUG
+-
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-#include <linux/bootmem.h>
+-
+-#include <asm/sections.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/machdep.h>
+-#include <asm/iommu.h>
+-
+-#include "pci.h"
+-
+-#ifdef DEBUG
+-#define DBG(x...) printk(x)
+-#else
+-#define DBG(x...)
+-#endif
+-
+-static struct pci_controller *u3_agp, *u3_ht;
+-
+-static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
+-{
+- for (; node != 0;node = node->sibling) {
+- int * bus_range;
+- unsigned int *class_code;
+- int len;
+-
+- /* For PCI<->PCI bridges or CardBus bridges, we go down */
+- class_code = (unsigned int *) get_property(node, "class-code", NULL);
+- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+- continue;
+- bus_range = (int *) get_property(node, "bus-range", &len);
+- if (bus_range != NULL && len > 2 * sizeof(int)) {
+- if (bus_range[1] > higher)
+- higher = bus_range[1];
+- }
+- higher = fixup_one_level_bus_range(node->child, higher);
+- }
+- return higher;
+-}
+-
+-/* This routine fixes the "bus-range" property of all bridges in the
+- * system since they tend to have their "last" member wrong on macs
+- *
+- * Note that the bus numbers manipulated here are OF bus numbers, they
+- * are not Linux bus numbers.
+- */
+-static void __init fixup_bus_range(struct device_node *bridge)
+-{
+- int * bus_range;
+- int len;
+-
+- /* Lookup the "bus-range" property for the hose */
+- bus_range = (int *) get_property(bridge, "bus-range", &len);
+- if (bus_range == NULL || len < 2 * sizeof(int)) {
+- printk(KERN_WARNING "Can't get bus-range for %s\n",
+- bridge->full_name);
+- return;
+- }
+- bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
+-}
+-
+-
+-#define U3_AGP_CFA0(devfn, off) \
+- ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
+- | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
+- | (((unsigned long)(off)) & 0xFCUL))
+-
+-#define U3_AGP_CFA1(bus, devfn, off) \
+- ((((unsigned long)(bus)) << 16) \
+- |(((unsigned long)(devfn)) << 8) \
+- |(((unsigned long)(off)) & 0xFCUL) \
+- |1UL)
+-
+-static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
+- u8 bus, u8 dev_fn, u8 offset)
+-{
+- unsigned int caddr;
+-
+- if (bus == hose->first_busno) {
+- if (dev_fn < (11 << 3))
+- return 0;
+- caddr = U3_AGP_CFA0(dev_fn, offset);
+- } else
+- caddr = U3_AGP_CFA1(bus, dev_fn, offset);
+-
+- /* Uninorth will return garbage if we don't read back the value ! */
+- do {
+- out_le32(hose->cfg_addr, caddr);
+- } while (in_le32(hose->cfg_addr) != caddr);
+-
+- offset &= 0x07;
+- return ((unsigned long)hose->cfg_data) + offset;
+-}
+-
+-static int u3_agp_read_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 *val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- *val = in_8((u8 *)addr);
+- break;
+- case 2:
+- *val = in_le16((u16 *)addr);
+- break;
+- default:
+- *val = in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- out_8((u8 *)addr, val);
+- (void) in_8((u8 *)addr);
+- break;
+- case 2:
+- out_le16((u16 *)addr, val);
+- (void) in_le16((u16 *)addr);
+- break;
+- default:
+- out_le32((u32 *)addr, val);
+- (void) in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops u3_agp_pci_ops =
+-{
+- u3_agp_read_config,
+- u3_agp_write_config
+-};
+-
+-
+-#define U3_HT_CFA0(devfn, off) \
+- ((((unsigned long)devfn) << 8) | offset)
+-#define U3_HT_CFA1(bus, devfn, off) \
+- (U3_HT_CFA0(devfn, off) \
+- + (((unsigned long)bus) << 16) \
+- + 0x01000000UL)
+-
+-static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
+- u8 bus, u8 devfn, u8 offset)
+-{
+- if (bus == hose->first_busno) {
+- if (PCI_SLOT(devfn) == 0)
+- return 0;
+- return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
+- } else
+- return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset);
+-}
+-
+-static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 *val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- *val = in_8((u8 *)addr);
+- break;
+- case 2:
+- *val = in_le16((u16 *)addr);
+- break;
+- default:
+- *val = in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- out_8((u8 *)addr, val);
+- (void) in_8((u8 *)addr);
+- break;
+- case 2:
+- out_le16((u16 *)addr, val);
+- (void) in_le16((u16 *)addr);
+- break;
+- default:
+- out_le32((u32 *)addr, val);
+- (void) in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops u3_ht_pci_ops =
+-{
+- u3_ht_read_config,
+- u3_ht_write_config
+-};
+-
+-static void __init setup_u3_agp(struct pci_controller* hose)
+-{
+- /* On G5, we move AGP up to high bus number so we don't need
+- * to reassign bus numbers for HT. If we ever have P2P bridges
+- * on AGP, we'll have to move pci_assign_all_busses to the
+- * pci_controller structure so we enable it for AGP and not for
+- * HT childs.
+- * We hard code the address because of the different size of
+- * the reg address cell, we shall fix that by killing struct
+- * reg_property and using some accessor functions instead
+- */
+- hose->first_busno = 0xf0;
+- hose->last_busno = 0xff;
+- hose->ops = &u3_agp_pci_ops;
+- hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+- hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+-
+- u3_agp = hose;
+-}
+-
+-static void __init setup_u3_ht(struct pci_controller* hose)
+-{
+- hose->ops = &u3_ht_pci_ops;
+-
+- /* We hard code the address because of the different size of
+- * the reg address cell, we shall fix that by killing struct
+- * reg_property and using some accessor functions instead
+- */
+- hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
+-
+- hose->first_busno = 0;
+- hose->last_busno = 0xef;
+-
+- u3_ht = hose;
+-}
+-
+-static int __init add_bridge(struct device_node *dev)
+-{
+- int len;
+- struct pci_controller *hose;
+- char* disp_name;
+- int *bus_range;
+- int primary = 1;
+- struct property *of_prop;
+-
+- DBG("Adding PCI host bridge %s\n", dev->full_name);
+-
+- bus_range = (int *) get_property(dev, "bus-range", &len);
+- if (bus_range == NULL || len < 2 * sizeof(int)) {
+- printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+- dev->full_name);
+- }
+-
+- hose = alloc_bootmem(sizeof(struct pci_controller));
+- if (hose == NULL)
+- return -ENOMEM;
+- pci_setup_pci_controller(hose);
+-
+- hose->arch_data = dev;
+- hose->first_busno = bus_range ? bus_range[0] : 0;
+- hose->last_busno = bus_range ? bus_range[1] : 0xff;
+-
+- of_prop = alloc_bootmem(sizeof(struct property) +
+- sizeof(hose->global_number));
+- if (of_prop) {
+- memset(of_prop, 0, sizeof(struct property));
+- of_prop->name = "linux,pci-domain";
+- of_prop->length = sizeof(hose->global_number);
+- of_prop->value = (unsigned char *)&of_prop[1];
+- memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number));
+- prom_add_property(dev, of_prop);
+- }
+-
+- disp_name = NULL;
+- if (device_is_compatible(dev, "u3-agp")) {
+- setup_u3_agp(hose);
+- disp_name = "U3-AGP";
+- primary = 0;
+- } else if (device_is_compatible(dev, "u3-ht")) {
+- setup_u3_ht(hose);
+- disp_name = "U3-HT";
+- primary = 1;
+- }
+- printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+- disp_name, hose->first_busno, hose->last_busno);
+-
+- /* Interpret the "ranges" property */
+- /* This also maps the I/O region and sets isa_io/mem_base */
+- pci_process_bridge_OF_ranges(hose, dev);
+- pci_setup_phb_io(hose, primary);
+-
+- /* Fixup "bus-range" OF property */
+- fixup_bus_range(dev);
+-
+- return 0;
+-}
+-
+-
+-void __init maple_pcibios_fixup(void)
+-{
+- struct pci_dev *dev = NULL;
+-
+- DBG(" -> maple_pcibios_fixup\n");
+-
+- for_each_pci_dev(dev)
+- pci_read_irq_line(dev);
+-
+- /* Do the mapping of the IO space */
+- phbs_remap_io();
+-
+- DBG(" <- maple_pcibios_fixup\n");
+-}
+-
+-static void __init maple_fixup_phb_resources(void)
+-{
+- struct pci_controller *hose, *tmp;
+-
+- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+- unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+- hose->io_resource.start += offset;
+- hose->io_resource.end += offset;
+- printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
+- hose->global_number,
+- hose->io_resource.start, hose->io_resource.end);
+- }
+-}
+-
+-void __init maple_pci_init(void)
+-{
+- struct device_node *np, *root;
+- struct device_node *ht = NULL;
+-
+- /* Probe root PCI hosts, that is on U3 the AGP host and the
+- * HyperTransport host. That one is actually "kept" around
+- * and actually added last as it's resource management relies
+- * on the AGP resources to have been setup first
+- */
+- root = of_find_node_by_path("/");
+- if (root == NULL) {
+- printk(KERN_CRIT "maple_find_bridges: can't find root of device tree\n");
+- return;
+- }
+- for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
+- if (np->name == NULL)
+- continue;
+- if (strcmp(np->name, "pci") == 0) {
+- if (add_bridge(np) == 0)
+- of_node_get(np);
+- }
+- if (strcmp(np->name, "ht") == 0) {
+- of_node_get(np);
+- ht = np;
+- }
+- }
+- of_node_put(root);
+-
+- /* Now setup the HyperTransport host if we found any
+- */
+- if (ht && add_bridge(ht) != 0)
+- of_node_put(ht);
+-
+- /* Fixup the IO resources on our host bridges as the common code
+- * does it only for childs of the host bridges
+- */
+- maple_fixup_phb_resources();
+-
+- /* Setup the linkage between OF nodes and PHBs */
+- pci_devs_phb_init();
+-
+- /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
+- * assume there is no P2P bridge on the AGP bus, which should be a
+- * safe assumptions hopefully.
+- */
+- if (u3_agp) {
+- struct device_node *np = u3_agp->arch_data;
+- PCI_DN(np)->busno = 0xf0;
+- for (np = np->child; np; np = np->sibling)
+- PCI_DN(np)->busno = 0xf0;
+- }
+-
+- /* Tell pci.c to use the common resource allocation mecanism */
+- pci_probe_only = 0;
+-
+- /* Allow all IO */
+- io_page_mask = -1;
+-}
+-
+-int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
+-{
+- struct device_node *np;
+- int irq = channel ? 15 : 14;
+-
+- if (pdev->vendor != PCI_VENDOR_ID_AMD ||
+- pdev->device != PCI_DEVICE_ID_AMD_8111_IDE)
+- return irq;
+-
+- np = pci_device_to_OF_node(pdev);
+- if (np == NULL)
+- return irq;
+- if (np->n_intrs < 2)
+- return irq;
+- return np->intrs[channel & 0x1].line;
+-}
+-
+-/* XXX: To remove once all firmwares are ok */
+-static void fixup_maple_ide(struct pci_dev* dev)
+-{
+-#if 0 /* Enable this to enable IDE port 0 */
+- {
+- u8 v;
+-
+- pci_read_config_byte(dev, 0x40, &v);
+- v |= 2;
+- pci_write_config_byte(dev, 0x40, v);
+- }
+-#endif
+-#if 0 /* fix bus master base */
+- pci_write_config_dword(dev, 0x20, 0xcc01);
+- printk("old ide resource: %lx -> %lx \n",
+- dev->resource[4].start, dev->resource[4].end);
+- dev->resource[4].start = 0xcc00;
+- dev->resource[4].end = 0xcc10;
+-#endif
+-#if 1 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
+- {
+- struct pci_dev *apicdev;
+- u32 v;
+-
+- apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
+- if (apicdev == NULL)
+- printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
+- else {
+- pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
+- pci_read_config_dword(apicdev, 0xf4, &v);
+- v &= ~0x00000022;
+- pci_write_config_dword(apicdev, 0xf4, v);
+- pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
+- pci_read_config_dword(apicdev, 0xf4, &v);
+- v &= ~0x00000022;
+- pci_write_config_dword(apicdev, 0xf4, v);
+- pci_dev_put(apicdev);
+- }
+- }
+-#endif
+-}
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
+- fixup_maple_ide);
+diff --git a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/maple_setup.c
++++ /dev/null
+@@ -1,300 +0,0 @@
+-/*
+- * arch/ppc64/kernel/maple_setup.c
+- *
+- * (c) Copyright 2004 Benjamin Herrenschmidt (benh at kernel.crashing.org),
+- * IBM Corp.
+- *
+- * 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.
+- *
+- */
+-
+-#define DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/init.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/user.h>
+-#include <linux/a.out.h>
+-#include <linux/tty.h>
+-#include <linux/string.h>
+-#include <linux/delay.h>
+-#include <linux/ioport.h>
+-#include <linux/major.h>
+-#include <linux/initrd.h>
+-#include <linux/vt_kern.h>
+-#include <linux/console.h>
+-#include <linux/ide.h>
+-#include <linux/pci.h>
+-#include <linux/adb.h>
+-#include <linux/cuda.h>
+-#include <linux/pmu.h>
+-#include <linux/irq.h>
+-#include <linux/seq_file.h>
+-#include <linux/root_dev.h>
+-#include <linux/serial.h>
+-#include <linux/smp.h>
+-
+-#include <asm/processor.h>
+-#include <asm/sections.h>
+-#include <asm/prom.h>
+-#include <asm/system.h>
+-#include <asm/pgtable.h>
+-#include <asm/bitops.h>
+-#include <asm/io.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/iommu.h>
+-#include <asm/machdep.h>
+-#include <asm/dma.h>
+-#include <asm/cputable.h>
+-#include <asm/time.h>
+-#include <asm/of_device.h>
+-#include <asm/lmb.h>
+-
+-#include "mpic.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-extern int maple_set_rtc_time(struct rtc_time *tm);
+-extern void maple_get_rtc_time(struct rtc_time *tm);
+-extern void maple_get_boot_time(struct rtc_time *tm);
+-extern void maple_calibrate_decr(void);
+-extern void maple_pci_init(void);
+-extern void maple_pcibios_fixup(void);
+-extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
+-extern void generic_find_legacy_serial_ports(u64 *physport,
+- unsigned int *default_speed);
+-
+-static void maple_restart(char *cmd)
+-{
+- unsigned int maple_nvram_base;
+- unsigned int maple_nvram_offset;
+- unsigned int maple_nvram_command;
+- struct device_node *rtcs;
+-
+- /* find NVRAM device */
+- rtcs = find_compatible_devices("nvram", "AMD8111");
+- if (rtcs && rtcs->addrs) {
+- maple_nvram_base = rtcs->addrs[0].address;
+- } else {
+- printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
+- printk(KERN_EMERG "Maple: Manual Restart Required\n");
+- return;
+- }
+-
+- /* find service processor device */
+- rtcs = find_devices("service-processor");
+- if (!rtcs) {
+- printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
+- printk(KERN_EMERG "Maple: Manual Restart Required\n");
+- return;
+- }
+- maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+- "restart-addr", NULL);
+- maple_nvram_command = *(unsigned int*) get_property(rtcs,
+- "restart-value", NULL);
+-
+- /* send command */
+- outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
+- for (;;) ;
+-}
+-
+-static void maple_power_off(void)
+-{
+- unsigned int maple_nvram_base;
+- unsigned int maple_nvram_offset;
+- unsigned int maple_nvram_command;
+- struct device_node *rtcs;
+-
+- /* find NVRAM device */
+- rtcs = find_compatible_devices("nvram", "AMD8111");
+- if (rtcs && rtcs->addrs) {
+- maple_nvram_base = rtcs->addrs[0].address;
+- } else {
+- printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
+- printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
+- return;
+- }
+-
+- /* find service processor device */
+- rtcs = find_devices("service-processor");
+- if (!rtcs) {
+- printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
+- printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
+- return;
+- }
+- maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+- "power-off-addr", NULL);
+- maple_nvram_command = *(unsigned int*) get_property(rtcs,
+- "power-off-value", NULL);
+-
+- /* send command */
+- outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
+- for (;;) ;
+-}
+-
+-static void maple_halt(void)
+-{
+- maple_power_off();
+-}
+-
+-#ifdef CONFIG_SMP
+-struct smp_ops_t maple_smp_ops = {
+- .probe = smp_mpic_probe,
+- .message_pass = smp_mpic_message_pass,
+- .kick_cpu = smp_generic_kick_cpu,
+- .setup_cpu = smp_mpic_setup_cpu,
+- .give_timebase = smp_generic_give_timebase,
+- .take_timebase = smp_generic_take_timebase,
+-};
+-#endif /* CONFIG_SMP */
+-
+-void __init maple_setup_arch(void)
+-{
+- /* init to some ~sane value until calibrate_delay() runs */
+- loops_per_jiffy = 50000000;
+-
+- /* Setup SMP callback */
+-#ifdef CONFIG_SMP
+- smp_ops = &maple_smp_ops;
+-#endif
+- /* Lookup PCI hosts */
+- maple_pci_init();
+-
+-#ifdef CONFIG_DUMMY_CONSOLE
+- conswitchp = &dummy_con;
+-#endif
+-
+- printk(KERN_INFO "Using native/NAP idle loop\n");
+-}
+-
+-/*
+- * Early initialization.
+- */
+-static void __init maple_init_early(void)
+-{
+- unsigned int default_speed;
+- u64 physport;
+-
+- DBG(" -> maple_init_early\n");
+-
+- /* Initialize hash table, from now on, we can take hash faults
+- * and call ioremap
+- */
+- hpte_init_native();
+-
+- /* Find the serial port */
+- generic_find_legacy_serial_ports(&physport, &default_speed);
+-
+- DBG("phys port addr: %lx\n", (long)physport);
+-
+- if (physport) {
+- void *comport;
+- /* Map the uart for udbg. */
+- comport = (void *)ioremap(physport, 16);
+- udbg_init_uart(comport, default_speed);
+-
+- DBG("Hello World !\n");
+- }
+-
+- /* Setup interrupt mapping options */
+- ppc64_interrupt_controller = IC_OPEN_PIC;
+-
+- iommu_init_early_u3();
+-
+- DBG(" <- maple_init_early\n");
+-}
+-
+-
+-static __init void maple_init_IRQ(void)
+-{
+- struct device_node *root;
+- unsigned int *opprop;
+- unsigned long opic_addr;
+- struct mpic *mpic;
+- unsigned char senses[128];
+- int n;
+-
+- DBG(" -> maple_init_IRQ\n");
+-
+- /* XXX: Non standard, replace that with a proper openpic/mpic node
+- * in the device-tree. Find the Open PIC if present */
+- root = of_find_node_by_path("/");
+- opprop = (unsigned int *) get_property(root,
+- "platform-open-pic", NULL);
+- if (opprop == 0)
+- panic("OpenPIC not found !\n");
+-
+- n = prom_n_addr_cells(root);
+- for (opic_addr = 0; n > 0; --n)
+- opic_addr = (opic_addr << 32) + *opprop++;
+- of_node_put(root);
+-
+- /* Obtain sense values from device-tree */
+- prom_get_irq_senses(senses, 0, 128);
+-
+- mpic = mpic_alloc(opic_addr,
+- MPIC_PRIMARY | MPIC_BIG_ENDIAN |
+- MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
+- 0, 0, 128, 128, senses, 128, "U3-MPIC");
+- BUG_ON(mpic == NULL);
+- mpic_init(mpic);
+-
+- DBG(" <- maple_init_IRQ\n");
+-}
+-
+-static void __init maple_progress(char *s, unsigned short hex)
+-{
+- printk("*** %04x : %s\n", hex, s ? s : "");
+-}
+-
+-
+-/*
+- * Called very early, MMU is off, device-tree isn't unflattened
+- */
+-static int __init maple_probe(int platform)
+-{
+- if (platform != PLATFORM_MAPLE)
+- return 0;
+- /*
+- * On U3, the DART (iommu) must be allocated now since it
+- * has an impact on htab_initialize (due to the large page it
+- * occupies having to be broken up so the DART itself is not
+- * part of the cacheable linar mapping
+- */
+- alloc_u3_dart_table();
+-
+- return 1;
+-}
+-
+-struct machdep_calls __initdata maple_md = {
+- .probe = maple_probe,
+- .setup_arch = maple_setup_arch,
+- .init_early = maple_init_early,
+- .init_IRQ = maple_init_IRQ,
+- .get_irq = mpic_get_irq,
+- .pcibios_fixup = maple_pcibios_fixup,
+- .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
+- .restart = maple_restart,
+- .power_off = maple_power_off,
+- .halt = maple_halt,
+- .get_boot_time = maple_get_boot_time,
+- .set_rtc_time = maple_set_rtc_time,
+- .get_rtc_time = maple_get_rtc_time,
+- .calibrate_decr = generic_calibrate_decr,
+- .progress = maple_progress,
+- .idle_loop = native_idle,
+-};
+diff --git a/arch/ppc64/kernel/maple_time.c b/arch/ppc64/kernel/maple_time.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/maple_time.c
++++ /dev/null
+@@ -1,175 +0,0 @@
+-/*
+- * arch/ppc64/kernel/maple_time.c
+- *
+- * (c) Copyright 2004 Benjamin Herrenschmidt (benh at kernel.crashing.org),
+- * IBM Corp.
+- *
+- * 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.
+- *
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/time.h>
+-#include <linux/adb.h>
+-#include <linux/pmu.h>
+-#include <linux/interrupt.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/bcd.h>
+-
+-#include <asm/sections.h>
+-#include <asm/prom.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/machdep.h>
+-#include <asm/time.h>
+-
+-#ifdef DEBUG
+-#define DBG(x...) printk(x)
+-#else
+-#define DBG(x...)
+-#endif
+-
+-extern void GregorianDay(struct rtc_time * tm);
+-
+-static int maple_rtc_addr;
+-
+-static int maple_clock_read(int addr)
+-{
+- outb_p(addr, maple_rtc_addr);
+- return inb_p(maple_rtc_addr+1);
+-}
+-
+-static void maple_clock_write(unsigned long val, int addr)
+-{
+- outb_p(addr, maple_rtc_addr);
+- outb_p(val, maple_rtc_addr+1);
+-}
+-
+-void maple_get_rtc_time(struct rtc_time *tm)
+-{
+- int uip, i;
+-
+- /* The Linux interpretation of the CMOS clock register contents:
+- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+- * RTC registers show the second which has precisely just started.
+- * Let's hope other operating systems interpret the RTC the same way.
+- */
+-
+- /* Since the UIP flag is set for about 2.2 ms and the clock
+- * is typically written with a precision of 1 jiffy, trying
+- * to obtain a precision better than a few milliseconds is
+- * an illusion. Only consistency is interesting, this also
+- * allows to use the routine for /dev/rtc without a potential
+- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
+- */
+-
+- for (i = 0; i<1000000; i++) {
+- uip = maple_clock_read(RTC_FREQ_SELECT);
+- tm->tm_sec = maple_clock_read(RTC_SECONDS);
+- tm->tm_min = maple_clock_read(RTC_MINUTES);
+- tm->tm_hour = maple_clock_read(RTC_HOURS);
+- tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH);
+- tm->tm_mon = maple_clock_read(RTC_MONTH);
+- tm->tm_year = maple_clock_read(RTC_YEAR);
+- uip |= maple_clock_read(RTC_FREQ_SELECT);
+- if ((uip & RTC_UIP)==0)
+- break;
+- }
+-
+- if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
+- || RTC_ALWAYS_BCD) {
+- BCD_TO_BIN(tm->tm_sec);
+- BCD_TO_BIN(tm->tm_min);
+- BCD_TO_BIN(tm->tm_hour);
+- BCD_TO_BIN(tm->tm_mday);
+- BCD_TO_BIN(tm->tm_mon);
+- BCD_TO_BIN(tm->tm_year);
+- }
+- if ((tm->tm_year + 1900) < 1970)
+- tm->tm_year += 100;
+-
+- GregorianDay(tm);
+-}
+-
+-int maple_set_rtc_time(struct rtc_time *tm)
+-{
+- unsigned char save_control, save_freq_select;
+- int sec, min, hour, mon, mday, year;
+-
+- spin_lock(&rtc_lock);
+-
+- save_control = maple_clock_read(RTC_CONTROL); /* tell the clock it's being set */
+-
+- maple_clock_write((save_control|RTC_SET), RTC_CONTROL);
+-
+- save_freq_select = maple_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+-
+- maple_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+-
+- sec = tm->tm_sec;
+- min = tm->tm_min;
+- hour = tm->tm_hour;
+- mon = tm->tm_mon;
+- mday = tm->tm_mday;
+- year = tm->tm_year;
+-
+- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+- BIN_TO_BCD(sec);
+- BIN_TO_BCD(min);
+- BIN_TO_BCD(hour);
+- BIN_TO_BCD(mon);
+- BIN_TO_BCD(mday);
+- BIN_TO_BCD(year);
+- }
+- maple_clock_write(sec, RTC_SECONDS);
+- maple_clock_write(min, RTC_MINUTES);
+- maple_clock_write(hour, RTC_HOURS);
+- maple_clock_write(mon, RTC_MONTH);
+- maple_clock_write(mday, RTC_DAY_OF_MONTH);
+- maple_clock_write(year, RTC_YEAR);
+-
+- /* The following flags have to be released exactly in this order,
+- * otherwise the DS12887 (popular MC146818A clone with integrated
+- * battery and quartz) will not reset the oscillator and will not
+- * update precisely 500 ms later. You won't find this mentioned in
+- * the Dallas Semiconductor data sheets, but who believes data
+- * sheets anyway ... -- Markus Kuhn
+- */
+- maple_clock_write(save_control, RTC_CONTROL);
+- maple_clock_write(save_freq_select, RTC_FREQ_SELECT);
+-
+- spin_unlock(&rtc_lock);
+-
+- return 0;
+-}
+-
+-void __init maple_get_boot_time(struct rtc_time *tm)
+-{
+- struct device_node *rtcs;
+-
+- rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
+- if (rtcs && rtcs->addrs) {
+- maple_rtc_addr = rtcs->addrs[0].address;
+- printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr);
+- } else {
+- maple_rtc_addr = RTC_PORT(0); /* legacy address */
+- printk(KERN_INFO "Maple: No device node for RTC, assuming "
+- "legacy address (0x%x)\n", maple_rtc_addr);
+- }
+-
+- maple_get_rtc_time(tm);
+-}
+-
+diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/mf.c
++++ /dev/null
+@@ -1,1281 +0,0 @@
+-/*
+- * mf.c
+- * Copyright (C) 2001 Troy D. Armstrong IBM Corporation
+- * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation
+- *
+- * This modules exists as an interface between a Linux secondary partition
+- * running on an iSeries and the primary partition's Virtual Service
+- * Processor (VSP) object. The VSP has final authority over powering on/off
+- * all partitions in the iSeries. It also provides miscellaneous low-level
+- * machine facility type operations.
+- *
+- *
+- * 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/types.h>
+-#include <linux/errno.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/completion.h>
+-#include <linux/delay.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/bcd.h>
+-
+-#include <asm/time.h>
+-#include <asm/uaccess.h>
+-#include <asm/paca.h>
+-#include <asm/iSeries/vio.h>
+-#include <asm/iSeries/mf.h>
+-#include <asm/iSeries/HvLpConfig.h>
+-#include <asm/iSeries/ItLpQueue.h>
+-
+-/*
+- * This is the structure layout for the Machine Facilites LPAR event
+- * flows.
+- */
+-struct vsp_cmd_data {
+- u64 token;
+- u16 cmd;
+- HvLpIndex lp_index;
+- u8 result_code;
+- u32 reserved;
+- union {
+- u64 state; /* GetStateOut */
+- u64 ipl_type; /* GetIplTypeOut, Function02SelectIplTypeIn */
+- u64 ipl_mode; /* GetIplModeOut, Function02SelectIplModeIn */
+- u64 page[4]; /* GetSrcHistoryIn */
+- u64 flag; /* GetAutoIplWhenPrimaryIplsOut,
+- SetAutoIplWhenPrimaryIplsIn,
+- WhiteButtonPowerOffIn,
+- Function08FastPowerOffIn,
+- IsSpcnRackPowerIncompleteOut */
+- struct {
+- u64 token;
+- u64 address_type;
+- u64 side;
+- u32 length;
+- u32 offset;
+- } kern; /* SetKernelImageIn, GetKernelImageIn,
+- SetKernelCmdLineIn, GetKernelCmdLineIn */
+- u32 length_out; /* GetKernelImageOut, GetKernelCmdLineOut */
+- u8 reserved[80];
+- } sub_data;
+-};
+-
+-struct vsp_rsp_data {
+- struct completion com;
+- struct vsp_cmd_data *response;
+-};
+-
+-struct alloc_data {
+- u16 size;
+- u16 type;
+- u32 count;
+- u16 reserved1;
+- u8 reserved2;
+- HvLpIndex target_lp;
+-};
+-
+-struct ce_msg_data;
+-
+-typedef void (*ce_msg_comp_hdlr)(void *token, struct ce_msg_data *vsp_cmd_rsp);
+-
+-struct ce_msg_comp_data {
+- ce_msg_comp_hdlr handler;
+- void *token;
+-};
+-
+-struct ce_msg_data {
+- u8 ce_msg[12];
+- char reserved[4];
+- struct ce_msg_comp_data *completion;
+-};
+-
+-struct io_mf_lp_event {
+- struct HvLpEvent hp_lp_event;
+- u16 subtype_result_code;
+- u16 reserved1;
+- u32 reserved2;
+- union {
+- struct alloc_data alloc;
+- struct ce_msg_data ce_msg;
+- struct vsp_cmd_data vsp_cmd;
+- } data;
+-};
+-
+-#define subtype_data(a, b, c, d) \
+- (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
+-
+-/*
+- * All outgoing event traffic is kept on a FIFO queue. The first
+- * pointer points to the one that is outstanding, and all new
+- * requests get stuck on the end. Also, we keep a certain number of
+- * preallocated pending events so that we can operate very early in
+- * the boot up sequence (before kmalloc is ready).
+- */
+-struct pending_event {
+- struct pending_event *next;
+- struct io_mf_lp_event event;
+- MFCompleteHandler hdlr;
+- char dma_data[72];
+- unsigned dma_data_length;
+- unsigned remote_address;
+-};
+-static spinlock_t pending_event_spinlock;
+-static struct pending_event *pending_event_head;
+-static struct pending_event *pending_event_tail;
+-static struct pending_event *pending_event_avail;
+-static struct pending_event pending_event_prealloc[16];
+-
+-/*
+- * Put a pending event onto the available queue, so it can get reused.
+- * Attention! You must have the pending_event_spinlock before calling!
+- */
+-static void free_pending_event(struct pending_event *ev)
+-{
+- if (ev != NULL) {
+- ev->next = pending_event_avail;
+- pending_event_avail = ev;
+- }
+-}
+-
+-/*
+- * Enqueue the outbound event onto the stack. If the queue was
+- * empty to begin with, we must also issue it via the Hypervisor
+- * interface. There is a section of code below that will touch
+- * the first stack pointer without the protection of the pending_event_spinlock.
+- * This is OK, because we know that nobody else will be modifying
+- * the first pointer when we do this.
+- */
+-static int signal_event(struct pending_event *ev)
+-{
+- int rc = 0;
+- unsigned long flags;
+- int go = 1;
+- struct pending_event *ev1;
+- HvLpEvent_Rc hv_rc;
+-
+- /* enqueue the event */
+- if (ev != NULL) {
+- ev->next = NULL;
+- spin_lock_irqsave(&pending_event_spinlock, flags);
+- if (pending_event_head == NULL)
+- pending_event_head = ev;
+- else {
+- go = 0;
+- pending_event_tail->next = ev;
+- }
+- pending_event_tail = ev;
+- spin_unlock_irqrestore(&pending_event_spinlock, flags);
+- }
+-
+- /* send the event */
+- while (go) {
+- go = 0;
+-
+- /* any DMA data to send beforehand? */
+- if (pending_event_head->dma_data_length > 0)
+- HvCallEvent_dmaToSp(pending_event_head->dma_data,
+- pending_event_head->remote_address,
+- pending_event_head->dma_data_length,
+- HvLpDma_Direction_LocalToRemote);
+-
+- hv_rc = HvCallEvent_signalLpEvent(
+- &pending_event_head->event.hp_lp_event);
+- if (hv_rc != HvLpEvent_Rc_Good) {
+- printk(KERN_ERR "mf.c: HvCallEvent_signalLpEvent() "
+- "failed with %d\n", (int)hv_rc);
+-
+- spin_lock_irqsave(&pending_event_spinlock, flags);
+- ev1 = pending_event_head;
+- pending_event_head = pending_event_head->next;
+- if (pending_event_head != NULL)
+- go = 1;
+- spin_unlock_irqrestore(&pending_event_spinlock, flags);
+-
+- if (ev1 == ev)
+- rc = -EIO;
+- else if (ev1->hdlr != NULL)
+- (*ev1->hdlr)((void *)ev1->event.hp_lp_event.xCorrelationToken, -EIO);
+-
+- spin_lock_irqsave(&pending_event_spinlock, flags);
+- free_pending_event(ev1);
+- spin_unlock_irqrestore(&pending_event_spinlock, flags);
+- }
+- }
+-
+- return rc;
+-}
+-
+-/*
+- * Allocate a new pending_event structure, and initialize it.
+- */
+-static struct pending_event *new_pending_event(void)
+-{
+- struct pending_event *ev = NULL;
+- HvLpIndex primary_lp = HvLpConfig_getPrimaryLpIndex();
+- unsigned long flags;
+- struct HvLpEvent *hev;
+-
+- spin_lock_irqsave(&pending_event_spinlock, flags);
+- if (pending_event_avail != NULL) {
+- ev = pending_event_avail;
+- pending_event_avail = pending_event_avail->next;
+- }
+- spin_unlock_irqrestore(&pending_event_spinlock, flags);
+- if (ev == NULL) {
+- ev = kmalloc(sizeof(struct pending_event), GFP_ATOMIC);
+- if (ev == NULL) {
+- printk(KERN_ERR "mf.c: unable to kmalloc %ld bytes\n",
+- sizeof(struct pending_event));
+- return NULL;
+- }
+- }
+- memset(ev, 0, sizeof(struct pending_event));
+- hev = &ev->event.hp_lp_event;
+- hev->xFlags.xValid = 1;
+- hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck;
+- hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck;
+- hev->xFlags.xFunction = HvLpEvent_Function_Int;
+- hev->xType = HvLpEvent_Type_MachineFac;
+- hev->xSourceLp = HvLpConfig_getLpIndex();
+- hev->xTargetLp = primary_lp;
+- hev->xSizeMinus1 = sizeof(ev->event) - 1;
+- hev->xRc = HvLpEvent_Rc_Good;
+- hev->xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primary_lp,
+- HvLpEvent_Type_MachineFac);
+- hev->xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primary_lp,
+- HvLpEvent_Type_MachineFac);
+-
+- return ev;
+-}
+-
+-static int signal_vsp_instruction(struct vsp_cmd_data *vsp_cmd)
+-{
+- struct pending_event *ev = new_pending_event();
+- int rc;
+- struct vsp_rsp_data response;
+-
+- if (ev == NULL)
+- return -ENOMEM;
+-
+- init_completion(&response.com);
+- response.response = vsp_cmd;
+- ev->event.hp_lp_event.xSubtype = 6;
+- ev->event.hp_lp_event.x.xSubtypeData =
+- subtype_data('M', 'F', 'V', 'I');
+- ev->event.data.vsp_cmd.token = (u64)&response;
+- ev->event.data.vsp_cmd.cmd = vsp_cmd->cmd;
+- ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
+- ev->event.data.vsp_cmd.result_code = 0xFF;
+- ev->event.data.vsp_cmd.reserved = 0;
+- memcpy(&(ev->event.data.vsp_cmd.sub_data),
+- &(vsp_cmd->sub_data), sizeof(vsp_cmd->sub_data));
+- mb();
+-
+- rc = signal_event(ev);
+- if (rc == 0)
+- wait_for_completion(&response.com);
+- return rc;
+-}
+-
+-
+-/*
+- * Send a 12-byte CE message to the primary partition VSP object
+- */
+-static int signal_ce_msg(char *ce_msg, struct ce_msg_comp_data *completion)
+-{
+- struct pending_event *ev = new_pending_event();
+-
+- if (ev == NULL)
+- return -ENOMEM;
+-
+- ev->event.hp_lp_event.xSubtype = 0;
+- ev->event.hp_lp_event.x.xSubtypeData =
+- subtype_data('M', 'F', 'C', 'E');
+- memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
+- ev->event.data.ce_msg.completion = completion;
+- return signal_event(ev);
+-}
+-
+-/*
+- * Send a 12-byte CE message (with no data) to the primary partition VSP object
+- */
+-static int signal_ce_msg_simple(u8 ce_op, struct ce_msg_comp_data *completion)
+-{
+- u8 ce_msg[12];
+-
+- memset(ce_msg, 0, sizeof(ce_msg));
+- ce_msg[3] = ce_op;
+- return signal_ce_msg(ce_msg, completion);
+-}
+-
+-/*
+- * Send a 12-byte CE message and DMA data to the primary partition VSP object
+- */
+-static int dma_and_signal_ce_msg(char *ce_msg,
+- struct ce_msg_comp_data *completion, void *dma_data,
+- unsigned dma_data_length, unsigned remote_address)
+-{
+- struct pending_event *ev = new_pending_event();
+-
+- if (ev == NULL)
+- return -ENOMEM;
+-
+- ev->event.hp_lp_event.xSubtype = 0;
+- ev->event.hp_lp_event.x.xSubtypeData =
+- subtype_data('M', 'F', 'C', 'E');
+- memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
+- ev->event.data.ce_msg.completion = completion;
+- memcpy(ev->dma_data, dma_data, dma_data_length);
+- ev->dma_data_length = dma_data_length;
+- ev->remote_address = remote_address;
+- return signal_event(ev);
+-}
+-
+-/*
+- * Initiate a nice (hopefully) shutdown of Linux. We simply are
+- * going to try and send the init process a SIGINT signal. If
+- * this fails (why?), we'll simply force it off in a not-so-nice
+- * manner.
+- */
+-static int shutdown(void)
+-{
+- int rc = kill_proc(1, SIGINT, 1);
+-
+- if (rc) {
+- printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), "
+- "hard shutdown commencing\n", rc);
+- mf_power_off();
+- } else
+- printk(KERN_INFO "mf.c: init has been successfully notified "
+- "to proceed with shutdown\n");
+- return rc;
+-}
+-
+-/*
+- * The primary partition VSP object is sending us a new
+- * event flow. Handle it...
+- */
+-static void handle_int(struct io_mf_lp_event *event)
+-{
+- struct ce_msg_data *ce_msg_data;
+- struct ce_msg_data *pce_msg_data;
+- unsigned long flags;
+- struct pending_event *pev;
+-
+- /* ack the interrupt */
+- event->hp_lp_event.xRc = HvLpEvent_Rc_Good;
+- HvCallEvent_ackLpEvent(&event->hp_lp_event);
+-
+- /* process interrupt */
+- switch (event->hp_lp_event.xSubtype) {
+- case 0: /* CE message */
+- ce_msg_data = &event->data.ce_msg;
+- switch (ce_msg_data->ce_msg[3]) {
+- case 0x5B: /* power control notification */
+- if ((ce_msg_data->ce_msg[5] & 0x20) != 0) {
+- printk(KERN_INFO "mf.c: Commencing partition shutdown\n");
+- if (shutdown() == 0)
+- signal_ce_msg_simple(0xDB, NULL);
+- }
+- break;
+- case 0xC0: /* get time */
+- spin_lock_irqsave(&pending_event_spinlock, flags);
+- pev = pending_event_head;
+- if (pev != NULL)
+- pending_event_head = pending_event_head->next;
+- spin_unlock_irqrestore(&pending_event_spinlock, flags);
+- if (pev == NULL)
+- break;
+- pce_msg_data = &pev->event.data.ce_msg;
+- if (pce_msg_data->ce_msg[3] != 0x40)
+- break;
+- if (pce_msg_data->completion != NULL) {
+- ce_msg_comp_hdlr handler =
+- pce_msg_data->completion->handler;
+- void *token = pce_msg_data->completion->token;
+-
+- if (handler != NULL)
+- (*handler)(token, ce_msg_data);
+- }
+- spin_lock_irqsave(&pending_event_spinlock, flags);
+- free_pending_event(pev);
+- spin_unlock_irqrestore(&pending_event_spinlock, flags);
+- /* send next waiting event */
+- if (pending_event_head != NULL)
+- signal_event(NULL);
+- break;
+- }
+- break;
+- case 1: /* IT sys shutdown */
+- printk(KERN_INFO "mf.c: Commencing system shutdown\n");
+- shutdown();
+- break;
+- }
+-}
+-
+-/*
+- * The primary partition VSP object is acknowledging the receipt
+- * of a flow we sent to them. If there are other flows queued
+- * up, we must send another one now...
+- */
+-static void handle_ack(struct io_mf_lp_event *event)
+-{
+- unsigned long flags;
+- struct pending_event *two = NULL;
+- unsigned long free_it = 0;
+- struct ce_msg_data *ce_msg_data;
+- struct ce_msg_data *pce_msg_data;
+- struct vsp_rsp_data *rsp;
+-
+- /* handle current event */
+- if (pending_event_head == NULL) {
+- printk(KERN_ERR "mf.c: stack empty for receiving ack\n");
+- return;
+- }
+-
+- switch (event->hp_lp_event.xSubtype) {
+- case 0: /* CE msg */
+- ce_msg_data = &event->data.ce_msg;
+- if (ce_msg_data->ce_msg[3] != 0x40) {
+- free_it = 1;
+- break;
+- }
+- if (ce_msg_data->ce_msg[2] == 0)
+- break;
+- free_it = 1;
+- pce_msg_data = &pending_event_head->event.data.ce_msg;
+- if (pce_msg_data->completion != NULL) {
+- ce_msg_comp_hdlr handler =
+- pce_msg_data->completion->handler;
+- void *token = pce_msg_data->completion->token;
+-
+- if (handler != NULL)
+- (*handler)(token, ce_msg_data);
+- }
+- break;
+- case 4: /* allocate */
+- case 5: /* deallocate */
+- if (pending_event_head->hdlr != NULL)
+- (*pending_event_head->hdlr)((void *)event->hp_lp_event.xCorrelationToken, event->data.alloc.count);
+- free_it = 1;
+- break;
+- case 6:
+- free_it = 1;
+- rsp = (struct vsp_rsp_data *)event->data.vsp_cmd.token;
+- if (rsp == NULL) {
+- printk(KERN_ERR "mf.c: no rsp\n");
+- break;
+- }
+- if (rsp->response != NULL)
+- memcpy(rsp->response, &event->data.vsp_cmd,
+- sizeof(event->data.vsp_cmd));
+- complete(&rsp->com);
+- break;
+- }
+-
+- /* remove from queue */
+- spin_lock_irqsave(&pending_event_spinlock, flags);
+- if ((pending_event_head != NULL) && (free_it == 1)) {
+- struct pending_event *oldHead = pending_event_head;
+-
+- pending_event_head = pending_event_head->next;
+- two = pending_event_head;
+- free_pending_event(oldHead);
+- }
+- spin_unlock_irqrestore(&pending_event_spinlock, flags);
+-
+- /* send next waiting event */
+- if (two != NULL)
+- signal_event(NULL);
+-}
+-
+-/*
+- * This is the generic event handler we are registering with
+- * the Hypervisor. Ensure the flows are for us, and then
+- * parse it enough to know if it is an interrupt or an
+- * acknowledge.
+- */
+-static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs)
+-{
+- if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {
+- switch(event->xFlags.xFunction) {
+- case HvLpEvent_Function_Ack:
+- handle_ack((struct io_mf_lp_event *)event);
+- break;
+- case HvLpEvent_Function_Int:
+- handle_int((struct io_mf_lp_event *)event);
+- break;
+- default:
+- printk(KERN_ERR "mf.c: non ack/int event received\n");
+- break;
+- }
+- } else
+- printk(KERN_ERR "mf.c: alien event received\n");
+-}
+-
+-/*
+- * Global kernel interface to allocate and seed events into the
+- * Hypervisor.
+- */
+-void mf_allocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
+- unsigned size, unsigned count, MFCompleteHandler hdlr,
+- void *user_token)
+-{
+- struct pending_event *ev = new_pending_event();
+- int rc;
+-
+- if (ev == NULL) {
+- rc = -ENOMEM;
+- } else {
+- ev->event.hp_lp_event.xSubtype = 4;
+- ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
+- ev->event.hp_lp_event.x.xSubtypeData =
+- subtype_data('M', 'F', 'M', 'A');
+- ev->event.data.alloc.target_lp = target_lp;
+- ev->event.data.alloc.type = type;
+- ev->event.data.alloc.size = size;
+- ev->event.data.alloc.count = count;
+- ev->hdlr = hdlr;
+- rc = signal_event(ev);
+- }
+- if ((rc != 0) && (hdlr != NULL))
+- (*hdlr)(user_token, rc);
+-}
+-EXPORT_SYMBOL(mf_allocate_lp_events);
+-
+-/*
+- * Global kernel interface to unseed and deallocate events already in
+- * Hypervisor.
+- */
+-void mf_deallocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
+- unsigned count, MFCompleteHandler hdlr, void *user_token)
+-{
+- struct pending_event *ev = new_pending_event();
+- int rc;
+-
+- if (ev == NULL)
+- rc = -ENOMEM;
+- else {
+- ev->event.hp_lp_event.xSubtype = 5;
+- ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
+- ev->event.hp_lp_event.x.xSubtypeData =
+- subtype_data('M', 'F', 'M', 'D');
+- ev->event.data.alloc.target_lp = target_lp;
+- ev->event.data.alloc.type = type;
+- ev->event.data.alloc.count = count;
+- ev->hdlr = hdlr;
+- rc = signal_event(ev);
+- }
+- if ((rc != 0) && (hdlr != NULL))
+- (*hdlr)(user_token, rc);
+-}
+-EXPORT_SYMBOL(mf_deallocate_lp_events);
+-
+-/*
+- * Global kernel interface to tell the VSP object in the primary
+- * partition to power this partition off.
+- */
+-void mf_power_off(void)
+-{
+- printk(KERN_INFO "mf.c: Down it goes...\n");
+- signal_ce_msg_simple(0x4d, NULL);
+- for (;;)
+- ;
+-}
+-
+-/*
+- * Global kernel interface to tell the VSP object in the primary
+- * partition to reboot this partition.
+- */
+-void mf_reboot(void)
+-{
+- printk(KERN_INFO "mf.c: Preparing to bounce...\n");
+- signal_ce_msg_simple(0x4e, NULL);
+- for (;;)
+- ;
+-}
+-
+-/*
+- * Display a single word SRC onto the VSP control panel.
+- */
+-void mf_display_src(u32 word)
+-{
+- u8 ce[12];
+-
+- memset(ce, 0, sizeof(ce));
+- ce[3] = 0x4a;
+- ce[7] = 0x01;
+- ce[8] = word >> 24;
+- ce[9] = word >> 16;
+- ce[10] = word >> 8;
+- ce[11] = word;
+- signal_ce_msg(ce, NULL);
+-}
+-
+-/*
+- * Display a single word SRC of the form "PROGXXXX" on the VSP control panel.
+- */
+-void mf_display_progress(u16 value)
+-{
+- u8 ce[12];
+- u8 src[72];
+-
+- memcpy(ce, "\x00\x00\x04\x4A\x00\x00\x00\x48\x00\x00\x00\x00", 12);
+- memcpy(src, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
+- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+- "\x00\x00\x00\x00PROGxxxx ",
+- 72);
+- src[6] = value >> 8;
+- src[7] = value & 255;
+- src[44] = "0123456789ABCDEF"[(value >> 12) & 15];
+- src[45] = "0123456789ABCDEF"[(value >> 8) & 15];
+- src[46] = "0123456789ABCDEF"[(value >> 4) & 15];
+- src[47] = "0123456789ABCDEF"[value & 15];
+- dma_and_signal_ce_msg(ce, NULL, src, sizeof(src), 9 * 64 * 1024);
+-}
+-
+-/*
+- * Clear the VSP control panel. Used to "erase" an SRC that was
+- * previously displayed.
+- */
+-void mf_clear_src(void)
+-{
+- signal_ce_msg_simple(0x4b, NULL);
+-}
+-
+-/*
+- * Initialization code here.
+- */
+-void mf_init(void)
+-{
+- int i;
+-
+- /* initialize */
+- spin_lock_init(&pending_event_spinlock);
+- for (i = 0;
+- i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc);
+- ++i)
+- free_pending_event(&pending_event_prealloc[i]);
+- HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler);
+-
+- /* virtual continue ack */
+- signal_ce_msg_simple(0x57, NULL);
+-
+- /* initialization complete */
+- printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities "
+- "initialized\n");
+-}
+-
+-struct rtc_time_data {
+- struct completion com;
+- struct ce_msg_data ce_msg;
+- int rc;
+-};
+-
+-static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
+-{
+- struct rtc_time_data *rtc = token;
+-
+- memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
+- rtc->rc = 0;
+- complete(&rtc->com);
+-}
+-
+-static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
+-{
+- tm->tm_wday = 0;
+- tm->tm_yday = 0;
+- tm->tm_isdst = 0;
+- if (rc) {
+- tm->tm_sec = 0;
+- tm->tm_min = 0;
+- tm->tm_hour = 0;
+- tm->tm_mday = 15;
+- tm->tm_mon = 5;
+- tm->tm_year = 52;
+- return rc;
+- }
+-
+- if ((ce_msg[2] == 0xa9) ||
+- (ce_msg[2] == 0xaf)) {
+- /* TOD clock is not set */
+- tm->tm_sec = 1;
+- tm->tm_min = 1;
+- tm->tm_hour = 1;
+- tm->tm_mday = 10;
+- tm->tm_mon = 8;
+- tm->tm_year = 71;
+- mf_set_rtc(tm);
+- }
+- {
+- u8 year = ce_msg[5];
+- u8 sec = ce_msg[6];
+- u8 min = ce_msg[7];
+- u8 hour = ce_msg[8];
+- u8 day = ce_msg[10];
+- u8 mon = ce_msg[11];
+-
+- BCD_TO_BIN(sec);
+- BCD_TO_BIN(min);
+- BCD_TO_BIN(hour);
+- BCD_TO_BIN(day);
+- BCD_TO_BIN(mon);
+- BCD_TO_BIN(year);
+-
+- if (year <= 69)
+- year += 100;
+-
+- tm->tm_sec = sec;
+- tm->tm_min = min;
+- tm->tm_hour = hour;
+- tm->tm_mday = day;
+- tm->tm_mon = mon;
+- tm->tm_year = year;
+- }
+-
+- return 0;
+-}
+-
+-int mf_get_rtc(struct rtc_time *tm)
+-{
+- struct ce_msg_comp_data ce_complete;
+- struct rtc_time_data rtc_data;
+- int rc;
+-
+- memset(&ce_complete, 0, sizeof(ce_complete));
+- memset(&rtc_data, 0, sizeof(rtc_data));
+- init_completion(&rtc_data.com);
+- ce_complete.handler = &get_rtc_time_complete;
+- ce_complete.token = &rtc_data;
+- rc = signal_ce_msg_simple(0x40, &ce_complete);
+- if (rc)
+- return rc;
+- wait_for_completion(&rtc_data.com);
+- return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
+-}
+-
+-struct boot_rtc_time_data {
+- int busy;
+- struct ce_msg_data ce_msg;
+- int rc;
+-};
+-
+-static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
+-{
+- struct boot_rtc_time_data *rtc = token;
+-
+- memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
+- rtc->rc = 0;
+- rtc->busy = 0;
+-}
+-
+-int mf_get_boot_rtc(struct rtc_time *tm)
+-{
+- struct ce_msg_comp_data ce_complete;
+- struct boot_rtc_time_data rtc_data;
+- int rc;
+-
+- memset(&ce_complete, 0, sizeof(ce_complete));
+- memset(&rtc_data, 0, sizeof(rtc_data));
+- rtc_data.busy = 1;
+- ce_complete.handler = &get_boot_rtc_time_complete;
+- ce_complete.token = &rtc_data;
+- rc = signal_ce_msg_simple(0x40, &ce_complete);
+- if (rc)
+- return rc;
+- /* We need to poll here as we are not yet taking interrupts */
+- while (rtc_data.busy) {
+- if (hvlpevent_is_pending())
+- process_hvlpevents(NULL);
+- }
+- return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
+-}
+-
+-int mf_set_rtc(struct rtc_time *tm)
+-{
+- char ce_time[12];
+- u8 day, mon, hour, min, sec, y1, y2;
+- unsigned year;
+-
+- year = 1900 + tm->tm_year;
+- y1 = year / 100;
+- y2 = year % 100;
+-
+- sec = tm->tm_sec;
+- min = tm->tm_min;
+- hour = tm->tm_hour;
+- day = tm->tm_mday;
+- mon = tm->tm_mon + 1;
+-
+- BIN_TO_BCD(sec);
+- BIN_TO_BCD(min);
+- BIN_TO_BCD(hour);
+- BIN_TO_BCD(mon);
+- BIN_TO_BCD(day);
+- BIN_TO_BCD(y1);
+- BIN_TO_BCD(y2);
+-
+- memset(ce_time, 0, sizeof(ce_time));
+- ce_time[3] = 0x41;
+- ce_time[4] = y1;
+- ce_time[5] = y2;
+- ce_time[6] = sec;
+- ce_time[7] = min;
+- ce_time[8] = hour;
+- ce_time[10] = day;
+- ce_time[11] = mon;
+-
+- return signal_ce_msg(ce_time, NULL);
+-}
+-
+-#ifdef CONFIG_PROC_FS
+-
+-static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- int len;
+- char *p;
+- struct vsp_cmd_data vsp_cmd;
+- int rc;
+- dma_addr_t dma_addr;
+-
+- /* The HV appears to return no more than 256 bytes of command line */
+- if (off >= 256)
+- return 0;
+- if ((off + count) > 256)
+- count = 256 - off;
+-
+- dma_addr = dma_map_single(iSeries_vio_dev, page, off + count,
+- DMA_FROM_DEVICE);
+- if (dma_mapping_error(dma_addr))
+- return -ENOMEM;
+- memset(page, 0, off + count);
+- memset(&vsp_cmd, 0, sizeof(vsp_cmd));
+- vsp_cmd.cmd = 33;
+- vsp_cmd.sub_data.kern.token = dma_addr;
+- vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
+- vsp_cmd.sub_data.kern.side = (u64)data;
+- vsp_cmd.sub_data.kern.length = off + count;
+- mb();
+- rc = signal_vsp_instruction(&vsp_cmd);
+- dma_unmap_single(iSeries_vio_dev, dma_addr, off + count,
+- DMA_FROM_DEVICE);
+- if (rc)
+- return rc;
+- if (vsp_cmd.result_code != 0)
+- return -ENOMEM;
+- p = page;
+- len = 0;
+- while (len < (off + count)) {
+- if ((*p == '\0') || (*p == '\n')) {
+- if (*p == '\0')
+- *p = '\n';
+- p++;
+- len++;
+- *eof = 1;
+- break;
+- }
+- p++;
+- len++;
+- }
+-
+- if (len < off) {
+- *eof = 1;
+- len = 0;
+- }
+- return len;
+-}
+-
+-#if 0
+-static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
+-{
+- struct vsp_cmd_data vsp_cmd;
+- int rc;
+- int len = *size;
+- dma_addr_t dma_addr;
+-
+- dma_addr = dma_map_single(iSeries_vio_dev, buffer, len,
+- DMA_FROM_DEVICE);
+- memset(buffer, 0, len);
+- memset(&vsp_cmd, 0, sizeof(vsp_cmd));
+- vsp_cmd.cmd = 32;
+- vsp_cmd.sub_data.kern.token = dma_addr;
+- vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
+- vsp_cmd.sub_data.kern.side = side;
+- vsp_cmd.sub_data.kern.offset = offset;
+- vsp_cmd.sub_data.kern.length = len;
+- mb();
+- rc = signal_vsp_instruction(&vsp_cmd);
+- if (rc == 0) {
+- if (vsp_cmd.result_code == 0)
+- *size = vsp_cmd.sub_data.length_out;
+- else
+- rc = -ENOMEM;
+- }
+-
+- dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE);
+-
+- return rc;
+-}
+-
+-static int proc_mf_dump_vmlinux(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- int sizeToGet = count;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EACCES;
+-
+- if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) {
+- if (sizeToGet != 0) {
+- *start = page + off;
+- return sizeToGet;
+- }
+- *eof = 1;
+- return 0;
+- }
+- *eof = 1;
+- return 0;
+-}
+-#endif
+-
+-static int proc_mf_dump_side(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- int len;
+- char mf_current_side = ' ';
+- struct vsp_cmd_data vsp_cmd;
+-
+- memset(&vsp_cmd, 0, sizeof(vsp_cmd));
+- vsp_cmd.cmd = 2;
+- vsp_cmd.sub_data.ipl_type = 0;
+- mb();
+-
+- if (signal_vsp_instruction(&vsp_cmd) == 0) {
+- if (vsp_cmd.result_code == 0) {
+- switch (vsp_cmd.sub_data.ipl_type) {
+- case 0: mf_current_side = 'A';
+- break;
+- case 1: mf_current_side = 'B';
+- break;
+- case 2: mf_current_side = 'C';
+- break;
+- default: mf_current_side = 'D';
+- break;
+- }
+- }
+- }
+-
+- len = sprintf(page, "%c\n", mf_current_side);
+-
+- if (len <= (off + count))
+- *eof = 1;
+- *start = page + off;
+- len -= off;
+- if (len > count)
+- len = count;
+- if (len < 0)
+- len = 0;
+- return len;
+-}
+-
+-static int proc_mf_change_side(struct file *file, const char __user *buffer,
+- unsigned long count, void *data)
+-{
+- char side;
+- u64 newSide;
+- struct vsp_cmd_data vsp_cmd;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EACCES;
+-
+- if (count == 0)
+- return 0;
+-
+- if (get_user(side, buffer))
+- return -EFAULT;
+-
+- switch (side) {
+- case 'A': newSide = 0;
+- break;
+- case 'B': newSide = 1;
+- break;
+- case 'C': newSide = 2;
+- break;
+- case 'D': newSide = 3;
+- break;
+- default:
+- printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n");
+- return -EINVAL;
+- }
+-
+- memset(&vsp_cmd, 0, sizeof(vsp_cmd));
+- vsp_cmd.sub_data.ipl_type = newSide;
+- vsp_cmd.cmd = 10;
+-
+- (void)signal_vsp_instruction(&vsp_cmd);
+-
+- return count;
+-}
+-
+-#if 0
+-static void mf_getSrcHistory(char *buffer, int size)
+-{
+- struct IplTypeReturnStuff return_stuff;
+- struct pending_event *ev = new_pending_event();
+- int rc = 0;
+- char *pages[4];
+-
+- pages[0] = kmalloc(4096, GFP_ATOMIC);
+- pages[1] = kmalloc(4096, GFP_ATOMIC);
+- pages[2] = kmalloc(4096, GFP_ATOMIC);
+- pages[3] = kmalloc(4096, GFP_ATOMIC);
+- if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL)
+- || (pages[2] == NULL) || (pages[3] == NULL))
+- return -ENOMEM;
+-
+- return_stuff.xType = 0;
+- return_stuff.xRc = 0;
+- return_stuff.xDone = 0;
+- ev->event.hp_lp_event.xSubtype = 6;
+- ev->event.hp_lp_event.x.xSubtypeData =
+- subtype_data('M', 'F', 'V', 'I');
+- ev->event.data.vsp_cmd.xEvent = &return_stuff;
+- ev->event.data.vsp_cmd.cmd = 4;
+- ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
+- ev->event.data.vsp_cmd.result_code = 0xFF;
+- ev->event.data.vsp_cmd.reserved = 0;
+- ev->event.data.vsp_cmd.sub_data.page[0] = ISERIES_HV_ADDR(pages[0]);
+- ev->event.data.vsp_cmd.sub_data.page[1] = ISERIES_HV_ADDR(pages[1]);
+- ev->event.data.vsp_cmd.sub_data.page[2] = ISERIES_HV_ADDR(pages[2]);
+- ev->event.data.vsp_cmd.sub_data.page[3] = ISERIES_HV_ADDR(pages[3]);
+- mb();
+- if (signal_event(ev) != 0)
+- return;
+-
+- while (return_stuff.xDone != 1)
+- udelay(10);
+- if (return_stuff.xRc == 0)
+- memcpy(buffer, pages[0], size);
+- kfree(pages[0]);
+- kfree(pages[1]);
+- kfree(pages[2]);
+- kfree(pages[3]);
+-}
+-#endif
+-
+-static int proc_mf_dump_src(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+-#if 0
+- int len;
+-
+- mf_getSrcHistory(page, count);
+- len = count;
+- len -= off;
+- if (len < count) {
+- *eof = 1;
+- if (len <= 0)
+- return 0;
+- } else
+- len = count;
+- *start = page + off;
+- return len;
+-#else
+- return 0;
+-#endif
+-}
+-
+-static int proc_mf_change_src(struct file *file, const char __user *buffer,
+- unsigned long count, void *data)
+-{
+- char stkbuf[10];
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EACCES;
+-
+- if ((count < 4) && (count != 1)) {
+- printk(KERN_ERR "mf_proc: invalid src\n");
+- return -EINVAL;
+- }
+-
+- if (count > (sizeof(stkbuf) - 1))
+- count = sizeof(stkbuf) - 1;
+- if (copy_from_user(stkbuf, buffer, count))
+- return -EFAULT;
+-
+- if ((count == 1) && (*stkbuf == '\0'))
+- mf_clear_src();
+- else
+- mf_display_src(*(u32 *)stkbuf);
+-
+- return count;
+-}
+-
+-static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
+- unsigned long count, void *data)
+-{
+- struct vsp_cmd_data vsp_cmd;
+- dma_addr_t dma_addr;
+- char *page;
+- int ret = -EACCES;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- goto out;
+-
+- dma_addr = 0;
+- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
+- GFP_ATOMIC);
+- ret = -ENOMEM;
+- if (page == NULL)
+- goto out;
+-
+- ret = -EFAULT;
+- if (copy_from_user(page, buffer, count))
+- goto out_free;
+-
+- memset(&vsp_cmd, 0, sizeof(vsp_cmd));
+- vsp_cmd.cmd = 31;
+- vsp_cmd.sub_data.kern.token = dma_addr;
+- vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
+- vsp_cmd.sub_data.kern.side = (u64)data;
+- vsp_cmd.sub_data.kern.length = count;
+- mb();
+- (void)signal_vsp_instruction(&vsp_cmd);
+- ret = count;
+-
+-out_free:
+- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+-out:
+- return ret;
+-}
+-
+-static ssize_t proc_mf_change_vmlinux(struct file *file,
+- const char __user *buf,
+- size_t count, loff_t *ppos)
+-{
+- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+- ssize_t rc;
+- dma_addr_t dma_addr;
+- char *page;
+- struct vsp_cmd_data vsp_cmd;
+-
+- rc = -EACCES;
+- if (!capable(CAP_SYS_ADMIN))
+- goto out;
+-
+- dma_addr = 0;
+- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
+- GFP_ATOMIC);
+- rc = -ENOMEM;
+- if (page == NULL) {
+- printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");
+- goto out;
+- }
+- rc = -EFAULT;
+- if (copy_from_user(page, buf, count))
+- goto out_free;
+-
+- memset(&vsp_cmd, 0, sizeof(vsp_cmd));
+- vsp_cmd.cmd = 30;
+- vsp_cmd.sub_data.kern.token = dma_addr;
+- vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
+- vsp_cmd.sub_data.kern.side = (u64)dp->data;
+- vsp_cmd.sub_data.kern.offset = *ppos;
+- vsp_cmd.sub_data.kern.length = count;
+- mb();
+- rc = signal_vsp_instruction(&vsp_cmd);
+- if (rc)
+- goto out_free;
+- rc = -ENOMEM;
+- if (vsp_cmd.result_code != 0)
+- goto out_free;
+-
+- *ppos += count;
+- rc = count;
+-out_free:
+- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+-out:
+- return rc;
+-}
+-
+-static struct file_operations proc_vmlinux_operations = {
+- .write = proc_mf_change_vmlinux,
+-};
+-
+-static int __init mf_proc_init(void)
+-{
+- struct proc_dir_entry *mf_proc_root;
+- struct proc_dir_entry *ent;
+- struct proc_dir_entry *mf;
+- char name[2];
+- int i;
+-
+- mf_proc_root = proc_mkdir("iSeries/mf", NULL);
+- if (!mf_proc_root)
+- return 1;
+-
+- name[1] = '\0';
+- for (i = 0; i < 4; i++) {
+- name[0] = 'A' + i;
+- mf = proc_mkdir(name, mf_proc_root);
+- if (!mf)
+- return 1;
+-
+- ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf);
+- if (!ent)
+- return 1;
+- ent->nlink = 1;
+- ent->data = (void *)(long)i;
+- ent->read_proc = proc_mf_dump_cmdline;
+- ent->write_proc = proc_mf_change_cmdline;
+-
+- if (i == 3) /* no vmlinux entry for 'D' */
+- continue;
+-
+- ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);
+- if (!ent)
+- return 1;
+- ent->nlink = 1;
+- ent->data = (void *)(long)i;
+- ent->proc_fops = &proc_vmlinux_operations;
+- }
+-
+- ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
+- if (!ent)
+- return 1;
+- ent->nlink = 1;
+- ent->data = (void *)0;
+- ent->read_proc = proc_mf_dump_side;
+- ent->write_proc = proc_mf_change_side;
+-
+- ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
+- if (!ent)
+- return 1;
+- ent->nlink = 1;
+- ent->data = (void *)0;
+- ent->read_proc = proc_mf_dump_src;
+- ent->write_proc = proc_mf_change_src;
+-
+- return 0;
+-}
+-
+-__initcall(mf_proc_init);
+-
+-#endif /* CONFIG_PROC_FS */
+diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
+--- a/arch/ppc64/kernel/misc.S
++++ b/arch/ppc64/kernel/misc.S
+@@ -28,6 +28,7 @@
+ #include <asm/ppc_asm.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/cputable.h>
++#include <asm/thread_info.h>
+
+ .text
+
+@@ -64,44 +65,6 @@ _GLOBAL(get_srr1)
+ _GLOBAL(get_sp)
+ mr r3,r1
+ blr
+-
+-#ifdef CONFIG_PPC_ISERIES
+-/* unsigned long local_save_flags(void) */
+-_GLOBAL(local_get_flags)
+- lbz r3,PACAPROCENABLED(r13)
+- blr
+-
+-/* unsigned long local_irq_disable(void) */
+-_GLOBAL(local_irq_disable)
+- lbz r3,PACAPROCENABLED(r13)
+- li r4,0
+- stb r4,PACAPROCENABLED(r13)
+- blr /* Done */
+-
+-/* void local_irq_restore(unsigned long flags) */
+-_GLOBAL(local_irq_restore)
+- lbz r5,PACAPROCENABLED(r13)
+- /* Check if things are setup the way we want _already_. */
+- cmpw 0,r3,r5
+- beqlr
+- /* are we enabling interrupts? */
+- cmpdi 0,r3,0
+- stb r3,PACAPROCENABLED(r13)
+- beqlr
+- /* Check pending interrupts */
+- /* A decrementer, IPI or PMC interrupt may have occurred
+- * while we were in the hypervisor (which enables) */
+- ld r4,PACALPPACA+LPPACAANYINT(r13)
+- cmpdi r4,0
+- beqlr
+-
+- /*
+- * Handle pending interrupts in interrupt context
+- */
+- li r0,0x5555
+- sc
+- blr
+-#endif /* CONFIG_PPC_ISERIES */
+
+ #ifdef CONFIG_IRQSTACKS
+ _GLOBAL(call_do_softirq)
+@@ -329,7 +292,7 @@ _GLOBAL(__flush_dcache_icache)
+
+ /* Flush the dcache */
+ ld r7,PPC64_CACHES at toc(r2)
+- clrrdi r3,r3,12 /* Page align */
++ clrrdi r3,r3,PAGE_SHIFT /* Page align */
+ lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */
+ lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */
+ mr r6,r3
+@@ -488,25 +451,6 @@ _GLOBAL(_outsl_ns)
+ sync
+ blr
+
+-
+-_GLOBAL(cvt_fd)
+- lfd 0,0(r5) /* load up fpscr value */
+- mtfsf 0xff,0
+- lfs 0,0(r3)
+- stfd 0,0(r4)
+- mffs 0 /* save new fpscr value */
+- stfd 0,0(r5)
+- blr
+-
+-_GLOBAL(cvt_df)
+- lfd 0,0(r5) /* load up fpscr value */
+- mtfsf 0xff,0
+- lfd 0,0(r3)
+- stfs 0,0(r4)
+- mffs 0 /* save new fpscr value */
+- stfd 0,0(r5)
+- blr
+-
+ /*
+ * identify_cpu and calls setup_cpu
+ * In: r3 = base of the cpu_specs array
+@@ -692,38 +636,6 @@ _GLOBAL(disable_kernel_fp)
+ isync
+ blr
+
+-/*
+- * giveup_fpu(tsk)
+- * Disable FP for the task given as the argument,
+- * and save the floating-point registers in its thread_struct.
+- * Enables the FPU for use in the kernel on return.
+- */
+-_GLOBAL(giveup_fpu)
+- mfmsr r5
+- ori r5,r5,MSR_FP
+- mtmsrd r5 /* enable use of fpu now */
+- isync
+- cmpdi 0,r3,0
+- beqlr- /* if no previous owner, done */
+- addi r3,r3,THREAD /* want THREAD of task */
+- ld r5,PT_REGS(r3)
+- cmpdi 0,r5,0
+- SAVE_32FPRS(0, r3)
+- mffs fr0
+- stfd fr0,THREAD_FPSCR(r3)
+- beq 1f
+- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+- li r3,MSR_FP|MSR_FE0|MSR_FE1
+- andc r4,r4,r3 /* disable FP for previous task */
+- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+-1:
+-#ifndef CONFIG_SMP
+- li r5,0
+- ld r4,last_task_used_math at got(r2)
+- std r5,0(r4)
+-#endif /* CONFIG_SMP */
+- blr
+-
+ #ifdef CONFIG_ALTIVEC
+
+ #if 0 /* this has no callers for now */
+@@ -778,6 +690,13 @@ _GLOBAL(giveup_altivec)
+ _GLOBAL(__setup_cpu_power3)
+ blr
+
++_GLOBAL(execve)
++ li r0,__NR_execve
++ sc
++ bnslr
++ neg r3,r3
++ blr
++
+ /* kexec_wait(phys_cpu)
+ *
+ * wait for the flag to change, indicating this kernel is going away but
+@@ -948,566 +867,3 @@ _GLOBAL(kexec_sequence)
+ li r5,0
+ blr /* image->start(physid, image->start, 0); */
+ #endif /* CONFIG_KEXEC */
+-
+-/* Why isn't this a) automatic, b) written in 'C'? */
+- .balign 8
+-_GLOBAL(sys_call_table32)
+- .llong .sys_restart_syscall /* 0 */
+- .llong .sys_exit
+- .llong .ppc_fork
+- .llong .sys_read
+- .llong .sys_write
+- .llong .compat_sys_open /* 5 */
+- .llong .sys_close
+- .llong .sys32_waitpid
+- .llong .sys32_creat
+- .llong .sys_link
+- .llong .sys_unlink /* 10 */
+- .llong .sys32_execve
+- .llong .sys_chdir
+- .llong .compat_sys_time
+- .llong .sys_mknod
+- .llong .sys_chmod /* 15 */
+- .llong .sys_lchown
+- .llong .sys_ni_syscall /* old break syscall */
+- .llong .sys_ni_syscall /* old stat syscall */
+- .llong .ppc32_lseek
+- .llong .sys_getpid /* 20 */
+- .llong .compat_sys_mount
+- .llong .sys_oldumount
+- .llong .sys_setuid
+- .llong .sys_getuid
+- .llong .compat_sys_stime /* 25 */
+- .llong .sys32_ptrace
+- .llong .sys_alarm
+- .llong .sys_ni_syscall /* old fstat syscall */
+- .llong .sys32_pause
+- .llong .compat_sys_utime /* 30 */
+- .llong .sys_ni_syscall /* old stty syscall */
+- .llong .sys_ni_syscall /* old gtty syscall */
+- .llong .sys32_access
+- .llong .sys32_nice
+- .llong .sys_ni_syscall /* 35 - old ftime syscall */
+- .llong .sys_sync
+- .llong .sys32_kill
+- .llong .sys_rename
+- .llong .sys32_mkdir
+- .llong .sys_rmdir /* 40 */
+- .llong .sys_dup
+- .llong .sys_pipe
+- .llong .compat_sys_times
+- .llong .sys_ni_syscall /* old prof syscall */
+- .llong .sys_brk /* 45 */
+- .llong .sys_setgid
+- .llong .sys_getgid
+- .llong .sys_signal
+- .llong .sys_geteuid
+- .llong .sys_getegid /* 50 */
+- .llong .sys_acct
+- .llong .sys_umount
+- .llong .sys_ni_syscall /* old lock syscall */
+- .llong .compat_sys_ioctl
+- .llong .compat_sys_fcntl /* 55 */
+- .llong .sys_ni_syscall /* old mpx syscall */
+- .llong .sys32_setpgid
+- .llong .sys_ni_syscall /* old ulimit syscall */
+- .llong .sys32_olduname
+- .llong .sys32_umask /* 60 */
+- .llong .sys_chroot
+- .llong .sys_ustat
+- .llong .sys_dup2
+- .llong .sys_getppid
+- .llong .sys_getpgrp /* 65 */
+- .llong .sys_setsid
+- .llong .sys32_sigaction
+- .llong .sys_sgetmask
+- .llong .sys32_ssetmask
+- .llong .sys_setreuid /* 70 */
+- .llong .sys_setregid
+- .llong .ppc32_sigsuspend
+- .llong .compat_sys_sigpending
+- .llong .sys32_sethostname
+- .llong .compat_sys_setrlimit /* 75 */
+- .llong .compat_sys_old_getrlimit
+- .llong .compat_sys_getrusage
+- .llong .sys32_gettimeofday
+- .llong .sys32_settimeofday
+- .llong .sys32_getgroups /* 80 */
+- .llong .sys32_setgroups
+- .llong .sys_ni_syscall /* old select syscall */
+- .llong .sys_symlink
+- .llong .sys_ni_syscall /* old lstat syscall */
+- .llong .sys32_readlink /* 85 */
+- .llong .sys_uselib
+- .llong .sys_swapon
+- .llong .sys_reboot
+- .llong .old32_readdir
+- .llong .sys_mmap /* 90 */
+- .llong .sys_munmap
+- .llong .sys_truncate
+- .llong .sys_ftruncate
+- .llong .sys_fchmod
+- .llong .sys_fchown /* 95 */
+- .llong .sys32_getpriority
+- .llong .sys32_setpriority
+- .llong .sys_ni_syscall /* old profil syscall */
+- .llong .compat_sys_statfs
+- .llong .compat_sys_fstatfs /* 100 */
+- .llong .sys_ni_syscall /* old ioperm syscall */
+- .llong .compat_sys_socketcall
+- .llong .sys32_syslog
+- .llong .compat_sys_setitimer
+- .llong .compat_sys_getitimer /* 105 */
+- .llong .compat_sys_newstat
+- .llong .compat_sys_newlstat
+- .llong .compat_sys_newfstat
+- .llong .sys32_uname
+- .llong .sys_ni_syscall /* 110 old iopl syscall */
+- .llong .sys_vhangup
+- .llong .sys_ni_syscall /* old idle syscall */
+- .llong .sys_ni_syscall /* old vm86 syscall */
+- .llong .compat_sys_wait4
+- .llong .sys_swapoff /* 115 */
+- .llong .sys32_sysinfo
+- .llong .sys32_ipc
+- .llong .sys_fsync
+- .llong .ppc32_sigreturn
+- .llong .ppc_clone /* 120 */
+- .llong .sys32_setdomainname
+- .llong .ppc64_newuname
+- .llong .sys_ni_syscall /* old modify_ldt syscall */
+- .llong .sys32_adjtimex
+- .llong .sys_mprotect /* 125 */
+- .llong .compat_sys_sigprocmask
+- .llong .sys_ni_syscall /* old create_module syscall */
+- .llong .sys_init_module
+- .llong .sys_delete_module
+- .llong .sys_ni_syscall /* 130 old get_kernel_syms syscall */
+- .llong .sys_quotactl
+- .llong .sys32_getpgid
+- .llong .sys_fchdir
+- .llong .sys_bdflush
+- .llong .sys32_sysfs /* 135 */
+- .llong .ppc64_personality
+- .llong .sys_ni_syscall /* for afs_syscall */
+- .llong .sys_setfsuid
+- .llong .sys_setfsgid
+- .llong .sys_llseek /* 140 */
+- .llong .sys32_getdents
+- .llong .ppc32_select
+- .llong .sys_flock
+- .llong .sys_msync
+- .llong .compat_sys_readv /* 145 */
+- .llong .compat_sys_writev
+- .llong .sys32_getsid
+- .llong .sys_fdatasync
+- .llong .sys32_sysctl
+- .llong .sys_mlock /* 150 */
+- .llong .sys_munlock
+- .llong .sys_mlockall
+- .llong .sys_munlockall
+- .llong .sys32_sched_setparam
+- .llong .sys32_sched_getparam /* 155 */
+- .llong .sys32_sched_setscheduler
+- .llong .sys32_sched_getscheduler
+- .llong .sys_sched_yield
+- .llong .sys32_sched_get_priority_max
+- .llong .sys32_sched_get_priority_min /* 160 */
+- .llong .sys32_sched_rr_get_interval
+- .llong .compat_sys_nanosleep
+- .llong .sys_mremap
+- .llong .sys_setresuid
+- .llong .sys_getresuid /* 165 */
+- .llong .sys_ni_syscall /* old query_module syscall */
+- .llong .sys_poll
+- .llong .compat_sys_nfsservctl
+- .llong .sys_setresgid
+- .llong .sys_getresgid /* 170 */
+- .llong .sys32_prctl
+- .llong .ppc32_rt_sigreturn
+- .llong .sys32_rt_sigaction
+- .llong .sys32_rt_sigprocmask
+- .llong .sys32_rt_sigpending /* 175 */
+- .llong .compat_sys_rt_sigtimedwait
+- .llong .sys32_rt_sigqueueinfo
+- .llong .ppc32_rt_sigsuspend
+- .llong .sys32_pread64
+- .llong .sys32_pwrite64 /* 180 */
+- .llong .sys_chown
+- .llong .sys_getcwd
+- .llong .sys_capget
+- .llong .sys_capset
+- .llong .sys32_sigaltstack /* 185 */
+- .llong .sys32_sendfile
+- .llong .sys_ni_syscall /* reserved for streams1 */
+- .llong .sys_ni_syscall /* reserved for streams2 */
+- .llong .ppc_vfork
+- .llong .compat_sys_getrlimit /* 190 */
+- .llong .sys32_readahead
+- .llong .sys32_mmap2
+- .llong .sys32_truncate64
+- .llong .sys32_ftruncate64
+- .llong .sys_stat64 /* 195 */
+- .llong .sys_lstat64
+- .llong .sys_fstat64
+- .llong .sys32_pciconfig_read
+- .llong .sys32_pciconfig_write
+- .llong .sys32_pciconfig_iobase /* 200 - pciconfig_iobase */
+- .llong .sys_ni_syscall /* reserved for MacOnLinux */
+- .llong .sys_getdents64
+- .llong .sys_pivot_root
+- .llong .compat_sys_fcntl64
+- .llong .sys_madvise /* 205 */
+- .llong .sys_mincore
+- .llong .sys_gettid
+- .llong .sys_tkill
+- .llong .sys_setxattr
+- .llong .sys_lsetxattr /* 210 */
+- .llong .sys_fsetxattr
+- .llong .sys_getxattr
+- .llong .sys_lgetxattr
+- .llong .sys_fgetxattr
+- .llong .sys_listxattr /* 215 */
+- .llong .sys_llistxattr
+- .llong .sys_flistxattr
+- .llong .sys_removexattr
+- .llong .sys_lremovexattr
+- .llong .sys_fremovexattr /* 220 */
+- .llong .compat_sys_futex
+- .llong .compat_sys_sched_setaffinity
+- .llong .compat_sys_sched_getaffinity
+- .llong .sys_ni_syscall
+- .llong .sys_ni_syscall /* 225 - reserved for tux */
+- .llong .sys32_sendfile64
+- .llong .compat_sys_io_setup
+- .llong .sys_io_destroy
+- .llong .compat_sys_io_getevents
+- .llong .compat_sys_io_submit
+- .llong .sys_io_cancel
+- .llong .sys_set_tid_address
+- .llong .ppc32_fadvise64
+- .llong .sys_exit_group
+- .llong .ppc32_lookup_dcookie /* 235 */
+- .llong .sys_epoll_create
+- .llong .sys_epoll_ctl
+- .llong .sys_epoll_wait
+- .llong .sys_remap_file_pages
+- .llong .ppc32_timer_create /* 240 */
+- .llong .compat_sys_timer_settime
+- .llong .compat_sys_timer_gettime
+- .llong .sys_timer_getoverrun
+- .llong .sys_timer_delete
+- .llong .compat_sys_clock_settime /* 245 */
+- .llong .compat_sys_clock_gettime
+- .llong .compat_sys_clock_getres
+- .llong .compat_sys_clock_nanosleep
+- .llong .ppc32_swapcontext
+- .llong .sys32_tgkill /* 250 */
+- .llong .sys32_utimes
+- .llong .compat_sys_statfs64
+- .llong .compat_sys_fstatfs64
+- .llong .ppc32_fadvise64_64 /* 32bit only fadvise64_64 */
+- .llong .ppc_rtas /* 255 */
+- .llong .sys_ni_syscall /* 256 reserved for sys_debug_setcontext */
+- .llong .sys_ni_syscall /* 257 reserved for vserver */
+- .llong .sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */
+- .llong .compat_sys_mbind
+- .llong .compat_sys_get_mempolicy /* 260 */
+- .llong .compat_sys_set_mempolicy
+- .llong .compat_sys_mq_open
+- .llong .sys_mq_unlink
+- .llong .compat_sys_mq_timedsend
+- .llong .compat_sys_mq_timedreceive /* 265 */
+- .llong .compat_sys_mq_notify
+- .llong .compat_sys_mq_getsetattr
+- .llong .compat_sys_kexec_load
+- .llong .sys32_add_key
+- .llong .sys32_request_key /* 270 */
+- .llong .compat_sys_keyctl
+- .llong .compat_sys_waitid
+- .llong .sys32_ioprio_set
+- .llong .sys32_ioprio_get
+- .llong .sys_inotify_init /* 275 */
+- .llong .sys_inotify_add_watch
+- .llong .sys_inotify_rm_watch
+-
+- .balign 8
+-_GLOBAL(sys_call_table)
+- .llong .sys_restart_syscall /* 0 */
+- .llong .sys_exit
+- .llong .ppc_fork
+- .llong .sys_read
+- .llong .sys_write
+- .llong .sys_open /* 5 */
+- .llong .sys_close
+- .llong .sys_waitpid
+- .llong .sys_creat
+- .llong .sys_link
+- .llong .sys_unlink /* 10 */
+- .llong .sys_execve
+- .llong .sys_chdir
+- .llong .sys64_time
+- .llong .sys_mknod
+- .llong .sys_chmod /* 15 */
+- .llong .sys_lchown
+- .llong .sys_ni_syscall /* old break syscall */
+- .llong .sys_ni_syscall /* old stat syscall */
+- .llong .sys_lseek
+- .llong .sys_getpid /* 20 */
+- .llong .sys_mount
+- .llong .sys_ni_syscall /* old umount syscall */
+- .llong .sys_setuid
+- .llong .sys_getuid
+- .llong .sys_stime /* 25 */
+- .llong .sys_ptrace
+- .llong .sys_alarm
+- .llong .sys_ni_syscall /* old fstat syscall */
+- .llong .sys_pause
+- .llong .sys_utime /* 30 */
+- .llong .sys_ni_syscall /* old stty syscall */
+- .llong .sys_ni_syscall /* old gtty syscall */
+- .llong .sys_access
+- .llong .sys_nice
+- .llong .sys_ni_syscall /* 35 - old ftime syscall */
+- .llong .sys_sync
+- .llong .sys_kill
+- .llong .sys_rename
+- .llong .sys_mkdir
+- .llong .sys_rmdir /* 40 */
+- .llong .sys_dup
+- .llong .sys_pipe
+- .llong .sys_times
+- .llong .sys_ni_syscall /* old prof syscall */
+- .llong .sys_brk /* 45 */
+- .llong .sys_setgid
+- .llong .sys_getgid
+- .llong .sys_signal
+- .llong .sys_geteuid
+- .llong .sys_getegid /* 50 */
+- .llong .sys_acct
+- .llong .sys_umount
+- .llong .sys_ni_syscall /* old lock syscall */
+- .llong .sys_ioctl
+- .llong .sys_fcntl /* 55 */
+- .llong .sys_ni_syscall /* old mpx syscall */
+- .llong .sys_setpgid
+- .llong .sys_ni_syscall /* old ulimit syscall */
+- .llong .sys_ni_syscall /* old uname syscall */
+- .llong .sys_umask /* 60 */
+- .llong .sys_chroot
+- .llong .sys_ustat
+- .llong .sys_dup2
+- .llong .sys_getppid
+- .llong .sys_getpgrp /* 65 */
+- .llong .sys_setsid
+- .llong .sys_ni_syscall
+- .llong .sys_sgetmask
+- .llong .sys_ssetmask
+- .llong .sys_setreuid /* 70 */
+- .llong .sys_setregid
+- .llong .sys_ni_syscall
+- .llong .sys_ni_syscall
+- .llong .sys_sethostname
+- .llong .sys_setrlimit /* 75 */
+- .llong .sys_ni_syscall /* old getrlimit syscall */
+- .llong .sys_getrusage
+- .llong .sys_gettimeofday
+- .llong .sys_settimeofday
+- .llong .sys_getgroups /* 80 */
+- .llong .sys_setgroups
+- .llong .sys_ni_syscall /* old select syscall */
+- .llong .sys_symlink
+- .llong .sys_ni_syscall /* old lstat syscall */
+- .llong .sys_readlink /* 85 */
+- .llong .sys_uselib
+- .llong .sys_swapon
+- .llong .sys_reboot
+- .llong .sys_ni_syscall /* old readdir syscall */
+- .llong .sys_mmap /* 90 */
+- .llong .sys_munmap
+- .llong .sys_truncate
+- .llong .sys_ftruncate
+- .llong .sys_fchmod
+- .llong .sys_fchown /* 95 */
+- .llong .sys_getpriority
+- .llong .sys_setpriority
+- .llong .sys_ni_syscall /* old profil syscall holder */
+- .llong .sys_statfs
+- .llong .sys_fstatfs /* 100 */
+- .llong .sys_ni_syscall /* old ioperm syscall */
+- .llong .sys_socketcall
+- .llong .sys_syslog
+- .llong .sys_setitimer
+- .llong .sys_getitimer /* 105 */
+- .llong .sys_newstat
+- .llong .sys_newlstat
+- .llong .sys_newfstat
+- .llong .sys_ni_syscall /* old uname syscall */
+- .llong .sys_ni_syscall /* 110 old iopl syscall */
+- .llong .sys_vhangup
+- .llong .sys_ni_syscall /* old idle syscall */
+- .llong .sys_ni_syscall /* old vm86 syscall */
+- .llong .sys_wait4
+- .llong .sys_swapoff /* 115 */
+- .llong .sys_sysinfo
+- .llong .sys_ipc
+- .llong .sys_fsync
+- .llong .sys_ni_syscall
+- .llong .ppc_clone /* 120 */
+- .llong .sys_setdomainname
+- .llong .ppc64_newuname
+- .llong .sys_ni_syscall /* old modify_ldt syscall */
+- .llong .sys_adjtimex
+- .llong .sys_mprotect /* 125 */
+- .llong .sys_ni_syscall
+- .llong .sys_ni_syscall /* old create_module syscall */
+- .llong .sys_init_module
+- .llong .sys_delete_module
+- .llong .sys_ni_syscall /* 130 old get_kernel_syms syscall */
+- .llong .sys_quotactl
+- .llong .sys_getpgid
+- .llong .sys_fchdir
+- .llong .sys_bdflush
+- .llong .sys_sysfs /* 135 */
+- .llong .ppc64_personality
+- .llong .sys_ni_syscall /* for afs_syscall */
+- .llong .sys_setfsuid
+- .llong .sys_setfsgid
+- .llong .sys_llseek /* 140 */
+- .llong .sys_getdents
+- .llong .sys_select
+- .llong .sys_flock
+- .llong .sys_msync
+- .llong .sys_readv /* 145 */
+- .llong .sys_writev
+- .llong .sys_getsid
+- .llong .sys_fdatasync
+- .llong .sys_sysctl
+- .llong .sys_mlock /* 150 */
+- .llong .sys_munlock
+- .llong .sys_mlockall
+- .llong .sys_munlockall
+- .llong .sys_sched_setparam
+- .llong .sys_sched_getparam /* 155 */
+- .llong .sys_sched_setscheduler
+- .llong .sys_sched_getscheduler
+- .llong .sys_sched_yield
+- .llong .sys_sched_get_priority_max
+- .llong .sys_sched_get_priority_min /* 160 */
+- .llong .sys_sched_rr_get_interval
+- .llong .sys_nanosleep
+- .llong .sys_mremap
+- .llong .sys_setresuid
+- .llong .sys_getresuid /* 165 */
+- .llong .sys_ni_syscall /* old query_module syscall */
+- .llong .sys_poll
+- .llong .sys_nfsservctl
+- .llong .sys_setresgid
+- .llong .sys_getresgid /* 170 */
+- .llong .sys_prctl
+- .llong .ppc64_rt_sigreturn
+- .llong .sys_rt_sigaction
+- .llong .sys_rt_sigprocmask
+- .llong .sys_rt_sigpending /* 175 */
+- .llong .sys_rt_sigtimedwait
+- .llong .sys_rt_sigqueueinfo
+- .llong .ppc64_rt_sigsuspend
+- .llong .sys_pread64
+- .llong .sys_pwrite64 /* 180 */
+- .llong .sys_chown
+- .llong .sys_getcwd
+- .llong .sys_capget
+- .llong .sys_capset
+- .llong .sys_sigaltstack /* 185 */
+- .llong .sys_sendfile64
+- .llong .sys_ni_syscall /* reserved for streams1 */
+- .llong .sys_ni_syscall /* reserved for streams2 */
+- .llong .ppc_vfork
+- .llong .sys_getrlimit /* 190 */
+- .llong .sys_readahead
+- .llong .sys_ni_syscall /* 32bit only mmap2 */
+- .llong .sys_ni_syscall /* 32bit only truncate64 */
+- .llong .sys_ni_syscall /* 32bit only ftruncate64 */
+- .llong .sys_ni_syscall /* 195 - 32bit only stat64 */
+- .llong .sys_ni_syscall /* 32bit only lstat64 */
+- .llong .sys_ni_syscall /* 32bit only fstat64 */
+- .llong .sys_pciconfig_read
+- .llong .sys_pciconfig_write
+- .llong .sys_pciconfig_iobase /* 200 - pciconfig_iobase */
+- .llong .sys_ni_syscall /* reserved for MacOnLinux */
+- .llong .sys_getdents64
+- .llong .sys_pivot_root
+- .llong .sys_ni_syscall /* 32bit only fcntl64 */
+- .llong .sys_madvise /* 205 */
+- .llong .sys_mincore
+- .llong .sys_gettid
+- .llong .sys_tkill
+- .llong .sys_setxattr
+- .llong .sys_lsetxattr /* 210 */
+- .llong .sys_fsetxattr
+- .llong .sys_getxattr
+- .llong .sys_lgetxattr
+- .llong .sys_fgetxattr
+- .llong .sys_listxattr /* 215 */
+- .llong .sys_llistxattr
+- .llong .sys_flistxattr
+- .llong .sys_removexattr
+- .llong .sys_lremovexattr
+- .llong .sys_fremovexattr /* 220 */
+- .llong .sys_futex
+- .llong .sys_sched_setaffinity
+- .llong .sys_sched_getaffinity
+- .llong .sys_ni_syscall
+- .llong .sys_ni_syscall /* 225 - reserved for tux */
+- .llong .sys_ni_syscall /* 32bit only sendfile64 */
+- .llong .sys_io_setup
+- .llong .sys_io_destroy
+- .llong .sys_io_getevents
+- .llong .sys_io_submit /* 230 */
+- .llong .sys_io_cancel
+- .llong .sys_set_tid_address
+- .llong .sys_fadvise64
+- .llong .sys_exit_group
+- .llong .sys_lookup_dcookie /* 235 */
+- .llong .sys_epoll_create
+- .llong .sys_epoll_ctl
+- .llong .sys_epoll_wait
+- .llong .sys_remap_file_pages
+- .llong .sys_timer_create /* 240 */
+- .llong .sys_timer_settime
+- .llong .sys_timer_gettime
+- .llong .sys_timer_getoverrun
+- .llong .sys_timer_delete
+- .llong .sys_clock_settime /* 245 */
+- .llong .sys_clock_gettime
+- .llong .sys_clock_getres
+- .llong .sys_clock_nanosleep
+- .llong .ppc64_swapcontext
+- .llong .sys_tgkill /* 250 */
+- .llong .sys_utimes
+- .llong .sys_statfs64
+- .llong .sys_fstatfs64
+- .llong .sys_ni_syscall /* 32bit only fadvise64_64 */
+- .llong .ppc_rtas /* 255 */
+- .llong .sys_ni_syscall /* 256 reserved for sys_debug_setcontext */
+- .llong .sys_ni_syscall /* 257 reserved for vserver */
+- .llong .sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */
+- .llong .sys_mbind
+- .llong .sys_get_mempolicy /* 260 */
+- .llong .sys_set_mempolicy
+- .llong .sys_mq_open
+- .llong .sys_mq_unlink
+- .llong .sys_mq_timedsend
+- .llong .sys_mq_timedreceive /* 265 */
+- .llong .sys_mq_notify
+- .llong .sys_mq_getsetattr
+- .llong .sys_kexec_load
+- .llong .sys_add_key
+- .llong .sys_request_key /* 270 */
+- .llong .sys_keyctl
+- .llong .sys_waitid
+- .llong .sys_ioprio_set
+- .llong .sys_ioprio_get
+- .llong .sys_inotify_init /* 275 */
+- .llong .sys_inotify_add_watch
+- .llong .sys_inotify_rm_watch
+diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/mpic.c
++++ /dev/null
+@@ -1,888 +0,0 @@
+-/*
+- * arch/ppc64/kernel/mpic.c
+- *
+- * Driver for interrupt controllers following the OpenPIC standard, the
+- * common implementation beeing IBM's MPIC. This driver also can deal
+- * with various broken implementations of this HW.
+- *
+- * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
+- *
+- * 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/irq.h>
+-#include <linux/smp.h>
+-#include <linux/interrupt.h>
+-#include <linux/bootmem.h>
+-#include <linux/spinlock.h>
+-#include <linux/pci.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/signal.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/irq.h>
+-#include <asm/machdep.h>
+-
+-#include "mpic.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) printk(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-static struct mpic *mpics;
+-static struct mpic *mpic_primary;
+-static DEFINE_SPINLOCK(mpic_lock);
+-
+-
+-/*
+- * Register accessor functions
+- */
+-
+-
+-static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base,
+- unsigned int reg)
+-{
+- if (be)
+- return in_be32(base + (reg >> 2));
+- else
+- return in_le32(base + (reg >> 2));
+-}
+-
+-static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
+- unsigned int reg, u32 value)
+-{
+- if (be)
+- out_be32(base + (reg >> 2), value);
+- else
+- out_le32(base + (reg >> 2), value);
+-}
+-
+-static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
+-{
+- unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
+- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+-
+- if (mpic->flags & MPIC_BROKEN_IPI)
+- be = !be;
+- return _mpic_read(be, mpic->gregs, offset);
+-}
+-
+-static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
+-{
+- unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+-
+- _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
+-}
+-
+-static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
+-{
+- unsigned int cpu = 0;
+-
+- if (mpic->flags & MPIC_PRIMARY)
+- cpu = hard_smp_processor_id();
+-
+- return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg);
+-}
+-
+-static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
+-{
+- unsigned int cpu = 0;
+-
+- if (mpic->flags & MPIC_PRIMARY)
+- cpu = hard_smp_processor_id();
+-
+- _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value);
+-}
+-
+-static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg)
+-{
+- unsigned int isu = src_no >> mpic->isu_shift;
+- unsigned int idx = src_no & mpic->isu_mask;
+-
+- return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+- reg + (idx * MPIC_IRQ_STRIDE));
+-}
+-
+-static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
+- unsigned int reg, u32 value)
+-{
+- unsigned int isu = src_no >> mpic->isu_shift;
+- unsigned int idx = src_no & mpic->isu_mask;
+-
+- _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+- reg + (idx * MPIC_IRQ_STRIDE), value);
+-}
+-
+-#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
+-#define mpic_write(b,r,v) _mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v))
+-#define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i))
+-#define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v))
+-#define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i))
+-#define mpic_cpu_write(i,v) _mpic_cpu_write(mpic,(i),(v))
+-#define mpic_irq_read(s,r) _mpic_irq_read(mpic,(s),(r))
+-#define mpic_irq_write(s,r,v) _mpic_irq_write(mpic,(s),(r),(v))
+-
+-
+-/*
+- * Low level utility functions
+- */
+-
+-
+-
+-/* Check if we have one of those nice broken MPICs with a flipped endian on
+- * reads from IPI registers
+- */
+-static void __init mpic_test_broken_ipi(struct mpic *mpic)
+-{
+- u32 r;
+-
+- mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
+- r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+-
+- if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
+- printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
+- mpic->flags |= MPIC_BROKEN_IPI;
+- }
+-}
+-
+-#ifdef CONFIG_MPIC_BROKEN_U3
+-
+-/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
+- * to force the edge setting on the MPIC and do the ack workaround.
+- */
+-static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no)
+-{
+- if (source_no >= 128 || !mpic->fixups)
+- return 0;
+- return mpic->fixups[source_no].base != NULL;
+-}
+-
+-static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
+-{
+- struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
+- u32 tmp;
+-
+- spin_lock(&mpic->fixup_lock);
+- writeb(0x11 + 2 * fixup->irq, fixup->base);
+- tmp = readl(fixup->base + 2);
+- writel(tmp | 0x80000000ul, fixup->base + 2);
+- /* config writes shouldn't be posted but let's be safe ... */
+- (void)readl(fixup->base + 2);
+- spin_unlock(&mpic->fixup_lock);
+-}
+-
+-
+-static void __init mpic_amd8111_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+-{
+- int i, irq;
+- u32 tmp;
+-
+- printk(KERN_INFO "mpic: - Workarounds on AMD 8111 @ %p\n", devbase);
+-
+- for (i=0; i < 24; i++) {
+- writeb(0x10 + 2*i, devbase + 0xf2);
+- tmp = readl(devbase + 0xf4);
+- if ((tmp & 0x1) || !(tmp & 0x20))
+- continue;
+- irq = (tmp >> 16) & 0xff;
+- mpic->fixups[irq].irq = i;
+- mpic->fixups[irq].base = devbase + 0xf2;
+- }
+-}
+-
+-static void __init mpic_amd8131_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+-{
+- int i, irq;
+- u32 tmp;
+-
+- printk(KERN_INFO "mpic: - Workarounds on AMD 8131 @ %p\n", devbase);
+-
+- for (i=0; i < 4; i++) {
+- writeb(0x10 + 2*i, devbase + 0xba);
+- tmp = readl(devbase + 0xbc);
+- if ((tmp & 0x1) || !(tmp & 0x20))
+- continue;
+- irq = (tmp >> 16) & 0xff;
+- mpic->fixups[irq].irq = i;
+- mpic->fixups[irq].base = devbase + 0xba;
+- }
+-}
+-
+-static void __init mpic_scan_ioapics(struct mpic *mpic)
+-{
+- unsigned int devfn;
+- u8 __iomem *cfgspace;
+-
+- printk(KERN_INFO "mpic: Setting up IO-APICs workarounds for U3\n");
+-
+- /* Allocate fixups array */
+- mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
+- BUG_ON(mpic->fixups == NULL);
+- memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
+-
+- /* Init spinlock */
+- spin_lock_init(&mpic->fixup_lock);
+-
+- /* Map u3 config space. We assume all IO-APICs are on the primary bus
+- * and slot will never be above "0xf" so we only need to map 32k
+- */
+- cfgspace = (unsigned char __iomem *)ioremap(0xf2000000, 0x8000);
+- BUG_ON(cfgspace == NULL);
+-
+- /* Now we scan all slots. We do a very quick scan, we read the header type,
+- * vendor ID and device ID only, that's plenty enough
+- */
+- for (devfn = 0; devfn < PCI_DEVFN(0x10,0); devfn ++) {
+- u8 __iomem *devbase = cfgspace + (devfn << 8);
+- u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
+- u32 l = readl(devbase + PCI_VENDOR_ID);
+- u16 vendor_id, device_id;
+- int multifunc = 0;
+-
+- DBG("devfn %x, l: %x\n", devfn, l);
+-
+- /* If no device, skip */
+- if (l == 0xffffffff || l == 0x00000000 ||
+- l == 0x0000ffff || l == 0xffff0000)
+- goto next;
+-
+- /* Check if it's a multifunction device (only really used
+- * to function 0 though
+- */
+- multifunc = !!(hdr_type & 0x80);
+- vendor_id = l & 0xffff;
+- device_id = (l >> 16) & 0xffff;
+-
+- /* If a known device, go to fixup setup code */
+- if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7460)
+- mpic_amd8111_read_irq(mpic, devbase);
+- if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7450)
+- mpic_amd8131_read_irq(mpic, devbase);
+- next:
+- /* next device, if function 0 */
+- if ((PCI_FUNC(devfn) == 0) && !multifunc)
+- devfn += 7;
+- }
+-}
+-
+-#endif /* CONFIG_MPIC_BROKEN_U3 */
+-
+-
+-/* Find an mpic associated with a given linux interrupt */
+-static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
+-{
+- struct mpic *mpic = mpics;
+-
+- while(mpic) {
+- /* search IPIs first since they may override the main interrupts */
+- if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) {
+- if (is_ipi)
+- *is_ipi = 1;
+- return mpic;
+- }
+- if (irq >= mpic->irq_offset &&
+- irq < (mpic->irq_offset + mpic->irq_count)) {
+- if (is_ipi)
+- *is_ipi = 0;
+- return mpic;
+- }
+- mpic = mpic -> next;
+- }
+- return NULL;
+-}
+-
+-/* Convert a cpu mask from logical to physical cpu numbers. */
+-static inline u32 mpic_physmask(u32 cpumask)
+-{
+- int i;
+- u32 mask = 0;
+-
+- for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
+- mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
+- return mask;
+-}
+-
+-#ifdef CONFIG_SMP
+-/* Get the mpic structure from the IPI number */
+-static inline struct mpic * mpic_from_ipi(unsigned int ipi)
+-{
+- return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi);
+-}
+-#endif
+-
+-/* Get the mpic structure from the irq number */
+-static inline struct mpic * mpic_from_irq(unsigned int irq)
+-{
+- return container_of(irq_desc[irq].handler, struct mpic, hc_irq);
+-}
+-
+-/* Send an EOI */
+-static inline void mpic_eoi(struct mpic *mpic)
+-{
+- mpic_cpu_write(MPIC_CPU_EOI, 0);
+- (void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+-}
+-
+-#ifdef CONFIG_SMP
+-static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+-{
+- struct mpic *mpic = dev_id;
+-
+- smp_message_recv(irq - mpic->ipi_offset, regs);
+- return IRQ_HANDLED;
+-}
+-#endif /* CONFIG_SMP */
+-
+-/*
+- * Linux descriptor level callbacks
+- */
+-
+-
+-static void mpic_enable_irq(unsigned int irq)
+-{
+- unsigned int loops = 100000;
+- struct mpic *mpic = mpic_from_irq(irq);
+- unsigned int src = irq - mpic->irq_offset;
+-
+- DBG("%s: enable_irq: %d (src %d)\n", mpic->name, irq, src);
+-
+- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+- mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & ~MPIC_VECPRI_MASK);
+-
+- /* make sure mask gets to controller before we return to user */
+- do {
+- if (!loops--) {
+- printk(KERN_ERR "mpic_enable_irq timeout\n");
+- break;
+- }
+- } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
+-}
+-
+-static void mpic_disable_irq(unsigned int irq)
+-{
+- unsigned int loops = 100000;
+- struct mpic *mpic = mpic_from_irq(irq);
+- unsigned int src = irq - mpic->irq_offset;
+-
+- DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
+-
+- mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+- mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | MPIC_VECPRI_MASK);
+-
+- /* make sure mask gets to controller before we return to user */
+- do {
+- if (!loops--) {
+- printk(KERN_ERR "mpic_enable_irq timeout\n");
+- break;
+- }
+- } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+-}
+-
+-static void mpic_end_irq(unsigned int irq)
+-{
+- struct mpic *mpic = mpic_from_irq(irq);
+-
+- DBG("%s: end_irq: %d\n", mpic->name, irq);
+-
+- /* We always EOI on end_irq() even for edge interrupts since that
+- * should only lower the priority, the MPIC should have properly
+- * latched another edge interrupt coming in anyway
+- */
+-
+-#ifdef CONFIG_MPIC_BROKEN_U3
+- if (mpic->flags & MPIC_BROKEN_U3) {
+- unsigned int src = irq - mpic->irq_offset;
+- if (mpic_is_ht_interrupt(mpic, src))
+- mpic_apic_end_irq(mpic, src);
+- }
+-#endif /* CONFIG_MPIC_BROKEN_U3 */
+-
+- mpic_eoi(mpic);
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-static void mpic_enable_ipi(unsigned int irq)
+-{
+- struct mpic *mpic = mpic_from_ipi(irq);
+- unsigned int src = irq - mpic->ipi_offset;
+-
+- DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
+- mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
+-}
+-
+-static void mpic_disable_ipi(unsigned int irq)
+-{
+- /* NEVER disable an IPI... that's just plain wrong! */
+-}
+-
+-static void mpic_end_ipi(unsigned int irq)
+-{
+- struct mpic *mpic = mpic_from_ipi(irq);
+-
+- /*
+- * IPIs are marked IRQ_PER_CPU. This has the side effect of
+- * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
+- * applying to them. We EOI them late to avoid re-entering.
+- * We mark IPI's with SA_INTERRUPT as they must run with
+- * irqs disabled.
+- */
+- mpic_eoi(mpic);
+-}
+-
+-#endif /* CONFIG_SMP */
+-
+-static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+-{
+- struct mpic *mpic = mpic_from_irq(irq);
+-
+- cpumask_t tmp;
+-
+- cpus_and(tmp, cpumask, cpu_online_map);
+-
+- mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
+- mpic_physmask(cpus_addr(tmp)[0]));
+-}
+-
+-
+-/*
+- * Exported functions
+- */
+-
+-
+-struct mpic * __init mpic_alloc(unsigned long phys_addr,
+- unsigned int flags,
+- unsigned int isu_size,
+- unsigned int irq_offset,
+- unsigned int irq_count,
+- unsigned int ipi_offset,
+- unsigned char *senses,
+- unsigned int senses_count,
+- const char *name)
+-{
+- struct mpic *mpic;
+- u32 reg;
+- const char *vers;
+- int i;
+-
+- mpic = alloc_bootmem(sizeof(struct mpic));
+- if (mpic == NULL)
+- return NULL;
+-
+- memset(mpic, 0, sizeof(struct mpic));
+- mpic->name = name;
+-
+- mpic->hc_irq.typename = name;
+- mpic->hc_irq.enable = mpic_enable_irq;
+- mpic->hc_irq.disable = mpic_disable_irq;
+- mpic->hc_irq.end = mpic_end_irq;
+- if (flags & MPIC_PRIMARY)
+- mpic->hc_irq.set_affinity = mpic_set_affinity;
+-#ifdef CONFIG_SMP
+- mpic->hc_ipi.typename = name;
+- mpic->hc_ipi.enable = mpic_enable_ipi;
+- mpic->hc_ipi.disable = mpic_disable_ipi;
+- mpic->hc_ipi.end = mpic_end_ipi;
+-#endif /* CONFIG_SMP */
+-
+- mpic->flags = flags;
+- mpic->isu_size = isu_size;
+- mpic->irq_offset = irq_offset;
+- mpic->irq_count = irq_count;
+- mpic->ipi_offset = ipi_offset;
+- mpic->num_sources = 0; /* so far */
+- mpic->senses = senses;
+- mpic->senses_count = senses_count;
+-
+- /* Map the global registers */
+- mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x2000);
+- mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
+- BUG_ON(mpic->gregs == NULL);
+-
+- /* Reset */
+- if (flags & MPIC_WANTS_RESET) {
+- mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+- mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+- | MPIC_GREG_GCONF_RESET);
+- while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+- & MPIC_GREG_GCONF_RESET)
+- mb();
+- }
+-
+- /* Read feature register, calculate num CPUs and, for non-ISU
+- * MPICs, num sources as well. On ISU MPICs, sources are counted
+- * as ISUs are added
+- */
+- reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+- mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+- >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
+- if (isu_size == 0)
+- mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+- >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+-
+- /* Map the per-CPU registers */
+- for (i = 0; i < mpic->num_cpus; i++) {
+- mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
+- i * MPIC_CPU_STRIDE, 0x1000);
+- BUG_ON(mpic->cpuregs[i] == NULL);
+- }
+-
+- /* Initialize main ISU if none provided */
+- if (mpic->isu_size == 0) {
+- mpic->isu_size = mpic->num_sources;
+- mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
+- MPIC_IRQ_STRIDE * mpic->isu_size);
+- BUG_ON(mpic->isus[0] == NULL);
+- }
+- mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
+- mpic->isu_mask = (1 << mpic->isu_shift) - 1;
+-
+- /* Display version */
+- switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
+- case 1:
+- vers = "1.0";
+- break;
+- case 2:
+- vers = "1.2";
+- break;
+- case 3:
+- vers = "1.3";
+- break;
+- default:
+- vers = "<unknown>";
+- break;
+- }
+- printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n",
+- name, vers, phys_addr, mpic->num_cpus);
+- printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size,
+- mpic->isu_shift, mpic->isu_mask);
+-
+- mpic->next = mpics;
+- mpics = mpic;
+-
+- if (flags & MPIC_PRIMARY)
+- mpic_primary = mpic;
+-
+- return mpic;
+-}
+-
+-void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+- unsigned long phys_addr)
+-{
+- unsigned int isu_first = isu_num * mpic->isu_size;
+-
+- BUG_ON(isu_num >= MPIC_MAX_ISU);
+-
+- mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
+- if ((isu_first + mpic->isu_size) > mpic->num_sources)
+- mpic->num_sources = isu_first + mpic->isu_size;
+-}
+-
+-void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
+- void *data)
+-{
+- struct mpic *mpic = mpic_find(irq, NULL);
+- unsigned long flags;
+-
+- /* Synchronization here is a bit dodgy, so don't try to replace cascade
+- * interrupts on the fly too often ... but normally it's set up at boot.
+- */
+- spin_lock_irqsave(&mpic_lock, flags);
+- if (mpic->cascade)
+- mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
+- mpic->cascade = NULL;
+- wmb();
+- mpic->cascade_vec = irq - mpic->irq_offset;
+- mpic->cascade_data = data;
+- wmb();
+- mpic->cascade = handler;
+- mpic_enable_irq(irq);
+- spin_unlock_irqrestore(&mpic_lock, flags);
+-}
+-
+-void __init mpic_init(struct mpic *mpic)
+-{
+- int i;
+-
+- BUG_ON(mpic->num_sources == 0);
+-
+- printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
+-
+- /* Set current processor priority to max */
+- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+-
+- /* Initialize timers: just disable them all */
+- for (i = 0; i < 4; i++) {
+- mpic_write(mpic->tmregs,
+- i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+- mpic_write(mpic->tmregs,
+- i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+- MPIC_VECPRI_MASK |
+- (MPIC_VEC_TIMER_0 + i));
+- }
+-
+- /* Initialize IPIs to our reserved vectors and mark them disabled for now */
+- mpic_test_broken_ipi(mpic);
+- for (i = 0; i < 4; i++) {
+- mpic_ipi_write(i,
+- MPIC_VECPRI_MASK |
+- (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
+- (MPIC_VEC_IPI_0 + i));
+-#ifdef CONFIG_SMP
+- if (!(mpic->flags & MPIC_PRIMARY))
+- continue;
+- irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
+- irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi;
+-
+-#endif /* CONFIG_SMP */
+- }
+-
+- /* Initialize interrupt sources */
+- if (mpic->irq_count == 0)
+- mpic->irq_count = mpic->num_sources;
+-
+-#ifdef CONFIG_MPIC_BROKEN_U3
+- /* Do the ioapic fixups on U3 broken mpic */
+- DBG("MPIC flags: %x\n", mpic->flags);
+- if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
+- mpic_scan_ioapics(mpic);
+-#endif /* CONFIG_MPIC_BROKEN_U3 */
+-
+- for (i = 0; i < mpic->num_sources; i++) {
+- /* start with vector = source number, and masked */
+- u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
+- int level = 0;
+-
+- /* if it's an IPI, we skip it */
+- if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
+- (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4))
+- continue;
+-
+- /* do senses munging */
+- if (mpic->senses && i < mpic->senses_count) {
+- if (mpic->senses[i] & IRQ_SENSE_LEVEL)
+- vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+- if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
+- vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+- } else
+- vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+-
+- /* remember if it was a level interrupts */
+- level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
+-
+- /* deal with broken U3 */
+- if (mpic->flags & MPIC_BROKEN_U3) {
+-#ifdef CONFIG_MPIC_BROKEN_U3
+- if (mpic_is_ht_interrupt(mpic, i)) {
+- vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
+- MPIC_VECPRI_POLARITY_MASK);
+- vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+- }
+-#else
+- printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n");
+-#endif
+- }
+-
+- DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
+- (level != 0));
+-
+- /* init hw */
+- mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
+- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+- 1 << get_hard_smp_processor_id(boot_cpuid));
+-
+- /* init linux descriptors */
+- if (i < mpic->irq_count) {
+- irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0;
+- irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq;
+- }
+- }
+-
+- /* Init spurrious vector */
+- mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+-
+- /* Disable 8259 passthrough */
+- mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+- mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+- | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+-
+- /* Set current processor priority to 0 */
+- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+-}
+-
+-
+-
+-void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+-{
+- int is_ipi;
+- struct mpic *mpic = mpic_find(irq, &is_ipi);
+- unsigned long flags;
+- u32 reg;
+-
+- spin_lock_irqsave(&mpic_lock, flags);
+- if (is_ipi) {
+- reg = mpic_ipi_read(irq - mpic->ipi_offset) & MPIC_VECPRI_PRIORITY_MASK;
+- mpic_ipi_write(irq - mpic->ipi_offset,
+- reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+- } else {
+- reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI)
+- & MPIC_VECPRI_PRIORITY_MASK;
+- mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
+- reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+- }
+- spin_unlock_irqrestore(&mpic_lock, flags);
+-}
+-
+-unsigned int mpic_irq_get_priority(unsigned int irq)
+-{
+- int is_ipi;
+- struct mpic *mpic = mpic_find(irq, &is_ipi);
+- unsigned long flags;
+- u32 reg;
+-
+- spin_lock_irqsave(&mpic_lock, flags);
+- if (is_ipi)
+- reg = mpic_ipi_read(irq - mpic->ipi_offset);
+- else
+- reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI);
+- spin_unlock_irqrestore(&mpic_lock, flags);
+- return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
+-}
+-
+-void mpic_setup_this_cpu(void)
+-{
+-#ifdef CONFIG_SMP
+- struct mpic *mpic = mpic_primary;
+- unsigned long flags;
+- u32 msk = 1 << hard_smp_processor_id();
+- unsigned int i;
+-
+- BUG_ON(mpic == NULL);
+-
+- DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+-
+- spin_lock_irqsave(&mpic_lock, flags);
+-
+- /* let the mpic know we want intrs. default affinity is 0xffffffff
+- * until changed via /proc. That's how it's done on x86. If we want
+- * it differently, then we should make sure we also change the default
+- * values of irq_affinity in irq.c.
+- */
+- if (distribute_irqs) {
+- for (i = 0; i < mpic->num_sources ; i++)
+- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+- mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+- }
+-
+- /* Set current processor priority to 0 */
+- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+-
+- spin_unlock_irqrestore(&mpic_lock, flags);
+-#endif /* CONFIG_SMP */
+-}
+-
+-/*
+- * XXX: someone who knows mpic should check this.
+- * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
+- * or can we reset the mpic in the new kernel?
+- */
+-void mpic_teardown_this_cpu(int secondary)
+-{
+- struct mpic *mpic = mpic_primary;
+- unsigned long flags;
+- u32 msk = 1 << hard_smp_processor_id();
+- unsigned int i;
+-
+- BUG_ON(mpic == NULL);
+-
+- DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+- spin_lock_irqsave(&mpic_lock, flags);
+-
+- /* let the mpic know we don't want intrs. */
+- for (i = 0; i < mpic->num_sources ; i++)
+- mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+- mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+-
+- /* Set current processor priority to max */
+- mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+-
+- spin_unlock_irqrestore(&mpic_lock, flags);
+-}
+-
+-
+-void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
+-{
+- struct mpic *mpic = mpic_primary;
+-
+- BUG_ON(mpic == NULL);
+-
+- DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
+-
+- mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+- mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
+-}
+-
+-int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
+-{
+- u32 irq;
+-
+- irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+- DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
+-
+- if (mpic->cascade && irq == mpic->cascade_vec) {
+- DBG("%s: cascading ...\n", mpic->name);
+- irq = mpic->cascade(regs, mpic->cascade_data);
+- mpic_eoi(mpic);
+- return irq;
+- }
+- if (unlikely(irq == MPIC_VEC_SPURRIOUS))
+- return -1;
+- if (irq < MPIC_VEC_IPI_0)
+- return irq + mpic->irq_offset;
+- DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
+- return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
+-}
+-
+-int mpic_get_irq(struct pt_regs *regs)
+-{
+- struct mpic *mpic = mpic_primary;
+-
+- BUG_ON(mpic == NULL);
+-
+- return mpic_get_one_irq(mpic, regs);
+-}
+-
+-
+-#ifdef CONFIG_SMP
+-void mpic_request_ipis(void)
+-{
+- struct mpic *mpic = mpic_primary;
+-
+- BUG_ON(mpic == NULL);
+-
+- printk("requesting IPIs ... \n");
+-
+- /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+- request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
+- "IPI0 (call function)", mpic);
+- request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
+- "IPI1 (reschedule)", mpic);
+- request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
+- "IPI2 (unused)", mpic);
+- request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
+- "IPI3 (debugger break)", mpic);
+-
+- printk("IPIs requested... \n");
+-}
+-#endif /* CONFIG_SMP */
+diff --git a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h
+deleted file mode 100644
+--- a/arch/ppc64/kernel/mpic.h
++++ /dev/null
+@@ -1,273 +0,0 @@
+-#include <linux/irq.h>
+-
+-/*
+- * Global registers
+- */
+-
+-#define MPIC_GREG_BASE 0x01000
+-
+-#define MPIC_GREG_FEATURE_0 0x00000
+-#define MPIC_GREG_FEATURE_LAST_SRC_MASK 0x07ff0000
+-#define MPIC_GREG_FEATURE_LAST_SRC_SHIFT 16
+-#define MPIC_GREG_FEATURE_LAST_CPU_MASK 0x00001f00
+-#define MPIC_GREG_FEATURE_LAST_CPU_SHIFT 8
+-#define MPIC_GREG_FEATURE_VERSION_MASK 0xff
+-#define MPIC_GREG_FEATURE_1 0x00010
+-#define MPIC_GREG_GLOBAL_CONF_0 0x00020
+-#define MPIC_GREG_GCONF_RESET 0x80000000
+-#define MPIC_GREG_GCONF_8259_PTHROU_DIS 0x20000000
+-#define MPIC_GREG_GCONF_BASE_MASK 0x000fffff
+-#define MPIC_GREG_GLOBAL_CONF_1 0x00030
+-#define MPIC_GREG_VENDOR_0 0x00040
+-#define MPIC_GREG_VENDOR_1 0x00050
+-#define MPIC_GREG_VENDOR_2 0x00060
+-#define MPIC_GREG_VENDOR_3 0x00070
+-#define MPIC_GREG_VENDOR_ID 0x00080
+-#define MPIC_GREG_VENDOR_ID_STEPPING_MASK 0x00ff0000
+-#define MPIC_GREG_VENDOR_ID_STEPPING_SHIFT 16
+-#define MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
+-#define MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT 8
+-#define MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
+-#define MPIC_GREG_PROCESSOR_INIT 0x00090
+-#define MPIC_GREG_IPI_VECTOR_PRI_0 0x000a0
+-#define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0
+-#define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0
+-#define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0
+-#define MPIC_GREG_SPURIOUS 0x000e0
+-#define MPIC_GREG_TIMER_FREQ 0x000f0
+-
+-/*
+- *
+- * Timer registers
+- */
+-#define MPIC_TIMER_BASE 0x01100
+-#define MPIC_TIMER_STRIDE 0x40
+-
+-#define MPIC_TIMER_CURRENT_CNT 0x00000
+-#define MPIC_TIMER_BASE_CNT 0x00010
+-#define MPIC_TIMER_VECTOR_PRI 0x00020
+-#define MPIC_TIMER_DESTINATION 0x00030
+-
+-/*
+- * Per-Processor registers
+- */
+-
+-#define MPIC_CPU_THISBASE 0x00000
+-#define MPIC_CPU_BASE 0x20000
+-#define MPIC_CPU_STRIDE 0x01000
+-
+-#define MPIC_CPU_IPI_DISPATCH_0 0x00040
+-#define MPIC_CPU_IPI_DISPATCH_1 0x00050
+-#define MPIC_CPU_IPI_DISPATCH_2 0x00060
+-#define MPIC_CPU_IPI_DISPATCH_3 0x00070
+-#define MPIC_CPU_CURRENT_TASK_PRI 0x00080
+-#define MPIC_CPU_TASKPRI_MASK 0x0000000f
+-#define MPIC_CPU_WHOAMI 0x00090
+-#define MPIC_CPU_WHOAMI_MASK 0x0000001f
+-#define MPIC_CPU_INTACK 0x000a0
+-#define MPIC_CPU_EOI 0x000b0
+-
+-/*
+- * Per-source registers
+- */
+-
+-#define MPIC_IRQ_BASE 0x10000
+-#define MPIC_IRQ_STRIDE 0x00020
+-#define MPIC_IRQ_VECTOR_PRI 0x00000
+-#define MPIC_VECPRI_MASK 0x80000000
+-#define MPIC_VECPRI_ACTIVITY 0x40000000 /* Read Only */
+-#define MPIC_VECPRI_PRIORITY_MASK 0x000f0000
+-#define MPIC_VECPRI_PRIORITY_SHIFT 16
+-#define MPIC_VECPRI_VECTOR_MASK 0x000007ff
+-#define MPIC_VECPRI_POLARITY_POSITIVE 0x00800000
+-#define MPIC_VECPRI_POLARITY_NEGATIVE 0x00000000
+-#define MPIC_VECPRI_POLARITY_MASK 0x00800000
+-#define MPIC_VECPRI_SENSE_LEVEL 0x00400000
+-#define MPIC_VECPRI_SENSE_EDGE 0x00000000
+-#define MPIC_VECPRI_SENSE_MASK 0x00400000
+-#define MPIC_IRQ_DESTINATION 0x00010
+-
+-#define MPIC_MAX_IRQ_SOURCES 2048
+-#define MPIC_MAX_CPUS 32
+-#define MPIC_MAX_ISU 32
+-
+-/*
+- * Special vector numbers (internal use only)
+- */
+-#define MPIC_VEC_SPURRIOUS 255
+-#define MPIC_VEC_IPI_3 254
+-#define MPIC_VEC_IPI_2 253
+-#define MPIC_VEC_IPI_1 252
+-#define MPIC_VEC_IPI_0 251
+-
+-/* unused */
+-#define MPIC_VEC_TIMER_3 250
+-#define MPIC_VEC_TIMER_2 249
+-#define MPIC_VEC_TIMER_1 248
+-#define MPIC_VEC_TIMER_0 247
+-
+-/* Type definition of the cascade handler */
+-typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
+-
+-#ifdef CONFIG_MPIC_BROKEN_U3
+-/* Fixup table entry */
+-struct mpic_irq_fixup
+-{
+- u8 __iomem *base;
+- unsigned int irq;
+-};
+-#endif /* CONFIG_MPIC_BROKEN_U3 */
+-
+-
+-/* The instance data of a given MPIC */
+-struct mpic
+-{
+- /* The "linux" controller struct */
+- hw_irq_controller hc_irq;
+-#ifdef CONFIG_SMP
+- hw_irq_controller hc_ipi;
+-#endif
+- const char *name;
+- /* Flags */
+- unsigned int flags;
+- /* How many irq sources in a given ISU */
+- unsigned int isu_size;
+- unsigned int isu_shift;
+- unsigned int isu_mask;
+- /* Offset of irq vector numbers */
+- unsigned int irq_offset;
+- unsigned int irq_count;
+- /* Offset of ipi vector numbers */
+- unsigned int ipi_offset;
+- /* Number of sources */
+- unsigned int num_sources;
+- /* Number of CPUs */
+- unsigned int num_cpus;
+- /* cascade handler */
+- mpic_cascade_t cascade;
+- void *cascade_data;
+- unsigned int cascade_vec;
+- /* senses array */
+- unsigned char *senses;
+- unsigned int senses_count;
+-
+-#ifdef CONFIG_MPIC_BROKEN_U3
+- /* The fixup table */
+- struct mpic_irq_fixup *fixups;
+- spinlock_t fixup_lock;
+-#endif
+-
+- /* The various ioremap'ed bases */
+- volatile u32 __iomem *gregs;
+- volatile u32 __iomem *tmregs;
+- volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS];
+- volatile u32 __iomem *isus[MPIC_MAX_ISU];
+-
+- /* link */
+- struct mpic *next;
+-};
+-
+-/* This is the primary controller, only that one has IPIs and
+- * has afinity control. A non-primary MPIC always uses CPU0
+- * registers only
+- */
+-#define MPIC_PRIMARY 0x00000001
+-/* Set this for a big-endian MPIC */
+-#define MPIC_BIG_ENDIAN 0x00000002
+-/* Broken U3 MPIC */
+-#define MPIC_BROKEN_U3 0x00000004
+-/* Broken IPI registers (autodetected) */
+-#define MPIC_BROKEN_IPI 0x00000008
+-/* MPIC wants a reset */
+-#define MPIC_WANTS_RESET 0x00000010
+-
+-/* Allocate the controller structure and setup the linux irq descs
+- * for the range if interrupts passed in. No HW initialization is
+- * actually performed.
+- *
+- * @phys_addr: physial base address of the MPIC
+- * @flags: flags, see constants above
+- * @isu_size: number of interrupts in an ISU. Use 0 to use a
+- * standard ISU-less setup (aka powermac)
+- * @irq_offset: first irq number to assign to this mpic
+- * @irq_count: number of irqs to use with this mpic IRQ sources. Pass 0
+- * to match the number of sources
+- * @ipi_offset: first irq number to assign to this mpic IPI sources,
+- * used only on primary mpic
+- * @senses: array of sense values
+- * @senses_num: number of entries in the array
+- *
+- * Note about the sense array. If none is passed, all interrupts are
+- * setup to be level negative unless MPIC_BROKEN_U3 is set in which
+- * case they are edge positive (and the array is ignored anyway).
+- * The values in the array start at the first source of the MPIC,
+- * that is senses[0] correspond to linux irq "irq_offset".
+- */
+-extern struct mpic *mpic_alloc(unsigned long phys_addr,
+- unsigned int flags,
+- unsigned int isu_size,
+- unsigned int irq_offset,
+- unsigned int irq_count,
+- unsigned int ipi_offset,
+- unsigned char *senses,
+- unsigned int senses_num,
+- const char *name);
+-
+-/* Assign ISUs, to call before mpic_init()
+- *
+- * @mpic: controller structure as returned by mpic_alloc()
+- * @isu_num: ISU number
+- * @phys_addr: physical address of the ISU
+- */
+-extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+- unsigned long phys_addr);
+-
+-/* Initialize the controller. After this has been called, none of the above
+- * should be called again for this mpic
+- */
+-extern void mpic_init(struct mpic *mpic);
+-
+-/* Setup a cascade. Currently, only one cascade is supported this
+- * way, though you can always do a normal request_irq() and add
+- * other cascades this way. You should call this _after_ having
+- * added all the ISUs
+- *
+- * @irq_no: "linux" irq number of the cascade (that is offset'ed vector)
+- * @handler: cascade handler function
+- */
+-extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
+- void *data);
+-
+-/*
+- * All of the following functions must only be used after the
+- * ISUs have been assigned and the controller fully initialized
+- * with mpic_init()
+- */
+-
+-
+-/* Change/Read the priority of an interrupt. Default is 8 for irqs and
+- * 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the
+- * IPI number is then the offset'ed (linux irq number mapped to the IPI)
+- */
+-extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri);
+-extern unsigned int mpic_irq_get_priority(unsigned int irq);
+-
+-/* Setup a non-boot CPU */
+-extern void mpic_setup_this_cpu(void);
+-
+-/* Clean up for kexec (or cpu offline or ...) */
+-extern void mpic_teardown_this_cpu(int secondary);
+-
+-/* Request IPIs on primary mpic */
+-extern void mpic_request_ipis(void);
+-
+-/* Send an IPI (non offseted number 0..3) */
+-extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
+-
+-/* Fetch interrupt from a given mpic */
+-extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
+-/* This one gets to the primary mpic */
+-extern int mpic_get_irq(struct pt_regs *regs);
+-
+-/* global mpic for pSeries */
+-extern struct mpic *pSeries_mpic;
+diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/of_device.c
++++ /dev/null
+@@ -1,274 +0,0 @@
+-#include <linux/config.h>
+-#include <linux/string.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/mod_devicetable.h>
+-#include <asm/errno.h>
+-#include <asm/of_device.h>
+-
+-/**
+- * of_match_device - Tell if an of_device structure has a matching
+- * of_match structure
+- * @ids: array of of device match structures to search in
+- * @dev: the of device structure to match against
+- *
+- * Used by a driver to check whether an of_device present in the
+- * system is in its list of supported devices.
+- */
+-const struct of_device_id *of_match_device(const struct of_device_id *matches,
+- const struct of_device *dev)
+-{
+- if (!dev->node)
+- return NULL;
+- while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+- int match = 1;
+- if (matches->name[0])
+- match &= dev->node->name
+- && !strcmp(matches->name, dev->node->name);
+- if (matches->type[0])
+- match &= dev->node->type
+- && !strcmp(matches->type, dev->node->type);
+- if (matches->compatible[0])
+- match &= device_is_compatible(dev->node,
+- matches->compatible);
+- if (match)
+- return matches;
+- matches++;
+- }
+- return NULL;
+-}
+-
+-static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+- const struct of_device_id * matches = of_drv->match_table;
+-
+- if (!matches)
+- return 0;
+-
+- return of_match_device(matches, of_dev) != NULL;
+-}
+-
+-struct of_device *of_dev_get(struct of_device *dev)
+-{
+- struct device *tmp;
+-
+- if (!dev)
+- return NULL;
+- tmp = get_device(&dev->dev);
+- if (tmp)
+- return to_of_device(tmp);
+- else
+- return NULL;
+-}
+-
+-void of_dev_put(struct of_device *dev)
+-{
+- if (dev)
+- put_device(&dev->dev);
+-}
+-
+-
+-static int of_device_probe(struct device *dev)
+-{
+- int error = -ENODEV;
+- struct of_platform_driver *drv;
+- struct of_device *of_dev;
+- const struct of_device_id *match;
+-
+- drv = to_of_platform_driver(dev->driver);
+- of_dev = to_of_device(dev);
+-
+- if (!drv->probe)
+- return error;
+-
+- of_dev_get(of_dev);
+-
+- match = of_match_device(drv->match_table, of_dev);
+- if (match)
+- error = drv->probe(of_dev, match);
+- if (error)
+- of_dev_put(of_dev);
+-
+- return error;
+-}
+-
+-static int of_device_remove(struct device *dev)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+-
+- if (dev->driver && drv->remove)
+- drv->remove(of_dev);
+- return 0;
+-}
+-
+-static int of_device_suspend(struct device *dev, pm_message_t state)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+- int error = 0;
+-
+- if (dev->driver && drv->suspend)
+- error = drv->suspend(of_dev, state);
+- return error;
+-}
+-
+-static int of_device_resume(struct device * dev)
+-{
+- struct of_device * of_dev = to_of_device(dev);
+- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+- int error = 0;
+-
+- if (dev->driver && drv->resume)
+- error = drv->resume(of_dev);
+- return error;
+-}
+-
+-struct bus_type of_platform_bus_type = {
+- .name = "of_platform",
+- .match = of_platform_bus_match,
+- .suspend = of_device_suspend,
+- .resume = of_device_resume,
+-};
+-
+-static int __init of_bus_driver_init(void)
+-{
+- return bus_register(&of_platform_bus_type);
+-}
+-
+-postcore_initcall(of_bus_driver_init);
+-
+-int of_register_driver(struct of_platform_driver *drv)
+-{
+- int count = 0;
+-
+- /* initialize common driver fields */
+- drv->driver.name = drv->name;
+- drv->driver.bus = &of_platform_bus_type;
+- drv->driver.probe = of_device_probe;
+- drv->driver.remove = of_device_remove;
+-
+- /* register with core */
+- count = driver_register(&drv->driver);
+- return count ? count : 1;
+-}
+-
+-void of_unregister_driver(struct of_platform_driver *drv)
+-{
+- driver_unregister(&drv->driver);
+-}
+-
+-
+-static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct of_device *ofdev;
+-
+- ofdev = to_of_device(dev);
+- return sprintf(buf, "%s", ofdev->node->full_name);
+-}
+-
+-static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+-
+-/**
+- * of_release_dev - free an of device structure when all users of it are finished.
+- * @dev: device that's been disconnected
+- *
+- * Will be called only by the device core when all users of this of device are
+- * done.
+- */
+-void of_release_dev(struct device *dev)
+-{
+- struct of_device *ofdev;
+-
+- ofdev = to_of_device(dev);
+- kfree(ofdev);
+-}
+-
+-int of_device_register(struct of_device *ofdev)
+-{
+- int rc;
+- struct of_device **odprop;
+-
+- BUG_ON(ofdev->node == NULL);
+-
+- odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
+- if (!odprop) {
+- struct property *new_prop;
+-
+- new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
+- GFP_KERNEL);
+- if (new_prop == NULL)
+- return -ENOMEM;
+- new_prop->name = "linux,device";
+- new_prop->length = sizeof(sizeof(struct of_device *));
+- new_prop->value = (unsigned char *)&new_prop[1];
+- odprop = (struct of_device **)new_prop->value;
+- *odprop = NULL;
+- prom_add_property(ofdev->node, new_prop);
+- }
+- *odprop = ofdev;
+-
+- rc = device_register(&ofdev->dev);
+- if (rc)
+- return rc;
+-
+- device_create_file(&ofdev->dev, &dev_attr_devspec);
+-
+- return 0;
+-}
+-
+-void of_device_unregister(struct of_device *ofdev)
+-{
+- struct of_device **odprop;
+-
+- device_remove_file(&ofdev->dev, &dev_attr_devspec);
+-
+- odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
+- if (odprop)
+- *odprop = NULL;
+-
+- device_unregister(&ofdev->dev);
+-}
+-
+-struct of_device* of_platform_device_create(struct device_node *np,
+- const char *bus_id,
+- struct device *parent)
+-{
+- struct of_device *dev;
+-
+- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+- if (!dev)
+- return NULL;
+- memset(dev, 0, sizeof(*dev));
+-
+- dev->node = np;
+- dev->dma_mask = 0xffffffffUL;
+- dev->dev.dma_mask = &dev->dma_mask;
+- dev->dev.parent = parent;
+- dev->dev.bus = &of_platform_bus_type;
+- dev->dev.release = of_release_dev;
+-
+- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+-
+- if (of_device_register(dev) != 0) {
+- kfree(dev);
+- return NULL;
+- }
+-
+- return dev;
+-}
+-
+-
+-EXPORT_SYMBOL(of_match_device);
+-EXPORT_SYMBOL(of_platform_bus_type);
+-EXPORT_SYMBOL(of_register_driver);
+-EXPORT_SYMBOL(of_unregister_driver);
+-EXPORT_SYMBOL(of_device_register);
+-EXPORT_SYMBOL(of_device_unregister);
+-EXPORT_SYMBOL(of_dev_get);
+-EXPORT_SYMBOL(of_dev_put);
+-EXPORT_SYMBOL(of_platform_device_create);
+-EXPORT_SYMBOL(of_release_dev);
+diff --git a/arch/ppc64/kernel/pSeries_hvCall.S b/arch/ppc64/kernel/pSeries_hvCall.S
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_hvCall.S
++++ /dev/null
+@@ -1,131 +0,0 @@
+-/*
+- * arch/ppc64/kernel/pSeries_hvCall.S
+- *
+- * This file contains the generic code to perform a call to the
+- * pSeries LPAR hypervisor.
+- * NOTE: this file will go away when we move to inline this work.
+- *
+- * 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 <asm/hvcall.h>
+-#include <asm/processor.h>
+-#include <asm/ppc_asm.h>
+-
+-#define STK_PARM(i) (48 + ((i)-3)*8)
+-
+- .text
+-
+-/* long plpar_hcall(unsigned long opcode, R3
+- unsigned long arg1, R4
+- unsigned long arg2, R5
+- unsigned long arg3, R6
+- unsigned long arg4, R7
+- unsigned long *out1, R8
+- unsigned long *out2, R9
+- unsigned long *out3); R10
+- */
+-_GLOBAL(plpar_hcall)
+- HMT_MEDIUM
+-
+- mfcr r0
+-
+- std r8,STK_PARM(r8)(r1) /* Save out ptrs */
+- std r9,STK_PARM(r9)(r1)
+- std r10,STK_PARM(r10)(r1)
+-
+- stw r0,8(r1)
+-
+- HVSC /* invoke the hypervisor */
+-
+- lwz r0,8(r1)
+-
+- ld r8,STK_PARM(r8)(r1) /* Fetch r4-r6 ret args */
+- ld r9,STK_PARM(r9)(r1)
+- ld r10,STK_PARM(r10)(r1)
+- std r4,0(r8)
+- std r5,0(r9)
+- std r6,0(r10)
+-
+- mtcrf 0xff,r0
+- blr /* return r3 = status */
+-
+-
+-/* Simple interface with no output values (other than status) */
+-_GLOBAL(plpar_hcall_norets)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HVSC /* invoke the hypervisor */
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+- blr /* return r3 = status */
+-
+-
+-/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3
+- unsigned long arg1, R4
+- unsigned long arg2, R5
+- unsigned long arg3, R6
+- unsigned long arg4, R7
+- unsigned long arg5, R8
+- unsigned long arg6, R9
+- unsigned long arg7, R10
+- unsigned long arg8, 112(R1)
+- unsigned long *out1); 120(R1)
+- */
+-_GLOBAL(plpar_hcall_8arg_2ret)
+- HMT_MEDIUM
+-
+- mfcr r0
+- ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
+- stw r0,8(r1)
+-
+- HVSC /* invoke the hypervisor */
+-
+- lwz r0,8(r1)
+- ld r10,STK_PARM(r12)(r1) /* Fetch r4 ret arg */
+- std r4,0(r10)
+- mtcrf 0xff,r0
+- blr /* return r3 = status */
+-
+-
+-/* long plpar_hcall_4out(unsigned long opcode, R3
+- unsigned long arg1, R4
+- unsigned long arg2, R5
+- unsigned long arg3, R6
+- unsigned long arg4, R7
+- unsigned long *out1, R8
+- unsigned long *out2, R9
+- unsigned long *out3, R10
+- unsigned long *out4); 112(R1)
+- */
+-_GLOBAL(plpar_hcall_4out)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- std r8,STK_PARM(r8)(r1) /* Save out ptrs */
+- std r9,STK_PARM(r9)(r1)
+- std r10,STK_PARM(r10)(r1)
+-
+- HVSC /* invoke the hypervisor */
+-
+- lwz r0,8(r1)
+-
+- ld r8,STK_PARM(r8)(r1) /* Fetch r4-r7 ret args */
+- ld r9,STK_PARM(r9)(r1)
+- ld r10,STK_PARM(r10)(r1)
+- ld r11,STK_PARM(r11)(r1)
+- std r4,0(r8)
+- std r5,0(r9)
+- std r6,0(r10)
+- std r7,0(r11)
+-
+- mtcrf 0xff,r0
+- blr /* return r3 = status */
+diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_iommu.c
++++ /dev/null
+@@ -1,590 +0,0 @@
+-/*
+- * arch/ppc64/kernel/pSeries_iommu.c
+- *
+- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+- *
+- * Rewrite, cleanup:
+- *
+- * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
+- *
+- * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
+- *
+- *
+- * 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/init.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/mm.h>
+-#include <linux/spinlock.h>
+-#include <linux/string.h>
+-#include <linux/pci.h>
+-#include <linux/dma-mapping.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/rtas.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/iommu.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/machdep.h>
+-#include <asm/abs_addr.h>
+-#include <asm/plpar_wrappers.h>
+-#include <asm/pSeries_reconfig.h>
+-#include <asm/systemcfg.h>
+-#include <asm/firmware.h>
+-#include "pci.h"
+-
+-#define DBG(fmt...)
+-
+-extern int is_python(struct device_node *);
+-
+-static void tce_build_pSeries(struct iommu_table *tbl, long index,
+- long npages, unsigned long uaddr,
+- enum dma_data_direction direction)
+-{
+- union tce_entry t;
+- union tce_entry *tp;
+-
+- t.te_word = 0;
+- t.te_rdwr = 1; // Read allowed
+-
+- if (direction != DMA_TO_DEVICE)
+- t.te_pciwr = 1;
+-
+- tp = ((union tce_entry *)tbl->it_base) + index;
+-
+- while (npages--) {
+- /* can't move this out since we might cross LMB boundary */
+- t.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+-
+- tp->te_word = t.te_word;
+-
+- uaddr += PAGE_SIZE;
+- tp++;
+- }
+-}
+-
+-
+-static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
+-{
+- union tce_entry t;
+- union tce_entry *tp;
+-
+- t.te_word = 0;
+- tp = ((union tce_entry *)tbl->it_base) + index;
+-
+- while (npages--) {
+- tp->te_word = t.te_word;
+-
+- tp++;
+- }
+-}
+-
+-
+-static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
+- long npages, unsigned long uaddr,
+- enum dma_data_direction direction)
+-{
+- u64 rc;
+- union tce_entry tce;
+-
+- tce.te_word = 0;
+- tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+- tce.te_rdwr = 1;
+- if (direction != DMA_TO_DEVICE)
+- tce.te_pciwr = 1;
+-
+- while (npages--) {
+- rc = plpar_tce_put((u64)tbl->it_index,
+- (u64)tcenum << 12,
+- tce.te_word );
+-
+- if (rc && printk_ratelimit()) {
+- printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
+- printk("\ttcenum = 0x%lx\n", (u64)tcenum);
+- printk("\ttce val = 0x%lx\n", tce.te_word );
+- show_stack(current, (unsigned long *)__get_SP());
+- }
+-
+- tcenum++;
+- tce.te_rpn++;
+- }
+-}
+-
+-static DEFINE_PER_CPU(void *, tce_page) = NULL;
+-
+-static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+- long npages, unsigned long uaddr,
+- enum dma_data_direction direction)
+-{
+- u64 rc;
+- union tce_entry tce, *tcep;
+- long l, limit;
+-
+- if (npages == 1)
+- return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+- direction);
+-
+- tcep = __get_cpu_var(tce_page);
+-
+- /* This is safe to do since interrupts are off when we're called
+- * from iommu_alloc{,_sg}()
+- */
+- if (!tcep) {
+- tcep = (void *)__get_free_page(GFP_ATOMIC);
+- /* If allocation fails, fall back to the loop implementation */
+- if (!tcep)
+- return tce_build_pSeriesLP(tbl, tcenum, npages,
+- uaddr, direction);
+- __get_cpu_var(tce_page) = tcep;
+- }
+-
+- tce.te_word = 0;
+- tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+- tce.te_rdwr = 1;
+- if (direction != DMA_TO_DEVICE)
+- tce.te_pciwr = 1;
+-
+- /* We can map max one pageful of TCEs at a time */
+- do {
+- /*
+- * Set up the page with TCE data, looping through and setting
+- * the values.
+- */
+- limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry));
+-
+- for (l = 0; l < limit; l++) {
+- tcep[l] = tce;
+- tce.te_rpn++;
+- }
+-
+- rc = plpar_tce_put_indirect((u64)tbl->it_index,
+- (u64)tcenum << 12,
+- (u64)virt_to_abs(tcep),
+- limit);
+-
+- npages -= limit;
+- tcenum += limit;
+- } while (npages > 0 && !rc);
+-
+- if (rc && printk_ratelimit()) {
+- printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
+- printk("\tnpages = 0x%lx\n", (u64)npages);
+- printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
+- show_stack(current, (unsigned long *)__get_SP());
+- }
+-}
+-
+-static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+-{
+- u64 rc;
+- union tce_entry tce;
+-
+- tce.te_word = 0;
+-
+- while (npages--) {
+- rc = plpar_tce_put((u64)tbl->it_index,
+- (u64)tcenum << 12,
+- tce.te_word);
+-
+- if (rc && printk_ratelimit()) {
+- printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
+- printk("\ttcenum = 0x%lx\n", (u64)tcenum);
+- printk("\ttce val = 0x%lx\n", tce.te_word );
+- show_stack(current, (unsigned long *)__get_SP());
+- }
+-
+- tcenum++;
+- }
+-}
+-
+-
+-static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+-{
+- u64 rc;
+- union tce_entry tce;
+-
+- tce.te_word = 0;
+-
+- rc = plpar_tce_stuff((u64)tbl->it_index,
+- (u64)tcenum << 12,
+- tce.te_word,
+- npages);
+-
+- if (rc && printk_ratelimit()) {
+- printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
+- printk("\trc = %ld\n", rc);
+- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
+- printk("\tnpages = 0x%lx\n", (u64)npages);
+- printk("\ttce val = 0x%lx\n", tce.te_word );
+- show_stack(current, (unsigned long *)__get_SP());
+- }
+-}
+-
+-static void iommu_table_setparms(struct pci_controller *phb,
+- struct device_node *dn,
+- struct iommu_table *tbl)
+-{
+- struct device_node *node;
+- unsigned long *basep;
+- unsigned int *sizep;
+-
+- node = (struct device_node *)phb->arch_data;
+-
+- basep = (unsigned long *)get_property(node, "linux,tce-base", NULL);
+- sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL);
+- if (basep == NULL || sizep == NULL) {
+- printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has "
+- "missing tce entries !\n", dn->full_name);
+- return;
+- }
+-
+- tbl->it_base = (unsigned long)__va(*basep);
+- memset((void *)tbl->it_base, 0, *sizep);
+-
+- tbl->it_busno = phb->bus->number;
+-
+- /* Units of tce entries */
+- tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
+-
+- /* Test if we are going over 2GB of DMA space */
+- if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
+- udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
+- panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
+- }
+-
+- phb->dma_window_base_cur += phb->dma_window_size;
+-
+- /* Set the tce table size - measured in entries */
+- tbl->it_size = phb->dma_window_size >> PAGE_SHIFT;
+-
+- tbl->it_index = 0;
+- tbl->it_blocksize = 16;
+- tbl->it_type = TCE_PCI;
+-}
+-
+-/*
+- * iommu_table_setparms_lpar
+- *
+- * Function: On pSeries LPAR systems, return TCE table info, given a pci bus.
+- *
+- * ToDo: properly interpret the ibm,dma-window property. The definition is:
+- * logical-bus-number (1 word)
+- * phys-address (#address-cells words)
+- * size (#cell-size words)
+- *
+- * Currently we hard code these sizes (more or less).
+- */
+-static void iommu_table_setparms_lpar(struct pci_controller *phb,
+- struct device_node *dn,
+- struct iommu_table *tbl,
+- unsigned int *dma_window)
+-{
+- tbl->it_busno = PCI_DN(dn)->bussubno;
+-
+- /* TODO: Parse field size properties properly. */
+- tbl->it_size = (((unsigned long)dma_window[4] << 32) |
+- (unsigned long)dma_window[5]) >> PAGE_SHIFT;
+- tbl->it_offset = (((unsigned long)dma_window[2] << 32) |
+- (unsigned long)dma_window[3]) >> PAGE_SHIFT;
+- tbl->it_base = 0;
+- tbl->it_index = dma_window[0];
+- tbl->it_blocksize = 16;
+- tbl->it_type = TCE_PCI;
+-}
+-
+-static void iommu_bus_setup_pSeries(struct pci_bus *bus)
+-{
+- struct device_node *dn;
+- struct iommu_table *tbl;
+- struct device_node *isa_dn, *isa_dn_orig;
+- struct device_node *tmp;
+- struct pci_dn *pci;
+- int children;
+-
+- DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
+-
+- dn = pci_bus_to_OF_node(bus);
+- pci = PCI_DN(dn);
+-
+- if (bus->self) {
+- /* This is not a root bus, any setup will be done for the
+- * device-side of the bridge in iommu_dev_setup_pSeries().
+- */
+- return;
+- }
+-
+- /* Check if the ISA bus on the system is under
+- * this PHB.
+- */
+- isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa");
+-
+- while (isa_dn && isa_dn != dn)
+- isa_dn = isa_dn->parent;
+-
+- if (isa_dn_orig)
+- of_node_put(isa_dn_orig);
+-
+- /* Count number of direct PCI children of the PHB.
+- * All PCI device nodes have class-code property, so it's
+- * an easy way to find them.
+- */
+- for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
+- if (get_property(tmp, "class-code", NULL))
+- children++;
+-
+- DBG("Children: %d\n", children);
+-
+- /* Calculate amount of DMA window per slot. Each window must be
+- * a power of two (due to pci_alloc_consistent requirements).
+- *
+- * Keep 256MB aside for PHBs with ISA.
+- */
+-
+- if (!isa_dn) {
+- /* No ISA/IDE - just set window size and return */
+- pci->phb->dma_window_size = 0x80000000ul; /* To be divided */
+-
+- while (pci->phb->dma_window_size * children > 0x80000000ul)
+- pci->phb->dma_window_size >>= 1;
+- DBG("No ISA/IDE, window size is 0x%lx\n",
+- pci->phb->dma_window_size);
+- pci->phb->dma_window_base_cur = 0;
+-
+- return;
+- }
+-
+- /* If we have ISA, then we probably have an IDE
+- * controller too. Allocate a 128MB table but
+- * skip the first 128MB to avoid stepping on ISA
+- * space.
+- */
+- pci->phb->dma_window_size = 0x8000000ul;
+- pci->phb->dma_window_base_cur = 0x8000000ul;
+-
+- tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+-
+- iommu_table_setparms(pci->phb, dn, tbl);
+- pci->iommu_table = iommu_init_table(tbl);
+-
+- /* Divide the rest (1.75GB) among the children */
+- pci->phb->dma_window_size = 0x80000000ul;
+- while (pci->phb->dma_window_size * children > 0x70000000ul)
+- pci->phb->dma_window_size >>= 1;
+-
+- DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
+-
+-}
+-
+-
+-static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
+-{
+- struct iommu_table *tbl;
+- struct device_node *dn, *pdn;
+- struct pci_dn *ppci;
+- unsigned int *dma_window = NULL;
+-
+- DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
+-
+- dn = pci_bus_to_OF_node(bus);
+-
+- /* Find nearest ibm,dma-window, walking up the device tree */
+- for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
+- dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
+- if (dma_window != NULL)
+- break;
+- }
+-
+- if (dma_window == NULL) {
+- DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name);
+- return;
+- }
+-
+- ppci = pdn->data;
+- if (!ppci->iommu_table) {
+- /* Bussubno hasn't been copied yet.
+- * Do it now because iommu_table_setparms_lpar needs it.
+- */
+-
+- ppci->bussubno = bus->number;
+-
+- tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
+- GFP_KERNEL);
+-
+- iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
+-
+- ppci->iommu_table = iommu_init_table(tbl);
+- }
+-
+- if (pdn != dn)
+- PCI_DN(dn)->iommu_table = ppci->iommu_table;
+-}
+-
+-
+-static void iommu_dev_setup_pSeries(struct pci_dev *dev)
+-{
+- struct device_node *dn, *mydn;
+- struct iommu_table *tbl;
+-
+- DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev));
+-
+- mydn = dn = pci_device_to_OF_node(dev);
+-
+- /* If we're the direct child of a root bus, then we need to allocate
+- * an iommu table ourselves. The bus setup code should have setup
+- * the window sizes already.
+- */
+- if (!dev->bus->self) {
+- DBG(" --> first child, no bridge. Allocating iommu table.\n");
+- tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+- iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl);
+- PCI_DN(mydn)->iommu_table = iommu_init_table(tbl);
+-
+- return;
+- }
+-
+- /* If this device is further down the bus tree, search upwards until
+- * an already allocated iommu table is found and use that.
+- */
+-
+- while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
+- dn = dn->parent;
+-
+- if (dn && dn->data) {
+- PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
+- } else {
+- DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev));
+- }
+-}
+-
+-static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
+-{
+- int err = NOTIFY_OK;
+- struct device_node *np = node;
+- struct pci_dn *pci = np->data;
+-
+- switch (action) {
+- case PSERIES_RECONFIG_REMOVE:
+- if (pci->iommu_table &&
+- get_property(np, "ibm,dma-window", NULL))
+- iommu_free_table(np);
+- break;
+- default:
+- err = NOTIFY_DONE;
+- break;
+- }
+- return err;
+-}
+-
+-static struct notifier_block iommu_reconfig_nb = {
+- .notifier_call = iommu_reconfig_notifier,
+-};
+-
+-static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
+-{
+- struct device_node *pdn, *dn;
+- struct iommu_table *tbl;
+- int *dma_window = NULL;
+- struct pci_dn *pci;
+-
+- DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev));
+-
+- /* dev setup for LPAR is a little tricky, since the device tree might
+- * contain the dma-window properties per-device and not neccesarily
+- * for the bus. So we need to search upwards in the tree until we
+- * either hit a dma-window property, OR find a parent with a table
+- * already allocated.
+- */
+- dn = pci_device_to_OF_node(dev);
+-
+- for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table;
+- pdn = pdn->parent) {
+- dma_window = (unsigned int *)
+- get_property(pdn, "ibm,dma-window", NULL);
+- if (dma_window)
+- break;
+- }
+-
+- /* Check for parent == NULL so we don't try to setup the empty EADS
+- * slots on POWER4 machines.
+- */
+- if (dma_window == NULL || pdn->parent == NULL) {
+- DBG("No dma window for device, linking to parent\n");
+- PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table;
+- return;
+- } else {
+- DBG("Found DMA window, allocating table\n");
+- }
+-
+- pci = pdn->data;
+- if (!pci->iommu_table) {
+- /* iommu_table_setparms_lpar needs bussubno. */
+- pci->bussubno = pci->phb->bus->number;
+-
+- tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
+- GFP_KERNEL);
+-
+- iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
+-
+- pci->iommu_table = iommu_init_table(tbl);
+- }
+-
+- if (pdn != dn)
+- PCI_DN(dn)->iommu_table = pci->iommu_table;
+-}
+-
+-static void iommu_bus_setup_null(struct pci_bus *b) { }
+-static void iommu_dev_setup_null(struct pci_dev *d) { }
+-
+-/* These are called very early. */
+-void iommu_init_early_pSeries(void)
+-{
+- if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) {
+- /* Direct I/O, IOMMU off */
+- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+- ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+- pci_direct_iommu_init();
+-
+- return;
+- }
+-
+- if (systemcfg->platform & PLATFORM_LPAR) {
+- if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
+- ppc_md.tce_build = tce_buildmulti_pSeriesLP;
+- ppc_md.tce_free = tce_freemulti_pSeriesLP;
+- } else {
+- ppc_md.tce_build = tce_build_pSeriesLP;
+- ppc_md.tce_free = tce_free_pSeriesLP;
+- }
+- ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP;
+- ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP;
+- } else {
+- ppc_md.tce_build = tce_build_pSeries;
+- ppc_md.tce_free = tce_free_pSeries;
+- ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries;
+- ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
+- }
+-
+-
+- pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
+-
+- pci_iommu_init();
+-}
+-
+diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_lpar.c
++++ /dev/null
+@@ -1,518 +0,0 @@
+-/*
+- * pSeries_lpar.c
+- * Copyright (C) 2001 Todd Inglett, IBM Corporation
+- *
+- * pSeries LPAR support.
+- *
+- * 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 DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/dma-mapping.h>
+-#include <asm/processor.h>
+-#include <asm/mmu.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/machdep.h>
+-#include <asm/abs_addr.h>
+-#include <asm/mmu_context.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/iommu.h>
+-#include <asm/tlbflush.h>
+-#include <asm/tlb.h>
+-#include <asm/prom.h>
+-#include <asm/abs_addr.h>
+-#include <asm/cputable.h>
+-#include <asm/plpar_wrappers.h>
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/* in pSeries_hvCall.S */
+-EXPORT_SYMBOL(plpar_hcall);
+-EXPORT_SYMBOL(plpar_hcall_4out);
+-EXPORT_SYMBOL(plpar_hcall_norets);
+-EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
+-
+-extern void pSeries_find_serial_port(void);
+-
+-
+-int vtermno; /* virtual terminal# for udbg */
+-
+-#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
+-static void udbg_hvsi_putc(unsigned char c)
+-{
+- /* packet's seqno isn't used anyways */
+- uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
+- int rc;
+-
+- if (c == '\n')
+- udbg_hvsi_putc('\r');
+-
+- do {
+- rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
+- } while (rc == H_Busy);
+-}
+-
+-static long hvsi_udbg_buf_len;
+-static uint8_t hvsi_udbg_buf[256];
+-
+-static int udbg_hvsi_getc_poll(void)
+-{
+- unsigned char ch;
+- int rc, i;
+-
+- if (hvsi_udbg_buf_len == 0) {
+- rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
+- if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
+- /* bad read or non-data packet */
+- hvsi_udbg_buf_len = 0;
+- } else {
+- /* remove the packet header */
+- for (i = 4; i < hvsi_udbg_buf_len; i++)
+- hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
+- hvsi_udbg_buf_len -= 4;
+- }
+- }
+-
+- if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
+- /* no data ready */
+- hvsi_udbg_buf_len = 0;
+- return -1;
+- }
+-
+- ch = hvsi_udbg_buf[0];
+- /* shift remaining data down */
+- for (i = 1; i < hvsi_udbg_buf_len; i++) {
+- hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
+- }
+- hvsi_udbg_buf_len--;
+-
+- return ch;
+-}
+-
+-static unsigned char udbg_hvsi_getc(void)
+-{
+- int ch;
+- for (;;) {
+- ch = udbg_hvsi_getc_poll();
+- if (ch == -1) {
+- /* This shouldn't be needed...but... */
+- volatile unsigned long delay;
+- for (delay=0; delay < 2000000; delay++)
+- ;
+- } else {
+- return ch;
+- }
+- }
+-}
+-
+-static void udbg_putcLP(unsigned char c)
+-{
+- char buf[16];
+- unsigned long rc;
+-
+- if (c == '\n')
+- udbg_putcLP('\r');
+-
+- buf[0] = c;
+- do {
+- rc = plpar_put_term_char(vtermno, 1, buf);
+- } while(rc == H_Busy);
+-}
+-
+-/* Buffered chars getc */
+-static long inbuflen;
+-static long inbuf[2]; /* must be 2 longs */
+-
+-static int udbg_getc_pollLP(void)
+-{
+- /* The interface is tricky because it may return up to 16 chars.
+- * We save them statically for future calls to udbg_getc().
+- */
+- char ch, *buf = (char *)inbuf;
+- int i;
+- long rc;
+- if (inbuflen == 0) {
+- /* get some more chars. */
+- inbuflen = 0;
+- rc = plpar_get_term_char(vtermno, &inbuflen, buf);
+- if (rc != H_Success)
+- inbuflen = 0; /* otherwise inbuflen is garbage */
+- }
+- if (inbuflen <= 0 || inbuflen > 16) {
+- /* Catch error case as well as other oddities (corruption) */
+- inbuflen = 0;
+- return -1;
+- }
+- ch = buf[0];
+- for (i = 1; i < inbuflen; i++) /* shuffle them down. */
+- buf[i-1] = buf[i];
+- inbuflen--;
+- return ch;
+-}
+-
+-static unsigned char udbg_getcLP(void)
+-{
+- int ch;
+- for (;;) {
+- ch = udbg_getc_pollLP();
+- if (ch == -1) {
+- /* This shouldn't be needed...but... */
+- volatile unsigned long delay;
+- for (delay=0; delay < 2000000; delay++)
+- ;
+- } else {
+- return ch;
+- }
+- }
+-}
+-
+-/* call this from early_init() for a working debug console on
+- * vterm capable LPAR machines
+- */
+-void udbg_init_debug_lpar(void)
+-{
+- vtermno = 0;
+- udbg_putc = udbg_putcLP;
+- udbg_getc = udbg_getcLP;
+- udbg_getc_poll = udbg_getc_pollLP;
+-}
+-
+-/* returns 0 if couldn't find or use /chosen/stdout as console */
+-int find_udbg_vterm(void)
+-{
+- struct device_node *stdout_node;
+- u32 *termno;
+- char *name;
+- int found = 0;
+-
+- /* find the boot console from /chosen/stdout */
+- if (!of_chosen)
+- return 0;
+- name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+- if (name == NULL)
+- return 0;
+- stdout_node = of_find_node_by_path(name);
+- if (!stdout_node)
+- return 0;
+-
+- /* now we have the stdout node; figure out what type of device it is. */
+- name = (char *)get_property(stdout_node, "name", NULL);
+- if (!name) {
+- printk(KERN_WARNING "stdout node missing 'name' property!\n");
+- goto out;
+- }
+-
+- if (strncmp(name, "vty", 3) == 0) {
+- if (device_is_compatible(stdout_node, "hvterm1")) {
+- termno = (u32 *)get_property(stdout_node, "reg", NULL);
+- if (termno) {
+- vtermno = termno[0];
+- udbg_putc = udbg_putcLP;
+- udbg_getc = udbg_getcLP;
+- udbg_getc_poll = udbg_getc_pollLP;
+- found = 1;
+- }
+- } else if (device_is_compatible(stdout_node, "hvterm-protocol")) {
+- termno = (u32 *)get_property(stdout_node, "reg", NULL);
+- if (termno) {
+- vtermno = termno[0];
+- udbg_putc = udbg_hvsi_putc;
+- udbg_getc = udbg_hvsi_getc;
+- udbg_getc_poll = udbg_hvsi_getc_poll;
+- found = 1;
+- }
+- }
+- } else if (strncmp(name, "serial", 6)) {
+- /* XXX fix ISA serial console */
+- printk(KERN_WARNING "serial stdout on LPAR ('%s')! "
+- "can't print udbg messages\n",
+- stdout_node->full_name);
+- } else {
+- printk(KERN_WARNING "don't know how to print to stdout '%s'\n",
+- stdout_node->full_name);
+- }
+-
+-out:
+- of_node_put(stdout_node);
+- return found;
+-}
+-
+-void vpa_init(int cpu)
+-{
+- int hwcpu = get_hard_smp_processor_id(cpu);
+- unsigned long vpa = (unsigned long)&(paca[cpu].lppaca);
+- long ret;
+- unsigned long flags;
+-
+- /* Register the Virtual Processor Area (VPA) */
+- flags = 1UL << (63 - 18);
+-
+- if (cpu_has_feature(CPU_FTR_ALTIVEC))
+- paca[cpu].lppaca.vmxregs_in_use = 1;
+-
+- ret = register_vpa(flags, hwcpu, __pa(vpa));
+-
+- if (ret)
+- printk(KERN_ERR "WARNING: vpa_init: VPA registration for "
+- "cpu %d (hw %d) of area %lx returns %ld\n",
+- cpu, hwcpu, __pa(vpa), ret);
+-}
+-
+-long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+- unsigned long va, unsigned long prpn,
+- unsigned long vflags, unsigned long rflags)
+-{
+- unsigned long lpar_rc;
+- unsigned long flags;
+- unsigned long slot;
+- unsigned long hpte_v, hpte_r;
+- unsigned long dummy0, dummy1;
+-
+- hpte_v = ((va >> 23) << HPTE_V_AVPN_SHIFT) | vflags | HPTE_V_VALID;
+- if (vflags & HPTE_V_LARGE)
+- hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT);
+-
+- hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
+-
+- /* Now fill in the actual HPTE */
+- /* Set CEC cookie to 0 */
+- /* Zero page = 0 */
+- /* I-cache Invalidate = 0 */
+- /* I-cache synchronize = 0 */
+- /* Exact = 0 */
+- flags = 0;
+-
+- /* XXX why is this here? - Anton */
+- if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+- hpte_r &= ~_PAGE_COHERENT;
+-
+- lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
+- hpte_r, &slot, &dummy0, &dummy1);
+-
+- if (unlikely(lpar_rc == H_PTEG_Full))
+- return -1;
+-
+- /*
+- * Since we try and ioremap PHBs we don't own, the pte insert
+- * will fail. However we must catch the failure in hash_page
+- * or we will loop forever, so return -2 in this case.
+- */
+- if (unlikely(lpar_rc != H_Success))
+- return -2;
+-
+- /* Because of iSeries, we have to pass down the secondary
+- * bucket bit here as well
+- */
+- return (slot & 7) | (!!(vflags & HPTE_V_SECONDARY) << 3);
+-}
+-
+-static DEFINE_SPINLOCK(pSeries_lpar_tlbie_lock);
+-
+-static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
+-{
+- unsigned long slot_offset;
+- unsigned long lpar_rc;
+- int i;
+- unsigned long dummy1, dummy2;
+-
+- /* pick a random slot to start at */
+- slot_offset = mftb() & 0x7;
+-
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+-
+- /* don't remove a bolted entry */
+- lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,
+- (0x1UL << 4), &dummy1, &dummy2);
+-
+- if (lpar_rc == H_Success)
+- return i;
+-
+- BUG_ON(lpar_rc != H_Not_Found);
+-
+- slot_offset++;
+- slot_offset &= 0x7;
+- }
+-
+- return -1;
+-}
+-
+-static void pSeries_lpar_hptab_clear(void)
+-{
+- unsigned long size_bytes = 1UL << ppc64_pft_size;
+- unsigned long hpte_count = size_bytes >> 4;
+- unsigned long dummy1, dummy2;
+- int i;
+-
+- /* TODO: Use bulk call */
+- for (i = 0; i < hpte_count; i++)
+- plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
+-}
+-
+-/*
+- * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+- * the low 3 bits of flags happen to line up. So no transform is needed.
+- * We can probably optimize here and assume the high bits of newpp are
+- * already zero. For now I am paranoid.
+- */
+-static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
+- unsigned long va, int large, int local)
+-{
+- unsigned long lpar_rc;
+- unsigned long flags = (newpp & 7) | H_AVPN;
+- unsigned long avpn = va >> 23;
+-
+- if (large)
+- avpn &= ~0x1UL;
+-
+- lpar_rc = plpar_pte_protect(flags, slot, (avpn << 7));
+-
+- if (lpar_rc == H_Not_Found)
+- return -1;
+-
+- BUG_ON(lpar_rc != H_Success);
+-
+- return 0;
+-}
+-
+-static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
+-{
+- unsigned long dword0;
+- unsigned long lpar_rc;
+- unsigned long dummy_word1;
+- unsigned long flags;
+-
+- /* Read 1 pte at a time */
+- /* Do not need RPN to logical page translation */
+- /* No cross CEC PFT access */
+- flags = 0;
+-
+- lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
+-
+- BUG_ON(lpar_rc != H_Success);
+-
+- return dword0;
+-}
+-
+-static long pSeries_lpar_hpte_find(unsigned long vpn)
+-{
+- unsigned long hash;
+- unsigned long i, j;
+- long slot;
+- unsigned long hpte_v;
+-
+- hash = hpt_hash(vpn, 0);
+-
+- for (j = 0; j < 2; j++) {
+- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+- hpte_v = pSeries_lpar_hpte_getword0(slot);
+-
+- if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11))
+- && (hpte_v & HPTE_V_VALID)
+- && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
+- /* HPTE matches */
+- if (j)
+- slot = -slot;
+- return slot;
+- }
+- ++slot;
+- }
+- hash = ~hash;
+- }
+-
+- return -1;
+-}
+-
+-static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
+- unsigned long ea)
+-{
+- unsigned long lpar_rc;
+- unsigned long vsid, va, vpn, flags;
+- long slot;
+-
+- vsid = get_kernel_vsid(ea);
+- va = (vsid << 28) | (ea & 0x0fffffff);
+- vpn = va >> PAGE_SHIFT;
+-
+- slot = pSeries_lpar_hpte_find(vpn);
+- BUG_ON(slot == -1);
+-
+- flags = newpp & 7;
+- lpar_rc = plpar_pte_protect(flags, slot, 0);
+-
+- BUG_ON(lpar_rc != H_Success);
+-}
+-
+-static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+- int large, int local)
+-{
+- unsigned long avpn = va >> 23;
+- unsigned long lpar_rc;
+- unsigned long dummy1, dummy2;
+-
+- if (large)
+- avpn &= ~0x1UL;
+-
+- lpar_rc = plpar_pte_remove(H_AVPN, slot, (avpn << 7), &dummy1,
+- &dummy2);
+-
+- if (lpar_rc == H_Not_Found)
+- return;
+-
+- BUG_ON(lpar_rc != H_Success);
+-}
+-
+-/*
+- * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
+- * lock.
+- */
+-void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
+- int local)
+-{
+- int i;
+- unsigned long flags = 0;
+- struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+- int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
+-
+- if (lock_tlbie)
+- spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
+-
+- for (i = 0; i < number; i++)
+- flush_hash_page(context, batch->addr[i], batch->pte[i], local);
+-
+- if (lock_tlbie)
+- spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
+-}
+-
+-void hpte_init_lpar(void)
+-{
+- ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate;
+- ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp;
+- ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
+- ppc_md.hpte_insert = pSeries_lpar_hpte_insert;
+- ppc_md.hpte_remove = pSeries_lpar_hpte_remove;
+- ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
+- ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear;
+-
+- htab_finish_init();
+-}
+diff --git a/arch/ppc64/kernel/pSeries_nvram.c b/arch/ppc64/kernel/pSeries_nvram.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_nvram.c
++++ /dev/null
+@@ -1,148 +0,0 @@
+-/*
+- * c 2001 PPC 64 Team, IBM Corp
+- *
+- * 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.
+- *
+- * /dev/nvram driver for PPC64
+- *
+- * This perhaps should live in drivers/char
+- */
+-
+-
+-#include <linux/types.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/spinlock.h>
+-#include <asm/uaccess.h>
+-#include <asm/nvram.h>
+-#include <asm/rtas.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-
+-static unsigned int nvram_size;
+-static int nvram_fetch, nvram_store;
+-static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
+-static DEFINE_SPINLOCK(nvram_lock);
+-
+-
+-static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
+-{
+- unsigned int i;
+- unsigned long len;
+- int done;
+- unsigned long flags;
+- char *p = buf;
+-
+-
+- if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE)
+- return -ENODEV;
+-
+- if (*index >= nvram_size)
+- return 0;
+-
+- i = *index;
+- if (i + count > nvram_size)
+- count = nvram_size - i;
+-
+- spin_lock_irqsave(&nvram_lock, flags);
+-
+- for (; count != 0; count -= len) {
+- len = count;
+- if (len > NVRW_CNT)
+- len = NVRW_CNT;
+-
+- if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf),
+- len) != 0) || len != done) {
+- spin_unlock_irqrestore(&nvram_lock, flags);
+- return -EIO;
+- }
+-
+- memcpy(p, nvram_buf, len);
+-
+- p += len;
+- i += len;
+- }
+-
+- spin_unlock_irqrestore(&nvram_lock, flags);
+-
+- *index = i;
+- return p - buf;
+-}
+-
+-static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index)
+-{
+- unsigned int i;
+- unsigned long len;
+- int done;
+- unsigned long flags;
+- const char *p = buf;
+-
+- if (nvram_size == 0 || nvram_store == RTAS_UNKNOWN_SERVICE)
+- return -ENODEV;
+-
+- if (*index >= nvram_size)
+- return 0;
+-
+- i = *index;
+- if (i + count > nvram_size)
+- count = nvram_size - i;
+-
+- spin_lock_irqsave(&nvram_lock, flags);
+-
+- for (; count != 0; count -= len) {
+- len = count;
+- if (len > NVRW_CNT)
+- len = NVRW_CNT;
+-
+- memcpy(nvram_buf, p, len);
+-
+- if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf),
+- len) != 0) || len != done) {
+- spin_unlock_irqrestore(&nvram_lock, flags);
+- return -EIO;
+- }
+-
+- p += len;
+- i += len;
+- }
+- spin_unlock_irqrestore(&nvram_lock, flags);
+-
+- *index = i;
+- return p - buf;
+-}
+-
+-static ssize_t pSeries_nvram_get_size(void)
+-{
+- return nvram_size ? nvram_size : -ENODEV;
+-}
+-
+-int __init pSeries_nvram_init(void)
+-{
+- struct device_node *nvram;
+- unsigned int *nbytes_p, proplen;
+-
+- nvram = of_find_node_by_type(NULL, "nvram");
+- if (nvram == NULL)
+- return -ENODEV;
+-
+- nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
+- if (nbytes_p == NULL || proplen != sizeof(unsigned int))
+- return -EIO;
+-
+- nvram_size = *nbytes_p;
+-
+- nvram_fetch = rtas_token("nvram-fetch");
+- nvram_store = rtas_token("nvram-store");
+- printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size);
+- of_node_put(nvram);
+-
+- ppc_md.nvram_read = pSeries_nvram_read;
+- ppc_md.nvram_write = pSeries_nvram_write;
+- ppc_md.nvram_size = pSeries_nvram_get_size;
+-
+- return 0;
+-}
+diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_pci.c
++++ /dev/null
+@@ -1,143 +0,0 @@
+-/*
+- * arch/ppc64/kernel/pSeries_pci.c
+- *
+- * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
+- * Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * pSeries specific routines for PCI.
+- *
+- * 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/ioport.h>
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-
+-#include <asm/pci-bridge.h>
+-#include <asm/prom.h>
+-
+-#include "pci.h"
+-
+-static int __devinitdata s7a_workaround = -1;
+-
+-#if 0
+-void pcibios_name_device(struct pci_dev *dev)
+-{
+- struct device_node *dn;
+-
+- /*
+- * Add IBM loc code (slot) as a prefix to the device names for service
+- */
+- dn = pci_device_to_OF_node(dev);
+- if (dn) {
+- char *loc_code = get_property(dn, "ibm,loc-code", 0);
+- if (loc_code) {
+- int loc_len = strlen(loc_code);
+- if (loc_len < sizeof(dev->dev.name)) {
+- memmove(dev->dev.name+loc_len+1, dev->dev.name,
+- sizeof(dev->dev.name)-loc_len-1);
+- memcpy(dev->dev.name, loc_code, loc_len);
+- dev->dev.name[loc_len] = ' ';
+- dev->dev.name[sizeof(dev->dev.name)-1] = '\0';
+- }
+- }
+- }
+-}
+-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
+-#endif
+-
+-static void __devinit check_s7a(void)
+-{
+- struct device_node *root;
+- char *model;
+-
+- s7a_workaround = 0;
+- root = of_find_node_by_path("/");
+- if (root) {
+- model = get_property(root, "model", NULL);
+- if (model && !strcmp(model, "IBM,7013-S7A"))
+- s7a_workaround = 1;
+- of_node_put(root);
+- }
+-}
+-
+-void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
+-{
+- struct pci_dev *dev;
+-
+- if (s7a_workaround < 0)
+- check_s7a();
+- list_for_each_entry(dev, &bus->devices, bus_list) {
+- pci_read_irq_line(dev);
+- if (s7a_workaround) {
+- if (dev->irq > 16) {
+- dev->irq -= 3;
+- pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+- dev->irq);
+- }
+- }
+- }
+-}
+-
+-static void __init pSeries_request_regions(void)
+-{
+- if (!isa_io_base)
+- return;
+-
+- request_region(0x20,0x20,"pic1");
+- request_region(0xa0,0x20,"pic2");
+- request_region(0x00,0x20,"dma1");
+- request_region(0x40,0x20,"timer");
+- request_region(0x80,0x10,"dma page reg");
+- request_region(0xc0,0x20,"dma2");
+-}
+-
+-void __init pSeries_final_fixup(void)
+-{
+- phbs_remap_io();
+- pSeries_request_regions();
+-
+- pci_addr_cache_build();
+-}
+-
+-/*
+- * Assume the winbond 82c105 is the IDE controller on a
+- * p610. We should probably be more careful in case
+- * someone tries to plug in a similar adapter.
+- */
+-static void fixup_winbond_82c105(struct pci_dev* dev)
+-{
+- int i;
+- unsigned int reg;
+-
+- if (!(systemcfg->platform & PLATFORM_PSERIES))
+- return;
+-
+- printk("Using INTC for W82c105 IDE controller.\n");
+- pci_read_config_dword(dev, 0x40, ®);
+- /* Enable LEGIRQ to use INTC instead of ISA interrupts */
+- pci_write_config_dword(dev, 0x40, reg | (1<<11));
+-
+- for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) {
+- /* zap the 2nd function of the winbond chip */
+- if (dev->resource[i].flags & IORESOURCE_IO
+- && dev->bus->number == 0 && dev->devfn == 0x81)
+- dev->resource[i].flags &= ~IORESOURCE_IO;
+- }
+-}
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
+- fixup_winbond_82c105);
+diff --git a/arch/ppc64/kernel/pSeries_reconfig.c b/arch/ppc64/kernel/pSeries_reconfig.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_reconfig.c
++++ /dev/null
+@@ -1,426 +0,0 @@
+-/*
+- * pSeries_reconfig.c - support for dynamic reconfiguration (including PCI
+- * Hotplug and Dynamic Logical Partitioning on RPA platforms).
+- *
+- * Copyright (C) 2005 Nathan Lynch
+- * Copyright (C) 2005 IBM 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.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/kref.h>
+-#include <linux/notifier.h>
+-#include <linux/proc_fs.h>
+-
+-#include <asm/prom.h>
+-#include <asm/pSeries_reconfig.h>
+-#include <asm/uaccess.h>
+-
+-
+-
+-/*
+- * Routines for "runtime" addition and removal of device tree nodes.
+- */
+-#ifdef CONFIG_PROC_DEVICETREE
+-/*
+- * Add a node to /proc/device-tree.
+- */
+-static void add_node_proc_entries(struct device_node *np)
+-{
+- struct proc_dir_entry *ent;
+-
+- ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
+- if (ent)
+- proc_device_tree_add_node(np, ent);
+-}
+-
+-static void remove_node_proc_entries(struct device_node *np)
+-{
+- struct property *pp = np->properties;
+- struct device_node *parent = np->parent;
+-
+- while (pp) {
+- remove_proc_entry(pp->name, np->pde);
+- pp = pp->next;
+- }
+- if (np->pde)
+- remove_proc_entry(np->pde->name, parent->pde);
+-}
+-#else /* !CONFIG_PROC_DEVICETREE */
+-static void add_node_proc_entries(struct device_node *np)
+-{
+- return;
+-}
+-
+-static void remove_node_proc_entries(struct device_node *np)
+-{
+- return;
+-}
+-#endif /* CONFIG_PROC_DEVICETREE */
+-
+-/**
+- * derive_parent - basically like dirname(1)
+- * @path: the full_name of a node to be added to the tree
+- *
+- * Returns the node which should be the parent of the node
+- * described by path. E.g., for path = "/foo/bar", returns
+- * the node with full_name = "/foo".
+- */
+-static struct device_node *derive_parent(const char *path)
+-{
+- struct device_node *parent = NULL;
+- char *parent_path = "/";
+- size_t parent_path_len = strrchr(path, '/') - path + 1;
+-
+- /* reject if path is "/" */
+- if (!strcmp(path, "/"))
+- return ERR_PTR(-EINVAL);
+-
+- if (strrchr(path, '/') != path) {
+- parent_path = kmalloc(parent_path_len, GFP_KERNEL);
+- if (!parent_path)
+- return ERR_PTR(-ENOMEM);
+- strlcpy(parent_path, path, parent_path_len);
+- }
+- parent = of_find_node_by_path(parent_path);
+- if (!parent)
+- return ERR_PTR(-EINVAL);
+- if (strcmp(parent_path, "/"))
+- kfree(parent_path);
+- return parent;
+-}
+-
+-static struct notifier_block *pSeries_reconfig_chain;
+-
+-int pSeries_reconfig_notifier_register(struct notifier_block *nb)
+-{
+- return notifier_chain_register(&pSeries_reconfig_chain, nb);
+-}
+-
+-void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
+-{
+- notifier_chain_unregister(&pSeries_reconfig_chain, nb);
+-}
+-
+-static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
+-{
+- struct device_node *np;
+- int err = -ENOMEM;
+-
+- np = kzalloc(sizeof(*np), GFP_KERNEL);
+- if (!np)
+- goto out_err;
+-
+- np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+- if (!np->full_name)
+- goto out_err;
+-
+- strcpy(np->full_name, path);
+-
+- np->properties = proplist;
+- OF_MARK_DYNAMIC(np);
+- kref_init(&np->kref);
+-
+- np->parent = derive_parent(path);
+- if (IS_ERR(np->parent)) {
+- err = PTR_ERR(np->parent);
+- goto out_err;
+- }
+-
+- err = notifier_call_chain(&pSeries_reconfig_chain,
+- PSERIES_RECONFIG_ADD, np);
+- if (err == NOTIFY_BAD) {
+- printk(KERN_ERR "Failed to add device node %s\n", path);
+- err = -ENOMEM; /* For now, safe to assume kmalloc failure */
+- goto out_err;
+- }
+-
+- of_attach_node(np);
+-
+- add_node_proc_entries(np);
+-
+- of_node_put(np->parent);
+-
+- return 0;
+-
+-out_err:
+- if (np) {
+- of_node_put(np->parent);
+- kfree(np->full_name);
+- kfree(np);
+- }
+- return err;
+-}
+-
+-static int pSeries_reconfig_remove_node(struct device_node *np)
+-{
+- struct device_node *parent, *child;
+-
+- parent = of_get_parent(np);
+- if (!parent)
+- return -EINVAL;
+-
+- if ((child = of_get_next_child(np, NULL))) {
+- of_node_put(child);
+- return -EBUSY;
+- }
+-
+- remove_node_proc_entries(np);
+-
+- notifier_call_chain(&pSeries_reconfig_chain,
+- PSERIES_RECONFIG_REMOVE, np);
+- of_detach_node(np);
+-
+- of_node_put(parent);
+- of_node_put(np); /* Must decrement the refcount */
+- return 0;
+-}
+-
+-/*
+- * /proc/ppc64/ofdt - yucky binary interface for adding and removing
+- * OF device nodes. Should be deprecated as soon as we get an
+- * in-kernel wrapper for the RTAS ibm,configure-connector call.
+- */
+-
+-static void release_prop_list(const struct property *prop)
+-{
+- struct property *next;
+- for (; prop; prop = next) {
+- next = prop->next;
+- kfree(prop->name);
+- kfree(prop->value);
+- kfree(prop);
+- }
+-
+-}
+-
+-/**
+- * parse_next_property - process the next property from raw input buffer
+- * @buf: input buffer, must be nul-terminated
+- * @end: end of the input buffer + 1, for validation
+- * @name: return value; set to property name in buf
+- * @length: return value; set to length of value
+- * @value: return value; set to the property value in buf
+- *
+- * Note that the caller must make copies of the name and value returned,
+- * this function does no allocation or copying of the data. Return value
+- * is set to the next name in buf, or NULL on error.
+- */
+-static char * parse_next_property(char *buf, char *end, char **name, int *length,
+- unsigned char **value)
+-{
+- char *tmp;
+-
+- *name = buf;
+-
+- tmp = strchr(buf, ' ');
+- if (!tmp) {
+- printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
+- return NULL;
+- }
+- *tmp = '\0';
+-
+- if (++tmp >= end) {
+- printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
+- return NULL;
+- }
+-
+- /* now we're on the length */
+- *length = -1;
+- *length = simple_strtoul(tmp, &tmp, 10);
+- if (*length == -1) {
+- printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
+- return NULL;
+- }
+- if (*tmp != ' ' || ++tmp >= end) {
+- printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
+- return NULL;
+- }
+-
+- /* now we're on the value */
+- *value = tmp;
+- tmp += *length;
+- if (tmp > end) {
+- printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
+- return NULL;
+- }
+- else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
+- printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
+- return NULL;
+- }
+- tmp++;
+-
+- /* and now we should be on the next name, or the end */
+- return tmp;
+-}
+-
+-static struct property *new_property(const char *name, const int length,
+- const unsigned char *value, struct property *last)
+-{
+- struct property *new = kmalloc(sizeof(*new), GFP_KERNEL);
+-
+- if (!new)
+- return NULL;
+- memset(new, 0, sizeof(*new));
+-
+- if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
+- goto cleanup;
+- if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
+- goto cleanup;
+-
+- strcpy(new->name, name);
+- memcpy(new->value, value, length);
+- *(((char *)new->value) + length) = 0;
+- new->length = length;
+- new->next = last;
+- return new;
+-
+-cleanup:
+- if (new->name)
+- kfree(new->name);
+- if (new->value)
+- kfree(new->value);
+- kfree(new);
+- return NULL;
+-}
+-
+-static int do_add_node(char *buf, size_t bufsize)
+-{
+- char *path, *end, *name;
+- struct device_node *np;
+- struct property *prop = NULL;
+- unsigned char* value;
+- int length, rv = 0;
+-
+- end = buf + bufsize;
+- path = buf;
+- buf = strchr(buf, ' ');
+- if (!buf)
+- return -EINVAL;
+- *buf = '\0';
+- buf++;
+-
+- if ((np = of_find_node_by_path(path))) {
+- of_node_put(np);
+- return -EINVAL;
+- }
+-
+- /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */
+- while (buf < end &&
+- (buf = parse_next_property(buf, end, &name, &length, &value))) {
+- struct property *last = prop;
+-
+- prop = new_property(name, length, value, last);
+- if (!prop) {
+- rv = -ENOMEM;
+- prop = last;
+- goto out;
+- }
+- }
+- if (!buf) {
+- rv = -EINVAL;
+- goto out;
+- }
+-
+- rv = pSeries_reconfig_add_node(path, prop);
+-
+-out:
+- if (rv)
+- release_prop_list(prop);
+- return rv;
+-}
+-
+-static int do_remove_node(char *buf)
+-{
+- struct device_node *node;
+- int rv = -ENODEV;
+-
+- if ((node = of_find_node_by_path(buf)))
+- rv = pSeries_reconfig_remove_node(node);
+-
+- of_node_put(node);
+- return rv;
+-}
+-
+-/**
+- * ofdt_write - perform operations on the Open Firmware device tree
+- *
+- * @file: not used
+- * @buf: command and arguments
+- * @count: size of the command buffer
+- * @off: not used
+- *
+- * Operations supported at this time are addition and removal of
+- * whole nodes along with their properties. Operations on individual
+- * properties are not implemented (yet).
+- */
+-static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count,
+- loff_t *off)
+-{
+- int rv = 0;
+- char *kbuf;
+- char *tmp;
+-
+- if (!(kbuf = kmalloc(count + 1, GFP_KERNEL))) {
+- rv = -ENOMEM;
+- goto out;
+- }
+- if (copy_from_user(kbuf, buf, count)) {
+- rv = -EFAULT;
+- goto out;
+- }
+-
+- kbuf[count] = '\0';
+-
+- tmp = strchr(kbuf, ' ');
+- if (!tmp) {
+- rv = -EINVAL;
+- goto out;
+- }
+- *tmp = '\0';
+- tmp++;
+-
+- if (!strcmp(kbuf, "add_node"))
+- rv = do_add_node(tmp, count - (tmp - kbuf));
+- else if (!strcmp(kbuf, "remove_node"))
+- rv = do_remove_node(tmp);
+- else
+- rv = -EINVAL;
+-out:
+- kfree(kbuf);
+- return rv ? rv : count;
+-}
+-
+-static struct file_operations ofdt_fops = {
+- .write = ofdt_write
+-};
+-
+-/* create /proc/ppc64/ofdt write-only by root */
+-static int proc_ppc64_create_ofdt(void)
+-{
+- struct proc_dir_entry *ent;
+-
+- if (!(systemcfg->platform & PLATFORM_PSERIES))
+- return 0;
+-
+- ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
+- if (ent) {
+- ent->nlink = 1;
+- ent->data = NULL;
+- ent->size = 0;
+- ent->proc_fops = &ofdt_fops;
+- }
+-
+- return 0;
+-}
+-__initcall(proc_ppc64_create_ofdt);
+diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_setup.c
++++ /dev/null
+@@ -1,622 +0,0 @@
+-/*
+- * linux/arch/ppc/kernel/setup.c
+- *
+- * Copyright (C) 1995 Linus Torvalds
+- * Adapted from 'alpha' version by Gary Thomas
+- * Modified by Cort Dougan (cort at cs.nmt.edu)
+- * Modified by PPC64 Team, IBM Corp
+- *
+- * 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.
+- */
+-
+-/*
+- * bootup setup stuff..
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/cpu.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/slab.h>
+-#include <linux/user.h>
+-#include <linux/a.out.h>
+-#include <linux/tty.h>
+-#include <linux/major.h>
+-#include <linux/interrupt.h>
+-#include <linux/reboot.h>
+-#include <linux/init.h>
+-#include <linux/ioport.h>
+-#include <linux/console.h>
+-#include <linux/pci.h>
+-#include <linux/utsname.h>
+-#include <linux/adb.h>
+-#include <linux/module.h>
+-#include <linux/delay.h>
+-#include <linux/irq.h>
+-#include <linux/seq_file.h>
+-#include <linux/root_dev.h>
+-
+-#include <asm/mmu.h>
+-#include <asm/processor.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/prom.h>
+-#include <asm/rtas.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/iommu.h>
+-#include <asm/dma.h>
+-#include <asm/machdep.h>
+-#include <asm/irq.h>
+-#include <asm/time.h>
+-#include <asm/nvram.h>
+-#include <asm/plpar_wrappers.h>
+-#include <asm/xics.h>
+-#include <asm/firmware.h>
+-#include <asm/pmc.h>
+-
+-#include "i8259.h"
+-#include "mpic.h"
+-#include "pci.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-extern void find_udbg_vterm(void);
+-extern void system_reset_fwnmi(void); /* from head.S */
+-extern void machine_check_fwnmi(void); /* from head.S */
+-extern void generic_find_legacy_serial_ports(u64 *physport,
+- unsigned int *default_speed);
+-
+-int fwnmi_active; /* TRUE if an FWNMI handler is present */
+-
+-extern void pSeries_system_reset_exception(struct pt_regs *regs);
+-extern int pSeries_machine_check_exception(struct pt_regs *regs);
+-
+-static int pseries_shared_idle(void);
+-static int pseries_dedicated_idle(void);
+-
+-static volatile void __iomem * chrp_int_ack_special;
+-struct mpic *pSeries_mpic;
+-
+-void pSeries_get_cpuinfo(struct seq_file *m)
+-{
+- struct device_node *root;
+- const char *model = "";
+-
+- root = of_find_node_by_path("/");
+- if (root)
+- model = get_property(root, "model", NULL);
+- seq_printf(m, "machine\t\t: CHRP %s\n", model);
+- of_node_put(root);
+-}
+-
+-/* Initialize firmware assisted non-maskable interrupts if
+- * the firmware supports this feature.
+- *
+- */
+-static void __init fwnmi_init(void)
+-{
+- int ret;
+- int ibm_nmi_register = rtas_token("ibm,nmi-register");
+- if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
+- return;
+- ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
+- __pa((unsigned long)system_reset_fwnmi),
+- __pa((unsigned long)machine_check_fwnmi));
+- if (ret == 0)
+- fwnmi_active = 1;
+-}
+-
+-static int pSeries_irq_cascade(struct pt_regs *regs, void *data)
+-{
+- if (chrp_int_ack_special)
+- return readb(chrp_int_ack_special);
+- else
+- return i8259_irq(smp_processor_id());
+-}
+-
+-static void __init pSeries_init_mpic(void)
+-{
+- unsigned int *addrp;
+- struct device_node *np;
+- int i;
+-
+- /* All ISUs are setup, complete initialization */
+- mpic_init(pSeries_mpic);
+-
+- /* Check what kind of cascade ACK we have */
+- if (!(np = of_find_node_by_name(NULL, "pci"))
+- || !(addrp = (unsigned int *)
+- get_property(np, "8259-interrupt-acknowledge", NULL)))
+- printk(KERN_ERR "Cannot find pci to get ack address\n");
+- else
+- chrp_int_ack_special = ioremap(addrp[prom_n_addr_cells(np)-1], 1);
+- of_node_put(np);
+-
+- /* Setup the legacy interrupts & controller */
+- for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
+- irq_desc[i].handler = &i8259_pic;
+- i8259_init(0);
+-
+- /* Hook cascade to mpic */
+- mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL);
+-}
+-
+-static void __init pSeries_setup_mpic(void)
+-{
+- unsigned int *opprop;
+- unsigned long openpic_addr = 0;
+- unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS];
+- struct device_node *root;
+- int irq_count;
+-
+- /* Find the Open PIC if present */
+- root = of_find_node_by_path("/");
+- opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL);
+- if (opprop != 0) {
+- int n = prom_n_addr_cells(root);
+-
+- for (openpic_addr = 0; n > 0; --n)
+- openpic_addr = (openpic_addr << 32) + *opprop++;
+- printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
+- }
+- of_node_put(root);
+-
+- BUG_ON(openpic_addr == 0);
+-
+- /* Get the sense values from OF */
+- prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
+-
+- /* Setup the openpic driver */
+- irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
+- pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY,
+- 16, 16, irq_count, /* isu size, irq offset, irq count */
+- NR_IRQS - 4, /* ipi offset */
+- senses, irq_count, /* sense & sense size */
+- " MPIC ");
+-}
+-
+-static void pseries_lpar_enable_pmcs(void)
+-{
+- unsigned long set, reset;
+-
+- power4_enable_pmcs();
+-
+- set = 1UL << 63;
+- reset = 0;
+- plpar_hcall_norets(H_PERFMON, set, reset);
+-
+- /* instruct hypervisor to maintain PMCs */
+- if (firmware_has_feature(FW_FEATURE_SPLPAR))
+- get_paca()->lppaca.pmcregs_in_use = 1;
+-}
+-
+-static void __init pSeries_setup_arch(void)
+-{
+- /* Fixup ppc_md depending on the type of interrupt controller */
+- if (ppc64_interrupt_controller == IC_OPEN_PIC) {
+- ppc_md.init_IRQ = pSeries_init_mpic;
+- ppc_md.get_irq = mpic_get_irq;
+- ppc_md.cpu_irq_down = mpic_teardown_this_cpu;
+- /* Allocate the mpic now, so that find_and_init_phbs() can
+- * fill the ISUs */
+- pSeries_setup_mpic();
+- } else {
+- ppc_md.init_IRQ = xics_init_IRQ;
+- ppc_md.get_irq = xics_get_irq;
+- ppc_md.cpu_irq_down = xics_teardown_cpu;
+- }
+-
+-#ifdef CONFIG_SMP
+- smp_init_pSeries();
+-#endif
+- /* openpic global configuration register (64-bit format). */
+- /* openpic Interrupt Source Unit pointer (64-bit format). */
+- /* python0 facility area (mmio) (64-bit format) REAL address. */
+-
+- /* init to some ~sane value until calibrate_delay() runs */
+- loops_per_jiffy = 50000000;
+-
+- if (ROOT_DEV == 0) {
+- printk("No ramdisk, default root is /dev/sda2\n");
+- ROOT_DEV = Root_SDA2;
+- }
+-
+- fwnmi_init();
+-
+- /* Find and initialize PCI host bridges */
+- init_pci_config_tokens();
+- find_and_init_phbs();
+- eeh_init();
+-
+-#ifdef CONFIG_DUMMY_CONSOLE
+- conswitchp = &dummy_con;
+-#endif
+-
+- pSeries_nvram_init();
+-
+- /* Choose an idle loop */
+- if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+- vpa_init(boot_cpuid);
+- if (get_paca()->lppaca.shared_proc) {
+- printk(KERN_INFO "Using shared processor idle loop\n");
+- ppc_md.idle_loop = pseries_shared_idle;
+- } else {
+- printk(KERN_INFO "Using dedicated idle loop\n");
+- ppc_md.idle_loop = pseries_dedicated_idle;
+- }
+- } else {
+- printk(KERN_INFO "Using default idle loop\n");
+- ppc_md.idle_loop = default_idle;
+- }
+-
+- if (systemcfg->platform & PLATFORM_LPAR)
+- ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
+- else
+- ppc_md.enable_pmcs = power4_enable_pmcs;
+-}
+-
+-static int __init pSeries_init_panel(void)
+-{
+- /* Manually leave the kernel version on the panel. */
+- ppc_md.progress("Linux ppc64\n", 0);
+- ppc_md.progress(system_utsname.version, 0);
+-
+- return 0;
+-}
+-arch_initcall(pSeries_init_panel);
+-
+-
+-/* Build up the ppc64_firmware_features bitmask field
+- * using contents of device-tree/ibm,hypertas-functions.
+- * Ultimately this functionality may be moved into prom.c prom_init().
+- */
+-static void __init fw_feature_init(void)
+-{
+- struct device_node * dn;
+- char * hypertas;
+- unsigned int len;
+-
+- DBG(" -> fw_feature_init()\n");
+-
+- ppc64_firmware_features = 0;
+- dn = of_find_node_by_path("/rtas");
+- if (dn == NULL) {
+- printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
+- goto no_rtas;
+- }
+-
+- hypertas = get_property(dn, "ibm,hypertas-functions", &len);
+- if (hypertas) {
+- while (len > 0){
+- int i, hypertas_len;
+- /* check value against table of strings */
+- for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) {
+- if ((firmware_features_table[i].name) &&
+- (strcmp(firmware_features_table[i].name,hypertas))==0) {
+- /* we have a match */
+- ppc64_firmware_features |=
+- (firmware_features_table[i].val);
+- break;
+- }
+- }
+- hypertas_len = strlen(hypertas);
+- len -= hypertas_len +1;
+- hypertas+= hypertas_len +1;
+- }
+- }
+-
+- of_node_put(dn);
+- no_rtas:
+- printk(KERN_INFO "firmware_features = 0x%lx\n",
+- ppc64_firmware_features);
+-
+- DBG(" <- fw_feature_init()\n");
+-}
+-
+-
+-static void __init pSeries_discover_pic(void)
+-{
+- struct device_node *np;
+- char *typep;
+-
+- /*
+- * Setup interrupt mapping options that are needed for finish_device_tree
+- * to properly parse the OF interrupt tree & do the virtual irq mapping
+- */
+- __irq_offset_value = NUM_ISA_INTERRUPTS;
+- ppc64_interrupt_controller = IC_INVALID;
+- for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
+- typep = (char *)get_property(np, "compatible", NULL);
+- if (strstr(typep, "open-pic"))
+- ppc64_interrupt_controller = IC_OPEN_PIC;
+- else if (strstr(typep, "ppc-xicp"))
+- ppc64_interrupt_controller = IC_PPC_XIC;
+- else
+- printk("pSeries_discover_pic: failed to recognize"
+- " interrupt-controller\n");
+- break;
+- }
+-}
+-
+-static void pSeries_mach_cpu_die(void)
+-{
+- local_irq_disable();
+- idle_task_exit();
+- /* Some hardware requires clearing the CPPR, while other hardware does not
+- * it is safe either way
+- */
+- pSeriesLP_cppr_info(0, 0);
+- rtas_stop_self();
+- /* Should never get here... */
+- BUG();
+- for(;;);
+-}
+-
+-
+-/*
+- * Early initialization. Relocation is on but do not reference unbolted pages
+- */
+-static void __init pSeries_init_early(void)
+-{
+- void *comport;
+- int iommu_off = 0;
+- unsigned int default_speed;
+- u64 physport;
+-
+- DBG(" -> pSeries_init_early()\n");
+-
+- fw_feature_init();
+-
+- if (systemcfg->platform & PLATFORM_LPAR)
+- hpte_init_lpar();
+- else {
+- hpte_init_native();
+- iommu_off = (of_chosen &&
+- get_property(of_chosen, "linux,iommu-off", NULL));
+- }
+-
+- generic_find_legacy_serial_ports(&physport, &default_speed);
+-
+- if (systemcfg->platform & PLATFORM_LPAR)
+- find_udbg_vterm();
+- else if (physport) {
+- /* Map the uart for udbg. */
+- comport = (void *)ioremap(physport, 16);
+- udbg_init_uart(comport, default_speed);
+-
+- DBG("Hello World !\n");
+- }
+-
+-
+- iommu_init_early_pSeries();
+-
+- pSeries_discover_pic();
+-
+- DBG(" <- pSeries_init_early()\n");
+-}
+-
+-
+-static int pSeries_check_legacy_ioport(unsigned int baseport)
+-{
+- struct device_node *np;
+-
+-#define I8042_DATA_REG 0x60
+-#define FDC_BASE 0x3f0
+-
+-
+- switch(baseport) {
+- case I8042_DATA_REG:
+- np = of_find_node_by_type(NULL, "8042");
+- if (np == NULL)
+- return -ENODEV;
+- of_node_put(np);
+- break;
+- case FDC_BASE:
+- np = of_find_node_by_type(NULL, "fdc");
+- if (np == NULL)
+- return -ENODEV;
+- of_node_put(np);
+- break;
+- }
+- return 0;
+-}
+-
+-/*
+- * Called very early, MMU is off, device-tree isn't unflattened
+- */
+-extern struct machdep_calls pSeries_md;
+-
+-static int __init pSeries_probe(int platform)
+-{
+- if (platform != PLATFORM_PSERIES &&
+- platform != PLATFORM_PSERIES_LPAR)
+- return 0;
+-
+- /* if we have some ppc_md fixups for LPAR to do, do
+- * it here ...
+- */
+-
+- return 1;
+-}
+-
+-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+-
+-static inline void dedicated_idle_sleep(unsigned int cpu)
+-{
+- struct paca_struct *ppaca = &paca[cpu ^ 1];
+-
+- /* Only sleep if the other thread is not idle */
+- if (!(ppaca->lppaca.idle)) {
+- local_irq_disable();
+-
+- /*
+- * We are about to sleep the thread and so wont be polling any
+- * more.
+- */
+- clear_thread_flag(TIF_POLLING_NRFLAG);
+-
+- /*
+- * SMT dynamic mode. Cede will result in this thread going
+- * dormant, if the partner thread is still doing work. Thread
+- * wakes up if partner goes idle, an interrupt is presented, or
+- * a prod occurs. Returning from the cede enables external
+- * interrupts.
+- */
+- if (!need_resched())
+- cede_processor();
+- else
+- local_irq_enable();
+- } else {
+- /*
+- * Give the HV an opportunity at the processor, since we are
+- * not doing any work.
+- */
+- poll_pending();
+- }
+-}
+-
+-static int pseries_dedicated_idle(void)
+-{
+- long oldval;
+- struct paca_struct *lpaca = get_paca();
+- unsigned int cpu = smp_processor_id();
+- unsigned long start_snooze;
+- unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
+-
+- while (1) {
+- /*
+- * Indicate to the HV that we are idle. Now would be
+- * a good time to find other work to dispatch.
+- */
+- lpaca->lppaca.idle = 1;
+-
+- oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+- if (!oldval) {
+- set_thread_flag(TIF_POLLING_NRFLAG);
+-
+- start_snooze = __get_tb() +
+- *smt_snooze_delay * tb_ticks_per_usec;
+-
+- while (!need_resched() && !cpu_is_offline(cpu)) {
+- ppc64_runlatch_off();
+-
+- /*
+- * Go into low thread priority and possibly
+- * low power mode.
+- */
+- HMT_low();
+- HMT_very_low();
+-
+- if (*smt_snooze_delay != 0 &&
+- __get_tb() > start_snooze) {
+- HMT_medium();
+- dedicated_idle_sleep(cpu);
+- }
+-
+- }
+-
+- HMT_medium();
+- clear_thread_flag(TIF_POLLING_NRFLAG);
+- } else {
+- set_need_resched();
+- }
+-
+- lpaca->lppaca.idle = 0;
+- ppc64_runlatch_on();
+-
+- schedule();
+-
+- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+- cpu_die();
+- }
+-}
+-
+-static int pseries_shared_idle(void)
+-{
+- struct paca_struct *lpaca = get_paca();
+- unsigned int cpu = smp_processor_id();
+-
+- while (1) {
+- /*
+- * Indicate to the HV that we are idle. Now would be
+- * a good time to find other work to dispatch.
+- */
+- lpaca->lppaca.idle = 1;
+-
+- while (!need_resched() && !cpu_is_offline(cpu)) {
+- local_irq_disable();
+- ppc64_runlatch_off();
+-
+- /*
+- * Yield the processor to the hypervisor. We return if
+- * an external interrupt occurs (which are driven prior
+- * to returning here) or if a prod occurs from another
+- * processor. When returning here, external interrupts
+- * are enabled.
+- *
+- * Check need_resched() again with interrupts disabled
+- * to avoid a race.
+- */
+- if (!need_resched())
+- cede_processor();
+- else
+- local_irq_enable();
+-
+- HMT_medium();
+- }
+-
+- lpaca->lppaca.idle = 0;
+- ppc64_runlatch_on();
+-
+- schedule();
+-
+- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+- cpu_die();
+- }
+-
+- return 0;
+-}
+-
+-static int pSeries_pci_probe_mode(struct pci_bus *bus)
+-{
+- if (systemcfg->platform & PLATFORM_LPAR)
+- return PCI_PROBE_DEVTREE;
+- return PCI_PROBE_NORMAL;
+-}
+-
+-struct machdep_calls __initdata pSeries_md = {
+- .probe = pSeries_probe,
+- .setup_arch = pSeries_setup_arch,
+- .init_early = pSeries_init_early,
+- .get_cpuinfo = pSeries_get_cpuinfo,
+- .log_error = pSeries_log_error,
+- .pcibios_fixup = pSeries_final_fixup,
+- .pci_probe_mode = pSeries_pci_probe_mode,
+- .irq_bus_setup = pSeries_irq_bus_setup,
+- .restart = rtas_restart,
+- .power_off = rtas_power_off,
+- .halt = rtas_halt,
+- .panic = rtas_os_term,
+- .cpu_die = pSeries_mach_cpu_die,
+- .get_boot_time = rtas_get_boot_time,
+- .get_rtc_time = rtas_get_rtc_time,
+- .set_rtc_time = rtas_set_rtc_time,
+- .calibrate_decr = generic_calibrate_decr,
+- .progress = rtas_progress,
+- .check_legacy_ioport = pSeries_check_legacy_ioport,
+- .system_reset_exception = pSeries_system_reset_exception,
+- .machine_check_exception = pSeries_machine_check_exception,
+-};
+diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_smp.c
++++ /dev/null
+@@ -1,517 +0,0 @@
+-/*
+- * SMP support for pSeries and BPA machines.
+- *
+- * Dave Engebretsen, Peter Bergner, and
+- * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+- *
+- * Plus various changes from other IBM teams...
+- *
+- * 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/interrupt.h>
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/spinlock.h>
+-#include <linux/cache.h>
+-#include <linux/err.h>
+-#include <linux/sysdev.h>
+-#include <linux/cpu.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/atomic.h>
+-#include <asm/irq.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/smp.h>
+-#include <asm/paca.h>
+-#include <asm/time.h>
+-#include <asm/machdep.h>
+-#include <asm/xics.h>
+-#include <asm/cputable.h>
+-#include <asm/firmware.h>
+-#include <asm/system.h>
+-#include <asm/rtas.h>
+-#include <asm/plpar_wrappers.h>
+-#include <asm/pSeries_reconfig.h>
+-
+-#include "mpic.h"
+-#include "bpa_iic.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/*
+- * The primary thread of each non-boot processor is recorded here before
+- * smp init.
+- */
+-static cpumask_t of_spin_map;
+-
+-extern void pSeries_secondary_smp_init(unsigned long);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-/* Get state of physical CPU.
+- * Return codes:
+- * 0 - The processor is in the RTAS stopped state
+- * 1 - stop-self is in progress
+- * 2 - The processor is not in the RTAS stopped state
+- * -1 - Hardware Error
+- * -2 - Hardware Busy, Try again later.
+- */
+-static int query_cpu_stopped(unsigned int pcpu)
+-{
+- int cpu_status;
+- int status, qcss_tok;
+-
+- qcss_tok = rtas_token("query-cpu-stopped-state");
+- if (qcss_tok == RTAS_UNKNOWN_SERVICE)
+- return -1;
+- status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+- if (status != 0) {
+- printk(KERN_ERR
+- "RTAS query-cpu-stopped-state failed: %i\n", status);
+- return status;
+- }
+-
+- return cpu_status;
+-}
+-
+-int pSeries_cpu_disable(void)
+-{
+- int cpu = smp_processor_id();
+-
+- cpu_clear(cpu, cpu_online_map);
+- systemcfg->processorCount--;
+-
+- /*fix boot_cpuid here*/
+- if (cpu == boot_cpuid)
+- boot_cpuid = any_online_cpu(cpu_online_map);
+-
+- /* FIXME: abstract this to not be platform specific later on */
+- xics_migrate_irqs_away();
+- return 0;
+-}
+-
+-void pSeries_cpu_die(unsigned int cpu)
+-{
+- int tries;
+- int cpu_status;
+- unsigned int pcpu = get_hard_smp_processor_id(cpu);
+-
+- for (tries = 0; tries < 25; tries++) {
+- cpu_status = query_cpu_stopped(pcpu);
+- if (cpu_status == 0 || cpu_status == -1)
+- break;
+- msleep(200);
+- }
+- if (cpu_status != 0) {
+- printk("Querying DEAD? cpu %i (%i) shows %i\n",
+- cpu, pcpu, cpu_status);
+- }
+-
+- /* Isolation and deallocation are definatly done by
+- * drslot_chrp_cpu. If they were not they would be
+- * done here. Change isolate state to Isolate and
+- * change allocation-state to Unusable.
+- */
+- paca[cpu].cpu_start = 0;
+-}
+-
+-/*
+- * Update cpu_present_map and paca(s) for a new cpu node. The wrinkle
+- * here is that a cpu device node may represent up to two logical cpus
+- * in the SMT case. We must honor the assumption in other code that
+- * the logical ids for sibling SMT threads x and y are adjacent, such
+- * that x^1 == y and y^1 == x.
+- */
+-static int pSeries_add_processor(struct device_node *np)
+-{
+- unsigned int cpu;
+- cpumask_t candidate_map, tmp = CPU_MASK_NONE;
+- int err = -ENOSPC, len, nthreads, i;
+- u32 *intserv;
+-
+- intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len);
+- if (!intserv)
+- return 0;
+-
+- nthreads = len / sizeof(u32);
+- for (i = 0; i < nthreads; i++)
+- cpu_set(i, tmp);
+-
+- lock_cpu_hotplug();
+-
+- BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
+-
+- /* Get a bitmap of unoccupied slots. */
+- cpus_xor(candidate_map, cpu_possible_map, cpu_present_map);
+- if (cpus_empty(candidate_map)) {
+- /* If we get here, it most likely means that NR_CPUS is
+- * less than the partition's max processors setting.
+- */
+- printk(KERN_ERR "Cannot add cpu %s; this system configuration"
+- " supports %d logical cpus.\n", np->full_name,
+- cpus_weight(cpu_possible_map));
+- goto out_unlock;
+- }
+-
+- while (!cpus_empty(tmp))
+- if (cpus_subset(tmp, candidate_map))
+- /* Found a range where we can insert the new cpu(s) */
+- break;
+- else
+- cpus_shift_left(tmp, tmp, nthreads);
+-
+- if (cpus_empty(tmp)) {
+- printk(KERN_ERR "Unable to find space in cpu_present_map for"
+- " processor %s with %d thread(s)\n", np->name,
+- nthreads);
+- goto out_unlock;
+- }
+-
+- for_each_cpu_mask(cpu, tmp) {
+- BUG_ON(cpu_isset(cpu, cpu_present_map));
+- cpu_set(cpu, cpu_present_map);
+- set_hard_smp_processor_id(cpu, *intserv++);
+- }
+- err = 0;
+-out_unlock:
+- unlock_cpu_hotplug();
+- return err;
+-}
+-
+-/*
+- * Update the present map for a cpu node which is going away, and set
+- * the hard id in the paca(s) to -1 to be consistent with boot time
+- * convention for non-present cpus.
+- */
+-static void pSeries_remove_processor(struct device_node *np)
+-{
+- unsigned int cpu;
+- int len, nthreads, i;
+- u32 *intserv;
+-
+- intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len);
+- if (!intserv)
+- return;
+-
+- nthreads = len / sizeof(u32);
+-
+- lock_cpu_hotplug();
+- for (i = 0; i < nthreads; i++) {
+- for_each_present_cpu(cpu) {
+- if (get_hard_smp_processor_id(cpu) != intserv[i])
+- continue;
+- BUG_ON(cpu_online(cpu));
+- cpu_clear(cpu, cpu_present_map);
+- set_hard_smp_processor_id(cpu, -1);
+- break;
+- }
+- if (cpu == NR_CPUS)
+- printk(KERN_WARNING "Could not find cpu to remove "
+- "with physical id 0x%x\n", intserv[i]);
+- }
+- unlock_cpu_hotplug();
+-}
+-
+-static int pSeries_smp_notifier(struct notifier_block *nb, unsigned long action, void *node)
+-{
+- int err = NOTIFY_OK;
+-
+- switch (action) {
+- case PSERIES_RECONFIG_ADD:
+- if (pSeries_add_processor(node))
+- err = NOTIFY_BAD;
+- break;
+- case PSERIES_RECONFIG_REMOVE:
+- pSeries_remove_processor(node);
+- break;
+- default:
+- err = NOTIFY_DONE;
+- break;
+- }
+- return err;
+-}
+-
+-static struct notifier_block pSeries_smp_nb = {
+- .notifier_call = pSeries_smp_notifier,
+-};
+-
+-#endif /* CONFIG_HOTPLUG_CPU */
+-
+-/**
+- * smp_startup_cpu() - start the given cpu
+- *
+- * At boot time, there is nothing to do for primary threads which were
+- * started from Open Firmware. For anything else, call RTAS with the
+- * appropriate start location.
+- *
+- * Returns:
+- * 0 - failure
+- * 1 - success
+- */
+-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+-{
+- int status;
+- unsigned long start_here = __pa((u32)*((unsigned long *)
+- pSeries_secondary_smp_init));
+- unsigned int pcpu;
+- int start_cpu;
+-
+- if (cpu_isset(lcpu, of_spin_map))
+- /* Already started by OF and sitting in spin loop */
+- return 1;
+-
+- pcpu = get_hard_smp_processor_id(lcpu);
+-
+- /* Fixup atomic count: it exited inside IRQ handler. */
+- paca[lcpu].__current->thread_info->preempt_count = 0;
+-
+- /*
+- * If the RTAS start-cpu token does not exist then presume the
+- * cpu is already spinning.
+- */
+- start_cpu = rtas_token("start-cpu");
+- if (start_cpu == RTAS_UNKNOWN_SERVICE)
+- return 1;
+-
+- status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
+- if (status != 0) {
+- printk(KERN_ERR "start-cpu failed: %i\n", status);
+- return 0;
+- }
+-
+- return 1;
+-}
+-
+-#ifdef CONFIG_XICS
+-static inline void smp_xics_do_message(int cpu, int msg)
+-{
+- set_bit(msg, &xics_ipi_message[cpu].value);
+- mb();
+- xics_cause_IPI(cpu);
+-}
+-
+-static void smp_xics_message_pass(int target, int msg)
+-{
+- unsigned int i;
+-
+- if (target < NR_CPUS) {
+- smp_xics_do_message(target, msg);
+- } else {
+- for_each_online_cpu(i) {
+- if (target == MSG_ALL_BUT_SELF
+- && i == smp_processor_id())
+- continue;
+- smp_xics_do_message(i, msg);
+- }
+- }
+-}
+-
+-static int __init smp_xics_probe(void)
+-{
+- xics_request_IPIs();
+-
+- return cpus_weight(cpu_possible_map);
+-}
+-
+-static void __devinit smp_xics_setup_cpu(int cpu)
+-{
+- if (cpu != boot_cpuid)
+- xics_setup_cpu();
+-
+- if (firmware_has_feature(FW_FEATURE_SPLPAR))
+- vpa_init(cpu);
+-
+- cpu_clear(cpu, of_spin_map);
+-
+-}
+-#endif /* CONFIG_XICS */
+-#ifdef CONFIG_BPA_IIC
+-static void smp_iic_message_pass(int target, int msg)
+-{
+- unsigned int i;
+-
+- if (target < NR_CPUS) {
+- iic_cause_IPI(target, msg);
+- } else {
+- for_each_online_cpu(i) {
+- if (target == MSG_ALL_BUT_SELF
+- && i == smp_processor_id())
+- continue;
+- iic_cause_IPI(i, msg);
+- }
+- }
+-}
+-
+-static int __init smp_iic_probe(void)
+-{
+- iic_request_IPIs();
+-
+- return cpus_weight(cpu_possible_map);
+-}
+-
+-static void __devinit smp_iic_setup_cpu(int cpu)
+-{
+- if (cpu != boot_cpuid)
+- iic_setup_cpu();
+-}
+-#endif /* CONFIG_BPA_IIC */
+-
+-static DEFINE_SPINLOCK(timebase_lock);
+-static unsigned long timebase = 0;
+-
+-static void __devinit pSeries_give_timebase(void)
+-{
+- spin_lock(&timebase_lock);
+- rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
+- timebase = get_tb();
+- spin_unlock(&timebase_lock);
+-
+- while (timebase)
+- barrier();
+- rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
+-}
+-
+-static void __devinit pSeries_take_timebase(void)
+-{
+- while (!timebase)
+- barrier();
+- spin_lock(&timebase_lock);
+- set_tb(timebase >> 32, timebase & 0xffffffff);
+- timebase = 0;
+- spin_unlock(&timebase_lock);
+-}
+-
+-static void __devinit smp_pSeries_kick_cpu(int nr)
+-{
+- BUG_ON(nr < 0 || nr >= NR_CPUS);
+-
+- if (!smp_startup_cpu(nr))
+- return;
+-
+- /*
+- * The processor is currently spinning, waiting for the
+- * cpu_start field to become non-zero After we set cpu_start,
+- * the processor will continue on to secondary_start
+- */
+- paca[nr].cpu_start = 1;
+-}
+-
+-static int smp_pSeries_cpu_bootable(unsigned int nr)
+-{
+- /* Special case - we inhibit secondary thread startup
+- * during boot if the user requests it. Odd-numbered
+- * cpus are assumed to be secondary threads.
+- */
+- if (system_state < SYSTEM_RUNNING &&
+- cpu_has_feature(CPU_FTR_SMT) &&
+- !smt_enabled_at_boot && nr % 2 != 0)
+- return 0;
+-
+- return 1;
+-}
+-#ifdef CONFIG_MPIC
+-static struct smp_ops_t pSeries_mpic_smp_ops = {
+- .message_pass = smp_mpic_message_pass,
+- .probe = smp_mpic_probe,
+- .kick_cpu = smp_pSeries_kick_cpu,
+- .setup_cpu = smp_mpic_setup_cpu,
+-};
+-#endif
+-#ifdef CONFIG_XICS
+-static struct smp_ops_t pSeries_xics_smp_ops = {
+- .message_pass = smp_xics_message_pass,
+- .probe = smp_xics_probe,
+- .kick_cpu = smp_pSeries_kick_cpu,
+- .setup_cpu = smp_xics_setup_cpu,
+- .cpu_bootable = smp_pSeries_cpu_bootable,
+-};
+-#endif
+-#ifdef CONFIG_BPA_IIC
+-static struct smp_ops_t bpa_iic_smp_ops = {
+- .message_pass = smp_iic_message_pass,
+- .probe = smp_iic_probe,
+- .kick_cpu = smp_pSeries_kick_cpu,
+- .setup_cpu = smp_iic_setup_cpu,
+- .cpu_bootable = smp_pSeries_cpu_bootable,
+-};
+-#endif
+-
+-/* This is called very early */
+-void __init smp_init_pSeries(void)
+-{
+- int i;
+-
+- DBG(" -> smp_init_pSeries()\n");
+-
+- switch (ppc64_interrupt_controller) {
+-#ifdef CONFIG_MPIC
+- case IC_OPEN_PIC:
+- smp_ops = &pSeries_mpic_smp_ops;
+- break;
+-#endif
+-#ifdef CONFIG_XICS
+- case IC_PPC_XIC:
+- smp_ops = &pSeries_xics_smp_ops;
+- break;
+-#endif
+-#ifdef CONFIG_BPA_IIC
+- case IC_BPA_IIC:
+- smp_ops = &bpa_iic_smp_ops;
+- break;
+-#endif
+- default:
+- panic("Invalid interrupt controller");
+- }
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+- smp_ops->cpu_disable = pSeries_cpu_disable;
+- smp_ops->cpu_die = pSeries_cpu_die;
+-
+- /* Processors can be added/removed only on LPAR */
+- if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
+- pSeries_reconfig_notifier_register(&pSeries_smp_nb);
+-#endif
+-
+- /* Mark threads which are still spinning in hold loops. */
+- if (cpu_has_feature(CPU_FTR_SMT)) {
+- for_each_present_cpu(i) {
+- if (i % 2 == 0)
+- /*
+- * Even-numbered logical cpus correspond to
+- * primary threads.
+- */
+- cpu_set(i, of_spin_map);
+- }
+- } else {
+- of_spin_map = cpu_present_map;
+- }
+-
+- cpu_clear(boot_cpuid, of_spin_map);
+-
+- /* Non-lpar has additional take/give timebase */
+- if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
+- smp_ops->give_timebase = pSeries_give_timebase;
+- smp_ops->take_timebase = pSeries_take_timebase;
+- }
+-
+- DBG(" <- smp_init_pSeries()\n");
+-}
+-
+diff --git a/arch/ppc64/kernel/pSeries_vio.c b/arch/ppc64/kernel/pSeries_vio.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pSeries_vio.c
++++ /dev/null
+@@ -1,273 +0,0 @@
+-/*
+- * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
+- *
+- * Copyright (c) 2003-2005 IBM Corp.
+- * Dave Engebretsen engebret at us.ibm.com
+- * Santiago Leon santil at us.ibm.com
+- * Hollis Blanchard <hollisb at us.ibm.com>
+- * Stephen Rothwell
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/mm.h>
+-#include <linux/kobject.h>
+-#include <asm/iommu.h>
+-#include <asm/dma.h>
+-#include <asm/prom.h>
+-#include <asm/vio.h>
+-#include <asm/hvcall.h>
+-
+-extern struct subsystem devices_subsys; /* needed for vio_find_name() */
+-
+-static void probe_bus_pseries(void)
+-{
+- struct device_node *node_vroot, *of_node;
+-
+- node_vroot = find_devices("vdevice");
+- if ((node_vroot == NULL) || (node_vroot->child == NULL))
+- /* this machine doesn't do virtual IO, and that's ok */
+- return;
+-
+- /*
+- * Create struct vio_devices for each virtual device in the device tree.
+- * Drivers will associate with them later.
+- */
+- for (of_node = node_vroot->child; of_node != NULL;
+- of_node = of_node->sibling) {
+- printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
+- vio_register_device_node(of_node);
+- }
+-}
+-
+-/**
+- * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
+- * vio_device_id
+- */
+-static int vio_match_device_pseries(const struct vio_device_id *id,
+- const struct vio_dev *dev)
+-{
+- return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
+- device_is_compatible(dev->dev.platform_data, id->compat);
+-}
+-
+-static void vio_release_device_pseries(struct device *dev)
+-{
+- /* XXX free TCE table */
+- of_node_put(dev->platform_data);
+-}
+-
+-static ssize_t viodev_show_devspec(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct device_node *of_node = dev->platform_data;
+-
+- return sprintf(buf, "%s\n", of_node->full_name);
+-}
+-DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
+-
+-static void vio_unregister_device_pseries(struct vio_dev *viodev)
+-{
+- device_remove_file(&viodev->dev, &dev_attr_devspec);
+-}
+-
+-static struct vio_bus_ops vio_bus_ops_pseries = {
+- .match = vio_match_device_pseries,
+- .unregister_device = vio_unregister_device_pseries,
+- .release_device = vio_release_device_pseries,
+-};
+-
+-/**
+- * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
+- */
+-static int __init vio_bus_init_pseries(void)
+-{
+- int err;
+-
+- err = vio_bus_init(&vio_bus_ops_pseries);
+- if (err == 0)
+- probe_bus_pseries();
+- return err;
+-}
+-
+-__initcall(vio_bus_init_pseries);
+-
+-/**
+- * vio_build_iommu_table: - gets the dma information from OF and
+- * builds the TCE tree.
+- * @dev: the virtual device.
+- *
+- * Returns a pointer to the built tce tree, or NULL if it can't
+- * find property.
+-*/
+-static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+-{
+- unsigned int *dma_window;
+- struct iommu_table *newTceTable;
+- unsigned long offset;
+- int dma_window_property_size;
+-
+- dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
+- if(!dma_window) {
+- return NULL;
+- }
+-
+- newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+-
+- /* There should be some code to extract the phys-encoded offset
+- using prom_n_addr_cells(). However, according to a comment
+- on earlier versions, it's always zero, so we don't bother */
+- offset = dma_window[1] >> PAGE_SHIFT;
+-
+- /* TCE table size - measured in tce entries */
+- newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
+- /* offset for VIO should always be 0 */
+- newTceTable->it_offset = offset;
+- newTceTable->it_busno = 0;
+- newTceTable->it_index = (unsigned long)dma_window[0];
+- newTceTable->it_type = TCE_VB;
+-
+- return iommu_init_table(newTceTable);
+-}
+-
+-/**
+- * vio_register_device_node: - Register a new vio device.
+- * @of_node: The OF node for this device.
+- *
+- * Creates and initializes a vio_dev structure from the data in
+- * of_node (dev.platform_data) and adds it to the list of virtual devices.
+- * Returns a pointer to the created vio_dev or NULL if node has
+- * NULL device_type or compatible fields.
+- */
+-struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
+-{
+- struct vio_dev *viodev;
+- unsigned int *unit_address;
+- unsigned int *irq_p;
+-
+- /* we need the 'device_type' property, in order to match with drivers */
+- if ((NULL == of_node->type)) {
+- printk(KERN_WARNING
+- "%s: node %s missing 'device_type'\n", __FUNCTION__,
+- of_node->name ? of_node->name : "<unknown>");
+- return NULL;
+- }
+-
+- unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
+- if (!unit_address) {
+- printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
+- of_node->name ? of_node->name : "<unknown>");
+- return NULL;
+- }
+-
+- /* allocate a vio_dev for this node */
+- viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
+- if (!viodev) {
+- return NULL;
+- }
+- memset(viodev, 0, sizeof(struct vio_dev));
+-
+- viodev->dev.platform_data = of_node_get(of_node);
+-
+- viodev->irq = NO_IRQ;
+- irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
+- if (irq_p) {
+- int virq = virt_irq_create_mapping(*irq_p);
+- if (virq == NO_IRQ) {
+- printk(KERN_ERR "Unable to allocate interrupt "
+- "number for %s\n", of_node->full_name);
+- } else
+- viodev->irq = irq_offset_up(virq);
+- }
+-
+- snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
+- viodev->name = of_node->name;
+- viodev->type = of_node->type;
+- viodev->unit_address = *unit_address;
+- viodev->iommu_table = vio_build_iommu_table(viodev);
+-
+- /* register with generic device framework */
+- if (vio_register_device(viodev) == NULL) {
+- /* XXX free TCE table */
+- kfree(viodev);
+- return NULL;
+- }
+- device_create_file(&viodev->dev, &dev_attr_devspec);
+-
+- return viodev;
+-}
+-EXPORT_SYMBOL(vio_register_device_node);
+-
+-/**
+- * vio_get_attribute: - get attribute for virtual device
+- * @vdev: The vio device to get property.
+- * @which: The property/attribute to be extracted.
+- * @length: Pointer to length of returned data size (unused if NULL).
+- *
+- * Calls prom.c's get_property() to return the value of the
+- * attribute specified by the preprocessor constant @which
+-*/
+-const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
+-{
+- return get_property(vdev->dev.platform_data, (char*)which, length);
+-}
+-EXPORT_SYMBOL(vio_get_attribute);
+-
+-/* vio_find_name() - internal because only vio.c knows how we formatted the
+- * kobject name
+- * XXX once vio_bus_type.devices is actually used as a kset in
+- * drivers/base/bus.c, this function should be removed in favor of
+- * "device_find(kobj_name, &vio_bus_type)"
+- */
+-static struct vio_dev *vio_find_name(const char *kobj_name)
+-{
+- struct kobject *found;
+-
+- found = kset_find_obj(&devices_subsys.kset, kobj_name);
+- if (!found)
+- return NULL;
+-
+- return to_vio_dev(container_of(found, struct device, kobj));
+-}
+-
+-/**
+- * vio_find_node - find an already-registered vio_dev
+- * @vnode: device_node of the virtual device we're looking for
+- */
+-struct vio_dev *vio_find_node(struct device_node *vnode)
+-{
+- uint32_t *unit_address;
+- char kobj_name[BUS_ID_SIZE];
+-
+- /* construct the kobject name from the device node */
+- unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
+- if (!unit_address)
+- return NULL;
+- snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
+-
+- return vio_find_name(kobj_name);
+-}
+-EXPORT_SYMBOL(vio_find_node);
+-
+-int vio_enable_interrupts(struct vio_dev *dev)
+-{
+- int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
+- if (rc != H_Success)
+- printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
+- return rc;
+-}
+-EXPORT_SYMBOL(vio_enable_interrupts);
+-
+-int vio_disable_interrupts(struct vio_dev *dev)
+-{
+- int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
+- if (rc != H_Success)
+- printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
+- return rc;
+-}
+-EXPORT_SYMBOL(vio_disable_interrupts);
+diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
+--- a/arch/ppc64/kernel/pci.c
++++ b/arch/ppc64/kernel/pci.c
+@@ -31,8 +31,7 @@
+ #include <asm/irq.h>
+ #include <asm/machdep.h>
+ #include <asm/udbg.h>
+-
+-#include "pci.h"
++#include <asm/ppc-pci.h>
+
+ #ifdef DEBUG
+ #define DBG(fmt...) udbg_printf(fmt)
+@@ -727,16 +726,17 @@ static pgprot_t __pci_mmap_set_pgprot(st
+ * above routine
+ */
+ pgprot_t pci_phys_mem_access_prot(struct file *file,
+- unsigned long offset,
++ unsigned long pfn,
+ unsigned long size,
+ pgprot_t protection)
+ {
+ struct pci_dev *pdev = NULL;
+ struct resource *found = NULL;
+ unsigned long prot = pgprot_val(protection);
++ unsigned long offset = pfn << PAGE_SHIFT;
+ int i;
+
+- if (page_is_ram(offset >> PAGE_SHIFT))
++ if (page_is_ram(pfn))
+ return __pgprot(prot);
+
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+@@ -881,9 +881,9 @@ static void __devinit pci_process_ISA_OF
+ }
+
+ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
+- struct device_node *dev)
++ struct device_node *dev, int prim)
+ {
+- unsigned int *ranges;
++ unsigned int *ranges, pci_space;
+ unsigned long size;
+ int rlen = 0;
+ int memno = 0;
+@@ -906,16 +906,39 @@ void __devinit pci_process_bridge_OF_ran
+ ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+ while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+ res = NULL;
+- pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
++ pci_space = ranges[0];
++ pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
+
+ cpu_phys_addr = ranges[3];
+- if (na == 2)
+- cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
++ if (na >= 2)
++ cpu_phys_addr = (cpu_phys_addr << 32) | ranges[4];
+
+- size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
++ size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
++ ranges += np;
+ if (size == 0)
+ continue;
+- switch ((ranges[0] >> 24) & 0x3) {
++
++ /* Now consume following elements while they are contiguous */
++ while (rlen >= np * sizeof(unsigned int)) {
++ unsigned long addr, phys;
++
++ if (ranges[0] != pci_space)
++ break;
++ addr = ((unsigned long)ranges[1] << 32) | ranges[2];
++ phys = ranges[3];
++ if (na >= 2)
++ phys = (phys << 32) | ranges[4];
++ if (addr != pci_addr + size ||
++ phys != cpu_phys_addr + size)
++ break;
++
++ size += ((unsigned long)ranges[na+3] << 32)
++ | ranges[na+4];
++ ranges += np;
++ rlen -= np * sizeof(unsigned int);
++ }
++
++ switch ((pci_space >> 24) & 0x3) {
+ case 1: /* I/O space */
+ hose->io_base_phys = cpu_phys_addr;
+ hose->pci_io_size = size;
+@@ -949,7 +972,6 @@ void __devinit pci_process_bridge_OF_ran
+ res->sibling = NULL;
+ res->child = NULL;
+ }
+- ranges += np;
+ }
+ }
+
+diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pci.h
++++ /dev/null
+@@ -1,54 +0,0 @@
+-/*
+- * c 2001 PPC 64 Team, IBM Corp
+- *
+- * 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 __PPC_KERNEL_PCI_H__
+-#define __PPC_KERNEL_PCI_H__
+-
+-#include <linux/pci.h>
+-#include <asm/pci-bridge.h>
+-
+-extern unsigned long isa_io_base;
+-
+-extern void pci_setup_pci_controller(struct pci_controller *hose);
+-extern void pci_setup_phb_io(struct pci_controller *hose, int primary);
+-extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary);
+-
+-
+-extern struct list_head hose_list;
+-extern int global_phb_number;
+-
+-extern unsigned long find_and_init_phbs(void);
+-
+-extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */
+-
+-/* PCI device_node operations */
+-struct device_node;
+-typedef void *(*traverse_func)(struct device_node *me, void *data);
+-void *traverse_pci_devices(struct device_node *start, traverse_func pre,
+- void *data);
+-
+-void pci_devs_phb_init(void);
+-void pci_devs_phb_init_dynamic(struct pci_controller *phb);
+-
+-/* PCI address cache management routines */
+-void pci_addr_cache_insert_device(struct pci_dev *dev);
+-void pci_addr_cache_remove_device(struct pci_dev *dev);
+-
+-/* From rtas_pci.h */
+-void init_pci_config_tokens (void);
+-unsigned long get_phb_buid (struct device_node *);
+-
+-/* From pSeries_pci.h */
+-extern void pSeries_final_fixup(void);
+-extern void pSeries_irq_bus_setup(struct pci_bus *bus);
+-
+-extern unsigned long pci_probe_only;
+-extern unsigned long pci_assign_all_buses;
+-extern int pci_read_irq_line(struct pci_dev *pci_dev);
+-
+-#endif /* __PPC_KERNEL_PCI_H__ */
+diff --git a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/ppc64/kernel/pci_direct_iommu.c
+--- a/arch/ppc64/kernel/pci_direct_iommu.c
++++ b/arch/ppc64/kernel/pci_direct_iommu.c
+@@ -27,8 +27,7 @@
+ #include <asm/machdep.h>
+ #include <asm/pmac_feature.h>
+ #include <asm/abs_addr.h>
+-
+-#include "pci.h"
++#include <asm/ppc-pci.h>
+
+ static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
+--- a/arch/ppc64/kernel/pci_dn.c
++++ b/arch/ppc64/kernel/pci_dn.c
+@@ -30,8 +30,7 @@
+ #include <asm/prom.h>
+ #include <asm/pci-bridge.h>
+ #include <asm/pSeries_reconfig.h>
+-
+-#include "pci.h"
++#include <asm/ppc-pci.h>
+
+ /*
+ * Traverse_func that inits the PCI fields of the device node.
+diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
+--- a/arch/ppc64/kernel/pci_iommu.c
++++ b/arch/ppc64/kernel/pci_iommu.c
+@@ -1,8 +1,8 @@
+ /*
+ * arch/ppc64/kernel/pci_iommu.c
+ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+- *
+- * Rewrite, cleanup, new allocation schemes:
++ *
++ * Rewrite, cleanup, new allocation schemes:
+ * Copyright (C) 2004 Olof Johansson, IBM Corporation
+ *
+ * Dynamic DMA mapping support, platform-independent parts.
+@@ -11,19 +11,18 @@
+ * 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/init.h>
+ #include <linux/types.h>
+ #include <linux/slab.h>
+@@ -37,11 +36,7 @@
+ #include <asm/iommu.h>
+ #include <asm/pci-bridge.h>
+ #include <asm/machdep.h>
+-#include "pci.h"
+-
+-#ifdef CONFIG_PPC_ISERIES
+-#include <asm/iSeries/iSeries_pci.h>
+-#endif /* CONFIG_PPC_ISERIES */
++#include <asm/ppc-pci.h>
+
+ /*
+ * We can use ->sysdata directly and avoid the extra work in
+@@ -61,13 +56,7 @@ static inline struct iommu_table *devnod
+ } else
+ pdev = to_pci_dev(dev);
+
+-#ifdef CONFIG_PPC_ISERIES
+- return ISERIES_DEVNODE(pdev)->iommu_table;
+-#endif /* CONFIG_PPC_ISERIES */
+-
+-#ifdef CONFIG_PPC_MULTIPLATFORM
+ return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
+-#endif /* CONFIG_PPC_MULTIPLATFORM */
+ }
+
+
+diff --git a/arch/ppc64/kernel/pmac.h b/arch/ppc64/kernel/pmac.h
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-#ifndef __PMAC_H__
+-#define __PMAC_H__
+-
+-#include <linux/pci.h>
+-#include <linux/ide.h>
+-
+-/*
+- * Declaration for the various functions exported by the
+- * pmac_* files. Mostly for use by pmac_setup
+- */
+-
+-extern void pmac_get_boot_time(struct rtc_time *tm);
+-extern void pmac_get_rtc_time(struct rtc_time *tm);
+-extern int pmac_set_rtc_time(struct rtc_time *tm);
+-extern void pmac_read_rtc_time(void);
+-extern void pmac_calibrate_decr(void);
+-
+-extern void pmac_pcibios_fixup(void);
+-extern void pmac_pci_init(void);
+-extern void pmac_setup_pci_dma(void);
+-extern void pmac_check_ht_link(void);
+-
+-extern void pmac_setup_smp(void);
+-
+-extern unsigned long pmac_ide_get_base(int index);
+-extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+- unsigned long data_port, unsigned long ctrl_port, int *irq);
+-
+-extern void pmac_nvram_init(void);
+-
+-#endif /* __PMAC_H__ */
+diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac_feature.c
++++ /dev/null
+@@ -1,767 +0,0 @@
+-/*
+- * arch/ppc/platforms/pmac_feature.c
+- *
+- * Copyright (C) 1996-2001 Paul Mackerras (paulus at cs.anu.edu.au)
+- * Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * TODO:
+- *
+- * - Replace mdelay with some schedule loop if possible
+- * - Shorten some obfuscated delays on some routines (like modem
+- * power)
+- * - Refcount some clocks (see darwin)
+- * - Split split split...
+- *
+- */
+-#include <linux/config.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/spinlock.h>
+-#include <linux/adb.h>
+-#include <linux/pmu.h>
+-#include <linux/ioport.h>
+-#include <linux/pci.h>
+-#include <asm/sections.h>
+-#include <asm/errno.h>
+-#include <asm/keylargo.h>
+-#include <asm/uninorth.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pmac_feature.h>
+-#include <asm/dbdma.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/pmac_low_i2c.h>
+-
+-#undef DEBUG_FEATURE
+-
+-#ifdef DEBUG_FEATURE
+-#define DBG(fmt...) printk(KERN_DEBUG fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/*
+- * We use a single global lock to protect accesses. Each driver has
+- * to take care of its own locking
+- */
+-static DEFINE_SPINLOCK(feature_lock __pmacdata);
+-
+-#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
+-#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
+-
+-
+-/*
+- * Instance of some macio stuffs
+- */
+-struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata;
+-
+-struct macio_chip* __pmac macio_find(struct device_node* child, int type)
+-{
+- while(child) {
+- int i;
+-
+- for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
+- if (child == macio_chips[i].of_node &&
+- (!type || macio_chips[i].type == type))
+- return &macio_chips[i];
+- child = child->parent;
+- }
+- return NULL;
+-}
+-EXPORT_SYMBOL_GPL(macio_find);
+-
+-static const char* macio_names[] __pmacdata =
+-{
+- "Unknown",
+- "Grand Central",
+- "OHare",
+- "OHareII",
+- "Heathrow",
+- "Gatwick",
+- "Paddington",
+- "Keylargo",
+- "Pangea",
+- "Intrepid",
+- "K2"
+-};
+-
+-
+-
+-/*
+- * Uninorth reg. access. Note that Uni-N regs are big endian
+- */
+-
+-#define UN_REG(r) (uninorth_base + ((r) >> 2))
+-#define UN_IN(r) (in_be32(UN_REG(r)))
+-#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
+-#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
+-#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
+-
+-static struct device_node* uninorth_node __pmacdata;
+-static u32* uninorth_base __pmacdata;
+-static u32 uninorth_rev __pmacdata;
+-static void *u3_ht;
+-
+-extern struct device_node *k2_skiplist[2];
+-
+-/*
+- * For each motherboard family, we have a table of functions pointers
+- * that handle the various features.
+- */
+-
+-typedef long (*feature_call)(struct device_node* node, long param, long value);
+-
+-struct feature_table_entry {
+- unsigned int selector;
+- feature_call function;
+-};
+-
+-struct pmac_mb_def
+-{
+- const char* model_string;
+- const char* model_name;
+- int model_id;
+- struct feature_table_entry* features;
+- unsigned long board_flags;
+-};
+-static struct pmac_mb_def pmac_mb __pmacdata;
+-
+-/*
+- * Here are the chip specific feature functions
+- */
+-
+-
+-static long __pmac g5_read_gpio(struct device_node* node, long param, long value)
+-{
+- struct macio_chip* macio = &macio_chips[0];
+-
+- return MACIO_IN8(param);
+-}
+-
+-
+-static long __pmac g5_write_gpio(struct device_node* node, long param, long value)
+-{
+- struct macio_chip* macio = &macio_chips[0];
+-
+- MACIO_OUT8(param, (u8)(value & 0xff));
+- return 0;
+-}
+-
+-static long __pmac g5_gmac_enable(struct device_node* node, long param, long value)
+-{
+- struct macio_chip* macio = &macio_chips[0];
+- unsigned long flags;
+-
+- if (node == NULL)
+- return -ENODEV;
+-
+- LOCK(flags);
+- if (value) {
+- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
+- mb();
+- k2_skiplist[0] = NULL;
+- } else {
+- k2_skiplist[0] = node;
+- mb();
+- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
+- }
+-
+- UNLOCK(flags);
+- mdelay(1);
+-
+- return 0;
+-}
+-
+-static long __pmac g5_fw_enable(struct device_node* node, long param, long value)
+-{
+- struct macio_chip* macio = &macio_chips[0];
+- unsigned long flags;
+-
+- if (node == NULL)
+- return -ENODEV;
+-
+- LOCK(flags);
+- if (value) {
+- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
+- mb();
+- k2_skiplist[1] = NULL;
+- } else {
+- k2_skiplist[1] = node;
+- mb();
+- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
+- }
+-
+- UNLOCK(flags);
+- mdelay(1);
+-
+- return 0;
+-}
+-
+-static long __pmac g5_mpic_enable(struct device_node* node, long param, long value)
+-{
+- unsigned long flags;
+-
+- if (node->parent == NULL || strcmp(node->parent->name, "u3"))
+- return 0;
+-
+- LOCK(flags);
+- UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);
+- UNLOCK(flags);
+-
+- return 0;
+-}
+-
+-static long __pmac g5_eth_phy_reset(struct device_node* node, long param, long value)
+-{
+- struct macio_chip* macio = &macio_chips[0];
+- struct device_node *phy;
+- int need_reset;
+-
+- /*
+- * We must not reset the combo PHYs, only the BCM5221 found in
+- * the iMac G5.
+- */
+- phy = of_get_next_child(node, NULL);
+- if (!phy)
+- return -ENODEV;
+- need_reset = device_is_compatible(phy, "B5221");
+- of_node_put(phy);
+- if (!need_reset)
+- return 0;
+-
+- /* PHY reset is GPIO 29, not in device-tree unfortunately */
+- MACIO_OUT8(K2_GPIO_EXTINT_0 + 29,
+- KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+- /* Thankfully, this is now always called at a time when we can
+- * schedule by sungem.
+- */
+- msleep(10);
+- MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 0);
+-
+- return 0;
+-}
+-
+-static long __pmac g5_i2s_enable(struct device_node *node, long param, long value)
+-{
+- /* Very crude implementation for now */
+- struct macio_chip* macio = &macio_chips[0];
+- unsigned long flags;
+-
+- if (value == 0)
+- return 0; /* don't disable yet */
+-
+- LOCK(flags);
+- MACIO_BIS(KEYLARGO_FCR3, KL3_CLK45_ENABLE | KL3_CLK49_ENABLE |
+- KL3_I2S0_CLK18_ENABLE);
+- udelay(10);
+- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_I2S0_CELL_ENABLE |
+- K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE);
+- udelay(10);
+- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_I2S0_RESET);
+- UNLOCK(flags);
+- udelay(10);
+-
+- return 0;
+-}
+-
+-
+-#ifdef CONFIG_SMP
+-static long __pmac g5_reset_cpu(struct device_node* node, long param, long value)
+-{
+- unsigned int reset_io = 0;
+- unsigned long flags;
+- struct macio_chip* macio;
+- struct device_node* np;
+-
+- macio = &macio_chips[0];
+- if (macio->type != macio_keylargo2)
+- return -ENODEV;
+-
+- np = find_path_device("/cpus");
+- if (np == NULL)
+- return -ENODEV;
+- for (np = np->child; np != NULL; np = np->sibling) {
+- u32* num = (u32 *)get_property(np, "reg", NULL);
+- u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
+- if (num == NULL || rst == NULL)
+- continue;
+- if (param == *num) {
+- reset_io = *rst;
+- break;
+- }
+- }
+- if (np == NULL || reset_io == 0)
+- return -ENODEV;
+-
+- LOCK(flags);
+- MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
+- (void)MACIO_IN8(reset_io);
+- udelay(1);
+- MACIO_OUT8(reset_io, 0);
+- (void)MACIO_IN8(reset_io);
+- UNLOCK(flags);
+-
+- return 0;
+-}
+-#endif /* CONFIG_SMP */
+-
+-/*
+- * This can be called from pmac_smp so isn't static
+- *
+- * This takes the second CPU off the bus on dual CPU machines
+- * running UP
+- */
+-void __pmac g5_phy_disable_cpu1(void)
+-{
+- UN_OUT(U3_API_PHY_CONFIG_1, 0);
+-}
+-
+-static long __pmac generic_get_mb_info(struct device_node* node, long param, long value)
+-{
+- switch(param) {
+- case PMAC_MB_INFO_MODEL:
+- return pmac_mb.model_id;
+- case PMAC_MB_INFO_FLAGS:
+- return pmac_mb.board_flags;
+- case PMAC_MB_INFO_NAME:
+- /* hack hack hack... but should work */
+- *((const char **)value) = pmac_mb.model_name;
+- return 0;
+- }
+- return -EINVAL;
+-}
+-
+-
+-/*
+- * Table definitions
+- */
+-
+-/* Used on any machine
+- */
+-static struct feature_table_entry any_features[] __pmacdata = {
+- { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },
+- { 0, NULL }
+-};
+-
+-/* G5 features
+- */
+-static struct feature_table_entry g5_features[] __pmacdata = {
+- { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },
+- { PMAC_FTR_1394_ENABLE, g5_fw_enable },
+- { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
+- { PMAC_FTR_READ_GPIO, g5_read_gpio },
+- { PMAC_FTR_WRITE_GPIO, g5_write_gpio },
+- { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset },
+- { PMAC_FTR_SOUND_CHIP_ENABLE, g5_i2s_enable },
+-#ifdef CONFIG_SMP
+- { PMAC_FTR_RESET_CPU, g5_reset_cpu },
+-#endif /* CONFIG_SMP */
+- { 0, NULL }
+-};
+-
+-static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
+- { "PowerMac7,2", "PowerMac G5",
+- PMAC_TYPE_POWERMAC_G5, g5_features,
+- 0,
+- },
+- { "PowerMac7,3", "PowerMac G5",
+- PMAC_TYPE_POWERMAC_G5, g5_features,
+- 0,
+- },
+- { "PowerMac8,1", "iMac G5",
+- PMAC_TYPE_IMAC_G5, g5_features,
+- 0,
+- },
+- { "PowerMac9,1", "PowerMac G5",
+- PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
+- 0,
+- },
+- { "RackMac3,1", "XServe G5",
+- PMAC_TYPE_XSERVE_G5, g5_features,
+- 0,
+- },
+-};
+-
+-/*
+- * The toplevel feature_call callback
+- */
+-long __pmac pmac_do_feature_call(unsigned int selector, ...)
+-{
+- struct device_node* node;
+- long param, value;
+- int i;
+- feature_call func = NULL;
+- va_list args;
+-
+- if (pmac_mb.features)
+- for (i=0; pmac_mb.features[i].function; i++)
+- if (pmac_mb.features[i].selector == selector) {
+- func = pmac_mb.features[i].function;
+- break;
+- }
+- if (!func)
+- for (i=0; any_features[i].function; i++)
+- if (any_features[i].selector == selector) {
+- func = any_features[i].function;
+- break;
+- }
+- if (!func)
+- return -ENODEV;
+-
+- va_start(args, selector);
+- node = (struct device_node*)va_arg(args, void*);
+- param = va_arg(args, long);
+- value = va_arg(args, long);
+- va_end(args);
+-
+- return func(node, param, value);
+-}
+-
+-static int __init probe_motherboard(void)
+-{
+- int i;
+- struct macio_chip* macio = &macio_chips[0];
+- const char* model = NULL;
+- struct device_node *dt;
+-
+- /* Lookup known motherboard type in device-tree. First try an
+- * exact match on the "model" property, then try a "compatible"
+- * match is none is found.
+- */
+- dt = find_devices("device-tree");
+- if (dt != NULL)
+- model = (const char *) get_property(dt, "model", NULL);
+- for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+- if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
+- pmac_mb = pmac_mb_defs[i];
+- goto found;
+- }
+- }
+- for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+- if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
+- pmac_mb = pmac_mb_defs[i];
+- goto found;
+- }
+- }
+-
+- /* Fallback to selection depending on mac-io chip type */
+- switch(macio->type) {
+- case macio_keylargo2:
+- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
+- pmac_mb.model_name = "Unknown K2-based";
+- pmac_mb.features = g5_features;
+-
+- default:
+- return -ENODEV;
+- }
+-found:
+- /* Check for "mobile" machine */
+- if (model && (strncmp(model, "PowerBook", 9) == 0
+- || strncmp(model, "iBook", 5) == 0))
+- pmac_mb.board_flags |= PMAC_MB_MOBILE;
+-
+-
+- printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
+- return 0;
+-}
+-
+-/* Initialize the Core99 UniNorth host bridge and memory controller
+- */
+-static void __init probe_uninorth(void)
+-{
+- uninorth_node = of_find_node_by_name(NULL, "u3");
+- if (uninorth_node && uninorth_node->n_addrs > 0) {
+- /* Small hack until I figure out if parsing in prom.c is correct. I should
+- * get rid of those pre-parsed junk anyway
+- */
+- unsigned long address = uninorth_node->addrs[0].address;
+- uninorth_base = ioremap(address, 0x40000);
+- uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+- u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
+- } else
+- uninorth_node = NULL;
+-
+- if (!uninorth_node)
+- return;
+-
+- printk(KERN_INFO "Found U3 memory controller & host bridge, revision: %d\n",
+- uninorth_rev);
+- printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
+-
+-}
+-
+-static void __init probe_one_macio(const char* name, const char* compat, int type)
+-{
+- struct device_node* node;
+- int i;
+- volatile u32* base;
+- u32* revp;
+-
+- node = find_devices(name);
+- if (!node || !node->n_addrs)
+- return;
+- if (compat)
+- do {
+- if (device_is_compatible(node, compat))
+- break;
+- node = node->next;
+- } while (node);
+- if (!node)
+- return;
+- for(i=0; i<MAX_MACIO_CHIPS; i++) {
+- if (!macio_chips[i].of_node)
+- break;
+- if (macio_chips[i].of_node == node)
+- return;
+- }
+- if (i >= MAX_MACIO_CHIPS) {
+- printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
+- printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
+- return;
+- }
+- base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size);
+- if (!base) {
+- printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
+- return;
+- }
+- if (type == macio_keylargo) {
+- u32* did = (u32 *)get_property(node, "device-id", NULL);
+- if (*did == 0x00000025)
+- type = macio_pangea;
+- if (*did == 0x0000003e)
+- type = macio_intrepid;
+- }
+- macio_chips[i].of_node = node;
+- macio_chips[i].type = type;
+- macio_chips[i].base = base;
+- macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
+- macio_chips[i].name = macio_names[type];
+- revp = (u32 *)get_property(node, "revision-id", NULL);
+- if (revp)
+- macio_chips[i].rev = *revp;
+- printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
+- macio_names[type], macio_chips[i].rev, macio_chips[i].base);
+-}
+-
+-static int __init
+-probe_macios(void)
+-{
+- probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);
+-
+- macio_chips[0].lbus.index = 0;
+- macio_chips[1].lbus.index = 1;
+-
+- return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
+-}
+-
+-static void __init
+-set_initial_features(void)
+-{
+- struct device_node *np;
+-
+- if (macio_chips[0].type == macio_keylargo2) {
+-#ifndef CONFIG_SMP
+- /* On SMP machines running UP, we have the second CPU eating
+- * bus cycles. We need to take it off the bus. This is done
+- * from pmac_smp for SMP kernels running on one CPU
+- */
+- np = of_find_node_by_type(NULL, "cpu");
+- if (np != NULL)
+- np = of_find_node_by_type(np, "cpu");
+- if (np != NULL) {
+- g5_phy_disable_cpu1();
+- of_node_put(np);
+- }
+-#endif /* CONFIG_SMP */
+- /* Enable GMAC for now for PCI probing. It will be disabled
+- * later on after PCI probe
+- */
+- np = of_find_node_by_name(NULL, "ethernet");
+- while(np) {
+- if (device_is_compatible(np, "K2-GMAC"))
+- g5_gmac_enable(np, 0, 1);
+- np = of_find_node_by_name(np, "ethernet");
+- }
+-
+- /* Enable FW before PCI probe. Will be disabled later on
+- * Note: We should have a batter way to check that we are
+- * dealing with uninorth internal cell and not a PCI cell
+- * on the external PCI. The code below works though.
+- */
+- np = of_find_node_by_name(NULL, "firewire");
+- while(np) {
+- if (device_is_compatible(np, "pci106b,5811")) {
+- macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
+- g5_fw_enable(np, 0, 1);
+- }
+- np = of_find_node_by_name(np, "firewire");
+- }
+- }
+-}
+-
+-void __init
+-pmac_feature_init(void)
+-{
+- /* Detect the UniNorth memory controller */
+- probe_uninorth();
+-
+- /* Probe mac-io controllers */
+- if (probe_macios()) {
+- printk(KERN_WARNING "No mac-io chip found\n");
+- return;
+- }
+-
+- /* Setup low-level i2c stuffs */
+- pmac_init_low_i2c();
+-
+- /* Probe machine type */
+- if (probe_motherboard())
+- printk(KERN_WARNING "Unknown PowerMac !\n");
+-
+- /* Set some initial features (turn off some chips that will
+- * be later turned on)
+- */
+- set_initial_features();
+-}
+-
+-int __init pmac_feature_late_init(void)
+-{
+-#if 0
+- struct device_node* np;
+-
+- /* Request some resources late */
+- if (uninorth_node)
+- request_OF_resource(uninorth_node, 0, NULL);
+- np = find_devices("hammerhead");
+- if (np)
+- request_OF_resource(np, 0, NULL);
+- np = find_devices("interrupt-controller");
+- if (np)
+- request_OF_resource(np, 0, NULL);
+-#endif
+- return 0;
+-}
+-
+-device_initcall(pmac_feature_late_init);
+-
+-#if 0
+-static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
+-{
+- int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
+- int bits[8] = { 8,16,0,32,2,4,0,0 };
+- int freq = (frq >> 8) & 0xf;
+-
+- if (freqs[freq] == 0)
+- printk("%s: Unknown HT link frequency %x\n", name, freq);
+- else
+- printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",
+- name, freqs[freq],
+- bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
+-}
+-#endif
+-
+-void __init pmac_check_ht_link(void)
+-{
+-#if 0 /* Disabled for now */
+- u32 ufreq, freq, ucfg, cfg;
+- struct device_node *pcix_node;
+- struct pci_dn *pdn;
+- u8 px_bus, px_devfn;
+- struct pci_controller *px_hose;
+-
+- (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
+- ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
+- ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
+- dump_HT_speeds("U3 HyperTransport", cfg, freq);
+-
+- pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
+- if (pcix_node == NULL) {
+- printk("No PCI-X bridge found\n");
+- return;
+- }
+- pdn = pcix_node->data;
+- px_hose = pdn->phb;
+- px_bus = pdn->busno;
+- px_devfn = pdn->devfn;
+-
+- early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
+- early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
+- dump_HT_speeds("PCI-X HT Uplink", cfg, freq);
+- early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
+- early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
+- dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
+-#endif
+-}
+-
+-/*
+- * Early video resume hook
+- */
+-
+-static void (*pmac_early_vresume_proc)(void *data) __pmacdata;
+-static void *pmac_early_vresume_data __pmacdata;
+-
+-void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
+-{
+- if (_machine != _MACH_Pmac)
+- return;
+- preempt_disable();
+- pmac_early_vresume_proc = proc;
+- pmac_early_vresume_data = data;
+- preempt_enable();
+-}
+-EXPORT_SYMBOL(pmac_set_early_video_resume);
+-
+-
+-/*
+- * AGP related suspend/resume code
+- */
+-
+-static struct pci_dev *pmac_agp_bridge __pmacdata;
+-static int (*pmac_agp_suspend)(struct pci_dev *bridge) __pmacdata;
+-static int (*pmac_agp_resume)(struct pci_dev *bridge) __pmacdata;
+-
+-void __pmac pmac_register_agp_pm(struct pci_dev *bridge,
+- int (*suspend)(struct pci_dev *bridge),
+- int (*resume)(struct pci_dev *bridge))
+-{
+- if (suspend || resume) {
+- pmac_agp_bridge = bridge;
+- pmac_agp_suspend = suspend;
+- pmac_agp_resume = resume;
+- return;
+- }
+- if (bridge != pmac_agp_bridge)
+- return;
+- pmac_agp_suspend = pmac_agp_resume = NULL;
+- return;
+-}
+-EXPORT_SYMBOL(pmac_register_agp_pm);
+-
+-void __pmac pmac_suspend_agp_for_card(struct pci_dev *dev)
+-{
+- if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
+- return;
+- if (pmac_agp_bridge->bus != dev->bus)
+- return;
+- pmac_agp_suspend(pmac_agp_bridge);
+-}
+-EXPORT_SYMBOL(pmac_suspend_agp_for_card);
+-
+-void __pmac pmac_resume_agp_for_card(struct pci_dev *dev)
+-{
+- if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
+- return;
+- if (pmac_agp_bridge->bus != dev->bus)
+- return;
+- pmac_agp_resume(pmac_agp_bridge);
+-}
+-EXPORT_SYMBOL(pmac_resume_agp_for_card);
+diff --git a/arch/ppc64/kernel/pmac_low_i2c.c b/arch/ppc64/kernel/pmac_low_i2c.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac_low_i2c.c
++++ /dev/null
+@@ -1,523 +0,0 @@
+-/*
+- * arch/ppc/platforms/pmac_low_i2c.c
+- *
+- * Copyright (C) 2003 Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * This file contains some low-level i2c access routines that
+- * need to be used by various bits of the PowerMac platform code
+- * at times where the real asynchronous & interrupt driven driver
+- * cannot be used. The API borrows some semantics from the darwin
+- * driver in order to ease the implementation of the platform
+- * properties parser
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/types.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/adb.h>
+-#include <linux/pmu.h>
+-#include <asm/keylargo.h>
+-#include <asm/uninorth.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pmac_low_i2c.h>
+-
+-#define MAX_LOW_I2C_HOST 4
+-
+-#ifdef DEBUG
+-#define DBG(x...) do {\
+- printk(KERN_DEBUG "KW:" x); \
+- } while(0)
+-#else
+-#define DBG(x...)
+-#endif
+-
+-struct low_i2c_host;
+-
+-typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);
+-
+-struct low_i2c_host
+-{
+- struct device_node *np; /* OF device node */
+- struct semaphore mutex; /* Access mutex for use by i2c-keywest */
+- low_i2c_func_t func; /* Access function */
+- unsigned int is_open : 1; /* Poor man's access control */
+- int mode; /* Current mode */
+- int channel; /* Current channel */
+- int num_channels; /* Number of channels */
+- void __iomem *base; /* For keywest-i2c, base address */
+- int bsteps; /* And register stepping */
+- int speed; /* And speed */
+-};
+-
+-static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST];
+-
+-/* No locking is necessary on allocation, we are running way before
+- * anything can race with us
+- */
+-static struct low_i2c_host *find_low_i2c_host(struct device_node *np)
+-{
+- int i;
+-
+- for (i = 0; i < MAX_LOW_I2C_HOST; i++)
+- if (low_i2c_hosts[i].np == np)
+- return &low_i2c_hosts[i];
+- return NULL;
+-}
+-
+-/*
+- *
+- * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
+- *
+- */
+-
+-/*
+- * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
+- * should be moved somewhere in include/asm-ppc/
+- */
+-/* Register indices */
+-typedef enum {
+- reg_mode = 0,
+- reg_control,
+- reg_status,
+- reg_isr,
+- reg_ier,
+- reg_addr,
+- reg_subaddr,
+- reg_data
+-} reg_t;
+-
+-
+-/* Mode register */
+-#define KW_I2C_MODE_100KHZ 0x00
+-#define KW_I2C_MODE_50KHZ 0x01
+-#define KW_I2C_MODE_25KHZ 0x02
+-#define KW_I2C_MODE_DUMB 0x00
+-#define KW_I2C_MODE_STANDARD 0x04
+-#define KW_I2C_MODE_STANDARDSUB 0x08
+-#define KW_I2C_MODE_COMBINED 0x0C
+-#define KW_I2C_MODE_MODE_MASK 0x0C
+-#define KW_I2C_MODE_CHAN_MASK 0xF0
+-
+-/* Control register */
+-#define KW_I2C_CTL_AAK 0x01
+-#define KW_I2C_CTL_XADDR 0x02
+-#define KW_I2C_CTL_STOP 0x04
+-#define KW_I2C_CTL_START 0x08
+-
+-/* Status register */
+-#define KW_I2C_STAT_BUSY 0x01
+-#define KW_I2C_STAT_LAST_AAK 0x02
+-#define KW_I2C_STAT_LAST_RW 0x04
+-#define KW_I2C_STAT_SDA 0x08
+-#define KW_I2C_STAT_SCL 0x10
+-
+-/* IER & ISR registers */
+-#define KW_I2C_IRQ_DATA 0x01
+-#define KW_I2C_IRQ_ADDR 0x02
+-#define KW_I2C_IRQ_STOP 0x04
+-#define KW_I2C_IRQ_START 0x08
+-#define KW_I2C_IRQ_MASK 0x0F
+-
+-/* State machine states */
+-enum {
+- state_idle,
+- state_addr,
+- state_read,
+- state_write,
+- state_stop,
+- state_dead
+-};
+-
+-#define WRONG_STATE(name) do {\
+- printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
+- name, __kw_state_names[state], isr); \
+- } while(0)
+-
+-static const char *__kw_state_names[] = {
+- "state_idle",
+- "state_addr",
+- "state_read",
+- "state_write",
+- "state_stop",
+- "state_dead"
+-};
+-
+-static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
+-{
+- return readb(host->base + (((unsigned int)reg) << host->bsteps));
+-}
+-
+-static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
+-{
+- writeb(val, host->base + (((unsigned)reg) << host->bsteps));
+- (void)__kw_read_reg(host, reg_subaddr);
+-}
+-
+-#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
+-#define kw_read_reg(reg) __kw_read_reg(host, reg)
+-
+-
+-/* Don't schedule, the g5 fan controller is too
+- * timing sensitive
+- */
+-static u8 kw_wait_interrupt(struct low_i2c_host* host)
+-{
+- int i, j;
+- u8 isr;
+-
+- for (i = 0; i < 100000; i++) {
+- isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
+- if (isr != 0)
+- return isr;
+-
+- /* This code is used with the timebase frozen, we cannot rely
+- * on udelay ! For now, just use a bogus loop
+- */
+- for (j = 1; j < 10000; j++)
+- mb();
+- }
+- return isr;
+-}
+-
+-static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)
+-{
+- u8 ack;
+-
+- DBG("kw_handle_interrupt(%s, isr: %x)\n", __kw_state_names[state], isr);
+-
+- if (isr == 0) {
+- if (state != state_stop) {
+- DBG("KW: Timeout !\n");
+- *rc = -EIO;
+- goto stop;
+- }
+- if (state == state_stop) {
+- ack = kw_read_reg(reg_status);
+- if (!(ack & KW_I2C_STAT_BUSY)) {
+- state = state_idle;
+- kw_write_reg(reg_ier, 0x00);
+- }
+- }
+- return state;
+- }
+-
+- if (isr & KW_I2C_IRQ_ADDR) {
+- ack = kw_read_reg(reg_status);
+- if (state != state_addr) {
+- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
+- WRONG_STATE("KW_I2C_IRQ_ADDR");
+- *rc = -EIO;
+- goto stop;
+- }
+- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
+- *rc = -ENODEV;
+- DBG("KW: NAK on address\n");
+- return state_stop;
+- } else {
+- if (rw) {
+- state = state_read;
+- if (*len > 1)
+- kw_write_reg(reg_control, KW_I2C_CTL_AAK);
+- } else {
+- state = state_write;
+- kw_write_reg(reg_data, **data);
+- (*data)++; (*len)--;
+- }
+- }
+- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
+- }
+-
+- if (isr & KW_I2C_IRQ_DATA) {
+- if (state == state_read) {
+- **data = kw_read_reg(reg_data);
+- (*data)++; (*len)--;
+- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+- if ((*len) == 0)
+- state = state_stop;
+- else if ((*len) == 1)
+- kw_write_reg(reg_control, 0);
+- } else if (state == state_write) {
+- ack = kw_read_reg(reg_status);
+- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
+- DBG("KW: nack on data write\n");
+- *rc = -EIO;
+- goto stop;
+- } else if (*len) {
+- kw_write_reg(reg_data, **data);
+- (*data)++; (*len)--;
+- } else {
+- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+- state = state_stop;
+- *rc = 0;
+- }
+- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+- } else {
+- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+- WRONG_STATE("KW_I2C_IRQ_DATA");
+- if (state != state_stop) {
+- *rc = -EIO;
+- goto stop;
+- }
+- }
+- }
+-
+- if (isr & KW_I2C_IRQ_STOP) {
+- kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
+- if (state != state_stop) {
+- WRONG_STATE("KW_I2C_IRQ_STOP");
+- *rc = -EIO;
+- }
+- return state_idle;
+- }
+-
+- if (isr & KW_I2C_IRQ_START)
+- kw_write_reg(reg_isr, KW_I2C_IRQ_START);
+-
+- return state;
+-
+- stop:
+- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+- return state_stop;
+-}
+-
+-static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)
+-{
+- u8 mode_reg = host->speed;
+- int state = state_addr;
+- int rc = 0;
+-
+- /* Setup mode & subaddress if any */
+- switch(host->mode) {
+- case pmac_low_i2c_mode_dumb:
+- printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");
+- return -EINVAL;
+- case pmac_low_i2c_mode_std:
+- mode_reg |= KW_I2C_MODE_STANDARD;
+- break;
+- case pmac_low_i2c_mode_stdsub:
+- mode_reg |= KW_I2C_MODE_STANDARDSUB;
+- break;
+- case pmac_low_i2c_mode_combined:
+- mode_reg |= KW_I2C_MODE_COMBINED;
+- break;
+- }
+-
+- /* Setup channel & clear pending irqs */
+- kw_write_reg(reg_isr, kw_read_reg(reg_isr));
+- kw_write_reg(reg_mode, mode_reg | (host->channel << 4));
+- kw_write_reg(reg_status, 0);
+-
+- /* Set up address and r/w bit */
+- kw_write_reg(reg_addr, addr);
+-
+- /* Set up the sub address */
+- if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
+- || (mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
+- kw_write_reg(reg_subaddr, subaddr);
+-
+- /* Start sending address & disable interrupt*/
+- kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
+- kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
+-
+- /* State machine, to turn into an interrupt handler */
+- while(state != state_idle) {
+- u8 isr = kw_wait_interrupt(host);
+- state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);
+- }
+-
+- return rc;
+-}
+-
+-static void keywest_low_i2c_add(struct device_node *np)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(NULL);
+- u32 *psteps, *prate, steps, aoffset = 0;
+- struct device_node *parent;
+-
+- if (host == NULL) {
+- printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
+- np->full_name);
+- return;
+- }
+- memset(host, 0, sizeof(*host));
+-
+- init_MUTEX(&host->mutex);
+- host->np = of_node_get(np);
+- psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
+- steps = psteps ? (*psteps) : 0x10;
+- for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
+- steps >>= 1;
+- parent = of_get_parent(np);
+- host->num_channels = 1;
+- if (parent && parent->name[0] == 'u') {
+- host->num_channels = 2;
+- aoffset = 3;
+- }
+- /* Select interface rate */
+- host->speed = KW_I2C_MODE_100KHZ;
+- prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
+- if (prate) switch(*prate) {
+- case 100:
+- host->speed = KW_I2C_MODE_100KHZ;
+- break;
+- case 50:
+- host->speed = KW_I2C_MODE_50KHZ;
+- break;
+- case 25:
+- host->speed = KW_I2C_MODE_25KHZ;
+- break;
+- }
+-
+- host->mode = pmac_low_i2c_mode_std;
+- host->base = ioremap(np->addrs[0].address + aoffset,
+- np->addrs[0].size);
+- host->func = keywest_low_i2c_func;
+-}
+-
+-/*
+- *
+- * PMU implementation
+- *
+- */
+-
+-
+-#ifdef CONFIG_ADB_PMU
+-
+-static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)
+-{
+- // TODO
+- return -ENODEV;
+-}
+-
+-static void pmu_low_i2c_add(struct device_node *np)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(NULL);
+-
+- if (host == NULL) {
+- printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
+- np->full_name);
+- return;
+- }
+- memset(host, 0, sizeof(*host));
+-
+- init_MUTEX(&host->mutex);
+- host->np = of_node_get(np);
+- host->num_channels = 3;
+- host->mode = pmac_low_i2c_mode_std;
+- host->func = pmu_low_i2c_func;
+-}
+-
+-#endif /* CONFIG_ADB_PMU */
+-
+-void __init pmac_init_low_i2c(void)
+-{
+- struct device_node *np;
+-
+- /* Probe keywest-i2c busses */
+- np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");
+- while(np) {
+- keywest_low_i2c_add(np);
+- np = of_find_compatible_node(np, "i2c", "keywest-i2c");
+- }
+-
+-#ifdef CONFIG_ADB_PMU
+- /* Probe PMU busses */
+- np = of_find_node_by_name(NULL, "via-pmu");
+- if (np)
+- pmu_low_i2c_add(np);
+-#endif /* CONFIG_ADB_PMU */
+-
+- /* TODO: Add CUDA support as well */
+-}
+-
+-int pmac_low_i2c_lock(struct device_node *np)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(np);
+-
+- if (!host)
+- return -ENODEV;
+- down(&host->mutex);
+- return 0;
+-}
+-EXPORT_SYMBOL(pmac_low_i2c_lock);
+-
+-int pmac_low_i2c_unlock(struct device_node *np)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(np);
+-
+- if (!host)
+- return -ENODEV;
+- up(&host->mutex);
+- return 0;
+-}
+-EXPORT_SYMBOL(pmac_low_i2c_unlock);
+-
+-
+-int pmac_low_i2c_open(struct device_node *np, int channel)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(np);
+-
+- if (!host)
+- return -ENODEV;
+-
+- if (channel >= host->num_channels)
+- return -EINVAL;
+-
+- down(&host->mutex);
+- host->is_open = 1;
+- host->channel = channel;
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(pmac_low_i2c_open);
+-
+-int pmac_low_i2c_close(struct device_node *np)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(np);
+-
+- if (!host)
+- return -ENODEV;
+-
+- host->is_open = 0;
+- up(&host->mutex);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(pmac_low_i2c_close);
+-
+-int pmac_low_i2c_setmode(struct device_node *np, int mode)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(np);
+-
+- if (!host)
+- return -ENODEV;
+- WARN_ON(!host->is_open);
+- host->mode = mode;
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(pmac_low_i2c_setmode);
+-
+-int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)
+-{
+- struct low_i2c_host *host = find_low_i2c_host(np);
+-
+- if (!host)
+- return -ENODEV;
+- WARN_ON(!host->is_open);
+-
+- return host->func(host, addrdir, subaddr, data, len);
+-}
+-EXPORT_SYMBOL(pmac_low_i2c_xfer);
+-
+diff --git a/arch/ppc64/kernel/pmac_nvram.c b/arch/ppc64/kernel/pmac_nvram.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac_nvram.c
++++ /dev/null
+@@ -1,495 +0,0 @@
+-/*
+- * arch/ppc/platforms/pmac_nvram.c
+- *
+- * Copyright (C) 2002 Benjamin Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Todo: - add support for the OF persistent properties
+- */
+-#include <linux/config.h>
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/stddef.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/delay.h>
+-#include <linux/errno.h>
+-#include <linux/bootmem.h>
+-#include <linux/completion.h>
+-#include <linux/spinlock.h>
+-#include <asm/sections.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/nvram.h>
+-
+-#define DEBUG
+-
+-#ifdef DEBUG
+-#define DBG(x...) printk(x)
+-#else
+-#define DBG(x...)
+-#endif
+-
+-#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
+-
+-#define CORE99_SIGNATURE 0x5a
+-#define CORE99_ADLER_START 0x14
+-
+-/* On Core99, nvram is either a sharp, a micron or an AMD flash */
+-#define SM_FLASH_STATUS_DONE 0x80
+-#define SM_FLASH_STATUS_ERR 0x38
+-
+-#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0
+-#define SM_FLASH_CMD_ERASE_SETUP 0x20
+-#define SM_FLASH_CMD_RESET 0xff
+-#define SM_FLASH_CMD_WRITE_SETUP 0x40
+-#define SM_FLASH_CMD_CLEAR_STATUS 0x50
+-#define SM_FLASH_CMD_READ_STATUS 0x70
+-
+-/* CHRP NVRAM header */
+-struct chrp_header {
+- u8 signature;
+- u8 cksum;
+- u16 len;
+- char name[12];
+- u8 data[0];
+-};
+-
+-struct core99_header {
+- struct chrp_header hdr;
+- u32 adler;
+- u32 generation;
+- u32 reserved[2];
+-};
+-
+-/*
+- * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
+- */
+-static volatile unsigned char *nvram_data;
+-static int core99_bank = 0;
+-// XXX Turn that into a sem
+-static DEFINE_SPINLOCK(nv_lock);
+-
+-extern int system_running;
+-
+-static int (*core99_write_bank)(int bank, u8* datas);
+-static int (*core99_erase_bank)(int bank);
+-
+-static char *nvram_image __pmacdata;
+-
+-
+-static ssize_t __pmac core99_nvram_read(char *buf, size_t count, loff_t *index)
+-{
+- int i;
+-
+- if (nvram_image == NULL)
+- return -ENODEV;
+- if (*index > NVRAM_SIZE)
+- return 0;
+-
+- i = *index;
+- if (i + count > NVRAM_SIZE)
+- count = NVRAM_SIZE - i;
+-
+- memcpy(buf, &nvram_image[i], count);
+- *index = i + count;
+- return count;
+-}
+-
+-static ssize_t __pmac core99_nvram_write(char *buf, size_t count, loff_t *index)
+-{
+- int i;
+-
+- if (nvram_image == NULL)
+- return -ENODEV;
+- if (*index > NVRAM_SIZE)
+- return 0;
+-
+- i = *index;
+- if (i + count > NVRAM_SIZE)
+- count = NVRAM_SIZE - i;
+-
+- memcpy(&nvram_image[i], buf, count);
+- *index = i + count;
+- return count;
+-}
+-
+-static ssize_t __pmac core99_nvram_size(void)
+-{
+- if (nvram_image == NULL)
+- return -ENODEV;
+- return NVRAM_SIZE;
+-}
+-
+-static u8 __pmac chrp_checksum(struct chrp_header* hdr)
+-{
+- u8 *ptr;
+- u16 sum = hdr->signature;
+- for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
+- sum += *ptr;
+- while (sum > 0xFF)
+- sum = (sum & 0xFF) + (sum>>8);
+- return sum;
+-}
+-
+-static u32 __pmac core99_calc_adler(u8 *buffer)
+-{
+- int cnt;
+- u32 low, high;
+-
+- buffer += CORE99_ADLER_START;
+- low = 1;
+- high = 0;
+- for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
+- if ((cnt % 5000) == 0) {
+- high %= 65521UL;
+- high %= 65521UL;
+- }
+- low += buffer[cnt];
+- high += low;
+- }
+- low %= 65521UL;
+- high %= 65521UL;
+-
+- return (high << 16) | low;
+-}
+-
+-static u32 __pmac core99_check(u8* datas)
+-{
+- struct core99_header* hdr99 = (struct core99_header*)datas;
+-
+- if (hdr99->hdr.signature != CORE99_SIGNATURE) {
+- DBG("Invalid signature\n");
+- return 0;
+- }
+- if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
+- DBG("Invalid checksum\n");
+- return 0;
+- }
+- if (hdr99->adler != core99_calc_adler(datas)) {
+- DBG("Invalid adler\n");
+- return 0;
+- }
+- return hdr99->generation;
+-}
+-
+-static int __pmac sm_erase_bank(int bank)
+-{
+- int stat, i;
+- unsigned long timeout;
+-
+- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+-
+- DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
+-
+- out_8(base, SM_FLASH_CMD_ERASE_SETUP);
+- out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
+- timeout = 0;
+- do {
+- if (++timeout > 1000000) {
+- printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n");
+- break;
+- }
+- out_8(base, SM_FLASH_CMD_READ_STATUS);
+- stat = in_8(base);
+- } while (!(stat & SM_FLASH_STATUS_DONE));
+-
+- out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
+- out_8(base, SM_FLASH_CMD_RESET);
+-
+- for (i=0; i<NVRAM_SIZE; i++)
+- if (base[i] != 0xff) {
+- printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
+- return -ENXIO;
+- }
+- return 0;
+-}
+-
+-static int __pmac sm_write_bank(int bank, u8* datas)
+-{
+- int i, stat = 0;
+- unsigned long timeout;
+-
+- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+-
+- DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
+-
+- for (i=0; i<NVRAM_SIZE; i++) {
+- out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
+- udelay(1);
+- out_8(base+i, datas[i]);
+- timeout = 0;
+- do {
+- if (++timeout > 1000000) {
+- printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
+- break;
+- }
+- out_8(base, SM_FLASH_CMD_READ_STATUS);
+- stat = in_8(base);
+- } while (!(stat & SM_FLASH_STATUS_DONE));
+- if (!(stat & SM_FLASH_STATUS_DONE))
+- break;
+- }
+- out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
+- out_8(base, SM_FLASH_CMD_RESET);
+- for (i=0; i<NVRAM_SIZE; i++)
+- if (base[i] != datas[i]) {
+- printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
+- return -ENXIO;
+- }
+- return 0;
+-}
+-
+-static int __pmac amd_erase_bank(int bank)
+-{
+- int i, stat = 0;
+- unsigned long timeout;
+-
+- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+-
+- DBG("nvram: AMD Erasing bank %d...\n", bank);
+-
+- /* Unlock 1 */
+- out_8(base+0x555, 0xaa);
+- udelay(1);
+- /* Unlock 2 */
+- out_8(base+0x2aa, 0x55);
+- udelay(1);
+-
+- /* Sector-Erase */
+- out_8(base+0x555, 0x80);
+- udelay(1);
+- out_8(base+0x555, 0xaa);
+- udelay(1);
+- out_8(base+0x2aa, 0x55);
+- udelay(1);
+- out_8(base, 0x30);
+- udelay(1);
+-
+- timeout = 0;
+- do {
+- if (++timeout > 1000000) {
+- printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
+- break;
+- }
+- stat = in_8(base) ^ in_8(base);
+- } while (stat != 0);
+-
+- /* Reset */
+- out_8(base, 0xf0);
+- udelay(1);
+-
+- for (i=0; i<NVRAM_SIZE; i++)
+- if (base[i] != 0xff) {
+- printk(KERN_ERR "nvram: AMD flash erase failed !\n");
+- return -ENXIO;
+- }
+- return 0;
+-}
+-
+-static int __pmac amd_write_bank(int bank, u8* datas)
+-{
+- int i, stat = 0;
+- unsigned long timeout;
+-
+- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+-
+- DBG("nvram: AMD Writing bank %d...\n", bank);
+-
+- for (i=0; i<NVRAM_SIZE; i++) {
+- /* Unlock 1 */
+- out_8(base+0x555, 0xaa);
+- udelay(1);
+- /* Unlock 2 */
+- out_8(base+0x2aa, 0x55);
+- udelay(1);
+-
+- /* Write single word */
+- out_8(base+0x555, 0xa0);
+- udelay(1);
+- out_8(base+i, datas[i]);
+-
+- timeout = 0;
+- do {
+- if (++timeout > 1000000) {
+- printk(KERN_ERR "nvram: AMD flash write timeout !\n");
+- break;
+- }
+- stat = in_8(base) ^ in_8(base);
+- } while (stat != 0);
+- if (stat != 0)
+- break;
+- }
+-
+- /* Reset */
+- out_8(base, 0xf0);
+- udelay(1);
+-
+- for (i=0; i<NVRAM_SIZE; i++)
+- if (base[i] != datas[i]) {
+- printk(KERN_ERR "nvram: AMD flash write failed !\n");
+- return -ENXIO;
+- }
+- return 0;
+-}
+-
+-
+-static int __pmac core99_nvram_sync(void)
+-{
+- struct core99_header* hdr99;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&nv_lock, flags);
+- if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
+- NVRAM_SIZE))
+- goto bail;
+-
+- DBG("Updating nvram...\n");
+-
+- hdr99 = (struct core99_header*)nvram_image;
+- hdr99->generation++;
+- hdr99->hdr.signature = CORE99_SIGNATURE;
+- hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
+- hdr99->adler = core99_calc_adler(nvram_image);
+- core99_bank = core99_bank ? 0 : 1;
+- if (core99_erase_bank)
+- if (core99_erase_bank(core99_bank)) {
+- printk("nvram: Error erasing bank %d\n", core99_bank);
+- goto bail;
+- }
+- if (core99_write_bank)
+- if (core99_write_bank(core99_bank, nvram_image))
+- printk("nvram: Error writing bank %d\n", core99_bank);
+- bail:
+- spin_unlock_irqrestore(&nv_lock, flags);
+-
+- return 0;
+-}
+-
+-int __init pmac_nvram_init(void)
+-{
+- struct device_node *dp;
+- u32 gen_bank0, gen_bank1;
+- int i;
+-
+- dp = find_devices("nvram");
+- if (dp == NULL) {
+- printk(KERN_ERR "Can't find NVRAM device\n");
+- return -ENODEV;
+- }
+- if (!device_is_compatible(dp, "nvram,flash")) {
+- printk(KERN_ERR "Incompatible type of NVRAM\n");
+- return -ENXIO;
+- }
+-
+- nvram_image = alloc_bootmem(NVRAM_SIZE);
+- if (nvram_image == NULL) {
+- printk(KERN_ERR "nvram: can't allocate ram image\n");
+- return -ENOMEM;
+- }
+- nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
+-
+- DBG("nvram: Checking bank 0...\n");
+-
+- gen_bank0 = core99_check((u8 *)nvram_data);
+- gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
+- core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
+-
+- DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
+- DBG("nvram: Active bank is: %d\n", core99_bank);
+-
+- for (i=0; i<NVRAM_SIZE; i++)
+- nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
+-
+- ppc_md.nvram_read = core99_nvram_read;
+- ppc_md.nvram_write = core99_nvram_write;
+- ppc_md.nvram_size = core99_nvram_size;
+- ppc_md.nvram_sync = core99_nvram_sync;
+-
+- /*
+- * Maybe we could be smarter here though making an exclusive list
+- * of known flash chips is a bit nasty as older OF didn't provide us
+- * with a useful "compatible" entry. A solution would be to really
+- * identify the chip using flash id commands and base ourselves on
+- * a list of known chips IDs
+- */
+- if (device_is_compatible(dp, "amd-0137")) {
+- core99_erase_bank = amd_erase_bank;
+- core99_write_bank = amd_write_bank;
+- } else {
+- core99_erase_bank = sm_erase_bank;
+- core99_write_bank = sm_write_bank;
+- }
+-
+- return 0;
+-}
+-
+-int __pmac pmac_get_partition(int partition)
+-{
+- struct nvram_partition *part;
+- const char *name;
+- int sig;
+-
+- switch(partition) {
+- case pmac_nvram_OF:
+- name = "common";
+- sig = NVRAM_SIG_SYS;
+- break;
+- case pmac_nvram_XPRAM:
+- name = "APL,MacOS75";
+- sig = NVRAM_SIG_OS;
+- break;
+- case pmac_nvram_NR:
+- default:
+- /* Oldworld stuff */
+- return -ENODEV;
+- }
+-
+- part = nvram_find_partition(sig, name);
+- if (part == NULL)
+- return 0;
+-
+- return part->index;
+-}
+-
+-u8 __pmac pmac_xpram_read(int xpaddr)
+-{
+- int offset = pmac_get_partition(pmac_nvram_XPRAM);
+- loff_t index;
+- u8 buf;
+- ssize_t count;
+-
+- if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
+- return 0xff;
+- index = offset + xpaddr;
+-
+- count = ppc_md.nvram_read(&buf, 1, &index);
+- if (count != 1)
+- return 0xff;
+- return buf;
+-}
+-
+-void __pmac pmac_xpram_write(int xpaddr, u8 data)
+-{
+- int offset = pmac_get_partition(pmac_nvram_XPRAM);
+- loff_t index;
+- u8 buf;
+-
+- if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
+- return;
+- index = offset + xpaddr;
+- buf = data;
+-
+- ppc_md.nvram_write(&buf, 1, &index);
+-}
+-
+-EXPORT_SYMBOL(pmac_get_partition);
+-EXPORT_SYMBOL(pmac_xpram_read);
+-EXPORT_SYMBOL(pmac_xpram_write);
+diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac_pci.c
++++ /dev/null
+@@ -1,793 +0,0 @@
+-/*
+- * Support for PCI bridges found on Power Macintoshes.
+- * At present the "bandit" and "chaos" bridges are supported.
+- * Fortunately you access configuration space in the same
+- * way with either bridge.
+- *
+- * Copyright (C) 2003 Benjamin Herrenschmuidt (benh at kernel.crashing.org)
+- * Copyright (C) 1997 Paul Mackerras (paulus at samba.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/kernel.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-#include <linux/bootmem.h>
+-
+-#include <asm/sections.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/machdep.h>
+-#include <asm/pmac_feature.h>
+-#include <asm/iommu.h>
+-
+-#include "pci.h"
+-#include "pmac.h"
+-
+-#define DEBUG
+-
+-#ifdef DEBUG
+-#define DBG(x...) printk(x)
+-#else
+-#define DBG(x...)
+-#endif
+-
+-/* XXX Could be per-controller, but I don't think we risk anything by
+- * assuming we won't have both UniNorth and Bandit */
+-static int has_uninorth;
+-static struct pci_controller *u3_agp;
+-struct device_node *k2_skiplist[2];
+-
+-static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
+-{
+- for (; node != 0;node = node->sibling) {
+- int * bus_range;
+- unsigned int *class_code;
+- int len;
+-
+- /* For PCI<->PCI bridges or CardBus bridges, we go down */
+- class_code = (unsigned int *) get_property(node, "class-code", NULL);
+- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+- continue;
+- bus_range = (int *) get_property(node, "bus-range", &len);
+- if (bus_range != NULL && len > 2 * sizeof(int)) {
+- if (bus_range[1] > higher)
+- higher = bus_range[1];
+- }
+- higher = fixup_one_level_bus_range(node->child, higher);
+- }
+- return higher;
+-}
+-
+-/* This routine fixes the "bus-range" property of all bridges in the
+- * system since they tend to have their "last" member wrong on macs
+- *
+- * Note that the bus numbers manipulated here are OF bus numbers, they
+- * are not Linux bus numbers.
+- */
+-static void __init fixup_bus_range(struct device_node *bridge)
+-{
+- int * bus_range;
+- int len;
+-
+- /* Lookup the "bus-range" property for the hose */
+- bus_range = (int *) get_property(bridge, "bus-range", &len);
+- if (bus_range == NULL || len < 2 * sizeof(int)) {
+- printk(KERN_WARNING "Can't get bus-range for %s\n",
+- bridge->full_name);
+- return;
+- }
+- bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
+-}
+-
+-/*
+- * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers.
+- *
+- * The "Bandit" version is present in all early PCI PowerMacs,
+- * and up to the first ones using Grackle. Some machines may
+- * have 2 bandit controllers (2 PCI busses).
+- *
+- * "Chaos" is used in some "Bandit"-type machines as a bridge
+- * for the separate display bus. It is accessed the same
+- * way as bandit, but cannot be probed for devices. It therefore
+- * has its own config access functions.
+- *
+- * The "UniNorth" version is present in all Core99 machines
+- * (iBook, G4, new IMacs, and all the recent Apple machines).
+- * It contains 3 controllers in one ASIC.
+- *
+- * The U3 is the bridge used on G5 machines. It contains on
+- * AGP bus which is dealt with the old UniNorth access routines
+- * and an HyperTransport bus which uses its own set of access
+- * functions.
+- */
+-
+-#define MACRISC_CFA0(devfn, off) \
+- ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
+- | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
+- | (((unsigned long)(off)) & 0xFCUL))
+-
+-#define MACRISC_CFA1(bus, devfn, off) \
+- ((((unsigned long)(bus)) << 16) \
+- |(((unsigned long)(devfn)) << 8) \
+- |(((unsigned long)(off)) & 0xFCUL) \
+- |1UL)
+-
+-static unsigned long __pmac macrisc_cfg_access(struct pci_controller* hose,
+- u8 bus, u8 dev_fn, u8 offset)
+-{
+- unsigned int caddr;
+-
+- if (bus == hose->first_busno) {
+- if (dev_fn < (11 << 3))
+- return 0;
+- caddr = MACRISC_CFA0(dev_fn, offset);
+- } else
+- caddr = MACRISC_CFA1(bus, dev_fn, offset);
+-
+- /* Uninorth will return garbage if we don't read back the value ! */
+- do {
+- out_le32(hose->cfg_addr, caddr);
+- } while (in_le32(hose->cfg_addr) != caddr);
+-
+- offset &= has_uninorth ? 0x07 : 0x03;
+- return ((unsigned long)hose->cfg_data) + offset;
+-}
+-
+-static int __pmac macrisc_read_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 *val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- *val = in_8((u8 *)addr);
+- break;
+- case 2:
+- *val = in_le16((u16 *)addr);
+- break;
+- default:
+- *val = in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static int __pmac macrisc_write_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- out_8((u8 *)addr, val);
+- (void) in_8((u8 *)addr);
+- break;
+- case 2:
+- out_le16((u16 *)addr, val);
+- (void) in_le16((u16 *)addr);
+- break;
+- default:
+- out_le32((u32 *)addr, val);
+- (void) in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops macrisc_pci_ops =
+-{
+- macrisc_read_config,
+- macrisc_write_config
+-};
+-
+-/*
+- * These versions of U3 HyperTransport config space access ops do not
+- * implement self-view of the HT host yet
+- */
+-
+-/*
+- * This function deals with some "special cases" devices.
+- *
+- * 0 -> No special case
+- * 1 -> Skip the device but act as if the access was successfull
+- * (return 0xff's on reads, eventually, cache config space
+- * accesses in a later version)
+- * -1 -> Hide the device (unsuccessful acess)
+- */
+-static int u3_ht_skip_device(struct pci_controller *hose,
+- struct pci_bus *bus, unsigned int devfn)
+-{
+- struct device_node *busdn, *dn;
+- int i;
+-
+- /* We only allow config cycles to devices that are in OF device-tree
+- * as we are apparently having some weird things going on with some
+- * revs of K2 on recent G5s
+- */
+- if (bus->self)
+- busdn = pci_device_to_OF_node(bus->self);
+- else
+- busdn = hose->arch_data;
+- for (dn = busdn->child; dn; dn = dn->sibling)
+- if (dn->data && PCI_DN(dn)->devfn == devfn)
+- break;
+- if (dn == NULL)
+- return -1;
+-
+- /*
+- * When a device in K2 is powered down, we die on config
+- * cycle accesses. Fix that here.
+- */
+- for (i=0; i<2; i++)
+- if (k2_skiplist[i] == dn)
+- return 1;
+-
+- return 0;
+-}
+-
+-#define U3_HT_CFA0(devfn, off) \
+- ((((unsigned long)devfn) << 8) | offset)
+-#define U3_HT_CFA1(bus, devfn, off) \
+- (U3_HT_CFA0(devfn, off) \
+- + (((unsigned long)bus) << 16) \
+- + 0x01000000UL)
+-
+-static unsigned long __pmac u3_ht_cfg_access(struct pci_controller* hose,
+- u8 bus, u8 devfn, u8 offset)
+-{
+- if (bus == hose->first_busno) {
+- /* For now, we don't self probe U3 HT bridge */
+- if (PCI_SLOT(devfn) == 0)
+- return 0;
+- return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
+- } else
+- return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset);
+-}
+-
+-static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 *val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- switch (u3_ht_skip_device(hose, bus, devfn)) {
+- case 0:
+- break;
+- case 1:
+- switch (len) {
+- case 1:
+- *val = 0xff; break;
+- case 2:
+- *val = 0xffff; break;
+- default:
+- *val = 0xfffffffful; break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+- default:
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- *val = in_8((u8 *)addr);
+- break;
+- case 2:
+- *val = in_le16((u16 *)addr);
+- break;
+- default:
+- *val = in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static int __pmac u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
+- int offset, int len, u32 val)
+-{
+- struct pci_controller *hose;
+- unsigned long addr;
+-
+- hose = pci_bus_to_host(bus);
+- if (hose == NULL)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+- if (!addr)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- switch (u3_ht_skip_device(hose, bus, devfn)) {
+- case 0:
+- break;
+- case 1:
+- return PCIBIOS_SUCCESSFUL;
+- default:
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- /*
+- * Note: the caller has already checked that offset is
+- * suitably aligned and that len is 1, 2 or 4.
+- */
+- switch (len) {
+- case 1:
+- out_8((u8 *)addr, val);
+- (void) in_8((u8 *)addr);
+- break;
+- case 2:
+- out_le16((u16 *)addr, val);
+- (void) in_le16((u16 *)addr);
+- break;
+- default:
+- out_le32((u32 *)addr, val);
+- (void) in_le32((u32 *)addr);
+- break;
+- }
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops u3_ht_pci_ops =
+-{
+- u3_ht_read_config,
+- u3_ht_write_config
+-};
+-
+-static void __init setup_u3_agp(struct pci_controller* hose)
+-{
+- /* On G5, we move AGP up to high bus number so we don't need
+- * to reassign bus numbers for HT. If we ever have P2P bridges
+- * on AGP, we'll have to move pci_assign_all_busses to the
+- * pci_controller structure so we enable it for AGP and not for
+- * HT childs.
+- * We hard code the address because of the different size of
+- * the reg address cell, we shall fix that by killing struct
+- * reg_property and using some accessor functions instead
+- */
+- hose->first_busno = 0xf0;
+- hose->last_busno = 0xff;
+- has_uninorth = 1;
+- hose->ops = ¯isc_pci_ops;
+- hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+- hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+-
+- u3_agp = hose;
+-}
+-
+-static void __init setup_u3_ht(struct pci_controller* hose)
+-{
+- struct device_node *np = (struct device_node *)hose->arch_data;
+- int i, cur;
+-
+- hose->ops = &u3_ht_pci_ops;
+-
+- /* We hard code the address because of the different size of
+- * the reg address cell, we shall fix that by killing struct
+- * reg_property and using some accessor functions instead
+- */
+- hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
+-
+- /*
+- * /ht node doesn't expose a "ranges" property, so we "remove" regions that
+- * have been allocated to AGP. So far, this version of the code doesn't assign
+- * any of the 0xfxxxxxxx "fine" memory regions to /ht.
+- * We need to fix that sooner or later by either parsing all child "ranges"
+- * properties or figuring out the U3 address space decoding logic and
+- * then read it's configuration register (if any).
+- */
+- hose->io_base_phys = 0xf4000000;
+- hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
+- isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt;
+- hose->io_resource.name = np->full_name;
+- hose->io_resource.start = 0;
+- hose->io_resource.end = 0x003fffff;
+- hose->io_resource.flags = IORESOURCE_IO;
+- hose->pci_mem_offset = 0;
+- hose->first_busno = 0;
+- hose->last_busno = 0xef;
+- hose->mem_resources[0].name = np->full_name;
+- hose->mem_resources[0].start = 0x80000000;
+- hose->mem_resources[0].end = 0xefffffff;
+- hose->mem_resources[0].flags = IORESOURCE_MEM;
+-
+- if (u3_agp == NULL) {
+- DBG("U3 has no AGP, using full resource range\n");
+- return;
+- }
+-
+- /* We "remove" the AGP resources from the resources allocated to HT, that
+- * is we create "holes". However, that code does assumptions that so far
+- * happen to be true (cross fingers...), typically that resources in the
+- * AGP node are properly ordered
+- */
+- cur = 0;
+- for (i=0; i<3; i++) {
+- struct resource *res = &u3_agp->mem_resources[i];
+- if (res->flags != IORESOURCE_MEM)
+- continue;
+- /* We don't care about "fine" resources */
+- if (res->start >= 0xf0000000)
+- continue;
+- /* Check if it's just a matter of "shrinking" us in one direction */
+- if (hose->mem_resources[cur].start == res->start) {
+- DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
+- cur, hose->mem_resources[cur].start, res->end + 1);
+- hose->mem_resources[cur].start = res->end + 1;
+- continue;
+- }
+- if (hose->mem_resources[cur].end == res->end) {
+- DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
+- cur, hose->mem_resources[cur].end, res->start - 1);
+- hose->mem_resources[cur].end = res->start - 1;
+- continue;
+- }
+- /* No, it's not the case, we need a hole */
+- if (cur == 2) {
+- /* not enough resources for a hole, we drop part of the range */
+- printk(KERN_WARNING "Running out of resources for /ht host !\n");
+- hose->mem_resources[cur].end = res->start - 1;
+- continue;
+- }
+- cur++;
+- DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
+- cur-1, res->start - 1, cur, res->end + 1);
+- hose->mem_resources[cur].name = np->full_name;
+- hose->mem_resources[cur].flags = IORESOURCE_MEM;
+- hose->mem_resources[cur].start = res->end + 1;
+- hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
+- hose->mem_resources[cur-1].end = res->start - 1;
+- }
+-}
+-
+-static void __init pmac_process_bridge_OF_ranges(struct pci_controller *hose,
+- struct device_node *dev, int primary)
+-{
+- static unsigned int static_lc_ranges[2024];
+- unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
+- unsigned int size;
+- int rlen = 0, orig_rlen;
+- int memno = 0;
+- struct resource *res;
+- int np, na = prom_n_addr_cells(dev);
+-
+- np = na + 5;
+-
+- /* First we try to merge ranges to fix a problem with some pmacs
+- * that can have more than 3 ranges, fortunately using contiguous
+- * addresses -- BenH
+- */
+- dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+- if (!dt_ranges)
+- return;
+- /* lc_ranges = alloc_bootmem(rlen);*/
+- lc_ranges = static_lc_ranges;
+- if (!lc_ranges)
+- return; /* what can we do here ? */
+- memcpy(lc_ranges, dt_ranges, rlen);
+- orig_rlen = rlen;
+-
+- /* Let's work on a copy of the "ranges" property instead of damaging
+- * the device-tree image in memory
+- */
+- ranges = lc_ranges;
+- prev = NULL;
+- while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+- if (prev) {
+- if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
+- (prev[2] + prev[na+4]) == ranges[2] &&
+- (prev[na+2] + prev[na+4]) == ranges[na+2]) {
+- prev[na+4] += ranges[na+4];
+- ranges[0] = 0;
+- ranges += np;
+- continue;
+- }
+- }
+- prev = ranges;
+- ranges += np;
+- }
+-
+- /*
+- * The ranges property is laid out as an array of elements,
+- * each of which comprises:
+- * cells 0 - 2: a PCI address
+- * cells 3 or 3+4: a CPU physical address
+- * (size depending on dev->n_addr_cells)
+- * cells 4+5 or 5+6: the size of the range
+- */
+- ranges = lc_ranges;
+- rlen = orig_rlen;
+- while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
+- res = NULL;
+- size = ranges[na+4];
+- switch (ranges[0] >> 24) {
+- case 1: /* I/O space */
+- if (ranges[2] != 0)
+- break;
+- hose->io_base_phys = ranges[na+2];
+- /* limit I/O space to 16MB */
+- if (size > 0x01000000)
+- size = 0x01000000;
+- hose->io_base_virt = ioremap(ranges[na+2], size);
+- if (primary)
+- isa_io_base = (unsigned long) hose->io_base_virt;
+- res = &hose->io_resource;
+- res->flags = IORESOURCE_IO;
+- res->start = ranges[2];
+- break;
+- case 2: /* memory space */
+- memno = 0;
+- if (ranges[1] == 0 && ranges[2] == 0
+- && ranges[na+4] <= (16 << 20)) {
+- /* 1st 16MB, i.e. ISA memory area */
+-#if 0
+- if (primary)
+- isa_mem_base = ranges[na+2];
+-#endif
+- memno = 1;
+- }
+- while (memno < 3 && hose->mem_resources[memno].flags)
+- ++memno;
+- if (memno == 0)
+- hose->pci_mem_offset = ranges[na+2] - ranges[2];
+- if (memno < 3) {
+- res = &hose->mem_resources[memno];
+- res->flags = IORESOURCE_MEM;
+- res->start = ranges[na+2];
+- }
+- break;
+- }
+- if (res != NULL) {
+- res->name = dev->full_name;
+- res->end = res->start + size - 1;
+- res->parent = NULL;
+- res->sibling = NULL;
+- res->child = NULL;
+- }
+- ranges += np;
+- }
+-}
+-
+-/*
+- * We assume that if we have a G3 powermac, we have one bridge called
+- * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
+- * if we have one or more bandit or chaos bridges, we don't have a MPC106.
+- */
+-static int __init add_bridge(struct device_node *dev)
+-{
+- int len;
+- struct pci_controller *hose;
+- char* disp_name;
+- int *bus_range;
+- int primary = 1;
+- struct property *of_prop;
+-
+- DBG("Adding PCI host bridge %s\n", dev->full_name);
+-
+- bus_range = (int *) get_property(dev, "bus-range", &len);
+- if (bus_range == NULL || len < 2 * sizeof(int)) {
+- printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+- dev->full_name);
+- }
+-
+- hose = alloc_bootmem(sizeof(struct pci_controller));
+- if (hose == NULL)
+- return -ENOMEM;
+- pci_setup_pci_controller(hose);
+-
+- hose->arch_data = dev;
+- hose->first_busno = bus_range ? bus_range[0] : 0;
+- hose->last_busno = bus_range ? bus_range[1] : 0xff;
+-
+- of_prop = alloc_bootmem(sizeof(struct property) +
+- sizeof(hose->global_number));
+- if (of_prop) {
+- memset(of_prop, 0, sizeof(struct property));
+- of_prop->name = "linux,pci-domain";
+- of_prop->length = sizeof(hose->global_number);
+- of_prop->value = (unsigned char *)&of_prop[1];
+- memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number));
+- prom_add_property(dev, of_prop);
+- }
+-
+- disp_name = NULL;
+- if (device_is_compatible(dev, "u3-agp")) {
+- setup_u3_agp(hose);
+- disp_name = "U3-AGP";
+- primary = 0;
+- } else if (device_is_compatible(dev, "u3-ht")) {
+- setup_u3_ht(hose);
+- disp_name = "U3-HT";
+- primary = 1;
+- }
+- printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+- disp_name, hose->first_busno, hose->last_busno);
+-
+- /* Interpret the "ranges" property */
+- /* This also maps the I/O region and sets isa_io/mem_base */
+- pmac_process_bridge_OF_ranges(hose, dev, primary);
+-
+- /* Fixup "bus-range" OF property */
+- fixup_bus_range(dev);
+-
+- return 0;
+-}
+-
+-/*
+- * We use our own read_irq_line here because PCI_INTERRUPT_PIN is
+- * crap on some of Apple ASICs. We unconditionally use the Open Firmware
+- * interrupt number as this is always right.
+- */
+-static int pmac_pci_read_irq_line(struct pci_dev *pci_dev)
+-{
+- struct device_node *node;
+-
+- node = pci_device_to_OF_node(pci_dev);
+- if (node == NULL)
+- return -1;
+- if (node->n_intrs == 0)
+- return -1;
+- pci_dev->irq = node->intrs[0].line;
+- pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
+-
+- return 0;
+-}
+-
+-void __init pmac_pcibios_fixup(void)
+-{
+- struct pci_dev *dev = NULL;
+-
+- for_each_pci_dev(dev)
+- pmac_pci_read_irq_line(dev);
+-}
+-
+-static void __init pmac_fixup_phb_resources(void)
+-{
+- struct pci_controller *hose, *tmp;
+-
+- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+- unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+- hose->io_resource.start += offset;
+- hose->io_resource.end += offset;
+- printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
+- hose->global_number,
+- hose->io_resource.start, hose->io_resource.end);
+- }
+-}
+-
+-void __init pmac_pci_init(void)
+-{
+- struct device_node *np, *root;
+- struct device_node *ht = NULL;
+-
+- /* Probe root PCI hosts, that is on U3 the AGP host and the
+- * HyperTransport host. That one is actually "kept" around
+- * and actually added last as it's resource management relies
+- * on the AGP resources to have been setup first
+- */
+- root = of_find_node_by_path("/");
+- if (root == NULL) {
+- printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n");
+- return;
+- }
+- for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
+- if (np->name == NULL)
+- continue;
+- if (strcmp(np->name, "pci") == 0) {
+- if (add_bridge(np) == 0)
+- of_node_get(np);
+- }
+- if (strcmp(np->name, "ht") == 0) {
+- of_node_get(np);
+- ht = np;
+- }
+- }
+- of_node_put(root);
+-
+- /* Now setup the HyperTransport host if we found any
+- */
+- if (ht && add_bridge(ht) != 0)
+- of_node_put(ht);
+-
+- /* Fixup the IO resources on our host bridges as the common code
+- * does it only for childs of the host bridges
+- */
+- pmac_fixup_phb_resources();
+-
+- /* Setup the linkage between OF nodes and PHBs */
+- pci_devs_phb_init();
+-
+- /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
+- * assume there is no P2P bridge on the AGP bus, which should be a
+- * safe assumptions hopefully.
+- */
+- if (u3_agp) {
+- struct device_node *np = u3_agp->arch_data;
+- PCI_DN(np)->busno = 0xf0;
+- for (np = np->child; np; np = np->sibling)
+- PCI_DN(np)->busno = 0xf0;
+- }
+-
+- pmac_check_ht_link();
+-
+- /* Tell pci.c to not use the common resource allocation mecanism */
+- pci_probe_only = 1;
+-
+- /* Allow all IO */
+- io_page_mask = -1;
+-}
+-
+-/*
+- * Disable second function on K2-SATA, it's broken
+- * and disable IO BARs on first one
+- */
+-static void fixup_k2_sata(struct pci_dev* dev)
+-{
+- int i;
+- u16 cmd;
+-
+- if (PCI_FUNC(dev->devfn) > 0) {
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- for (i = 0; i < 6; i++) {
+- dev->resource[i].start = dev->resource[i].end = 0;
+- dev->resource[i].flags = 0;
+- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+- }
+- } else {
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- cmd &= ~PCI_COMMAND_IO;
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- for (i = 0; i < 5; i++) {
+- dev->resource[i].start = dev->resource[i].end = 0;
+- dev->resource[i].flags = 0;
+- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+- }
+- }
+-}
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
+-
+diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac_setup.c
++++ /dev/null
+@@ -1,525 +0,0 @@
+-/*
+- * arch/ppc/platforms/setup.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Adapted for Power Macintosh by Paul Mackerras
+- * Copyright (C) 1996 Paul Mackerras (paulus at cs.anu.edu.au)
+- *
+- * Derived from "arch/alpha/kernel/setup.c"
+- * Copyright (C) 1995 Linus Torvalds
+- *
+- * Maintained by Benjamin Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- */
+-
+-/*
+- * bootup setup stuff..
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/init.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/user.h>
+-#include <linux/a.out.h>
+-#include <linux/tty.h>
+-#include <linux/string.h>
+-#include <linux/delay.h>
+-#include <linux/ioport.h>
+-#include <linux/major.h>
+-#include <linux/initrd.h>
+-#include <linux/vt_kern.h>
+-#include <linux/console.h>
+-#include <linux/ide.h>
+-#include <linux/pci.h>
+-#include <linux/adb.h>
+-#include <linux/cuda.h>
+-#include <linux/pmu.h>
+-#include <linux/irq.h>
+-#include <linux/seq_file.h>
+-#include <linux/root_dev.h>
+-#include <linux/bitops.h>
+-
+-#include <asm/processor.h>
+-#include <asm/sections.h>
+-#include <asm/prom.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/iommu.h>
+-#include <asm/machdep.h>
+-#include <asm/dma.h>
+-#include <asm/btext.h>
+-#include <asm/cputable.h>
+-#include <asm/pmac_feature.h>
+-#include <asm/time.h>
+-#include <asm/of_device.h>
+-#include <asm/lmb.h>
+-#include <asm/smu.h>
+-#include <asm/pmc.h>
+-
+-#include "pmac.h"
+-#include "mpic.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-static int current_root_goodness = -1;
+-#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
+-
+-extern int powersave_nap;
+-int sccdbg;
+-
+-sys_ctrler_t sys_ctrler;
+-EXPORT_SYMBOL(sys_ctrler);
+-
+-#ifdef CONFIG_PMAC_SMU
+-unsigned long smu_cmdbuf_abs;
+-EXPORT_SYMBOL(smu_cmdbuf_abs);
+-#endif
+-
+-extern void udbg_init_scc(struct device_node *np);
+-
+-static void __pmac pmac_show_cpuinfo(struct seq_file *m)
+-{
+- struct device_node *np;
+- char *pp;
+- int plen;
+- char* mbname;
+- int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL,
+- PMAC_MB_INFO_MODEL, 0);
+- unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL,
+- PMAC_MB_INFO_FLAGS, 0);
+-
+- if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME,
+- (long)&mbname) != 0)
+- mbname = "Unknown";
+-
+- /* find motherboard type */
+- seq_printf(m, "machine\t\t: ");
+- np = of_find_node_by_path("/");
+- if (np != NULL) {
+- pp = (char *) get_property(np, "model", NULL);
+- if (pp != NULL)
+- seq_printf(m, "%s\n", pp);
+- else
+- seq_printf(m, "PowerMac\n");
+- pp = (char *) get_property(np, "compatible", &plen);
+- if (pp != NULL) {
+- seq_printf(m, "motherboard\t:");
+- while (plen > 0) {
+- int l = strlen(pp) + 1;
+- seq_printf(m, " %s", pp);
+- plen -= l;
+- pp += l;
+- }
+- seq_printf(m, "\n");
+- }
+- of_node_put(np);
+- } else
+- seq_printf(m, "PowerMac\n");
+-
+- /* print parsed model */
+- seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
+- seq_printf(m, "pmac flags\t: %08x\n", mbflags);
+-
+- /* Indicate newworld */
+- seq_printf(m, "pmac-generation\t: NewWorld\n");
+-}
+-
+-
+-static void __init pmac_setup_arch(void)
+-{
+- /* init to some ~sane value until calibrate_delay() runs */
+- loops_per_jiffy = 50000000;
+-
+- /* Probe motherboard chipset */
+- pmac_feature_init();
+-#if 0
+- /* Lock-enable the SCC channel used for debug */
+- if (sccdbg) {
+- np = of_find_node_by_name(NULL, "escc");
+- if (np)
+- pmac_call_feature(PMAC_FTR_SCC_ENABLE, np,
+- PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
+- }
+-#endif
+- /* We can NAP */
+- powersave_nap = 1;
+-
+-#ifdef CONFIG_ADB_PMU
+- /* Initialize the PMU if any */
+- find_via_pmu();
+-#endif
+-#ifdef CONFIG_PMAC_SMU
+- /* Initialize the SMU if any */
+- smu_init();
+-#endif
+-
+- /* Init NVRAM access */
+- pmac_nvram_init();
+-
+- /* Setup SMP callback */
+-#ifdef CONFIG_SMP
+- pmac_setup_smp();
+-#endif
+-
+- /* Lookup PCI hosts */
+- pmac_pci_init();
+-
+-#ifdef CONFIG_DUMMY_CONSOLE
+- conswitchp = &dummy_con;
+-#endif
+-
+- printk(KERN_INFO "Using native/NAP idle loop\n");
+-}
+-
+-#ifdef CONFIG_SCSI
+-void note_scsi_host(struct device_node *node, void *host)
+-{
+- /* Obsolete */
+-}
+-#endif
+-
+-
+-static int initializing = 1;
+-
+-static int pmac_late_init(void)
+-{
+- initializing = 0;
+- return 0;
+-}
+-
+-late_initcall(pmac_late_init);
+-
+-/* can't be __init - can be called whenever a disk is first accessed */
+-void __pmac note_bootable_part(dev_t dev, int part, int goodness)
+-{
+- extern dev_t boot_dev;
+- char *p;
+-
+- if (!initializing)
+- return;
+- if ((goodness <= current_root_goodness) &&
+- ROOT_DEV != DEFAULT_ROOT_DEVICE)
+- return;
+- p = strstr(saved_command_line, "root=");
+- if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+- return;
+-
+- if (!boot_dev || dev == boot_dev) {
+- ROOT_DEV = dev + part;
+- boot_dev = 0;
+- current_root_goodness = goodness;
+- }
+-}
+-
+-static void __pmac pmac_restart(char *cmd)
+-{
+- switch(sys_ctrler) {
+-#ifdef CONFIG_ADB_PMU
+- case SYS_CTRLER_PMU:
+- pmu_restart();
+- break;
+-#endif
+-
+-#ifdef CONFIG_PMAC_SMU
+- case SYS_CTRLER_SMU:
+- smu_restart();
+- break;
+-#endif
+- default:
+- ;
+- }
+-}
+-
+-static void __pmac pmac_power_off(void)
+-{
+- switch(sys_ctrler) {
+-#ifdef CONFIG_ADB_PMU
+- case SYS_CTRLER_PMU:
+- pmu_shutdown();
+- break;
+-#endif
+-#ifdef CONFIG_PMAC_SMU
+- case SYS_CTRLER_SMU:
+- smu_shutdown();
+- break;
+-#endif
+- default:
+- ;
+- }
+-}
+-
+-static void __pmac pmac_halt(void)
+-{
+- pmac_power_off();
+-}
+-
+-#ifdef CONFIG_BOOTX_TEXT
+-static void btext_putc(unsigned char c)
+-{
+- btext_drawchar(c);
+-}
+-
+-static void __init init_boot_display(void)
+-{
+- char *name;
+- struct device_node *np = NULL;
+- int rc = -ENODEV;
+-
+- printk("trying to initialize btext ...\n");
+-
+- name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+- if (name != NULL) {
+- np = of_find_node_by_path(name);
+- if (np != NULL) {
+- if (strcmp(np->type, "display") != 0) {
+- printk("boot stdout isn't a display !\n");
+- of_node_put(np);
+- np = NULL;
+- }
+- }
+- }
+- if (np)
+- rc = btext_initialize(np);
+- if (rc == 0)
+- return;
+-
+- for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
+- if (get_property(np, "linux,opened", NULL)) {
+- printk("trying %s ...\n", np->full_name);
+- rc = btext_initialize(np);
+- printk("result: %d\n", rc);
+- }
+- if (rc == 0)
+- return;
+- }
+-}
+-#endif /* CONFIG_BOOTX_TEXT */
+-
+-/*
+- * Early initialization.
+- */
+-static void __init pmac_init_early(void)
+-{
+- DBG(" -> pmac_init_early\n");
+-
+- /* Initialize hash table, from now on, we can take hash faults
+- * and call ioremap
+- */
+- hpte_init_native();
+-
+- /* Init SCC */
+- if (strstr(cmd_line, "sccdbg")) {
+- sccdbg = 1;
+- udbg_init_scc(NULL);
+- }
+-#ifdef CONFIG_BOOTX_TEXT
+- else {
+- init_boot_display();
+-
+- udbg_putc = btext_putc;
+- }
+-#endif /* CONFIG_BOOTX_TEXT */
+-
+- /* Setup interrupt mapping options */
+- ppc64_interrupt_controller = IC_OPEN_PIC;
+-
+- iommu_init_early_u3();
+-
+- DBG(" <- pmac_init_early\n");
+-}
+-
+-static int pmac_u3_cascade(struct pt_regs *regs, void *data)
+-{
+- return mpic_get_one_irq((struct mpic *)data, regs);
+-}
+-
+-static __init void pmac_init_IRQ(void)
+-{
+- struct device_node *irqctrler = NULL;
+- struct device_node *irqctrler2 = NULL;
+- struct device_node *np = NULL;
+- struct mpic *mpic1, *mpic2;
+-
+- /* We first try to detect Apple's new Core99 chipset, since mac-io
+- * is quite different on those machines and contains an IBM MPIC2.
+- */
+- while ((np = of_find_node_by_type(np, "open-pic")) != NULL) {
+- struct device_node *parent = of_get_parent(np);
+- if (parent && !strcmp(parent->name, "u3"))
+- irqctrler2 = of_node_get(np);
+- else
+- irqctrler = of_node_get(np);
+- of_node_put(parent);
+- }
+- if (irqctrler != NULL && irqctrler->n_addrs > 0) {
+- unsigned char senses[128];
+-
+- printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n",
+- (unsigned int)irqctrler->addrs[0].address);
+-
+- prom_get_irq_senses(senses, 0, 128);
+- mpic1 = mpic_alloc(irqctrler->addrs[0].address,
+- MPIC_PRIMARY | MPIC_WANTS_RESET,
+- 0, 0, 128, 256, senses, 128, " K2-MPIC ");
+- BUG_ON(mpic1 == NULL);
+- mpic_init(mpic1);
+-
+- if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
+- irqctrler2->n_addrs > 0) {
+- printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
+- (u32)irqctrler2->addrs[0].address,
+- irqctrler2->intrs[0].line);
+-
+- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
+- prom_get_irq_senses(senses, 128, 128 + 128);
+-
+- /* We don't need to set MPIC_BROKEN_U3 here since we don't have
+- * hypertransport interrupts routed to it
+- */
+- mpic2 = mpic_alloc(irqctrler2->addrs[0].address,
+- MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
+- 0, 128, 128, 0, senses, 128, " U3-MPIC ");
+- BUG_ON(mpic2 == NULL);
+- mpic_init(mpic2);
+- mpic_setup_cascade(irqctrler2->intrs[0].line,
+- pmac_u3_cascade, mpic2);
+- }
+- }
+- of_node_put(irqctrler);
+- of_node_put(irqctrler2);
+-}
+-
+-static void __init pmac_progress(char *s, unsigned short hex)
+-{
+- if (sccdbg) {
+- udbg_puts(s);
+- udbg_puts("\n");
+- }
+-#ifdef CONFIG_BOOTX_TEXT
+- else if (boot_text_mapped) {
+- btext_drawstring(s);
+- btext_drawstring("\n");
+- }
+-#endif /* CONFIG_BOOTX_TEXT */
+-}
+-
+-/*
+- * pmac has no legacy IO, anything calling this function has to
+- * fail or bad things will happen
+- */
+-static int pmac_check_legacy_ioport(unsigned int baseport)
+-{
+- return -ENODEV;
+-}
+-
+-static int __init pmac_declare_of_platform_devices(void)
+-{
+- struct device_node *np, *npp;
+-
+- npp = of_find_node_by_name(NULL, "u3");
+- if (npp) {
+- for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) {
+- if (strncmp(np->name, "i2c", 3) == 0) {
+- of_platform_device_create(np, "u3-i2c", NULL);
+- of_node_put(np);
+- break;
+- }
+- }
+- of_node_put(npp);
+- }
+- npp = of_find_node_by_type(NULL, "smu");
+- if (npp) {
+- of_platform_device_create(npp, "smu", NULL);
+- of_node_put(npp);
+- }
+-
+- return 0;
+-}
+-
+-device_initcall(pmac_declare_of_platform_devices);
+-
+-/*
+- * Called very early, MMU is off, device-tree isn't unflattened
+- */
+-static int __init pmac_probe(int platform)
+-{
+- if (platform != PLATFORM_POWERMAC)
+- return 0;
+- /*
+- * On U3, the DART (iommu) must be allocated now since it
+- * has an impact on htab_initialize (due to the large page it
+- * occupies having to be broken up so the DART itself is not
+- * part of the cacheable linar mapping
+- */
+- alloc_u3_dart_table();
+-
+-#ifdef CONFIG_PMAC_SMU
+- /*
+- * SMU based G5s need some memory below 2Gb, at least the current
+- * driver needs that. We have to allocate it now. We allocate 4k
+- * (1 small page) for now.
+- */
+- smu_cmdbuf_abs = lmb_alloc_base(4096, 4096, 0x80000000UL);
+-#endif /* CONFIG_PMAC_SMU */
+-
+- return 1;
+-}
+-
+-static int pmac_probe_mode(struct pci_bus *bus)
+-{
+- struct device_node *node = bus->sysdata;
+-
+- /* We need to use normal PCI probing for the AGP bus,
+- since the device for the AGP bridge isn't in the tree. */
+- if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
+- return PCI_PROBE_NORMAL;
+-
+- return PCI_PROBE_DEVTREE;
+-}
+-
+-struct machdep_calls __initdata pmac_md = {
+-#ifdef CONFIG_HOTPLUG_CPU
+- .cpu_die = generic_mach_cpu_die,
+-#endif
+- .probe = pmac_probe,
+- .setup_arch = pmac_setup_arch,
+- .init_early = pmac_init_early,
+- .get_cpuinfo = pmac_show_cpuinfo,
+- .init_IRQ = pmac_init_IRQ,
+- .get_irq = mpic_get_irq,
+- .pcibios_fixup = pmac_pcibios_fixup,
+- .pci_probe_mode = pmac_probe_mode,
+- .restart = pmac_restart,
+- .power_off = pmac_power_off,
+- .halt = pmac_halt,
+- .get_boot_time = pmac_get_boot_time,
+- .set_rtc_time = pmac_set_rtc_time,
+- .get_rtc_time = pmac_get_rtc_time,
+- .calibrate_decr = pmac_calibrate_decr,
+- .feature_call = pmac_do_feature_call,
+- .progress = pmac_progress,
+- .check_legacy_ioport = pmac_check_legacy_ioport,
+- .idle_loop = native_idle,
+- .enable_pmcs = power4_enable_pmcs,
+-};
+diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac_smp.c
++++ /dev/null
+@@ -1,330 +0,0 @@
+-/*
+- * SMP support for power macintosh.
+- *
+- * We support both the old "powersurge" SMP architecture
+- * and the current Core99 (G4 PowerMac) machines.
+- *
+- * Note that we don't support the very first rev. of
+- * Apple/DayStar 2 CPUs board, the one with the funky
+- * watchdog. Hopefully, none of these should be there except
+- * maybe internally to Apple. I should probably still add some
+- * code to detect this card though and disable SMP. --BenH.
+- *
+- * Support Macintosh G4 SMP by Troy Benjegerdes (hozer at drgw.net)
+- * and Ben Herrenschmidt <benh at kernel.crashing.org>.
+- *
+- * Support for DayStar quad CPU cards
+- * Copyright (C) XLR8, Inc. 1994-2000
+- *
+- * 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/interrupt.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/init.h>
+-#include <linux/spinlock.h>
+-#include <linux/errno.h>
+-#include <linux/irq.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/atomic.h>
+-#include <asm/irq.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/sections.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/smp.h>
+-#include <asm/machdep.h>
+-#include <asm/pmac_feature.h>
+-#include <asm/time.h>
+-#include <asm/cacheflush.h>
+-#include <asm/keylargo.h>
+-#include <asm/pmac_low_i2c.h>
+-
+-#include "mpic.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-extern void pmac_secondary_start_1(void);
+-extern void pmac_secondary_start_2(void);
+-extern void pmac_secondary_start_3(void);
+-
+-extern struct smp_ops_t *smp_ops;
+-
+-static void (*pmac_tb_freeze)(int freeze);
+-static struct device_node *pmac_tb_clock_chip_host;
+-static u8 pmac_tb_pulsar_addr;
+-static DEFINE_SPINLOCK(timebase_lock);
+-static unsigned long timebase;
+-
+-static void smp_core99_cypress_tb_freeze(int freeze)
+-{
+- u8 data;
+- int rc;
+-
+- /* Strangely, the device-tree says address is 0xd2, but darwin
+- * accesses 0xd0 ...
+- */
+- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
+- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
+- 0xd0 | pmac_low_i2c_read,
+- 0x81, &data, 1);
+- if (rc != 0)
+- goto bail;
+-
+- data = (data & 0xf3) | (freeze ? 0x00 : 0x0c);
+-
+- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
+- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
+- 0xd0 | pmac_low_i2c_write,
+- 0x81, &data, 1);
+-
+- bail:
+- if (rc != 0) {
+- printk("Cypress Timebase %s rc: %d\n",
+- freeze ? "freeze" : "unfreeze", rc);
+- panic("Timebase freeze failed !\n");
+- }
+-}
+-
+-static void smp_core99_pulsar_tb_freeze(int freeze)
+-{
+- u8 data;
+- int rc;
+-
+- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
+- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
+- pmac_tb_pulsar_addr | pmac_low_i2c_read,
+- 0x2e, &data, 1);
+- if (rc != 0)
+- goto bail;
+-
+- data = (data & 0x88) | (freeze ? 0x11 : 0x22);
+-
+- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
+- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
+- pmac_tb_pulsar_addr | pmac_low_i2c_write,
+- 0x2e, &data, 1);
+- bail:
+- if (rc != 0) {
+- printk(KERN_ERR "Pulsar Timebase %s rc: %d\n",
+- freeze ? "freeze" : "unfreeze", rc);
+- panic("Timebase freeze failed !\n");
+- }
+-}
+-
+-
+-static void smp_core99_give_timebase(void)
+-{
+- /* Open i2c bus for synchronous access */
+- if (pmac_low_i2c_open(pmac_tb_clock_chip_host, 0))
+- panic("Can't open i2c for TB sync !\n");
+-
+- spin_lock(&timebase_lock);
+- (*pmac_tb_freeze)(1);
+- mb();
+- timebase = get_tb();
+- spin_unlock(&timebase_lock);
+-
+- while (timebase)
+- barrier();
+-
+- spin_lock(&timebase_lock);
+- (*pmac_tb_freeze)(0);
+- spin_unlock(&timebase_lock);
+-
+- /* Close i2c bus */
+- pmac_low_i2c_close(pmac_tb_clock_chip_host);
+-}
+-
+-
+-static void __devinit smp_core99_take_timebase(void)
+-{
+- while (!timebase)
+- barrier();
+- spin_lock(&timebase_lock);
+- set_tb(timebase >> 32, timebase & 0xffffffff);
+- timebase = 0;
+- spin_unlock(&timebase_lock);
+-}
+-
+-
+-static int __init smp_core99_probe(void)
+-{
+- struct device_node *cpus;
+- struct device_node *cc;
+- int ncpus = 0;
+-
+- /* Maybe use systemconfiguration here ? */
+- if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
+-
+- /* Count CPUs in the device-tree */
+- for (cpus = NULL; (cpus = of_find_node_by_type(cpus, "cpu")) != NULL;)
+- ++ncpus;
+-
+- printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
+-
+- /* Nothing more to do if less than 2 of them */
+- if (ncpus <= 1)
+- return 1;
+-
+- /* HW sync only on these platforms */
+- if (!machine_is_compatible("PowerMac7,2") &&
+- !machine_is_compatible("PowerMac7,3") &&
+- !machine_is_compatible("RackMac3,1"))
+- goto nohwsync;
+-
+- /* Look for the clock chip */
+- for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
+- struct device_node *p = of_get_parent(cc);
+- u32 *reg;
+- int ok;
+- ok = p && device_is_compatible(p, "uni-n-i2c");
+- if (!ok)
+- goto next;
+- reg = (u32 *)get_property(cc, "reg", NULL);
+- if (reg == NULL)
+- goto next;
+- switch (*reg) {
+- case 0xd2:
+- if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
+- pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+- pmac_tb_pulsar_addr = 0xd2;
+- printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+- } else if (device_is_compatible(cc, "cy28508")) {
+- pmac_tb_freeze = smp_core99_cypress_tb_freeze;
+- printk(KERN_INFO "Timebase clock is Cypress chip\n");
+- }
+- break;
+- case 0xd4:
+- pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+- pmac_tb_pulsar_addr = 0xd4;
+- printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+- break;
+- }
+- if (pmac_tb_freeze != NULL) {
+- pmac_tb_clock_chip_host = p;
+- smp_ops->give_timebase = smp_core99_give_timebase;
+- smp_ops->take_timebase = smp_core99_take_timebase;
+- of_node_put(cc);
+- of_node_put(p);
+- break;
+- }
+- next:
+- of_node_put(p);
+- }
+-
+- nohwsync:
+- mpic_request_ipis();
+-
+- return ncpus;
+-}
+-
+-static void __init smp_core99_kick_cpu(int nr)
+-{
+- int save_vector, j;
+- unsigned long new_vector;
+- unsigned long flags;
+- volatile unsigned int *vector
+- = ((volatile unsigned int *)(KERNELBASE+0x100));
+-
+- if (nr < 1 || nr > 3)
+- return;
+- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
+-
+- local_irq_save(flags);
+- local_irq_disable();
+-
+- /* Save reset vector */
+- save_vector = *vector;
+-
+- /* Setup fake reset vector that does
+- * b .pmac_secondary_start - KERNELBASE
+- */
+- switch(nr) {
+- case 1:
+- new_vector = (unsigned long)pmac_secondary_start_1;
+- break;
+- case 2:
+- new_vector = (unsigned long)pmac_secondary_start_2;
+- break;
+- case 3:
+- default:
+- new_vector = (unsigned long)pmac_secondary_start_3;
+- break;
+- }
+- *vector = 0x48000002 + (new_vector - KERNELBASE);
+-
+- /* flush data cache and inval instruction cache */
+- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+-
+- /* Put some life in our friend */
+- pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
+- paca[nr].cpu_start = 1;
+-
+- /* FIXME: We wait a bit for the CPU to take the exception, I should
+- * instead wait for the entry code to set something for me. Well,
+- * ideally, all that crap will be done in prom.c and the CPU left
+- * in a RAM-based wait loop like CHRP.
+- */
+- for (j = 1; j < 1000000; j++)
+- mb();
+-
+- /* Restore our exception vector */
+- *vector = save_vector;
+- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+-
+- local_irq_restore(flags);
+- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
+-}
+-
+-static void __init smp_core99_setup_cpu(int cpu_nr)
+-{
+- /* Setup MPIC */
+- mpic_setup_this_cpu();
+-
+- if (cpu_nr == 0) {
+- extern void g5_phy_disable_cpu1(void);
+-
+- /* If we didn't start the second CPU, we must take
+- * it off the bus
+- */
+- if (num_online_cpus() < 2)
+- g5_phy_disable_cpu1();
+- if (ppc_md.progress) ppc_md.progress("smp_core99_setup_cpu 0 done", 0x349);
+- }
+-}
+-
+-struct smp_ops_t core99_smp_ops __pmacdata = {
+- .message_pass = smp_mpic_message_pass,
+- .probe = smp_core99_probe,
+- .kick_cpu = smp_core99_kick_cpu,
+- .setup_cpu = smp_core99_setup_cpu,
+- .give_timebase = smp_generic_give_timebase,
+- .take_timebase = smp_generic_take_timebase,
+-};
+-
+-void __init pmac_setup_smp(void)
+-{
+- smp_ops = &core99_smp_ops;
+-#ifdef CONFIG_HOTPLUG_CPU
+- smp_ops->cpu_enable = generic_cpu_enable;
+- smp_ops->cpu_disable = generic_cpu_disable;
+- smp_ops->cpu_die = generic_cpu_die;
+-#endif
+-}
+diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmac_time.c
++++ /dev/null
+@@ -1,195 +0,0 @@
+-/*
+- * Support for periodic interrupts (100 per second) and for getting
+- * the current time from the RTC on Power Macintoshes.
+- *
+- * We use the decrementer register for our periodic interrupts.
+- *
+- * Paul Mackerras August 1996.
+- * Copyright (C) 1996 Paul Mackerras.
+- * Copyright (C) 2003-2005 Benjamin Herrenschmidt.
+- *
+- */
+-#include <linux/config.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/time.h>
+-#include <linux/adb.h>
+-#include <linux/pmu.h>
+-#include <linux/interrupt.h>
+-
+-#include <asm/sections.h>
+-#include <asm/prom.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/machdep.h>
+-#include <asm/time.h>
+-#include <asm/nvram.h>
+-#include <asm/smu.h>
+-
+-#undef DEBUG
+-
+-#ifdef DEBUG
+-#define DBG(x...) printk(x)
+-#else
+-#define DBG(x...)
+-#endif
+-
+-/* Apparently the RTC stores seconds since 1 Jan 1904 */
+-#define RTC_OFFSET 2082844800
+-
+-/*
+- * Calibrate the decrementer frequency with the VIA timer 1.
+- */
+-#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
+-
+-extern struct timezone sys_tz;
+-extern void to_tm(int tim, struct rtc_time * tm);
+-
+-void __pmac pmac_get_rtc_time(struct rtc_time *tm)
+-{
+- switch(sys_ctrler) {
+-#ifdef CONFIG_ADB_PMU
+- case SYS_CTRLER_PMU: {
+- /* TODO: Move that to a function in the PMU driver */
+- struct adb_request req;
+- unsigned int now;
+-
+- if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+- return;
+- pmu_wait_complete(&req);
+- if (req.reply_len != 4)
+- printk(KERN_ERR "pmac_get_rtc_time: PMU returned a %d"
+- " bytes reply\n", req.reply_len);
+- now = (req.reply[0] << 24) + (req.reply[1] << 16)
+- + (req.reply[2] << 8) + req.reply[3];
+- DBG("get: %u -> %u\n", (int)now, (int)(now - RTC_OFFSET));
+- now -= RTC_OFFSET;
+-
+- to_tm(now, tm);
+- tm->tm_year -= 1900;
+- tm->tm_mon -= 1;
+-
+- DBG("-> tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n",
+- tm->tm_mday, tm->tm_mon, tm->tm_year,
+- tm->tm_hour, tm->tm_min, tm->tm_sec);
+- break;
+- }
+-#endif /* CONFIG_ADB_PMU */
+-
+-#ifdef CONFIG_PMAC_SMU
+- case SYS_CTRLER_SMU:
+- smu_get_rtc_time(tm, 1);
+- break;
+-#endif /* CONFIG_PMAC_SMU */
+- default:
+- ;
+- }
+-}
+-
+-int __pmac pmac_set_rtc_time(struct rtc_time *tm)
+-{
+- switch(sys_ctrler) {
+-#ifdef CONFIG_ADB_PMU
+- case SYS_CTRLER_PMU: {
+- /* TODO: Move that to a function in the PMU driver */
+- struct adb_request req;
+- unsigned int nowtime;
+-
+- DBG("set: tm_mday: %d, tm_mon: %d, tm_year: %d,"
+- " %d:%02d:%02d\n",
+- tm->tm_mday, tm->tm_mon, tm->tm_year,
+- tm->tm_hour, tm->tm_min, tm->tm_sec);
+-
+- nowtime = mktime(tm->tm_year + 1900, tm->tm_mon + 1,
+- tm->tm_mday, tm->tm_hour, tm->tm_min,
+- tm->tm_sec);
+-
+- DBG("-> %u -> %u\n", (int)nowtime,
+- (int)(nowtime + RTC_OFFSET));
+- nowtime += RTC_OFFSET;
+-
+- if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
+- nowtime >> 24, nowtime >> 16,
+- nowtime >> 8, nowtime) < 0)
+- return -ENXIO;
+- pmu_wait_complete(&req);
+- if (req.reply_len != 0)
+- printk(KERN_ERR "pmac_set_rtc_time: PMU returned a %d"
+- " bytes reply\n", req.reply_len);
+- return 0;
+- }
+-#endif /* CONFIG_ADB_PMU */
+-
+-#ifdef CONFIG_PMAC_SMU
+- case SYS_CTRLER_SMU:
+- return smu_set_rtc_time(tm, 1);
+-#endif /* CONFIG_PMAC_SMU */
+- default:
+- return -ENODEV;
+- }
+-}
+-
+-void __init pmac_get_boot_time(struct rtc_time *tm)
+-{
+- pmac_get_rtc_time(tm);
+-
+-#ifdef disabled__CONFIG_NVRAM
+- s32 delta = 0;
+- int dst;
+-
+- delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
+- delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
+- delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
+- if (delta & 0x00800000UL)
+- delta |= 0xFF000000UL;
+- dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
+- printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
+- dst ? "on" : "off");
+-#endif
+-}
+-
+-/*
+- * Query the OF and get the decr frequency.
+- * FIXME: merge this with generic_calibrate_decr
+- */
+-void __init pmac_calibrate_decr(void)
+-{
+- struct device_node *cpu;
+- unsigned int freq, *fp;
+- struct div_result divres;
+-
+- /*
+- * The cpu node should have a timebase-frequency property
+- * to tell us the rate at which the decrementer counts.
+- */
+- cpu = find_type_devices("cpu");
+- if (cpu == 0)
+- panic("can't find cpu node in time_init");
+- fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
+- if (fp == 0)
+- panic("can't get cpu timebase frequency");
+- freq = *fp;
+- printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+- freq/1000000, freq%1000000);
+- tb_ticks_per_jiffy = freq / HZ;
+- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+- tb_ticks_per_usec = freq / 1000000;
+- tb_to_us = mulhwu_scale_factor(freq, 1000000);
+- div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres );
+- tb_to_xs = divres.result_low;
+- ppc_tb_freq = freq;
+-
+- fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);
+- if (fp == 0)
+- panic("can't get cpu processor frequency");
+- ppc_proc_freq = *fp;
+-
+- setup_default_decr();
+-}
+-
+diff --git a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/pmc.c
++++ /dev/null
+@@ -1,88 +0,0 @@
+-/*
+- * linux/arch/ppc64/kernel/pmc.c
+- *
+- * Copyright (C) 2004 David Gibson, IBM Corporation.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/errno.h>
+-#include <linux/spinlock.h>
+-#include <linux/module.h>
+-
+-#include <asm/processor.h>
+-#include <asm/pmc.h>
+-
+-/* Ensure exceptions are disabled */
+-static void dummy_perf(struct pt_regs *regs)
+-{
+- unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+-
+- mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
+- mtspr(SPRN_MMCR0, mmcr0);
+-}
+-
+-static DEFINE_SPINLOCK(pmc_owner_lock);
+-static void *pmc_owner_caller; /* mostly for debugging */
+-perf_irq_t perf_irq = dummy_perf;
+-
+-int reserve_pmc_hardware(perf_irq_t new_perf_irq)
+-{
+- int err = 0;
+-
+- spin_lock(&pmc_owner_lock);
+-
+- if (pmc_owner_caller) {
+- printk(KERN_WARNING "reserve_pmc_hardware: "
+- "PMC hardware busy (reserved by caller %p)\n",
+- pmc_owner_caller);
+- err = -EBUSY;
+- goto out;
+- }
+-
+- pmc_owner_caller = __builtin_return_address(0);
+- perf_irq = new_perf_irq ? : dummy_perf;
+-
+- out:
+- spin_unlock(&pmc_owner_lock);
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(reserve_pmc_hardware);
+-
+-void release_pmc_hardware(void)
+-{
+- spin_lock(&pmc_owner_lock);
+-
+- WARN_ON(! pmc_owner_caller);
+-
+- pmc_owner_caller = NULL;
+- perf_irq = dummy_perf;
+-
+- spin_unlock(&pmc_owner_lock);
+-}
+-EXPORT_SYMBOL_GPL(release_pmc_hardware);
+-
+-void power4_enable_pmcs(void)
+-{
+- unsigned long hid0;
+-
+- hid0 = mfspr(HID0);
+- hid0 |= 1UL << (63 - 20);
+-
+- /* POWER4 requires the following sequence */
+- asm volatile(
+- "sync\n"
+- "mtspr %1, %0\n"
+- "mfspr %0, %1\n"
+- "mfspr %0, %1\n"
+- "mfspr %0, %1\n"
+- "mfspr %0, %1\n"
+- "mfspr %0, %1\n"
+- "mfspr %0, %1\n"
+- "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
+- "memory");
+-}
+diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
+--- a/arch/ppc64/kernel/ppc_ksyms.c
++++ b/arch/ppc64/kernel/ppc_ksyms.c
+@@ -19,7 +19,6 @@
+ #include <asm/hw_irq.h>
+ #include <asm/abs_addr.h>
+ #include <asm/cacheflush.h>
+-#include <asm/iSeries/HvCallSc.h>
+
+ EXPORT_SYMBOL(strcpy);
+ EXPORT_SYMBOL(strncpy);
+@@ -46,17 +45,6 @@ EXPORT_SYMBOL(__strnlen_user);
+
+ EXPORT_SYMBOL(reloc_offset);
+
+-#ifdef CONFIG_PPC_ISERIES
+-EXPORT_SYMBOL(HvCall0);
+-EXPORT_SYMBOL(HvCall1);
+-EXPORT_SYMBOL(HvCall2);
+-EXPORT_SYMBOL(HvCall3);
+-EXPORT_SYMBOL(HvCall4);
+-EXPORT_SYMBOL(HvCall5);
+-EXPORT_SYMBOL(HvCall6);
+-EXPORT_SYMBOL(HvCall7);
+-#endif
+-
+ EXPORT_SYMBOL(_insb);
+ EXPORT_SYMBOL(_outsb);
+ EXPORT_SYMBOL(_insw);
+@@ -77,14 +65,6 @@ EXPORT_SYMBOL(giveup_altivec);
+ EXPORT_SYMBOL(__flush_icache_range);
+ EXPORT_SYMBOL(flush_dcache_range);
+
+-#ifdef CONFIG_SMP
+-#ifdef CONFIG_PPC_ISERIES
+-EXPORT_SYMBOL(local_get_flags);
+-EXPORT_SYMBOL(local_irq_disable);
+-EXPORT_SYMBOL(local_irq_restore);
+-#endif
+-#endif
+-
+ EXPORT_SYMBOL(memcpy);
+ EXPORT_SYMBOL(memset);
+ EXPORT_SYMBOL(memmove);
+diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/process.c
++++ /dev/null
+@@ -1,713 +0,0 @@
+-/*
+- * linux/arch/ppc64/kernel/process.c
+- *
+- * Derived from "arch/i386/kernel/process.c"
+- * Copyright (C) 1995 Linus Torvalds
+- *
+- * Updated and modified by Cort Dougan (cort at cs.nmt.edu) and
+- * Paul Mackerras (paulus at cs.anu.edu.au)
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.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/config.h>
+-#include <linux/module.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/slab.h>
+-#include <linux/user.h>
+-#include <linux/elf.h>
+-#include <linux/init.h>
+-#include <linux/init_task.h>
+-#include <linux/prctl.h>
+-#include <linux/ptrace.h>
+-#include <linux/kallsyms.h>
+-#include <linux/interrupt.h>
+-#include <linux/utsname.h>
+-#include <linux/kprobes.h>
+-
+-#include <asm/pgtable.h>
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/processor.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/prom.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/machdep.h>
+-#include <asm/iSeries/HvCallHpt.h>
+-#include <asm/cputable.h>
+-#include <asm/firmware.h>
+-#include <asm/sections.h>
+-#include <asm/tlbflush.h>
+-#include <asm/time.h>
+-#include <asm/plpar_wrappers.h>
+-
+-#ifndef CONFIG_SMP
+-struct task_struct *last_task_used_math = NULL;
+-struct task_struct *last_task_used_altivec = NULL;
+-#endif
+-
+-/*
+- * Make sure the floating-point register state in the
+- * the thread_struct is up to date for task tsk.
+- */
+-void flush_fp_to_thread(struct task_struct *tsk)
+-{
+- if (tsk->thread.regs) {
+- /*
+- * We need to disable preemption here because if we didn't,
+- * another process could get scheduled after the regs->msr
+- * test but before we have finished saving the FP registers
+- * to the thread_struct. That process could take over the
+- * FPU, and then when we get scheduled again we would store
+- * bogus values for the remaining FP registers.
+- */
+- preempt_disable();
+- if (tsk->thread.regs->msr & MSR_FP) {
+-#ifdef CONFIG_SMP
+- /*
+- * This should only ever be called for current or
+- * for a stopped child process. Since we save away
+- * the FP register state on context switch on SMP,
+- * there is something wrong if a stopped child appears
+- * to still have its FP state in the CPU registers.
+- */
+- BUG_ON(tsk != current);
+-#endif
+- giveup_fpu(current);
+- }
+- preempt_enable();
+- }
+-}
+-
+-void enable_kernel_fp(void)
+-{
+- WARN_ON(preemptible());
+-
+-#ifdef CONFIG_SMP
+- if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
+- giveup_fpu(current);
+- else
+- giveup_fpu(NULL); /* just enables FP for kernel */
+-#else
+- giveup_fpu(last_task_used_math);
+-#endif /* CONFIG_SMP */
+-}
+-EXPORT_SYMBOL(enable_kernel_fp);
+-
+-int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
+-{
+- if (!tsk->thread.regs)
+- return 0;
+- flush_fp_to_thread(current);
+-
+- memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
+-
+- return 1;
+-}
+-
+-#ifdef CONFIG_ALTIVEC
+-
+-void enable_kernel_altivec(void)
+-{
+- WARN_ON(preemptible());
+-
+-#ifdef CONFIG_SMP
+- if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
+- giveup_altivec(current);
+- else
+- giveup_altivec(NULL); /* just enables FP for kernel */
+-#else
+- giveup_altivec(last_task_used_altivec);
+-#endif /* CONFIG_SMP */
+-}
+-EXPORT_SYMBOL(enable_kernel_altivec);
+-
+-/*
+- * Make sure the VMX/Altivec register state in the
+- * the thread_struct is up to date for task tsk.
+- */
+-void flush_altivec_to_thread(struct task_struct *tsk)
+-{
+- if (tsk->thread.regs) {
+- preempt_disable();
+- if (tsk->thread.regs->msr & MSR_VEC) {
+-#ifdef CONFIG_SMP
+- BUG_ON(tsk != current);
+-#endif
+- giveup_altivec(current);
+- }
+- preempt_enable();
+- }
+-}
+-
+-int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
+-{
+- flush_altivec_to_thread(current);
+- memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs));
+- return 1;
+-}
+-
+-#endif /* CONFIG_ALTIVEC */
+-
+-static void set_dabr_spr(unsigned long val)
+-{
+- mtspr(SPRN_DABR, val);
+-}
+-
+-int set_dabr(unsigned long dabr)
+-{
+- int ret = 0;
+-
+- if (firmware_has_feature(FW_FEATURE_XDABR)) {
+- /* We want to catch accesses from kernel and userspace */
+- unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER;
+- ret = plpar_set_xdabr(dabr, flags);
+- } else if (firmware_has_feature(FW_FEATURE_DABR)) {
+- ret = plpar_set_dabr(dabr);
+- } else {
+- set_dabr_spr(dabr);
+- }
+-
+- return ret;
+-}
+-
+-DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+-static DEFINE_PER_CPU(unsigned long, current_dabr);
+-
+-struct task_struct *__switch_to(struct task_struct *prev,
+- struct task_struct *new)
+-{
+- struct thread_struct *new_thread, *old_thread;
+- unsigned long flags;
+- struct task_struct *last;
+-
+-#ifdef CONFIG_SMP
+- /* avoid complexity of lazy save/restore of fpu
+- * by just saving it every time we switch out if
+- * this task used the fpu during the last quantum.
+- *
+- * If it tries to use the fpu again, it'll trap and
+- * reload its fp regs. So we don't have to do a restore
+- * every switch, just a save.
+- * -- Cort
+- */
+- if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
+- giveup_fpu(prev);
+-#ifdef CONFIG_ALTIVEC
+- if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))
+- giveup_altivec(prev);
+-#endif /* CONFIG_ALTIVEC */
+-#endif /* CONFIG_SMP */
+-
+-#if defined(CONFIG_ALTIVEC) && !defined(CONFIG_SMP)
+- /* Avoid the trap. On smp this this never happens since
+- * we don't set last_task_used_altivec -- Cort
+- */
+- if (new->thread.regs && last_task_used_altivec == new)
+- new->thread.regs->msr |= MSR_VEC;
+-#endif /* CONFIG_ALTIVEC */
+-
+- if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
+- set_dabr(new->thread.dabr);
+- __get_cpu_var(current_dabr) = new->thread.dabr;
+- }
+-
+- flush_tlb_pending();
+-
+- new_thread = &new->thread;
+- old_thread = ¤t->thread;
+-
+- /* Collect purr utilization data per process and per processor
+- * wise purr is nothing but processor time base
+- */
+- if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+- struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
+- long unsigned start_tb, current_tb;
+- start_tb = old_thread->start_tb;
+- cu->current_tb = current_tb = mfspr(SPRN_PURR);
+- old_thread->accum_tb += (current_tb - start_tb);
+- new_thread->start_tb = current_tb;
+- }
+-
+- local_irq_save(flags);
+- last = _switch(old_thread, new_thread);
+-
+- local_irq_restore(flags);
+-
+- return last;
+-}
+-
+-static int instructions_to_print = 16;
+-
+-static void show_instructions(struct pt_regs *regs)
+-{
+- int i;
+- unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 *
+- sizeof(int));
+-
+- printk("Instruction dump:");
+-
+- for (i = 0; i < instructions_to_print; i++) {
+- int instr;
+-
+- if (!(i % 8))
+- printk("\n");
+-
+- if (((REGION_ID(pc) != KERNEL_REGION_ID) &&
+- (REGION_ID(pc) != VMALLOC_REGION_ID)) ||
+- __get_user(instr, (unsigned int *)pc)) {
+- printk("XXXXXXXX ");
+- } else {
+- if (regs->nip == pc)
+- printk("<%08x> ", instr);
+- else
+- printk("%08x ", instr);
+- }
+-
+- pc += sizeof(int);
+- }
+-
+- printk("\n");
+-}
+-
+-void show_regs(struct pt_regs * regs)
+-{
+- int i;
+- unsigned long trap;
+-
+- printk("NIP: %016lX XER: %08X LR: %016lX CTR: %016lX\n",
+- regs->nip, (unsigned int)regs->xer, regs->link, regs->ctr);
+- printk("REGS: %p TRAP: %04lx %s (%s)\n",
+- regs, regs->trap, print_tainted(), system_utsname.release);
+- printk("MSR: %016lx EE: %01x PR: %01x FP: %01x ME: %01x "
+- "IR/DR: %01x%01x CR: %08X\n",
+- regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+- regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+- regs->msr&MSR_IR ? 1 : 0,
+- regs->msr&MSR_DR ? 1 : 0,
+- (unsigned int)regs->ccr);
+- trap = TRAP(regs);
+- printk("DAR: %016lx DSISR: %016lx\n", regs->dar, regs->dsisr);
+- printk("TASK: %p[%d] '%s' THREAD: %p",
+- current, current->pid, current->comm, current->thread_info);
+-
+-#ifdef CONFIG_SMP
+- printk(" CPU: %d", smp_processor_id());
+-#endif /* CONFIG_SMP */
+-
+- for (i = 0; i < 32; i++) {
+- if ((i % 4) == 0) {
+- printk("\n" KERN_INFO "GPR%02d: ", i);
+- }
+-
+- printk("%016lX ", regs->gpr[i]);
+- if (i == 13 && !FULL_REGS(regs))
+- break;
+- }
+- printk("\n");
+- /*
+- * Lookup NIP late so we have the best change of getting the
+- * above info out without failing
+- */
+- printk("NIP [%016lx] ", regs->nip);
+- print_symbol("%s\n", regs->nip);
+- printk("LR [%016lx] ", regs->link);
+- print_symbol("%s\n", regs->link);
+- show_stack(current, (unsigned long *)regs->gpr[1]);
+- if (!user_mode(regs))
+- show_instructions(regs);
+-}
+-
+-void exit_thread(void)
+-{
+- kprobe_flush_task(current);
+-
+-#ifndef CONFIG_SMP
+- if (last_task_used_math == current)
+- last_task_used_math = NULL;
+-#ifdef CONFIG_ALTIVEC
+- if (last_task_used_altivec == current)
+- last_task_used_altivec = NULL;
+-#endif /* CONFIG_ALTIVEC */
+-#endif /* CONFIG_SMP */
+-}
+-
+-void flush_thread(void)
+-{
+- struct thread_info *t = current_thread_info();
+-
+- kprobe_flush_task(current);
+- if (t->flags & _TIF_ABI_PENDING)
+- t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
+-
+-#ifndef CONFIG_SMP
+- if (last_task_used_math == current)
+- last_task_used_math = NULL;
+-#ifdef CONFIG_ALTIVEC
+- if (last_task_used_altivec == current)
+- last_task_used_altivec = NULL;
+-#endif /* CONFIG_ALTIVEC */
+-#endif /* CONFIG_SMP */
+-
+- if (current->thread.dabr) {
+- current->thread.dabr = 0;
+- set_dabr(0);
+- }
+-}
+-
+-void
+-release_thread(struct task_struct *t)
+-{
+-}
+-
+-
+-/*
+- * This gets called before we allocate a new thread and copy
+- * the current task into it.
+- */
+-void prepare_to_copy(struct task_struct *tsk)
+-{
+- flush_fp_to_thread(current);
+- flush_altivec_to_thread(current);
+-}
+-
+-/*
+- * Copy a thread..
+- */
+-int
+-copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+- unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+-{
+- struct pt_regs *childregs, *kregs;
+- extern void ret_from_fork(void);
+- unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
+-
+- /* Copy registers */
+- sp -= sizeof(struct pt_regs);
+- childregs = (struct pt_regs *) sp;
+- *childregs = *regs;
+- if ((childregs->msr & MSR_PR) == 0) {
+- /* for kernel thread, set stackptr in new task */
+- childregs->gpr[1] = sp + sizeof(struct pt_regs);
+- p->thread.regs = NULL; /* no user register state */
+- clear_ti_thread_flag(p->thread_info, TIF_32BIT);
+- } else {
+- childregs->gpr[1] = usp;
+- p->thread.regs = childregs;
+- if (clone_flags & CLONE_SETTLS) {
+- if (test_thread_flag(TIF_32BIT))
+- childregs->gpr[2] = childregs->gpr[6];
+- else
+- childregs->gpr[13] = childregs->gpr[6];
+- }
+- }
+- childregs->gpr[3] = 0; /* Result from fork() */
+- sp -= STACK_FRAME_OVERHEAD;
+-
+- /*
+- * The way this works is that at some point in the future
+- * some task will call _switch to switch to the new task.
+- * That will pop off the stack frame created below and start
+- * the new task running at ret_from_fork. The new task will
+- * do some house keeping and then return from the fork or clone
+- * system call, using the stack frame created above.
+- */
+- sp -= sizeof(struct pt_regs);
+- kregs = (struct pt_regs *) sp;
+- sp -= STACK_FRAME_OVERHEAD;
+- p->thread.ksp = sp;
+- if (cpu_has_feature(CPU_FTR_SLB)) {
+- unsigned long sp_vsid = get_kernel_vsid(sp);
+-
+- sp_vsid <<= SLB_VSID_SHIFT;
+- sp_vsid |= SLB_VSID_KERNEL;
+- if (cpu_has_feature(CPU_FTR_16M_PAGE))
+- sp_vsid |= SLB_VSID_L;
+-
+- p->thread.ksp_vsid = sp_vsid;
+- }
+-
+- /*
+- * The PPC64 ABI makes use of a TOC to contain function
+- * pointers. The function (ret_from_except) is actually a pointer
+- * to the TOC entry. The first entry is a pointer to the actual
+- * function.
+- */
+- kregs->nip = *((unsigned long *)ret_from_fork);
+-
+- return 0;
+-}
+-
+-/*
+- * Set up a thread for executing a new program
+- */
+-void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp)
+-{
+- unsigned long entry, toc, load_addr = regs->gpr[2];
+-
+- /* fdptr is a relocated pointer to the function descriptor for
+- * the elf _start routine. The first entry in the function
+- * descriptor is the entry address of _start and the second
+- * entry is the TOC value we need to use.
+- */
+- set_fs(USER_DS);
+- __get_user(entry, (unsigned long __user *)fdptr);
+- __get_user(toc, (unsigned long __user *)fdptr+1);
+-
+- /* Check whether the e_entry function descriptor entries
+- * need to be relocated before we can use them.
+- */
+- if (load_addr != 0) {
+- entry += load_addr;
+- toc += load_addr;
+- }
+-
+- /*
+- * If we exec out of a kernel thread then thread.regs will not be
+- * set. Do it now.
+- */
+- if (!current->thread.regs) {
+- unsigned long childregs = (unsigned long)current->thread_info +
+- THREAD_SIZE;
+- childregs -= sizeof(struct pt_regs);
+- current->thread.regs = (struct pt_regs *)childregs;
+- }
+-
+- regs->nip = entry;
+- regs->gpr[1] = sp;
+- regs->gpr[2] = toc;
+- regs->msr = MSR_USER64;
+-#ifndef CONFIG_SMP
+- if (last_task_used_math == current)
+- last_task_used_math = 0;
+-#endif /* CONFIG_SMP */
+- memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
+- current->thread.fpscr = 0;
+-#ifdef CONFIG_ALTIVEC
+-#ifndef CONFIG_SMP
+- if (last_task_used_altivec == current)
+- last_task_used_altivec = 0;
+-#endif /* CONFIG_SMP */
+- memset(current->thread.vr, 0, sizeof(current->thread.vr));
+- current->thread.vscr.u[0] = 0;
+- current->thread.vscr.u[1] = 0;
+- current->thread.vscr.u[2] = 0;
+- current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */
+- current->thread.vrsave = 0;
+- current->thread.used_vr = 0;
+-#endif /* CONFIG_ALTIVEC */
+-}
+-EXPORT_SYMBOL(start_thread);
+-
+-int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
+-{
+- struct pt_regs *regs = tsk->thread.regs;
+-
+- if (val > PR_FP_EXC_PRECISE)
+- return -EINVAL;
+- tsk->thread.fpexc_mode = __pack_fe01(val);
+- if (regs != NULL && (regs->msr & MSR_FP) != 0)
+- regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
+- | tsk->thread.fpexc_mode;
+- return 0;
+-}
+-
+-int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
+-{
+- unsigned int val;
+-
+- val = __unpack_fe01(tsk->thread.fpexc_mode);
+- return put_user(val, (unsigned int __user *) adr);
+-}
+-
+-int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3,
+- unsigned long p4, unsigned long p5, unsigned long p6,
+- struct pt_regs *regs)
+-{
+- unsigned long parent_tidptr = 0;
+- unsigned long child_tidptr = 0;
+-
+- if (p2 == 0)
+- p2 = regs->gpr[1]; /* stack pointer for child */
+-
+- if (clone_flags & (CLONE_PARENT_SETTID | CLONE_CHILD_SETTID |
+- CLONE_CHILD_CLEARTID)) {
+- parent_tidptr = p3;
+- child_tidptr = p5;
+- if (test_thread_flag(TIF_32BIT)) {
+- parent_tidptr &= 0xffffffff;
+- child_tidptr &= 0xffffffff;
+- }
+- }
+-
+- return do_fork(clone_flags, p2, regs, 0,
+- (int __user *)parent_tidptr, (int __user *)child_tidptr);
+-}
+-
+-int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
+- unsigned long p4, unsigned long p5, unsigned long p6,
+- struct pt_regs *regs)
+-{
+- return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
+-}
+-
+-int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
+- unsigned long p4, unsigned long p5, unsigned long p6,
+- struct pt_regs *regs)
+-{
+- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0,
+- NULL, NULL);
+-}
+-
+-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+- unsigned long a3, unsigned long a4, unsigned long a5,
+- struct pt_regs *regs)
+-{
+- int error;
+- char * filename;
+-
+- filename = getname((char __user *) a0);
+- error = PTR_ERR(filename);
+- if (IS_ERR(filename))
+- goto out;
+- flush_fp_to_thread(current);
+- flush_altivec_to_thread(current);
+- error = do_execve(filename, (char __user * __user *) a1,
+- (char __user * __user *) a2, regs);
+-
+- if (error == 0) {
+- task_lock(current);
+- current->ptrace &= ~PT_DTRACE;
+- task_unlock(current);
+- }
+- putname(filename);
+-
+-out:
+- return error;
+-}
+-
+-static int kstack_depth_to_print = 64;
+-
+-static int validate_sp(unsigned long sp, struct task_struct *p,
+- unsigned long nbytes)
+-{
+- unsigned long stack_page = (unsigned long)p->thread_info;
+-
+- if (sp >= stack_page + sizeof(struct thread_struct)
+- && sp <= stack_page + THREAD_SIZE - nbytes)
+- return 1;
+-
+-#ifdef CONFIG_IRQSTACKS
+- stack_page = (unsigned long) hardirq_ctx[task_cpu(p)];
+- if (sp >= stack_page + sizeof(struct thread_struct)
+- && sp <= stack_page + THREAD_SIZE - nbytes)
+- return 1;
+-
+- stack_page = (unsigned long) softirq_ctx[task_cpu(p)];
+- if (sp >= stack_page + sizeof(struct thread_struct)
+- && sp <= stack_page + THREAD_SIZE - nbytes)
+- return 1;
+-#endif
+-
+- return 0;
+-}
+-
+-unsigned long get_wchan(struct task_struct *p)
+-{
+- unsigned long ip, sp;
+- int count = 0;
+-
+- if (!p || p == current || p->state == TASK_RUNNING)
+- return 0;
+-
+- sp = p->thread.ksp;
+- if (!validate_sp(sp, p, 112))
+- return 0;
+-
+- do {
+- sp = *(unsigned long *)sp;
+- if (!validate_sp(sp, p, 112))
+- return 0;
+- if (count > 0) {
+- ip = *(unsigned long *)(sp + 16);
+- if (!in_sched_functions(ip))
+- return ip;
+- }
+- } while (count++ < 16);
+- return 0;
+-}
+-EXPORT_SYMBOL(get_wchan);
+-
+-void show_stack(struct task_struct *p, unsigned long *_sp)
+-{
+- unsigned long ip, newsp, lr;
+- int count = 0;
+- unsigned long sp = (unsigned long)_sp;
+- int firstframe = 1;
+-
+- if (sp == 0) {
+- if (p) {
+- sp = p->thread.ksp;
+- } else {
+- sp = __get_SP();
+- p = current;
+- }
+- }
+-
+- lr = 0;
+- printk("Call Trace:\n");
+- do {
+- if (!validate_sp(sp, p, 112))
+- return;
+-
+- _sp = (unsigned long *) sp;
+- newsp = _sp[0];
+- ip = _sp[2];
+- if (!firstframe || ip != lr) {
+- printk("[%016lx] [%016lx] ", sp, ip);
+- print_symbol("%s", ip);
+- if (firstframe)
+- printk(" (unreliable)");
+- printk("\n");
+- }
+- firstframe = 0;
+-
+- /*
+- * See if this is an exception frame.
+- * We look for the "regshere" marker in the current frame.
+- */
+- if (validate_sp(sp, p, sizeof(struct pt_regs) + 400)
+- && _sp[12] == 0x7265677368657265ul) {
+- struct pt_regs *regs = (struct pt_regs *)
+- (sp + STACK_FRAME_OVERHEAD);
+- printk("--- Exception: %lx", regs->trap);
+- print_symbol(" at %s\n", regs->nip);
+- lr = regs->link;
+- print_symbol(" LR = %s\n", lr);
+- firstframe = 1;
+- }
+-
+- sp = newsp;
+- } while (count++ < kstack_depth_to_print);
+-}
+-
+-void dump_stack(void)
+-{
+- show_stack(current, (unsigned long *)__get_SP());
+-}
+-EXPORT_SYMBOL(dump_stack);
+diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
+--- a/arch/ppc64/kernel/prom.c
++++ b/arch/ppc64/kernel/prom.c
+@@ -46,7 +46,6 @@
+ #include <asm/pgtable.h>
+ #include <asm/pci.h>
+ #include <asm/iommu.h>
+-#include <asm/bootinfo.h>
+ #include <asm/ppcdebug.h>
+ #include <asm/btext.h>
+ #include <asm/sections.h>
+@@ -78,11 +77,14 @@ typedef int interpret_func(struct device
+ extern struct rtas_t rtas;
+ extern struct lmb lmb;
+ extern unsigned long klimit;
++extern unsigned long memory_limit;
+
+ static int __initdata dt_root_addr_cells;
+ static int __initdata dt_root_size_cells;
+ static int __initdata iommu_is_off;
+ int __initdata iommu_force_on;
++unsigned long tce_alloc_start, tce_alloc_end;
++
+ typedef u32 cell_t;
+
+ #if 0
+@@ -1063,7 +1065,6 @@ static int __init early_init_dt_scan_cho
+ {
+ u32 *prop;
+ u64 *prop64;
+- extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
+
+ DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+@@ -1237,7 +1238,7 @@ void __init early_init_devtree(void *par
+ lmb_init();
+ scan_flat_dt(early_init_dt_scan_root, NULL);
+ scan_flat_dt(early_init_dt_scan_memory, NULL);
+- lmb_enforce_memory_limit();
++ lmb_enforce_memory_limit(memory_limit);
+ lmb_analyze();
+ systemcfg->physicalMemorySize = lmb_phys_mem_size();
+ lmb_reserve(0, __pa(klimit));
+diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
+--- a/arch/ppc64/kernel/prom_init.c
++++ b/arch/ppc64/kernel/prom_init.c
+@@ -44,7 +44,6 @@
+ #include <asm/pgtable.h>
+ #include <asm/pci.h>
+ #include <asm/iommu.h>
+-#include <asm/bootinfo.h>
+ #include <asm/ppcdebug.h>
+ #include <asm/btext.h>
+ #include <asm/sections.h>
+diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/ptrace.c
++++ /dev/null
+@@ -1,363 +0,0 @@
+-/*
+- * linux/arch/ppc64/kernel/ptrace.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Derived from "arch/m68k/kernel/ptrace.c"
+- * Copyright (C) 1994 by Hamish Macdonald
+- * Taken from linux/kernel/ptrace.c and modified for M680x0.
+- * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+- *
+- * Modified by Cort Dougan (cort at hq.fsmlabs.com)
+- * and Paul Mackerras (paulus at linuxcare.com.au).
+- *
+- * This file is subject to the terms and conditions of the GNU General
+- * Public License. See the file README.legal in the main directory of
+- * this archive for more details.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/errno.h>
+-#include <linux/ptrace.h>
+-#include <linux/user.h>
+-#include <linux/security.h>
+-#include <linux/audit.h>
+-#include <linux/seccomp.h>
+-#include <linux/signal.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/system.h>
+-#include <asm/ptrace-common.h>
+-
+-/*
+- * does not yet catch signals sent when the child dies.
+- * in exit.c or in signal.c.
+- */
+-
+-/*
+- * Called by kernel/ptrace.c when detaching..
+- *
+- * Make sure single step bits etc are not set.
+- */
+-void ptrace_disable(struct task_struct *child)
+-{
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+-}
+-
+-int sys_ptrace(long request, long pid, long addr, long data)
+-{
+- struct task_struct *child;
+- int ret = -EPERM;
+-
+- lock_kernel();
+- if (request == PTRACE_TRACEME) {
+- /* are we already being traced? */
+- if (current->ptrace & PT_PTRACED)
+- goto out;
+- ret = security_ptrace(current->parent, current);
+- if (ret)
+- goto out;
+- /* set the ptrace bit in the process flags. */
+- current->ptrace |= PT_PTRACED;
+- ret = 0;
+- goto out;
+- }
+- ret = -ESRCH;
+- read_lock(&tasklist_lock);
+- child = find_task_by_pid(pid);
+- if (child)
+- get_task_struct(child);
+- read_unlock(&tasklist_lock);
+- if (!child)
+- goto out;
+-
+- ret = -EPERM;
+- if (pid == 1) /* you may not mess with init */
+- goto out_tsk;
+-
+- if (request == PTRACE_ATTACH) {
+- ret = ptrace_attach(child);
+- goto out_tsk;
+- }
+-
+- ret = ptrace_check_attach(child, request == PTRACE_KILL);
+- if (ret < 0)
+- goto out_tsk;
+-
+- switch (request) {
+- /* when I and D space are separate, these will need to be fixed. */
+- case PTRACE_PEEKTEXT: /* read word at location addr. */
+- case PTRACE_PEEKDATA: {
+- unsigned long tmp;
+- int copied;
+-
+- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+- ret = -EIO;
+- if (copied != sizeof(tmp))
+- break;
+- ret = put_user(tmp,(unsigned long __user *) data);
+- break;
+- }
+-
+- /* read the word at location addr in the USER area. */
+- case PTRACE_PEEKUSR: {
+- unsigned long index;
+- unsigned long tmp;
+-
+- ret = -EIO;
+- /* convert to index and check */
+- index = (unsigned long) addr >> 3;
+- if ((addr & 7) || (index > PT_FPSCR))
+- break;
+-
+- if (index < PT_FPR0) {
+- tmp = get_reg(child, (int)index);
+- } else {
+- flush_fp_to_thread(child);
+- tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
+- }
+- ret = put_user(tmp,(unsigned long __user *) data);
+- break;
+- }
+-
+- /* If I and D space are separate, this will have to be fixed. */
+- case PTRACE_POKETEXT: /* write the word at location addr. */
+- case PTRACE_POKEDATA:
+- ret = 0;
+- if (access_process_vm(child, addr, &data, sizeof(data), 1)
+- == sizeof(data))
+- break;
+- ret = -EIO;
+- break;
+-
+- /* write the word at location addr in the USER area */
+- case PTRACE_POKEUSR: {
+- unsigned long index;
+-
+- ret = -EIO;
+- /* convert to index and check */
+- index = (unsigned long) addr >> 3;
+- if ((addr & 7) || (index > PT_FPSCR))
+- break;
+-
+- if (index == PT_ORIG_R3)
+- break;
+- if (index < PT_FPR0) {
+- ret = put_reg(child, index, data);
+- } else {
+- flush_fp_to_thread(child);
+- ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
+- ret = 0;
+- }
+- break;
+- }
+-
+- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+- case PTRACE_CONT: { /* restart after signal. */
+- ret = -EIO;
+- if (!valid_signal(data))
+- break;
+- if (request == PTRACE_SYSCALL)
+- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- else
+- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- child->exit_code = data;
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+- wake_up_process(child);
+- ret = 0;
+- break;
+- }
+-
+- /*
+- * make the child exit. Best I can do is send it a sigkill.
+- * perhaps it should be put in the status that it wants to
+- * exit.
+- */
+- case PTRACE_KILL: {
+- ret = 0;
+- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+- break;
+- child->exit_code = SIGKILL;
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+- wake_up_process(child);
+- break;
+- }
+-
+- case PTRACE_SINGLESTEP: { /* set the trap flag. */
+- ret = -EIO;
+- if (!valid_signal(data))
+- break;
+- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- set_single_step(child);
+- child->exit_code = data;
+- /* give it a chance to run. */
+- wake_up_process(child);
+- ret = 0;
+- break;
+- }
+-
+- case PTRACE_GET_DEBUGREG: {
+- ret = -EINVAL;
+- /* We only support one DABR and no IABRS at the moment */
+- if (addr > 0)
+- break;
+- ret = put_user(child->thread.dabr,
+- (unsigned long __user *)data);
+- break;
+- }
+-
+- case PTRACE_SET_DEBUGREG:
+- ret = ptrace_set_debugreg(child, addr, data);
+- break;
+-
+- case PTRACE_DETACH:
+- ret = ptrace_detach(child, data);
+- break;
+-
+- case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+- unsigned long __user *tmp = (unsigned long __user *)addr;
+-
+- for (i = 0; i < 32; i++) {
+- ret = put_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+- case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+- unsigned long __user *tmp = (unsigned long __user *)addr;
+-
+- for (i = 0; i < 32; i++) {
+- ret = get_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+- case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+- unsigned long __user *tmp = (unsigned long __user *)addr;
+-
+- flush_fp_to_thread(child);
+-
+- for (i = 0; i < 32; i++) {
+- ret = put_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+- case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+- unsigned long __user *tmp = (unsigned long __user *)addr;
+-
+- flush_fp_to_thread(child);
+-
+- for (i = 0; i < 32; i++) {
+- ret = get_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+-#ifdef CONFIG_ALTIVEC
+- case PTRACE_GETVRREGS:
+- /* Get the child altivec register state. */
+- flush_altivec_to_thread(child);
+- ret = get_vrregs((unsigned long __user *)data, child);
+- break;
+-
+- case PTRACE_SETVRREGS:
+- /* Set the child altivec register state. */
+- flush_altivec_to_thread(child);
+- ret = set_vrregs(child, (unsigned long __user *)data);
+- break;
+-#endif
+-
+- default:
+- ret = ptrace_request(child, request, addr, data);
+- break;
+- }
+-out_tsk:
+- put_task_struct(child);
+-out:
+- unlock_kernel();
+- return ret;
+-}
+-
+-static void do_syscall_trace(void)
+-{
+- /* the 0x80 provides a way for the tracing parent to distinguish
+- between a syscall stop and SIGTRAP delivery */
+- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+- ? 0x80 : 0));
+-
+- /*
+- * this isn't the same as continuing with a signal, but it will do
+- * for normal use. strace only continues with a signal if the
+- * stopping signal is not SIGTRAP. -brl
+- */
+- if (current->exit_code) {
+- send_sig(current->exit_code, current, 1);
+- current->exit_code = 0;
+- }
+-}
+-
+-void do_syscall_trace_enter(struct pt_regs *regs)
+-{
+- secure_computing(regs->gpr[0]);
+-
+- if (test_thread_flag(TIF_SYSCALL_TRACE)
+- && (current->ptrace & PT_PTRACED))
+- do_syscall_trace();
+-
+- if (unlikely(current->audit_context))
+- audit_syscall_entry(current,
+- test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
+- regs->gpr[0],
+- regs->gpr[3], regs->gpr[4],
+- regs->gpr[5], regs->gpr[6]);
+-
+-}
+-
+-void do_syscall_trace_leave(struct pt_regs *regs)
+-{
+- if (unlikely(current->audit_context))
+- audit_syscall_exit(current,
+- (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+- regs->result);
+-
+- if ((test_thread_flag(TIF_SYSCALL_TRACE)
+- || test_thread_flag(TIF_SINGLESTEP))
+- && (current->ptrace & PT_PTRACED))
+- do_syscall_trace();
+-}
+diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/ptrace32.c
++++ /dev/null
+@@ -1,449 +0,0 @@
+-/*
+- * linux/arch/ppc64/kernel/ptrace32.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Derived from "arch/m68k/kernel/ptrace.c"
+- * Copyright (C) 1994 by Hamish Macdonald
+- * Taken from linux/kernel/ptrace.c and modified for M680x0.
+- * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+- *
+- * Modified by Cort Dougan (cort at hq.fsmlabs.com)
+- * and Paul Mackerras (paulus at linuxcare.com.au).
+- *
+- * This file is subject to the terms and conditions of the GNU General
+- * Public License. See the file README.legal in the main directory of
+- * this archive for more details.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/errno.h>
+-#include <linux/ptrace.h>
+-#include <linux/user.h>
+-#include <linux/security.h>
+-#include <linux/signal.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/system.h>
+-#include <asm/ptrace-common.h>
+-
+-/*
+- * does not yet catch signals sent when the child dies.
+- * in exit.c or in signal.c.
+- */
+-
+-int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
+-{
+- struct task_struct *child;
+- int ret = -EPERM;
+-
+- lock_kernel();
+- if (request == PTRACE_TRACEME) {
+- /* are we already being traced? */
+- if (current->ptrace & PT_PTRACED)
+- goto out;
+- ret = security_ptrace(current->parent, current);
+- if (ret)
+- goto out;
+- /* set the ptrace bit in the process flags. */
+- current->ptrace |= PT_PTRACED;
+- ret = 0;
+- goto out;
+- }
+- ret = -ESRCH;
+- read_lock(&tasklist_lock);
+- child = find_task_by_pid(pid);
+- if (child)
+- get_task_struct(child);
+- read_unlock(&tasklist_lock);
+- if (!child)
+- goto out;
+-
+- ret = -EPERM;
+- if (pid == 1) /* you may not mess with init */
+- goto out_tsk;
+-
+- if (request == PTRACE_ATTACH) {
+- ret = ptrace_attach(child);
+- goto out_tsk;
+- }
+-
+- ret = ptrace_check_attach(child, request == PTRACE_KILL);
+- if (ret < 0)
+- goto out_tsk;
+-
+- switch (request) {
+- /* when I and D space are separate, these will need to be fixed. */
+- case PTRACE_PEEKTEXT: /* read word at location addr. */
+- case PTRACE_PEEKDATA: {
+- unsigned int tmp;
+- int copied;
+-
+- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+- ret = -EIO;
+- if (copied != sizeof(tmp))
+- break;
+- ret = put_user(tmp, (u32 __user *)data);
+- 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 PPC_PTRACE_PEEKTEXT_3264:
+- case PPC_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 *)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 *)data);
+- break;
+- }
+-
+- /* Read a register (specified by ADDR) out of the "user area" */
+- case PTRACE_PEEKUSR: {
+- int index;
+- unsigned long tmp;
+-
+- ret = -EIO;
+- /* convert to index and check */
+- index = (unsigned long) addr >> 2;
+- if ((addr & 3) || (index > PT_FPSCR32))
+- break;
+-
+- if (index < PT_FPR0) {
+- tmp = get_reg(child, index);
+- } else {
+- flush_fp_to_thread(child);
+- /*
+- * the user space code considers the floating point
+- * to be an array of unsigned int (32 bits) - the
+- * index passed in is based on this assumption.
+- */
+- tmp = ((unsigned int *)child->thread.fpr)[index - PT_FPR0];
+- }
+- ret = put_user((unsigned int)tmp, (u32 __user *)data);
+- break;
+- }
+-
+- /*
+- * Read 4 bytes out of the other process' pt_regs area
+- * data is a pointer specifying where the user wants the
+- * 4 bytes copied into
+- * addr is the offset into the other process' pt_regs structure
+- * that is to be read
+- * (this is run in a 32-bit process looking at a 64-bit process)
+- */
+- case PPC_PTRACE_PEEKUSR_3264: {
+- u32 index;
+- u32 reg32bits;
+- u64 tmp;
+- u32 numReg;
+- u32 part;
+-
+- ret = -EIO;
+- /* Determine which register the user wants */
+- index = (u64)addr >> 2;
+- numReg = index / 2;
+- /* Determine which part of the register the user wants */
+- if (index % 2)
+- part = 1; /* want the 2nd half of the register (right-most). */
+- else
+- part = 0; /* want the 1st half of the register (left-most). */
+-
+- /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
+- if ((addr & 3) || numReg > PT_FPSCR)
+- break;
+-
+- if (numReg >= PT_FPR0) {
+- flush_fp_to_thread(child);
+- tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
+- } else { /* register within PT_REGS struct */
+- tmp = get_reg(child, numReg);
+- }
+- reg32bits = ((u32*)&tmp)[part];
+- ret = put_user(reg32bits, (u32 __user *)data);
+- break;
+- }
+-
+- /* If I and D space are separate, this will have to be fixed. */
+- case PTRACE_POKETEXT: /* write the word at location addr. */
+- case PTRACE_POKEDATA: {
+- unsigned int tmp;
+- tmp = data;
+- ret = 0;
+- if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1)
+- == sizeof(tmp))
+- break;
+- 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 PPC_PTRACE_POKETEXT_3264:
+- case PPC_PTRACE_POKEDATA_3264: {
+- u32 tmp = data;
+- 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 *)addr) != 0)
+- break;
+- ret = 0;
+- if (access_process_vm(child, (u64)addrOthers, &tmp,
+- sizeof(tmp), 1) == sizeof(tmp))
+- break;
+- ret = -EIO;
+- break;
+- }
+-
+- /* write the word at location addr in the USER area */
+- case PTRACE_POKEUSR: {
+- unsigned long index;
+-
+- ret = -EIO;
+- /* convert to index and check */
+- index = (unsigned long) addr >> 2;
+- if ((addr & 3) || (index > PT_FPSCR32))
+- break;
+-
+- if (index == PT_ORIG_R3)
+- break;
+- if (index < PT_FPR0) {
+- ret = put_reg(child, index, data);
+- } else {
+- flush_fp_to_thread(child);
+- /*
+- * the user space code considers the floating point
+- * to be an array of unsigned int (32 bits) - the
+- * index passed in is based on this assumption.
+- */
+- ((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data;
+- ret = 0;
+- }
+- break;
+- }
+-
+- /*
+- * Write 4 bytes into the other process' pt_regs area
+- * data is the 4 bytes that the user wants written
+- * addr is the offset into the other process' pt_regs structure
+- * that is to be written into
+- * (this is run in a 32-bit process looking at a 64-bit process)
+- */
+- case PPC_PTRACE_POKEUSR_3264: {
+- u32 index;
+- u32 numReg;
+-
+- ret = -EIO;
+- /* Determine which register the user wants */
+- index = (u64)addr >> 2;
+- numReg = index / 2;
+- /*
+- * Validate the input - check to see if address is on the
+- * wrong boundary or beyond the end of the user area
+- */
+- if ((addr & 3) || (numReg > PT_FPSCR))
+- break;
+- /* Insure it is a register we let them change */
+- if ((numReg == PT_ORIG_R3)
+- || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
+- break;
+- if (numReg >= PT_FPR0) {
+- flush_fp_to_thread(child);
+- }
+- if (numReg == PT_MSR)
+- data = (data & MSR_DEBUGCHANGE)
+- | (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
+- ((u32*)child->thread.regs)[index] = data;
+- ret = 0;
+- break;
+- }
+-
+- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+- case PTRACE_CONT: { /* restart after signal. */
+- ret = -EIO;
+- if (!valid_signal(data))
+- break;
+- if (request == PTRACE_SYSCALL)
+- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- else
+- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- child->exit_code = data;
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+- wake_up_process(child);
+- ret = 0;
+- break;
+- }
+-
+- /*
+- * make the child exit. Best I can do is send it a sigkill.
+- * perhaps it should be put in the status that it wants to
+- * exit.
+- */
+- case PTRACE_KILL: {
+- ret = 0;
+- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+- break;
+- child->exit_code = SIGKILL;
+- /* make sure the single step bit is not set. */
+- clear_single_step(child);
+- wake_up_process(child);
+- break;
+- }
+-
+- case PTRACE_SINGLESTEP: { /* set the trap flag. */
+- ret = -EIO;
+- if (!valid_signal(data))
+- break;
+- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+- set_single_step(child);
+- child->exit_code = data;
+- /* give it a chance to run. */
+- wake_up_process(child);
+- ret = 0;
+- break;
+- }
+-
+- case PTRACE_GET_DEBUGREG: {
+- ret = -EINVAL;
+- /* We only support one DABR and no IABRS at the moment */
+- if (addr > 0)
+- break;
+- ret = put_user(child->thread.dabr, (u32 __user *)data);
+- break;
+- }
+-
+- case PTRACE_SET_DEBUGREG:
+- ret = ptrace_set_debugreg(child, addr, data);
+- break;
+-
+- case PTRACE_DETACH:
+- ret = ptrace_detach(child, data);
+- break;
+-
+- case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+- unsigned int __user *tmp = (unsigned int __user *)addr;
+-
+- for (i = 0; i < 32; i++) {
+- ret = put_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+- case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+- unsigned int __user *tmp = (unsigned int __user *)addr;
+-
+- for (i = 0; i < 32; i++) {
+- ret = get_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+- case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+- unsigned int __user *tmp = (unsigned int __user *)addr;
+-
+- flush_fp_to_thread(child);
+-
+- for (i = 0; i < 32; i++) {
+- ret = put_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+- case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+- int i;
+- unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
+- unsigned int __user *tmp = (unsigned int __user *)addr;
+-
+- flush_fp_to_thread(child);
+-
+- for (i = 0; i < 32; i++) {
+- ret = get_user(*reg, tmp);
+- if (ret)
+- break;
+- reg++;
+- tmp++;
+- }
+- break;
+- }
+-
+- case PTRACE_GETEVENTMSG:
+- ret = put_user(child->ptrace_message, (unsigned int __user *) data);
+- break;
+-
+-#ifdef CONFIG_ALTIVEC
+- case PTRACE_GETVRREGS:
+- /* Get the child altivec register state. */
+- flush_altivec_to_thread(child);
+- ret = get_vrregs((unsigned long __user *)data, child);
+- break;
+-
+- case PTRACE_SETVRREGS:
+- /* Set the child altivec register state. */
+- flush_altivec_to_thread(child);
+- ret = set_vrregs(child, (unsigned long __user *)data);
+- break;
+-#endif
+-
+- default:
+- ret = ptrace_request(child, request, addr, data);
+- break;
+- }
+-out_tsk:
+- put_task_struct(child);
+-out:
+- unlock_kernel();
+- return ret;
+-}
+diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/ras.c
++++ /dev/null
+@@ -1,353 +0,0 @@
+-/*
+- * ras.c
+- * Copyright (C) 2001 Dave Engebretsen IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-/* Change Activity:
+- * 2001/09/21 : engebret : Created with minimal EPOW and HW exception support.
+- * End Change Activity
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/threads.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/ioport.h>
+-#include <linux/interrupt.h>
+-#include <linux/timex.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/irq.h>
+-#include <linux/random.h>
+-#include <linux/sysrq.h>
+-#include <linux/bitops.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/irq.h>
+-#include <asm/cache.h>
+-#include <asm/prom.h>
+-#include <asm/ptrace.h>
+-#include <asm/machdep.h>
+-#include <asm/rtas.h>
+-#include <asm/ppcdebug.h>
+-
+-static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
+-static DEFINE_SPINLOCK(ras_log_buf_lock);
+-
+-char mce_data_buf[RTAS_ERROR_LOG_MAX]
+-;
+-/* This is true if we are using the firmware NMI handler (typically LPAR) */
+-extern int fwnmi_active;
+-
+-static int ras_get_sensor_state_token;
+-static int ras_check_exception_token;
+-
+-#define EPOW_SENSOR_TOKEN 9
+-#define EPOW_SENSOR_INDEX 0
+-#define RAS_VECTOR_OFFSET 0x500
+-
+-static irqreturn_t ras_epow_interrupt(int irq, void *dev_id,
+- struct pt_regs * regs);
+-static irqreturn_t ras_error_interrupt(int irq, void *dev_id,
+- struct pt_regs * regs);
+-
+-/* #define DEBUG */
+-
+-static void request_ras_irqs(struct device_node *np, char *propname,
+- irqreturn_t (*handler)(int, void *, struct pt_regs *),
+- const char *name)
+-{
+- unsigned int *ireg, len, i;
+- int virq, n_intr;
+-
+- ireg = (unsigned int *)get_property(np, propname, &len);
+- if (ireg == NULL)
+- return;
+- n_intr = prom_n_intr_cells(np);
+- len /= n_intr * sizeof(*ireg);
+-
+- for (i = 0; i < len; i++) {
+- virq = virt_irq_create_mapping(*ireg);
+- if (virq == NO_IRQ) {
+- printk(KERN_ERR "Unable to allocate interrupt "
+- "number for %s\n", np->full_name);
+- return;
+- }
+- if (request_irq(irq_offset_up(virq), handler, 0, name, NULL)) {
+- printk(KERN_ERR "Unable to request interrupt %d for "
+- "%s\n", irq_offset_up(virq), np->full_name);
+- return;
+- }
+- ireg += n_intr;
+- }
+-}
+-
+-/*
+- * Initialize handlers for the set of interrupts caused by hardware errors
+- * and power system events.
+- */
+-static int __init init_ras_IRQ(void)
+-{
+- struct device_node *np;
+-
+- ras_get_sensor_state_token = rtas_token("get-sensor-state");
+- ras_check_exception_token = rtas_token("check-exception");
+-
+- /* Internal Errors */
+- np = of_find_node_by_path("/event-sources/internal-errors");
+- if (np != NULL) {
+- request_ras_irqs(np, "open-pic-interrupt", ras_error_interrupt,
+- "RAS_ERROR");
+- request_ras_irqs(np, "interrupts", ras_error_interrupt,
+- "RAS_ERROR");
+- of_node_put(np);
+- }
+-
+- /* EPOW Events */
+- np = of_find_node_by_path("/event-sources/epow-events");
+- if (np != NULL) {
+- request_ras_irqs(np, "open-pic-interrupt", ras_epow_interrupt,
+- "RAS_EPOW");
+- request_ras_irqs(np, "interrupts", ras_epow_interrupt,
+- "RAS_EPOW");
+- of_node_put(np);
+- }
+-
+- return 1;
+-}
+-__initcall(init_ras_IRQ);
+-
+-/*
+- * Handle power subsystem events (EPOW).
+- *
+- * Presently we just log the event has occurred. This should be fixed
+- * to examine the type of power failure and take appropriate action where
+- * the time horizon permits something useful to be done.
+- */
+-static irqreturn_t
+-ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+-{
+- int status = 0xdeadbeef;
+- int state = 0;
+- int critical;
+-
+- status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
+- EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);
+-
+- if (state > 3)
+- critical = 1; /* Time Critical */
+- else
+- critical = 0;
+-
+- spin_lock(&ras_log_buf_lock);
+-
+- status = rtas_call(ras_check_exception_token, 6, 1, NULL,
+- RAS_VECTOR_OFFSET,
+- virt_irq_to_real(irq_offset_down(irq)),
+- RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
+- critical, __pa(&ras_log_buf),
+- rtas_get_error_log_max());
+-
+- udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
+- *((unsigned long *)&ras_log_buf), status, state);
+- printk(KERN_WARNING "EPOW <0x%lx 0x%x 0x%x>\n",
+- *((unsigned long *)&ras_log_buf), status, state);
+-
+- /* format and print the extended information */
+- log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
+-
+- spin_unlock(&ras_log_buf_lock);
+- return IRQ_HANDLED;
+-}
+-
+-/*
+- * Handle hardware error interrupts.
+- *
+- * RTAS check-exception is called to collect data on the exception. If
+- * the error is deemed recoverable, we log a warning and return.
+- * For nonrecoverable errors, an error is logged and we stop all processing
+- * as quickly as possible in order to prevent propagation of the failure.
+- */
+-static irqreturn_t
+-ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+-{
+- struct rtas_error_log *rtas_elog;
+- int status = 0xdeadbeef;
+- int fatal;
+-
+- spin_lock(&ras_log_buf_lock);
+-
+- status = rtas_call(ras_check_exception_token, 6, 1, NULL,
+- RAS_VECTOR_OFFSET,
+- virt_irq_to_real(irq_offset_down(irq)),
+- RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
+- __pa(&ras_log_buf),
+- rtas_get_error_log_max());
+-
+- rtas_elog = (struct rtas_error_log *)ras_log_buf;
+-
+- if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC))
+- fatal = 1;
+- else
+- fatal = 0;
+-
+- /* format and print the extended information */
+- log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
+-
+- if (fatal) {
+- udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
+- *((unsigned long *)&ras_log_buf), status);
+- printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
+- *((unsigned long *)&ras_log_buf), status);
+-
+-#ifndef DEBUG
+- /* Don't actually power off when debugging so we can test
+- * without actually failing while injecting errors.
+- * Error data will not be logged to syslog.
+- */
+- ppc_md.power_off();
+-#endif
+- } else {
+- udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
+- *((unsigned long *)&ras_log_buf), status);
+- printk(KERN_WARNING
+- "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
+- *((unsigned long *)&ras_log_buf), status);
+- }
+-
+- spin_unlock(&ras_log_buf_lock);
+- return IRQ_HANDLED;
+-}
+-
+-/* Get the error information for errors coming through the
+- * FWNMI vectors. The pt_regs' r3 will be updated to reflect
+- * the actual r3 if possible, and a ptr to the error log entry
+- * will be returned if found.
+- *
+- * The mce_data_buf does not have any locks or protection around it,
+- * if a second machine check comes in, or a system reset is done
+- * before we have logged the error, then we will get corruption in the
+- * error log. This is preferable over holding off on calling
+- * ibm,nmi-interlock which would result in us checkstopping if a
+- * second machine check did come in.
+- */
+-static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
+-{
+- unsigned long errdata = regs->gpr[3];
+- struct rtas_error_log *errhdr = NULL;
+- unsigned long *savep;
+-
+- if ((errdata >= 0x7000 && errdata < 0x7fff0) ||
+- (errdata >= rtas.base && errdata < rtas.base + rtas.size - 16)) {
+- savep = __va(errdata);
+- regs->gpr[3] = savep[0]; /* restore original r3 */
+- memset(mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
+- memcpy(mce_data_buf, (char *)(savep + 1), RTAS_ERROR_LOG_MAX);
+- errhdr = (struct rtas_error_log *)mce_data_buf;
+- } else {
+- printk("FWNMI: corrupt r3\n");
+- }
+- return errhdr;
+-}
+-
+-/* Call this when done with the data returned by FWNMI_get_errinfo.
+- * It will release the saved data area for other CPUs in the
+- * partition to receive FWNMI errors.
+- */
+-static void fwnmi_release_errinfo(void)
+-{
+- int ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
+- if (ret != 0)
+- printk("FWNMI: nmi-interlock failed: %d\n", ret);
+-}
+-
+-void pSeries_system_reset_exception(struct pt_regs *regs)
+-{
+- if (fwnmi_active) {
+- struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
+- if (errhdr) {
+- /* XXX Should look at FWNMI information */
+- }
+- fwnmi_release_errinfo();
+- }
+-}
+-
+-/*
+- * See if we can recover from a machine check exception.
+- * This is only called on power4 (or above) and only via
+- * the Firmware Non-Maskable Interrupts (fwnmi) handler
+- * which provides the error analysis for us.
+- *
+- * Return 1 if corrected (or delivered a signal).
+- * Return 0 if there is nothing we can do.
+- */
+-static int recover_mce(struct pt_regs *regs, struct rtas_error_log * err)
+-{
+- int nonfatal = 0;
+-
+- if (err->disposition == RTAS_DISP_FULLY_RECOVERED) {
+- /* Platform corrected itself */
+- nonfatal = 1;
+- } else if ((regs->msr & MSR_RI) &&
+- user_mode(regs) &&
+- err->severity == RTAS_SEVERITY_ERROR_SYNC &&
+- err->disposition == RTAS_DISP_NOT_RECOVERED &&
+- err->target == RTAS_TARGET_MEMORY &&
+- err->type == RTAS_TYPE_ECC_UNCORR &&
+- !(current->pid == 0 || current->pid == 1)) {
+- /* Kill off a user process with an ECC error */
+- printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
+- current->pid);
+- /* XXX something better for ECC error? */
+- _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
+- nonfatal = 1;
+- }
+-
+- log_error((char *)err, ERR_TYPE_RTAS_LOG, !nonfatal);
+-
+- return nonfatal;
+-}
+-
+-/*
+- * Handle a machine check.
+- *
+- * Note that on Power 4 and beyond Firmware Non-Maskable Interrupts (fwnmi)
+- * should be present. If so the handler which called us tells us if the
+- * error was recovered (never true if RI=0).
+- *
+- * On hardware prior to Power 4 these exceptions were asynchronous which
+- * means we can't tell exactly where it occurred and so we can't recover.
+- */
+-int pSeries_machine_check_exception(struct pt_regs *regs)
+-{
+- struct rtas_error_log *errp;
+-
+- if (fwnmi_active) {
+- errp = fwnmi_get_errinfo(regs);
+- fwnmi_release_errinfo();
+- if (errp && recover_mce(regs, errp))
+- return 1;
+- }
+-
+- return 0;
+-}
+diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
+--- a/arch/ppc64/kernel/rtas-proc.c
++++ b/arch/ppc64/kernel/rtas-proc.c
+@@ -23,6 +23,7 @@
+ #include <linux/init.h>
+ #include <linux/seq_file.h>
+ #include <linux/bitops.h>
++#include <linux/rtc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/processor.h>
+diff --git a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/rtas.c
++++ /dev/null
+@@ -1,774 +0,0 @@
+-/*
+- *
+- * Procedures for interfacing to the RTAS on CHRP machines.
+- *
+- * Peter Bergner, IBM March 2001.
+- * Copyright (C) 2001 IBM.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <stdarg.h>
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/spinlock.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-
+-#include <asm/prom.h>
+-#include <asm/rtas.h>
+-#include <asm/semaphore.h>
+-#include <asm/machdep.h>
+-#include <asm/page.h>
+-#include <asm/param.h>
+-#include <asm/system.h>
+-#include <asm/abs_addr.h>
+-#include <asm/udbg.h>
+-#include <asm/delay.h>
+-#include <asm/uaccess.h>
+-#include <asm/systemcfg.h>
+-
+-struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
+-
+-struct rtas_t rtas = {
+- .lock = SPIN_LOCK_UNLOCKED
+-};
+-
+-EXPORT_SYMBOL(rtas);
+-
+-char rtas_err_buf[RTAS_ERROR_LOG_MAX];
+-
+-DEFINE_SPINLOCK(rtas_data_buf_lock);
+-char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned;
+-unsigned long rtas_rmo_buf;
+-
+-void
+-call_rtas_display_status(unsigned char c)
+-{
+- struct rtas_args *args = &rtas.args;
+- unsigned long s;
+-
+- if (!rtas.base)
+- return;
+- spin_lock_irqsave(&rtas.lock, s);
+-
+- args->token = 10;
+- args->nargs = 1;
+- args->nret = 1;
+- args->rets = (rtas_arg_t *)&(args->args[1]);
+- args->args[0] = (int)c;
+-
+- enter_rtas(__pa(args));
+-
+- spin_unlock_irqrestore(&rtas.lock, s);
+-}
+-
+-void
+-call_rtas_display_status_delay(unsigned char c)
+-{
+- static int pending_newline = 0; /* did last write end with unprinted newline? */
+- static int width = 16;
+-
+- if (c == '\n') {
+- while (width-- > 0)
+- call_rtas_display_status(' ');
+- width = 16;
+- udelay(500000);
+- pending_newline = 1;
+- } else {
+- if (pending_newline) {
+- call_rtas_display_status('\r');
+- call_rtas_display_status('\n');
+- }
+- pending_newline = 0;
+- if (width--) {
+- call_rtas_display_status(c);
+- udelay(10000);
+- }
+- }
+-}
+-
+-void
+-rtas_progress(char *s, unsigned short hex)
+-{
+- struct device_node *root;
+- int width, *p;
+- char *os;
+- static int display_character, set_indicator;
+- static int display_width, display_lines, *row_width, form_feed;
+- static DEFINE_SPINLOCK(progress_lock);
+- static int current_line;
+- static int pending_newline = 0; /* did last write end with unprinted newline? */
+-
+- if (!rtas.base)
+- return;
+-
+- if (display_width == 0) {
+- display_width = 0x10;
+- if ((root = find_path_device("/rtas"))) {
+- if ((p = (unsigned int *)get_property(root,
+- "ibm,display-line-length", NULL)))
+- display_width = *p;
+- if ((p = (unsigned int *)get_property(root,
+- "ibm,form-feed", NULL)))
+- form_feed = *p;
+- if ((p = (unsigned int *)get_property(root,
+- "ibm,display-number-of-lines", NULL)))
+- display_lines = *p;
+- row_width = (unsigned int *)get_property(root,
+- "ibm,display-truncation-length", NULL);
+- }
+- display_character = rtas_token("display-character");
+- set_indicator = rtas_token("set-indicator");
+- }
+-
+- if (display_character == RTAS_UNKNOWN_SERVICE) {
+- /* use hex display if available */
+- if (set_indicator != RTAS_UNKNOWN_SERVICE)
+- rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
+- return;
+- }
+-
+- spin_lock(&progress_lock);
+-
+- /*
+- * Last write ended with newline, but we didn't print it since
+- * it would just clear the bottom line of output. Print it now
+- * instead.
+- *
+- * If no newline is pending and form feed is supported, clear the
+- * display with a form feed; otherwise, print a CR to start output
+- * at the beginning of the line.
+- */
+- if (pending_newline) {
+- rtas_call(display_character, 1, 1, NULL, '\r');
+- rtas_call(display_character, 1, 1, NULL, '\n');
+- pending_newline = 0;
+- } else {
+- current_line = 0;
+- if (form_feed)
+- rtas_call(display_character, 1, 1, NULL,
+- (char)form_feed);
+- else
+- rtas_call(display_character, 1, 1, NULL, '\r');
+- }
+-
+- if (row_width)
+- width = row_width[current_line];
+- else
+- width = display_width;
+- os = s;
+- while (*os) {
+- if (*os == '\n' || *os == '\r') {
+- /* If newline is the last character, save it
+- * until next call to avoid bumping up the
+- * display output.
+- */
+- if (*os == '\n' && !os[1]) {
+- pending_newline = 1;
+- current_line++;
+- if (current_line > display_lines-1)
+- current_line = display_lines-1;
+- spin_unlock(&progress_lock);
+- return;
+- }
+-
+- /* RTAS wants CR-LF, not just LF */
+-
+- if (*os == '\n') {
+- rtas_call(display_character, 1, 1, NULL, '\r');
+- rtas_call(display_character, 1, 1, NULL, '\n');
+- } else {
+- /* CR might be used to re-draw a line, so we'll
+- * leave it alone and not add LF.
+- */
+- rtas_call(display_character, 1, 1, NULL, *os);
+- }
+-
+- if (row_width)
+- width = row_width[current_line];
+- else
+- width = display_width;
+- } else {
+- width--;
+- rtas_call(display_character, 1, 1, NULL, *os);
+- }
+-
+- os++;
+-
+- /* if we overwrite the screen length */
+- if (width <= 0)
+- while ((*os != 0) && (*os != '\n') && (*os != '\r'))
+- os++;
+- }
+-
+- spin_unlock(&progress_lock);
+-}
+-
+-int
+-rtas_token(const char *service)
+-{
+- int *tokp;
+- if (rtas.dev == NULL) {
+- PPCDBG(PPCDBG_RTAS,"\tNo rtas device in device-tree...\n");
+- return RTAS_UNKNOWN_SERVICE;
+- }
+- tokp = (int *) get_property(rtas.dev, service, NULL);
+- return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
+-}
+-
+-/*
+- * Return the firmware-specified size of the error log buffer
+- * for all rtas calls that require an error buffer argument.
+- * This includes 'check-exception' and 'rtas-last-error'.
+- */
+-int rtas_get_error_log_max(void)
+-{
+- static int rtas_error_log_max;
+- if (rtas_error_log_max)
+- return rtas_error_log_max;
+-
+- rtas_error_log_max = rtas_token ("rtas-error-log-max");
+- if ((rtas_error_log_max == RTAS_UNKNOWN_SERVICE) ||
+- (rtas_error_log_max > RTAS_ERROR_LOG_MAX)) {
+- printk (KERN_WARNING "RTAS: bad log buffer size %d\n", rtas_error_log_max);
+- rtas_error_log_max = RTAS_ERROR_LOG_MAX;
+- }
+- return rtas_error_log_max;
+-}
+-
+-
+-/** Return a copy of the detailed error text associated with the
+- * most recent failed call to rtas. Because the error text
+- * might go stale if there are any other intervening rtas calls,
+- * this routine must be called atomically with whatever produced
+- * the error (i.e. with rtas.lock still held from the previous call).
+- */
+-static int
+-__fetch_rtas_last_error(void)
+-{
+- struct rtas_args err_args, save_args;
+- u32 bufsz;
+-
+- bufsz = rtas_get_error_log_max();
+-
+- err_args.token = rtas_token("rtas-last-error");
+- err_args.nargs = 2;
+- err_args.nret = 1;
+-
+- err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
+- err_args.args[1] = bufsz;
+- err_args.args[2] = 0;
+-
+- save_args = rtas.args;
+- rtas.args = err_args;
+-
+- enter_rtas(__pa(&rtas.args));
+-
+- err_args = rtas.args;
+- rtas.args = save_args;
+-
+- return err_args.args[2];
+-}
+-
+-int rtas_call(int token, int nargs, int nret, int *outputs, ...)
+-{
+- va_list list;
+- int i, logit = 0;
+- unsigned long s;
+- struct rtas_args *rtas_args;
+- char * buff_copy = NULL;
+- int ret;
+-
+- PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n");
+- PPCDBG(PPCDBG_RTAS, "\ttoken = 0x%x\n", token);
+- PPCDBG(PPCDBG_RTAS, "\tnargs = %d\n", nargs);
+- PPCDBG(PPCDBG_RTAS, "\tnret = %d\n", nret);
+- PPCDBG(PPCDBG_RTAS, "\t&outputs = 0x%lx\n", outputs);
+- if (token == RTAS_UNKNOWN_SERVICE)
+- return -1;
+-
+- /* Gotta do something different here, use global lock for now... */
+- spin_lock_irqsave(&rtas.lock, s);
+- rtas_args = &rtas.args;
+-
+- rtas_args->token = token;
+- rtas_args->nargs = nargs;
+- rtas_args->nret = nret;
+- rtas_args->rets = (rtas_arg_t *)&(rtas_args->args[nargs]);
+- va_start(list, outputs);
+- for (i = 0; i < nargs; ++i) {
+- rtas_args->args[i] = va_arg(list, rtas_arg_t);
+- PPCDBG(PPCDBG_RTAS, "\tnarg[%d] = 0x%x\n", i, rtas_args->args[i]);
+- }
+- va_end(list);
+-
+- for (i = 0; i < nret; ++i)
+- rtas_args->rets[i] = 0;
+-
+- PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
+- __pa(rtas_args));
+- enter_rtas(__pa(rtas_args));
+- PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
+-
+- /* A -1 return code indicates that the last command couldn't
+- be completed due to a hardware error. */
+- if (rtas_args->rets[0] == -1)
+- logit = (__fetch_rtas_last_error() == 0);
+-
+- ifppcdebug(PPCDBG_RTAS) {
+- for(i=0; i < nret ;i++)
+- udbg_printf("\tnret[%d] = 0x%lx\n", i, (ulong)rtas_args->rets[i]);
+- }
+-
+- if (nret > 1 && outputs != NULL)
+- for (i = 0; i < nret-1; ++i)
+- outputs[i] = rtas_args->rets[i+1];
+- ret = (nret > 0)? rtas_args->rets[0]: 0;
+-
+- /* Log the error in the unlikely case that there was one. */
+- if (unlikely(logit)) {
+- buff_copy = rtas_err_buf;
+- if (mem_init_done) {
+- buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
+- if (buff_copy)
+- memcpy(buff_copy, rtas_err_buf,
+- RTAS_ERROR_LOG_MAX);
+- }
+- }
+-
+- /* Gotta do something different here, use global lock for now... */
+- spin_unlock_irqrestore(&rtas.lock, s);
+-
+- if (buff_copy) {
+- log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
+- if (mem_init_done)
+- kfree(buff_copy);
+- }
+- return ret;
+-}
+-
+-/* Given an RTAS status code of 990n compute the hinted delay of 10^n
+- * (last digit) milliseconds. For now we bound at n=5 (100 sec).
+- */
+-unsigned int
+-rtas_extended_busy_delay_time(int status)
+-{
+- int order = status - 9900;
+- unsigned long ms;
+-
+- if (order < 0)
+- order = 0; /* RTC depends on this for -2 clock busy */
+- else if (order > 5)
+- order = 5; /* bound */
+-
+- /* Use microseconds for reasonable accuracy */
+- for (ms=1; order > 0; order--)
+- ms *= 10;
+-
+- return ms;
+-}
+-
+-int rtas_error_rc(int rtas_rc)
+-{
+- int rc;
+-
+- switch (rtas_rc) {
+- case -1: /* Hardware Error */
+- rc = -EIO;
+- break;
+- case -3: /* Bad indicator/domain/etc */
+- rc = -EINVAL;
+- break;
+- case -9000: /* Isolation error */
+- rc = -EFAULT;
+- break;
+- case -9001: /* Outstanding TCE/PTE */
+- rc = -EEXIST;
+- break;
+- case -9002: /* No usable slot */
+- rc = -ENODEV;
+- break;
+- default:
+- printk(KERN_ERR "%s: unexpected RTAS error %d\n",
+- __FUNCTION__, rtas_rc);
+- rc = -ERANGE;
+- break;
+- }
+- return rc;
+-}
+-
+-int rtas_get_power_level(int powerdomain, int *level)
+-{
+- int token = rtas_token("get-power-level");
+- int rc;
+-
+- if (token == RTAS_UNKNOWN_SERVICE)
+- return -ENOENT;
+-
+- while ((rc = rtas_call(token, 1, 2, level, powerdomain)) == RTAS_BUSY)
+- udelay(1);
+-
+- if (rc < 0)
+- return rtas_error_rc(rc);
+- return rc;
+-}
+-
+-int rtas_set_power_level(int powerdomain, int level, int *setlevel)
+-{
+- int token = rtas_token("set-power-level");
+- unsigned int wait_time;
+- int rc;
+-
+- if (token == RTAS_UNKNOWN_SERVICE)
+- return -ENOENT;
+-
+- while (1) {
+- rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
+- if (rc == RTAS_BUSY)
+- udelay(1);
+- else if (rtas_is_extended_busy(rc)) {
+- wait_time = rtas_extended_busy_delay_time(rc);
+- udelay(wait_time * 1000);
+- } else
+- break;
+- }
+-
+- if (rc < 0)
+- return rtas_error_rc(rc);
+- return rc;
+-}
+-
+-int rtas_get_sensor(int sensor, int index, int *state)
+-{
+- int token = rtas_token("get-sensor-state");
+- unsigned int wait_time;
+- int rc;
+-
+- if (token == RTAS_UNKNOWN_SERVICE)
+- return -ENOENT;
+-
+- while (1) {
+- rc = rtas_call(token, 2, 2, state, sensor, index);
+- if (rc == RTAS_BUSY)
+- udelay(1);
+- else if (rtas_is_extended_busy(rc)) {
+- wait_time = rtas_extended_busy_delay_time(rc);
+- udelay(wait_time * 1000);
+- } else
+- break;
+- }
+-
+- if (rc < 0)
+- return rtas_error_rc(rc);
+- return rc;
+-}
+-
+-int rtas_set_indicator(int indicator, int index, int new_value)
+-{
+- int token = rtas_token("set-indicator");
+- unsigned int wait_time;
+- int rc;
+-
+- if (token == RTAS_UNKNOWN_SERVICE)
+- return -ENOENT;
+-
+- while (1) {
+- rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
+- if (rc == RTAS_BUSY)
+- udelay(1);
+- else if (rtas_is_extended_busy(rc)) {
+- wait_time = rtas_extended_busy_delay_time(rc);
+- udelay(wait_time * 1000);
+- }
+- else
+- break;
+- }
+-
+- if (rc < 0)
+- return rtas_error_rc(rc);
+- return rc;
+-}
+-
+-#define FLASH_BLOCK_LIST_VERSION (1UL)
+-static void
+-rtas_flash_firmware(void)
+-{
+- unsigned long image_size;
+- struct flash_block_list *f, *next, *flist;
+- unsigned long rtas_block_list;
+- int i, status, update_token;
+-
+- update_token = rtas_token("ibm,update-flash-64-and-reboot");
+- if (update_token == RTAS_UNKNOWN_SERVICE) {
+- printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
+- printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
+- return;
+- }
+-
+- /* NOTE: the "first" block list is a global var with no data
+- * blocks in the kernel data segment. We do this because
+- * we want to ensure this block_list addr is under 4GB.
+- */
+- rtas_firmware_flash_list.num_blocks = 0;
+- flist = (struct flash_block_list *)&rtas_firmware_flash_list;
+- rtas_block_list = virt_to_abs(flist);
+- if (rtas_block_list >= 4UL*1024*1024*1024) {
+- printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
+- return;
+- }
+-
+- printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
+- /* Update the block_list in place. */
+- image_size = 0;
+- for (f = flist; f; f = next) {
+- /* Translate data addrs to absolute */
+- for (i = 0; i < f->num_blocks; i++) {
+- f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
+- image_size += f->blocks[i].length;
+- }
+- next = f->next;
+- /* Don't translate NULL pointer for last entry */
+- if (f->next)
+- f->next = (struct flash_block_list *)virt_to_abs(f->next);
+- else
+- f->next = NULL;
+- /* make num_blocks into the version/length field */
+- f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
+- }
+-
+- printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
+- printk(KERN_ALERT "FLASH: performing flash and reboot\n");
+- rtas_progress("Flashing \n", 0x0);
+- rtas_progress("Please Wait... ", 0x0);
+- printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
+- status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
+- switch (status) { /* should only get "bad" status */
+- case 0:
+- printk(KERN_ALERT "FLASH: success\n");
+- break;
+- case -1:
+- printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n");
+- break;
+- case -3:
+- printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n");
+- break;
+- case -4:
+- printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n");
+- break;
+- default:
+- printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
+- break;
+- }
+-}
+-
+-void rtas_flash_bypass_warning(void)
+-{
+- printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");
+- printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");
+-}
+-
+-
+-void
+-rtas_restart(char *cmd)
+-{
+- if (rtas_firmware_flash_list.next)
+- rtas_flash_firmware();
+-
+- printk("RTAS system-reboot returned %d\n",
+- rtas_call(rtas_token("system-reboot"), 0, 1, NULL));
+- for (;;);
+-}
+-
+-void
+-rtas_power_off(void)
+-{
+- if (rtas_firmware_flash_list.next)
+- rtas_flash_bypass_warning();
+- /* allow power on only with power button press */
+- printk("RTAS power-off returned %d\n",
+- rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
+- for (;;);
+-}
+-
+-void
+-rtas_halt(void)
+-{
+- if (rtas_firmware_flash_list.next)
+- rtas_flash_bypass_warning();
+- rtas_power_off();
+-}
+-
+-/* Must be in the RMO region, so we place it here */
+-static char rtas_os_term_buf[2048];
+-
+-void rtas_os_term(char *str)
+-{
+- int status;
+-
+- if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term"))
+- return;
+-
+- snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);
+-
+- do {
+- status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
+- __pa(rtas_os_term_buf));
+-
+- if (status == RTAS_BUSY)
+- udelay(1);
+- else if (status != 0)
+- printk(KERN_EMERG "ibm,os-term call failed %d\n",
+- status);
+- } while (status == RTAS_BUSY);
+-}
+-
+-
+-asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
+-{
+- struct rtas_args args;
+- unsigned long flags;
+- char * buff_copy;
+- int nargs;
+- int err_rc = 0;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
+- return -EFAULT;
+-
+- nargs = args.nargs;
+- if (nargs > ARRAY_SIZE(args.args)
+- || args.nret > ARRAY_SIZE(args.args)
+- || nargs + args.nret > ARRAY_SIZE(args.args))
+- return -EINVAL;
+-
+- /* Copy in args. */
+- if (copy_from_user(args.args, uargs->args,
+- nargs * sizeof(rtas_arg_t)) != 0)
+- return -EFAULT;
+-
+- buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_KERNEL);
+-
+- spin_lock_irqsave(&rtas.lock, flags);
+-
+- rtas.args = args;
+- enter_rtas(__pa(&rtas.args));
+- args = rtas.args;
+-
+- args.rets = &args.args[nargs];
+-
+- /* A -1 return code indicates that the last command couldn't
+- be completed due to a hardware error. */
+- if (args.rets[0] == -1) {
+- err_rc = __fetch_rtas_last_error();
+- if ((err_rc == 0) && buff_copy) {
+- memcpy(buff_copy, rtas_err_buf, RTAS_ERROR_LOG_MAX);
+- }
+- }
+-
+- spin_unlock_irqrestore(&rtas.lock, flags);
+-
+- if (buff_copy) {
+- if ((args.rets[0] == -1) && (err_rc == 0)) {
+- log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
+- }
+- kfree(buff_copy);
+- }
+-
+- /* Copy out args. */
+- if (copy_to_user(uargs->args + nargs,
+- args.args + nargs,
+- args.nret * sizeof(rtas_arg_t)) != 0)
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-/* This version can't take the spinlock, because it never returns */
+-
+-struct rtas_args rtas_stop_self_args = {
+- /* The token is initialized for real in setup_system() */
+- .token = RTAS_UNKNOWN_SERVICE,
+- .nargs = 0,
+- .nret = 1,
+- .rets = &rtas_stop_self_args.args[0],
+-};
+-
+-void rtas_stop_self(void)
+-{
+- struct rtas_args *rtas_args = &rtas_stop_self_args;
+-
+- local_irq_disable();
+-
+- BUG_ON(rtas_args->token == RTAS_UNKNOWN_SERVICE);
+-
+- printk("cpu %u (hwid %u) Ready to die...\n",
+- smp_processor_id(), hard_smp_processor_id());
+- enter_rtas(__pa(rtas_args));
+-
+- panic("Alas, I survived.\n");
+-}
+-
+-/*
+- * Call early during boot, before mem init or bootmem, to retreive the RTAS
+- * informations from the device-tree and allocate the RMO buffer for userland
+- * accesses.
+- */
+-void __init rtas_initialize(void)
+-{
+- /* Get RTAS dev node and fill up our "rtas" structure with infos
+- * about it.
+- */
+- rtas.dev = of_find_node_by_name(NULL, "rtas");
+- if (rtas.dev) {
+- u32 *basep, *entryp;
+- u32 *sizep;
+-
+- basep = (u32 *)get_property(rtas.dev, "linux,rtas-base", NULL);
+- sizep = (u32 *)get_property(rtas.dev, "rtas-size", NULL);
+- if (basep != NULL && sizep != NULL) {
+- rtas.base = *basep;
+- rtas.size = *sizep;
+- entryp = (u32 *)get_property(rtas.dev, "linux,rtas-entry", NULL);
+- if (entryp == NULL) /* Ugh */
+- rtas.entry = rtas.base;
+- else
+- rtas.entry = *entryp;
+- } else
+- rtas.dev = NULL;
+- }
+- /* If RTAS was found, allocate the RMO buffer for it and look for
+- * the stop-self token if any
+- */
+- if (rtas.dev) {
+- unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
+- if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
+- rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
+-
+- rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,
+- rtas_region);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+- rtas_stop_self_args.token = rtas_token("stop-self");
+-#endif /* CONFIG_HOTPLUG_CPU */
+- }
+-
+-}
+-
+-
+-EXPORT_SYMBOL(rtas_firmware_flash_list);
+-EXPORT_SYMBOL(rtas_token);
+-EXPORT_SYMBOL(rtas_call);
+-EXPORT_SYMBOL(rtas_data_buf);
+-EXPORT_SYMBOL(rtas_data_buf_lock);
+-EXPORT_SYMBOL(rtas_extended_busy_delay_time);
+-EXPORT_SYMBOL(rtas_get_sensor);
+-EXPORT_SYMBOL(rtas_get_power_level);
+-EXPORT_SYMBOL(rtas_set_power_level);
+-EXPORT_SYMBOL(rtas_set_indicator);
+-EXPORT_SYMBOL(rtas_get_error_log_max);
+diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
+--- a/arch/ppc64/kernel/rtas_pci.c
++++ b/arch/ppc64/kernel/rtas_pci.c
+@@ -38,9 +38,8 @@
+ #include <asm/pci-bridge.h>
+ #include <asm/iommu.h>
+ #include <asm/rtas.h>
+-
+-#include "mpic.h"
+-#include "pci.h"
++#include <asm/mpic.h>
++#include <asm/ppc-pci.h>
+
+ /* RTAS tokens */
+ static int read_pci_config;
+@@ -401,7 +400,7 @@ unsigned long __init find_and_init_phbs(
+ if (!phb)
+ continue;
+
+- pci_process_bridge_OF_ranges(phb, node);
++ pci_process_bridge_OF_ranges(phb, node, 0);
+ pci_setup_phb_io(phb, index == 0);
+ #ifdef CONFIG_PPC_PSERIES
+ if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
+@@ -451,7 +450,7 @@ struct pci_controller * __devinit init_p
+ if (!phb)
+ return NULL;
+
+- pci_process_bridge_OF_ranges(phb, dn);
++ pci_process_bridge_OF_ranges(phb, dn, primary);
+
+ pci_setup_phb_io_dynamic(phb, primary);
+ of_node_put(root);
+diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
+--- a/arch/ppc64/kernel/rtc.c
++++ b/arch/ppc64/kernel/rtc.c
+@@ -43,11 +43,8 @@
+ #include <asm/time.h>
+ #include <asm/rtas.h>
+
+-#include <asm/iSeries/mf.h>
+ #include <asm/machdep.h>
+
+-extern int piranha_simulator;
+-
+ /*
+ * We sponge a minor off of the misc major. No need slurping
+ * up another valuable major dev number for this. If you add
+@@ -265,44 +262,10 @@ static int rtc_read_proc(char *page, cha
+ return len;
+ }
+
+-#ifdef CONFIG_PPC_ISERIES
+-/*
+- * Get the RTC from the virtual service processor
+- * This requires flowing LpEvents to the primary partition
+- */
+-void iSeries_get_rtc_time(struct rtc_time *rtc_tm)
+-{
+- if (piranha_simulator)
+- return;
+-
+- mf_get_rtc(rtc_tm);
+- rtc_tm->tm_mon--;
+-}
+-
+-/*
+- * Set the RTC in the virtual service processor
+- * This requires flowing LpEvents to the primary partition
+- */
+-int iSeries_set_rtc_time(struct rtc_time *tm)
+-{
+- mf_set_rtc(tm);
+- return 0;
+-}
+-
+-void iSeries_get_boot_time(struct rtc_time *tm)
+-{
+- if ( piranha_simulator )
+- return;
+-
+- mf_get_boot_rtc(tm);
+- tm->tm_mon -= 1;
+-}
+-#endif
+-
+ #ifdef CONFIG_PPC_RTAS
+ #define MAX_RTC_WAIT 5000 /* 5 sec */
+ #define RTAS_CLOCK_BUSY (-2)
+-void rtas_get_boot_time(struct rtc_time *rtc_tm)
++unsigned long rtas_get_boot_time(void)
+ {
+ int ret[8];
+ int error, wait_time;
+@@ -322,15 +285,10 @@ void rtas_get_boot_time(struct rtc_time
+ if (error != 0 && printk_ratelimit()) {
+ printk(KERN_WARNING "error: reading the clock failed (%d)\n",
+ error);
+- return;
++ return 0;
+ }
+
+- rtc_tm->tm_sec = ret[5];
+- rtc_tm->tm_min = ret[4];
+- rtc_tm->tm_hour = ret[3];
+- rtc_tm->tm_mday = ret[2];
+- rtc_tm->tm_mon = ret[1] - 1;
+- rtc_tm->tm_year = ret[0] - 1900;
++ return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
+ }
+
+ /* NOTE: get_rtc_time will get an error if executed in interrupt context
+diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/setup.c
++++ /dev/null
+@@ -1,1316 +0,0 @@
+-/*
+- *
+- * Common boot and setup code.
+- *
+- * Copyright (C) 2001 PPC64 Team, IBM Corp
+- *
+- * 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/module.h>
+-#include <linux/string.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/reboot.h>
+-#include <linux/delay.h>
+-#include <linux/initrd.h>
+-#include <linux/ide.h>
+-#include <linux/seq_file.h>
+-#include <linux/ioport.h>
+-#include <linux/console.h>
+-#include <linux/utsname.h>
+-#include <linux/tty.h>
+-#include <linux/root_dev.h>
+-#include <linux/notifier.h>
+-#include <linux/cpu.h>
+-#include <linux/unistd.h>
+-#include <linux/serial.h>
+-#include <linux/serial_8250.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/processor.h>
+-#include <asm/pgtable.h>
+-#include <asm/bootinfo.h>
+-#include <asm/smp.h>
+-#include <asm/elf.h>
+-#include <asm/machdep.h>
+-#include <asm/paca.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/time.h>
+-#include <asm/cputable.h>
+-#include <asm/sections.h>
+-#include <asm/btext.h>
+-#include <asm/nvram.h>
+-#include <asm/setup.h>
+-#include <asm/system.h>
+-#include <asm/rtas.h>
+-#include <asm/iommu.h>
+-#include <asm/serial.h>
+-#include <asm/cache.h>
+-#include <asm/page.h>
+-#include <asm/mmu.h>
+-#include <asm/lmb.h>
+-#include <asm/iSeries/ItLpNaca.h>
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/*
+- * Here are some early debugging facilities. You can enable one
+- * but your kernel will not boot on anything else if you do so
+- */
+-
+-/* This one is for use on LPAR machines that support an HVC console
+- * on vterm 0
+- */
+-extern void udbg_init_debug_lpar(void);
+-/* This one is for use on Apple G5 machines
+- */
+-extern void udbg_init_pmac_realmode(void);
+-/* That's RTAS panel debug */
+-extern void call_rtas_display_status_delay(unsigned char c);
+-/* Here's maple real mode debug */
+-extern void udbg_init_maple_realmode(void);
+-
+-#define EARLY_DEBUG_INIT() do {} while(0)
+-
+-#if 0
+-#define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
+-#define EARLY_DEBUG_INIT() udbg_init_maple_realmode()
+-#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
+-#define EARLY_DEBUG_INIT() \
+- do { udbg_putc = call_rtas_display_status_delay; } while(0)
+-#endif
+-
+-/* extern void *stab; */
+-extern unsigned long klimit;
+-
+-extern void mm_init_ppc64(void);
+-extern void stab_initialize(unsigned long stab);
+-extern void htab_initialize(void);
+-extern void early_init_devtree(void *flat_dt);
+-extern void unflatten_device_tree(void);
+-
+-extern void smp_release_cpus(void);
+-
+-int have_of = 1;
+-int boot_cpuid = 0;
+-int boot_cpuid_phys = 0;
+-dev_t boot_dev;
+-u64 ppc64_pft_size;
+-
+-struct ppc64_caches ppc64_caches;
+-EXPORT_SYMBOL_GPL(ppc64_caches);
+-
+-/*
+- * These are used in binfmt_elf.c to put aux entries on the stack
+- * for each elf executable being started.
+- */
+-int dcache_bsize;
+-int icache_bsize;
+-int ucache_bsize;
+-
+-/* The main machine-dep calls structure
+- */
+-struct machdep_calls ppc_md;
+-EXPORT_SYMBOL(ppc_md);
+-
+-#ifdef CONFIG_MAGIC_SYSRQ
+-unsigned long SYSRQ_KEY;
+-#endif /* CONFIG_MAGIC_SYSRQ */
+-
+-
+-static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
+-static struct notifier_block ppc64_panic_block = {
+- .notifier_call = ppc64_panic_event,
+- .priority = INT_MIN /* may not return; must be done last */
+-};
+-
+-/*
+- * Perhaps we can put the pmac screen_info[] here
+- * on pmac as well so we don't need the ifdef's.
+- * Until we get multiple-console support in here
+- * that is. -- Cort
+- * Maybe tie it to serial consoles, since this is really what
+- * these processors use on existing boards. -- Dan
+- */
+-struct screen_info screen_info = {
+- .orig_x = 0,
+- .orig_y = 25,
+- .orig_video_cols = 80,
+- .orig_video_lines = 25,
+- .orig_video_isVGA = 1,
+- .orig_video_points = 16
+-};
+-
+-#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP)
+-
+-static int smt_enabled_cmdline;
+-
+-/* Look for ibm,smt-enabled OF option */
+-static void check_smt_enabled(void)
+-{
+- struct device_node *dn;
+- char *smt_option;
+-
+- /* Allow the command line to overrule the OF option */
+- if (smt_enabled_cmdline)
+- return;
+-
+- dn = of_find_node_by_path("/options");
+-
+- if (dn) {
+- smt_option = (char *)get_property(dn, "ibm,smt-enabled", NULL);
+-
+- if (smt_option) {
+- if (!strcmp(smt_option, "on"))
+- smt_enabled_at_boot = 1;
+- else if (!strcmp(smt_option, "off"))
+- smt_enabled_at_boot = 0;
+- }
+- }
+-}
+-
+-/* Look for smt-enabled= cmdline option */
+-static int __init early_smt_enabled(char *p)
+-{
+- smt_enabled_cmdline = 1;
+-
+- if (!p)
+- return 0;
+-
+- if (!strcmp(p, "on") || !strcmp(p, "1"))
+- smt_enabled_at_boot = 1;
+- else if (!strcmp(p, "off") || !strcmp(p, "0"))
+- smt_enabled_at_boot = 0;
+-
+- return 0;
+-}
+-early_param("smt-enabled", early_smt_enabled);
+-
+-/**
+- * setup_cpu_maps - initialize the following cpu maps:
+- * cpu_possible_map
+- * cpu_present_map
+- * cpu_sibling_map
+- *
+- * Having the possible map set up early allows us to restrict allocations
+- * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
+- *
+- * We do not initialize the online map here; cpus set their own bits in
+- * cpu_online_map as they come up.
+- *
+- * This function is valid only for Open Firmware systems. finish_device_tree
+- * must be called before using this.
+- *
+- * While we're here, we may as well set the "physical" cpu ids in the paca.
+- */
+-static void __init setup_cpu_maps(void)
+-{
+- struct device_node *dn = NULL;
+- int cpu = 0;
+- int swap_cpuid = 0;
+-
+- check_smt_enabled();
+-
+- while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
+- u32 *intserv;
+- int j, len = sizeof(u32), nthreads;
+-
+- intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s",
+- &len);
+- if (!intserv)
+- intserv = (u32 *)get_property(dn, "reg", NULL);
+-
+- nthreads = len / sizeof(u32);
+-
+- for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
+- cpu_set(cpu, cpu_present_map);
+- set_hard_smp_processor_id(cpu, intserv[j]);
+-
+- if (intserv[j] == boot_cpuid_phys)
+- swap_cpuid = cpu;
+- cpu_set(cpu, cpu_possible_map);
+- cpu++;
+- }
+- }
+-
+- /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
+- * boot cpu is logical 0.
+- */
+- if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
+- u32 tmp;
+- tmp = get_hard_smp_processor_id(0);
+- set_hard_smp_processor_id(0, boot_cpuid_phys);
+- set_hard_smp_processor_id(swap_cpuid, tmp);
+- }
+-
+- /*
+- * On pSeries LPAR, we need to know how many cpus
+- * could possibly be added to this partition.
+- */
+- if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
+- (dn = of_find_node_by_path("/rtas"))) {
+- int num_addr_cell, num_size_cell, maxcpus;
+- unsigned int *ireg;
+-
+- num_addr_cell = prom_n_addr_cells(dn);
+- num_size_cell = prom_n_size_cells(dn);
+-
+- ireg = (unsigned int *)
+- get_property(dn, "ibm,lrdr-capacity", NULL);
+-
+- if (!ireg)
+- goto out;
+-
+- maxcpus = ireg[num_addr_cell + num_size_cell];
+-
+- /* Double maxcpus for processors which have SMT capability */
+- if (cpu_has_feature(CPU_FTR_SMT))
+- maxcpus *= 2;
+-
+- if (maxcpus > NR_CPUS) {
+- printk(KERN_WARNING
+- "Partition configured for %d cpus, "
+- "operating system maximum is %d.\n",
+- maxcpus, NR_CPUS);
+- maxcpus = NR_CPUS;
+- } else
+- printk(KERN_INFO "Partition configured for %d cpus.\n",
+- maxcpus);
+-
+- for (cpu = 0; cpu < maxcpus; cpu++)
+- cpu_set(cpu, cpu_possible_map);
+- out:
+- of_node_put(dn);
+- }
+-
+- /*
+- * Do the sibling map; assume only two threads per processor.
+- */
+- for_each_cpu(cpu) {
+- cpu_set(cpu, cpu_sibling_map[cpu]);
+- if (cpu_has_feature(CPU_FTR_SMT))
+- cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
+- }
+-
+- systemcfg->processorCount = num_present_cpus();
+-}
+-#endif /* defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) */
+-
+-
+-#ifdef CONFIG_PPC_MULTIPLATFORM
+-
+-extern struct machdep_calls pSeries_md;
+-extern struct machdep_calls pmac_md;
+-extern struct machdep_calls maple_md;
+-extern struct machdep_calls bpa_md;
+-
+-/* Ultimately, stuff them in an elf section like initcalls... */
+-static struct machdep_calls __initdata *machines[] = {
+-#ifdef CONFIG_PPC_PSERIES
+- &pSeries_md,
+-#endif /* CONFIG_PPC_PSERIES */
+-#ifdef CONFIG_PPC_PMAC
+- &pmac_md,
+-#endif /* CONFIG_PPC_PMAC */
+-#ifdef CONFIG_PPC_MAPLE
+- &maple_md,
+-#endif /* CONFIG_PPC_MAPLE */
+-#ifdef CONFIG_PPC_BPA
+- &bpa_md,
+-#endif
+- NULL
+-};
+-
+-/*
+- * Early initialization entry point. This is called by head.S
+- * with MMU translation disabled. We rely on the "feature" of
+- * the CPU that ignores the top 2 bits of the address in real
+- * mode so we can access kernel globals normally provided we
+- * only toy with things in the RMO region. From here, we do
+- * some early parsing of the device-tree to setup out LMB
+- * data structures, and allocate & initialize the hash table
+- * and segment tables so we can start running with translation
+- * enabled.
+- *
+- * It is this function which will call the probe() callback of
+- * the various platform types and copy the matching one to the
+- * global ppc_md structure. Your platform can eventually do
+- * some very early initializations from the probe() routine, but
+- * this is not recommended, be very careful as, for example, the
+- * device-tree is not accessible via normal means at this point.
+- */
+-
+-void __init early_setup(unsigned long dt_ptr)
+-{
+- struct paca_struct *lpaca = get_paca();
+- static struct machdep_calls **mach;
+-
+- /*
+- * Enable early debugging if any specified (see top of
+- * this file)
+- */
+- EARLY_DEBUG_INIT();
+-
+- DBG(" -> early_setup()\n");
+-
+- /*
+- * Fill the default DBG level (do we want to keep
+- * that old mecanism around forever ?)
+- */
+- ppcdbg_initialize();
+-
+- /*
+- * Do early initializations using the flattened device
+- * tree, like retreiving the physical memory map or
+- * calculating/retreiving the hash table size
+- */
+- early_init_devtree(__va(dt_ptr));
+-
+- /*
+- * Iterate all ppc_md structures until we find the proper
+- * one for the current machine type
+- */
+- DBG("Probing machine type for platform %x...\n",
+- systemcfg->platform);
+-
+- for (mach = machines; *mach; mach++) {
+- if ((*mach)->probe(systemcfg->platform))
+- break;
+- }
+- /* What can we do if we didn't find ? */
+- if (*mach == NULL) {
+- DBG("No suitable machine found !\n");
+- for (;;);
+- }
+- ppc_md = **mach;
+-
+- DBG("Found, Initializing memory management...\n");
+-
+- /*
+- * Initialize stab / SLB management
+- */
+- stab_initialize(lpaca->stab_real);
+-
+- /*
+- * Initialize the MMU Hash table and create the linear mapping
+- * of memory
+- */
+- htab_initialize();
+-
+- DBG(" <- early_setup()\n");
+-}
+-
+-
+-/*
+- * Initialize some remaining members of the ppc64_caches and systemcfg structures
+- * (at least until we get rid of them completely). This is mostly some
+- * cache informations about the CPU that will be used by cache flush
+- * routines and/or provided to userland
+- */
+-static void __init initialize_cache_info(void)
+-{
+- struct device_node *np;
+- unsigned long num_cpus = 0;
+-
+- DBG(" -> initialize_cache_info()\n");
+-
+- for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
+- num_cpus += 1;
+-
+- /* We're assuming *all* of the CPUs have the same
+- * d-cache and i-cache sizes... -Peter
+- */
+-
+- if ( num_cpus == 1 ) {
+- u32 *sizep, *lsizep;
+- u32 size, lsize;
+- const char *dc, *ic;
+-
+- /* Then read cache informations */
+- if (systemcfg->platform == PLATFORM_POWERMAC) {
+- dc = "d-cache-block-size";
+- ic = "i-cache-block-size";
+- } else {
+- dc = "d-cache-line-size";
+- ic = "i-cache-line-size";
+- }
+-
+- size = 0;
+- lsize = cur_cpu_spec->dcache_bsize;
+- sizep = (u32 *)get_property(np, "d-cache-size", NULL);
+- if (sizep != NULL)
+- size = *sizep;
+- lsizep = (u32 *) get_property(np, dc, NULL);
+- if (lsizep != NULL)
+- lsize = *lsizep;
+- if (sizep == 0 || lsizep == 0)
+- DBG("Argh, can't find dcache properties ! "
+- "sizep: %p, lsizep: %p\n", sizep, lsizep);
+-
+- systemcfg->dcache_size = ppc64_caches.dsize = size;
+- systemcfg->dcache_line_size =
+- ppc64_caches.dline_size = lsize;
+- ppc64_caches.log_dline_size = __ilog2(lsize);
+- ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
+-
+- size = 0;
+- lsize = cur_cpu_spec->icache_bsize;
+- sizep = (u32 *)get_property(np, "i-cache-size", NULL);
+- if (sizep != NULL)
+- size = *sizep;
+- lsizep = (u32 *)get_property(np, ic, NULL);
+- if (lsizep != NULL)
+- lsize = *lsizep;
+- if (sizep == 0 || lsizep == 0)
+- DBG("Argh, can't find icache properties ! "
+- "sizep: %p, lsizep: %p\n", sizep, lsizep);
+-
+- systemcfg->icache_size = ppc64_caches.isize = size;
+- systemcfg->icache_line_size =
+- ppc64_caches.iline_size = lsize;
+- ppc64_caches.log_iline_size = __ilog2(lsize);
+- ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
+- }
+- }
+-
+- /* Add an eye catcher and the systemcfg layout version number */
+- strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
+- systemcfg->version.major = SYSTEMCFG_MAJOR;
+- systemcfg->version.minor = SYSTEMCFG_MINOR;
+- systemcfg->processor = mfspr(SPRN_PVR);
+-
+- DBG(" <- initialize_cache_info()\n");
+-}
+-
+-static void __init check_for_initrd(void)
+-{
+-#ifdef CONFIG_BLK_DEV_INITRD
+- u64 *prop;
+-
+- DBG(" -> check_for_initrd()\n");
+-
+- if (of_chosen) {
+- prop = (u64 *)get_property(of_chosen,
+- "linux,initrd-start", NULL);
+- if (prop != NULL) {
+- initrd_start = (unsigned long)__va(*prop);
+- prop = (u64 *)get_property(of_chosen,
+- "linux,initrd-end", NULL);
+- if (prop != NULL) {
+- initrd_end = (unsigned long)__va(*prop);
+- initrd_below_start_ok = 1;
+- } else
+- initrd_start = 0;
+- }
+- }
+-
+- /* If we were passed an initrd, set the ROOT_DEV properly if the values
+- * look sensible. If not, clear initrd reference.
+- */
+- if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
+- initrd_end > initrd_start)
+- ROOT_DEV = Root_RAM0;
+- else
+- initrd_start = initrd_end = 0;
+-
+- if (initrd_start)
+- printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end);
+-
+- DBG(" <- check_for_initrd()\n");
+-#endif /* CONFIG_BLK_DEV_INITRD */
+-}
+-
+-#endif /* CONFIG_PPC_MULTIPLATFORM */
+-
+-/*
+- * Do some initial setup of the system. The parameters are those which
+- * were passed in from the bootloader.
+- */
+-void __init setup_system(void)
+-{
+- DBG(" -> setup_system()\n");
+-
+-#ifdef CONFIG_PPC_ISERIES
+- /* pSeries systems are identified in prom.c via OF. */
+- if (itLpNaca.xLparInstalled == 1)
+- systemcfg->platform = PLATFORM_ISERIES_LPAR;
+-
+- ppc_md.init_early();
+-#else /* CONFIG_PPC_ISERIES */
+-
+- /*
+- * Unflatten the device-tree passed by prom_init or kexec
+- */
+- unflatten_device_tree();
+-
+- /*
+- * Fill the ppc64_caches & systemcfg structures with informations
+- * retreived from the device-tree. Need to be called before
+- * finish_device_tree() since the later requires some of the
+- * informations filled up here to properly parse the interrupt
+- * tree.
+- * It also sets up the cache line sizes which allows to call
+- * routines like flush_icache_range (used by the hash init
+- * later on).
+- */
+- initialize_cache_info();
+-
+-#ifdef CONFIG_PPC_RTAS
+- /*
+- * Initialize RTAS if available
+- */
+- rtas_initialize();
+-#endif /* CONFIG_PPC_RTAS */
+-
+- /*
+- * Check if we have an initrd provided via the device-tree
+- */
+- check_for_initrd();
+-
+- /*
+- * Do some platform specific early initializations, that includes
+- * setting up the hash table pointers. It also sets up some interrupt-mapping
+- * related options that will be used by finish_device_tree()
+- */
+- ppc_md.init_early();
+-
+- /*
+- * "Finish" the device-tree, that is do the actual parsing of
+- * some of the properties like the interrupt map
+- */
+- finish_device_tree();
+-
+- /*
+- * Initialize xmon
+- */
+-#ifdef CONFIG_XMON_DEFAULT
+- xmon_init(1);
+-#endif
+- /*
+- * Register early console
+- */
+- register_early_udbg_console();
+-
+- /* Save unparsed command line copy for /proc/cmdline */
+- strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+-
+- parse_early_param();
+-#endif /* !CONFIG_PPC_ISERIES */
+-
+-#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
+- /*
+- * iSeries has already initialized the cpu maps at this point.
+- */
+- setup_cpu_maps();
+-
+- /* Release secondary cpus out of their spinloops at 0x60 now that
+- * we can map physical -> logical CPU ids
+- */
+- smp_release_cpus();
+-#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */
+-
+- printk("Starting Linux PPC64 %s\n", system_utsname.version);
+-
+- printk("-----------------------------------------------------\n");
+- printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
+- printk("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch);
+- printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller);
+- printk("systemcfg = 0x%p\n", systemcfg);
+- printk("systemcfg->platform = 0x%x\n", systemcfg->platform);
+- printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount);
+- printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
+- printk("ppc64_caches.dcache_line_size = 0x%x\n",
+- ppc64_caches.dline_size);
+- printk("ppc64_caches.icache_line_size = 0x%x\n",
+- ppc64_caches.iline_size);
+- printk("htab_address = 0x%p\n", htab_address);
+- printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
+- printk("-----------------------------------------------------\n");
+-
+- mm_init_ppc64();
+-
+- DBG(" <- setup_system()\n");
+-}
+-
+-/* also used by kexec */
+-void machine_shutdown(void)
+-{
+- if (ppc_md.nvram_sync)
+- ppc_md.nvram_sync();
+-}
+-
+-void machine_restart(char *cmd)
+-{
+- machine_shutdown();
+- ppc_md.restart(cmd);
+-#ifdef CONFIG_SMP
+- smp_send_stop();
+-#endif
+- printk(KERN_EMERG "System Halted, OK to turn off power\n");
+- local_irq_disable();
+- while (1) ;
+-}
+-
+-void machine_power_off(void)
+-{
+- machine_shutdown();
+- ppc_md.power_off();
+-#ifdef CONFIG_SMP
+- smp_send_stop();
+-#endif
+- printk(KERN_EMERG "System Halted, OK to turn off power\n");
+- local_irq_disable();
+- while (1) ;
+-}
+-/* Used by the G5 thermal driver */
+-EXPORT_SYMBOL_GPL(machine_power_off);
+-
+-void machine_halt(void)
+-{
+- machine_shutdown();
+- ppc_md.halt();
+-#ifdef CONFIG_SMP
+- smp_send_stop();
+-#endif
+- printk(KERN_EMERG "System Halted, OK to turn off power\n");
+- local_irq_disable();
+- while (1) ;
+-}
+-
+-static int ppc64_panic_event(struct notifier_block *this,
+- unsigned long event, void *ptr)
+-{
+- ppc_md.panic((char *)ptr); /* May not return */
+- return NOTIFY_DONE;
+-}
+-
+-
+-#ifdef CONFIG_SMP
+-DEFINE_PER_CPU(unsigned int, pvr);
+-#endif
+-
+-static int show_cpuinfo(struct seq_file *m, void *v)
+-{
+- unsigned long cpu_id = (unsigned long)v - 1;
+- unsigned int pvr;
+- unsigned short maj;
+- unsigned short min;
+-
+- if (cpu_id == NR_CPUS) {
+- seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
+-
+- if (ppc_md.get_cpuinfo != NULL)
+- ppc_md.get_cpuinfo(m);
+-
+- return 0;
+- }
+-
+- /* We only show online cpus: disable preempt (overzealous, I
+- * knew) to prevent cpu going down. */
+- preempt_disable();
+- if (!cpu_online(cpu_id)) {
+- preempt_enable();
+- return 0;
+- }
+-
+-#ifdef CONFIG_SMP
+- pvr = per_cpu(pvr, cpu_id);
+-#else
+- pvr = mfspr(SPRN_PVR);
+-#endif
+- maj = (pvr >> 8) & 0xFF;
+- min = pvr & 0xFF;
+-
+- seq_printf(m, "processor\t: %lu\n", cpu_id);
+- seq_printf(m, "cpu\t\t: ");
+-
+- if (cur_cpu_spec->pvr_mask)
+- seq_printf(m, "%s", cur_cpu_spec->cpu_name);
+- else
+- seq_printf(m, "unknown (%08x)", pvr);
+-
+-#ifdef CONFIG_ALTIVEC
+- if (cpu_has_feature(CPU_FTR_ALTIVEC))
+- seq_printf(m, ", altivec supported");
+-#endif /* CONFIG_ALTIVEC */
+-
+- seq_printf(m, "\n");
+-
+- /*
+- * Assume here that all clock rates are the same in a
+- * smp system. -- Cort
+- */
+- seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
+- ppc_proc_freq % 1000000);
+-
+- seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
+-
+- preempt_enable();
+- return 0;
+-}
+-
+-static void *c_start(struct seq_file *m, loff_t *pos)
+-{
+- return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
+-}
+-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+-{
+- ++*pos;
+- return c_start(m, pos);
+-}
+-static void c_stop(struct seq_file *m, void *v)
+-{
+-}
+-struct seq_operations cpuinfo_op = {
+- .start =c_start,
+- .next = c_next,
+- .stop = c_stop,
+- .show = show_cpuinfo,
+-};
+-
+-/*
+- * These three variables are used to save values passed to us by prom_init()
+- * via the device tree. The TCE variables are needed because with a memory_limit
+- * in force we may need to explicitly map the TCE are at the top of RAM.
+- */
+-unsigned long memory_limit;
+-unsigned long tce_alloc_start;
+-unsigned long tce_alloc_end;
+-
+-#ifdef CONFIG_PPC_ISERIES
+-/*
+- * On iSeries we just parse the mem=X option from the command line.
+- * On pSeries it's a bit more complicated, see prom_init_mem()
+- */
+-static int __init early_parsemem(char *p)
+-{
+- if (!p)
+- return 0;
+-
+- memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
+-
+- return 0;
+-}
+-early_param("mem", early_parsemem);
+-#endif /* CONFIG_PPC_ISERIES */
+-
+-#ifdef CONFIG_PPC_MULTIPLATFORM
+-static int __init set_preferred_console(void)
+-{
+- struct device_node *prom_stdout = NULL;
+- char *name;
+- u32 *spd;
+- int offset = 0;
+-
+- DBG(" -> set_preferred_console()\n");
+-
+- /* The user has requested a console so this is already set up. */
+- if (strstr(saved_command_line, "console=")) {
+- DBG(" console was specified !\n");
+- return -EBUSY;
+- }
+-
+- if (!of_chosen) {
+- DBG(" of_chosen is NULL !\n");
+- return -ENODEV;
+- }
+- /* We are getting a weird phandle from OF ... */
+- /* ... So use the full path instead */
+- name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+- if (name == NULL) {
+- DBG(" no linux,stdout-path !\n");
+- return -ENODEV;
+- }
+- prom_stdout = of_find_node_by_path(name);
+- if (!prom_stdout) {
+- DBG(" can't find stdout package %s !\n", name);
+- return -ENODEV;
+- }
+- DBG("stdout is %s\n", prom_stdout->full_name);
+-
+- name = (char *)get_property(prom_stdout, "name", NULL);
+- if (!name) {
+- DBG(" stdout package has no name !\n");
+- goto not_found;
+- }
+- spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
+-
+- if (0)
+- ;
+-#ifdef CONFIG_SERIAL_8250_CONSOLE
+- else if (strcmp(name, "serial") == 0) {
+- int i;
+- u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
+- if (i > 8) {
+- switch (reg[1]) {
+- case 0x3f8:
+- offset = 0;
+- break;
+- case 0x2f8:
+- offset = 1;
+- break;
+- case 0x898:
+- offset = 2;
+- break;
+- case 0x890:
+- offset = 3;
+- break;
+- default:
+- /* We dont recognise the serial port */
+- goto not_found;
+- }
+- }
+- }
+-#endif /* CONFIG_SERIAL_8250_CONSOLE */
+-#ifdef CONFIG_PPC_PSERIES
+- else if (strcmp(name, "vty") == 0) {
+- u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
+- char *compat = (char *)get_property(prom_stdout, "compatible", NULL);
+-
+- if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) {
+- /* Host Virtual Serial Interface */
+- int offset;
+- switch (reg[0]) {
+- case 0x30000000:
+- offset = 0;
+- break;
+- case 0x30000001:
+- offset = 1;
+- break;
+- default:
+- goto not_found;
+- }
+- of_node_put(prom_stdout);
+- DBG("Found hvsi console at offset %d\n", offset);
+- return add_preferred_console("hvsi", offset, NULL);
+- } else {
+- /* pSeries LPAR virtual console */
+- of_node_put(prom_stdout);
+- DBG("Found hvc console\n");
+- return add_preferred_console("hvc", 0, NULL);
+- }
+- }
+-#endif /* CONFIG_PPC_PSERIES */
+-#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
+- else if (strcmp(name, "ch-a") == 0)
+- offset = 0;
+- else if (strcmp(name, "ch-b") == 0)
+- offset = 1;
+-#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
+- else
+- goto not_found;
+- of_node_put(prom_stdout);
+-
+- DBG("Found serial console at ttyS%d\n", offset);
+-
+- if (spd) {
+- static char __initdata opt[16];
+- sprintf(opt, "%d", *spd);
+- return add_preferred_console("ttyS", offset, opt);
+- } else
+- return add_preferred_console("ttyS", offset, NULL);
+-
+- not_found:
+- DBG("No preferred console found !\n");
+- of_node_put(prom_stdout);
+- return -ENODEV;
+-}
+-console_initcall(set_preferred_console);
+-#endif /* CONFIG_PPC_MULTIPLATFORM */
+-
+-#ifdef CONFIG_IRQSTACKS
+-static void __init irqstack_early_init(void)
+-{
+- unsigned int i;
+-
+- /*
+- * interrupt stacks must be under 256MB, we cannot afford to take
+- * SLB misses on them.
+- */
+- for_each_cpu(i) {
+- softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
+- THREAD_SIZE, 0x10000000));
+- hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
+- THREAD_SIZE, 0x10000000));
+- }
+-}
+-#else
+-#define irqstack_early_init()
+-#endif
+-
+-/*
+- * Stack space used when we detect a bad kernel stack pointer, and
+- * early in SMP boots before relocation is enabled.
+- */
+-static void __init emergency_stack_init(void)
+-{
+- unsigned long limit;
+- unsigned int i;
+-
+- /*
+- * Emergency stacks must be under 256MB, we cannot afford to take
+- * SLB misses on them. The ABI also requires them to be 128-byte
+- * aligned.
+- *
+- * Since we use these as temporary stacks during secondary CPU
+- * bringup, we need to get at them in real mode. This means they
+- * must also be within the RMO region.
+- */
+- limit = min(0x10000000UL, lmb.rmo_size);
+-
+- for_each_cpu(i)
+- paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128,
+- limit)) + PAGE_SIZE;
+-}
+-
+-/*
+- * Called from setup_arch to initialize the bitmap of available
+- * syscalls in the systemcfg page
+- */
+-void __init setup_syscall_map(void)
+-{
+- unsigned int i, count64 = 0, count32 = 0;
+- extern unsigned long *sys_call_table;
+- extern unsigned long *sys_call_table32;
+- extern unsigned long sys_ni_syscall;
+-
+-
+- for (i = 0; i < __NR_syscalls; i++) {
+- if (sys_call_table[i] == sys_ni_syscall)
+- continue;
+- count64++;
+- systemcfg->syscall_map_64[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+- }
+- for (i = 0; i < __NR_syscalls; i++) {
+- if (sys_call_table32[i] == sys_ni_syscall)
+- continue;
+- count32++;
+- systemcfg->syscall_map_32[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+- }
+- printk(KERN_INFO "Syscall map setup, %d 32 bits and %d 64 bits syscalls\n",
+- count32, count64);
+-}
+-
+-/*
+- * Called into from start_kernel, after lock_kernel has been called.
+- * Initializes bootmem, which is unsed to manage page allocation until
+- * mem_init is called.
+- */
+-void __init setup_arch(char **cmdline_p)
+-{
+- extern void do_init_bootmem(void);
+-
+- ppc64_boot_msg(0x12, "Setup Arch");
+-
+- *cmdline_p = cmd_line;
+-
+- /*
+- * Set cache line size based on type of cpu as a default.
+- * Systems with OF can look in the properties on the cpu node(s)
+- * for a possibly more accurate value.
+- */
+- dcache_bsize = ppc64_caches.dline_size;
+- icache_bsize = ppc64_caches.iline_size;
+-
+- /* reboot on panic */
+- panic_timeout = 180;
+-
+- if (ppc_md.panic)
+- notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
+-
+- init_mm.start_code = PAGE_OFFSET;
+- init_mm.end_code = (unsigned long) _etext;
+- init_mm.end_data = (unsigned long) _edata;
+- init_mm.brk = klimit;
+-
+- irqstack_early_init();
+- emergency_stack_init();
+-
+- stabs_alloc();
+-
+- /* set up the bootmem stuff with available memory */
+- do_init_bootmem();
+- sparse_init();
+-
+- /* initialize the syscall map in systemcfg */
+- setup_syscall_map();
+-
+- ppc_md.setup_arch();
+-
+- /* Use the default idle loop if the platform hasn't provided one. */
+- if (NULL == ppc_md.idle_loop) {
+- ppc_md.idle_loop = default_idle;
+- printk(KERN_INFO "Using default idle loop\n");
+- }
+-
+- paging_init();
+- ppc64_boot_msg(0x15, "Setup Done");
+-}
+-
+-
+-/* ToDo: do something useful if ppc_md is not yet setup. */
+-#define PPC64_LINUX_FUNCTION 0x0f000000
+-#define PPC64_IPL_MESSAGE 0xc0000000
+-#define PPC64_TERM_MESSAGE 0xb0000000
+-
+-static void ppc64_do_msg(unsigned int src, const char *msg)
+-{
+- if (ppc_md.progress) {
+- char buf[128];
+-
+- sprintf(buf, "%08X\n", src);
+- ppc_md.progress(buf, 0);
+- snprintf(buf, 128, "%s", msg);
+- ppc_md.progress(buf, 0);
+- }
+-}
+-
+-/* Print a boot progress message. */
+-void ppc64_boot_msg(unsigned int src, const char *msg)
+-{
+- ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
+- printk("[boot]%04x %s\n", src, msg);
+-}
+-
+-/* Print a termination message (print only -- does not stop the kernel) */
+-void ppc64_terminate_msg(unsigned int src, const char *msg)
+-{
+- ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
+- printk("[terminate]%04x %s\n", src, msg);
+-}
+-
+-/* This should only be called on processor 0 during calibrate decr */
+-void __init setup_default_decr(void)
+-{
+- struct paca_struct *lpaca = get_paca();
+-
+- lpaca->default_decr = tb_ticks_per_jiffy;
+- lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
+-}
+-
+-#ifndef CONFIG_PPC_ISERIES
+-/*
+- * This function can be used by platforms to "find" legacy serial ports.
+- * It works for "serial" nodes under an "isa" node, and will try to
+- * respect the "ibm,aix-loc" property if any. It works with up to 8
+- * ports.
+- */
+-
+-#define MAX_LEGACY_SERIAL_PORTS 8
+-static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
+-static unsigned int old_serial_count;
+-
+-void __init generic_find_legacy_serial_ports(u64 *physport,
+- unsigned int *default_speed)
+-{
+- struct device_node *np;
+- u32 *sizeprop;
+-
+- struct isa_reg_property {
+- u32 space;
+- u32 address;
+- u32 size;
+- };
+- struct pci_reg_property {
+- struct pci_address addr;
+- u32 size_hi;
+- u32 size_lo;
+- };
+-
+- DBG(" -> generic_find_legacy_serial_port()\n");
+-
+- *physport = 0;
+- if (default_speed)
+- *default_speed = 0;
+-
+- np = of_find_node_by_path("/");
+- if (!np)
+- return;
+-
+- /* First fill our array */
+- for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
+- struct device_node *isa, *pci;
+- struct isa_reg_property *reg;
+- unsigned long phys_size, addr_size, io_base;
+- u32 *rangesp;
+- u32 *interrupts, *clk, *spd;
+- char *typep;
+- int index, rlen, rentsize;
+-
+- /* Ok, first check if it's under an "isa" parent */
+- isa = of_get_parent(np);
+- if (!isa || strcmp(isa->name, "isa")) {
+- DBG("%s: no isa parent found\n", np->full_name);
+- continue;
+- }
+-
+- /* Now look for an "ibm,aix-loc" property that gives us ordering
+- * if any...
+- */
+- typep = (char *)get_property(np, "ibm,aix-loc", NULL);
+-
+- /* Get the ISA port number */
+- reg = (struct isa_reg_property *)get_property(np, "reg", NULL);
+- if (reg == NULL)
+- goto next_port;
+- /* We assume the interrupt number isn't translated ... */
+- interrupts = (u32 *)get_property(np, "interrupts", NULL);
+- /* get clock freq. if present */
+- clk = (u32 *)get_property(np, "clock-frequency", NULL);
+- /* get default speed if present */
+- spd = (u32 *)get_property(np, "current-speed", NULL);
+- /* Default to locate at end of array */
+- index = old_serial_count; /* end of the array by default */
+-
+- /* If we have a location index, then use it */
+- if (typep && *typep == 'S') {
+- index = simple_strtol(typep+1, NULL, 0) - 1;
+- /* if index is out of range, use end of array instead */
+- if (index >= MAX_LEGACY_SERIAL_PORTS)
+- index = old_serial_count;
+- /* if our index is still out of range, that mean that
+- * array is full, we could scan for a free slot but that
+- * make little sense to bother, just skip the port
+- */
+- if (index >= MAX_LEGACY_SERIAL_PORTS)
+- goto next_port;
+- if (index >= old_serial_count)
+- old_serial_count = index + 1;
+- /* Check if there is a port who already claimed our slot */
+- if (serial_ports[index].iobase != 0) {
+- /* if we still have some room, move it, else override */
+- if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
+- DBG("Moved legacy port %d -> %d\n", index,
+- old_serial_count);
+- serial_ports[old_serial_count++] =
+- serial_ports[index];
+- } else {
+- DBG("Replacing legacy port %d\n", index);
+- }
+- }
+- }
+- if (index >= MAX_LEGACY_SERIAL_PORTS)
+- goto next_port;
+- if (index >= old_serial_count)
+- old_serial_count = index + 1;
+-
+- /* Now fill the entry */
+- memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port));
+- serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16;
+- serial_ports[index].iobase = reg->address;
+- serial_ports[index].irq = interrupts ? interrupts[0] : 0;
+- serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
+-
+- DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
+- index,
+- serial_ports[index].iobase,
+- serial_ports[index].irq,
+- serial_ports[index].uartclk);
+-
+- /* Get phys address of IO reg for port 1 */
+- if (index != 0)
+- goto next_port;
+-
+- pci = of_get_parent(isa);
+- if (!pci) {
+- DBG("%s: no pci parent found\n", np->full_name);
+- goto next_port;
+- }
+-
+- rangesp = (u32 *)get_property(pci, "ranges", &rlen);
+- if (rangesp == NULL) {
+- of_node_put(pci);
+- goto next_port;
+- }
+- rlen /= 4;
+-
+- /* we need the #size-cells of the PCI bridge node itself */
+- phys_size = 1;
+- sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
+- if (sizeprop != NULL)
+- phys_size = *sizeprop;
+- /* we need the parent #addr-cells */
+- addr_size = prom_n_addr_cells(pci);
+- rentsize = 3 + addr_size + phys_size;
+- io_base = 0;
+- for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
+- if (((rangesp[0] >> 24) & 0x3) != 1)
+- continue; /* not IO space */
+- io_base = rangesp[3];
+- if (addr_size == 2)
+- io_base = (io_base << 32) | rangesp[4];
+- }
+- if (io_base != 0) {
+- *physport = io_base + reg->address;
+- if (default_speed && spd)
+- *default_speed = *spd;
+- }
+- of_node_put(pci);
+- next_port:
+- of_node_put(isa);
+- }
+-
+- DBG(" <- generic_find_legacy_serial_port()\n");
+-}
+-
+-static struct platform_device serial_device = {
+- .name = "serial8250",
+- .id = PLAT8250_DEV_PLATFORM,
+- .dev = {
+- .platform_data = serial_ports,
+- },
+-};
+-
+-static int __init serial_dev_init(void)
+-{
+- return platform_device_register(&serial_device);
+-}
+-arch_initcall(serial_dev_init);
+-
+-#endif /* CONFIG_PPC_ISERIES */
+-
+-int check_legacy_ioport(unsigned long base_port)
+-{
+- if (ppc_md.check_legacy_ioport == NULL)
+- return 0;
+- return ppc_md.check_legacy_ioport(base_port);
+-}
+-EXPORT_SYMBOL(check_legacy_ioport);
+-
+-#ifdef CONFIG_XMON
+-static int __init early_xmon(char *p)
+-{
+- /* ensure xmon is enabled */
+- if (p) {
+- if (strncmp(p, "on", 2) == 0)
+- xmon_init(1);
+- if (strncmp(p, "off", 3) == 0)
+- xmon_init(0);
+- if (strncmp(p, "early", 5) != 0)
+- return 0;
+- }
+- xmon_init(1);
+- debugger(NULL);
+-
+- return 0;
+-}
+-early_param("xmon", early_xmon);
+-#endif
+-
+-void cpu_die(void)
+-{
+- if (ppc_md.cpu_die)
+- ppc_md.cpu_die();
+-}
+diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
+--- a/arch/ppc64/kernel/signal.c
++++ b/arch/ppc64/kernel/signal.c
+@@ -133,7 +133,7 @@ static long setup_sigcontext(struct sigc
+ flush_fp_to_thread(current);
+
+ /* Make sure signal doesn't get spurrious FP exceptions */
+- current->thread.fpscr = 0;
++ current->thread.fpscr.val = 0;
+
+ #ifdef CONFIG_ALTIVEC
+ err |= __put_user(v_regs, &sc->v_regs);
+diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/signal32.c
++++ /dev/null
+@@ -1,998 +0,0 @@
+-/*
+- * signal32.c: Support 32bit signal syscalls.
+- *
+- * Copyright (C) 2001 IBM
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1997 David S. Miller (davem at caip.rutgers.edu)
+- *
+- * These routines maintain argument size conversion between 32bit and 64bit
+- * environment.
+- *
+- * 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/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/kernel.h>
+-#include <linux/signal.h>
+-#include <linux/syscalls.h>
+-#include <linux/errno.h>
+-#include <linux/elf.h>
+-#include <linux/compat.h>
+-#include <linux/ptrace.h>
+-#include <asm/ppc32.h>
+-#include <asm/uaccess.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/unistd.h>
+-#include <asm/cacheflush.h>
+-#include <asm/vdso.h>
+-
+-#define DEBUG_SIG 0
+-
+-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+-
+-#define GP_REGS_SIZE32 min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32))
+-
+-/*
+- * When we have signals to deliver, we set up on the
+- * user stack, going down from the original stack pointer:
+- * a sigregs32 struct
+- * a sigcontext32 struct
+- * a gap of __SIGNAL_FRAMESIZE32 bytes
+- *
+- * Each of these things must be a multiple of 16 bytes in size.
+- *
+- */
+-struct sigregs32 {
+- struct mcontext32 mctx; /* all the register values */
+- /*
+- * Programs using the rs6000/xcoff abi can save up to 19 gp
+- * regs and 18 fp regs below sp before decrementing it.
+- */
+- int abigap[56];
+-};
+-
+-/* We use the mc_pad field for the signal return trampoline. */
+-#define tramp mc_pad
+-
+-/*
+- * When we have rt signals to deliver, we set up on the
+- * user stack, going down from the original stack pointer:
+- * one rt_sigframe32 struct (siginfo + ucontext + ABI gap)
+- * a gap of __SIGNAL_FRAMESIZE32+16 bytes
+- * (the +16 is to get the siginfo and ucontext32 in the same
+- * positions as in older kernels).
+- *
+- * Each of these things must be a multiple of 16 bytes in size.
+- *
+- */
+-struct rt_sigframe32 {
+- compat_siginfo_t info;
+- struct ucontext32 uc;
+- /*
+- * Programs using the rs6000/xcoff abi can save up to 19 gp
+- * regs and 18 fp regs below sp before decrementing it.
+- */
+- int abigap[56];
+-};
+-
+-
+-/*
+- * Common utility functions used by signal and context support
+- *
+- */
+-
+-/*
+- * Restore the user process's signal mask
+- * (implemented in signal.c)
+- */
+-extern void restore_sigmask(sigset_t *set);
+-
+-/*
+- * Functions for flipping sigsets (thanks to brain dead generic
+- * implementation that makes things simple for little endian only
+- */
+-static inline void compat_from_sigset(compat_sigset_t *compat, sigset_t *set)
+-{
+- switch (_NSIG_WORDS) {
+- case 4: compat->sig[5] = set->sig[3] & 0xffffffffull ;
+- compat->sig[7] = set->sig[3] >> 32;
+- case 3: compat->sig[4] = set->sig[2] & 0xffffffffull ;
+- compat->sig[5] = set->sig[2] >> 32;
+- case 2: compat->sig[2] = set->sig[1] & 0xffffffffull ;
+- compat->sig[3] = set->sig[1] >> 32;
+- case 1: compat->sig[0] = set->sig[0] & 0xffffffffull ;
+- compat->sig[1] = set->sig[0] >> 32;
+- }
+-}
+-
+-static inline void sigset_from_compat(sigset_t *set, compat_sigset_t *compat)
+-{
+- switch (_NSIG_WORDS) {
+- case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32);
+- case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32);
+- case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32);
+- case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32);
+- }
+-}
+-
+-
+-/*
+- * Save the current user registers on the user stack.
+- * We only save the altivec registers if the process has used
+- * altivec instructions at some point.
+- */
+-static int save_user_regs(struct pt_regs *regs, struct mcontext32 __user *frame, int sigret)
+-{
+- elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
+- int i, err = 0;
+-
+- /* Make sure floating point registers are stored in regs */
+- flush_fp_to_thread(current);
+-
+- /* save general and floating-point registers */
+- for (i = 0; i <= PT_RESULT; i ++)
+- err |= __put_user((unsigned int)gregs[i], &frame->mc_gregs[i]);
+- err |= __copy_to_user(&frame->mc_fregs, current->thread.fpr,
+- ELF_NFPREG * sizeof(double));
+- if (err)
+- return 1;
+-
+- current->thread.fpscr = 0; /* turn off all fp exceptions */
+-
+-#ifdef CONFIG_ALTIVEC
+- /* save altivec registers */
+- if (current->thread.used_vr) {
+- flush_altivec_to_thread(current);
+- if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
+- ELF_NVRREG32 * sizeof(vector128)))
+- return 1;
+- /* set MSR_VEC in the saved MSR value to indicate that
+- frame->mc_vregs contains valid data */
+- if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR]))
+- return 1;
+- }
+- /* else assert((regs->msr & MSR_VEC) == 0) */
+-
+- /* We always copy to/from vrsave, it's 0 if we don't have or don't
+- * use altivec. Since VSCR only contains 32 bits saved in the least
+- * significant bits of a vector, we "cheat" and stuff VRSAVE in the
+- * most significant bits of that same vector. --BenH
+- */
+- if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))
+- return 1;
+-#endif /* CONFIG_ALTIVEC */
+-
+- if (sigret) {
+- /* Set up the sigreturn trampoline: li r0,sigret; sc */
+- if (__put_user(0x38000000UL + sigret, &frame->tramp[0])
+- || __put_user(0x44000002UL, &frame->tramp[1]))
+- return 1;
+- flush_icache_range((unsigned long) &frame->tramp[0],
+- (unsigned long) &frame->tramp[2]);
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * Restore the current user register values from the user stack,
+- * (except for MSR).
+- */
+-static long restore_user_regs(struct pt_regs *regs,
+- struct mcontext32 __user *sr, int sig)
+-{
+- elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
+- int i;
+- long err = 0;
+- unsigned int save_r2 = 0;
+-#ifdef CONFIG_ALTIVEC
+- unsigned long msr;
+-#endif
+-
+- /*
+- * restore general registers but not including MSR or SOFTE. Also
+- * take care of keeping r2 (TLS) intact if not a signal
+- */
+- if (!sig)
+- save_r2 = (unsigned int)regs->gpr[2];
+- for (i = 0; i <= PT_RESULT; i++) {
+- if ((i == PT_MSR) || (i == PT_SOFTE))
+- continue;
+- err |= __get_user(gregs[i], &sr->mc_gregs[i]);
+- }
+- if (!sig)
+- regs->gpr[2] = (unsigned long) save_r2;
+- if (err)
+- return 1;
+-
+- /* force the process to reload the FP registers from
+- current->thread when it next does FP instructions */
+- regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
+- if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
+- sizeof(sr->mc_fregs)))
+- return 1;
+-
+-#ifdef CONFIG_ALTIVEC
+- /* force the process to reload the altivec registers from
+- current->thread when it next does altivec instructions */
+- regs->msr &= ~MSR_VEC;
+- if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
+- /* restore altivec registers from the stack */
+- if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
+- sizeof(sr->mc_vregs)))
+- return 1;
+- } else if (current->thread.used_vr)
+- memset(current->thread.vr, 0, ELF_NVRREG32 * sizeof(vector128));
+-
+- /* Always get VRSAVE back */
+- if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
+- return 1;
+-#endif /* CONFIG_ALTIVEC */
+-
+-#ifndef CONFIG_SMP
+- preempt_disable();
+- if (last_task_used_math == current)
+- last_task_used_math = NULL;
+- if (last_task_used_altivec == current)
+- last_task_used_altivec = NULL;
+- preempt_enable();
+-#endif
+- return 0;
+-}
+-
+-
+-/*
+- * Start of nonRT signal support
+- *
+- * sigset_t is 32 bits for non-rt signals
+- *
+- * System Calls
+- * sigaction sys32_sigaction
+- * sigreturn sys32_sigreturn
+- *
+- * Note sigsuspend has no special 32 bit routine - uses the 64 bit routine
+- *
+- * Other routines
+- * setup_frame32
+- */
+-
+-/*
+- * Atomically swap in the new signal mask, and wait for a signal.
+- */
+-long sys32_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
+- struct pt_regs *regs)
+-{
+- sigset_t saveset;
+-
+- mask &= _BLOCKABLE;
+- spin_lock_irq(¤t->sighand->siglock);
+- saveset = current->blocked;
+- siginitset(¤t->blocked, mask);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+-
+- regs->result = -EINTR;
+- regs->gpr[3] = EINTR;
+- regs->ccr |= 0x10000000;
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal32(&saveset, regs))
+- /*
+- * Returning 0 means we return to userspace via
+- * ret_from_except and thus restore all user
+- * registers from *regs. This is what we need
+- * to do when a signal has been delivered.
+- */
+- return 0;
+- }
+-}
+-
+-long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
+- struct old_sigaction32 __user *oact)
+-{
+- struct k_sigaction new_ka, old_ka;
+- int ret;
+-
+- if (sig < 0)
+- sig = -sig;
+-
+- if (act) {
+- compat_old_sigset_t mask;
+- compat_uptr_t handler, restorer;
+-
+- if (get_user(handler, &act->sa_handler) ||
+- __get_user(restorer, &act->sa_restorer) ||
+- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+- __get_user(mask, &act->sa_mask))
+- return -EFAULT;
+- new_ka.sa.sa_handler = compat_ptr(handler);
+- new_ka.sa.sa_restorer = compat_ptr(restorer);
+- siginitset(&new_ka.sa.sa_mask, mask);
+- }
+-
+- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+- if (!ret && oact) {
+- if (put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) ||
+- __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
+- return -EFAULT;
+- }
+-
+- return ret;
+-}
+-
+-
+-
+-/*
+- * Start of RT signal support
+- *
+- * sigset_t is 64 bits for rt signals
+- *
+- * System Calls
+- * sigaction sys32_rt_sigaction
+- * sigpending sys32_rt_sigpending
+- * sigprocmask sys32_rt_sigprocmask
+- * sigreturn sys32_rt_sigreturn
+- * sigqueueinfo sys32_rt_sigqueueinfo
+- * sigsuspend sys32_rt_sigsuspend
+- *
+- * Other routines
+- * setup_rt_frame32
+- * copy_siginfo_to_user32
+- * siginfo32to64
+- */
+-
+-
+-long sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
+- struct sigaction32 __user *oact, size_t sigsetsize)
+-{
+- struct k_sigaction new_ka, old_ka;
+- int ret;
+- compat_sigset_t set32;
+-
+- /* XXX: Don't preclude handling different sized sigset_t's. */
+- if (sigsetsize != sizeof(compat_sigset_t))
+- return -EINVAL;
+-
+- if (act) {
+- compat_uptr_t handler;
+-
+- ret = get_user(handler, &act->sa_handler);
+- new_ka.sa.sa_handler = compat_ptr(handler);
+- ret |= __copy_from_user(&set32, &act->sa_mask,
+- sizeof(compat_sigset_t));
+- sigset_from_compat(&new_ka.sa.sa_mask, &set32);
+- ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+- if (ret)
+- return -EFAULT;
+- }
+-
+- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+- if (!ret && oact) {
+- compat_from_sigset(&set32, &old_ka.sa.sa_mask);
+- ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
+- ret |= __copy_to_user(&oact->sa_mask, &set32,
+- sizeof(compat_sigset_t));
+- ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+- }
+- return ret;
+-}
+-
+-/*
+- * Note: it is necessary to treat how as an unsigned int, with the
+- * corresponding cast to a signed int to insure that the proper
+- * conversion (sign extension) between the register representation
+- * of a signed int (msr in 32-bit mode) and the register representation
+- * of a signed int (msr in 64-bit mode) is performed.
+- */
+-long sys32_rt_sigprocmask(u32 how, compat_sigset_t __user *set,
+- compat_sigset_t __user *oset, size_t sigsetsize)
+-{
+- sigset_t s;
+- sigset_t __user *up;
+- compat_sigset_t s32;
+- int ret;
+- mm_segment_t old_fs = get_fs();
+-
+- if (set) {
+- if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
+- return -EFAULT;
+- sigset_from_compat(&s, &s32);
+- }
+-
+- set_fs(KERNEL_DS);
+- /* This is valid because of the set_fs() */
+- up = (sigset_t __user *) &s;
+- ret = sys_rt_sigprocmask((int)how, set ? up : NULL, oset ? up : NULL,
+- sigsetsize);
+- set_fs(old_fs);
+- if (ret)
+- return ret;
+- if (oset) {
+- compat_from_sigset(&s32, &s);
+- if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
+- return -EFAULT;
+- }
+- return 0;
+-}
+-
+-long sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
+-{
+- sigset_t s;
+- compat_sigset_t s32;
+- int ret;
+- mm_segment_t old_fs = get_fs();
+-
+- set_fs(KERNEL_DS);
+- /* The __user pointer cast is valid because of the set_fs() */
+- ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
+- set_fs(old_fs);
+- if (!ret) {
+- compat_from_sigset(&s32, &s);
+- if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
+- return -EFAULT;
+- }
+- return ret;
+-}
+-
+-
+-int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
+-{
+- int err;
+-
+- if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
+- return -EFAULT;
+-
+- /* If you change siginfo_t structure, please be sure
+- * this code is fixed accordingly.
+- * It should never copy any pad contained in the structure
+- * to avoid security leaks, but must copy the generic
+- * 3 ints plus the relevant union member.
+- * This routine must convert siginfo from 64bit to 32bit as well
+- * at the same time.
+- */
+- err = __put_user(s->si_signo, &d->si_signo);
+- err |= __put_user(s->si_errno, &d->si_errno);
+- err |= __put_user((short)s->si_code, &d->si_code);
+- if (s->si_code < 0)
+- err |= __copy_to_user(&d->_sifields._pad, &s->_sifields._pad,
+- SI_PAD_SIZE32);
+- else switch(s->si_code >> 16) {
+- case __SI_CHLD >> 16:
+- err |= __put_user(s->si_pid, &d->si_pid);
+- err |= __put_user(s->si_uid, &d->si_uid);
+- err |= __put_user(s->si_utime, &d->si_utime);
+- err |= __put_user(s->si_stime, &d->si_stime);
+- err |= __put_user(s->si_status, &d->si_status);
+- break;
+- case __SI_FAULT >> 16:
+- err |= __put_user((unsigned int)(unsigned long)s->si_addr,
+- &d->si_addr);
+- break;
+- case __SI_POLL >> 16:
+- err |= __put_user(s->si_band, &d->si_band);
+- err |= __put_user(s->si_fd, &d->si_fd);
+- break;
+- case __SI_TIMER >> 16:
+- err |= __put_user(s->si_tid, &d->si_tid);
+- err |= __put_user(s->si_overrun, &d->si_overrun);
+- err |= __put_user(s->si_int, &d->si_int);
+- break;
+- case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
+- case __SI_MESGQ >> 16:
+- err |= __put_user(s->si_int, &d->si_int);
+- /* fallthrough */
+- case __SI_KILL >> 16:
+- default:
+- err |= __put_user(s->si_pid, &d->si_pid);
+- err |= __put_user(s->si_uid, &d->si_uid);
+- break;
+- }
+- return err;
+-}
+-
+-/*
+- * Note: it is necessary to treat pid and sig as unsigned ints, with the
+- * corresponding cast to a signed int to insure that the proper conversion
+- * (sign extension) between the register representation of a signed int
+- * (msr in 32-bit mode) and the register representation of a signed int
+- * (msr in 64-bit mode) is performed.
+- */
+-long sys32_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo)
+-{
+- siginfo_t info;
+- int ret;
+- mm_segment_t old_fs = get_fs();
+-
+- if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
+- copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
+- return -EFAULT;
+- set_fs (KERNEL_DS);
+- /* The __user pointer cast is valid becasuse of the set_fs() */
+- ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info);
+- set_fs (old_fs);
+- return ret;
+-}
+-
+-int sys32_rt_sigsuspend(compat_sigset_t __user * unewset, size_t sigsetsize, int p3,
+- int p4, int p6, int p7, struct pt_regs *regs)
+-{
+- sigset_t saveset, newset;
+- compat_sigset_t s32;
+-
+- /* XXX: Don't preclude handling different sized sigset_t's. */
+- if (sigsetsize != sizeof(sigset_t))
+- return -EINVAL;
+-
+- if (copy_from_user(&s32, unewset, sizeof(s32)))
+- return -EFAULT;
+-
+- /*
+- * Swap the 2 words of the 64-bit sigset_t (they are stored
+- * in the "wrong" endian in 32-bit user storage).
+- */
+- sigset_from_compat(&newset, &s32);
+-
+- sigdelsetmask(&newset, ~_BLOCKABLE);
+- spin_lock_irq(¤t->sighand->siglock);
+- saveset = current->blocked;
+- current->blocked = newset;
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+-
+- regs->result = -EINTR;
+- regs->gpr[3] = EINTR;
+- regs->ccr |= 0x10000000;
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal32(&saveset, regs))
+- /*
+- * Returning 0 means we return to userspace via
+- * ret_from_except and thus restore all user
+- * registers from *regs. This is what we need
+- * to do when a signal has been delivered.
+- */
+- return 0;
+- }
+-}
+-
+-/*
+- * Start Alternate signal stack support
+- *
+- * System Calls
+- * sigaltatck sys32_sigaltstack
+- */
+-
+-int sys32_sigaltstack(u32 __new, u32 __old, int r5,
+- int r6, int r7, int r8, struct pt_regs *regs)
+-{
+- stack_32_t __user * newstack = (stack_32_t __user *)(long) __new;
+- stack_32_t __user * oldstack = (stack_32_t __user *)(long) __old;
+- stack_t uss, uoss;
+- int ret;
+- mm_segment_t old_fs;
+- unsigned long sp;
+- compat_uptr_t ss_sp;
+-
+- /*
+- * set sp to the user stack on entry to the system call
+- * the system call router sets R9 to the saved registers
+- */
+- sp = regs->gpr[1];
+-
+- /* Put new stack info in local 64 bit stack struct */
+- if (newstack) {
+- if (get_user(ss_sp, &newstack->ss_sp) ||
+- __get_user(uss.ss_flags, &newstack->ss_flags) ||
+- __get_user(uss.ss_size, &newstack->ss_size))
+- return -EFAULT;
+- uss.ss_sp = compat_ptr(ss_sp);
+- }
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- /* The __user pointer casts are valid because of the set_fs() */
+- ret = do_sigaltstack(
+- newstack ? (stack_t __user *) &uss : NULL,
+- oldstack ? (stack_t __user *) &uoss : NULL,
+- sp);
+- set_fs(old_fs);
+- /* Copy the stack information to the user output buffer */
+- if (!ret && oldstack &&
+- (put_user((long)uoss.ss_sp, &oldstack->ss_sp) ||
+- __put_user(uoss.ss_flags, &oldstack->ss_flags) ||
+- __put_user(uoss.ss_size, &oldstack->ss_size)))
+- return -EFAULT;
+- return ret;
+-}
+-
+-
+-/*
+- * Set up a signal frame for a "real-time" signal handler
+- * (one which gets siginfo).
+- */
+-static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+- siginfo_t *info, sigset_t *oldset,
+- struct pt_regs * regs, unsigned long newsp)
+-{
+- struct rt_sigframe32 __user *rt_sf;
+- struct mcontext32 __user *frame;
+- unsigned long origsp = newsp;
+- compat_sigset_t c_oldset;
+-
+- /* Set up Signal Frame */
+- /* Put a Real Time Context onto stack */
+- newsp -= sizeof(*rt_sf);
+- rt_sf = (struct rt_sigframe32 __user *)newsp;
+-
+- /* create a stack frame for the caller of the handler */
+- newsp -= __SIGNAL_FRAMESIZE32 + 16;
+-
+- if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
+- goto badframe;
+-
+- compat_from_sigset(&c_oldset, oldset);
+-
+- /* Put the siginfo & fill in most of the ucontext */
+- if (copy_siginfo_to_user32(&rt_sf->info, info)
+- || __put_user(0, &rt_sf->uc.uc_flags)
+- || __put_user(0, &rt_sf->uc.uc_link)
+- || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
+- || __put_user(sas_ss_flags(regs->gpr[1]),
+- &rt_sf->uc.uc_stack.ss_flags)
+- || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
+- || __put_user((u32)(u64)&rt_sf->uc.uc_mcontext, &rt_sf->uc.uc_regs)
+- || __copy_to_user(&rt_sf->uc.uc_sigmask, &c_oldset, sizeof(c_oldset)))
+- goto badframe;
+-
+- /* Save user registers on the stack */
+- frame = &rt_sf->uc.uc_mcontext;
+- if (put_user(regs->gpr[1], (u32 __user *)newsp))
+- goto badframe;
+-
+- if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+- if (save_user_regs(regs, frame, 0))
+- goto badframe;
+- regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+- } else {
+- if (save_user_regs(regs, frame, __NR_rt_sigreturn))
+- goto badframe;
+- regs->link = (unsigned long) frame->tramp;
+- }
+- regs->gpr[1] = (unsigned long) newsp;
+- regs->gpr[3] = sig;
+- regs->gpr[4] = (unsigned long) &rt_sf->info;
+- regs->gpr[5] = (unsigned long) &rt_sf->uc;
+- regs->gpr[6] = (unsigned long) rt_sf;
+- regs->nip = (unsigned long) ka->sa.sa_handler;
+- regs->trap = 0;
+- regs->result = 0;
+-
+- if (test_thread_flag(TIF_SINGLESTEP))
+- ptrace_notify(SIGTRAP);
+-
+- return 1;
+-
+-badframe:
+-#if DEBUG_SIG
+- printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
+- regs, frame, newsp);
+-#endif
+- force_sigsegv(sig, current);
+- return 0;
+-}
+-
+-static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig)
+-{
+- compat_sigset_t c_set;
+- sigset_t set;
+- u32 mcp;
+-
+- if (__copy_from_user(&c_set, &ucp->uc_sigmask, sizeof(c_set))
+- || __get_user(mcp, &ucp->uc_regs))
+- return -EFAULT;
+- sigset_from_compat(&set, &c_set);
+- restore_sigmask(&set);
+- if (restore_user_regs(regs, (struct mcontext32 __user *)(u64)mcp, sig))
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-/*
+- * Handle {get,set,swap}_context operations for 32 bits processes
+- */
+-
+-long sys32_swapcontext(struct ucontext32 __user *old_ctx,
+- struct ucontext32 __user *new_ctx,
+- int ctx_size, int r6, int r7, int r8, struct pt_regs *regs)
+-{
+- unsigned char tmp;
+- compat_sigset_t c_set;
+-
+- /* Context size is for future use. Right now, we only make sure
+- * we are passed something we understand
+- */
+- if (ctx_size < sizeof(struct ucontext32))
+- return -EINVAL;
+-
+- if (old_ctx != NULL) {
+- compat_from_sigset(&c_set, ¤t->blocked);
+- if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
+- || save_user_regs(regs, &old_ctx->uc_mcontext, 0)
+- || __copy_to_user(&old_ctx->uc_sigmask, &c_set, sizeof(c_set))
+- || __put_user((u32)(u64)&old_ctx->uc_mcontext, &old_ctx->uc_regs))
+- return -EFAULT;
+- }
+- if (new_ctx == NULL)
+- return 0;
+- if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
+- || __get_user(tmp, (u8 __user *) new_ctx)
+- || __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
+- return -EFAULT;
+-
+- /*
+- * If we get a fault copying the context into the kernel's
+- * image of the user's registers, we can't just return -EFAULT
+- * because the user's registers will be corrupted. For instance
+- * the NIP value may have been updated but not some of the
+- * other registers. Given that we have done the access_ok
+- * and successfully read the first and last bytes of the region
+- * above, this should only happen in an out-of-memory situation
+- * or if another thread unmaps the region containing the context.
+- * We kill the task with a SIGSEGV in this situation.
+- */
+- if (do_setcontext32(new_ctx, regs, 0))
+- do_exit(SIGSEGV);
+-
+- return 0;
+-}
+-
+-long sys32_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
+- struct pt_regs *regs)
+-{
+- struct rt_sigframe32 __user *rt_sf;
+- int ret;
+-
+-
+- /* Always make any pending restarted system calls return -EINTR */
+- current_thread_info()->restart_block.fn = do_no_restart_syscall;
+-
+- rt_sf = (struct rt_sigframe32 __user *)
+- (regs->gpr[1] + __SIGNAL_FRAMESIZE32 + 16);
+- if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf)))
+- goto bad;
+- if (do_setcontext32(&rt_sf->uc, regs, 1))
+- goto bad;
+-
+- /*
+- * It's not clear whether or why it is desirable to save the
+- * sigaltstack setting on signal delivery and restore it on
+- * signal return. But other architectures do this and we have
+- * always done it up until now so it is probably better not to
+- * change it. -- paulus
+- * We use the sys32_ version that does the 32/64 bits conversion
+- * and takes userland pointer directly. What about error checking ?
+- * nobody does any...
+- */
+- sys32_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs);
+-
+- ret = regs->result;
+-
+- return ret;
+-
+- bad:
+- force_sig(SIGSEGV, current);
+- return 0;
+-}
+-
+-
+-/*
+- * OK, we're invoking a handler
+- */
+-static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+- siginfo_t *info, sigset_t *oldset,
+- struct pt_regs * regs, unsigned long newsp)
+-{
+- struct sigcontext32 __user *sc;
+- struct sigregs32 __user *frame;
+- unsigned long origsp = newsp;
+-
+- /* Set up Signal Frame */
+- newsp -= sizeof(struct sigregs32);
+- frame = (struct sigregs32 __user *) newsp;
+-
+- /* Put a sigcontext on the stack */
+- newsp -= sizeof(*sc);
+- sc = (struct sigcontext32 __user *) newsp;
+-
+- /* create a stack frame for the caller of the handler */
+- newsp -= __SIGNAL_FRAMESIZE32;
+-
+- if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+- goto badframe;
+-
+-#if _NSIG != 64
+-#error "Please adjust handle_signal32()"
+-#endif
+- if (__put_user((u32)(u64)ka->sa.sa_handler, &sc->handler)
+- || __put_user(oldset->sig[0], &sc->oldmask)
+- || __put_user((oldset->sig[0] >> 32), &sc->_unused[3])
+- || __put_user((u32)(u64)frame, &sc->regs)
+- || __put_user(sig, &sc->signal))
+- goto badframe;
+-
+- if (vdso32_sigtramp && current->thread.vdso_base) {
+- if (save_user_regs(regs, &frame->mctx, 0))
+- goto badframe;
+- regs->link = current->thread.vdso_base + vdso32_sigtramp;
+- } else {
+- if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
+- goto badframe;
+- regs->link = (unsigned long) frame->mctx.tramp;
+- }
+-
+- if (put_user(regs->gpr[1], (u32 __user *)newsp))
+- goto badframe;
+- regs->gpr[1] = (unsigned long) newsp;
+- regs->gpr[3] = sig;
+- regs->gpr[4] = (unsigned long) sc;
+- regs->nip = (unsigned long) ka->sa.sa_handler;
+- regs->trap = 0;
+- regs->result = 0;
+-
+- if (test_thread_flag(TIF_SINGLESTEP))
+- ptrace_notify(SIGTRAP);
+-
+- return 1;
+-
+-badframe:
+-#if DEBUG_SIG
+- printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n",
+- regs, frame, *newspp);
+-#endif
+- force_sigsegv(sig, current);
+- return 0;
+-}
+-
+-/*
+- * Do a signal return; undo the signal stack.
+- */
+-long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
+- struct pt_regs *regs)
+-{
+- struct sigcontext32 __user *sc;
+- struct sigcontext32 sigctx;
+- struct mcontext32 __user *sr;
+- sigset_t set;
+- int ret;
+-
+- /* Always make any pending restarted system calls return -EINTR */
+- current_thread_info()->restart_block.fn = do_no_restart_syscall;
+-
+- sc = (struct sigcontext32 __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32);
+- if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
+- goto badframe;
+-
+- /*
+- * Note that PPC32 puts the upper 32 bits of the sigmask in the
+- * unused part of the signal stackframe
+- */
+- set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3]) << 32);
+- restore_sigmask(&set);
+-
+- sr = (struct mcontext32 __user *)(u64)sigctx.regs;
+- if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
+- || restore_user_regs(regs, sr, 1))
+- goto badframe;
+-
+- ret = regs->result;
+- return ret;
+-
+-badframe:
+- force_sig(SIGSEGV, current);
+- return 0;
+-}
+-
+-
+-
+-/*
+- * Start of do_signal32 routine
+- *
+- * This routine gets control when a pending signal needs to be processed
+- * in the 32 bit target thread -
+- *
+- * It handles both rt and non-rt signals
+- */
+-
+-/*
+- * Note that 'init' is a special process: it doesn't get signals it doesn't
+- * want to handle. Thus you cannot kill init even with a SIGKILL even by
+- * mistake.
+- */
+-
+-int do_signal32(sigset_t *oldset, struct pt_regs *regs)
+-{
+- siginfo_t info;
+- unsigned int frame, newsp;
+- int signr, ret;
+- struct k_sigaction ka;
+-
+- if (!oldset)
+- oldset = ¤t->blocked;
+-
+- newsp = frame = 0;
+-
+- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+-
+- if (TRAP(regs) == 0x0C00 /* System Call! */
+- && regs->ccr & 0x10000000 /* error signalled */
+- && ((ret = regs->gpr[3]) == ERESTARTSYS
+- || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
+- || ret == ERESTART_RESTARTBLOCK)) {
+-
+- if (signr > 0
+- && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
+- || (ret == ERESTARTSYS
+- && !(ka.sa.sa_flags & SA_RESTART)))) {
+- /* make the system call return an EINTR error */
+- regs->result = -EINTR;
+- regs->gpr[3] = EINTR;
+- /* note that the cr0.SO bit is already set */
+- } else {
+- regs->nip -= 4; /* Back up & retry system call */
+- regs->result = 0;
+- regs->trap = 0;
+- if (ret == ERESTART_RESTARTBLOCK)
+- regs->gpr[0] = __NR_restart_syscall;
+- else
+- regs->gpr[3] = regs->orig_gpr3;
+- }
+- }
+-
+- if (signr == 0)
+- return 0; /* no signals delivered */
+-
+- if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+- && (!on_sig_stack(regs->gpr[1])))
+- newsp = (current->sas_ss_sp + current->sas_ss_size);
+- else
+- newsp = regs->gpr[1];
+- newsp &= ~0xfUL;
+-
+- /*
+- * Reenable the DABR before delivering the signal to
+- * user space. The DABR will have been cleared if it
+- * triggered inside the kernel.
+- */
+- if (current->thread.dabr)
+- set_dabr(current->thread.dabr);
+-
+- /* Whee! Actually deliver the signal. */
+- if (ka.sa.sa_flags & SA_SIGINFO)
+- ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
+- else
+- ret = handle_signal32(signr, &ka, &info, oldset, regs, newsp);
+-
+- if (ret) {
+- spin_lock_irq(¤t->sighand->siglock);
+- sigorsets(¤t->blocked, ¤t->blocked,
+- &ka.sa.sa_mask);
+- if (!(ka.sa.sa_flags & SA_NODEFER))
+- sigaddset(¤t->blocked, signr);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- }
+-
+- return ret;
+-}
+diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
+--- a/arch/ppc64/kernel/smp.c
++++ b/arch/ppc64/kernel/smp.c
+@@ -45,8 +45,7 @@
+ #include <asm/cputable.h>
+ #include <asm/system.h>
+ #include <asm/abs_addr.h>
+-
+-#include "mpic.h"
++#include <asm/mpic.h>
+
+ #ifdef DEBUG
+ #define DBG(fmt...) udbg_printf(fmt)
+@@ -70,28 +69,6 @@ void smp_call_function_interrupt(void);
+ int smt_enabled_at_boot = 1;
+
+ #ifdef CONFIG_MPIC
+-void smp_mpic_message_pass(int target, int msg)
+-{
+- /* make sure we're sending something that translates to an IPI */
+- if ( msg > 0x3 ){
+- printk("SMP %d: smp_message_pass: unknown msg %d\n",
+- smp_processor_id(), msg);
+- return;
+- }
+- switch ( target )
+- {
+- case MSG_ALL:
+- mpic_send_ipi(msg, 0xffffffff);
+- break;
+- case MSG_ALL_BUT_SELF:
+- mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
+- break;
+- default:
+- mpic_send_ipi(msg, 1 << target);
+- break;
+- }
+-}
+-
+ int __init smp_mpic_probe(void)
+ {
+ int nr_cpus;
+@@ -128,21 +105,6 @@ void __devinit smp_generic_kick_cpu(int
+
+ #endif /* CONFIG_MPIC */
+
+-static void __init smp_space_timers(unsigned int max_cpus)
+-{
+- int i;
+- unsigned long offset = tb_ticks_per_jiffy / max_cpus;
+- unsigned long previous_tb = paca[boot_cpuid].next_jiffy_update_tb;
+-
+- for_each_cpu(i) {
+- if (i != boot_cpuid) {
+- paca[i].next_jiffy_update_tb =
+- previous_tb + offset;
+- previous_tb = paca[i].next_jiffy_update_tb;
+- }
+- }
+-}
+-
+ void smp_message_recv(int msg, struct pt_regs *regs)
+ {
+ switch(msg) {
+diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/sys_ppc32.c
++++ /dev/null
+@@ -1,1222 +0,0 @@
+-/*
+- * sys_ppc32.c: Conversion between 32bit and 64bit native syscalls.
+- *
+- * Copyright (C) 2001 IBM
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1997 David S. Miller (davem at caip.rutgers.edu)
+- *
+- * These routines maintain argument size conversion between 32bit and 64bit
+- * environment.
+- *
+- * 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/fs.h>
+-#include <linux/mm.h>
+-#include <linux/file.h>
+-#include <linux/signal.h>
+-#include <linux/resource.h>
+-#include <linux/times.h>
+-#include <linux/utsname.h>
+-#include <linux/timex.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/sem.h>
+-#include <linux/msg.h>
+-#include <linux/shm.h>
+-#include <linux/poll.h>
+-#include <linux/personality.h>
+-#include <linux/stat.h>
+-#include <linux/mman.h>
+-#include <linux/in.h>
+-#include <linux/syscalls.h>
+-#include <linux/unistd.h>
+-#include <linux/sysctl.h>
+-#include <linux/binfmts.h>
+-#include <linux/security.h>
+-#include <linux/compat.h>
+-#include <linux/ptrace.h>
+-#include <linux/elf.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/types.h>
+-#include <asm/ipc.h>
+-#include <asm/uaccess.h>
+-#include <asm/unistd.h>
+-#include <asm/semaphore.h>
+-#include <asm/time.h>
+-#include <asm/mmu_context.h>
+-#include <asm/systemcfg.h>
+-
+-#include "pci.h"
+-
+-/* readdir & getdents */
+-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
+-#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
+-
+-struct old_linux_dirent32 {
+- u32 d_ino;
+- u32 d_offset;
+- unsigned short d_namlen;
+- char d_name[1];
+-};
+-
+-struct readdir_callback32 {
+- struct old_linux_dirent32 __user * dirent;
+- int count;
+-};
+-
+-static int fillonedir(void * __buf, const char * name, int namlen,
+- off_t offset, ino_t ino, unsigned int d_type)
+-{
+- struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
+- struct old_linux_dirent32 __user * dirent;
+-
+- if (buf->count)
+- return -EINVAL;
+- buf->count++;
+- dirent = buf->dirent;
+- put_user(ino, &dirent->d_ino);
+- put_user(offset, &dirent->d_offset);
+- put_user(namlen, &dirent->d_namlen);
+- copy_to_user(dirent->d_name, name, namlen);
+- put_user(0, dirent->d_name + namlen);
+- return 0;
+-}
+-
+-asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 __user *dirent, unsigned int count)
+-{
+- int error = -EBADF;
+- struct file * file;
+- struct readdir_callback32 buf;
+-
+- file = fget(fd);
+- if (!file)
+- goto out;
+-
+- buf.count = 0;
+- buf.dirent = dirent;
+-
+- error = vfs_readdir(file, (filldir_t)fillonedir, &buf);
+- if (error < 0)
+- goto out_putf;
+- error = buf.count;
+-
+-out_putf:
+- fput(file);
+-out:
+- return error;
+-}
+-
+-struct linux_dirent32 {
+- u32 d_ino;
+- u32 d_off;
+- unsigned short d_reclen;
+- char d_name[1];
+-};
+-
+-struct getdents_callback32 {
+- struct linux_dirent32 __user * current_dir;
+- struct linux_dirent32 __user * previous;
+- int count;
+- int error;
+-};
+-
+-static int filldir(void * __buf, const char * name, int namlen, off_t offset,
+- ino_t ino, unsigned int d_type)
+-{
+- struct linux_dirent32 __user * dirent;
+- struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
+- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
+-
+- buf->error = -EINVAL; /* only used if we fail.. */
+- if (reclen > buf->count)
+- return -EINVAL;
+- dirent = buf->previous;
+- if (dirent) {
+- if (__put_user(offset, &dirent->d_off))
+- goto efault;
+- }
+- dirent = buf->current_dir;
+- if (__put_user(ino, &dirent->d_ino))
+- goto efault;
+- if (__put_user(reclen, &dirent->d_reclen))
+- goto efault;
+- if (copy_to_user(dirent->d_name, name, namlen))
+- goto efault;
+- if (__put_user(0, dirent->d_name + namlen))
+- goto efault;
+- if (__put_user(d_type, (char __user *) dirent + reclen - 1))
+- goto efault;
+- buf->previous = dirent;
+- dirent = (void __user *)dirent + reclen;
+- buf->current_dir = dirent;
+- buf->count -= reclen;
+- return 0;
+-efault:
+- buf->error = -EFAULT;
+- return -EFAULT;
+-}
+-
+-asmlinkage long sys32_getdents(unsigned int fd, struct linux_dirent32 __user *dirent,
+- unsigned int count)
+-{
+- struct file * file;
+- struct linux_dirent32 __user * lastdirent;
+- struct getdents_callback32 buf;
+- int error;
+-
+- error = -EFAULT;
+- if (!access_ok(VERIFY_WRITE, dirent, count))
+- goto out;
+-
+- error = -EBADF;
+- file = fget(fd);
+- if (!file)
+- goto out;
+-
+- buf.current_dir = dirent;
+- buf.previous = NULL;
+- buf.count = count;
+- buf.error = 0;
+-
+- error = vfs_readdir(file, (filldir_t)filldir, &buf);
+- if (error < 0)
+- goto out_putf;
+- error = buf.error;
+- lastdirent = buf.previous;
+- if (lastdirent) {
+- if (put_user(file->f_pos, &lastdirent->d_off))
+- error = -EFAULT;
+- else
+- error = count - buf.count;
+- }
+-
+-out_putf:
+- fput(file);
+-out:
+- return error;
+-}
+-
+-asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
+- compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+- compat_uptr_t tvp_x)
+-{
+- /* sign extend n */
+- return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
+-}
+-
+-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
+-{
+- long err;
+-
+- if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
+- !new_valid_dev(stat->rdev))
+- return -EOVERFLOW;
+-
+- err = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
+- err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
+- err |= __put_user(stat->ino, &statbuf->st_ino);
+- err |= __put_user(stat->mode, &statbuf->st_mode);
+- err |= __put_user(stat->nlink, &statbuf->st_nlink);
+- err |= __put_user(stat->uid, &statbuf->st_uid);
+- err |= __put_user(stat->gid, &statbuf->st_gid);
+- err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
+- err |= __put_user(stat->size, &statbuf->st_size);
+- err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime);
+- err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
+- err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
+- err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
+- err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
+- err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
+- err |= __put_user(stat->blksize, &statbuf->st_blksize);
+- err |= __put_user(stat->blocks, &statbuf->st_blocks);
+- err |= __put_user(0, &statbuf->__unused4[0]);
+- err |= __put_user(0, &statbuf->__unused4[1]);
+-
+- return err;
+-}
+-
+-/* Note: it is necessary to treat option as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sysfs(u32 option, u32 arg1, u32 arg2)
+-{
+- return sys_sysfs((int)option, arg1, arg2);
+-}
+-
+-/* Handle adjtimex compatibility. */
+-struct timex32 {
+- u32 modes;
+- s32 offset, freq, maxerror, esterror;
+- s32 status, constant, precision, tolerance;
+- struct compat_timeval time;
+- s32 tick;
+- s32 ppsfreq, jitter, shift, stabil;
+- s32 jitcnt, calcnt, errcnt, stbcnt;
+- s32 :32; s32 :32; s32 :32; s32 :32;
+- s32 :32; s32 :32; s32 :32; s32 :32;
+- s32 :32; s32 :32; s32 :32; s32 :32;
+-};
+-
+-extern int do_adjtimex(struct timex *);
+-extern void ppc_adjtimex(void);
+-
+-asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
+-{
+- struct timex txc;
+- int ret;
+-
+- memset(&txc, 0, sizeof(struct timex));
+-
+- if(get_user(txc.modes, &utp->modes) ||
+- __get_user(txc.offset, &utp->offset) ||
+- __get_user(txc.freq, &utp->freq) ||
+- __get_user(txc.maxerror, &utp->maxerror) ||
+- __get_user(txc.esterror, &utp->esterror) ||
+- __get_user(txc.status, &utp->status) ||
+- __get_user(txc.constant, &utp->constant) ||
+- __get_user(txc.precision, &utp->precision) ||
+- __get_user(txc.tolerance, &utp->tolerance) ||
+- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+- __get_user(txc.tick, &utp->tick) ||
+- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
+- __get_user(txc.jitter, &utp->jitter) ||
+- __get_user(txc.shift, &utp->shift) ||
+- __get_user(txc.stabil, &utp->stabil) ||
+- __get_user(txc.jitcnt, &utp->jitcnt) ||
+- __get_user(txc.calcnt, &utp->calcnt) ||
+- __get_user(txc.errcnt, &utp->errcnt) ||
+- __get_user(txc.stbcnt, &utp->stbcnt))
+- return -EFAULT;
+-
+- ret = do_adjtimex(&txc);
+-
+- /* adjust the conversion of TB to time of day to track adjtimex */
+- ppc_adjtimex();
+-
+- if(put_user(txc.modes, &utp->modes) ||
+- __put_user(txc.offset, &utp->offset) ||
+- __put_user(txc.freq, &utp->freq) ||
+- __put_user(txc.maxerror, &utp->maxerror) ||
+- __put_user(txc.esterror, &utp->esterror) ||
+- __put_user(txc.status, &utp->status) ||
+- __put_user(txc.constant, &utp->constant) ||
+- __put_user(txc.precision, &utp->precision) ||
+- __put_user(txc.tolerance, &utp->tolerance) ||
+- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+- __put_user(txc.tick, &utp->tick) ||
+- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
+- __put_user(txc.jitter, &utp->jitter) ||
+- __put_user(txc.shift, &utp->shift) ||
+- __put_user(txc.stabil, &utp->stabil) ||
+- __put_user(txc.jitcnt, &utp->jitcnt) ||
+- __put_user(txc.calcnt, &utp->calcnt) ||
+- __put_user(txc.errcnt, &utp->errcnt) ||
+- __put_user(txc.stbcnt, &utp->stbcnt))
+- ret = -EFAULT;
+-
+- return ret;
+-}
+-
+-asmlinkage long sys32_pause(void)
+-{
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+-
+- return -ERESTARTNOHAND;
+-}
+-
+-static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
+-{
+- long usec;
+-
+- if (!access_ok(VERIFY_READ, i, sizeof(*i)))
+- return -EFAULT;
+- if (__get_user(o->tv_sec, &i->tv_sec))
+- return -EFAULT;
+- if (__get_user(usec, &i->tv_usec))
+- return -EFAULT;
+- o->tv_nsec = usec * 1000;
+- return 0;
+-}
+-
+-static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
+-{
+- return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
+- (__put_user(i->tv_sec, &o->tv_sec) |
+- __put_user(i->tv_usec, &o->tv_usec)));
+-}
+-
+-struct sysinfo32 {
+- s32 uptime;
+- u32 loads[3];
+- u32 totalram;
+- u32 freeram;
+- u32 sharedram;
+- u32 bufferram;
+- u32 totalswap;
+- u32 freeswap;
+- unsigned short procs;
+- unsigned short pad;
+- u32 totalhigh;
+- u32 freehigh;
+- u32 mem_unit;
+- char _f[20-2*sizeof(int)-sizeof(int)];
+-};
+-
+-asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info)
+-{
+- struct sysinfo s;
+- int ret, err;
+- int bitcount=0;
+- mm_segment_t old_fs = get_fs ();
+-
+- /* The __user cast is valid due to set_fs() */
+- set_fs (KERNEL_DS);
+- ret = sys_sysinfo((struct sysinfo __user *)&s);
+- set_fs (old_fs);
+-
+- /* Check to see if any memory value is too large for 32-bit and
+- * scale down if needed.
+- */
+- if ((s.totalram >> 32) || (s.totalswap >> 32)) {
+- while (s.mem_unit < PAGE_SIZE) {
+- s.mem_unit <<= 1;
+- bitcount++;
+- }
+- s.totalram >>=bitcount;
+- s.freeram >>= bitcount;
+- s.sharedram >>= bitcount;
+- s.bufferram >>= bitcount;
+- s.totalswap >>= bitcount;
+- s.freeswap >>= bitcount;
+- s.totalhigh >>= bitcount;
+- s.freehigh >>= bitcount;
+- }
+-
+- err = put_user (s.uptime, &info->uptime);
+- err |= __put_user (s.loads[0], &info->loads[0]);
+- err |= __put_user (s.loads[1], &info->loads[1]);
+- err |= __put_user (s.loads[2], &info->loads[2]);
+- err |= __put_user (s.totalram, &info->totalram);
+- err |= __put_user (s.freeram, &info->freeram);
+- err |= __put_user (s.sharedram, &info->sharedram);
+- err |= __put_user (s.bufferram, &info->bufferram);
+- err |= __put_user (s.totalswap, &info->totalswap);
+- err |= __put_user (s.freeswap, &info->freeswap);
+- err |= __put_user (s.procs, &info->procs);
+- err |= __put_user (s.totalhigh, &info->totalhigh);
+- err |= __put_user (s.freehigh, &info->freehigh);
+- err |= __put_user (s.mem_unit, &info->mem_unit);
+- if (err)
+- return -EFAULT;
+-
+- return ret;
+-}
+-
+-
+-
+-
+-/* Translations due to time_t size differences. Which affects all
+- sorts of things, like timeval and itimerval. */
+-extern struct timezone sys_tz;
+-
+-asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
+-{
+- if (tv) {
+- struct timeval ktv;
+- do_gettimeofday(&ktv);
+- if (put_tv32(tv, &ktv))
+- return -EFAULT;
+- }
+- if (tz) {
+- if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+- return -EFAULT;
+- }
+-
+- return 0;
+-}
+-
+-
+-
+-asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
+-{
+- struct timespec kts;
+- struct timezone ktz;
+-
+- if (tv) {
+- if (get_ts32(&kts, tv))
+- return -EFAULT;
+- }
+- if (tz) {
+- if (copy_from_user(&ktz, tz, sizeof(ktz)))
+- return -EFAULT;
+- }
+-
+- return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
+-}
+-
+-#ifdef CONFIG_SYSVIPC
+-long sys32_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
+- u32 fifth)
+-{
+- int version;
+-
+- version = call >> 16; /* hack for backward compatibility */
+- call &= 0xffff;
+-
+- switch (call) {
+-
+- case SEMTIMEDOP:
+- if (fifth)
+- /* sign extend semid */
+- return compat_sys_semtimedop((int)first,
+- compat_ptr(ptr), second,
+- compat_ptr(fifth));
+- /* else fall through for normal semop() */
+- case SEMOP:
+- /* struct sembuf is the same on 32 and 64bit :)) */
+- /* sign extend semid */
+- return sys_semtimedop((int)first, compat_ptr(ptr), second,
+- NULL);
+- case SEMGET:
+- /* sign extend key, nsems */
+- return sys_semget((int)first, (int)second, third);
+- case SEMCTL:
+- /* sign extend semid, semnum */
+- return compat_sys_semctl((int)first, (int)second, third,
+- compat_ptr(ptr));
+-
+- case MSGSND:
+- /* sign extend msqid */
+- return compat_sys_msgsnd((int)first, (int)second, third,
+- compat_ptr(ptr));
+- case MSGRCV:
+- /* sign extend msqid, msgtyp */
+- return compat_sys_msgrcv((int)first, second, (int)fifth,
+- third, version, compat_ptr(ptr));
+- case MSGGET:
+- /* sign extend key */
+- return sys_msgget((int)first, second);
+- case MSGCTL:
+- /* sign extend msqid */
+- return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
+-
+- case SHMAT:
+- /* sign extend shmid */
+- return compat_sys_shmat((int)first, second, third, version,
+- compat_ptr(ptr));
+- case SHMDT:
+- return sys_shmdt(compat_ptr(ptr));
+- case SHMGET:
+- /* sign extend key_t */
+- return sys_shmget((int)first, second, third);
+- case SHMCTL:
+- /* sign extend shmid */
+- return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
+-
+- default:
+- return -ENOSYS;
+- }
+-
+- return -ENOSYS;
+-}
+-#endif
+-
+-/* Note: it is necessary to treat out_fd and in_fd as unsigned ints,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sendfile(u32 out_fd, u32 in_fd, compat_off_t __user * offset, u32 count)
+-{
+- mm_segment_t old_fs = get_fs();
+- int ret;
+- off_t of;
+- off_t __user *up;
+-
+- if (offset && get_user(of, offset))
+- return -EFAULT;
+-
+- /* The __user pointer cast is valid because of the set_fs() */
+- set_fs(KERNEL_DS);
+- up = offset ? (off_t __user *) &of : NULL;
+- ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
+- set_fs(old_fs);
+-
+- if (offset && put_user(of, offset))
+- return -EFAULT;
+-
+- return ret;
+-}
+-
+-asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
+-{
+- mm_segment_t old_fs = get_fs();
+- int ret;
+- loff_t lof;
+- loff_t __user *up;
+-
+- if (offset && get_user(lof, offset))
+- return -EFAULT;
+-
+- /* The __user pointer cast is valid because of the set_fs() */
+- set_fs(KERNEL_DS);
+- up = offset ? (loff_t __user *) &lof : NULL;
+- ret = sys_sendfile64(out_fd, in_fd, up, count);
+- set_fs(old_fs);
+-
+- if (offset && put_user(lof, offset))
+- return -EFAULT;
+-
+- return ret;
+-}
+-
+-long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+- unsigned long a3, unsigned long a4, unsigned long a5,
+- struct pt_regs *regs)
+-{
+- int error;
+- char * filename;
+-
+- filename = getname((char __user *) a0);
+- error = PTR_ERR(filename);
+- if (IS_ERR(filename))
+- goto out;
+- flush_fp_to_thread(current);
+- flush_altivec_to_thread(current);
+-
+- error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
+-
+- if (error == 0) {
+- task_lock(current);
+- current->ptrace &= ~PT_DTRACE;
+- task_unlock(current);
+- }
+- putname(filename);
+-
+-out:
+- return error;
+-}
+-
+-/* Set up a thread for executing a new program. */
+-void start_thread32(struct pt_regs* regs, unsigned long nip, unsigned long sp)
+-{
+- set_fs(USER_DS);
+-
+- /*
+- * If we exec out of a kernel thread then thread.regs will not be
+- * set. Do it now.
+- */
+- if (!current->thread.regs) {
+- unsigned long childregs = (unsigned long)current->thread_info +
+- THREAD_SIZE;
+- childregs -= sizeof(struct pt_regs);
+- current->thread.regs = (struct pt_regs *)childregs;
+- }
+-
+- /*
+- * ELF_PLAT_INIT already clears all registers but it also sets r2.
+- * So just clear r2 here.
+- */
+- regs->gpr[2] = 0;
+-
+- regs->nip = nip;
+- regs->gpr[1] = sp;
+- regs->msr = MSR_USER32;
+-#ifndef CONFIG_SMP
+- if (last_task_used_math == current)
+- last_task_used_math = 0;
+-#endif /* CONFIG_SMP */
+- current->thread.fpscr = 0;
+- memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
+-#ifdef CONFIG_ALTIVEC
+-#ifndef CONFIG_SMP
+- if (last_task_used_altivec == current)
+- last_task_used_altivec = 0;
+-#endif /* CONFIG_SMP */
+- memset(current->thread.vr, 0, sizeof(current->thread.vr));
+- current->thread.vscr.u[0] = 0;
+- current->thread.vscr.u[1] = 0;
+- current->thread.vscr.u[2] = 0;
+- current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */
+- current->thread.vrsave = 0;
+- current->thread.used_vr = 0;
+-#endif /* CONFIG_ALTIVEC */
+-}
+-
+-/* Note: it is necessary to treat option as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+-{
+- return sys_prctl((int)option,
+- (unsigned long) arg2,
+- (unsigned long) arg3,
+- (unsigned long) arg4,
+- (unsigned long) arg5);
+-}
+-
+-/* Note: it is necessary to treat pid as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
+-{
+- struct timespec t;
+- int ret;
+- mm_segment_t old_fs = get_fs ();
+-
+- /* The __user pointer cast is valid because of the set_fs() */
+- set_fs (KERNEL_DS);
+- ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
+- set_fs (old_fs);
+- if (put_compat_timespec(&t, interval))
+- return -EFAULT;
+- return ret;
+-}
+-
+-asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
+-{
+- return sys_pciconfig_read((unsigned long) bus,
+- (unsigned long) dfn,
+- (unsigned long) off,
+- (unsigned long) len,
+- compat_ptr(ubuf));
+-}
+-
+-asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
+-{
+- return sys_pciconfig_write((unsigned long) bus,
+- (unsigned long) dfn,
+- (unsigned long) off,
+- (unsigned long) len,
+- compat_ptr(ubuf));
+-}
+-
+-asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
+-{
+- return sys_pciconfig_iobase(which, in_bus, in_devfn);
+-}
+-
+-
+-/* Note: it is necessary to treat mode as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_access(const char __user * filename, u32 mode)
+-{
+- return sys_access(filename, (int)mode);
+-}
+-
+-
+-/* Note: it is necessary to treat mode as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_creat(const char __user * pathname, u32 mode)
+-{
+- return sys_creat(pathname, (int)mode);
+-}
+-
+-
+-/* Note: it is necessary to treat pid and options as unsigned ints,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_waitpid(u32 pid, unsigned int __user * stat_addr, u32 options)
+-{
+- return sys_waitpid((int)pid, stat_addr, (int)options);
+-}
+-
+-
+-/* Note: it is necessary to treat gidsetsize as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_getgroups(u32 gidsetsize, gid_t __user *grouplist)
+-{
+- return sys_getgroups((int)gidsetsize, grouplist);
+-}
+-
+-
+-/* Note: it is necessary to treat pid as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_getpgid(u32 pid)
+-{
+- return sys_getpgid((int)pid);
+-}
+-
+-
+-
+-/* Note: it is necessary to treat pid as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_getsid(u32 pid)
+-{
+- return sys_getsid((int)pid);
+-}
+-
+-
+-/* Note: it is necessary to treat pid and sig as unsigned ints,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_kill(u32 pid, u32 sig)
+-{
+- return sys_kill((int)pid, (int)sig);
+-}
+-
+-
+-/* Note: it is necessary to treat mode as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_mkdir(const char __user * pathname, u32 mode)
+-{
+- return sys_mkdir(pathname, (int)mode);
+-}
+-
+-long sys32_nice(u32 increment)
+-{
+- /* sign extend increment */
+- return sys_nice((int)increment);
+-}
+-
+-off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
+-{
+- /* sign extend n */
+- return sys_lseek(fd, (int)offset, origin);
+-}
+-
+-/* Note: it is necessary to treat bufsiz as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_readlink(const char __user * path, char __user * buf, u32 bufsiz)
+-{
+- return sys_readlink(path, buf, (int)bufsiz);
+-}
+-
+-/* Note: it is necessary to treat option as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sched_get_priority_max(u32 policy)
+-{
+- return sys_sched_get_priority_max((int)policy);
+-}
+-
+-
+-/* Note: it is necessary to treat policy as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sched_get_priority_min(u32 policy)
+-{
+- return sys_sched_get_priority_min((int)policy);
+-}
+-
+-
+-/* Note: it is necessary to treat pid as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sched_getparam(u32 pid, struct sched_param __user *param)
+-{
+- return sys_sched_getparam((int)pid, param);
+-}
+-
+-
+-/* Note: it is necessary to treat pid as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sched_getscheduler(u32 pid)
+-{
+- return sys_sched_getscheduler((int)pid);
+-}
+-
+-
+-/* Note: it is necessary to treat pid as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sched_setparam(u32 pid, struct sched_param __user *param)
+-{
+- return sys_sched_setparam((int)pid, param);
+-}
+-
+-
+-/* Note: it is necessary to treat pid and policy as unsigned ints,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_sched_setscheduler(u32 pid, u32 policy, struct sched_param __user *param)
+-{
+- return sys_sched_setscheduler((int)pid, (int)policy, param);
+-}
+-
+-
+-/* Note: it is necessary to treat len as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_setdomainname(char __user *name, u32 len)
+-{
+- return sys_setdomainname(name, (int)len);
+-}
+-
+-
+-/* Note: it is necessary to treat gidsetsize as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_setgroups(u32 gidsetsize, gid_t __user *grouplist)
+-{
+- return sys_setgroups((int)gidsetsize, grouplist);
+-}
+-
+-
+-asmlinkage long sys32_sethostname(char __user *name, u32 len)
+-{
+- /* sign extend len */
+- return sys_sethostname(name, (int)len);
+-}
+-
+-
+-/* Note: it is necessary to treat pid and pgid as unsigned ints,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_setpgid(u32 pid, u32 pgid)
+-{
+- return sys_setpgid((int)pid, (int)pgid);
+-}
+-
+-long sys32_getpriority(u32 which, u32 who)
+-{
+- /* sign extend which and who */
+- return sys_getpriority((int)which, (int)who);
+-}
+-
+-long sys32_setpriority(u32 which, u32 who, u32 niceval)
+-{
+- /* sign extend which, who and niceval */
+- return sys_setpriority((int)which, (int)who, (int)niceval);
+-}
+-
+-long sys32_ioprio_get(u32 which, u32 who)
+-{
+- /* sign extend which and who */
+- return sys_ioprio_get((int)which, (int)who);
+-}
+-
+-long sys32_ioprio_set(u32 which, u32 who, u32 ioprio)
+-{
+- /* sign extend which, who and ioprio */
+- return sys_ioprio_set((int)which, (int)who, (int)ioprio);
+-}
+-
+-/* Note: it is necessary to treat newmask as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_ssetmask(u32 newmask)
+-{
+- return sys_ssetmask((int) newmask);
+-}
+-
+-asmlinkage long sys32_syslog(u32 type, char __user * buf, u32 len)
+-{
+- /* sign extend len */
+- return sys_syslog(type, buf, (int)len);
+-}
+-
+-
+-/* Note: it is necessary to treat mask as an unsigned int,
+- * with the corresponding cast to a signed int to insure that the
+- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
+- * and the register representation of a signed int (msr in 64-bit mode) is performed.
+- */
+-asmlinkage long sys32_umask(u32 mask)
+-{
+- return sys_umask((int)mask);
+-}
+-
+-#ifdef CONFIG_SYSCTL
+-struct __sysctl_args32 {
+- u32 name;
+- int nlen;
+- u32 oldval;
+- u32 oldlenp;
+- u32 newval;
+- u32 newlen;
+- u32 __unused[4];
+-};
+-
+-asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
+-{
+- struct __sysctl_args32 tmp;
+- int error;
+- size_t oldlen;
+- size_t __user *oldlenp = NULL;
+- unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
+-
+- if (copy_from_user(&tmp, args, sizeof(tmp)))
+- return -EFAULT;
+-
+- if (tmp.oldval && tmp.oldlenp) {
+- /* Duh, this is ugly and might not work if sysctl_args
+- is in read-only memory, but do_sysctl does indirectly
+- a lot of uaccess in both directions and we'd have to
+- basically copy the whole sysctl.c here, and
+- glibc's __sysctl uses rw memory for the structure
+- anyway. */
+- oldlenp = (size_t __user *)addr;
+- if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
+- put_user(oldlen, oldlenp))
+- return -EFAULT;
+- }
+-
+- lock_kernel();
+- error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
+- compat_ptr(tmp.oldval), oldlenp,
+- compat_ptr(tmp.newval), tmp.newlen);
+- unlock_kernel();
+- if (oldlenp) {
+- if (!error) {
+- if (get_user(oldlen, oldlenp) ||
+- put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
+- error = -EFAULT;
+- }
+- copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
+- }
+- return error;
+-}
+-#endif
+-
+-asmlinkage int sys32_uname(struct old_utsname __user * name)
+-{
+- int err = 0;
+-
+- down_read(&uts_sem);
+- if (copy_to_user(name, &system_utsname, sizeof(*name)))
+- err = -EFAULT;
+- up_read(&uts_sem);
+- if (!err && personality(current->personality) == PER_LINUX32) {
+- /* change "ppc64" to "ppc" */
+- if (__put_user(0, name->machine + 3)
+- || __put_user(0, name->machine + 4))
+- err = -EFAULT;
+- }
+- return err;
+-}
+-
+-asmlinkage int sys32_olduname(struct oldold_utsname __user * name)
+-{
+- int error;
+-
+- if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+- return -EFAULT;
+-
+- down_read(&uts_sem);
+- error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+- error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+- error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+- error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+- error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+- error |= __put_user(0,name->release+__OLD_UTS_LEN);
+- error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+- error |= __put_user(0,name->version+__OLD_UTS_LEN);
+- error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+- error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+- if (personality(current->personality) == PER_LINUX32) {
+- /* change "ppc64" to "ppc" */
+- error |= __put_user(0, name->machine + 3);
+- error |= __put_user(0, name->machine + 4);
+- }
+-
+- up_read(&uts_sem);
+-
+- error = error ? -EFAULT : 0;
+-
+- return error;
+-}
+-
+-unsigned long sys32_mmap2(unsigned long addr, size_t len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, unsigned long pgoff)
+-{
+- /* This should remain 12 even if PAGE_SIZE changes */
+- return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
+-}
+-
+-int get_compat_timeval(struct timeval *tv, struct compat_timeval __user *ctv)
+-{
+- return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
+- __get_user(tv->tv_sec, &ctv->tv_sec) ||
+- __get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
+-}
+-
+-asmlinkage long sys32_utimes(char __user *filename, struct compat_timeval __user *tvs)
+-{
+- struct timeval ktvs[2], *ptr;
+-
+- ptr = NULL;
+- if (tvs) {
+- if (get_compat_timeval(&ktvs[0], &tvs[0]) ||
+- get_compat_timeval(&ktvs[1], &tvs[1]))
+- return -EFAULT;
+- ptr = ktvs;
+- }
+-
+- return do_utimes(filename, ptr);
+-}
+-
+-long sys32_tgkill(u32 tgid, u32 pid, int sig)
+-{
+- /* sign extend tgid, pid */
+- return sys_tgkill((int)tgid, (int)pid, sig);
+-}
+-
+-/*
+- * long long munging:
+- * The 32 bit ABI passes long longs in an odd even register pair.
+- */
+-
+-compat_ssize_t sys32_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
+- u32 reg6, u32 poshi, u32 poslo)
+-{
+- return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
+-}
+-
+-compat_ssize_t sys32_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count,
+- u32 reg6, u32 poshi, u32 poslo)
+-{
+- return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
+-}
+-
+-compat_ssize_t sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
+-{
+- return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
+-}
+-
+-asmlinkage int sys32_truncate64(const char __user * path, u32 reg4,
+- unsigned long high, unsigned long low)
+-{
+- return sys_truncate(path, (high << 32) | low);
+-}
+-
+-asmlinkage int sys32_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
+- unsigned long low)
+-{
+- return sys_ftruncate(fd, (high << 32) | low);
+-}
+-
+-long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
+- size_t len)
+-{
+- return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
+- buf, len);
+-}
+-
+-long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
+- size_t len, int advice)
+-{
+- return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len,
+- advice);
+-}
+-
+-long ppc32_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
+- u32 len_high, u32 len_low)
+-{
+- return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low,
+- (u64)len_high << 32 | len_low, advice);
+-}
+-
+-long ppc32_timer_create(clockid_t clock,
+- struct compat_sigevent __user *ev32,
+- timer_t __user *timer_id)
+-{
+- sigevent_t event;
+- timer_t t;
+- long err;
+- mm_segment_t savefs;
+-
+- if (ev32 == NULL)
+- return sys_timer_create(clock, NULL, timer_id);
+-
+- if (get_compat_sigevent(&event, ev32))
+- return -EFAULT;
+-
+- if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
+- return -EFAULT;
+-
+- savefs = get_fs();
+- set_fs(KERNEL_DS);
+- /* The __user pointer casts are valid due to the set_fs() */
+- err = sys_timer_create(clock,
+- (sigevent_t __user *) &event,
+- (timer_t __user *) &t);
+- set_fs(savefs);
+-
+- if (err == 0)
+- err = __put_user(t, timer_id);
+-
+- return err;
+-}
+-
+-asmlinkage long sys32_add_key(const char __user *_type,
+- const char __user *_description,
+- const void __user *_payload,
+- u32 plen,
+- u32 ringid)
+-{
+- return sys_add_key(_type, _description, _payload, plen, ringid);
+-}
+-
+-asmlinkage long sys32_request_key(const char __user *_type,
+- const char __user *_description,
+- const char __user *_callout_info,
+- u32 destringid)
+-{
+- return sys_request_key(_type, _description, _callout_info, destringid);
+-}
+-
+diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/syscalls.c
++++ /dev/null
+@@ -1,263 +0,0 @@
+-/*
+- * linux/arch/ppc64/kernel/sys_ppc.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Derived from "arch/i386/kernel/sys_i386.c"
+- * Adapted from the i386 version by Gary Thomas
+- * Modified by Cort Dougan (cort at cs.nmt.edu)
+- * and Paul Mackerras (paulus at cs.anu.edu.au).
+- *
+- * This file contains various random system calls that
+- * have a non-standard calling sequence on the Linux/PPC
+- * platform.
+- *
+- * 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/errno.h>
+-#include <linux/sched.h>
+-#include <linux/syscalls.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/sem.h>
+-#include <linux/msg.h>
+-#include <linux/shm.h>
+-#include <linux/stat.h>
+-#include <linux/mman.h>
+-#include <linux/sys.h>
+-#include <linux/ipc.h>
+-#include <linux/utsname.h>
+-#include <linux/file.h>
+-#include <linux/init.h>
+-#include <linux/personality.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/ipc.h>
+-#include <asm/semaphore.h>
+-#include <asm/time.h>
+-#include <asm/unistd.h>
+-
+-extern unsigned long wall_jiffies;
+-
+-
+-/*
+- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+- *
+- * This is really horribly ugly.
+- */
+-asmlinkage int
+-sys_ipc (uint call, int first, unsigned long second, long third,
+- void __user *ptr, long fifth)
+-{
+- int version, ret;
+-
+- version = call >> 16; /* hack for backward compatibility */
+- call &= 0xffff;
+-
+- ret = -ENOSYS;
+- switch (call) {
+- case SEMOP:
+- ret = sys_semtimedop(first, (struct sembuf __user *)ptr,
+- (unsigned)second, NULL);
+- break;
+- case SEMTIMEDOP:
+- ret = sys_semtimedop(first, (struct sembuf __user *)ptr,
+- (unsigned)second,
+- (const struct timespec __user *) fifth);
+- break;
+- case SEMGET:
+- ret = sys_semget (first, (int)second, third);
+- break;
+- case SEMCTL: {
+- union semun fourth;
+-
+- ret = -EINVAL;
+- if (!ptr)
+- break;
+- if ((ret = get_user(fourth.__pad, (void __user * __user *)ptr)))
+- break;
+- ret = sys_semctl(first, (int)second, third, fourth);
+- break;
+- }
+- case MSGSND:
+- ret = sys_msgsnd(first, (struct msgbuf __user *)ptr,
+- (size_t)second, third);
+- break;
+- case MSGRCV:
+- switch (version) {
+- case 0: {
+- struct ipc_kludge tmp;
+-
+- ret = -EINVAL;
+- if (!ptr)
+- break;
+- if ((ret = copy_from_user(&tmp,
+- (struct ipc_kludge __user *) ptr,
+- sizeof (tmp)) ? -EFAULT : 0))
+- break;
+- ret = sys_msgrcv(first, tmp.msgp, (size_t) second,
+- tmp.msgtyp, third);
+- break;
+- }
+- default:
+- ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
+- (size_t)second, fifth, third);
+- break;
+- }
+- break;
+- case MSGGET:
+- ret = sys_msgget ((key_t)first, (int)second);
+- break;
+- case MSGCTL:
+- ret = sys_msgctl(first, (int)second,
+- (struct msqid_ds __user *)ptr);
+- break;
+- case SHMAT:
+- switch (version) {
+- default: {
+- ulong raddr;
+- ret = do_shmat(first, (char __user *) ptr,
+- (int)second, &raddr);
+- if (ret)
+- break;
+- ret = put_user (raddr, (ulong __user *) third);
+- break;
+- }
+- case 1: /* iBCS2 emulator entry point */
+- ret = -EINVAL;
+- if (!segment_eq(get_fs(), get_ds()))
+- break;
+- ret = do_shmat(first, (char __user *)ptr,
+- (int)second, (ulong *)third);
+- break;
+- }
+- break;
+- case SHMDT:
+- ret = sys_shmdt ((char __user *)ptr);
+- break;
+- case SHMGET:
+- ret = sys_shmget (first, (size_t)second, third);
+- break;
+- case SHMCTL:
+- ret = sys_shmctl(first, (int)second,
+- (struct shmid_ds __user *)ptr);
+- break;
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * sys_pipe() is the normal C calling standard for creating
+- * a pipe. It's not the way unix traditionally does this, though.
+- */
+-asmlinkage int sys_pipe(int __user *fildes)
+-{
+- int fd[2];
+- int error;
+-
+- error = do_pipe(fd);
+- if (!error) {
+- if (copy_to_user(fildes, fd, 2*sizeof(int)))
+- error = -EFAULT;
+- }
+-
+- return error;
+-}
+-
+-unsigned long sys_mmap(unsigned long addr, size_t len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, off_t offset)
+-{
+- struct file * file = NULL;
+- unsigned long ret = -EBADF;
+-
+- if (!(flags & MAP_ANONYMOUS)) {
+- if (!(file = fget(fd)))
+- goto out;
+- }
+-
+- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+- down_write(¤t->mm->mmap_sem);
+- ret = do_mmap(file, addr, len, prot, flags, offset);
+- up_write(¤t->mm->mmap_sem);
+- if (file)
+- fput(file);
+-
+-out:
+- return ret;
+-}
+-
+-long ppc64_personality(unsigned long personality)
+-{
+- long ret;
+-
+- if (personality(current->personality) == PER_LINUX32
+- && personality == PER_LINUX)
+- personality = PER_LINUX32;
+- ret = sys_personality(personality);
+- if (ret == PER_LINUX32)
+- ret = PER_LINUX;
+- return ret;
+-}
+-
+-long ppc64_newuname(struct new_utsname __user * name)
+-{
+- int err = 0;
+-
+- down_read(&uts_sem);
+- if (copy_to_user(name, &system_utsname, sizeof(*name)))
+- err = -EFAULT;
+- up_read(&uts_sem);
+- if (!err && personality(current->personality) == PER_LINUX32) {
+- /* change ppc64 to ppc */
+- if (__put_user(0, name->machine + 3)
+- || __put_user(0, name->machine + 4))
+- err = -EFAULT;
+- }
+- return err;
+-}
+-
+-asmlinkage time_t sys64_time(time_t __user * tloc)
+-{
+- time_t secs;
+- time_t usecs;
+-
+- long tb_delta = tb_ticks_since(tb_last_stamp);
+- tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
+-
+- secs = xtime.tv_sec;
+- usecs = (xtime.tv_nsec/1000) + tb_delta / tb_ticks_per_usec;
+- while (usecs >= USEC_PER_SEC) {
+- ++secs;
+- usecs -= USEC_PER_SEC;
+- }
+-
+- if (tloc) {
+- if (put_user(secs,tloc))
+- secs = -EFAULT;
+- }
+-
+- return secs;
+-}
+-
+-void do_show_syscall(unsigned long r3, unsigned long r4, unsigned long r5,
+- unsigned long r6, unsigned long r7, unsigned long r8,
+- struct pt_regs *regs)
+-{
+- printk("syscall %ld(%lx, %lx, %lx, %lx, %lx, %lx) regs=%p current=%p"
+- " cpu=%d\n", regs->gpr[0], r3, r4, r5, r6, r7, r8, regs,
+- current, smp_processor_id());
+-}
+-
+-void do_show_syscall_exit(unsigned long r3)
+-{
+- printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id());
+-}
+diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/time.c
++++ /dev/null
+@@ -1,881 +0,0 @@
+-/*
+- *
+- * Common time routines among all ppc machines.
+- *
+- * Written by Cort Dougan (cort at cs.nmt.edu) to merge
+- * Paul Mackerras' version and mine for PReP and Pmac.
+- * MPC8xx/MBX changes by Dan Malek (dmalek at jlc.net).
+- * Converted for 64-bit by Mike Corrigan (mikejc at us.ibm.com)
+- *
+- * First round of bugfixes by Gabriel Paubert (paubert at iram.es)
+- * to make clock more stable (2.4.0-test5). The only thing
+- * that this code assumes is that the timebases have been synchronized
+- * by firmware on SMP and are never stopped (never do sleep
+- * on SMP then, nap and doze are OK).
+- *
+- * Speeded up do_gettimeofday by getting rid of references to
+- * xtime (which required locks for consistency). (mikejc at us.ibm.com)
+- *
+- * TODO (not necessarily in this file):
+- * - improve precision and reproducibility of timebase frequency
+- * measurement at boot time. (for iSeries, we calibrate the timebase
+- * against the Titan chip's clock.)
+- * - for astronomical applications: add a new function to get
+- * non ambiguous timestamps even around leap seconds. This needs
+- * a new timestamp format and a good name.
+- *
+- * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
+- * "A Kernel Model for Precision Timekeeping" by Dave Mills
+- *
+- * 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/errno.h>
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/interrupt.h>
+-#include <linux/timex.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/time.h>
+-#include <linux/init.h>
+-#include <linux/profile.h>
+-#include <linux/cpu.h>
+-#include <linux/security.h>
+-
+-#include <asm/io.h>
+-#include <asm/processor.h>
+-#include <asm/nvram.h>
+-#include <asm/cache.h>
+-#include <asm/machdep.h>
+-#ifdef CONFIG_PPC_ISERIES
+-#include <asm/iSeries/ItLpQueue.h>
+-#include <asm/iSeries/HvCallXm.h>
+-#endif
+-#include <asm/uaccess.h>
+-#include <asm/time.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/prom.h>
+-#include <asm/sections.h>
+-#include <asm/systemcfg.h>
+-#include <asm/firmware.h>
+-
+-u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
+-
+-EXPORT_SYMBOL(jiffies_64);
+-
+-/* keep track of when we need to update the rtc */
+-time_t last_rtc_update;
+-extern int piranha_simulator;
+-#ifdef CONFIG_PPC_ISERIES
+-unsigned long iSeries_recal_titan = 0;
+-unsigned long iSeries_recal_tb = 0;
+-static unsigned long first_settimeofday = 1;
+-#endif
+-
+-#define XSEC_PER_SEC (1024*1024)
+-
+-unsigned long tb_ticks_per_jiffy;
+-unsigned long tb_ticks_per_usec = 100; /* sane default */
+-EXPORT_SYMBOL(tb_ticks_per_usec);
+-unsigned long tb_ticks_per_sec;
+-unsigned long tb_to_xs;
+-unsigned tb_to_us;
+-unsigned long processor_freq;
+-DEFINE_SPINLOCK(rtc_lock);
+-EXPORT_SYMBOL_GPL(rtc_lock);
+-
+-unsigned long tb_to_ns_scale;
+-unsigned long tb_to_ns_shift;
+-
+-struct gettimeofday_struct do_gtod;
+-
+-extern unsigned long wall_jiffies;
+-extern int smp_tb_synchronized;
+-
+-extern struct timezone sys_tz;
+-
+-void ppc_adjtimex(void);
+-
+-static unsigned adjusting_time = 0;
+-
+-unsigned long ppc_proc_freq;
+-unsigned long ppc_tb_freq;
+-
+-static __inline__ void timer_check_rtc(void)
+-{
+- /*
+- * update the rtc when needed, this should be performed on the
+- * right fraction of a second. Half or full second ?
+- * Full second works on mk48t59 clocks, others need testing.
+- * Note that this update is basically only used through
+- * the adjtimex system calls. Setting the HW clock in
+- * any other way is a /dev/rtc and userland business.
+- * This is still wrong by -0.5/+1.5 jiffies because of the
+- * timer interrupt resolution and possible delay, but here we
+- * hit a quantization limit which can only be solved by higher
+- * resolution timers and decoupling time management from timer
+- * interrupts. This is also wrong on the clocks
+- * which require being written at the half second boundary.
+- * We should have an rtc call that only sets the minutes and
+- * seconds like on Intel to avoid problems with non UTC clocks.
+- */
+- if (ntp_synced() &&
+- xtime.tv_sec - last_rtc_update >= 659 &&
+- abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ &&
+- jiffies - wall_jiffies == 1) {
+- struct rtc_time tm;
+- to_tm(xtime.tv_sec+1, &tm);
+- tm.tm_year -= 1900;
+- tm.tm_mon -= 1;
+- if (ppc_md.set_rtc_time(&tm) == 0)
+- last_rtc_update = xtime.tv_sec+1;
+- else
+- /* Try again one minute later */
+- last_rtc_update += 60;
+- }
+-}
+-
+-/*
+- * This version of gettimeofday has microsecond resolution.
+- */
+-static inline void __do_gettimeofday(struct timeval *tv, unsigned long tb_val)
+-{
+- unsigned long sec, usec, tb_ticks;
+- unsigned long xsec, tb_xsec;
+- struct gettimeofday_vars * temp_varp;
+- unsigned long temp_tb_to_xs, temp_stamp_xsec;
+-
+- /*
+- * These calculations are faster (gets rid of divides)
+- * if done in units of 1/2^20 rather than microseconds.
+- * The conversion to microseconds at the end is done
+- * without a divide (and in fact, without a multiply)
+- */
+- temp_varp = do_gtod.varp;
+- tb_ticks = tb_val - temp_varp->tb_orig_stamp;
+- temp_tb_to_xs = temp_varp->tb_to_xs;
+- temp_stamp_xsec = temp_varp->stamp_xsec;
+- tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs );
+- xsec = temp_stamp_xsec + tb_xsec;
+- sec = xsec / XSEC_PER_SEC;
+- xsec -= sec * XSEC_PER_SEC;
+- usec = (xsec * USEC_PER_SEC)/XSEC_PER_SEC;
+-
+- tv->tv_sec = sec;
+- tv->tv_usec = usec;
+-}
+-
+-void do_gettimeofday(struct timeval *tv)
+-{
+- __do_gettimeofday(tv, get_tb());
+-}
+-
+-EXPORT_SYMBOL(do_gettimeofday);
+-
+-/* Synchronize xtime with do_gettimeofday */
+-
+-static inline void timer_sync_xtime(unsigned long cur_tb)
+-{
+- struct timeval my_tv;
+-
+- __do_gettimeofday(&my_tv, cur_tb);
+-
+- if (xtime.tv_sec <= my_tv.tv_sec) {
+- xtime.tv_sec = my_tv.tv_sec;
+- xtime.tv_nsec = my_tv.tv_usec * 1000;
+- }
+-}
+-
+-/*
+- * When the timebase - tb_orig_stamp gets too big, we do a manipulation
+- * between tb_orig_stamp and stamp_xsec. The goal here is to keep the
+- * difference tb - tb_orig_stamp small enough to always fit inside a
+- * 32 bits number. This is a requirement of our fast 32 bits userland
+- * implementation in the vdso. If we "miss" a call to this function
+- * (interrupt latency, CPU locked in a spinlock, ...) and we end up
+- * with a too big difference, then the vdso will fallback to calling
+- * the syscall
+- */
+-static __inline__ void timer_recalc_offset(unsigned long cur_tb)
+-{
+- struct gettimeofday_vars * temp_varp;
+- unsigned temp_idx;
+- unsigned long offset, new_stamp_xsec, new_tb_orig_stamp;
+-
+- if (((cur_tb - do_gtod.varp->tb_orig_stamp) & 0x80000000u) == 0)
+- return;
+-
+- temp_idx = (do_gtod.var_idx == 0);
+- temp_varp = &do_gtod.vars[temp_idx];
+-
+- new_tb_orig_stamp = cur_tb;
+- offset = new_tb_orig_stamp - do_gtod.varp->tb_orig_stamp;
+- new_stamp_xsec = do_gtod.varp->stamp_xsec + mulhdu(offset, do_gtod.varp->tb_to_xs);
+-
+- temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs;
+- temp_varp->tb_orig_stamp = new_tb_orig_stamp;
+- temp_varp->stamp_xsec = new_stamp_xsec;
+- smp_mb();
+- do_gtod.varp = temp_varp;
+- do_gtod.var_idx = temp_idx;
+-
+- ++(systemcfg->tb_update_count);
+- smp_wmb();
+- systemcfg->tb_orig_stamp = new_tb_orig_stamp;
+- systemcfg->stamp_xsec = new_stamp_xsec;
+- smp_wmb();
+- ++(systemcfg->tb_update_count);
+-}
+-
+-#ifdef CONFIG_SMP
+-unsigned long profile_pc(struct pt_regs *regs)
+-{
+- unsigned long pc = instruction_pointer(regs);
+-
+- if (in_lock_functions(pc))
+- return regs->link;
+-
+- return pc;
+-}
+-EXPORT_SYMBOL(profile_pc);
+-#endif
+-
+-#ifdef CONFIG_PPC_ISERIES
+-
+-/*
+- * This function recalibrates the timebase based on the 49-bit time-of-day
+- * value in the Titan chip. The Titan is much more accurate than the value
+- * returned by the service processor for the timebase frequency.
+- */
+-
+-static void iSeries_tb_recal(void)
+-{
+- struct div_result divres;
+- unsigned long titan, tb;
+- tb = get_tb();
+- titan = HvCallXm_loadTod();
+- if ( iSeries_recal_titan ) {
+- unsigned long tb_ticks = tb - iSeries_recal_tb;
+- unsigned long titan_usec = (titan - iSeries_recal_titan) >> 12;
+- unsigned long new_tb_ticks_per_sec = (tb_ticks * USEC_PER_SEC)/titan_usec;
+- unsigned long new_tb_ticks_per_jiffy = (new_tb_ticks_per_sec+(HZ/2))/HZ;
+- long tick_diff = new_tb_ticks_per_jiffy - tb_ticks_per_jiffy;
+- char sign = '+';
+- /* make sure tb_ticks_per_sec and tb_ticks_per_jiffy are consistent */
+- new_tb_ticks_per_sec = new_tb_ticks_per_jiffy * HZ;
+-
+- if ( tick_diff < 0 ) {
+- tick_diff = -tick_diff;
+- sign = '-';
+- }
+- if ( tick_diff ) {
+- if ( tick_diff < tb_ticks_per_jiffy/25 ) {
+- printk( "Titan recalibrate: new tb_ticks_per_jiffy = %lu (%c%ld)\n",
+- new_tb_ticks_per_jiffy, sign, tick_diff );
+- tb_ticks_per_jiffy = new_tb_ticks_per_jiffy;
+- tb_ticks_per_sec = new_tb_ticks_per_sec;
+- div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres );
+- do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
+- tb_to_xs = divres.result_low;
+- do_gtod.varp->tb_to_xs = tb_to_xs;
+- systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
+- systemcfg->tb_to_xs = tb_to_xs;
+- }
+- else {
+- printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
+- " new tb_ticks_per_jiffy = %lu\n"
+- " old tb_ticks_per_jiffy = %lu\n",
+- new_tb_ticks_per_jiffy, tb_ticks_per_jiffy );
+- }
+- }
+- }
+- iSeries_recal_titan = titan;
+- iSeries_recal_tb = tb;
+-}
+-#endif
+-
+-/*
+- * For iSeries shared processors, we have to let the hypervisor
+- * set the hardware decrementer. We set a virtual decrementer
+- * in the lppaca and call the hypervisor if the virtual
+- * decrementer is less than the current value in the hardware
+- * decrementer. (almost always the new decrementer value will
+- * be greater than the current hardware decementer so the hypervisor
+- * call will not be needed)
+- */
+-
+-unsigned long tb_last_stamp __cacheline_aligned_in_smp;
+-
+-/*
+- * timer_interrupt - gets called when the decrementer overflows,
+- * with interrupts disabled.
+- */
+-int timer_interrupt(struct pt_regs * regs)
+-{
+- int next_dec;
+- unsigned long cur_tb;
+- struct paca_struct *lpaca = get_paca();
+- unsigned long cpu = smp_processor_id();
+-
+- irq_enter();
+-
+- profile_tick(CPU_PROFILING, regs);
+-
+- lpaca->lppaca.int_dword.fields.decr_int = 0;
+-
+- while (lpaca->next_jiffy_update_tb <= (cur_tb = get_tb())) {
+- /*
+- * We cannot disable the decrementer, so in the period
+- * between this cpu's being marked offline in cpu_online_map
+- * and calling stop-self, it is taking timer interrupts.
+- * Avoid calling into the scheduler rebalancing code if this
+- * is the case.
+- */
+- if (!cpu_is_offline(cpu))
+- update_process_times(user_mode(regs));
+- /*
+- * No need to check whether cpu is offline here; boot_cpuid
+- * should have been fixed up by now.
+- */
+- if (cpu == boot_cpuid) {
+- write_seqlock(&xtime_lock);
+- tb_last_stamp = lpaca->next_jiffy_update_tb;
+- timer_recalc_offset(lpaca->next_jiffy_update_tb);
+- do_timer(regs);
+- timer_sync_xtime(lpaca->next_jiffy_update_tb);
+- timer_check_rtc();
+- write_sequnlock(&xtime_lock);
+- if ( adjusting_time && (time_adjust == 0) )
+- ppc_adjtimex();
+- }
+- lpaca->next_jiffy_update_tb += tb_ticks_per_jiffy;
+- }
+-
+- next_dec = lpaca->next_jiffy_update_tb - cur_tb;
+- if (next_dec > lpaca->default_decr)
+- next_dec = lpaca->default_decr;
+- set_dec(next_dec);
+-
+-#ifdef CONFIG_PPC_ISERIES
+- if (hvlpevent_is_pending())
+- process_hvlpevents(regs);
+-#endif
+-
+- /* collect purr register values often, for accurate calculations */
+- if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+- struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
+- cu->current_tb = mfspr(SPRN_PURR);
+- }
+-
+- irq_exit();
+-
+- return 1;
+-}
+-
+-/*
+- * Scheduler clock - returns current time in nanosec units.
+- *
+- * Note: mulhdu(a, b) (multiply high double unsigned) returns
+- * the high 64 bits of a * b, i.e. (a * b) >> 64, where a and b
+- * are 64-bit unsigned numbers.
+- */
+-unsigned long long sched_clock(void)
+-{
+- return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
+-}
+-
+-int do_settimeofday(struct timespec *tv)
+-{
+- time_t wtm_sec, new_sec = tv->tv_sec;
+- long wtm_nsec, new_nsec = tv->tv_nsec;
+- unsigned long flags;
+- unsigned long delta_xsec;
+- long int tb_delta;
+- unsigned long new_xsec;
+-
+- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+- return -EINVAL;
+-
+- write_seqlock_irqsave(&xtime_lock, flags);
+- /* Updating the RTC is not the job of this code. If the time is
+- * stepped under NTP, the RTC will be update after STA_UNSYNC
+- * is cleared. Tool like clock/hwclock either copy the RTC
+- * to the system time, in which case there is no point in writing
+- * to the RTC again, or write to the RTC but then they don't call
+- * settimeofday to perform this operation.
+- */
+-#ifdef CONFIG_PPC_ISERIES
+- if ( first_settimeofday ) {
+- iSeries_tb_recal();
+- first_settimeofday = 0;
+- }
+-#endif
+- tb_delta = tb_ticks_since(tb_last_stamp);
+- tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
+-
+- new_nsec -= tb_delta / tb_ticks_per_usec / 1000;
+-
+- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
+- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
+-
+- set_normalized_timespec(&xtime, new_sec, new_nsec);
+- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+-
+- /* In case of a large backwards jump in time with NTP, we want the
+- * clock to be updated as soon as the PLL is again in lock.
+- */
+- last_rtc_update = new_sec - 658;
+-
+- ntp_clear();
+-
+- delta_xsec = mulhdu( (tb_last_stamp-do_gtod.varp->tb_orig_stamp),
+- do_gtod.varp->tb_to_xs );
+-
+- new_xsec = (new_nsec * XSEC_PER_SEC) / NSEC_PER_SEC;
+- new_xsec += new_sec * XSEC_PER_SEC;
+- if ( new_xsec > delta_xsec ) {
+- do_gtod.varp->stamp_xsec = new_xsec - delta_xsec;
+- systemcfg->stamp_xsec = new_xsec - delta_xsec;
+- }
+- else {
+- /* This is only for the case where the user is setting the time
+- * way back to a time such that the boot time would have been
+- * before 1970 ... eg. we booted ten days ago, and we are setting
+- * the time to Jan 5, 1970 */
+- do_gtod.varp->stamp_xsec = new_xsec;
+- do_gtod.varp->tb_orig_stamp = tb_last_stamp;
+- systemcfg->stamp_xsec = new_xsec;
+- systemcfg->tb_orig_stamp = tb_last_stamp;
+- }
+-
+- systemcfg->tz_minuteswest = sys_tz.tz_minuteswest;
+- systemcfg->tz_dsttime = sys_tz.tz_dsttime;
+-
+- write_sequnlock_irqrestore(&xtime_lock, flags);
+- clock_was_set();
+- return 0;
+-}
+-
+-EXPORT_SYMBOL(do_settimeofday);
+-
+-#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA)
+-void __init generic_calibrate_decr(void)
+-{
+- struct device_node *cpu;
+- struct div_result divres;
+- unsigned int *fp;
+- int node_found;
+-
+- /*
+- * The cpu node should have a timebase-frequency property
+- * to tell us the rate at which the decrementer counts.
+- */
+- cpu = of_find_node_by_type(NULL, "cpu");
+-
+- ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
+- node_found = 0;
+- if (cpu != 0) {
+- fp = (unsigned int *)get_property(cpu, "timebase-frequency",
+- NULL);
+- if (fp != 0) {
+- node_found = 1;
+- ppc_tb_freq = *fp;
+- }
+- }
+- if (!node_found)
+- printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+- "(not found)\n");
+-
+- ppc_proc_freq = DEFAULT_PROC_FREQ;
+- node_found = 0;
+- if (cpu != 0) {
+- fp = (unsigned int *)get_property(cpu, "clock-frequency",
+- NULL);
+- if (fp != 0) {
+- node_found = 1;
+- ppc_proc_freq = *fp;
+- }
+- }
+- if (!node_found)
+- printk(KERN_ERR "WARNING: Estimating processor frequency "
+- "(not found)\n");
+-
+- of_node_put(cpu);
+-
+- printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+- ppc_tb_freq/1000000, ppc_tb_freq%1000000);
+- printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
+- ppc_proc_freq/1000000, ppc_proc_freq%1000000);
+-
+- tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+- tb_ticks_per_usec = ppc_tb_freq / 1000000;
+- tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
+- div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
+- tb_to_xs = divres.result_low;
+-
+- setup_default_decr();
+-}
+-#endif
+-
+-void __init time_init(void)
+-{
+- /* This function is only called on the boot processor */
+- unsigned long flags;
+- struct rtc_time tm;
+- struct div_result res;
+- unsigned long scale, shift;
+-
+- ppc_md.calibrate_decr();
+-
+- /*
+- * Compute scale factor for sched_clock.
+- * The calibrate_decr() function has set tb_ticks_per_sec,
+- * which is the timebase frequency.
+- * We compute 1e9 * 2^64 / tb_ticks_per_sec and interpret
+- * the 128-bit result as a 64.64 fixed-point number.
+- * We then shift that number right until it is less than 1.0,
+- * giving us the scale factor and shift count to use in
+- * sched_clock().
+- */
+- div128_by_32(1000000000, 0, tb_ticks_per_sec, &res);
+- scale = res.result_low;
+- for (shift = 0; res.result_high != 0; ++shift) {
+- scale = (scale >> 1) | (res.result_high << 63);
+- res.result_high >>= 1;
+- }
+- tb_to_ns_scale = scale;
+- tb_to_ns_shift = shift;
+-
+-#ifdef CONFIG_PPC_ISERIES
+- if (!piranha_simulator)
+-#endif
+- ppc_md.get_boot_time(&tm);
+-
+- write_seqlock_irqsave(&xtime_lock, flags);
+- xtime.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+- tm.tm_hour, tm.tm_min, tm.tm_sec);
+- tb_last_stamp = get_tb();
+- do_gtod.varp = &do_gtod.vars[0];
+- do_gtod.var_idx = 0;
+- do_gtod.varp->tb_orig_stamp = tb_last_stamp;
+- get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy;
+- do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
+- do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
+- do_gtod.varp->tb_to_xs = tb_to_xs;
+- do_gtod.tb_to_us = tb_to_us;
+- systemcfg->tb_orig_stamp = tb_last_stamp;
+- systemcfg->tb_update_count = 0;
+- systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
+- systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
+- systemcfg->tb_to_xs = tb_to_xs;
+-
+- time_freq = 0;
+-
+- xtime.tv_nsec = 0;
+- last_rtc_update = xtime.tv_sec;
+- set_normalized_timespec(&wall_to_monotonic,
+- -xtime.tv_sec, -xtime.tv_nsec);
+- write_sequnlock_irqrestore(&xtime_lock, flags);
+-
+- /* Not exact, but the timer interrupt takes care of this */
+- set_dec(tb_ticks_per_jiffy);
+-}
+-
+-/*
+- * After adjtimex is called, adjust the conversion of tb ticks
+- * to microseconds to keep do_gettimeofday synchronized
+- * with ntpd.
+- *
+- * Use the time_adjust, time_freq and time_offset computed by adjtimex to
+- * adjust the frequency.
+- */
+-
+-/* #define DEBUG_PPC_ADJTIMEX 1 */
+-
+-void ppc_adjtimex(void)
+-{
+- unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, new_tb_to_xs, new_xsec, new_stamp_xsec;
+- unsigned long tb_ticks_per_sec_delta;
+- long delta_freq, ltemp;
+- struct div_result divres;
+- unsigned long flags;
+- struct gettimeofday_vars * temp_varp;
+- unsigned temp_idx;
+- long singleshot_ppm = 0;
+-
+- /* Compute parts per million frequency adjustment to accomplish the time adjustment
+- implied by time_offset to be applied over the elapsed time indicated by time_constant.
+- Use SHIFT_USEC to get it into the same units as time_freq. */
+- if ( time_offset < 0 ) {
+- ltemp = -time_offset;
+- ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
+- ltemp >>= SHIFT_KG + time_constant;
+- ltemp = -ltemp;
+- }
+- else {
+- ltemp = time_offset;
+- ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
+- ltemp >>= SHIFT_KG + time_constant;
+- }
+-
+- /* If there is a single shot time adjustment in progress */
+- if ( time_adjust ) {
+-#ifdef DEBUG_PPC_ADJTIMEX
+- printk("ppc_adjtimex: ");
+- if ( adjusting_time == 0 )
+- printk("starting ");
+- printk("single shot time_adjust = %ld\n", time_adjust);
+-#endif
+-
+- adjusting_time = 1;
+-
+- /* Compute parts per million frequency adjustment to match time_adjust */
+- singleshot_ppm = tickadj * HZ;
+- /*
+- * The adjustment should be tickadj*HZ to match the code in
+- * linux/kernel/timer.c, but experiments show that this is too
+- * large. 3/4 of tickadj*HZ seems about right
+- */
+- singleshot_ppm -= singleshot_ppm / 4;
+- /* Use SHIFT_USEC to get it into the same units as time_freq */
+- singleshot_ppm <<= SHIFT_USEC;
+- if ( time_adjust < 0 )
+- singleshot_ppm = -singleshot_ppm;
+- }
+- else {
+-#ifdef DEBUG_PPC_ADJTIMEX
+- if ( adjusting_time )
+- printk("ppc_adjtimex: ending single shot time_adjust\n");
+-#endif
+- adjusting_time = 0;
+- }
+-
+- /* Add up all of the frequency adjustments */
+- delta_freq = time_freq + ltemp + singleshot_ppm;
+-
+- /* Compute a new value for tb_ticks_per_sec based on the frequency adjustment */
+- den = 1000000 * (1 << (SHIFT_USEC - 8));
+- if ( delta_freq < 0 ) {
+- tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den;
+- new_tb_ticks_per_sec = tb_ticks_per_sec + tb_ticks_per_sec_delta;
+- }
+- else {
+- tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den;
+- new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta;
+- }
+-
+-#ifdef DEBUG_PPC_ADJTIMEX
+- printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm);
+- printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);
+-#endif
+-
+- /* Compute a new value of tb_to_xs (used to convert tb to microseconds and a new value of
+- stamp_xsec which is the time (in 1/2^20 second units) corresponding to tb_orig_stamp. This
+- new value of stamp_xsec compensates for the change in frequency (implied by the new tb_to_xs)
+- which guarantees that the current time remains the same */
+- write_seqlock_irqsave( &xtime_lock, flags );
+- tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp;
+- div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres );
+- new_tb_to_xs = divres.result_low;
+- new_xsec = mulhdu( tb_ticks, new_tb_to_xs );
+-
+- old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs );
+- new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
+-
+- /* There are two copies of tb_to_xs and stamp_xsec so that no lock is needed to access and use these
+- values in do_gettimeofday. We alternate the copies and as long as a reasonable time elapses between
+- changes, there will never be inconsistent values. ntpd has a minimum of one minute between updates */
+-
+- temp_idx = (do_gtod.var_idx == 0);
+- temp_varp = &do_gtod.vars[temp_idx];
+-
+- temp_varp->tb_to_xs = new_tb_to_xs;
+- temp_varp->stamp_xsec = new_stamp_xsec;
+- temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp;
+- smp_mb();
+- do_gtod.varp = temp_varp;
+- do_gtod.var_idx = temp_idx;
+-
+- /*
+- * tb_update_count is used to allow the problem state gettimeofday code
+- * to assure itself that it sees a consistent view of the tb_to_xs and
+- * stamp_xsec variables. It reads the tb_update_count, then reads
+- * tb_to_xs and stamp_xsec and then reads tb_update_count again. If
+- * the two values of tb_update_count match and are even then the
+- * tb_to_xs and stamp_xsec values are consistent. If not, then it
+- * loops back and reads them again until this criteria is met.
+- */
+- ++(systemcfg->tb_update_count);
+- smp_wmb();
+- systemcfg->tb_to_xs = new_tb_to_xs;
+- systemcfg->stamp_xsec = new_stamp_xsec;
+- smp_wmb();
+- ++(systemcfg->tb_update_count);
+-
+- write_sequnlock_irqrestore( &xtime_lock, flags );
+-
+-}
+-
+-
+-#define TICK_SIZE tick
+-#define FEBRUARY 2
+-#define STARTOFTIME 1970
+-#define SECDAY 86400L
+-#define SECYR (SECDAY * 365)
+-#define leapyear(year) ((year) % 4 == 0)
+-#define days_in_year(a) (leapyear(a) ? 366 : 365)
+-#define days_in_month(a) (month_days[(a) - 1])
+-
+-static int month_days[12] = {
+- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+-};
+-
+-/*
+- * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
+- */
+-void GregorianDay(struct rtc_time * tm)
+-{
+- int leapsToDate;
+- int lastYear;
+- int day;
+- int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+-
+- lastYear=tm->tm_year-1;
+-
+- /*
+- * Number of leap corrections to apply up to end of last year
+- */
+- leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
+-
+- /*
+- * This year is a leap year if it is divisible by 4 except when it is
+- * divisible by 100 unless it is divisible by 400
+- *
+- * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
+- */
+- if((tm->tm_year%4==0) &&
+- ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
+- (tm->tm_mon>2))
+- {
+- /*
+- * We are past Feb. 29 in a leap year
+- */
+- day=1;
+- }
+- else
+- {
+- day=0;
+- }
+-
+- day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +
+- tm->tm_mday;
+-
+- tm->tm_wday=day%7;
+-}
+-
+-void to_tm(int tim, struct rtc_time * tm)
+-{
+- register int i;
+- register long hms, day;
+-
+- day = tim / SECDAY;
+- hms = tim % SECDAY;
+-
+- /* Hours, minutes, seconds are easy */
+- tm->tm_hour = hms / 3600;
+- tm->tm_min = (hms % 3600) / 60;
+- tm->tm_sec = (hms % 3600) % 60;
+-
+- /* Number of years in days */
+- for (i = STARTOFTIME; day >= days_in_year(i); i++)
+- day -= days_in_year(i);
+- tm->tm_year = i;
+-
+- /* Number of months in days left */
+- if (leapyear(tm->tm_year))
+- days_in_month(FEBRUARY) = 29;
+- for (i = 1; day >= days_in_month(i); i++)
+- day -= days_in_month(i);
+- days_in_month(FEBRUARY) = 28;
+- tm->tm_mon = i;
+-
+- /* Days are what is left over (+1) from all that. */
+- tm->tm_mday = day + 1;
+-
+- /*
+- * Determine the day of week
+- */
+- GregorianDay(tm);
+-}
+-
+-/* Auxiliary function to compute scaling factors */
+-/* Actually the choice of a timebase running at 1/4 the of the bus
+- * frequency giving resolution of a few tens of nanoseconds is quite nice.
+- * It makes this computation very precise (27-28 bits typically) which
+- * is optimistic considering the stability of most processor clock
+- * oscillators and the precision with which the timebase frequency
+- * is measured but does not harm.
+- */
+-unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) {
+- unsigned mlt=0, tmp, err;
+- /* No concern for performance, it's done once: use a stupid
+- * but safe and compact method to find the multiplier.
+- */
+-
+- for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {
+- if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp;
+- }
+-
+- /* We might still be off by 1 for the best approximation.
+- * A side effect of this is that if outscale is too large
+- * the returned value will be zero.
+- * Many corner cases have been checked and seem to work,
+- * some might have been forgotten in the test however.
+- */
+-
+- err = inscale*(mlt+1);
+- if (err <= inscale/2) mlt++;
+- return mlt;
+- }
+-
+-/*
+- * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit
+- * result.
+- */
+-
+-void div128_by_32( unsigned long dividend_high, unsigned long dividend_low,
+- unsigned divisor, struct div_result *dr )
+-{
+- unsigned long a,b,c,d, w,x,y,z, ra,rb,rc;
+-
+- a = dividend_high >> 32;
+- b = dividend_high & 0xffffffff;
+- c = dividend_low >> 32;
+- d = dividend_low & 0xffffffff;
+-
+- w = a/divisor;
+- ra = (a - (w * divisor)) << 32;
+-
+- x = (ra + b)/divisor;
+- rb = ((ra + b) - (x * divisor)) << 32;
+-
+- y = (rb + c)/divisor;
+- rc = ((rb + c) - (y * divisor)) << 32;
+-
+- z = (rc + d)/divisor;
+-
+- dr->result_high = (w << 32) + x;
+- dr->result_low = (y << 32) + z;
+-
+-}
+-
+diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/traps.c
++++ /dev/null
+@@ -1,568 +0,0 @@
+-/*
+- * linux/arch/ppc64/kernel/traps.c
+- *
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.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.
+- *
+- * Modified by Cort Dougan (cort at cs.nmt.edu)
+- * and Paul Mackerras (paulus at cs.anu.edu.au)
+- */
+-
+-/*
+- * This file handles the architecture-dependent parts of hardware exceptions
+- */
+-
+-#include <linux/config.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/slab.h>
+-#include <linux/user.h>
+-#include <linux/a.out.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/delay.h>
+-#include <linux/kprobes.h>
+-#include <asm/kdebug.h>
+-
+-#include <asm/pgtable.h>
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/processor.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/rtas.h>
+-#include <asm/systemcfg.h>
+-#include <asm/machdep.h>
+-#include <asm/pmc.h>
+-
+-#ifdef CONFIG_DEBUGGER
+-int (*__debugger)(struct pt_regs *regs);
+-int (*__debugger_ipi)(struct pt_regs *regs);
+-int (*__debugger_bpt)(struct pt_regs *regs);
+-int (*__debugger_sstep)(struct pt_regs *regs);
+-int (*__debugger_iabr_match)(struct pt_regs *regs);
+-int (*__debugger_dabr_match)(struct pt_regs *regs);
+-int (*__debugger_fault_handler)(struct pt_regs *regs);
+-
+-EXPORT_SYMBOL(__debugger);
+-EXPORT_SYMBOL(__debugger_ipi);
+-EXPORT_SYMBOL(__debugger_bpt);
+-EXPORT_SYMBOL(__debugger_sstep);
+-EXPORT_SYMBOL(__debugger_iabr_match);
+-EXPORT_SYMBOL(__debugger_dabr_match);
+-EXPORT_SYMBOL(__debugger_fault_handler);
+-#endif
+-
+-struct notifier_block *ppc64_die_chain;
+-static DEFINE_SPINLOCK(die_notifier_lock);
+-
+-int register_die_notifier(struct notifier_block *nb)
+-{
+- int err = 0;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&die_notifier_lock, flags);
+- err = notifier_chain_register(&ppc64_die_chain, nb);
+- spin_unlock_irqrestore(&die_notifier_lock, flags);
+- return err;
+-}
+-
+-/*
+- * Trap & Exception support
+- */
+-
+-static DEFINE_SPINLOCK(die_lock);
+-
+-int die(const char *str, struct pt_regs *regs, long err)
+-{
+- static int die_counter;
+- int nl = 0;
+-
+- if (debugger(regs))
+- return 1;
+-
+- console_verbose();
+- spin_lock_irq(&die_lock);
+- bust_spinlocks(1);
+- printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
+-#ifdef CONFIG_PREEMPT
+- printk("PREEMPT ");
+- nl = 1;
+-#endif
+-#ifdef CONFIG_SMP
+- printk("SMP NR_CPUS=%d ", NR_CPUS);
+- nl = 1;
+-#endif
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+- printk("DEBUG_PAGEALLOC ");
+- nl = 1;
+-#endif
+-#ifdef CONFIG_NUMA
+- printk("NUMA ");
+- nl = 1;
+-#endif
+- switch(systemcfg->platform) {
+- case PLATFORM_PSERIES:
+- printk("PSERIES ");
+- nl = 1;
+- break;
+- case PLATFORM_PSERIES_LPAR:
+- printk("PSERIES LPAR ");
+- nl = 1;
+- break;
+- case PLATFORM_ISERIES_LPAR:
+- printk("ISERIES LPAR ");
+- nl = 1;
+- break;
+- case PLATFORM_POWERMAC:
+- printk("POWERMAC ");
+- nl = 1;
+- break;
+- case PLATFORM_BPA:
+- printk("BPA ");
+- nl = 1;
+- break;
+- }
+- if (nl)
+- printk("\n");
+- print_modules();
+- show_regs(regs);
+- bust_spinlocks(0);
+- spin_unlock_irq(&die_lock);
+-
+- if (in_interrupt())
+- panic("Fatal exception in interrupt");
+-
+- if (panic_on_oops) {
+- printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+- ssleep(5);
+- panic("Fatal exception");
+- }
+- do_exit(SIGSEGV);
+-
+- return 0;
+-}
+-
+-void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
+-{
+- siginfo_t info;
+-
+- if (!user_mode(regs)) {
+- if (die("Exception in kernel mode", regs, signr))
+- return;
+- }
+-
+- memset(&info, 0, sizeof(info));
+- info.si_signo = signr;
+- info.si_code = code;
+- info.si_addr = (void __user *) addr;
+- force_sig_info(signr, &info, current);
+-}
+-
+-void system_reset_exception(struct pt_regs *regs)
+-{
+- /* See if any machine dependent calls */
+- if (ppc_md.system_reset_exception)
+- ppc_md.system_reset_exception(regs);
+-
+- die("System Reset", regs, 0);
+-
+- /* Must die if the interrupt is not recoverable */
+- if (!(regs->msr & MSR_RI))
+- panic("Unrecoverable System Reset");
+-
+- /* What should we do here? We could issue a shutdown or hard reset. */
+-}
+-
+-void machine_check_exception(struct pt_regs *regs)
+-{
+- int recover = 0;
+-
+- /* See if any machine dependent calls */
+- if (ppc_md.machine_check_exception)
+- recover = ppc_md.machine_check_exception(regs);
+-
+- if (recover)
+- return;
+-
+- if (debugger_fault_handler(regs))
+- return;
+- die("Machine check", regs, 0);
+-
+- /* Must die if the interrupt is not recoverable */
+- if (!(regs->msr & MSR_RI))
+- panic("Unrecoverable Machine check");
+-}
+-
+-void unknown_exception(struct pt_regs *regs)
+-{
+- printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+- regs->nip, regs->msr, regs->trap);
+-
+- _exception(SIGTRAP, regs, 0, 0);
+-}
+-
+-void instruction_breakpoint_exception(struct pt_regs *regs)
+-{
+- if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5,
+- 5, SIGTRAP) == NOTIFY_STOP)
+- return;
+- if (debugger_iabr_match(regs))
+- return;
+- _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+-}
+-
+-void __kprobes single_step_exception(struct pt_regs *regs)
+-{
+- regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
+-
+- if (notify_die(DIE_SSTEP, "single_step", regs, 5,
+- 5, SIGTRAP) == NOTIFY_STOP)
+- return;
+- if (debugger_sstep(regs))
+- return;
+-
+- _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
+-}
+-
+-/*
+- * After we have successfully emulated an instruction, we have to
+- * check if the instruction was being single-stepped, and if so,
+- * pretend we got a single-step exception. This was pointed out
+- * by Kumar Gala. -- paulus
+- */
+-static inline void emulate_single_step(struct pt_regs *regs)
+-{
+- if (regs->msr & MSR_SE)
+- single_step_exception(regs);
+-}
+-
+-static void parse_fpe(struct pt_regs *regs)
+-{
+- int code = 0;
+- unsigned long fpscr;
+-
+- flush_fp_to_thread(current);
+-
+- fpscr = current->thread.fpscr;
+-
+- /* Invalid operation */
+- if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
+- code = FPE_FLTINV;
+-
+- /* Overflow */
+- else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX))
+- code = FPE_FLTOVF;
+-
+- /* Underflow */
+- else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX))
+- code = FPE_FLTUND;
+-
+- /* Divide by zero */
+- else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX))
+- code = FPE_FLTDIV;
+-
+- /* Inexact result */
+- else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX))
+- code = FPE_FLTRES;
+-
+- _exception(SIGFPE, regs, code, regs->nip);
+-}
+-
+-/*
+- * Illegal instruction emulation support. Return non-zero if we can't
+- * emulate, or -EFAULT if the associated memory access caused an access
+- * fault. Return zero on success.
+- */
+-
+-#define INST_MFSPR_PVR 0x7c1f42a6
+-#define INST_MFSPR_PVR_MASK 0xfc1fffff
+-
+-#define INST_DCBA 0x7c0005ec
+-#define INST_DCBA_MASK 0x7c0007fe
+-
+-#define INST_MCRXR 0x7c000400
+-#define INST_MCRXR_MASK 0x7c0007fe
+-
+-static int emulate_instruction(struct pt_regs *regs)
+-{
+- unsigned int instword;
+-
+- if (!user_mode(regs))
+- return -EINVAL;
+-
+- CHECK_FULL_REGS(regs);
+-
+- if (get_user(instword, (unsigned int __user *)(regs->nip)))
+- return -EFAULT;
+-
+- /* Emulate the mfspr rD, PVR. */
+- if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+- unsigned int rd;
+-
+- rd = (instword >> 21) & 0x1f;
+- regs->gpr[rd] = mfspr(SPRN_PVR);
+- return 0;
+- }
+-
+- /* Emulating the dcba insn is just a no-op. */
+- if ((instword & INST_DCBA_MASK) == INST_DCBA) {
+- static int warned;
+-
+- if (!warned) {
+- printk(KERN_WARNING
+- "process %d (%s) uses obsolete 'dcba' insn\n",
+- current->pid, current->comm);
+- warned = 1;
+- }
+- return 0;
+- }
+-
+- /* Emulate the mcrxr insn. */
+- if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+- static int warned;
+- unsigned int shift;
+-
+- if (!warned) {
+- printk(KERN_WARNING
+- "process %d (%s) uses obsolete 'mcrxr' insn\n",
+- current->pid, current->comm);
+- warned = 1;
+- }
+-
+- shift = (instword >> 21) & 0x1c;
+- regs->ccr &= ~(0xf0000000 >> shift);
+- regs->ccr |= (regs->xer & 0xf0000000) >> shift;
+- regs->xer &= ~0xf0000000;
+- return 0;
+- }
+-
+- return -EINVAL;
+-}
+-
+-/*
+- * Look through the list of trap instructions that are used for BUG(),
+- * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
+- * that the exception was caused by a trap instruction of some kind.
+- * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
+- * otherwise.
+- */
+-extern struct bug_entry __start___bug_table[], __stop___bug_table[];
+-
+-#ifndef CONFIG_MODULES
+-#define module_find_bug(x) NULL
+-#endif
+-
+-struct bug_entry *find_bug(unsigned long bugaddr)
+-{
+- struct bug_entry *bug;
+-
+- for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
+- if (bugaddr == bug->bug_addr)
+- return bug;
+- return module_find_bug(bugaddr);
+-}
+-
+-static int
+-check_bug_trap(struct pt_regs *regs)
+-{
+- struct bug_entry *bug;
+- unsigned long addr;
+-
+- if (regs->msr & MSR_PR)
+- return 0; /* not in kernel */
+- addr = regs->nip; /* address of trap instruction */
+- if (addr < PAGE_OFFSET)
+- return 0;
+- bug = find_bug(regs->nip);
+- if (bug == NULL)
+- return 0;
+- if (bug->line & BUG_WARNING_TRAP) {
+- /* this is a WARN_ON rather than BUG/BUG_ON */
+- printk(KERN_ERR "Badness in %s at %s:%d\n",
+- bug->function, bug->file,
+- (unsigned int)bug->line & ~BUG_WARNING_TRAP);
+- show_stack(current, (void *)regs->gpr[1]);
+- return 1;
+- }
+- printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
+- bug->function, bug->file, (unsigned int)bug->line);
+- return 0;
+-}
+-
+-void __kprobes program_check_exception(struct pt_regs *regs)
+-{
+- if (debugger_fault_handler(regs))
+- return;
+-
+- if (regs->msr & 0x100000) {
+- /* IEEE FP exception */
+- parse_fpe(regs);
+- } else if (regs->msr & 0x20000) {
+- /* trap exception */
+-
+- if (notify_die(DIE_BPT, "breakpoint", regs, 5,
+- 5, SIGTRAP) == NOTIFY_STOP)
+- return;
+- if (debugger_bpt(regs))
+- return;
+-
+- if (check_bug_trap(regs)) {
+- regs->nip += 4;
+- return;
+- }
+- _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+-
+- } else {
+- /* Privileged or illegal instruction; try to emulate it. */
+- switch (emulate_instruction(regs)) {
+- case 0:
+- regs->nip += 4;
+- emulate_single_step(regs);
+- break;
+-
+- case -EFAULT:
+- _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+- break;
+-
+- default:
+- if (regs->msr & 0x40000)
+- /* priveleged */
+- _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+- else
+- /* illegal */
+- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+- break;
+- }
+- }
+-}
+-
+-void kernel_fp_unavailable_exception(struct pt_regs *regs)
+-{
+- printk(KERN_EMERG "Unrecoverable FP Unavailable Exception "
+- "%lx at %lx\n", regs->trap, regs->nip);
+- die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
+-}
+-
+-void altivec_unavailable_exception(struct pt_regs *regs)
+-{
+- if (user_mode(regs)) {
+- /* A user program has executed an altivec instruction,
+- but this kernel doesn't support altivec. */
+- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+- return;
+- }
+- printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
+- "%lx at %lx\n", regs->trap, regs->nip);
+- die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
+-}
+-
+-extern perf_irq_t perf_irq;
+-
+-void performance_monitor_exception(struct pt_regs *regs)
+-{
+- perf_irq(regs);
+-}
+-
+-void alignment_exception(struct pt_regs *regs)
+-{
+- int fixed;
+-
+- fixed = fix_alignment(regs);
+-
+- if (fixed == 1) {
+- regs->nip += 4; /* skip over emulated instruction */
+- emulate_single_step(regs);
+- return;
+- }
+-
+- /* Operand address was bad */
+- if (fixed == -EFAULT) {
+- if (user_mode(regs)) {
+- _exception(SIGSEGV, regs, SEGV_MAPERR, regs->dar);
+- } else {
+- /* Search exception table */
+- bad_page_fault(regs, regs->dar, SIGSEGV);
+- }
+-
+- return;
+- }
+-
+- _exception(SIGBUS, regs, BUS_ADRALN, regs->nip);
+-}
+-
+-#ifdef CONFIG_ALTIVEC
+-void altivec_assist_exception(struct pt_regs *regs)
+-{
+- int err;
+- siginfo_t info;
+-
+- if (!user_mode(regs)) {
+- printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode"
+- " at %lx\n", regs->nip);
+- die("Kernel VMX/Altivec assist exception", regs, SIGILL);
+- }
+-
+- flush_altivec_to_thread(current);
+-
+- err = emulate_altivec(regs);
+- if (err == 0) {
+- regs->nip += 4; /* skip emulated instruction */
+- emulate_single_step(regs);
+- return;
+- }
+-
+- if (err == -EFAULT) {
+- /* got an error reading the instruction */
+- info.si_signo = SIGSEGV;
+- info.si_errno = 0;
+- info.si_code = SEGV_MAPERR;
+- info.si_addr = (void __user *) regs->nip;
+- force_sig_info(SIGSEGV, &info, current);
+- } else {
+- /* didn't recognize the instruction */
+- /* XXX quick hack for now: set the non-Java bit in the VSCR */
+- if (printk_ratelimit())
+- printk(KERN_ERR "Unrecognized altivec instruction "
+- "in %s at %lx\n", current->comm, regs->nip);
+- current->thread.vscr.u[3] |= 0x10000;
+- }
+-}
+-#endif /* CONFIG_ALTIVEC */
+-
+-/*
+- * We enter here if we get an unrecoverable exception, that is, one
+- * that happened at a point where the RI (recoverable interrupt) bit
+- * in the MSR is 0. This indicates that SRR0/1 are live, and that
+- * we therefore lost state by taking this exception.
+- */
+-void unrecoverable_exception(struct pt_regs *regs)
+-{
+- printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n",
+- regs->trap, regs->nip);
+- die("Unrecoverable exception", regs, SIGABRT);
+-}
+-
+-/*
+- * We enter here if we discover during exception entry that we are
+- * running in supervisor mode with a userspace value in the stack pointer.
+- */
+-void kernel_bad_stack(struct pt_regs *regs)
+-{
+- printk(KERN_EMERG "Bad kernel stack pointer %lx at %lx\n",
+- regs->gpr[1], regs->nip);
+- die("Bad kernel stack pointer", regs, SIGABRT);
+-}
+-
+-void __init trap_init(void)
+-{
+-}
+diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/u3_iommu.c
++++ /dev/null
+@@ -1,349 +0,0 @@
+-/*
+- * arch/ppc64/kernel/u3_iommu.c
+- *
+- * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
+- *
+- * Based on pSeries_iommu.c:
+- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+- * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
+- *
+- * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu.
+- *
+- *
+- * 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/init.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/mm.h>
+-#include <linux/spinlock.h>
+-#include <linux/string.h>
+-#include <linux/pci.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/vmalloc.h>
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/iommu.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/machdep.h>
+-#include <asm/abs_addr.h>
+-#include <asm/cacheflush.h>
+-#include <asm/lmb.h>
+-
+-#include "pci.h"
+-
+-extern int iommu_force_on;
+-
+-/* physical base of DART registers */
+-#define DART_BASE 0xf8033000UL
+-
+-/* Offset from base to control register */
+-#define DARTCNTL 0
+-/* Offset from base to exception register */
+-#define DARTEXCP 0x10
+-/* Offset from base to TLB tag registers */
+-#define DARTTAG 0x1000
+-
+-
+-/* Control Register fields */
+-
+-/* base address of table (pfn) */
+-#define DARTCNTL_BASE_MASK 0xfffff
+-#define DARTCNTL_BASE_SHIFT 12
+-
+-#define DARTCNTL_FLUSHTLB 0x400
+-#define DARTCNTL_ENABLE 0x200
+-
+-/* size of table in pages */
+-#define DARTCNTL_SIZE_MASK 0x1ff
+-#define DARTCNTL_SIZE_SHIFT 0
+-
+-/* DART table fields */
+-#define DARTMAP_VALID 0x80000000
+-#define DARTMAP_RPNMASK 0x00ffffff
+-
+-/* Physical base address and size of the DART table */
+-unsigned long dart_tablebase; /* exported to htab_initialize */
+-static unsigned long dart_tablesize;
+-
+-/* Virtual base address of the DART table */
+-static u32 *dart_vbase;
+-
+-/* Mapped base address for the dart */
+-static unsigned int *dart;
+-
+-/* Dummy val that entries are set to when unused */
+-static unsigned int dart_emptyval;
+-
+-static struct iommu_table iommu_table_u3;
+-static int iommu_table_u3_inited;
+-static int dart_dirty;
+-
+-#define DBG(...)
+-
+-static inline void dart_tlb_invalidate_all(void)
+-{
+- unsigned long l = 0;
+- unsigned int reg;
+- unsigned long limit;
+-
+- DBG("dart: flush\n");
+-
+- /* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
+- * control register and wait for it to clear.
+- *
+- * Gotcha: Sometimes, the DART won't detect that the bit gets
+- * set. If so, clear it and set it again.
+- */
+-
+- limit = 0;
+-
+-retry:
+- reg = in_be32((unsigned int *)dart+DARTCNTL);
+- reg |= DARTCNTL_FLUSHTLB;
+- out_be32((unsigned int *)dart+DARTCNTL, reg);
+-
+- l = 0;
+- while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) &&
+- l < (1L<<limit)) {
+- l++;
+- }
+- if (l == (1L<<limit)) {
+- if (limit < 4) {
+- limit++;
+- reg = in_be32((unsigned int *)dart+DARTCNTL);
+- reg &= ~DARTCNTL_FLUSHTLB;
+- out_be32((unsigned int *)dart+DARTCNTL, reg);
+- goto retry;
+- } else
+- panic("U3-DART: TLB did not flush after waiting a long "
+- "time. Buggy U3 ?");
+- }
+-}
+-
+-static void dart_flush(struct iommu_table *tbl)
+-{
+- if (dart_dirty)
+- dart_tlb_invalidate_all();
+- dart_dirty = 0;
+-}
+-
+-static void dart_build(struct iommu_table *tbl, long index,
+- long npages, unsigned long uaddr,
+- enum dma_data_direction direction)
+-{
+- unsigned int *dp;
+- unsigned int rpn;
+-
+- DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
+-
+- dp = ((unsigned int*)tbl->it_base) + index;
+-
+- /* On U3, all memory is contigous, so we can move this
+- * out of the loop.
+- */
+- while (npages--) {
+- rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
+-
+- *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
+-
+- rpn++;
+- uaddr += PAGE_SIZE;
+- }
+-
+- dart_dirty = 1;
+-}
+-
+-
+-static void dart_free(struct iommu_table *tbl, long index, long npages)
+-{
+- unsigned int *dp;
+-
+- /* We don't worry about flushing the TLB cache. The only drawback of
+- * not doing it is that we won't catch buggy device drivers doing
+- * bad DMAs, but then no 32-bit architecture ever does either.
+- */
+-
+- DBG("dart: free at: %lx, %lx\n", index, npages);
+-
+- dp = ((unsigned int *)tbl->it_base) + index;
+-
+- while (npages--)
+- *(dp++) = dart_emptyval;
+-}
+-
+-
+-static int dart_init(struct device_node *dart_node)
+-{
+- unsigned int regword;
+- unsigned int i;
+- unsigned long tmp;
+-
+- if (dart_tablebase == 0 || dart_tablesize == 0) {
+- printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n");
+- return -ENODEV;
+- }
+-
+- /* Make sure nothing from the DART range remains in the CPU cache
+- * from a previous mapping that existed before the kernel took
+- * over
+- */
+- flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize);
+-
+- /* Allocate a spare page to map all invalid DART pages. We need to do
+- * that to work around what looks like a problem with the HT bridge
+- * prefetching into invalid pages and corrupting data
+- */
+- tmp = lmb_alloc(PAGE_SIZE, PAGE_SIZE);
+- if (!tmp)
+- panic("U3-DART: Cannot allocate spare page!");
+- dart_emptyval = DARTMAP_VALID | ((tmp >> PAGE_SHIFT) & DARTMAP_RPNMASK);
+-
+- /* Map in DART registers. FIXME: Use device node to get base address */
+- dart = ioremap(DART_BASE, 0x7000);
+- if (dart == NULL)
+- panic("U3-DART: Cannot map registers!");
+-
+- /* Set initial control register contents: table base,
+- * table size and enable bit
+- */
+- regword = DARTCNTL_ENABLE |
+- ((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
+- (((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
+- << DARTCNTL_SIZE_SHIFT);
+- dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
+-
+- /* Fill initial table */
+- for (i = 0; i < dart_tablesize/4; i++)
+- dart_vbase[i] = dart_emptyval;
+-
+- /* Initialize DART with table base and enable it. */
+- out_be32((unsigned int *)dart, regword);
+-
+- /* Invalidate DART to get rid of possible stale TLBs */
+- dart_tlb_invalidate_all();
+-
+- printk(KERN_INFO "U3/CPC925 DART IOMMU initialized\n");
+-
+- return 0;
+-}
+-
+-static void iommu_table_u3_setup(void)
+-{
+- iommu_table_u3.it_busno = 0;
+- iommu_table_u3.it_offset = 0;
+- /* it_size is in number of entries */
+- iommu_table_u3.it_size = dart_tablesize / sizeof(u32);
+-
+- /* Initialize the common IOMMU code */
+- iommu_table_u3.it_base = (unsigned long)dart_vbase;
+- iommu_table_u3.it_index = 0;
+- iommu_table_u3.it_blocksize = 1;
+- iommu_init_table(&iommu_table_u3);
+-
+- /* Reserve the last page of the DART to avoid possible prefetch
+- * past the DART mapped area
+- */
+- set_bit(iommu_table_u3.it_size - 1, iommu_table_u3.it_map);
+-}
+-
+-static void iommu_dev_setup_u3(struct pci_dev *dev)
+-{
+- struct device_node *dn;
+-
+- /* We only have one iommu table on the mac for now, which makes
+- * things simple. Setup all PCI devices to point to this table
+- *
+- * We must use pci_device_to_OF_node() to make sure that
+- * we get the real "final" pointer to the device in the
+- * pci_dev sysdata and not the temporary PHB one
+- */
+- dn = pci_device_to_OF_node(dev);
+-
+- if (dn)
+- PCI_DN(dn)->iommu_table = &iommu_table_u3;
+-}
+-
+-static void iommu_bus_setup_u3(struct pci_bus *bus)
+-{
+- struct device_node *dn;
+-
+- if (!iommu_table_u3_inited) {
+- iommu_table_u3_inited = 1;
+- iommu_table_u3_setup();
+- }
+-
+- dn = pci_bus_to_OF_node(bus);
+-
+- if (dn)
+- PCI_DN(dn)->iommu_table = &iommu_table_u3;
+-}
+-
+-static void iommu_dev_setup_null(struct pci_dev *dev) { }
+-static void iommu_bus_setup_null(struct pci_bus *bus) { }
+-
+-void iommu_init_early_u3(void)
+-{
+- struct device_node *dn;
+-
+- /* Find the DART in the device-tree */
+- dn = of_find_compatible_node(NULL, "dart", "u3-dart");
+- if (dn == NULL)
+- return;
+-
+- /* Setup low level TCE operations for the core IOMMU code */
+- ppc_md.tce_build = dart_build;
+- ppc_md.tce_free = dart_free;
+- ppc_md.tce_flush = dart_flush;
+-
+- /* Initialize the DART HW */
+- if (dart_init(dn)) {
+- /* If init failed, use direct iommu and null setup functions */
+- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+- ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+-
+- /* Setup pci_dma ops */
+- pci_direct_iommu_init();
+- } else {
+- ppc_md.iommu_dev_setup = iommu_dev_setup_u3;
+- ppc_md.iommu_bus_setup = iommu_bus_setup_u3;
+-
+- /* Setup pci_dma ops */
+- pci_iommu_init();
+- }
+-}
+-
+-
+-void __init alloc_u3_dart_table(void)
+-{
+- /* Only reserve DART space if machine has more than 2GB of RAM
+- * or if requested with iommu=on on cmdline.
+- */
+- if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+- return;
+-
+- /* 512 pages (2MB) is max DART tablesize. */
+- dart_tablesize = 1UL << 21;
+- /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
+- * will blow up an entire large page anyway in the kernel mapping
+- */
+- dart_tablebase = (unsigned long)
+- abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+-
+- printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase);
+-}
+diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c
+--- a/arch/ppc64/kernel/vdso.c
++++ b/arch/ppc64/kernel/vdso.c
+@@ -176,13 +176,13 @@ static struct page * vdso_vma_nopage(str
+ 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 @@ int arch_setup_additional_pages(struct l
+ * 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 @@ void __init vdso_init(void)
+ ClearPageReserved(pg);
+ get_page(pg);
+ }
++
++ get_page(virt_to_page(systemcfg));
+ }
+
+ int in_gate_area_no_task(unsigned long addr)
+diff --git a/arch/ppc64/kernel/vdso64/sigtramp.S b/arch/ppc64/kernel/vdso64/sigtramp.S
+--- a/arch/ppc64/kernel/vdso64/sigtramp.S
++++ b/arch/ppc64/kernel/vdso64/sigtramp.S
+@@ -15,6 +15,7 @@
+ #include <asm/ppc_asm.h>
+ #include <asm/unistd.h>
+ #include <asm/vdso.h>
++#include <asm/ptrace.h> /* XXX for __SIGNAL_FRAMESIZE */
+
+ .text
+
+diff --git a/arch/ppc64/kernel/vecemu.c b/arch/ppc64/kernel/vecemu.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/vecemu.c
++++ /dev/null
+@@ -1,346 +0,0 @@
+-/*
+- * Routines to emulate some Altivec/VMX instructions, specifically
+- * those that can trap when given denormalized operands in Java mode.
+- */
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <asm/ptrace.h>
+-#include <asm/processor.h>
+-#include <asm/uaccess.h>
+-
+-/* Functions in vector.S */
+-extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
+-extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b);
+-extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+-extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
+-extern void vrefp(vector128 *dst, vector128 *src);
+-extern void vrsqrtefp(vector128 *dst, vector128 *src);
+-extern void vexptep(vector128 *dst, vector128 *src);
+-
+-static unsigned int exp2s[8] = {
+- 0x800000,
+- 0x8b95c2,
+- 0x9837f0,
+- 0xa5fed7,
+- 0xb504f3,
+- 0xc5672a,
+- 0xd744fd,
+- 0xeac0c7
+-};
+-
+-/*
+- * Computes an estimate of 2^x. The `s' argument is the 32-bit
+- * single-precision floating-point representation of x.
+- */
+-static unsigned int eexp2(unsigned int s)
+-{
+- int exp, pwr;
+- unsigned int mant, frac;
+-
+- /* extract exponent field from input */
+- exp = ((s >> 23) & 0xff) - 127;
+- if (exp > 7) {
+- /* check for NaN input */
+- if (exp == 128 && (s & 0x7fffff) != 0)
+- return s | 0x400000; /* return QNaN */
+- /* 2^-big = 0, 2^+big = +Inf */
+- return (s & 0x80000000)? 0: 0x7f800000; /* 0 or +Inf */
+- }
+- if (exp < -23)
+- return 0x3f800000; /* 1.0 */
+-
+- /* convert to fixed point integer in 9.23 representation */
+- pwr = (s & 0x7fffff) | 0x800000;
+- if (exp > 0)
+- pwr <<= exp;
+- else
+- pwr >>= -exp;
+- if (s & 0x80000000)
+- pwr = -pwr;
+-
+- /* extract integer part, which becomes exponent part of result */
+- exp = (pwr >> 23) + 126;
+- if (exp >= 254)
+- return 0x7f800000;
+- if (exp < -23)
+- return 0;
+-
+- /* table lookup on top 3 bits of fraction to get mantissa */
+- mant = exp2s[(pwr >> 20) & 7];
+-
+- /* linear interpolation using remaining 20 bits of fraction */
+- asm("mulhwu %0,%1,%2" : "=r" (frac)
+- : "r" (pwr << 12), "r" (0x172b83ff));
+- asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant));
+- mant += frac;
+-
+- if (exp >= 0)
+- return mant + (exp << 23);
+-
+- /* denormalized result */
+- exp = -exp;
+- mant += 1 << (exp - 1);
+- return mant >> exp;
+-}
+-
+-/*
+- * Computes an estimate of log_2(x). The `s' argument is the 32-bit
+- * single-precision floating-point representation of x.
+- */
+-static unsigned int elog2(unsigned int s)
+-{
+- int exp, mant, lz, frac;
+-
+- exp = s & 0x7f800000;
+- mant = s & 0x7fffff;
+- if (exp == 0x7f800000) { /* Inf or NaN */
+- if (mant != 0)
+- s |= 0x400000; /* turn NaN into QNaN */
+- return s;
+- }
+- if ((exp | mant) == 0) /* +0 or -0 */
+- return 0xff800000; /* return -Inf */
+-
+- if (exp == 0) {
+- /* denormalized */
+- asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant));
+- mant <<= lz - 8;
+- exp = (-118 - lz) << 23;
+- } else {
+- mant |= 0x800000;
+- exp -= 127 << 23;
+- }
+-
+- if (mant >= 0xb504f3) { /* 2^0.5 * 2^23 */
+- exp |= 0x400000; /* 0.5 * 2^23 */
+- asm("mulhwu %0,%1,%2" : "=r" (mant)
+- : "r" (mant), "r" (0xb504f334)); /* 2^-0.5 * 2^32 */
+- }
+- if (mant >= 0x9837f0) { /* 2^0.25 * 2^23 */
+- exp |= 0x200000; /* 0.25 * 2^23 */
+- asm("mulhwu %0,%1,%2" : "=r" (mant)
+- : "r" (mant), "r" (0xd744fccb)); /* 2^-0.25 * 2^32 */
+- }
+- if (mant >= 0x8b95c2) { /* 2^0.125 * 2^23 */
+- exp |= 0x100000; /* 0.125 * 2^23 */
+- asm("mulhwu %0,%1,%2" : "=r" (mant)
+- : "r" (mant), "r" (0xeac0c6e8)); /* 2^-0.125 * 2^32 */
+- }
+- if (mant > 0x800000) { /* 1.0 * 2^23 */
+- /* calculate (mant - 1) * 1.381097463 */
+- /* 1.381097463 == 0.125 / (2^0.125 - 1) */
+- asm("mulhwu %0,%1,%2" : "=r" (frac)
+- : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a));
+- exp += frac;
+- }
+- s = exp & 0x80000000;
+- if (exp != 0) {
+- if (s)
+- exp = -exp;
+- asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp));
+- lz = 8 - lz;
+- if (lz > 0)
+- exp >>= lz;
+- else if (lz < 0)
+- exp <<= -lz;
+- s += ((lz + 126) << 23) + exp;
+- }
+- return s;
+-}
+-
+-#define VSCR_SAT 1
+-
+-static int ctsxs(unsigned int x, int scale, unsigned int *vscrp)
+-{
+- int exp, mant;
+-
+- exp = (x >> 23) & 0xff;
+- mant = x & 0x7fffff;
+- if (exp == 255 && mant != 0)
+- return 0; /* NaN -> 0 */
+- exp = exp - 127 + scale;
+- if (exp < 0)
+- return 0; /* round towards zero */
+- if (exp >= 31) {
+- /* saturate, unless the result would be -2^31 */
+- if (x + (scale << 23) != 0xcf000000)
+- *vscrp |= VSCR_SAT;
+- return (x & 0x80000000)? 0x80000000: 0x7fffffff;
+- }
+- mant |= 0x800000;
+- mant = (mant << 7) >> (30 - exp);
+- return (x & 0x80000000)? -mant: mant;
+-}
+-
+-static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp)
+-{
+- int exp;
+- unsigned int mant;
+-
+- exp = (x >> 23) & 0xff;
+- mant = x & 0x7fffff;
+- if (exp == 255 && mant != 0)
+- return 0; /* NaN -> 0 */
+- exp = exp - 127 + scale;
+- if (exp < 0)
+- return 0; /* round towards zero */
+- if (x & 0x80000000) {
+- /* negative => saturate to 0 */
+- *vscrp |= VSCR_SAT;
+- return 0;
+- }
+- if (exp >= 32) {
+- /* saturate */
+- *vscrp |= VSCR_SAT;
+- return 0xffffffff;
+- }
+- mant |= 0x800000;
+- mant = (mant << 8) >> (31 - exp);
+- return mant;
+-}
+-
+-/* Round to floating integer, towards 0 */
+-static unsigned int rfiz(unsigned int x)
+-{
+- int exp;
+-
+- exp = ((x >> 23) & 0xff) - 127;
+- if (exp == 128 && (x & 0x7fffff) != 0)
+- return x | 0x400000; /* NaN -> make it a QNaN */
+- if (exp >= 23)
+- return x; /* it's an integer already (or Inf) */
+- if (exp < 0)
+- return x & 0x80000000; /* |x| < 1.0 rounds to 0 */
+- return x & ~(0x7fffff >> exp);
+-}
+-
+-/* Round to floating integer, towards +/- Inf */
+-static unsigned int rfii(unsigned int x)
+-{
+- int exp, mask;
+-
+- exp = ((x >> 23) & 0xff) - 127;
+- if (exp == 128 && (x & 0x7fffff) != 0)
+- return x | 0x400000; /* NaN -> make it a QNaN */
+- if (exp >= 23)
+- return x; /* it's an integer already (or Inf) */
+- if ((x & 0x7fffffff) == 0)
+- return x; /* +/-0 -> +/-0 */
+- if (exp < 0)
+- /* 0 < |x| < 1.0 rounds to +/- 1.0 */
+- return (x & 0x80000000) | 0x3f800000;
+- mask = 0x7fffff >> exp;
+- /* mantissa overflows into exponent - that's OK,
+- it can't overflow into the sign bit */
+- return (x + mask) & ~mask;
+-}
+-
+-/* Round to floating integer, to nearest */
+-static unsigned int rfin(unsigned int x)
+-{
+- int exp, half;
+-
+- exp = ((x >> 23) & 0xff) - 127;
+- if (exp == 128 && (x & 0x7fffff) != 0)
+- return x | 0x400000; /* NaN -> make it a QNaN */
+- if (exp >= 23)
+- return x; /* it's an integer already (or Inf) */
+- if (exp < -1)
+- return x & 0x80000000; /* |x| < 0.5 -> +/-0 */
+- if (exp == -1)
+- /* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */
+- return (x & 0x80000000) | 0x3f800000;
+- half = 0x400000 >> exp;
+- /* add 0.5 to the magnitude and chop off the fraction bits */
+- return (x + half) & ~(0x7fffff >> exp);
+-}
+-
+-int
+-emulate_altivec(struct pt_regs *regs)
+-{
+- unsigned int instr, i;
+- unsigned int va, vb, vc, vd;
+- vector128 *vrs;
+-
+- if (get_user(instr, (unsigned int __user *) regs->nip))
+- return -EFAULT;
+- if ((instr >> 26) != 4)
+- return -EINVAL; /* not an altivec instruction */
+- vd = (instr >> 21) & 0x1f;
+- va = (instr >> 16) & 0x1f;
+- vb = (instr >> 11) & 0x1f;
+- vc = (instr >> 6) & 0x1f;
+-
+- vrs = current->thread.vr;
+- switch (instr & 0x3f) {
+- case 10:
+- switch (vc) {
+- case 0: /* vaddfp */
+- vaddfp(&vrs[vd], &vrs[va], &vrs[vb]);
+- break;
+- case 1: /* vsubfp */
+- vsubfp(&vrs[vd], &vrs[va], &vrs[vb]);
+- break;
+- case 4: /* vrefp */
+- vrefp(&vrs[vd], &vrs[vb]);
+- break;
+- case 5: /* vrsqrtefp */
+- vrsqrtefp(&vrs[vd], &vrs[vb]);
+- break;
+- case 6: /* vexptefp */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = eexp2(vrs[vb].u[i]);
+- break;
+- case 7: /* vlogefp */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = elog2(vrs[vb].u[i]);
+- break;
+- case 8: /* vrfin */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = rfin(vrs[vb].u[i]);
+- break;
+- case 9: /* vrfiz */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = rfiz(vrs[vb].u[i]);
+- break;
+- case 10: /* vrfip */
+- for (i = 0; i < 4; ++i) {
+- u32 x = vrs[vb].u[i];
+- x = (x & 0x80000000)? rfiz(x): rfii(x);
+- vrs[vd].u[i] = x;
+- }
+- break;
+- case 11: /* vrfim */
+- for (i = 0; i < 4; ++i) {
+- u32 x = vrs[vb].u[i];
+- x = (x & 0x80000000)? rfii(x): rfiz(x);
+- vrs[vd].u[i] = x;
+- }
+- break;
+- case 14: /* vctuxs */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
+- ¤t->thread.vscr.u[3]);
+- break;
+- case 15: /* vctsxs */
+- for (i = 0; i < 4; ++i)
+- vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
+- ¤t->thread.vscr.u[3]);
+- break;
+- default:
+- return -EINVAL;
+- }
+- break;
+- case 46: /* vmaddfp */
+- vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+- break;
+- case 47: /* vnmsubfp */
+- vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- return 0;
+-}
+diff --git a/arch/ppc64/kernel/vector.S b/arch/ppc64/kernel/vector.S
+deleted file mode 100644
+--- a/arch/ppc64/kernel/vector.S
++++ /dev/null
+@@ -1,172 +0,0 @@
+-#include <asm/ppc_asm.h>
+-#include <asm/processor.h>
+-
+-/*
+- * The routines below are in assembler so we can closely control the
+- * usage of floating-point registers. These routines must be called
+- * with preempt disabled.
+- */
+- .section ".toc","aw"
+-fpzero:
+- .tc FD_0_0[TC],0
+-fpone:
+- .tc FD_3ff00000_0[TC],0x3ff0000000000000 /* 1.0 */
+-fphalf:
+- .tc FD_3fe00000_0[TC],0x3fe0000000000000 /* 0.5 */
+-
+- .text
+-/*
+- * Internal routine to enable floating point and set FPSCR to 0.
+- * Don't call it from C; it doesn't use the normal calling convention.
+- */
+-fpenable:
+- mfmsr r10
+- ori r11,r10,MSR_FP
+- mtmsr r11
+- isync
+- stfd fr31,-8(r1)
+- stfd fr0,-16(r1)
+- stfd fr1,-24(r1)
+- mffs fr31
+- lfd fr1,fpzero at toc(r2)
+- mtfsf 0xff,fr1
+- blr
+-
+-fpdisable:
+- mtlr r12
+- mtfsf 0xff,fr31
+- lfd fr1,-24(r1)
+- lfd fr0,-16(r1)
+- lfd fr31,-8(r1)
+- mtmsr r10
+- isync
+- blr
+-
+-/*
+- * Vector add, floating point.
+- */
+-_GLOBAL(vaddfp)
+- mflr r12
+- bl fpenable
+- li r0,4
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- lfsx fr1,r5,r6
+- fadds fr0,fr0,fr1
+- stfsx fr0,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- b fpdisable
+-
+-/*
+- * Vector subtract, floating point.
+- */
+-_GLOBAL(vsubfp)
+- mflr r12
+- bl fpenable
+- li r0,4
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- lfsx fr1,r5,r6
+- fsubs fr0,fr0,fr1
+- stfsx fr0,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- b fpdisable
+-
+-/*
+- * Vector multiply and add, floating point.
+- */
+-_GLOBAL(vmaddfp)
+- mflr r12
+- bl fpenable
+- stfd fr2,-32(r1)
+- li r0,4
+- mtctr r0
+- li r7,0
+-1: lfsx fr0,r4,r7
+- lfsx fr1,r5,r7
+- lfsx fr2,r6,r7
+- fmadds fr0,fr0,fr2,fr1
+- stfsx fr0,r3,r7
+- addi r7,r7,4
+- bdnz 1b
+- lfd fr2,-32(r1)
+- b fpdisable
+-
+-/*
+- * Vector negative multiply and subtract, floating point.
+- */
+-_GLOBAL(vnmsubfp)
+- mflr r12
+- bl fpenable
+- stfd fr2,-32(r1)
+- li r0,4
+- mtctr r0
+- li r7,0
+-1: lfsx fr0,r4,r7
+- lfsx fr1,r5,r7
+- lfsx fr2,r6,r7
+- fnmsubs fr0,fr0,fr2,fr1
+- stfsx fr0,r3,r7
+- addi r7,r7,4
+- bdnz 1b
+- lfd fr2,-32(r1)
+- b fpdisable
+-
+-/*
+- * Vector reciprocal estimate. We just compute 1.0/x.
+- * r3 -> destination, r4 -> source.
+- */
+-_GLOBAL(vrefp)
+- mflr r12
+- bl fpenable
+- li r0,4
+- lfd fr1,fpone at toc(r2)
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- fdivs fr0,fr1,fr0
+- stfsx fr0,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- b fpdisable
+-
+-/*
+- * Vector reciprocal square-root estimate, floating point.
+- * We use the frsqrte instruction for the initial estimate followed
+- * by 2 iterations of Newton-Raphson to get sufficient accuracy.
+- * r3 -> destination, r4 -> source.
+- */
+-_GLOBAL(vrsqrtefp)
+- mflr r12
+- bl fpenable
+- stfd fr2,-32(r1)
+- stfd fr3,-40(r1)
+- stfd fr4,-48(r1)
+- stfd fr5,-56(r1)
+- li r0,4
+- lfd fr4,fpone at toc(r2)
+- lfd fr5,fphalf at toc(r2)
+- mtctr r0
+- li r6,0
+-1: lfsx fr0,r4,r6
+- frsqrte fr1,fr0 /* r = frsqrte(s) */
+- fmuls fr3,fr1,fr0 /* r * s */
+- fmuls fr2,fr1,fr5 /* r * 0.5 */
+- fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
+- fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
+- fmuls fr3,fr1,fr0 /* r * s */
+- fmuls fr2,fr1,fr5 /* r * 0.5 */
+- fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
+- fmadds fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
+- stfsx fr1,r3,r6
+- addi r6,r6,4
+- bdnz 1b
+- lfd fr5,-56(r1)
+- lfd fr4,-48(r1)
+- lfd fr3,-40(r1)
+- lfd fr2,-32(r1)
+- b fpdisable
+diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/vio.c
++++ /dev/null
+@@ -1,261 +0,0 @@
+-/*
+- * IBM PowerPC Virtual I/O Infrastructure Support.
+- *
+- * Copyright (c) 2003-2005 IBM Corp.
+- * Dave Engebretsen engebret at us.ibm.com
+- * Santiago Leon santil at us.ibm.com
+- * Hollis Blanchard <hollisb at us.ibm.com>
+- * Stephen Rothwell
+- *
+- * 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/console.h>
+-#include <linux/module.h>
+-#include <linux/mm.h>
+-#include <linux/dma-mapping.h>
+-#include <asm/iommu.h>
+-#include <asm/dma.h>
+-#include <asm/vio.h>
+-
+-static const struct vio_device_id *vio_match_device(
+- const struct vio_device_id *, const struct vio_dev *);
+-
+-struct vio_dev vio_bus_device = { /* fake "parent" device */
+- .name = vio_bus_device.dev.bus_id,
+- .type = "",
+- .dev.bus_id = "vio",
+- .dev.bus = &vio_bus_type,
+-};
+-
+-static struct vio_bus_ops vio_bus_ops;
+-
+-/*
+- * Convert from struct device to struct vio_dev and pass to driver.
+- * dev->driver has already been set by generic code because vio_bus_match
+- * succeeded.
+- */
+-static int vio_bus_probe(struct device *dev)
+-{
+- struct vio_dev *viodev = to_vio_dev(dev);
+- struct vio_driver *viodrv = to_vio_driver(dev->driver);
+- const struct vio_device_id *id;
+- int error = -ENODEV;
+-
+- if (!viodrv->probe)
+- return error;
+-
+- id = vio_match_device(viodrv->id_table, viodev);
+- if (id)
+- error = viodrv->probe(viodev, id);
+-
+- return error;
+-}
+-
+-/* convert from struct device to struct vio_dev and pass to driver. */
+-static int vio_bus_remove(struct device *dev)
+-{
+- struct vio_dev *viodev = to_vio_dev(dev);
+- struct vio_driver *viodrv = to_vio_driver(dev->driver);
+-
+- if (viodrv->remove)
+- return viodrv->remove(viodev);
+-
+- /* driver can't remove */
+- return 1;
+-}
+-
+-/**
+- * vio_register_driver: - Register a new vio driver
+- * @drv: The vio_driver structure to be registered.
+- */
+-int vio_register_driver(struct vio_driver *viodrv)
+-{
+- printk(KERN_DEBUG "%s: driver %s registering\n", __FUNCTION__,
+- viodrv->name);
+-
+- /* fill in 'struct driver' fields */
+- viodrv->driver.name = viodrv->name;
+- viodrv->driver.bus = &vio_bus_type;
+- viodrv->driver.probe = vio_bus_probe;
+- viodrv->driver.remove = vio_bus_remove;
+-
+- return driver_register(&viodrv->driver);
+-}
+-EXPORT_SYMBOL(vio_register_driver);
+-
+-/**
+- * vio_unregister_driver - Remove registration of vio driver.
+- * @driver: The vio_driver struct to be removed form registration
+- */
+-void vio_unregister_driver(struct vio_driver *viodrv)
+-{
+- driver_unregister(&viodrv->driver);
+-}
+-EXPORT_SYMBOL(vio_unregister_driver);
+-
+-/**
+- * vio_match_device: - Tell if a VIO device has a matching
+- * VIO device id structure.
+- * @ids: array of VIO device id structures to search in
+- * @dev: the VIO device structure to match against
+- *
+- * Used by a driver to check whether a VIO device present in the
+- * system is in its list of supported devices. Returns the matching
+- * vio_device_id structure or NULL if there is no match.
+- */
+-static const struct vio_device_id *vio_match_device(
+- const struct vio_device_id *ids, const struct vio_dev *dev)
+-{
+- while (ids->type[0] != '\0') {
+- if (vio_bus_ops.match(ids, dev))
+- return ids;
+- ids++;
+- }
+- return NULL;
+-}
+-
+-/**
+- * vio_bus_init: - Initialize the virtual IO bus
+- */
+-int __init vio_bus_init(struct vio_bus_ops *ops)
+-{
+- int err;
+-
+- vio_bus_ops = *ops;
+-
+- err = bus_register(&vio_bus_type);
+- if (err) {
+- printk(KERN_ERR "failed to register VIO bus\n");
+- return err;
+- }
+-
+- /*
+- * The fake parent of all vio devices, just to give us
+- * a nice directory
+- */
+- err = device_register(&vio_bus_device.dev);
+- if (err) {
+- printk(KERN_WARNING "%s: device_register returned %i\n",
+- __FUNCTION__, err);
+- return err;
+- }
+-
+- return 0;
+-}
+-
+-/* vio_dev refcount hit 0 */
+-static void __devinit vio_dev_release(struct device *dev)
+-{
+- if (vio_bus_ops.release_device)
+- vio_bus_ops.release_device(dev);
+- kfree(to_vio_dev(dev));
+-}
+-
+-static ssize_t viodev_show_name(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
+-}
+-DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
+-
+-struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
+-{
+- /* init generic 'struct device' fields: */
+- viodev->dev.parent = &vio_bus_device.dev;
+- viodev->dev.bus = &vio_bus_type;
+- viodev->dev.release = vio_dev_release;
+-
+- /* register with generic device framework */
+- if (device_register(&viodev->dev)) {
+- printk(KERN_ERR "%s: failed to register device %s\n",
+- __FUNCTION__, viodev->dev.bus_id);
+- return NULL;
+- }
+- device_create_file(&viodev->dev, &dev_attr_name);
+-
+- return viodev;
+-}
+-
+-void __devinit vio_unregister_device(struct vio_dev *viodev)
+-{
+- if (vio_bus_ops.unregister_device)
+- vio_bus_ops.unregister_device(viodev);
+- device_remove_file(&viodev->dev, &dev_attr_name);
+- device_unregister(&viodev->dev);
+-}
+-EXPORT_SYMBOL(vio_unregister_device);
+-
+-static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
+- size_t size, enum dma_data_direction direction)
+-{
+- return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
+- direction);
+-}
+-
+-static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
+- size_t size, enum dma_data_direction direction)
+-{
+- iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
+- direction);
+-}
+-
+-static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
+- int nelems, enum dma_data_direction direction)
+-{
+- return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
+- nelems, direction);
+-}
+-
+-static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
+- int nelems, enum dma_data_direction direction)
+-{
+- iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
+-}
+-
+-static void *vio_alloc_coherent(struct device *dev, size_t size,
+- dma_addr_t *dma_handle, gfp_t flag)
+-{
+- return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
+- dma_handle, flag);
+-}
+-
+-static void vio_free_coherent(struct device *dev, size_t size,
+- void *vaddr, dma_addr_t dma_handle)
+-{
+- iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
+- dma_handle);
+-}
+-
+-static int vio_dma_supported(struct device *dev, u64 mask)
+-{
+- return 1;
+-}
+-
+-struct dma_mapping_ops vio_dma_ops = {
+- .alloc_coherent = vio_alloc_coherent,
+- .free_coherent = vio_free_coherent,
+- .map_single = vio_map_single,
+- .unmap_single = vio_unmap_single,
+- .map_sg = vio_map_sg,
+- .unmap_sg = vio_unmap_sg,
+- .dma_supported = vio_dma_supported,
+-};
+-
+-static int vio_bus_match(struct device *dev, struct device_driver *drv)
+-{
+- const struct vio_dev *vio_dev = to_vio_dev(dev);
+- struct vio_driver *vio_drv = to_vio_driver(drv);
+- const struct vio_device_id *ids = vio_drv->id_table;
+-
+- return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
+-}
+-
+-struct bus_type vio_bus_type = {
+- .name = "vio",
+- .match = vio_bus_match,
+-};
+diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/viopath.c
++++ /dev/null
+@@ -1,673 +0,0 @@
+-/* -*- linux-c -*-
+- * arch/ppc64/kernel/viopath.c
+- *
+- * iSeries Virtual I/O Message Path code
+- *
+- * Authors: Dave Boutcher <boutcher at us.ibm.com>
+- * Ryan Arnold <ryanarn at us.ibm.com>
+- * Colin Devilbiss <devilbis at us.ibm.com>
+- *
+- * (C) Copyright 2000-2003 IBM Corporation
+- *
+- * This code is used by the iSeries virtual disk, cd,
+- * tape, and console to communicate with OS/400 in another
+- * partition.
+- *
+- * 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) anyu 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/module.h>
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/vmalloc.h>
+-#include <linux/string.h>
+-#include <linux/proc_fs.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/wait.h>
+-#include <linux/seq_file.h>
+-#include <linux/smp_lock.h>
+-#include <linux/interrupt.h>
+-
+-#include <asm/system.h>
+-#include <asm/uaccess.h>
+-#include <asm/iSeries/HvTypes.h>
+-#include <asm/iSeries/ItExtVpdPanel.h>
+-#include <asm/iSeries/HvLpEvent.h>
+-#include <asm/iSeries/HvLpConfig.h>
+-#include <asm/iSeries/mf.h>
+-#include <asm/iSeries/vio.h>
+-
+-/* Status of the path to each other partition in the system.
+- * This is overkill, since we will only ever establish connections
+- * to our hosting partition and the primary partition on the system.
+- * But this allows for other support in the future.
+- */
+-static struct viopathStatus {
+- int isOpen; /* Did we open the path? */
+- int isActive; /* Do we have a mon msg outstanding */
+- int users[VIO_MAX_SUBTYPES];
+- HvLpInstanceId mSourceInst;
+- HvLpInstanceId mTargetInst;
+- int numberAllocated;
+-} viopathStatus[HVMAXARCHITECTEDLPS];
+-
+-static DEFINE_SPINLOCK(statuslock);
+-
+-/*
+- * For each kind of event we allocate a buffer that is
+- * guaranteed not to cross a page boundary
+- */
+-static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] __page_aligned;
+-static atomic_t event_buffer_available[VIO_MAX_SUBTYPES];
+-static int event_buffer_initialised;
+-
+-static void handleMonitorEvent(struct HvLpEvent *event);
+-
+-/*
+- * We use this structure to handle asynchronous responses. The caller
+- * blocks on the semaphore and the handler posts the semaphore. However,
+- * if system_state is not SYSTEM_RUNNING, then wait_atomic is used ...
+- */
+-struct alloc_parms {
+- struct semaphore sem;
+- int number;
+- atomic_t wait_atomic;
+- int used_wait_atomic;
+-};
+-
+-/* Put a sequence number in each mon msg. The value is not
+- * important. Start at something other than 0 just for
+- * readability. wrapping this is ok.
+- */
+-static u8 viomonseq = 22;
+-
+-/* Our hosting logical partition. We get this at startup
+- * time, and different modules access this variable directly.
+- */
+-HvLpIndex viopath_hostLp = HvLpIndexInvalid;
+-EXPORT_SYMBOL(viopath_hostLp);
+-HvLpIndex viopath_ourLp = HvLpIndexInvalid;
+-EXPORT_SYMBOL(viopath_ourLp);
+-
+-/* For each kind of incoming event we set a pointer to a
+- * routine to call.
+- */
+-static vio_event_handler_t *vio_handler[VIO_MAX_SUBTYPES];
+-
+-#define VIOPATH_KERN_WARN KERN_WARNING "viopath: "
+-#define VIOPATH_KERN_INFO KERN_INFO "viopath: "
+-
+-static int proc_viopath_show(struct seq_file *m, void *v)
+-{
+- char *buf;
+- u16 vlanMap;
+- dma_addr_t handle;
+- HvLpEvent_Rc hvrc;
+- DECLARE_MUTEX_LOCKED(Semaphore);
+-
+- buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+- if (!buf)
+- return 0;
+- memset(buf, 0, PAGE_SIZE);
+-
+- handle = dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE,
+- DMA_FROM_DEVICE);
+-
+- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+- HvLpEvent_Type_VirtualIo,
+- viomajorsubtype_config | vioconfigget,
+- HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+- viopath_sourceinst(viopath_hostLp),
+- viopath_targetinst(viopath_hostLp),
+- (u64)(unsigned long)&Semaphore, VIOVERSION << 16,
+- ((u64)handle) << 32, PAGE_SIZE, 0, 0);
+-
+- if (hvrc != HvLpEvent_Rc_Good)
+- printk(VIOPATH_KERN_WARN "hv error on op %d\n", (int)hvrc);
+-
+- down(&Semaphore);
+-
+- vlanMap = HvLpConfig_getVirtualLanIndexMap();
+-
+- buf[PAGE_SIZE-1] = '\0';
+- seq_printf(m, "%s", buf);
+- seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap);
+- seq_printf(m, "SRLNBR=%c%c%c%c%c%c%c\n",
+- e2a(xItExtVpdPanel.mfgID[2]),
+- e2a(xItExtVpdPanel.mfgID[3]),
+- e2a(xItExtVpdPanel.systemSerial[1]),
+- e2a(xItExtVpdPanel.systemSerial[2]),
+- e2a(xItExtVpdPanel.systemSerial[3]),
+- e2a(xItExtVpdPanel.systemSerial[4]),
+- e2a(xItExtVpdPanel.systemSerial[5]));
+-
+- dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE);
+- kfree(buf);
+-
+- return 0;
+-}
+-
+-static int proc_viopath_open(struct inode *inode, struct file *file)
+-{
+- return single_open(file, proc_viopath_show, NULL);
+-}
+-
+-static struct file_operations proc_viopath_operations = {
+- .open = proc_viopath_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = single_release,
+-};
+-
+-static int __init vio_proc_init(void)
+-{
+- struct proc_dir_entry *e;
+-
+- e = create_proc_entry("iSeries/config", 0, NULL);
+- if (e)
+- e->proc_fops = &proc_viopath_operations;
+-
+- return 0;
+-}
+-__initcall(vio_proc_init);
+-
+-/* See if a given LP is active. Allow for invalid lps to be passed in
+- * and just return invalid
+- */
+-int viopath_isactive(HvLpIndex lp)
+-{
+- if (lp == HvLpIndexInvalid)
+- return 0;
+- if (lp < HVMAXARCHITECTEDLPS)
+- return viopathStatus[lp].isActive;
+- else
+- return 0;
+-}
+-EXPORT_SYMBOL(viopath_isactive);
+-
+-/*
+- * We cache the source and target instance ids for each
+- * partition.
+- */
+-HvLpInstanceId viopath_sourceinst(HvLpIndex lp)
+-{
+- return viopathStatus[lp].mSourceInst;
+-}
+-EXPORT_SYMBOL(viopath_sourceinst);
+-
+-HvLpInstanceId viopath_targetinst(HvLpIndex lp)
+-{
+- return viopathStatus[lp].mTargetInst;
+-}
+-EXPORT_SYMBOL(viopath_targetinst);
+-
+-/*
+- * Send a monitor message. This is a message with the acknowledge
+- * bit on that the other side will NOT explicitly acknowledge. When
+- * the other side goes down, the hypervisor will acknowledge any
+- * outstanding messages....so we will know when the other side dies.
+- */
+-static void sendMonMsg(HvLpIndex remoteLp)
+-{
+- HvLpEvent_Rc hvrc;
+-
+- viopathStatus[remoteLp].mSourceInst =
+- HvCallEvent_getSourceLpInstanceId(remoteLp,
+- HvLpEvent_Type_VirtualIo);
+- viopathStatus[remoteLp].mTargetInst =
+- HvCallEvent_getTargetLpInstanceId(remoteLp,
+- HvLpEvent_Type_VirtualIo);
+-
+- /*
+- * Deliberately ignore the return code here. if we call this
+- * more than once, we don't care.
+- */
+- vio_setHandler(viomajorsubtype_monitor, handleMonitorEvent);
+-
+- hvrc = HvCallEvent_signalLpEventFast(remoteLp, HvLpEvent_Type_VirtualIo,
+- viomajorsubtype_monitor, HvLpEvent_AckInd_DoAck,
+- HvLpEvent_AckType_DeferredAck,
+- viopathStatus[remoteLp].mSourceInst,
+- viopathStatus[remoteLp].mTargetInst,
+- viomonseq++, 0, 0, 0, 0, 0);
+-
+- if (hvrc == HvLpEvent_Rc_Good)
+- viopathStatus[remoteLp].isActive = 1;
+- else {
+- printk(VIOPATH_KERN_WARN "could not connect to partition %d\n",
+- remoteLp);
+- viopathStatus[remoteLp].isActive = 0;
+- }
+-}
+-
+-static void handleMonitorEvent(struct HvLpEvent *event)
+-{
+- HvLpIndex remoteLp;
+- int i;
+-
+- /*
+- * This handler is _also_ called as part of the loop
+- * at the end of this routine, so it must be able to
+- * ignore NULL events...
+- */
+- if (!event)
+- return;
+-
+- /*
+- * First see if this is just a normal monitor message from the
+- * other partition
+- */
+- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+- remoteLp = event->xSourceLp;
+- if (!viopathStatus[remoteLp].isActive)
+- sendMonMsg(remoteLp);
+- return;
+- }
+-
+- /*
+- * This path is for an acknowledgement; the other partition
+- * died
+- */
+- remoteLp = event->xTargetLp;
+- if ((event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst) ||
+- (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst)) {
+- printk(VIOPATH_KERN_WARN "ignoring ack....mismatched instances\n");
+- return;
+- }
+-
+- printk(VIOPATH_KERN_WARN "partition %d ended\n", remoteLp);
+-
+- viopathStatus[remoteLp].isActive = 0;
+-
+- /*
+- * For each active handler, pass them a NULL
+- * message to indicate that the other partition
+- * died
+- */
+- for (i = 0; i < VIO_MAX_SUBTYPES; i++) {
+- if (vio_handler[i] != NULL)
+- (*vio_handler[i])(NULL);
+- }
+-}
+-
+-int vio_setHandler(int subtype, vio_event_handler_t *beh)
+-{
+- subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
+- if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
+- return -EINVAL;
+- if (vio_handler[subtype] != NULL)
+- return -EBUSY;
+- vio_handler[subtype] = beh;
+- return 0;
+-}
+-EXPORT_SYMBOL(vio_setHandler);
+-
+-int vio_clearHandler(int subtype)
+-{
+- subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
+- if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
+- return -EINVAL;
+- if (vio_handler[subtype] == NULL)
+- return -EAGAIN;
+- vio_handler[subtype] = NULL;
+- return 0;
+-}
+-EXPORT_SYMBOL(vio_clearHandler);
+-
+-static void handleConfig(struct HvLpEvent *event)
+-{
+- if (!event)
+- return;
+- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+- printk(VIOPATH_KERN_WARN
+- "unexpected config request from partition %d",
+- event->xSourceLp);
+-
+- if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
+- (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
+- event->xRc = HvLpEvent_Rc_InvalidSubtype;
+- HvCallEvent_ackLpEvent(event);
+- }
+- return;
+- }
+-
+- up((struct semaphore *)event->xCorrelationToken);
+-}
+-
+-/*
+- * Initialization of the hosting partition
+- */
+-void vio_set_hostlp(void)
+-{
+- /*
+- * If this has already been set then we DON'T want to either change
+- * it or re-register the proc file system
+- */
+- if (viopath_hostLp != HvLpIndexInvalid)
+- return;
+-
+- /*
+- * Figure out our hosting partition. This isn't allowed to change
+- * while we're active
+- */
+- viopath_ourLp = HvLpConfig_getLpIndex();
+- viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);
+-
+- if (viopath_hostLp != HvLpIndexInvalid)
+- vio_setHandler(viomajorsubtype_config, handleConfig);
+-}
+-EXPORT_SYMBOL(vio_set_hostlp);
+-
+-static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
+-{
+- HvLpIndex remoteLp;
+- int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK)
+- >> VIOMAJOR_SUBTYPE_SHIFT;
+-
+- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+- remoteLp = event->xSourceLp;
+- /*
+- * The isActive is checked because if the hosting partition
+- * went down and came back up it would not be active but it
+- * would have different source and target instances, in which
+- * case we'd want to reset them. This case really protects
+- * against an unauthorized active partition sending interrupts
+- * or acks to this linux partition.
+- */
+- if (viopathStatus[remoteLp].isActive
+- && (event->xSourceInstanceId !=
+- viopathStatus[remoteLp].mTargetInst)) {
+- printk(VIOPATH_KERN_WARN
+- "message from invalid partition. "
+- "int msg rcvd, source inst (%d) doesnt match (%d)\n",
+- viopathStatus[remoteLp].mTargetInst,
+- event->xSourceInstanceId);
+- return;
+- }
+-
+- if (viopathStatus[remoteLp].isActive
+- && (event->xTargetInstanceId !=
+- viopathStatus[remoteLp].mSourceInst)) {
+- printk(VIOPATH_KERN_WARN
+- "message from invalid partition. "
+- "int msg rcvd, target inst (%d) doesnt match (%d)\n",
+- viopathStatus[remoteLp].mSourceInst,
+- event->xTargetInstanceId);
+- return;
+- }
+- } else {
+- remoteLp = event->xTargetLp;
+- if (event->xSourceInstanceId !=
+- viopathStatus[remoteLp].mSourceInst) {
+- printk(VIOPATH_KERN_WARN
+- "message from invalid partition. "
+- "ack msg rcvd, source inst (%d) doesnt match (%d)\n",
+- viopathStatus[remoteLp].mSourceInst,
+- event->xSourceInstanceId);
+- return;
+- }
+-
+- if (event->xTargetInstanceId !=
+- viopathStatus[remoteLp].mTargetInst) {
+- printk(VIOPATH_KERN_WARN
+- "message from invalid partition. "
+- "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n",
+- viopathStatus[remoteLp].mTargetInst,
+- event->xTargetInstanceId);
+- return;
+- }
+- }
+-
+- if (vio_handler[subtype] == NULL) {
+- printk(VIOPATH_KERN_WARN
+- "unexpected virtual io event subtype %d from partition %d\n",
+- event->xSubtype, remoteLp);
+- /* No handler. Ack if necessary */
+- if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
+- (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
+- event->xRc = HvLpEvent_Rc_InvalidSubtype;
+- HvCallEvent_ackLpEvent(event);
+- }
+- return;
+- }
+-
+- /* This innocuous little line is where all the real work happens */
+- (*vio_handler[subtype])(event);
+-}
+-
+-static void viopath_donealloc(void *parm, int number)
+-{
+- struct alloc_parms *parmsp = parm;
+-
+- parmsp->number = number;
+- if (parmsp->used_wait_atomic)
+- atomic_set(&parmsp->wait_atomic, 0);
+- else
+- up(&parmsp->sem);
+-}
+-
+-static int allocateEvents(HvLpIndex remoteLp, int numEvents)
+-{
+- struct alloc_parms parms;
+-
+- if (system_state != SYSTEM_RUNNING) {
+- parms.used_wait_atomic = 1;
+- atomic_set(&parms.wait_atomic, 1);
+- } else {
+- parms.used_wait_atomic = 0;
+- init_MUTEX_LOCKED(&parms.sem);
+- }
+- mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */
+- numEvents, &viopath_donealloc, &parms);
+- if (system_state != SYSTEM_RUNNING) {
+- while (atomic_read(&parms.wait_atomic))
+- mb();
+- } else
+- down(&parms.sem);
+- return parms.number;
+-}
+-
+-int viopath_open(HvLpIndex remoteLp, int subtype, int numReq)
+-{
+- int i;
+- unsigned long flags;
+- int tempNumAllocated;
+-
+- if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
+- return -EINVAL;
+-
+- subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
+- if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
+- return -EINVAL;
+-
+- spin_lock_irqsave(&statuslock, flags);
+-
+- if (!event_buffer_initialised) {
+- for (i = 0; i < VIO_MAX_SUBTYPES; i++)
+- atomic_set(&event_buffer_available[i], 1);
+- event_buffer_initialised = 1;
+- }
+-
+- viopathStatus[remoteLp].users[subtype]++;
+-
+- if (!viopathStatus[remoteLp].isOpen) {
+- viopathStatus[remoteLp].isOpen = 1;
+- HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo);
+-
+- /*
+- * Don't hold the spinlock during an operation that
+- * can sleep.
+- */
+- spin_unlock_irqrestore(&statuslock, flags);
+- tempNumAllocated = allocateEvents(remoteLp, 1);
+- spin_lock_irqsave(&statuslock, flags);
+-
+- viopathStatus[remoteLp].numberAllocated += tempNumAllocated;
+-
+- if (viopathStatus[remoteLp].numberAllocated == 0) {
+- HvCallEvent_closeLpEventPath(remoteLp,
+- HvLpEvent_Type_VirtualIo);
+-
+- spin_unlock_irqrestore(&statuslock, flags);
+- return -ENOMEM;
+- }
+-
+- viopathStatus[remoteLp].mSourceInst =
+- HvCallEvent_getSourceLpInstanceId(remoteLp,
+- HvLpEvent_Type_VirtualIo);
+- viopathStatus[remoteLp].mTargetInst =
+- HvCallEvent_getTargetLpInstanceId(remoteLp,
+- HvLpEvent_Type_VirtualIo);
+- HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo,
+- &vio_handleEvent);
+- sendMonMsg(remoteLp);
+- printk(VIOPATH_KERN_INFO "opening connection to partition %d, "
+- "setting sinst %d, tinst %d\n",
+- remoteLp, viopathStatus[remoteLp].mSourceInst,
+- viopathStatus[remoteLp].mTargetInst);
+- }
+-
+- spin_unlock_irqrestore(&statuslock, flags);
+- tempNumAllocated = allocateEvents(remoteLp, numReq);
+- spin_lock_irqsave(&statuslock, flags);
+- viopathStatus[remoteLp].numberAllocated += tempNumAllocated;
+- spin_unlock_irqrestore(&statuslock, flags);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(viopath_open);
+-
+-int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
+-{
+- unsigned long flags;
+- int i;
+- int numOpen;
+- struct alloc_parms parms;
+-
+- if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
+- return -EINVAL;
+-
+- subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
+- if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
+- return -EINVAL;
+-
+- spin_lock_irqsave(&statuslock, flags);
+- /*
+- * If the viopath_close somehow gets called before a
+- * viopath_open it could decrement to -1 which is a non
+- * recoverable state so we'll prevent this from
+- * happening.
+- */
+- if (viopathStatus[remoteLp].users[subtype] > 0)
+- viopathStatus[remoteLp].users[subtype]--;
+-
+- spin_unlock_irqrestore(&statuslock, flags);
+-
+- parms.used_wait_atomic = 0;
+- init_MUTEX_LOCKED(&parms.sem);
+- mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo,
+- numReq, &viopath_donealloc, &parms);
+- down(&parms.sem);
+-
+- spin_lock_irqsave(&statuslock, flags);
+- for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++)
+- numOpen += viopathStatus[remoteLp].users[i];
+-
+- if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) {
+- printk(VIOPATH_KERN_INFO "closing connection to partition %d",
+- remoteLp);
+-
+- HvCallEvent_closeLpEventPath(remoteLp,
+- HvLpEvent_Type_VirtualIo);
+- viopathStatus[remoteLp].isOpen = 0;
+- viopathStatus[remoteLp].isActive = 0;
+-
+- for (i = 0; i < VIO_MAX_SUBTYPES; i++)
+- atomic_set(&event_buffer_available[i], 0);
+- event_buffer_initialised = 0;
+- }
+- spin_unlock_irqrestore(&statuslock, flags);
+- return 0;
+-}
+-EXPORT_SYMBOL(viopath_close);
+-
+-void *vio_get_event_buffer(int subtype)
+-{
+- subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
+- if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
+- return NULL;
+-
+- if (atomic_dec_if_positive(&event_buffer_available[subtype]) == 0)
+- return &event_buffer[subtype * 256];
+- else
+- return NULL;
+-}
+-EXPORT_SYMBOL(vio_get_event_buffer);
+-
+-void vio_free_event_buffer(int subtype, void *buffer)
+-{
+- subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
+- if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) {
+- printk(VIOPATH_KERN_WARN
+- "unexpected subtype %d freeing event buffer\n", subtype);
+- return;
+- }
+-
+- if (atomic_read(&event_buffer_available[subtype]) != 0) {
+- printk(VIOPATH_KERN_WARN
+- "freeing unallocated event buffer, subtype %d\n",
+- subtype);
+- return;
+- }
+-
+- if (buffer != &event_buffer[subtype * 256]) {
+- printk(VIOPATH_KERN_WARN
+- "freeing invalid event buffer, subtype %d\n", subtype);
+- }
+-
+- atomic_set(&event_buffer_available[subtype], 1);
+-}
+-EXPORT_SYMBOL(vio_free_event_buffer);
+-
+-static const struct vio_error_entry vio_no_error =
+- { 0, 0, "Non-VIO Error" };
+-static const struct vio_error_entry vio_unknown_error =
+- { 0, EIO, "Unknown Error" };
+-
+-static const struct vio_error_entry vio_default_errors[] = {
+- {0x0001, EIO, "No Connection"},
+- {0x0002, EIO, "No Receiver"},
+- {0x0003, EIO, "No Buffer Available"},
+- {0x0004, EBADRQC, "Invalid Message Type"},
+- {0x0000, 0, NULL},
+-};
+-
+-const struct vio_error_entry *vio_lookup_rc(
+- const struct vio_error_entry *local_table, u16 rc)
+-{
+- const struct vio_error_entry *cur;
+-
+- if (!rc)
+- return &vio_no_error;
+- if (local_table)
+- for (cur = local_table; cur->rc; ++cur)
+- if (cur->rc == rc)
+- return cur;
+- for (cur = vio_default_errors; cur->rc; ++cur)
+- if (cur->rc == rc)
+- return cur;
+- return &vio_unknown_error;
+-}
+-EXPORT_SYMBOL(vio_lookup_rc);
+diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
+--- a/arch/ppc64/kernel/vmlinux.lds.S
++++ b/arch/ppc64/kernel/vmlinux.lds.S
+@@ -1,3 +1,4 @@
++#include <asm/page.h>
+ #include <asm-generic/vmlinux.lds.h>
+
+ OUTPUT_ARCH(powerpc:common64)
+@@ -17,7 +18,7 @@ SECTIONS
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE);
+ _etext = .;
+ }
+
+@@ -43,7 +44,7 @@ SECTIONS
+
+
+ /* will be freed after init */
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE);
+ __init_begin = .;
+
+ .init.text : {
+@@ -83,7 +84,7 @@ SECTIONS
+
+ SECURITY_INIT
+
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE);
+ .init.ramfs : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+@@ -96,18 +97,22 @@ SECTIONS
+ __per_cpu_end = .;
+ }
+
++ . = ALIGN(PAGE_SIZE);
+ . = ALIGN(16384);
+ __init_end = .;
+ /* freed after init ends here */
+
+
+ /* Read/write sections */
++ . = ALIGN(PAGE_SIZE);
+ . = ALIGN(16384);
++ _sdata = .;
+ /* The initial task and kernel stack */
+ .data.init_task : {
+ *(.data.init_task)
+ }
+
++ . = ALIGN(PAGE_SIZE);
+ .data.page_aligned : {
+ *(.data.page_aligned)
+ }
+@@ -129,18 +134,18 @@ SECTIONS
+ __toc_start = .;
+ *(.got)
+ *(.toc)
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE);
+ _edata = .;
+ }
+
+
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE);
+ .bss : {
+ __bss_start = .;
+ *(.bss)
+ __bss_stop = .;
+ }
+
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE);
+ _end = . ;
+ }
+diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
+deleted file mode 100644
+--- a/arch/ppc64/kernel/xics.c
++++ /dev/null
+@@ -1,747 +0,0 @@
+-/*
+- * arch/ppc64/kernel/xics.c
+- *
+- * Copyright 2000 IBM Corporation.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-#include <linux/config.h>
+-#include <linux/types.h>
+-#include <linux/threads.h>
+-#include <linux/kernel.h>
+-#include <linux/irq.h>
+-#include <linux/smp.h>
+-#include <linux/interrupt.h>
+-#include <linux/signal.h>
+-#include <linux/init.h>
+-#include <linux/gfp.h>
+-#include <linux/radix-tree.h>
+-#include <linux/cpu.h>
+-#include <asm/prom.h>
+-#include <asm/io.h>
+-#include <asm/pgtable.h>
+-#include <asm/smp.h>
+-#include <asm/rtas.h>
+-#include <asm/xics.h>
+-#include <asm/hvcall.h>
+-#include <asm/machdep.h>
+-
+-#include "i8259.h"
+-
+-static unsigned int xics_startup(unsigned int irq);
+-static void xics_enable_irq(unsigned int irq);
+-static void xics_disable_irq(unsigned int irq);
+-static void xics_mask_and_ack_irq(unsigned int irq);
+-static void xics_end_irq(unsigned int irq);
+-static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
+-
+-static struct hw_interrupt_type xics_pic = {
+- .typename = " XICS ",
+- .startup = xics_startup,
+- .enable = xics_enable_irq,
+- .disable = xics_disable_irq,
+- .ack = xics_mask_and_ack_irq,
+- .end = xics_end_irq,
+- .set_affinity = xics_set_affinity
+-};
+-
+-static struct hw_interrupt_type xics_8259_pic = {
+- .typename = " XICS/8259",
+- .ack = xics_mask_and_ack_irq,
+-};
+-
+-/* This is used to map real irq numbers to virtual */
+-static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC);
+-
+-#define XICS_IPI 2
+-#define XICS_IRQ_SPURIOUS 0
+-
+-/* Want a priority other than 0. Various HW issues require this. */
+-#define DEFAULT_PRIORITY 5
+-
+-/*
+- * Mark IPIs as higher priority so we can take them inside interrupts that
+- * arent marked SA_INTERRUPT
+- */
+-#define IPI_PRIORITY 4
+-
+-struct xics_ipl {
+- union {
+- u32 word;
+- u8 bytes[4];
+- } xirr_poll;
+- union {
+- u32 word;
+- u8 bytes[4];
+- } xirr;
+- u32 dummy;
+- union {
+- u32 word;
+- u8 bytes[4];
+- } qirr;
+-};
+-
+-static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
+-
+-static int xics_irq_8259_cascade = 0;
+-static int xics_irq_8259_cascade_real = 0;
+-static unsigned int default_server = 0xFF;
+-static unsigned int default_distrib_server = 0;
+-static unsigned int interrupt_server_size = 8;
+-
+-/*
+- * XICS only has a single IPI, so encode the messages per CPU
+- */
+-struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+-
+-/* RTAS service tokens */
+-static int ibm_get_xive;
+-static int ibm_set_xive;
+-static int ibm_int_on;
+-static int ibm_int_off;
+-
+-typedef struct {
+- int (*xirr_info_get)(int cpu);
+- void (*xirr_info_set)(int cpu, int val);
+- void (*cppr_info)(int cpu, u8 val);
+- void (*qirr_info)(int cpu, u8 val);
+-} xics_ops;
+-
+-
+-/* SMP */
+-
+-static int pSeries_xirr_info_get(int n_cpu)
+-{
+- return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
+-}
+-
+-static void pSeries_xirr_info_set(int n_cpu, int value)
+-{
+- out_be32(&xics_per_cpu[n_cpu]->xirr.word, value);
+-}
+-
+-static void pSeries_cppr_info(int n_cpu, u8 value)
+-{
+- out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value);
+-}
+-
+-static void pSeries_qirr_info(int n_cpu, u8 value)
+-{
+- out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value);
+-}
+-
+-static xics_ops pSeries_ops = {
+- pSeries_xirr_info_get,
+- pSeries_xirr_info_set,
+- pSeries_cppr_info,
+- pSeries_qirr_info
+-};
+-
+-static xics_ops *ops = &pSeries_ops;
+-
+-
+-/* LPAR */
+-
+-static inline long plpar_eoi(unsigned long xirr)
+-{
+- return plpar_hcall_norets(H_EOI, xirr);
+-}
+-
+-static inline long plpar_cppr(unsigned long cppr)
+-{
+- return plpar_hcall_norets(H_CPPR, cppr);
+-}
+-
+-static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr)
+-{
+- return plpar_hcall_norets(H_IPI, servernum, mfrr);
+-}
+-
+-static inline long plpar_xirr(unsigned long *xirr_ret)
+-{
+- unsigned long dummy;
+- return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy);
+-}
+-
+-static int pSeriesLP_xirr_info_get(int n_cpu)
+-{
+- unsigned long lpar_rc;
+- unsigned long return_value;
+-
+- lpar_rc = plpar_xirr(&return_value);
+- if (lpar_rc != H_Success)
+- panic(" bad return code xirr - rc = %lx \n", lpar_rc);
+- return (int)return_value;
+-}
+-
+-static void pSeriesLP_xirr_info_set(int n_cpu, int value)
+-{
+- unsigned long lpar_rc;
+- unsigned long val64 = value & 0xffffffff;
+-
+- lpar_rc = plpar_eoi(val64);
+- if (lpar_rc != H_Success)
+- panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
+- val64);
+-}
+-
+-void pSeriesLP_cppr_info(int n_cpu, u8 value)
+-{
+- unsigned long lpar_rc;
+-
+- lpar_rc = plpar_cppr(value);
+- if (lpar_rc != H_Success)
+- panic("bad return code cppr - rc = %lx\n", lpar_rc);
+-}
+-
+-static void pSeriesLP_qirr_info(int n_cpu , u8 value)
+-{
+- unsigned long lpar_rc;
+-
+- lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
+- if (lpar_rc != H_Success)
+- panic("bad return code qirr - rc = %lx\n", lpar_rc);
+-}
+-
+-xics_ops pSeriesLP_ops = {
+- pSeriesLP_xirr_info_get,
+- pSeriesLP_xirr_info_set,
+- pSeriesLP_cppr_info,
+- pSeriesLP_qirr_info
+-};
+-
+-static unsigned int xics_startup(unsigned int virq)
+-{
+- unsigned int irq;
+-
+- irq = irq_offset_down(virq);
+- if (radix_tree_insert(&irq_map, virt_irq_to_real(irq),
+- &virt_irq_to_real_map[irq]) == -ENOMEM)
+- printk(KERN_CRIT "Out of memory creating real -> virtual"
+- " IRQ mapping for irq %u (real 0x%x)\n",
+- virq, virt_irq_to_real(irq));
+- xics_enable_irq(virq);
+- return 0; /* return value is ignored */
+-}
+-
+-static unsigned int real_irq_to_virt(unsigned int real_irq)
+-{
+- unsigned int *ptr;
+-
+- ptr = radix_tree_lookup(&irq_map, real_irq);
+- if (ptr == NULL)
+- return NO_IRQ;
+- return ptr - virt_irq_to_real_map;
+-}
+-
+-#ifdef CONFIG_SMP
+-static int get_irq_server(unsigned int irq)
+-{
+- unsigned int server;
+- /* For the moment only implement delivery to all cpus or one cpu */
+- cpumask_t cpumask = irq_affinity[irq];
+- cpumask_t tmp = CPU_MASK_NONE;
+-
+- if (!distribute_irqs)
+- return default_server;
+-
+- if (cpus_equal(cpumask, CPU_MASK_ALL)) {
+- server = default_distrib_server;
+- } else {
+- cpus_and(tmp, cpu_online_map, cpumask);
+-
+- if (cpus_empty(tmp))
+- server = default_distrib_server;
+- else
+- server = get_hard_smp_processor_id(first_cpu(tmp));
+- }
+-
+- return server;
+-
+-}
+-#else
+-static int get_irq_server(unsigned int irq)
+-{
+- return default_server;
+-}
+-#endif
+-
+-static void xics_enable_irq(unsigned int virq)
+-{
+- unsigned int irq;
+- int call_status;
+- unsigned int server;
+-
+- irq = virt_irq_to_real(irq_offset_down(virq));
+- if (irq == XICS_IPI)
+- return;
+-
+- server = get_irq_server(virq);
+- call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
+- DEFAULT_PRIORITY);
+- if (call_status != 0) {
+- printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
+- "returned %d\n", irq, call_status);
+- printk("set_xive %x, server %x\n", ibm_set_xive, server);
+- return;
+- }
+-
+- /* Now unmask the interrupt (often a no-op) */
+- call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
+- if (call_status != 0) {
+- printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
+- "returned %d\n", irq, call_status);
+- return;
+- }
+-}
+-
+-static void xics_disable_real_irq(unsigned int irq)
+-{
+- int call_status;
+- unsigned int server;
+-
+- if (irq == XICS_IPI)
+- return;
+-
+- call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
+- if (call_status != 0) {
+- printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
+- "ibm_int_off returned %d\n", irq, call_status);
+- return;
+- }
+-
+- server = get_irq_server(irq);
+- /* Have to set XIVE to 0xff to be able to remove a slot */
+- call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
+- if (call_status != 0) {
+- printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
+- " returned %d\n", irq, call_status);
+- return;
+- }
+-}
+-
+-static void xics_disable_irq(unsigned int virq)
+-{
+- unsigned int irq;
+-
+- irq = virt_irq_to_real(irq_offset_down(virq));
+- xics_disable_real_irq(irq);
+-}
+-
+-static void xics_end_irq(unsigned int irq)
+-{
+- int cpu = smp_processor_id();
+-
+- iosync();
+- ops->xirr_info_set(cpu, ((0xff << 24) |
+- (virt_irq_to_real(irq_offset_down(irq)))));
+-
+-}
+-
+-static void xics_mask_and_ack_irq(unsigned int irq)
+-{
+- int cpu = smp_processor_id();
+-
+- if (irq < irq_offset_value()) {
+- i8259_pic.ack(irq);
+- iosync();
+- ops->xirr_info_set(cpu, ((0xff<<24) |
+- xics_irq_8259_cascade_real));
+- iosync();
+- }
+-}
+-
+-int xics_get_irq(struct pt_regs *regs)
+-{
+- unsigned int cpu = smp_processor_id();
+- unsigned int vec;
+- int irq;
+-
+- vec = ops->xirr_info_get(cpu);
+- /* (vec >> 24) == old priority */
+- vec &= 0x00ffffff;
+-
+- /* for sanity, this had better be < NR_IRQS - 16 */
+- if (vec == xics_irq_8259_cascade_real) {
+- irq = i8259_irq(cpu);
+- if (irq == -1) {
+- /* Spurious cascaded interrupt. Still must ack xics */
+- xics_end_irq(irq_offset_up(xics_irq_8259_cascade));
+-
+- irq = -1;
+- }
+- } else if (vec == XICS_IRQ_SPURIOUS) {
+- irq = -1;
+- } else {
+- irq = real_irq_to_virt(vec);
+- if (irq == NO_IRQ)
+- irq = real_irq_to_virt_slowpath(vec);
+- if (irq == NO_IRQ) {
+- printk(KERN_ERR "Interrupt %u (real) is invalid,"
+- " disabling it.\n", vec);
+- xics_disable_real_irq(vec);
+- } else
+- irq = irq_offset_up(irq);
+- }
+- return irq;
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+-{
+- int cpu = smp_processor_id();
+-
+- ops->qirr_info(cpu, 0xff);
+-
+- WARN_ON(cpu_is_offline(cpu));
+-
+- while (xics_ipi_message[cpu].value) {
+- if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
+- &xics_ipi_message[cpu].value)) {
+- mb();
+- smp_message_recv(PPC_MSG_CALL_FUNCTION, regs);
+- }
+- if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
+- &xics_ipi_message[cpu].value)) {
+- mb();
+- smp_message_recv(PPC_MSG_RESCHEDULE, regs);
+- }
+-#if 0
+- if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK,
+- &xics_ipi_message[cpu].value)) {
+- mb();
+- smp_message_recv(PPC_MSG_MIGRATE_TASK, regs);
+- }
+-#endif
+-#ifdef CONFIG_DEBUGGER
+- if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
+- &xics_ipi_message[cpu].value)) {
+- mb();
+- smp_message_recv(PPC_MSG_DEBUGGER_BREAK, regs);
+- }
+-#endif
+- }
+- return IRQ_HANDLED;
+-}
+-
+-void xics_cause_IPI(int cpu)
+-{
+- ops->qirr_info(cpu, IPI_PRIORITY);
+-}
+-#endif /* CONFIG_SMP */
+-
+-void xics_setup_cpu(void)
+-{
+- int cpu = smp_processor_id();
+-
+- ops->cppr_info(cpu, 0xff);
+- iosync();
+-
+- /*
+- * Put the calling processor into the GIQ. This is really only
+- * necessary from a secondary thread as the OF start-cpu interface
+- * performs this function for us on primary threads.
+- *
+- * XXX: undo of teardown on kexec needs this too, as may hotplug
+- */
+- rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+- (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
+-}
+-
+-void xics_init_IRQ(void)
+-{
+- int i;
+- unsigned long intr_size = 0;
+- struct device_node *np;
+- uint *ireg, ilen, indx = 0;
+- unsigned long intr_base = 0;
+- struct xics_interrupt_node {
+- unsigned long addr;
+- unsigned long size;
+- } intnodes[NR_CPUS];
+-
+- ppc64_boot_msg(0x20, "XICS Init");
+-
+- ibm_get_xive = rtas_token("ibm,get-xive");
+- ibm_set_xive = rtas_token("ibm,set-xive");
+- ibm_int_on = rtas_token("ibm,int-on");
+- ibm_int_off = rtas_token("ibm,int-off");
+-
+- np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation");
+- if (!np)
+- panic("xics_init_IRQ: can't find interrupt presentation");
+-
+-nextnode:
+- ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL);
+- if (ireg) {
+- /*
+- * set node starting index for this node
+- */
+- indx = *ireg;
+- }
+-
+- ireg = (uint *)get_property(np, "reg", &ilen);
+- if (!ireg)
+- panic("xics_init_IRQ: can't find interrupt reg property");
+-
+- while (ilen) {
+- intnodes[indx].addr = (unsigned long)*ireg++ << 32;
+- ilen -= sizeof(uint);
+- intnodes[indx].addr |= *ireg++;
+- ilen -= sizeof(uint);
+- intnodes[indx].size = (unsigned long)*ireg++ << 32;
+- ilen -= sizeof(uint);
+- intnodes[indx].size |= *ireg++;
+- ilen -= sizeof(uint);
+- indx++;
+- if (indx >= NR_CPUS) break;
+- }
+-
+- np = of_find_node_by_type(np, "PowerPC-External-Interrupt-Presentation");
+- if ((indx < NR_CPUS) && np) goto nextnode;
+-
+- /* Find the server numbers for the boot cpu. */
+- for (np = of_find_node_by_type(NULL, "cpu");
+- np;
+- np = of_find_node_by_type(np, "cpu")) {
+- ireg = (uint *)get_property(np, "reg", &ilen);
+- if (ireg && ireg[0] == boot_cpuid_phys) {
+- ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s",
+- &ilen);
+- i = ilen / sizeof(int);
+- if (ireg && i > 0) {
+- default_server = ireg[0];
+- default_distrib_server = ireg[i-1]; /* take last element */
+- }
+- ireg = (uint *)get_property(np,
+- "ibm,interrupt-server#-size", NULL);
+- if (ireg)
+- interrupt_server_size = *ireg;
+- break;
+- }
+- }
+- of_node_put(np);
+-
+- intr_base = intnodes[0].addr;
+- intr_size = intnodes[0].size;
+-
+- np = of_find_node_by_type(NULL, "interrupt-controller");
+- if (!np) {
+- printk(KERN_WARNING "xics: no ISA interrupt controller\n");
+- xics_irq_8259_cascade_real = -1;
+- xics_irq_8259_cascade = -1;
+- } else {
+- ireg = (uint *) get_property(np, "interrupts", NULL);
+- if (!ireg)
+- panic("xics_init_IRQ: can't find ISA interrupts property");
+-
+- xics_irq_8259_cascade_real = *ireg;
+- xics_irq_8259_cascade
+- = virt_irq_create_mapping(xics_irq_8259_cascade_real);
+- of_node_put(np);
+- }
+-
+- if (systemcfg->platform == PLATFORM_PSERIES) {
+-#ifdef CONFIG_SMP
+- for_each_cpu(i) {
+- int hard_id;
+-
+- /* FIXME: Do this dynamically! --RR */
+- if (!cpu_present(i))
+- continue;
+-
+- hard_id = get_hard_smp_processor_id(i);
+- xics_per_cpu[i] = ioremap(intnodes[hard_id].addr,
+- intnodes[hard_id].size);
+- }
+-#else
+- xics_per_cpu[0] = ioremap(intr_base, intr_size);
+-#endif /* CONFIG_SMP */
+- } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
+- ops = &pSeriesLP_ops;
+- }
+-
+- xics_8259_pic.enable = i8259_pic.enable;
+- xics_8259_pic.disable = i8259_pic.disable;
+- for (i = 0; i < 16; ++i)
+- get_irq_desc(i)->handler = &xics_8259_pic;
+- for (; i < NR_IRQS; ++i)
+- get_irq_desc(i)->handler = &xics_pic;
+-
+- xics_setup_cpu();
+-
+- ppc64_boot_msg(0x21, "XICS Done");
+-}
+-
+-/*
+- * We cant do this in init_IRQ because we need the memory subsystem up for
+- * request_irq()
+- */
+-static int __init xics_setup_i8259(void)
+-{
+- if (ppc64_interrupt_controller == IC_PPC_XIC &&
+- xics_irq_8259_cascade != -1) {
+- if (request_irq(irq_offset_up(xics_irq_8259_cascade),
+- no_action, 0, "8259 cascade", NULL))
+- printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
+- "cascade\n");
+- i8259_init(0);
+- }
+- return 0;
+-}
+-arch_initcall(xics_setup_i8259);
+-
+-#ifdef CONFIG_SMP
+-void xics_request_IPIs(void)
+-{
+- virt_irq_to_real_map[XICS_IPI] = XICS_IPI;
+-
+- /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+- request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, SA_INTERRUPT,
+- "IPI", NULL);
+- get_irq_desc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU;
+-}
+-#endif
+-
+-static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
+-{
+- unsigned int irq;
+- int status;
+- int xics_status[2];
+- unsigned long newmask;
+- cpumask_t tmp = CPU_MASK_NONE;
+-
+- irq = virt_irq_to_real(irq_offset_down(virq));
+- if (irq == XICS_IPI || irq == NO_IRQ)
+- return;
+-
+- status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
+-
+- if (status) {
+- printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
+- "returns %d\n", irq, status);
+- return;
+- }
+-
+- /* For the moment only implement delivery to all cpus or one cpu */
+- if (cpus_equal(cpumask, CPU_MASK_ALL)) {
+- newmask = default_distrib_server;
+- } else {
+- cpus_and(tmp, cpu_online_map, cpumask);
+- if (cpus_empty(tmp))
+- return;
+- newmask = get_hard_smp_processor_id(first_cpu(tmp));
+- }
+-
+- status = rtas_call(ibm_set_xive, 3, 1, NULL,
+- irq, newmask, xics_status[1]);
+-
+- if (status) {
+- printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
+- "returns %d\n", irq, status);
+- return;
+- }
+-}
+-
+-void xics_teardown_cpu(int secondary)
+-{
+- int cpu = smp_processor_id();
+-
+- ops->cppr_info(cpu, 0x00);
+- iosync();
+-
+- /*
+- * Some machines need to have at least one cpu in the GIQ,
+- * so leave the master cpu in the group.
+- */
+- if (secondary) {
+- /*
+- * we need to EOI the IPI if we got here from kexec down IPI
+- *
+- * probably need to check all the other interrupts too
+- * should we be flagging idle loop instead?
+- * or creating some task to be scheduled?
+- */
+- ops->xirr_info_set(cpu, XICS_IPI);
+- rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+- (1UL << interrupt_server_size) - 1 -
+- default_distrib_server, 0);
+- }
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-/* Interrupts are disabled. */
+-void xics_migrate_irqs_away(void)
+-{
+- int status;
+- unsigned int irq, virq, cpu = smp_processor_id();
+-
+- /* Reject any interrupt that was queued to us... */
+- ops->cppr_info(cpu, 0);
+- iosync();
+-
+- /* remove ourselves from the global interrupt queue */
+- status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+- (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
+- WARN_ON(status < 0);
+-
+- /* Allow IPIs again... */
+- ops->cppr_info(cpu, DEFAULT_PRIORITY);
+- iosync();
+-
+- for_each_irq(virq) {
+- irq_desc_t *desc;
+- int xics_status[2];
+- unsigned long flags;
+-
+- /* We cant set affinity on ISA interrupts */
+- if (virq < irq_offset_value())
+- continue;
+-
+- desc = get_irq_desc(virq);
+- irq = virt_irq_to_real(irq_offset_down(virq));
+-
+- /* We need to get IPIs still. */
+- if (irq == XICS_IPI || irq == NO_IRQ)
+- continue;
+-
+- /* We only need to migrate enabled IRQS */
+- if (desc == NULL || desc->handler == NULL
+- || desc->action == NULL
+- || desc->handler->set_affinity == NULL)
+- continue;
+-
+- spin_lock_irqsave(&desc->lock, flags);
+-
+- status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
+- if (status) {
+- printk(KERN_ERR "migrate_irqs_away: irq=%u "
+- "ibm,get-xive returns %d\n",
+- virq, status);
+- goto unlock;
+- }
+-
+- /*
+- * We only support delivery to all cpus or to one cpu.
+- * The irq has to be migrated only in the single cpu
+- * case.
+- */
+- if (xics_status[0] != get_hard_smp_processor_id(cpu))
+- goto unlock;
+-
+- printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
+- virq, cpu);
+-
+- /* Reset affinity to all cpus */
+- desc->handler->set_affinity(virq, CPU_MASK_ALL);
+- irq_affinity[virq] = CPU_MASK_ALL;
+-unlock:
+- spin_unlock_irqrestore(&desc->lock, flags);
+- }
+-}
+-#endif
+diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile
+--- a/arch/ppc64/lib/Makefile
++++ b/arch/ppc64/lib/Makefile
+@@ -2,17 +2,4 @@
+ # Makefile for ppc64-specific library files..
+ #
+
+-lib-y := checksum.o string.o strcase.o
+-lib-y += copypage.o memcpy.o copyuser.o usercopy.o
+-
+-# Lock primitives are defined as no-ops in include/linux/spinlock.h
+-# for non-SMP configs. Don't build the real versions.
+-
+-lib-$(CONFIG_SMP) += locks.o
+-
+-# e2a provides EBCDIC to ASCII conversions.
+-ifdef CONFIG_PPC_ISERIES
+-obj-y += e2a.o
+-endif
+-
+-lib-$(CONFIG_DEBUG_KERNEL) += sstep.o
++lib-y := string.o
+diff --git a/arch/ppc64/lib/checksum.S b/arch/ppc64/lib/checksum.S
+deleted file mode 100644
+--- a/arch/ppc64/lib/checksum.S
++++ /dev/null
+@@ -1,229 +0,0 @@
+-/*
+- * This file contains assembly-language implementations
+- * of IP-style 1's complement checksum routines.
+- *
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.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.
+- *
+- * Severely hacked about by Paul Mackerras (paulus at cs.anu.edu.au).
+- */
+-
+-#include <linux/sys.h>
+-#include <asm/processor.h>
+-#include <asm/errno.h>
+-#include <asm/ppc_asm.h>
+-
+-/*
+- * ip_fast_csum(r3=buf, r4=len) -- Optimized for IP header
+- * len is in words and is always >= 5.
+- *
+- * In practice len == 5, but this is not guaranteed. So this code does not
+- * attempt to use doubleword instructions.
+- */
+-_GLOBAL(ip_fast_csum)
+- lwz r0,0(r3)
+- lwzu r5,4(r3)
+- addic. r4,r4,-2
+- addc r0,r0,r5
+- mtctr r4
+- blelr-
+-1: lwzu r4,4(r3)
+- adde r0,r0,r4
+- bdnz 1b
+- addze r0,r0 /* add in final carry */
+- rldicl r4,r0,32,0 /* fold two 32-bit halves together */
+- add r0,r0,r4
+- srdi r0,r0,32
+- rlwinm r3,r0,16,0,31 /* fold two halves together */
+- add r3,r0,r3
+- not r3,r3
+- srwi r3,r3,16
+- blr
+-
+-/*
+- * Compute checksum of TCP or UDP pseudo-header:
+- * csum_tcpudp_magic(r3=saddr, r4=daddr, r5=len, r6=proto, r7=sum)
+- * No real gain trying to do this specially for 64 bit, but
+- * the 32 bit addition may spill into the upper bits of
+- * the doubleword so we still must fold it down from 64.
+- */
+-_GLOBAL(csum_tcpudp_magic)
+- rlwimi r5,r6,16,0,15 /* put proto in upper half of len */
+- addc r0,r3,r4 /* add 4 32-bit words together */
+- adde r0,r0,r5
+- adde r0,r0,r7
+- rldicl r4,r0,32,0 /* fold 64 bit value */
+- add r0,r4,r0
+- srdi r0,r0,32
+- rlwinm r3,r0,16,0,31 /* fold two halves together */
+- add r3,r0,r3
+- not r3,r3
+- srwi r3,r3,16
+- blr
+-
+-/*
+- * Computes the checksum of a memory block at buff, length len,
+- * and adds in "sum" (32-bit).
+- *
+- * This code assumes at least halfword alignment, though the length
+- * can be any number of bytes. The sum is accumulated in r5.
+- *
+- * csum_partial(r3=buff, r4=len, r5=sum)
+- */
+-_GLOBAL(csum_partial)
+- subi r3,r3,8 /* we'll offset by 8 for the loads */
+- srdi. r6,r4,3 /* divide by 8 for doubleword count */
+- addic r5,r5,0 /* clear carry */
+- beq 3f /* if we're doing < 8 bytes */
+- andi. r0,r3,2 /* aligned on a word boundary already? */
+- beq+ 1f
+- lhz r6,8(r3) /* do 2 bytes to get aligned */
+- addi r3,r3,2
+- subi r4,r4,2
+- addc r5,r5,r6
+- srdi. r6,r4,3 /* recompute number of doublewords */
+- beq 3f /* any left? */
+-1: mtctr r6
+-2: ldu r6,8(r3) /* main sum loop */
+- adde r5,r5,r6
+- bdnz 2b
+- andi. r4,r4,7 /* compute bytes left to sum after doublewords */
+-3: cmpwi 0,r4,4 /* is at least a full word left? */
+- blt 4f
+- lwz r6,8(r3) /* sum this word */
+- addi r3,r3,4
+- subi r4,r4,4
+- adde r5,r5,r6
+-4: cmpwi 0,r4,2 /* is at least a halfword left? */
+- blt+ 5f
+- lhz r6,8(r3) /* sum this halfword */
+- addi r3,r3,2
+- subi r4,r4,2
+- adde r5,r5,r6
+-5: cmpwi 0,r4,1 /* is at least a byte left? */
+- bne+ 6f
+- lbz r6,8(r3) /* sum this byte */
+- slwi r6,r6,8 /* this byte is assumed to be the upper byte of a halfword */
+- adde r5,r5,r6
+-6: addze r5,r5 /* add in final carry */
+- rldicl r4,r5,32,0 /* fold two 32-bit halves together */
+- add r3,r4,r5
+- srdi r3,r3,32
+- blr
+-
+-/*
+- * Computes the checksum of a memory block at src, length len,
+- * and adds in "sum" (32-bit), while copying the block to dst.
+- * If an access exception occurs on src or dst, it stores -EFAULT
+- * to *src_err or *dst_err respectively, and (for an error on
+- * src) zeroes the rest of dst.
+- *
+- * This code needs to be reworked to take advantage of 64 bit sum+copy.
+- * However, due to tokenring halfword alignment problems this will be very
+- * tricky. For now we'll leave it until we instrument it somehow.
+- *
+- * csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err)
+- */
+-_GLOBAL(csum_partial_copy_generic)
+- addic r0,r6,0
+- subi r3,r3,4
+- subi r4,r4,4
+- srwi. r6,r5,2
+- beq 3f /* if we're doing < 4 bytes */
+- andi. r9,r4,2 /* Align dst to longword boundary */
+- beq+ 1f
+-81: lhz r6,4(r3) /* do 2 bytes to get aligned */
+- addi r3,r3,2
+- subi r5,r5,2
+-91: sth r6,4(r4)
+- addi r4,r4,2
+- addc r0,r0,r6
+- srwi. r6,r5,2 /* # words to do */
+- beq 3f
+-1: mtctr r6
+-82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */
+-92: stwu r6,4(r4) /* be unnecessary to unroll this loop */
+- adde r0,r0,r6
+- bdnz 82b
+- andi. r5,r5,3
+-3: cmpwi 0,r5,2
+- blt+ 4f
+-83: lhz r6,4(r3)
+- addi r3,r3,2
+- subi r5,r5,2
+-93: sth r6,4(r4)
+- addi r4,r4,2
+- adde r0,r0,r6
+-4: cmpwi 0,r5,1
+- bne+ 5f
+-84: lbz r6,4(r3)
+-94: stb r6,4(r4)
+- slwi r6,r6,8 /* Upper byte of word */
+- adde r0,r0,r6
+-5: addze r3,r0 /* add in final carry (unlikely with 64-bit regs) */
+- rldicl r4,r3,32,0 /* fold 64 bit value */
+- add r3,r4,r3
+- srdi r3,r3,32
+- blr
+-
+-/* These shouldn't go in the fixup section, since that would
+- cause the ex_table addresses to get out of order. */
+-
+- .globl src_error_1
+-src_error_1:
+- li r6,0
+- subi r5,r5,2
+-95: sth r6,4(r4)
+- addi r4,r4,2
+- srwi. r6,r5,2
+- beq 3f
+- mtctr r6
+- .globl src_error_2
+-src_error_2:
+- li r6,0
+-96: stwu r6,4(r4)
+- bdnz 96b
+-3: andi. r5,r5,3
+- beq src_error
+- .globl src_error_3
+-src_error_3:
+- li r6,0
+- mtctr r5
+- addi r4,r4,3
+-97: stbu r6,1(r4)
+- bdnz 97b
+- .globl src_error
+-src_error:
+- cmpdi 0,r7,0
+- beq 1f
+- li r6,-EFAULT
+- stw r6,0(r7)
+-1: addze r3,r0
+- blr
+-
+- .globl dst_error
+-dst_error:
+- cmpdi 0,r8,0
+- beq 1f
+- li r6,-EFAULT
+- stw r6,0(r8)
+-1: addze r3,r0
+- blr
+-
+-.section __ex_table,"a"
+- .align 3
+- .llong 81b,src_error_1
+- .llong 91b,dst_error
+- .llong 82b,src_error_2
+- .llong 92b,dst_error
+- .llong 83b,src_error_3
+- .llong 93b,dst_error
+- .llong 84b,src_error_3
+- .llong 94b,dst_error
+- .llong 95b,dst_error
+- .llong 96b,dst_error
+- .llong 97b,dst_error
+diff --git a/arch/ppc64/lib/copypage.S b/arch/ppc64/lib/copypage.S
+deleted file mode 100644
+--- a/arch/ppc64/lib/copypage.S
++++ /dev/null
+@@ -1,121 +0,0 @@
+-/*
+- * arch/ppc64/lib/copypage.S
+- *
+- * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+- *
+- * 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 <asm/processor.h>
+-#include <asm/ppc_asm.h>
+-
+-_GLOBAL(copy_page)
+- std r31,-8(1)
+- std r30,-16(1)
+- std r29,-24(1)
+- std r28,-32(1)
+- std r27,-40(1)
+- std r26,-48(1)
+- std r25,-56(1)
+- std r24,-64(1)
+- std r23,-72(1)
+- std r22,-80(1)
+- std r21,-88(1)
+- std r20,-96(1)
+- li r5,4096/32 - 1
+- addi r3,r3,-8
+- li r12,5
+-0: addi r5,r5,-24
+- mtctr r12
+- ld r22,640(4)
+- ld r21,512(4)
+- ld r20,384(4)
+- ld r11,256(4)
+- ld r9,128(4)
+- ld r7,0(4)
+- ld r25,648(4)
+- ld r24,520(4)
+- ld r23,392(4)
+- ld r10,264(4)
+- ld r8,136(4)
+- ldu r6,8(4)
+- cmpwi r5,24
+-1: std r22,648(3)
+- std r21,520(3)
+- std r20,392(3)
+- std r11,264(3)
+- std r9,136(3)
+- std r7,8(3)
+- ld r28,648(4)
+- ld r27,520(4)
+- ld r26,392(4)
+- ld r31,264(4)
+- ld r30,136(4)
+- ld r29,8(4)
+- std r25,656(3)
+- std r24,528(3)
+- std r23,400(3)
+- std r10,272(3)
+- std r8,144(3)
+- std r6,16(3)
+- ld r22,656(4)
+- ld r21,528(4)
+- ld r20,400(4)
+- ld r11,272(4)
+- ld r9,144(4)
+- ld r7,16(4)
+- std r28,664(3)
+- std r27,536(3)
+- std r26,408(3)
+- std r31,280(3)
+- std r30,152(3)
+- stdu r29,24(3)
+- ld r25,664(4)
+- ld r24,536(4)
+- ld r23,408(4)
+- ld r10,280(4)
+- ld r8,152(4)
+- ldu r6,24(4)
+- bdnz 1b
+- std r22,648(3)
+- std r21,520(3)
+- std r20,392(3)
+- std r11,264(3)
+- std r9,136(3)
+- std r7,8(3)
+- addi r4,r4,640
+- addi r3,r3,648
+- bge 0b
+- mtctr r5
+- ld r7,0(4)
+- ld r8,8(4)
+- ldu r9,16(4)
+-3: ld r10,8(4)
+- std r7,8(3)
+- ld r7,16(4)
+- std r8,16(3)
+- ld r8,24(4)
+- std r9,24(3)
+- ldu r9,32(4)
+- stdu r10,32(3)
+- bdnz 3b
+-4: ld r10,8(4)
+- std r7,8(3)
+- std r8,16(3)
+- std r9,24(3)
+- std r10,32(3)
+-9: ld r20,-96(1)
+- ld r21,-88(1)
+- ld r22,-80(1)
+- ld r23,-72(1)
+- ld r24,-64(1)
+- ld r25,-56(1)
+- ld r26,-48(1)
+- ld r27,-40(1)
+- ld r28,-32(1)
+- ld r29,-24(1)
+- ld r30,-16(1)
+- ld r31,-8(1)
+- blr
+diff --git a/arch/ppc64/lib/copyuser.S b/arch/ppc64/lib/copyuser.S
+deleted file mode 100644
+--- a/arch/ppc64/lib/copyuser.S
++++ /dev/null
+@@ -1,576 +0,0 @@
+-/*
+- * arch/ppc64/lib/copyuser.S
+- *
+- * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+- *
+- * 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 <asm/processor.h>
+-#include <asm/ppc_asm.h>
+-
+- .align 7
+-_GLOBAL(__copy_tofrom_user)
+- /* first check for a whole page copy on a page boundary */
+- cmpldi cr1,r5,16
+- cmpdi cr6,r5,4096
+- or r0,r3,r4
+- neg r6,r3 /* LS 3 bits = # bytes to 8-byte dest bdry */
+- andi. r0,r0,4095
+- std r3,-24(r1)
+- crand cr0*4+2,cr0*4+2,cr6*4+2
+- std r4,-16(r1)
+- std r5,-8(r1)
+- dcbt 0,r4
+- beq .Lcopy_page
+- andi. r6,r6,7
+- mtcrf 0x01,r5
+- blt cr1,.Lshort_copy
+- bne .Ldst_unaligned
+-.Ldst_aligned:
+- andi. r0,r4,7
+- addi r3,r3,-16
+- bne .Lsrc_unaligned
+- srdi r7,r5,4
+-20: ld r9,0(r4)
+- addi r4,r4,-8
+- mtctr r7
+- andi. r5,r5,7
+- bf cr7*4+0,22f
+- addi r3,r3,8
+- addi r4,r4,8
+- mr r8,r9
+- blt cr1,72f
+-21: ld r9,8(r4)
+-70: std r8,8(r3)
+-22: ldu r8,16(r4)
+-71: stdu r9,16(r3)
+- bdnz 21b
+-72: std r8,8(r3)
+- beq+ 3f
+- addi r3,r3,16
+-23: ld r9,8(r4)
+-.Ldo_tail:
+- bf cr7*4+1,1f
+- rotldi r9,r9,32
+-73: stw r9,0(r3)
+- addi r3,r3,4
+-1: bf cr7*4+2,2f
+- rotldi r9,r9,16
+-74: sth r9,0(r3)
+- addi r3,r3,2
+-2: bf cr7*4+3,3f
+- rotldi r9,r9,8
+-75: stb r9,0(r3)
+-3: li r3,0
+- blr
+-
+-.Lsrc_unaligned:
+- srdi r6,r5,3
+- addi r5,r5,-16
+- subf r4,r0,r4
+- srdi r7,r5,4
+- sldi r10,r0,3
+- cmpldi cr6,r6,3
+- andi. r5,r5,7
+- mtctr r7
+- subfic r11,r10,64
+- add r5,r5,r0
+- bt cr7*4+0,28f
+-
+-24: ld r9,0(r4) /* 3+2n loads, 2+2n stores */
+-25: ld r0,8(r4)
+- sld r6,r9,r10
+-26: ldu r9,16(r4)
+- srd r7,r0,r11
+- sld r8,r0,r10
+- or r7,r7,r6
+- blt cr6,79f
+-27: ld r0,8(r4)
+- b 2f
+-
+-28: ld r0,0(r4) /* 4+2n loads, 3+2n stores */
+-29: ldu r9,8(r4)
+- sld r8,r0,r10
+- addi r3,r3,-8
+- blt cr6,5f
+-30: ld r0,8(r4)
+- srd r12,r9,r11
+- sld r6,r9,r10
+-31: ldu r9,16(r4)
+- or r12,r8,r12
+- srd r7,r0,r11
+- sld r8,r0,r10
+- addi r3,r3,16
+- beq cr6,78f
+-
+-1: or r7,r7,r6
+-32: ld r0,8(r4)
+-76: std r12,8(r3)
+-2: srd r12,r9,r11
+- sld r6,r9,r10
+-33: ldu r9,16(r4)
+- or r12,r8,r12
+-77: stdu r7,16(r3)
+- srd r7,r0,r11
+- sld r8,r0,r10
+- bdnz 1b
+-
+-78: std r12,8(r3)
+- or r7,r7,r6
+-79: std r7,16(r3)
+-5: srd r12,r9,r11
+- or r12,r8,r12
+-80: std r12,24(r3)
+- bne 6f
+- li r3,0
+- blr
+-6: cmpwi cr1,r5,8
+- addi r3,r3,32
+- sld r9,r9,r10
+- ble cr1,.Ldo_tail
+-34: ld r0,8(r4)
+- srd r7,r0,r11
+- or r9,r7,r9
+- b .Ldo_tail
+-
+-.Ldst_unaligned:
+- mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */
+- subf r5,r6,r5
+- li r7,0
+- cmpldi r1,r5,16
+- bf cr7*4+3,1f
+-35: lbz r0,0(r4)
+-81: stb r0,0(r3)
+- addi r7,r7,1
+-1: bf cr7*4+2,2f
+-36: lhzx r0,r7,r4
+-82: sthx r0,r7,r3
+- addi r7,r7,2
+-2: bf cr7*4+1,3f
+-37: lwzx r0,r7,r4
+-83: stwx r0,r7,r3
+-3: mtcrf 0x01,r5
+- add r4,r6,r4
+- add r3,r6,r3
+- b .Ldst_aligned
+-
+-.Lshort_copy:
+- bf cr7*4+0,1f
+-38: lwz r0,0(r4)
+-39: lwz r9,4(r4)
+- addi r4,r4,8
+-84: stw r0,0(r3)
+-85: stw r9,4(r3)
+- addi r3,r3,8
+-1: bf cr7*4+1,2f
+-40: lwz r0,0(r4)
+- addi r4,r4,4
+-86: stw r0,0(r3)
+- addi r3,r3,4
+-2: bf cr7*4+2,3f
+-41: lhz r0,0(r4)
+- addi r4,r4,2
+-87: sth r0,0(r3)
+- addi r3,r3,2
+-3: bf cr7*4+3,4f
+-42: lbz r0,0(r4)
+-88: stb r0,0(r3)
+-4: li r3,0
+- blr
+-
+-/*
+- * exception handlers follow
+- * we have to return the number of bytes not copied
+- * for an exception on a load, we set the rest of the destination to 0
+- */
+-
+-136:
+-137:
+- add r3,r3,r7
+- b 1f
+-130:
+-131:
+- addi r3,r3,8
+-120:
+-122:
+-124:
+-125:
+-126:
+-127:
+-128:
+-129:
+-133:
+- addi r3,r3,8
+-121:
+-132:
+- addi r3,r3,8
+-123:
+-134:
+-135:
+-138:
+-139:
+-140:
+-141:
+-142:
+-
+-/*
+- * here we have had a fault on a load and r3 points to the first
+- * unmodified byte of the destination
+- */
+-1: ld r6,-24(r1)
+- ld r4,-16(r1)
+- ld r5,-8(r1)
+- subf r6,r6,r3
+- add r4,r4,r6
+- subf r5,r6,r5 /* #bytes left to go */
+-
+-/*
+- * first see if we can copy any more bytes before hitting another exception
+- */
+- mtctr r5
+-43: lbz r0,0(r4)
+- addi r4,r4,1
+-89: stb r0,0(r3)
+- addi r3,r3,1
+- bdnz 43b
+- li r3,0 /* huh? all copied successfully this time? */
+- blr
+-
+-/*
+- * here we have trapped again, need to clear ctr bytes starting at r3
+- */
+-143: mfctr r5
+- li r0,0
+- mr r4,r3
+- mr r3,r5 /* return the number of bytes not copied */
+-1: andi. r9,r4,7
+- beq 3f
+-90: stb r0,0(r4)
+- addic. r5,r5,-1
+- addi r4,r4,1
+- bne 1b
+- blr
+-3: cmpldi cr1,r5,8
+- srdi r9,r5,3
+- andi. r5,r5,7
+- blt cr1,93f
+- mtctr r9
+-91: std r0,0(r4)
+- addi r4,r4,8
+- bdnz 91b
+-93: beqlr
+- mtctr r5
+-92: stb r0,0(r4)
+- addi r4,r4,1
+- bdnz 92b
+- blr
+-
+-/*
+- * exception handlers for stores: we just need to work
+- * out how many bytes weren't copied
+- */
+-182:
+-183:
+- add r3,r3,r7
+- b 1f
+-180:
+- addi r3,r3,8
+-171:
+-177:
+- addi r3,r3,8
+-170:
+-172:
+-176:
+-178:
+- addi r3,r3,4
+-185:
+- addi r3,r3,4
+-173:
+-174:
+-175:
+-179:
+-181:
+-184:
+-186:
+-187:
+-188:
+-189:
+-1:
+- ld r6,-24(r1)
+- ld r5,-8(r1)
+- add r6,r6,r5
+- subf r3,r3,r6 /* #bytes not copied */
+-190:
+-191:
+-192:
+- blr /* #bytes not copied in r3 */
+-
+- .section __ex_table,"a"
+- .align 3
+- .llong 20b,120b
+- .llong 21b,121b
+- .llong 70b,170b
+- .llong 22b,122b
+- .llong 71b,171b
+- .llong 72b,172b
+- .llong 23b,123b
+- .llong 73b,173b
+- .llong 74b,174b
+- .llong 75b,175b
+- .llong 24b,124b
+- .llong 25b,125b
+- .llong 26b,126b
+- .llong 27b,127b
+- .llong 28b,128b
+- .llong 29b,129b
+- .llong 30b,130b
+- .llong 31b,131b
+- .llong 32b,132b
+- .llong 76b,176b
+- .llong 33b,133b
+- .llong 77b,177b
+- .llong 78b,178b
+- .llong 79b,179b
+- .llong 80b,180b
+- .llong 34b,134b
+- .llong 35b,135b
+- .llong 81b,181b
+- .llong 36b,136b
+- .llong 82b,182b
+- .llong 37b,137b
+- .llong 83b,183b
+- .llong 38b,138b
+- .llong 39b,139b
+- .llong 84b,184b
+- .llong 85b,185b
+- .llong 40b,140b
+- .llong 86b,186b
+- .llong 41b,141b
+- .llong 87b,187b
+- .llong 42b,142b
+- .llong 88b,188b
+- .llong 43b,143b
+- .llong 89b,189b
+- .llong 90b,190b
+- .llong 91b,191b
+- .llong 92b,192b
+-
+- .text
+-
+-/*
+- * Routine to copy a whole page of data, optimized for POWER4.
+- * On POWER4 it is more than 50% faster than the simple loop
+- * above (following the .Ldst_aligned label) but it runs slightly
+- * slower on POWER3.
+- */
+-.Lcopy_page:
+- std r31,-32(1)
+- std r30,-40(1)
+- std r29,-48(1)
+- std r28,-56(1)
+- std r27,-64(1)
+- std r26,-72(1)
+- std r25,-80(1)
+- std r24,-88(1)
+- std r23,-96(1)
+- std r22,-104(1)
+- std r21,-112(1)
+- std r20,-120(1)
+- li r5,4096/32 - 1
+- addi r3,r3,-8
+- li r0,5
+-0: addi r5,r5,-24
+- mtctr r0
+-20: ld r22,640(4)
+-21: ld r21,512(4)
+-22: ld r20,384(4)
+-23: ld r11,256(4)
+-24: ld r9,128(4)
+-25: ld r7,0(4)
+-26: ld r25,648(4)
+-27: ld r24,520(4)
+-28: ld r23,392(4)
+-29: ld r10,264(4)
+-30: ld r8,136(4)
+-31: ldu r6,8(4)
+- cmpwi r5,24
+-1:
+-32: std r22,648(3)
+-33: std r21,520(3)
+-34: std r20,392(3)
+-35: std r11,264(3)
+-36: std r9,136(3)
+-37: std r7,8(3)
+-38: ld r28,648(4)
+-39: ld r27,520(4)
+-40: ld r26,392(4)
+-41: ld r31,264(4)
+-42: ld r30,136(4)
+-43: ld r29,8(4)
+-44: std r25,656(3)
+-45: std r24,528(3)
+-46: std r23,400(3)
+-47: std r10,272(3)
+-48: std r8,144(3)
+-49: std r6,16(3)
+-50: ld r22,656(4)
+-51: ld r21,528(4)
+-52: ld r20,400(4)
+-53: ld r11,272(4)
+-54: ld r9,144(4)
+-55: ld r7,16(4)
+-56: std r28,664(3)
+-57: std r27,536(3)
+-58: std r26,408(3)
+-59: std r31,280(3)
+-60: std r30,152(3)
+-61: stdu r29,24(3)
+-62: ld r25,664(4)
+-63: ld r24,536(4)
+-64: ld r23,408(4)
+-65: ld r10,280(4)
+-66: ld r8,152(4)
+-67: ldu r6,24(4)
+- bdnz 1b
+-68: std r22,648(3)
+-69: std r21,520(3)
+-70: std r20,392(3)
+-71: std r11,264(3)
+-72: std r9,136(3)
+-73: std r7,8(3)
+-74: addi r4,r4,640
+-75: addi r3,r3,648
+- bge 0b
+- mtctr r5
+-76: ld r7,0(4)
+-77: ld r8,8(4)
+-78: ldu r9,16(4)
+-3:
+-79: ld r10,8(4)
+-80: std r7,8(3)
+-81: ld r7,16(4)
+-82: std r8,16(3)
+-83: ld r8,24(4)
+-84: std r9,24(3)
+-85: ldu r9,32(4)
+-86: stdu r10,32(3)
+- bdnz 3b
+-4:
+-87: ld r10,8(4)
+-88: std r7,8(3)
+-89: std r8,16(3)
+-90: std r9,24(3)
+-91: std r10,32(3)
+-9: ld r20,-120(1)
+- ld r21,-112(1)
+- ld r22,-104(1)
+- ld r23,-96(1)
+- ld r24,-88(1)
+- ld r25,-80(1)
+- ld r26,-72(1)
+- ld r27,-64(1)
+- ld r28,-56(1)
+- ld r29,-48(1)
+- ld r30,-40(1)
+- ld r31,-32(1)
+- li r3,0
+- blr
+-
+-/*
+- * on an exception, reset to the beginning and jump back into the
+- * standard __copy_tofrom_user
+- */
+-100: ld r20,-120(1)
+- ld r21,-112(1)
+- ld r22,-104(1)
+- ld r23,-96(1)
+- ld r24,-88(1)
+- ld r25,-80(1)
+- ld r26,-72(1)
+- ld r27,-64(1)
+- ld r28,-56(1)
+- ld r29,-48(1)
+- ld r30,-40(1)
+- ld r31,-32(1)
+- ld r3,-24(r1)
+- ld r4,-16(r1)
+- li r5,4096
+- b .Ldst_aligned
+-
+- .section __ex_table,"a"
+- .align 3
+- .llong 20b,100b
+- .llong 21b,100b
+- .llong 22b,100b
+- .llong 23b,100b
+- .llong 24b,100b
+- .llong 25b,100b
+- .llong 26b,100b
+- .llong 27b,100b
+- .llong 28b,100b
+- .llong 29b,100b
+- .llong 30b,100b
+- .llong 31b,100b
+- .llong 32b,100b
+- .llong 33b,100b
+- .llong 34b,100b
+- .llong 35b,100b
+- .llong 36b,100b
+- .llong 37b,100b
+- .llong 38b,100b
+- .llong 39b,100b
+- .llong 40b,100b
+- .llong 41b,100b
+- .llong 42b,100b
+- .llong 43b,100b
+- .llong 44b,100b
+- .llong 45b,100b
+- .llong 46b,100b
+- .llong 47b,100b
+- .llong 48b,100b
+- .llong 49b,100b
+- .llong 50b,100b
+- .llong 51b,100b
+- .llong 52b,100b
+- .llong 53b,100b
+- .llong 54b,100b
+- .llong 55b,100b
+- .llong 56b,100b
+- .llong 57b,100b
+- .llong 58b,100b
+- .llong 59b,100b
+- .llong 60b,100b
+- .llong 61b,100b
+- .llong 62b,100b
+- .llong 63b,100b
+- .llong 64b,100b
+- .llong 65b,100b
+- .llong 66b,100b
+- .llong 67b,100b
+- .llong 68b,100b
+- .llong 69b,100b
+- .llong 70b,100b
+- .llong 71b,100b
+- .llong 72b,100b
+- .llong 73b,100b
+- .llong 74b,100b
+- .llong 75b,100b
+- .llong 76b,100b
+- .llong 77b,100b
+- .llong 78b,100b
+- .llong 79b,100b
+- .llong 80b,100b
+- .llong 81b,100b
+- .llong 82b,100b
+- .llong 83b,100b
+- .llong 84b,100b
+- .llong 85b,100b
+- .llong 86b,100b
+- .llong 87b,100b
+- .llong 88b,100b
+- .llong 89b,100b
+- .llong 90b,100b
+- .llong 91b,100b
+diff --git a/arch/ppc64/lib/e2a.c b/arch/ppc64/lib/e2a.c
+deleted file mode 100644
+--- a/arch/ppc64/lib/e2a.c
++++ /dev/null
+@@ -1,108 +0,0 @@
+-/*
+- * arch/ppc64/lib/e2a.c
+- *
+- * EBCDIC to ASCII conversion
+- *
+- * This function moved here from arch/ppc64/kernel/viopath.c
+- *
+- * (C) Copyright 2000-2004 IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License as
+- * published by the Free Software Foundation; either version 2 of the
+- * License, or (at your option) anyu 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/module.h>
+-
+-unsigned char e2a(unsigned char x)
+-{
+- switch (x) {
+- case 0xF0:
+- return '0';
+- case 0xF1:
+- return '1';
+- case 0xF2:
+- return '2';
+- case 0xF3:
+- return '3';
+- case 0xF4:
+- return '4';
+- case 0xF5:
+- return '5';
+- case 0xF6:
+- return '6';
+- case 0xF7:
+- return '7';
+- case 0xF8:
+- return '8';
+- case 0xF9:
+- return '9';
+- case 0xC1:
+- return 'A';
+- case 0xC2:
+- return 'B';
+- case 0xC3:
+- return 'C';
+- case 0xC4:
+- return 'D';
+- case 0xC5:
+- return 'E';
+- case 0xC6:
+- return 'F';
+- case 0xC7:
+- return 'G';
+- case 0xC8:
+- return 'H';
+- case 0xC9:
+- return 'I';
+- case 0xD1:
+- return 'J';
+- case 0xD2:
+- return 'K';
+- case 0xD3:
+- return 'L';
+- case 0xD4:
+- return 'M';
+- case 0xD5:
+- return 'N';
+- case 0xD6:
+- return 'O';
+- case 0xD7:
+- return 'P';
+- case 0xD8:
+- return 'Q';
+- case 0xD9:
+- return 'R';
+- case 0xE2:
+- return 'S';
+- case 0xE3:
+- return 'T';
+- case 0xE4:
+- return 'U';
+- case 0xE5:
+- return 'V';
+- case 0xE6:
+- return 'W';
+- case 0xE7:
+- return 'X';
+- case 0xE8:
+- return 'Y';
+- case 0xE9:
+- return 'Z';
+- }
+- return ' ';
+-}
+-EXPORT_SYMBOL(e2a);
+-
+-
+diff --git a/arch/ppc64/lib/locks.c b/arch/ppc64/lib/locks.c
+deleted file mode 100644
+--- a/arch/ppc64/lib/locks.c
++++ /dev/null
+@@ -1,95 +0,0 @@
+-/*
+- * Spin and read/write lock operations.
+- *
+- * Copyright (C) 2001-2004 Paul Mackerras <paulus at au.ibm.com>, IBM
+- * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
+- * Copyright (C) 2002 Dave Engebretsen <engebret at us.ibm.com>, IBM
+- * Rework to support virtual processors
+- *
+- * 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/spinlock.h>
+-#include <linux/module.h>
+-#include <linux/stringify.h>
+-#include <asm/hvcall.h>
+-#include <asm/iSeries/HvCall.h>
+-
+-/* waiting for a spinlock... */
+-#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
+-
+-void __spin_yield(raw_spinlock_t *lock)
+-{
+- unsigned int lock_value, holder_cpu, yield_count;
+- struct paca_struct *holder_paca;
+-
+- lock_value = lock->slock;
+- if (lock_value == 0)
+- return;
+- holder_cpu = lock_value & 0xffff;
+- BUG_ON(holder_cpu >= NR_CPUS);
+- holder_paca = &paca[holder_cpu];
+- yield_count = holder_paca->lppaca.yield_count;
+- if ((yield_count & 1) == 0)
+- return; /* virtual cpu is currently running */
+- rmb();
+- if (lock->slock != lock_value)
+- return; /* something has changed */
+-#ifdef CONFIG_PPC_ISERIES
+- HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
+- ((u64)holder_cpu << 32) | yield_count);
+-#else
+- plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+- yield_count);
+-#endif
+-}
+-
+-/*
+- * Waiting for a read lock or a write lock on a rwlock...
+- * This turns out to be the same for read and write locks, since
+- * we only know the holder if it is write-locked.
+- */
+-void __rw_yield(raw_rwlock_t *rw)
+-{
+- int lock_value;
+- unsigned int holder_cpu, yield_count;
+- struct paca_struct *holder_paca;
+-
+- lock_value = rw->lock;
+- if (lock_value >= 0)
+- return; /* no write lock at present */
+- holder_cpu = lock_value & 0xffff;
+- BUG_ON(holder_cpu >= NR_CPUS);
+- holder_paca = &paca[holder_cpu];
+- yield_count = holder_paca->lppaca.yield_count;
+- if ((yield_count & 1) == 0)
+- return; /* virtual cpu is currently running */
+- rmb();
+- if (rw->lock != lock_value)
+- return; /* something has changed */
+-#ifdef CONFIG_PPC_ISERIES
+- HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
+- ((u64)holder_cpu << 32) | yield_count);
+-#else
+- plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+- yield_count);
+-#endif
+-}
+-#endif
+-
+-void __raw_spin_unlock_wait(raw_spinlock_t *lock)
+-{
+- while (lock->slock) {
+- HMT_low();
+- if (SHARED_PROCESSOR)
+- __spin_yield(lock);
+- }
+- HMT_medium();
+-}
+-
+-EXPORT_SYMBOL(__raw_spin_unlock_wait);
+diff --git a/arch/ppc64/lib/memcpy.S b/arch/ppc64/lib/memcpy.S
+deleted file mode 100644
+--- a/arch/ppc64/lib/memcpy.S
++++ /dev/null
+@@ -1,172 +0,0 @@
+-/*
+- * arch/ppc64/lib/memcpy.S
+- *
+- * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+- *
+- * 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 <asm/processor.h>
+-#include <asm/ppc_asm.h>
+-
+- .align 7
+-_GLOBAL(memcpy)
+- mtcrf 0x01,r5
+- cmpldi cr1,r5,16
+- neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
+- andi. r6,r6,7
+- dcbt 0,r4
+- blt cr1,.Lshort_copy
+- bne .Ldst_unaligned
+-.Ldst_aligned:
+- andi. r0,r4,7
+- addi r3,r3,-16
+- bne .Lsrc_unaligned
+- srdi r7,r5,4
+- ld r9,0(r4)
+- addi r4,r4,-8
+- mtctr r7
+- andi. r5,r5,7
+- bf cr7*4+0,2f
+- addi r3,r3,8
+- addi r4,r4,8
+- mr r8,r9
+- blt cr1,3f
+-1: ld r9,8(r4)
+- std r8,8(r3)
+-2: ldu r8,16(r4)
+- stdu r9,16(r3)
+- bdnz 1b
+-3: std r8,8(r3)
+- beqlr
+- addi r3,r3,16
+- ld r9,8(r4)
+-.Ldo_tail:
+- bf cr7*4+1,1f
+- rotldi r9,r9,32
+- stw r9,0(r3)
+- addi r3,r3,4
+-1: bf cr7*4+2,2f
+- rotldi r9,r9,16
+- sth r9,0(r3)
+- addi r3,r3,2
+-2: bf cr7*4+3,3f
+- rotldi r9,r9,8
+- stb r9,0(r3)
+-3: blr
+-
+-.Lsrc_unaligned:
+- srdi r6,r5,3
+- addi r5,r5,-16
+- subf r4,r0,r4
+- srdi r7,r5,4
+- sldi r10,r0,3
+- cmpdi cr6,r6,3
+- andi. r5,r5,7
+- mtctr r7
+- subfic r11,r10,64
+- add r5,r5,r0
+-
+- bt cr7*4+0,0f
+-
+- ld r9,0(r4) # 3+2n loads, 2+2n stores
+- ld r0,8(r4)
+- sld r6,r9,r10
+- ldu r9,16(r4)
+- srd r7,r0,r11
+- sld r8,r0,r10
+- or r7,r7,r6
+- blt cr6,4f
+- ld r0,8(r4)
+- # s1<< in r8, d0=(s0<<|s1>>) in r7, s3 in r0, s2 in r9, nix in r6 & r12
+- b 2f
+-
+-0: ld r0,0(r4) # 4+2n loads, 3+2n stores
+- ldu r9,8(r4)
+- sld r8,r0,r10
+- addi r3,r3,-8
+- blt cr6,5f
+- ld r0,8(r4)
+- srd r12,r9,r11
+- sld r6,r9,r10
+- ldu r9,16(r4)
+- or r12,r8,r12
+- srd r7,r0,r11
+- sld r8,r0,r10
+- addi r3,r3,16
+- beq cr6,3f
+-
+- # d0=(s0<<|s1>>) in r12, s1<< in r6, s2>> in r7, s2<< in r8, s3 in r9
+-1: or r7,r7,r6
+- ld r0,8(r4)
+- std r12,8(r3)
+-2: srd r12,r9,r11
+- sld r6,r9,r10
+- ldu r9,16(r4)
+- or r12,r8,r12
+- stdu r7,16(r3)
+- srd r7,r0,r11
+- sld r8,r0,r10
+- bdnz 1b
+-
+-3: std r12,8(r3)
+- or r7,r7,r6
+-4: std r7,16(r3)
+-5: srd r12,r9,r11
+- or r12,r8,r12
+- std r12,24(r3)
+- beqlr
+- cmpwi cr1,r5,8
+- addi r3,r3,32
+- sld r9,r9,r10
+- ble cr1,.Ldo_tail
+- ld r0,8(r4)
+- srd r7,r0,r11
+- or r9,r7,r9
+- b .Ldo_tail
+-
+-.Ldst_unaligned:
+- mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7
+- subf r5,r6,r5
+- li r7,0
+- cmpldi r1,r5,16
+- bf cr7*4+3,1f
+- lbz r0,0(r4)
+- stb r0,0(r3)
+- addi r7,r7,1
+-1: bf cr7*4+2,2f
+- lhzx r0,r7,r4
+- sthx r0,r7,r3
+- addi r7,r7,2
+-2: bf cr7*4+1,3f
+- lwzx r0,r7,r4
+- stwx r0,r7,r3
+-3: mtcrf 0x01,r5
+- add r4,r6,r4
+- add r3,r6,r3
+- b .Ldst_aligned
+-
+-.Lshort_copy:
+- bf cr7*4+0,1f
+- lwz r0,0(r4)
+- lwz r9,4(r4)
+- addi r4,r4,8
+- stw r0,0(r3)
+- stw r9,4(r3)
+- addi r3,r3,8
+-1: bf cr7*4+1,2f
+- lwz r0,0(r4)
+- addi r4,r4,4
+- stw r0,0(r3)
+- addi r3,r3,4
+-2: bf cr7*4+2,3f
+- lhz r0,0(r4)
+- addi r4,r4,2
+- sth r0,0(r3)
+- addi r3,r3,2
+-3: bf cr7*4+3,4f
+- lbz r0,0(r4)
+- stb r0,0(r3)
+-4: blr
+diff --git a/arch/ppc64/lib/sstep.c b/arch/ppc64/lib/sstep.c
+deleted file mode 100644
+--- a/arch/ppc64/lib/sstep.c
++++ /dev/null
+@@ -1,141 +0,0 @@
+-/*
+- * Single-step support.
+- *
+- * Copyright (C) 2004 Paul Mackerras <paulus at au.ibm.com>, IBM
+- *
+- * 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/kernel.h>
+-#include <linux/ptrace.h>
+-#include <asm/sstep.h>
+-#include <asm/processor.h>
+-
+-extern char system_call_common[];
+-
+-/* Bits in SRR1 that are copied from MSR */
+-#define MSR_MASK 0xffffffff87c0ffff
+-
+-/*
+- * Determine whether a conditional branch instruction would branch.
+- */
+-static int branch_taken(unsigned int instr, struct pt_regs *regs)
+-{
+- unsigned int bo = (instr >> 21) & 0x1f;
+- unsigned int bi;
+-
+- if ((bo & 4) == 0) {
+- /* decrement counter */
+- --regs->ctr;
+- if (((bo >> 1) & 1) ^ (regs->ctr == 0))
+- return 0;
+- }
+- if ((bo & 0x10) == 0) {
+- /* check bit from CR */
+- bi = (instr >> 16) & 0x1f;
+- if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
+- return 0;
+- }
+- return 1;
+-}
+-
+-/*
+- * Emulate instructions that cause a transfer of control.
+- * Returns 1 if the step was emulated, 0 if not,
+- * or -1 if the instruction is one that should not be stepped,
+- * such as an rfid, or a mtmsrd that would clear MSR_RI.
+- */
+-int emulate_step(struct pt_regs *regs, unsigned int instr)
+-{
+- unsigned int opcode, rd;
+- unsigned long int imm;
+-
+- opcode = instr >> 26;
+- switch (opcode) {
+- case 16: /* bc */
+- imm = (signed short)(instr & 0xfffc);
+- if ((instr & 2) == 0)
+- imm += regs->nip;
+- regs->nip += 4;
+- if ((regs->msr & MSR_SF) == 0)
+- regs->nip &= 0xffffffffUL;
+- if (instr & 1)
+- regs->link = regs->nip;
+- if (branch_taken(instr, regs))
+- regs->nip = imm;
+- return 1;
+- case 17: /* sc */
+- /*
+- * N.B. this uses knowledge about how the syscall
+- * entry code works. If that is changed, this will
+- * need to be changed also.
+- */
+- regs->gpr[9] = regs->gpr[13];
+- regs->gpr[11] = regs->nip + 4;
+- regs->gpr[12] = regs->msr & MSR_MASK;
+- regs->gpr[13] = (unsigned long) get_paca();
+- regs->nip = (unsigned long) &system_call_common;
+- regs->msr = MSR_KERNEL;
+- return 1;
+- case 18: /* b */
+- imm = instr & 0x03fffffc;
+- if (imm & 0x02000000)
+- imm -= 0x04000000;
+- if ((instr & 2) == 0)
+- imm += regs->nip;
+- if (instr & 1) {
+- regs->link = regs->nip + 4;
+- if ((regs->msr & MSR_SF) == 0)
+- regs->link &= 0xffffffffUL;
+- }
+- if ((regs->msr & MSR_SF) == 0)
+- imm &= 0xffffffffUL;
+- regs->nip = imm;
+- return 1;
+- case 19:
+- switch (instr & 0x7fe) {
+- case 0x20: /* bclr */
+- case 0x420: /* bcctr */
+- imm = (instr & 0x400)? regs->ctr: regs->link;
+- regs->nip += 4;
+- if ((regs->msr & MSR_SF) == 0) {
+- regs->nip &= 0xffffffffUL;
+- imm &= 0xffffffffUL;
+- }
+- if (instr & 1)
+- regs->link = regs->nip;
+- if (branch_taken(instr, regs))
+- regs->nip = imm;
+- return 1;
+- case 0x24: /* rfid, scary */
+- return -1;
+- }
+- case 31:
+- rd = (instr >> 21) & 0x1f;
+- switch (instr & 0x7fe) {
+- case 0xa6: /* mfmsr */
+- regs->gpr[rd] = regs->msr & MSR_MASK;
+- regs->nip += 4;
+- if ((regs->msr & MSR_SF) == 0)
+- regs->nip &= 0xffffffffUL;
+- return 1;
+- case 0x164: /* mtmsrd */
+- /* only MSR_EE and MSR_RI get changed if bit 15 set */
+- /* mtmsrd doesn't change MSR_HV and MSR_ME */
+- imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
+- imm = (regs->msr & MSR_MASK & ~imm)
+- | (regs->gpr[rd] & imm);
+- if ((imm & MSR_RI) == 0)
+- /* can't step mtmsrd that would clear MSR_RI */
+- return -1;
+- regs->msr = imm;
+- regs->nip += 4;
+- if ((imm & MSR_SF) == 0)
+- regs->nip &= 0xffffffffUL;
+- return 1;
+- }
+- }
+- return 0;
+-}
+diff --git a/arch/ppc64/lib/strcase.c b/arch/ppc64/lib/strcase.c
+deleted file mode 100644
+--- a/arch/ppc64/lib/strcase.c
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * c 2001 PPC 64 Team, IBM Corp
+- *
+- * 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/ctype.h>
+-
+-int strcasecmp(const char *s1, const char *s2)
+-{
+- int c1, c2;
+-
+- do {
+- c1 = tolower(*s1++);
+- c2 = tolower(*s2++);
+- } while (c1 == c2 && c1 != 0);
+- return c1 - c2;
+-}
+-
+-int strncasecmp(const char *s1, const char *s2, int n)
+-{
+- int c1, c2;
+-
+- do {
+- c1 = tolower(*s1++);
+- c2 = tolower(*s2++);
+- } while ((--n > 0) && c1 == c2 && c1 != 0);
+- return c1 - c2;
+-}
+diff --git a/arch/ppc64/lib/string.S b/arch/ppc64/lib/string.S
+--- a/arch/ppc64/lib/string.S
++++ b/arch/ppc64/lib/string.S
+@@ -65,112 +65,6 @@ _GLOBAL(strlen)
+ subf r3,r3,r4
+ blr
+
+-_GLOBAL(memset)
+- neg r0,r3
+- rlwimi r4,r4,8,16,23
+- andi. r0,r0,7 /* # bytes to be 8-byte aligned */
+- rlwimi r4,r4,16,0,15
+- cmplw cr1,r5,r0 /* do we get that far? */
+- rldimi r4,r4,32,0
+- mtcrf 1,r0
+- mr r6,r3
+- blt cr1,8f
+- beq+ 3f /* if already 8-byte aligned */
+- subf r5,r0,r5
+- bf 31,1f
+- stb r4,0(r6)
+- addi r6,r6,1
+-1: bf 30,2f
+- sth r4,0(r6)
+- addi r6,r6,2
+-2: bf 29,3f
+- stw r4,0(r6)
+- addi r6,r6,4
+-3: srdi. r0,r5,6
+- clrldi r5,r5,58
+- mtctr r0
+- beq 5f
+-4: std r4,0(r6)
+- std r4,8(r6)
+- std r4,16(r6)
+- std r4,24(r6)
+- std r4,32(r6)
+- std r4,40(r6)
+- std r4,48(r6)
+- std r4,56(r6)
+- addi r6,r6,64
+- bdnz 4b
+-5: srwi. r0,r5,3
+- clrlwi r5,r5,29
+- mtcrf 1,r0
+- beq 8f
+- bf 29,6f
+- std r4,0(r6)
+- std r4,8(r6)
+- std r4,16(r6)
+- std r4,24(r6)
+- addi r6,r6,32
+-6: bf 30,7f
+- std r4,0(r6)
+- std r4,8(r6)
+- addi r6,r6,16
+-7: bf 31,8f
+- std r4,0(r6)
+- addi r6,r6,8
+-8: cmpwi r5,0
+- mtcrf 1,r5
+- beqlr+
+- bf 29,9f
+- stw r4,0(r6)
+- addi r6,r6,4
+-9: bf 30,10f
+- sth r4,0(r6)
+- addi r6,r6,2
+-10: bflr 31
+- stb r4,0(r6)
+- blr
+-
+-_GLOBAL(memmove)
+- cmplw 0,r3,r4
+- bgt .backwards_memcpy
+- b .memcpy
+-
+-_GLOBAL(backwards_memcpy)
+- rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+- add r6,r3,r5
+- add r4,r4,r5
+- beq 2f
+- andi. r0,r6,3
+- mtctr r7
+- bne 5f
+-1: lwz r7,-4(r4)
+- lwzu r8,-8(r4)
+- stw r7,-4(r6)
+- stwu r8,-8(r6)
+- bdnz 1b
+- andi. r5,r5,7
+-2: cmplwi 0,r5,4
+- blt 3f
+- lwzu r0,-4(r4)
+- subi r5,r5,4
+- stwu r0,-4(r6)
+-3: cmpwi 0,r5,0
+- beqlr
+- mtctr r5
+-4: lbzu r0,-1(r4)
+- stbu r0,-1(r6)
+- bdnz 4b
+- blr
+-5: mtctr r0
+-6: lbzu r7,-1(r4)
+- stbu r7,-1(r6)
+- bdnz 6b
+- subf r5,r0,r5
+- rlwinm. r7,r5,32-3,3,31
+- beq 2b
+- mtctr r7
+- b 1b
+-
+ _GLOBAL(memcmp)
+ cmpwi 0,r5,0
+ ble- 2f
+diff --git a/arch/ppc64/lib/usercopy.c b/arch/ppc64/lib/usercopy.c
+deleted file mode 100644
+--- a/arch/ppc64/lib/usercopy.c
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/*
+- * Functions which are too large to be inlined.
+- *
+- * 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 <asm/uaccess.h>
+-
+-unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
+-{
+- if (likely(access_ok(VERIFY_READ, from, n)))
+- n = __copy_from_user(to, from, n);
+- else
+- memset(to, 0, n);
+- return n;
+-}
+-
+-unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
+-{
+- if (likely(access_ok(VERIFY_WRITE, to, n)))
+- n = __copy_to_user(to, from, n);
+- return n;
+-}
+-
+-unsigned long copy_in_user(void __user *to, const void __user *from,
+- unsigned long n)
+-{
+- might_sleep();
+- if (likely(access_ok(VERIFY_READ, from, n) &&
+- access_ok(VERIFY_WRITE, to, n)))
+- n =__copy_tofrom_user(to, from, n);
+- return n;
+-}
+-
+-EXPORT_SYMBOL(copy_from_user);
+-EXPORT_SYMBOL(copy_to_user);
+-EXPORT_SYMBOL(copy_in_user);
+-
+diff --git a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile
+deleted file mode 100644
+--- a/arch/ppc64/mm/Makefile
++++ /dev/null
+@@ -1,11 +0,0 @@
+-#
+-# Makefile for the linux ppc-specific parts of the memory manager.
+-#
+-
+-EXTRA_CFLAGS += -mno-minimal-toc
+-
+-obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
+- slb_low.o slb.o stab.o mmap.o
+-obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
+-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+-obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
+diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/fault.c
++++ /dev/null
+@@ -1,333 +0,0 @@
+-/*
+- * arch/ppc/mm/fault.c
+- *
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Derived from "arch/i386/mm/fault.c"
+- * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+- *
+- * Modified by Cort Dougan and Paul Mackerras.
+- *
+- * Modified for PPC64 by Dave Engebretsen (engebret at ibm.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/types.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/interrupt.h>
+-#include <linux/smp_lock.h>
+-#include <linux/module.h>
+-#include <linux/kprobes.h>
+-
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/system.h>
+-#include <asm/uaccess.h>
+-#include <asm/kdebug.h>
+-#include <asm/siginfo.h>
+-
+-/*
+- * Check whether the instruction at regs->nip is a store using
+- * an update addressing form which will update r1.
+- */
+-static int store_updates_sp(struct pt_regs *regs)
+-{
+- unsigned int inst;
+-
+- if (get_user(inst, (unsigned int __user *)regs->nip))
+- return 0;
+- /* check for 1 in the rA field */
+- if (((inst >> 16) & 0x1f) != 1)
+- return 0;
+- /* check major opcode */
+- switch (inst >> 26) {
+- case 37: /* stwu */
+- case 39: /* stbu */
+- case 45: /* sthu */
+- case 53: /* stfsu */
+- case 55: /* stfdu */
+- return 1;
+- case 62: /* std or stdu */
+- return (inst & 3) == 1;
+- case 31:
+- /* check minor opcode */
+- switch ((inst >> 1) & 0x3ff) {
+- case 181: /* stdux */
+- case 183: /* stwux */
+- case 247: /* stbux */
+- case 439: /* sthux */
+- case 695: /* stfsux */
+- case 759: /* stfdux */
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+-static void do_dabr(struct pt_regs *regs, unsigned long error_code)
+-{
+- siginfo_t info;
+-
+- if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+- 11, SIGSEGV) == NOTIFY_STOP)
+- return;
+-
+- if (debugger_dabr_match(regs))
+- return;
+-
+- /* Clear the DABR */
+- set_dabr(0);
+-
+- /* Deliver the signal to userspace */
+- info.si_signo = SIGTRAP;
+- info.si_errno = 0;
+- info.si_code = TRAP_HWBKPT;
+- info.si_addr = (void __user *)regs->nip;
+- force_sig_info(SIGTRAP, &info, current);
+-}
+-
+-/*
+- * The error_code parameter is
+- * - DSISR for a non-SLB data access fault,
+- * - SRR1 & 0x08000000 for a non-SLB instruction access fault
+- * - 0 any SLB fault.
+- * The return value is 0 if the fault was handled, or the signal
+- * number if this is a kernel fault that can't be handled here.
+- */
+-int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
+- unsigned long error_code)
+-{
+- struct vm_area_struct * vma;
+- struct mm_struct *mm = current->mm;
+- siginfo_t info;
+- unsigned long code = SEGV_MAPERR;
+- unsigned long is_write = error_code & DSISR_ISSTORE;
+- unsigned long trap = TRAP(regs);
+- unsigned long is_exec = trap == 0x400;
+-
+- BUG_ON((trap == 0x380) || (trap == 0x480));
+-
+- if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, error_code,
+- 11, SIGSEGV) == NOTIFY_STOP)
+- return 0;
+-
+- if (trap == 0x300) {
+- if (debugger_fault_handler(regs))
+- return 0;
+- }
+-
+- /* On a kernel SLB miss we can only check for a valid exception entry */
+- if (!user_mode(regs) && (address >= TASK_SIZE))
+- return SIGSEGV;
+-
+- if (error_code & DSISR_DABRMATCH) {
+- do_dabr(regs, error_code);
+- return 0;
+- }
+-
+- if (in_atomic() || mm == NULL) {
+- if (!user_mode(regs))
+- return SIGSEGV;
+- /* in_atomic() in user mode is really bad,
+- as is current->mm == NULL. */
+- printk(KERN_EMERG "Page fault in user mode with"
+- "in_atomic() = %d mm = %p\n", in_atomic(), mm);
+- printk(KERN_EMERG "NIP = %lx MSR = %lx\n",
+- regs->nip, regs->msr);
+- die("Weird page fault", regs, SIGSEGV);
+- }
+-
+- /* When running in the kernel we expect faults to occur only to
+- * addresses in user space. All other faults represent errors in the
+- * kernel and should generate an OOPS. Unfortunatly, in the case of an
+- * erroneous fault occuring in a code path which already holds mmap_sem
+- * we will deadlock attempting to validate the fault against the
+- * address space. Luckily the kernel only validly references user
+- * space from well defined areas of code, which are listed in the
+- * exceptions table.
+- *
+- * As the vast majority of faults will be valid we will only perform
+- * the source reference check when there is a possibilty of a deadlock.
+- * Attempt to lock the address space, if we cannot we then validate the
+- * source. If this is invalid we can skip the address space check,
+- * thus avoiding the deadlock.
+- */
+- if (!down_read_trylock(&mm->mmap_sem)) {
+- if (!user_mode(regs) && !search_exception_tables(regs->nip))
+- goto bad_area_nosemaphore;
+-
+- down_read(&mm->mmap_sem);
+- }
+-
+- vma = find_vma(mm, address);
+- if (!vma)
+- goto bad_area;
+-
+- if (vma->vm_start <= address) {
+- goto good_area;
+- }
+- if (!(vma->vm_flags & VM_GROWSDOWN))
+- goto bad_area;
+-
+- /*
+- * N.B. The POWER/Open ABI allows programs to access up to
+- * 288 bytes below the stack pointer.
+- * The kernel signal delivery code writes up to about 1.5kB
+- * below the stack pointer (r1) before decrementing it.
+- * The exec code can write slightly over 640kB to the stack
+- * before setting the user r1. Thus we allow the stack to
+- * expand to 1MB without further checks.
+- */
+- if (address + 0x100000 < vma->vm_end) {
+- /* get user regs even if this fault is in kernel mode */
+- struct pt_regs *uregs = current->thread.regs;
+- if (uregs == NULL)
+- goto bad_area;
+-
+- /*
+- * A user-mode access to an address a long way below
+- * the stack pointer is only valid if the instruction
+- * is one which would update the stack pointer to the
+- * address accessed if the instruction completed,
+- * i.e. either stwu rs,n(r1) or stwux rs,r1,rb
+- * (or the byte, halfword, float or double forms).
+- *
+- * If we don't check this then any write to the area
+- * between the last mapped region and the stack will
+- * expand the stack rather than segfaulting.
+- */
+- if (address + 2048 < uregs->gpr[1]
+- && (!user_mode(regs) || !store_updates_sp(regs)))
+- goto bad_area;
+- }
+-
+- if (expand_stack(vma, address))
+- goto bad_area;
+-
+-good_area:
+- code = SEGV_ACCERR;
+-
+- if (is_exec) {
+- /* protection fault */
+- if (error_code & DSISR_PROTFAULT)
+- goto bad_area;
+- if (!(vma->vm_flags & VM_EXEC))
+- goto bad_area;
+- /* a write */
+- } else if (is_write) {
+- if (!(vma->vm_flags & VM_WRITE))
+- goto bad_area;
+- /* a read */
+- } else {
+- if (!(vma->vm_flags & VM_READ))
+- goto bad_area;
+- }
+-
+- survive:
+- /*
+- * If for any reason at all we couldn't handle the fault,
+- * make sure we exit gracefully rather than endlessly redo
+- * the fault.
+- */
+- switch (handle_mm_fault(mm, vma, address, is_write)) {
+-
+- case VM_FAULT_MINOR:
+- current->min_flt++;
+- break;
+- case VM_FAULT_MAJOR:
+- current->maj_flt++;
+- break;
+- case VM_FAULT_SIGBUS:
+- goto do_sigbus;
+- case VM_FAULT_OOM:
+- goto out_of_memory;
+- default:
+- BUG();
+- }
+-
+- up_read(&mm->mmap_sem);
+- return 0;
+-
+-bad_area:
+- up_read(&mm->mmap_sem);
+-
+-bad_area_nosemaphore:
+- /* User mode accesses cause a SIGSEGV */
+- if (user_mode(regs)) {
+- info.si_signo = SIGSEGV;
+- info.si_errno = 0;
+- info.si_code = code;
+- info.si_addr = (void __user *) address;
+- force_sig_info(SIGSEGV, &info, current);
+- return 0;
+- }
+-
+- if (trap == 0x400 && (error_code & DSISR_PROTFAULT)
+- && printk_ratelimit())
+- printk(KERN_CRIT "kernel tried to execute NX-protected"
+- " page (%lx) - exploit attempt? (uid: %d)\n",
+- address, current->uid);
+-
+- return SIGSEGV;
+-
+-/*
+- * We ran out of memory, or some other thing happened to us that made
+- * us unable to handle the page fault gracefully.
+- */
+-out_of_memory:
+- up_read(&mm->mmap_sem);
+- if (current->pid == 1) {
+- yield();
+- down_read(&mm->mmap_sem);
+- goto survive;
+- }
+- printk("VM: killing process %s\n", current->comm);
+- if (user_mode(regs))
+- do_exit(SIGKILL);
+- return SIGKILL;
+-
+-do_sigbus:
+- up_read(&mm->mmap_sem);
+- if (user_mode(regs)) {
+- info.si_signo = SIGBUS;
+- info.si_errno = 0;
+- info.si_code = BUS_ADRERR;
+- info.si_addr = (void __user *)address;
+- force_sig_info(SIGBUS, &info, current);
+- return 0;
+- }
+- return SIGBUS;
+-}
+-
+-/*
+- * bad_page_fault is called when we have a bad access from the kernel.
+- * It is called from do_page_fault above and from some of the procedures
+- * in traps.c.
+- */
+-void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
+-{
+- const struct exception_table_entry *entry;
+-
+- /* Are we prepared to handle this fault? */
+- if ((entry = search_exception_tables(regs->nip)) != NULL) {
+- regs->nip = entry->fixup;
+- return;
+- }
+-
+- /* kernel has accessed a bad area */
+- die("Kernel access of bad area", regs, sig);
+-}
+diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
+deleted file mode 100644
+--- a/arch/ppc64/mm/hash_low.S
++++ /dev/null
+@@ -1,288 +0,0 @@
+-/*
+- * ppc64 MMU hashtable management routines
+- *
+- * (c) Copyright IBM Corp. 2003
+- *
+- * Maintained by: Benjamin Herrenschmidt
+- * <benh at kernel.crashing.org>
+- *
+- * This file is covered by the GNU Public Licence v2 as
+- * described in the kernel's COPYING file.
+- */
+-
+-#include <asm/processor.h>
+-#include <asm/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/page.h>
+-#include <asm/types.h>
+-#include <asm/ppc_asm.h>
+-#include <asm/asm-offsets.h>
+-#include <asm/cputable.h>
+-
+- .text
+-
+-/*
+- * Stackframe:
+- *
+- * +-> Back chain (SP + 256)
+- * | General register save area (SP + 112)
+- * | Parameter save area (SP + 48)
+- * | TOC save area (SP + 40)
+- * | link editor doubleword (SP + 32)
+- * | compiler doubleword (SP + 24)
+- * | LR save area (SP + 16)
+- * | CR save area (SP + 8)
+- * SP ---> +-- Back chain (SP + 0)
+- */
+-#define STACKFRAMESIZE 256
+-
+-/* Save parameters offsets */
+-#define STK_PARM(i) (STACKFRAMESIZE + 48 + ((i)-3)*8)
+-
+-/* Save non-volatile offsets */
+-#define STK_REG(i) (112 + ((i)-14)*8)
+-
+-/*
+- * _hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
+- * pte_t *ptep, unsigned long trap, int local)
+- *
+- * Adds a page to the hash table. This is the non-LPAR version for now
+- */
+-
+-_GLOBAL(__hash_page)
+- mflr r0
+- std r0,16(r1)
+- stdu r1,-STACKFRAMESIZE(r1)
+- /* Save all params that we need after a function call */
+- std r6,STK_PARM(r6)(r1)
+- std r8,STK_PARM(r8)(r1)
+-
+- /* Add _PAGE_PRESENT to access */
+- ori r4,r4,_PAGE_PRESENT
+-
+- /* Save non-volatile registers.
+- * r31 will hold "old PTE"
+- * r30 is "new PTE"
+- * r29 is "va"
+- * r28 is a hash value
+- * r27 is hashtab mask (maybe dynamic patched instead ?)
+- */
+- std r27,STK_REG(r27)(r1)
+- std r28,STK_REG(r28)(r1)
+- std r29,STK_REG(r29)(r1)
+- std r30,STK_REG(r30)(r1)
+- std r31,STK_REG(r31)(r1)
+-
+- /* Step 1:
+- *
+- * Check permissions, atomically mark the linux PTE busy
+- * and hashed.
+- */
+-1:
+- ldarx r31,0,r6
+- /* Check access rights (access & ~(pte_val(*ptep))) */
+- andc. r0,r4,r31
+- bne- htab_wrong_access
+- /* Check if PTE is busy */
+- andi. r0,r31,_PAGE_BUSY
+- /* If so, just bail out and refault if needed. Someone else
+- * is changing this PTE anyway and might hash it.
+- */
+- bne- bail_ok
+- /* Prepare new PTE value (turn access RW into DIRTY, then
+- * add BUSY,HASHPTE and ACCESSED)
+- */
+- rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
+- or r30,r30,r31
+- ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
+- /* Write the linux PTE atomically (setting busy) */
+- stdcx. r30,0,r6
+- bne- 1b
+- isync
+-
+- /* Step 2:
+- *
+- * Insert/Update the HPTE in the hash table. At this point,
+- * r4 (access) is re-useable, we use it for the new HPTE flags
+- */
+-
+- /* Calc va and put it in r29 */
+- rldicr r29,r5,28,63-28
+- rldicl r3,r3,0,36
+- or r29,r3,r29
+-
+- /* Calculate hash value for primary slot and store it in r28 */
+- rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
+- rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */
+- xor r28,r5,r0
+-
+- /* Convert linux PTE bits into HW equivalents */
+- andi. r3,r30,0x1fe /* Get basic set of flags */
+- xori r3,r3,HW_NO_EXEC /* _PAGE_EXEC -> NOEXEC */
+- rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
+- rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
+- and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY -> r0 bit 30 */
+- andc r0,r30,r0 /* r0 = pte & ~r0 */
+- rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
+-
+- /* We eventually do the icache sync here (maybe inline that
+- * code rather than call a C function...)
+- */
+-BEGIN_FTR_SECTION
+- mr r4,r30
+- mr r5,r7
+- bl .hash_page_do_lazy_icache
+-END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
+-
+- /* At this point, r3 contains new PP bits, save them in
+- * place of "access" in the param area (sic)
+- */
+- std r3,STK_PARM(r4)(r1)
+-
+- /* Get htab_hash_mask */
+- ld r4,htab_hash_mask at got(2)
+- ld r27,0(r4) /* htab_hash_mask -> r27 */
+-
+- /* Check if we may already be in the hashtable, in this case, we
+- * go to out-of-line code to try to modify the HPTE
+- */
+- andi. r0,r31,_PAGE_HASHPTE
+- bne htab_modify_pte
+-
+-htab_insert_pte:
+- /* Clear hpte bits in new pte (we also clear BUSY btw) and
+- * add _PAGE_HASHPTE
+- */
+- lis r0,_PAGE_HPTEFLAGS at h
+- ori r0,r0,_PAGE_HPTEFLAGS at l
+- andc r30,r30,r0
+- ori r30,r30,_PAGE_HASHPTE
+-
+- /* page number in r5 */
+- rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT
+-
+- /* Calculate primary group hash */
+- and r0,r28,r27
+- rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
+-
+- /* Call ppc_md.hpte_insert */
+- ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */
+- mr r4,r29 /* Retreive va */
+- li r6,0 /* no vflags */
+-_GLOBAL(htab_call_hpte_insert1)
+- bl . /* Will be patched by htab_finish_init() */
+- cmpdi 0,r3,0
+- bge htab_pte_insert_ok /* Insertion successful */
+- cmpdi 0,r3,-2 /* Critical failure */
+- beq- htab_pte_insert_failure
+-
+- /* Now try secondary slot */
+-
+- /* page number in r5 */
+- rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT
+-
+- /* Calculate secondary group hash */
+- andc r0,r27,r28
+- rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
+-
+- /* Call ppc_md.hpte_insert */
+- ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */
+- mr r4,r29 /* Retreive va */
+- li r6,HPTE_V_SECONDARY at l /* secondary slot */
+-_GLOBAL(htab_call_hpte_insert2)
+- bl . /* Will be patched by htab_finish_init() */
+- cmpdi 0,r3,0
+- bge+ htab_pte_insert_ok /* Insertion successful */
+- cmpdi 0,r3,-2 /* Critical failure */
+- beq- htab_pte_insert_failure
+-
+- /* Both are full, we need to evict something */
+- mftb r0
+- /* Pick a random group based on TB */
+- andi. r0,r0,1
+- mr r5,r28
+- bne 2f
+- not r5,r5
+-2: and r0,r5,r27
+- rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
+- /* Call ppc_md.hpte_remove */
+-_GLOBAL(htab_call_hpte_remove)
+- bl . /* Will be patched by htab_finish_init() */
+-
+- /* Try all again */
+- b htab_insert_pte
+-
+-bail_ok:
+- li r3,0
+- b bail
+-
+-htab_pte_insert_ok:
+- /* Insert slot number & secondary bit in PTE */
+- rldimi r30,r3,12,63-15
+-
+- /* Write out the PTE with a normal write
+- * (maybe add eieio may be good still ?)
+- */
+-htab_write_out_pte:
+- ld r6,STK_PARM(r6)(r1)
+- std r30,0(r6)
+- li r3, 0
+-bail:
+- ld r27,STK_REG(r27)(r1)
+- ld r28,STK_REG(r28)(r1)
+- ld r29,STK_REG(r29)(r1)
+- ld r30,STK_REG(r30)(r1)
+- ld r31,STK_REG(r31)(r1)
+- addi r1,r1,STACKFRAMESIZE
+- ld r0,16(r1)
+- mtlr r0
+- blr
+-
+-htab_modify_pte:
+- /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
+- mr r4,r3
+- rlwinm r3,r31,32-12,29,31
+-
+- /* Secondary group ? if yes, get a inverted hash value */
+- mr r5,r28
+- andi. r0,r31,_PAGE_SECONDARY
+- beq 1f
+- not r5,r5
+-1:
+- /* Calculate proper slot value for ppc_md.hpte_updatepp */
+- and r0,r5,r27
+- rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
+- add r3,r0,r3 /* add slot idx */
+-
+- /* Call ppc_md.hpte_updatepp */
+- mr r5,r29 /* va */
+- li r6,0 /* large is 0 */
+- ld r7,STK_PARM(r8)(r1) /* get "local" param */
+-_GLOBAL(htab_call_hpte_updatepp)
+- bl . /* Will be patched by htab_finish_init() */
+-
+- /* if we failed because typically the HPTE wasn't really here
+- * we try an insertion.
+- */
+- cmpdi 0,r3,-1
+- beq- htab_insert_pte
+-
+- /* Clear the BUSY bit and Write out the PTE */
+- li r0,_PAGE_BUSY
+- andc r30,r30,r0
+- b htab_write_out_pte
+-
+-htab_wrong_access:
+- /* Bail out clearing reservation */
+- stdcx. r31,0,r6
+- li r3,1
+- b bail
+-
+-htab_pte_insert_failure:
+- /* Bail out restoring old PTE */
+- ld r6,STK_PARM(r6)(r1)
+- std r31,0(r6)
+- li r3,-1
+- b bail
+-
+-
+diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/hash_native.c
++++ /dev/null
+@@ -1,453 +0,0 @@
+-/*
+- * native hashtable management.
+- *
+- * SMP scalability work:
+- * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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/spinlock.h>
+-#include <linux/bitops.h>
+-#include <linux/threads.h>
+-#include <linux/smp.h>
+-
+-#include <asm/abs_addr.h>
+-#include <asm/machdep.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/pgtable.h>
+-#include <asm/tlbflush.h>
+-#include <asm/tlb.h>
+-#include <asm/cputable.h>
+-
+-#define HPTE_LOCK_BIT 3
+-
+-static DEFINE_SPINLOCK(native_tlbie_lock);
+-
+-static inline void native_lock_hpte(hpte_t *hptep)
+-{
+- unsigned long *word = &hptep->v;
+-
+- while (1) {
+- if (!test_and_set_bit(HPTE_LOCK_BIT, word))
+- break;
+- while(test_bit(HPTE_LOCK_BIT, word))
+- cpu_relax();
+- }
+-}
+-
+-static inline void native_unlock_hpte(hpte_t *hptep)
+-{
+- unsigned long *word = &hptep->v;
+-
+- asm volatile("lwsync":::"memory");
+- clear_bit(HPTE_LOCK_BIT, word);
+-}
+-
+-long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+- unsigned long prpn, unsigned long vflags,
+- unsigned long rflags)
+-{
+- hpte_t *hptep = htab_address + hpte_group;
+- unsigned long hpte_v, hpte_r;
+- int i;
+-
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+- if (! (hptep->v & HPTE_V_VALID)) {
+- /* retry with lock held */
+- native_lock_hpte(hptep);
+- if (! (hptep->v & HPTE_V_VALID))
+- break;
+- native_unlock_hpte(hptep);
+- }
+-
+- hptep++;
+- }
+-
+- if (i == HPTES_PER_GROUP)
+- return -1;
+-
+- hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
+- if (vflags & HPTE_V_LARGE)
+- va &= ~(1UL << HPTE_V_AVPN_SHIFT);
+- hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
+-
+- hptep->r = hpte_r;
+- /* Guarantee the second dword is visible before the valid bit */
+- __asm__ __volatile__ ("eieio" : : : "memory");
+- /*
+- * Now set the first dword including the valid bit
+- * NOTE: this also unlocks the hpte
+- */
+- hptep->v = hpte_v;
+-
+- __asm__ __volatile__ ("ptesync" : : : "memory");
+-
+- return i | (!!(vflags & HPTE_V_SECONDARY) << 3);
+-}
+-
+-static long native_hpte_remove(unsigned long hpte_group)
+-{
+- hpte_t *hptep;
+- int i;
+- int slot_offset;
+- unsigned long hpte_v;
+-
+- /* pick a random entry to start at */
+- slot_offset = mftb() & 0x7;
+-
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+- hptep = htab_address + hpte_group + slot_offset;
+- hpte_v = hptep->v;
+-
+- if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) {
+- /* retry with lock held */
+- native_lock_hpte(hptep);
+- hpte_v = hptep->v;
+- if ((hpte_v & HPTE_V_VALID)
+- && !(hpte_v & HPTE_V_BOLTED))
+- break;
+- native_unlock_hpte(hptep);
+- }
+-
+- slot_offset++;
+- slot_offset &= 0x7;
+- }
+-
+- if (i == HPTES_PER_GROUP)
+- return -1;
+-
+- /* Invalidate the hpte. NOTE: this also unlocks it */
+- hptep->v = 0;
+-
+- return i;
+-}
+-
+-static inline void set_pp_bit(unsigned long pp, hpte_t *addr)
+-{
+- unsigned long old;
+- unsigned long *p = &addr->r;
+-
+- __asm__ __volatile__(
+- "1: ldarx %0,0,%3\n\
+- rldimi %0,%2,0,61\n\
+- stdcx. %0,0,%3\n\
+- bne 1b"
+- : "=&r" (old), "=m" (*p)
+- : "r" (pp), "r" (p), "m" (*p)
+- : "cc");
+-}
+-
+-/*
+- * Only works on small pages. Yes its ugly to have to check each slot in
+- * the group but we only use this during bootup.
+- */
+-static long native_hpte_find(unsigned long vpn)
+-{
+- hpte_t *hptep;
+- unsigned long hash;
+- unsigned long i, j;
+- long slot;
+- unsigned long hpte_v;
+-
+- hash = hpt_hash(vpn, 0);
+-
+- for (j = 0; j < 2; j++) {
+- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+- hptep = htab_address + slot;
+- hpte_v = hptep->v;
+-
+- if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11))
+- && (hpte_v & HPTE_V_VALID)
+- && ( !!(hpte_v & HPTE_V_SECONDARY) == j)) {
+- /* HPTE matches */
+- if (j)
+- slot = -slot;
+- return slot;
+- }
+- ++slot;
+- }
+- hash = ~hash;
+- }
+-
+- return -1;
+-}
+-
+-static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
+- unsigned long va, int large, int local)
+-{
+- hpte_t *hptep = htab_address + slot;
+- unsigned long hpte_v;
+- unsigned long avpn = va >> 23;
+- int ret = 0;
+-
+- if (large)
+- avpn &= ~1;
+-
+- native_lock_hpte(hptep);
+-
+- hpte_v = hptep->v;
+-
+- /* Even if we miss, we need to invalidate the TLB */
+- if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
+- || !(hpte_v & HPTE_V_VALID)) {
+- native_unlock_hpte(hptep);
+- ret = -1;
+- } else {
+- set_pp_bit(newpp, hptep);
+- native_unlock_hpte(hptep);
+- }
+-
+- /* Ensure it is out of the tlb too */
+- if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
+- tlbiel(va);
+- } else {
+- int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
+-
+- if (lock_tlbie)
+- spin_lock(&native_tlbie_lock);
+- tlbie(va, large);
+- if (lock_tlbie)
+- spin_unlock(&native_tlbie_lock);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * Update the page protection bits. Intended to be used to create
+- * guard pages for kernel data structures on pages which are bolted
+- * in the HPT. Assumes pages being operated on will not be stolen.
+- * Does not work on large pages.
+- *
+- * No need to lock here because we should be the only user.
+- */
+-static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
+-{
+- unsigned long vsid, va, vpn, flags = 0;
+- long slot;
+- hpte_t *hptep;
+- int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
+-
+- vsid = get_kernel_vsid(ea);
+- va = (vsid << 28) | (ea & 0x0fffffff);
+- vpn = va >> PAGE_SHIFT;
+-
+- slot = native_hpte_find(vpn);
+- if (slot == -1)
+- panic("could not find page to bolt\n");
+- hptep = htab_address + slot;
+-
+- set_pp_bit(newpp, hptep);
+-
+- /* Ensure it is out of the tlb too */
+- if (lock_tlbie)
+- spin_lock_irqsave(&native_tlbie_lock, flags);
+- tlbie(va, 0);
+- if (lock_tlbie)
+- spin_unlock_irqrestore(&native_tlbie_lock, flags);
+-}
+-
+-static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+- int large, int local)
+-{
+- hpte_t *hptep = htab_address + slot;
+- unsigned long hpte_v;
+- unsigned long avpn = va >> 23;
+- unsigned long flags;
+- int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
+-
+- if (large)
+- avpn &= ~1;
+-
+- local_irq_save(flags);
+- native_lock_hpte(hptep);
+-
+- hpte_v = hptep->v;
+-
+- /* Even if we miss, we need to invalidate the TLB */
+- if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
+- || !(hpte_v & HPTE_V_VALID)) {
+- native_unlock_hpte(hptep);
+- } else {
+- /* Invalidate the hpte. NOTE: this also unlocks it */
+- hptep->v = 0;
+- }
+-
+- /* Invalidate the tlb */
+- if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
+- tlbiel(va);
+- } else {
+- if (lock_tlbie)
+- spin_lock(&native_tlbie_lock);
+- tlbie(va, large);
+- if (lock_tlbie)
+- spin_unlock(&native_tlbie_lock);
+- }
+- local_irq_restore(flags);
+-}
+-
+-/*
+- * clear all mappings on kexec. All cpus are in real mode (or they will
+- * be when they isi), and we are the only one left. We rely on our kernel
+- * mapping being 0xC0's and the hardware ignoring those two real bits.
+- *
+- * TODO: add batching support when enabled. remember, no dynamic memory here,
+- * athough there is the control page available...
+- */
+-static void native_hpte_clear(void)
+-{
+- unsigned long slot, slots, flags;
+- hpte_t *hptep = htab_address;
+- unsigned long hpte_v;
+- unsigned long pteg_count;
+-
+- pteg_count = htab_hash_mask + 1;
+-
+- local_irq_save(flags);
+-
+- /* we take the tlbie lock and hold it. Some hardware will
+- * deadlock if we try to tlbie from two processors at once.
+- */
+- spin_lock(&native_tlbie_lock);
+-
+- slots = pteg_count * HPTES_PER_GROUP;
+-
+- for (slot = 0; slot < slots; slot++, hptep++) {
+- /*
+- * we could lock the pte here, but we are the only cpu
+- * running, right? and for crash dump, we probably
+- * don't want to wait for a maybe bad cpu.
+- */
+- hpte_v = hptep->v;
+-
+- if (hpte_v & HPTE_V_VALID) {
+- hptep->v = 0;
+- tlbie(slot2va(hpte_v, slot), hpte_v & HPTE_V_LARGE);
+- }
+- }
+-
+- spin_unlock(&native_tlbie_lock);
+- local_irq_restore(flags);
+-}
+-
+-static void native_flush_hash_range(unsigned long context,
+- unsigned long number, int local)
+-{
+- unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
+- int i, j;
+- hpte_t *hptep;
+- unsigned long hpte_v;
+- struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+- unsigned long large = batch->large;
+-
+- local_irq_save(flags);
+-
+- j = 0;
+- for (i = 0; i < number; i++) {
+- if (batch->addr[i] < KERNELBASE)
+- vsid = get_vsid(context, batch->addr[i]);
+- else
+- vsid = get_kernel_vsid(batch->addr[i]);
+-
+- va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
+- batch->vaddr[j] = va;
+- if (large)
+- vpn = va >> HPAGE_SHIFT;
+- else
+- vpn = va >> PAGE_SHIFT;
+- hash = hpt_hash(vpn, large);
+- secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
+- if (secondary)
+- hash = ~hash;
+- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
+-
+- hptep = htab_address + slot;
+-
+- avpn = va >> 23;
+- if (large)
+- avpn &= ~0x1UL;
+-
+- native_lock_hpte(hptep);
+-
+- hpte_v = hptep->v;
+-
+- /* Even if we miss, we need to invalidate the TLB */
+- if ((HPTE_V_AVPN_VAL(hpte_v) != avpn)
+- || !(hpte_v & HPTE_V_VALID)) {
+- native_unlock_hpte(hptep);
+- } else {
+- /* Invalidate the hpte. NOTE: this also unlocks it */
+- hptep->v = 0;
+- }
+-
+- j++;
+- }
+-
+- if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
+- asm volatile("ptesync":::"memory");
+-
+- for (i = 0; i < j; i++)
+- __tlbiel(batch->vaddr[i]);
+-
+- asm volatile("ptesync":::"memory");
+- } else {
+- int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
+-
+- if (lock_tlbie)
+- spin_lock(&native_tlbie_lock);
+-
+- asm volatile("ptesync":::"memory");
+-
+- for (i = 0; i < j; i++)
+- __tlbie(batch->vaddr[i], large);
+-
+- asm volatile("eieio; tlbsync; ptesync":::"memory");
+-
+- if (lock_tlbie)
+- spin_unlock(&native_tlbie_lock);
+- }
+-
+- local_irq_restore(flags);
+-}
+-
+-#ifdef CONFIG_PPC_PSERIES
+-/* Disable TLB batching on nighthawk */
+-static inline int tlb_batching_enabled(void)
+-{
+- struct device_node *root = of_find_node_by_path("/");
+- int enabled = 1;
+-
+- if (root) {
+- const char *model = get_property(root, "model", NULL);
+- if (model && !strcmp(model, "IBM,9076-N81"))
+- enabled = 0;
+- of_node_put(root);
+- }
+-
+- return enabled;
+-}
+-#else
+-static inline int tlb_batching_enabled(void)
+-{
+- return 1;
+-}
+-#endif
+-
+-void hpte_init_native(void)
+-{
+- ppc_md.hpte_invalidate = native_hpte_invalidate;
+- ppc_md.hpte_updatepp = native_hpte_updatepp;
+- ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp;
+- ppc_md.hpte_insert = native_hpte_insert;
+- ppc_md.hpte_remove = native_hpte_remove;
+- ppc_md.hpte_clear_all = native_hpte_clear;
+- if (tlb_batching_enabled())
+- ppc_md.flush_hash_range = native_flush_hash_range;
+- htab_finish_init();
+-}
+diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/hash_utils.c
++++ /dev/null
+@@ -1,438 +0,0 @@
+-/*
+- * PowerPC64 port by Mike Corrigan and Dave Engebretsen
+- * {mikejc|engebret}@us.ibm.com
+- *
+- * Copyright (c) 2000 Mike Corrigan <mikejc at us.ibm.com>
+- *
+- * SMP scalability work:
+- * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * Module name: htab.c
+- *
+- * Description:
+- * PowerPC Hashed Page Table functions
+- *
+- * 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/config.h>
+-#include <linux/spinlock.h>
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/proc_fs.h>
+-#include <linux/stat.h>
+-#include <linux/sysctl.h>
+-#include <linux/ctype.h>
+-#include <linux/cache.h>
+-#include <linux/init.h>
+-#include <linux/signal.h>
+-
+-#include <asm/ppcdebug.h>
+-#include <asm/processor.h>
+-#include <asm/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/page.h>
+-#include <asm/types.h>
+-#include <asm/system.h>
+-#include <asm/uaccess.h>
+-#include <asm/machdep.h>
+-#include <asm/lmb.h>
+-#include <asm/abs_addr.h>
+-#include <asm/tlbflush.h>
+-#include <asm/io.h>
+-#include <asm/eeh.h>
+-#include <asm/tlb.h>
+-#include <asm/cacheflush.h>
+-#include <asm/cputable.h>
+-#include <asm/abs_addr.h>
+-#include <asm/sections.h>
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/*
+- * Note: pte --> Linux PTE
+- * HPTE --> PowerPC Hashed Page Table Entry
+- *
+- * Execution context:
+- * htab_initialize is called with the MMU off (of course), but
+- * the kernel has been copied down to zero so it can directly
+- * reference global data. At this point it is very difficult
+- * to print debug info.
+- *
+- */
+-
+-#ifdef CONFIG_U3_DART
+-extern unsigned long dart_tablebase;
+-#endif /* CONFIG_U3_DART */
+-
+-hpte_t *htab_address;
+-unsigned long htab_hash_mask;
+-
+-extern unsigned long _SDR1;
+-
+-#define KB (1024)
+-#define MB (1024*KB)
+-
+-static inline void loop_forever(void)
+-{
+- volatile unsigned long x = 1;
+- for(;x;x|=1)
+- ;
+-}
+-
+-#ifdef CONFIG_PPC_MULTIPLATFORM
+-static inline void create_pte_mapping(unsigned long start, unsigned long end,
+- unsigned long mode, int large)
+-{
+- unsigned long addr;
+- unsigned int step;
+- unsigned long tmp_mode;
+- unsigned long vflags;
+-
+- if (large) {
+- step = 16*MB;
+- vflags = HPTE_V_BOLTED | HPTE_V_LARGE;
+- } else {
+- step = 4*KB;
+- vflags = HPTE_V_BOLTED;
+- }
+-
+- for (addr = start; addr < end; addr += step) {
+- unsigned long vpn, hash, hpteg;
+- unsigned long vsid = get_kernel_vsid(addr);
+- unsigned long va = (vsid << 28) | (addr & 0xfffffff);
+- int ret;
+-
+- if (large)
+- vpn = va >> HPAGE_SHIFT;
+- else
+- vpn = va >> PAGE_SHIFT;
+-
+-
+- tmp_mode = mode;
+-
+- /* Make non-kernel text non-executable */
+- if (!in_kernel_text(addr))
+- tmp_mode = mode | HW_NO_EXEC;
+-
+- hash = hpt_hash(vpn, large);
+-
+- hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
+-
+-#ifdef CONFIG_PPC_PSERIES
+- if (systemcfg->platform & PLATFORM_LPAR)
+- ret = pSeries_lpar_hpte_insert(hpteg, va,
+- virt_to_abs(addr) >> PAGE_SHIFT,
+- vflags, tmp_mode);
+- else
+-#endif /* CONFIG_PPC_PSERIES */
+- ret = native_hpte_insert(hpteg, va,
+- virt_to_abs(addr) >> PAGE_SHIFT,
+- vflags, tmp_mode);
+-
+- if (ret == -1) {
+- ppc64_terminate_msg(0x20, "create_pte_mapping");
+- loop_forever();
+- }
+- }
+-}
+-
+-void __init htab_initialize(void)
+-{
+- unsigned long table, htab_size_bytes;
+- unsigned long pteg_count;
+- unsigned long mode_rw;
+- int i, use_largepages = 0;
+- unsigned long base = 0, size = 0;
+- extern unsigned long tce_alloc_start, tce_alloc_end;
+-
+- DBG(" -> htab_initialize()\n");
+-
+- /*
+- * Calculate the required size of the htab. We want the number of
+- * PTEGs to equal one half the number of real pages.
+- */
+- htab_size_bytes = 1UL << ppc64_pft_size;
+- pteg_count = htab_size_bytes >> 7;
+-
+- /* For debug, make the HTAB 1/8 as big as it normally would be. */
+- ifppcdebug(PPCDBG_HTABSIZE) {
+- pteg_count >>= 3;
+- htab_size_bytes = pteg_count << 7;
+- }
+-
+- htab_hash_mask = pteg_count - 1;
+-
+- if (systemcfg->platform & PLATFORM_LPAR) {
+- /* Using a hypervisor which owns the htab */
+- htab_address = NULL;
+- _SDR1 = 0;
+- } else {
+- /* Find storage for the HPT. Must be contiguous in
+- * the absolute address space.
+- */
+- table = lmb_alloc(htab_size_bytes, htab_size_bytes);
+-
+- DBG("Hash table allocated at %lx, size: %lx\n", table,
+- htab_size_bytes);
+-
+- if ( !table ) {
+- ppc64_terminate_msg(0x20, "hpt space");
+- loop_forever();
+- }
+- htab_address = abs_to_virt(table);
+-
+- /* htab absolute addr + encoded htabsize */
+- _SDR1 = table + __ilog2(pteg_count) - 11;
+-
+- /* Initialize the HPT with no entries */
+- memset((void *)table, 0, htab_size_bytes);
+- }
+-
+- mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
+-
+- /* On U3 based machines, we need to reserve the DART area and
+- * _NOT_ map it to avoid cache paradoxes as it's remapped non
+- * cacheable later on
+- */
+- if (cpu_has_feature(CPU_FTR_16M_PAGE))
+- use_largepages = 1;
+-
+- /* create bolted the linear mapping in the hash table */
+- for (i=0; i < lmb.memory.cnt; i++) {
+- base = lmb.memory.region[i].base + KERNELBASE;
+- size = lmb.memory.region[i].size;
+-
+- DBG("creating mapping for region: %lx : %lx\n", base, size);
+-
+-#ifdef CONFIG_U3_DART
+- /* Do not map the DART space. Fortunately, it will be aligned
+- * in such a way that it will not cross two lmb regions and will
+- * fit within a single 16Mb page.
+- * The DART space is assumed to be a full 16Mb region even if we
+- * only use 2Mb of that space. We will use more of it later for
+- * AGP GART. We have to use a full 16Mb large page.
+- */
+- DBG("DART base: %lx\n", dart_tablebase);
+-
+- if (dart_tablebase != 0 && dart_tablebase >= base
+- && dart_tablebase < (base + size)) {
+- if (base != dart_tablebase)
+- create_pte_mapping(base, dart_tablebase, mode_rw,
+- use_largepages);
+- if ((base + size) > (dart_tablebase + 16*MB))
+- create_pte_mapping(dart_tablebase + 16*MB, base + size,
+- mode_rw, use_largepages);
+- continue;
+- }
+-#endif /* CONFIG_U3_DART */
+- create_pte_mapping(base, base + size, mode_rw, use_largepages);
+- }
+-
+- /*
+- * If we have a memory_limit and we've allocated TCEs then we need to
+- * explicitly map the TCE area at the top of RAM. We also cope with the
+- * case that the TCEs start below memory_limit.
+- * tce_alloc_start/end are 16MB aligned so the mapping should work
+- * for either 4K or 16MB pages.
+- */
+- if (tce_alloc_start) {
+- tce_alloc_start += KERNELBASE;
+- tce_alloc_end += KERNELBASE;
+-
+- if (base + size >= tce_alloc_start)
+- tce_alloc_start = base + size + 1;
+-
+- create_pte_mapping(tce_alloc_start, tce_alloc_end,
+- mode_rw, use_largepages);
+- }
+-
+- DBG(" <- htab_initialize()\n");
+-}
+-#undef KB
+-#undef MB
+-#endif /* CONFIG_PPC_MULTIPLATFORM */
+-
+-/*
+- * Called by asm hashtable.S for doing lazy icache flush
+- */
+-unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
+-{
+- struct page *page;
+-
+- if (!pfn_valid(pte_pfn(pte)))
+- return pp;
+-
+- page = pte_page(pte);
+-
+- /* page is dirty */
+- if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) {
+- if (trap == 0x400) {
+- __flush_dcache_icache(page_address(page));
+- set_bit(PG_arch_1, &page->flags);
+- } else
+- pp |= HW_NO_EXEC;
+- }
+- return pp;
+-}
+-
+-/* Result code is:
+- * 0 - handled
+- * 1 - normal page fault
+- * -1 - critical hash insertion error
+- */
+-int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
+-{
+- void *pgdir;
+- unsigned long vsid;
+- struct mm_struct *mm;
+- pte_t *ptep;
+- int ret;
+- int user_region = 0;
+- int local = 0;
+- cpumask_t tmp;
+-
+- if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
+- return 1;
+-
+- switch (REGION_ID(ea)) {
+- case USER_REGION_ID:
+- user_region = 1;
+- mm = current->mm;
+- if (! mm)
+- return 1;
+-
+- vsid = get_vsid(mm->context.id, ea);
+- break;
+- case VMALLOC_REGION_ID:
+- mm = &init_mm;
+- vsid = get_kernel_vsid(ea);
+- break;
+-#if 0
+- case KERNEL_REGION_ID:
+- /*
+- * Should never get here - entire 0xC0... region is bolted.
+- * Send the problem up to do_page_fault
+- */
+-#endif
+- default:
+- /* Not a valid range
+- * Send the problem up to do_page_fault
+- */
+- return 1;
+- break;
+- }
+-
+- pgdir = mm->pgd;
+-
+- if (pgdir == NULL)
+- return 1;
+-
+- tmp = cpumask_of_cpu(smp_processor_id());
+- if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
+- local = 1;
+-
+- /* Is this a huge page ? */
+- if (unlikely(in_hugepage_area(mm->context, ea)))
+- ret = hash_huge_page(mm, access, ea, vsid, local);
+- else {
+- ptep = find_linux_pte(pgdir, ea);
+- if (ptep == NULL)
+- return 1;
+- ret = __hash_page(ea, access, vsid, ptep, trap, local);
+- }
+-
+- return ret;
+-}
+-
+-void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
+- int local)
+-{
+- unsigned long vsid, vpn, va, hash, secondary, slot;
+- unsigned long huge = pte_huge(pte);
+-
+- if (ea < KERNELBASE)
+- vsid = get_vsid(context, ea);
+- else
+- vsid = get_kernel_vsid(ea);
+-
+- va = (vsid << 28) | (ea & 0x0fffffff);
+- if (huge)
+- vpn = va >> HPAGE_SHIFT;
+- else
+- vpn = va >> PAGE_SHIFT;
+- hash = hpt_hash(vpn, huge);
+- secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15;
+- if (secondary)
+- hash = ~hash;
+- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12;
+-
+- ppc_md.hpte_invalidate(slot, va, huge, local);
+-}
+-
+-void flush_hash_range(unsigned long context, unsigned long number, int local)
+-{
+- if (ppc_md.flush_hash_range) {
+- ppc_md.flush_hash_range(context, number, local);
+- } else {
+- int i;
+- struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+-
+- for (i = 0; i < number; i++)
+- flush_hash_page(context, batch->addr[i], batch->pte[i],
+- local);
+- }
+-}
+-
+-static inline void make_bl(unsigned int *insn_addr, void *func)
+-{
+- unsigned long funcp = *((unsigned long *)func);
+- int offset = funcp - (unsigned long)insn_addr;
+-
+- *insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc));
+- flush_icache_range((unsigned long)insn_addr, 4+
+- (unsigned long)insn_addr);
+-}
+-
+-/*
+- * low_hash_fault is called when we the low level hash code failed
+- * to instert a PTE due to an hypervisor error
+- */
+-void low_hash_fault(struct pt_regs *regs, unsigned long address)
+-{
+- if (user_mode(regs)) {
+- siginfo_t info;
+-
+- info.si_signo = SIGBUS;
+- info.si_errno = 0;
+- info.si_code = BUS_ADRERR;
+- info.si_addr = (void __user *)address;
+- force_sig_info(SIGBUS, &info, current);
+- return;
+- }
+- bad_page_fault(regs, address, SIGBUS);
+-}
+-
+-void __init htab_finish_init(void)
+-{
+- extern unsigned int *htab_call_hpte_insert1;
+- extern unsigned int *htab_call_hpte_insert2;
+- extern unsigned int *htab_call_hpte_remove;
+- extern unsigned int *htab_call_hpte_updatepp;
+-
+- make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
+- make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
+- make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);
+- make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp);
+-}
+diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/hugetlbpage.c
++++ /dev/null
+@@ -1,745 +0,0 @@
+-/*
+- * PPC64 (POWER4) Huge TLB Page Support for Kernel.
+- *
+- * Copyright (C) 2003 David Gibson, IBM Corporation.
+- *
+- * Based on the IA-32 version:
+- * Copyright (C) 2002, Rohit Seth <rohit.seth at intel.com>
+- */
+-
+-#include <linux/init.h>
+-#include <linux/fs.h>
+-#include <linux/mm.h>
+-#include <linux/hugetlb.h>
+-#include <linux/pagemap.h>
+-#include <linux/smp_lock.h>
+-#include <linux/slab.h>
+-#include <linux/err.h>
+-#include <linux/sysctl.h>
+-#include <asm/mman.h>
+-#include <asm/pgalloc.h>
+-#include <asm/tlb.h>
+-#include <asm/tlbflush.h>
+-#include <asm/mmu_context.h>
+-#include <asm/machdep.h>
+-#include <asm/cputable.h>
+-#include <asm/tlb.h>
+-
+-#include <linux/sysctl.h>
+-
+-#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
+-#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
+-
+-/* Modelled after find_linux_pte() */
+-pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+-{
+- pgd_t *pg;
+- pud_t *pu;
+- pmd_t *pm;
+- pte_t *pt;
+-
+- BUG_ON(! in_hugepage_area(mm->context, addr));
+-
+- addr &= HPAGE_MASK;
+-
+- pg = pgd_offset(mm, addr);
+- if (!pgd_none(*pg)) {
+- pu = pud_offset(pg, addr);
+- if (!pud_none(*pu)) {
+- pm = pmd_offset(pu, addr);
+- pt = (pte_t *)pm;
+- BUG_ON(!pmd_none(*pm)
+- && !(pte_present(*pt) && pte_huge(*pt)));
+- return pt;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+-{
+- pgd_t *pg;
+- pud_t *pu;
+- pmd_t *pm;
+- pte_t *pt;
+-
+- BUG_ON(! in_hugepage_area(mm->context, addr));
+-
+- addr &= HPAGE_MASK;
+-
+- pg = pgd_offset(mm, addr);
+- pu = pud_alloc(mm, pg, addr);
+-
+- if (pu) {
+- pm = pmd_alloc(mm, pu, addr);
+- if (pm) {
+- pt = (pte_t *)pm;
+- BUG_ON(!pmd_none(*pm)
+- && !(pte_present(*pt) && pte_huge(*pt)));
+- return pt;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE)
+-
+-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+- pte_t *ptep, pte_t pte)
+-{
+- int i;
+-
+- if (pte_present(*ptep)) {
+- pte_clear(mm, addr, ptep);
+- flush_tlb_pending();
+- }
+-
+- for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) {
+- *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
+- ptep++;
+- }
+-}
+-
+-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+- pte_t *ptep)
+-{
+- unsigned long old = pte_update(ptep, ~0UL);
+- int i;
+-
+- if (old & _PAGE_HASHPTE)
+- hpte_update(mm, addr, old, 0);
+-
+- for (i = 1; i < HUGEPTE_BATCH_SIZE; i++)
+- ptep[i] = __pte(0);
+-
+- return __pte(old);
+-}
+-
+-/*
+- * This function checks for proper alignment of input addr and len parameters.
+- */
+-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+-{
+- if (len & ~HPAGE_MASK)
+- return -EINVAL;
+- if (addr & ~HPAGE_MASK)
+- return -EINVAL;
+- if (! (within_hugepage_low_range(addr, len)
+- || within_hugepage_high_range(addr, len)) )
+- return -EINVAL;
+- return 0;
+-}
+-
+-static void flush_low_segments(void *parm)
+-{
+- u16 areas = (unsigned long) parm;
+- unsigned long i;
+-
+- asm volatile("isync" : : : "memory");
+-
+- BUILD_BUG_ON((sizeof(areas)*8) != NUM_LOW_AREAS);
+-
+- for (i = 0; i < NUM_LOW_AREAS; i++) {
+- if (! (areas & (1U << i)))
+- continue;
+- asm volatile("slbie %0"
+- : : "r" ((i << SID_SHIFT) | SLBIE_C));
+- }
+-
+- asm volatile("isync" : : : "memory");
+-}
+-
+-static void flush_high_segments(void *parm)
+-{
+- u16 areas = (unsigned long) parm;
+- unsigned long i, j;
+-
+- asm volatile("isync" : : : "memory");
+-
+- BUILD_BUG_ON((sizeof(areas)*8) != NUM_HIGH_AREAS);
+-
+- for (i = 0; i < NUM_HIGH_AREAS; i++) {
+- if (! (areas & (1U << i)))
+- continue;
+- for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
+- asm volatile("slbie %0"
+- :: "r" (((i << HTLB_AREA_SHIFT)
+- + (j << SID_SHIFT)) | SLBIE_C));
+- }
+-
+- asm volatile("isync" : : : "memory");
+-}
+-
+-static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
+-{
+- unsigned long start = area << SID_SHIFT;
+- unsigned long end = (area+1) << SID_SHIFT;
+- struct vm_area_struct *vma;
+-
+- BUG_ON(area >= NUM_LOW_AREAS);
+-
+- /* Check no VMAs are in the region */
+- vma = find_vma(mm, start);
+- if (vma && (vma->vm_start < end))
+- return -EBUSY;
+-
+- return 0;
+-}
+-
+-static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
+-{
+- unsigned long start = area << HTLB_AREA_SHIFT;
+- unsigned long end = (area+1) << HTLB_AREA_SHIFT;
+- struct vm_area_struct *vma;
+-
+- BUG_ON(area >= NUM_HIGH_AREAS);
+-
+- /* Check no VMAs are in the region */
+- vma = find_vma(mm, start);
+- if (vma && (vma->vm_start < end))
+- return -EBUSY;
+-
+- return 0;
+-}
+-
+-static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
+-{
+- unsigned long i;
+-
+- BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
+- BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);
+-
+- newareas &= ~(mm->context.low_htlb_areas);
+- if (! newareas)
+- return 0; /* The segments we want are already open */
+-
+- for (i = 0; i < NUM_LOW_AREAS; i++)
+- if ((1 << i) & newareas)
+- if (prepare_low_area_for_htlb(mm, i) != 0)
+- return -EBUSY;
+-
+- mm->context.low_htlb_areas |= newareas;
+-
+- /* update the paca copy of the context struct */
+- get_paca()->context = mm->context;
+-
+- /* the context change must make it to memory before the flush,
+- * so that further SLB misses do the right thing. */
+- mb();
+- on_each_cpu(flush_low_segments, (void *)(unsigned long)newareas, 0, 1);
+-
+- return 0;
+-}
+-
+-static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
+-{
+- unsigned long i;
+-
+- BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
+- BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
+- != NUM_HIGH_AREAS);
+-
+- newareas &= ~(mm->context.high_htlb_areas);
+- if (! newareas)
+- return 0; /* The areas we want are already open */
+-
+- for (i = 0; i < NUM_HIGH_AREAS; i++)
+- if ((1 << i) & newareas)
+- if (prepare_high_area_for_htlb(mm, i) != 0)
+- return -EBUSY;
+-
+- mm->context.high_htlb_areas |= newareas;
+-
+- /* update the paca copy of the context struct */
+- get_paca()->context = mm->context;
+-
+- /* the context change must make it to memory before the flush,
+- * so that further SLB misses do the right thing. */
+- mb();
+- on_each_cpu(flush_high_segments, (void *)(unsigned long)newareas, 0, 1);
+-
+- return 0;
+-}
+-
+-int prepare_hugepage_range(unsigned long addr, unsigned long len)
+-{
+- int err;
+-
+- if ( (addr+len) < addr )
+- return -EINVAL;
+-
+- if ((addr + len) < 0x100000000UL)
+- err = open_low_hpage_areas(current->mm,
+- LOW_ESID_MASK(addr, len));
+- else
+- err = open_high_hpage_areas(current->mm,
+- HTLB_AREA_MASK(addr, len));
+- if (err) {
+- printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
+- " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",
+- addr, len,
+- LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));
+- return err;
+- }
+-
+- return 0;
+-}
+-
+-struct page *
+-follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
+-{
+- pte_t *ptep;
+- struct page *page;
+-
+- if (! in_hugepage_area(mm->context, address))
+- return ERR_PTR(-EINVAL);
+-
+- ptep = huge_pte_offset(mm, address);
+- page = pte_page(*ptep);
+- if (page)
+- page += (address % HPAGE_SIZE) / PAGE_SIZE;
+-
+- return page;
+-}
+-
+-int pmd_huge(pmd_t pmd)
+-{
+- return 0;
+-}
+-
+-struct page *
+-follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+- pmd_t *pmd, int write)
+-{
+- BUG();
+- return NULL;
+-}
+-
+-/* Because we have an exclusive hugepage region which lies within the
+- * normal user address space, we have to take special measures to make
+- * non-huge mmap()s evade the hugepage reserved regions. */
+-unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+- unsigned long len, unsigned long pgoff,
+- unsigned long flags)
+-{
+- struct mm_struct *mm = current->mm;
+- struct vm_area_struct *vma;
+- unsigned long start_addr;
+-
+- if (len > TASK_SIZE)
+- return -ENOMEM;
+-
+- if (addr) {
+- addr = PAGE_ALIGN(addr);
+- vma = find_vma(mm, addr);
+- if (((TASK_SIZE - len) >= addr)
+- && (!vma || (addr+len) <= vma->vm_start)
+- && !is_hugepage_only_range(mm, addr,len))
+- return addr;
+- }
+- if (len > mm->cached_hole_size) {
+- start_addr = addr = mm->free_area_cache;
+- } else {
+- start_addr = addr = TASK_UNMAPPED_BASE;
+- mm->cached_hole_size = 0;
+- }
+-
+-full_search:
+- vma = find_vma(mm, addr);
+- while (TASK_SIZE - len >= addr) {
+- BUG_ON(vma && (addr >= vma->vm_end));
+-
+- if (touches_hugepage_low_range(mm, addr, len)) {
+- addr = ALIGN(addr+1, 1<<SID_SHIFT);
+- vma = find_vma(mm, addr);
+- continue;
+- }
+- if (touches_hugepage_high_range(mm, addr, len)) {
+- addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
+- vma = find_vma(mm, addr);
+- continue;
+- }
+- if (!vma || addr + len <= vma->vm_start) {
+- /*
+- * Remember the place where we stopped the search:
+- */
+- mm->free_area_cache = addr + len;
+- return addr;
+- }
+- if (addr + mm->cached_hole_size < vma->vm_start)
+- mm->cached_hole_size = vma->vm_start - addr;
+- addr = vma->vm_end;
+- vma = vma->vm_next;
+- }
+-
+- /* Make sure we didn't miss any holes */
+- if (start_addr != TASK_UNMAPPED_BASE) {
+- start_addr = addr = TASK_UNMAPPED_BASE;
+- mm->cached_hole_size = 0;
+- goto full_search;
+- }
+- return -ENOMEM;
+-}
+-
+-/*
+- * This mmap-allocator allocates new areas top-down from below the
+- * stack's low limit (the base):
+- *
+- * Because we have an exclusive hugepage region which lies within the
+- * normal user address space, we have to take special measures to make
+- * non-huge mmap()s evade the hugepage reserved regions.
+- */
+-unsigned long
+-arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+- const unsigned long len, const unsigned long pgoff,
+- const unsigned long flags)
+-{
+- struct vm_area_struct *vma, *prev_vma;
+- struct mm_struct *mm = current->mm;
+- unsigned long base = mm->mmap_base, addr = addr0;
+- unsigned long largest_hole = mm->cached_hole_size;
+- int first_time = 1;
+-
+- /* requested length too big for entire address space */
+- if (len > TASK_SIZE)
+- return -ENOMEM;
+-
+- /* dont allow allocations above current base */
+- if (mm->free_area_cache > base)
+- mm->free_area_cache = base;
+-
+- /* requesting a specific address */
+- if (addr) {
+- addr = PAGE_ALIGN(addr);
+- vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start)
+- && !is_hugepage_only_range(mm, addr,len))
+- return addr;
+- }
+-
+- if (len <= largest_hole) {
+- largest_hole = 0;
+- mm->free_area_cache = base;
+- }
+-try_again:
+- /* make sure it can fit in the remaining address space */
+- if (mm->free_area_cache < len)
+- goto fail;
+-
+- /* either no address requested or cant fit in requested address hole */
+- addr = (mm->free_area_cache - len) & PAGE_MASK;
+- do {
+-hugepage_recheck:
+- if (touches_hugepage_low_range(mm, addr, len)) {
+- addr = (addr & ((~0) << SID_SHIFT)) - len;
+- goto hugepage_recheck;
+- } else if (touches_hugepage_high_range(mm, addr, len)) {
+- addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;
+- goto hugepage_recheck;
+- }
+-
+- /*
+- * Lookup failure means no vma is above this address,
+- * i.e. return with success:
+- */
+- if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+- return addr;
+-
+- /*
+- * new region fits between prev_vma->vm_end and
+- * vma->vm_start, use it:
+- */
+- if (addr+len <= vma->vm_start &&
+- (!prev_vma || (addr >= prev_vma->vm_end))) {
+- /* remember the address as a hint for next time */
+- mm->cached_hole_size = largest_hole;
+- return (mm->free_area_cache = addr);
+- } else {
+- /* pull free_area_cache down to the first hole */
+- if (mm->free_area_cache == vma->vm_end) {
+- mm->free_area_cache = vma->vm_start;
+- mm->cached_hole_size = largest_hole;
+- }
+- }
+-
+- /* remember the largest hole we saw so far */
+- if (addr + largest_hole < vma->vm_start)
+- largest_hole = vma->vm_start - addr;
+-
+- /* try just below the current vma->vm_start */
+- addr = vma->vm_start-len;
+- } while (len <= vma->vm_start);
+-
+-fail:
+- /*
+- * if hint left us with no space for the requested
+- * mapping then try again:
+- */
+- if (first_time) {
+- mm->free_area_cache = base;
+- largest_hole = 0;
+- first_time = 0;
+- goto try_again;
+- }
+- /*
+- * A failed mmap() very likely causes application failure,
+- * so fall back to the bottom-up function here. This scenario
+- * can happen with large stack limits and large mmap()
+- * allocations.
+- */
+- mm->free_area_cache = TASK_UNMAPPED_BASE;
+- mm->cached_hole_size = ~0UL;
+- addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+- /*
+- * Restore the topdown base:
+- */
+- mm->free_area_cache = base;
+- mm->cached_hole_size = ~0UL;
+-
+- return addr;
+-}
+-
+-static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
+-{
+- unsigned long addr = 0;
+- struct vm_area_struct *vma;
+-
+- vma = find_vma(current->mm, addr);
+- while (addr + len <= 0x100000000UL) {
+- BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
+-
+- if (! __within_hugepage_low_range(addr, len, segmask)) {
+- addr = ALIGN(addr+1, 1<<SID_SHIFT);
+- vma = find_vma(current->mm, addr);
+- continue;
+- }
+-
+- if (!vma || (addr + len) <= vma->vm_start)
+- return addr;
+- addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+- /* Depending on segmask this might not be a confirmed
+- * hugepage region, so the ALIGN could have skipped
+- * some VMAs */
+- vma = find_vma(current->mm, addr);
+- }
+-
+- return -ENOMEM;
+-}
+-
+-static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)
+-{
+- unsigned long addr = 0x100000000UL;
+- struct vm_area_struct *vma;
+-
+- vma = find_vma(current->mm, addr);
+- while (addr + len <= TASK_SIZE_USER64) {
+- BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
+-
+- if (! __within_hugepage_high_range(addr, len, areamask)) {
+- addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
+- vma = find_vma(current->mm, addr);
+- continue;
+- }
+-
+- if (!vma || (addr + len) <= vma->vm_start)
+- return addr;
+- addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+- /* Depending on segmask this might not be a confirmed
+- * hugepage region, so the ALIGN could have skipped
+- * some VMAs */
+- vma = find_vma(current->mm, addr);
+- }
+-
+- return -ENOMEM;
+-}
+-
+-unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+- unsigned long len, unsigned long pgoff,
+- unsigned long flags)
+-{
+- int lastshift;
+- u16 areamask, curareas;
+-
+- if (len & ~HPAGE_MASK)
+- return -EINVAL;
+-
+- if (!cpu_has_feature(CPU_FTR_16M_PAGE))
+- return -EINVAL;
+-
+- if (test_thread_flag(TIF_32BIT)) {
+- curareas = current->mm->context.low_htlb_areas;
+-
+- /* First see if we can do the mapping in the existing
+- * low areas */
+- addr = htlb_get_low_area(len, curareas);
+- if (addr != -ENOMEM)
+- return addr;
+-
+- lastshift = 0;
+- for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
+- ! lastshift; areamask >>=1) {
+- if (areamask & 1)
+- lastshift = 1;
+-
+- addr = htlb_get_low_area(len, curareas | areamask);
+- if ((addr != -ENOMEM)
+- && open_low_hpage_areas(current->mm, areamask) == 0)
+- return addr;
+- }
+- } else {
+- curareas = current->mm->context.high_htlb_areas;
+-
+- /* First see if we can do the mapping in the existing
+- * high areas */
+- addr = htlb_get_high_area(len, curareas);
+- if (addr != -ENOMEM)
+- return addr;
+-
+- lastshift = 0;
+- for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
+- ! lastshift; areamask >>=1) {
+- if (areamask & 1)
+- lastshift = 1;
+-
+- addr = htlb_get_high_area(len, curareas | areamask);
+- if ((addr != -ENOMEM)
+- && open_high_hpage_areas(current->mm, areamask) == 0)
+- return addr;
+- }
+- }
+- printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
+- " enough areas\n");
+- return -ENOMEM;
+-}
+-
+-int hash_huge_page(struct mm_struct *mm, unsigned long access,
+- unsigned long ea, unsigned long vsid, int local)
+-{
+- pte_t *ptep;
+- unsigned long va, vpn;
+- pte_t old_pte, new_pte;
+- unsigned long rflags, prpn;
+- long slot;
+- int err = 1;
+-
+- spin_lock(&mm->page_table_lock);
+-
+- ptep = huge_pte_offset(mm, ea);
+-
+- /* Search the Linux page table for a match with va */
+- va = (vsid << 28) | (ea & 0x0fffffff);
+- vpn = va >> HPAGE_SHIFT;
+-
+- /*
+- * If no pte found or not present, send the problem up to
+- * do_page_fault
+- */
+- if (unlikely(!ptep || pte_none(*ptep)))
+- goto out;
+-
+-/* BUG_ON(pte_bad(*ptep)); */
+-
+- /*
+- * Check the user's access rights to the page. If access should be
+- * prevented then send the problem up to do_page_fault.
+- */
+- if (unlikely(access & ~pte_val(*ptep)))
+- goto out;
+- /*
+- * At this point, we have a pte (old_pte) which can be used to build
+- * or update an HPTE. There are 2 cases:
+- *
+- * 1. There is a valid (present) pte with no associated HPTE (this is
+- * the most common case)
+- * 2. There is a valid (present) pte with an associated HPTE. The
+- * current values of the pp bits in the HPTE prevent access
+- * because we are doing software DIRTY bit management and the
+- * page is currently not DIRTY.
+- */
+-
+-
+- old_pte = *ptep;
+- new_pte = old_pte;
+-
+- rflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW));
+- /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */
+- rflags |= ((pte_val(new_pte) & _PAGE_EXEC) ? 0 : HW_NO_EXEC);
+-
+- /* Check if pte already has an hpte (case 2) */
+- if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) {
+- /* There MIGHT be an HPTE for this pte */
+- unsigned long hash, slot;
+-
+- hash = hpt_hash(vpn, 1);
+- if (pte_val(old_pte) & _PAGE_SECONDARY)
+- hash = ~hash;
+- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
+-
+- if (ppc_md.hpte_updatepp(slot, rflags, va, 1, local) == -1)
+- pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
+- }
+-
+- if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) {
+- unsigned long hash = hpt_hash(vpn, 1);
+- unsigned long hpte_group;
+-
+- prpn = pte_pfn(old_pte);
+-
+-repeat:
+- hpte_group = ((hash & htab_hash_mask) *
+- HPTES_PER_GROUP) & ~0x7UL;
+-
+- /* Update the linux pte with the HPTE slot */
+- pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;
+- pte_val(new_pte) |= _PAGE_HASHPTE;
+-
+- /* Add in WIMG bits */
+- /* XXX We should store these in the pte */
+- rflags |= _PAGE_COHERENT;
+-
+- slot = ppc_md.hpte_insert(hpte_group, va, prpn,
+- HPTE_V_LARGE, rflags);
+-
+- /* Primary is full, try the secondary */
+- if (unlikely(slot == -1)) {
+- pte_val(new_pte) |= _PAGE_SECONDARY;
+- hpte_group = ((~hash & htab_hash_mask) *
+- HPTES_PER_GROUP) & ~0x7UL;
+- slot = ppc_md.hpte_insert(hpte_group, va, prpn,
+- HPTE_V_LARGE |
+- HPTE_V_SECONDARY,
+- rflags);
+- if (slot == -1) {
+- if (mftb() & 0x1)
+- hpte_group = ((hash & htab_hash_mask) *
+- HPTES_PER_GROUP)&~0x7UL;
+-
+- ppc_md.hpte_remove(hpte_group);
+- goto repeat;
+- }
+- }
+-
+- if (unlikely(slot == -2))
+- panic("hash_huge_page: pte_insert failed\n");
+-
+- pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;
+-
+- /*
+- * No need to use ldarx/stdcx here because all who
+- * might be updating the pte will hold the
+- * page_table_lock
+- */
+- *ptep = new_pte;
+- }
+-
+- err = 0;
+-
+- out:
+- spin_unlock(&mm->page_table_lock);
+-
+- return err;
+-}
+diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/imalloc.c
++++ /dev/null
+@@ -1,317 +0,0 @@
+-/*
+- * c 2001 PPC 64 Team, IBM Corp
+- *
+- * 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/slab.h>
+-#include <linux/vmalloc.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/semaphore.h>
+-#include <asm/imalloc.h>
+-#include <asm/cacheflush.h>
+-
+-static DECLARE_MUTEX(imlist_sem);
+-struct vm_struct * imlist = NULL;
+-
+-static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
+-{
+- unsigned long addr;
+- struct vm_struct **p, *tmp;
+-
+- addr = ioremap_bot;
+- for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
+- if (size + addr < (unsigned long) tmp->addr)
+- break;
+- if ((unsigned long)tmp->addr >= ioremap_bot)
+- addr = tmp->size + (unsigned long) tmp->addr;
+- if (addr >= IMALLOC_END-size)
+- return 1;
+- }
+- *im_addr = addr;
+-
+- return 0;
+-}
+-
+-/* Return whether the region described by v_addr and size is a subset
+- * of the region described by parent
+- */
+-static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
+- struct vm_struct *parent)
+-{
+- return (int) (v_addr >= (unsigned long) parent->addr &&
+- v_addr < (unsigned long) parent->addr + parent->size &&
+- size < parent->size);
+-}
+-
+-/* Return whether the region described by v_addr and size is a superset
+- * of the region described by child
+- */
+-static int im_region_is_superset(unsigned long v_addr, unsigned long size,
+- struct vm_struct *child)
+-{
+- struct vm_struct parent;
+-
+- parent.addr = (void *) v_addr;
+- parent.size = size;
+-
+- return im_region_is_subset((unsigned long) child->addr, child->size,
+- &parent);
+-}
+-
+-/* Return whether the region described by v_addr and size overlaps
+- * the region described by vm. Overlapping regions meet the
+- * following conditions:
+- * 1) The regions share some part of the address space
+- * 2) The regions aren't identical
+- * 3) Neither region is a subset of the other
+- */
+-static int im_region_overlaps(unsigned long v_addr, unsigned long size,
+- struct vm_struct *vm)
+-{
+- if (im_region_is_superset(v_addr, size, vm))
+- return 0;
+-
+- return (v_addr + size > (unsigned long) vm->addr + vm->size &&
+- v_addr < (unsigned long) vm->addr + vm->size) ||
+- (v_addr < (unsigned long) vm->addr &&
+- v_addr + size > (unsigned long) vm->addr);
+-}
+-
+-/* Determine imalloc status of region described by v_addr and size.
+- * Can return one of the following:
+- * IM_REGION_UNUSED - Entire region is unallocated in imalloc space.
+- * IM_REGION_SUBSET - Region is a subset of a region that is already
+- * allocated in imalloc space.
+- * vm will be assigned to a ptr to the parent region.
+- * IM_REGION_EXISTS - Exact region already allocated in imalloc space.
+- * vm will be assigned to a ptr to the existing imlist
+- * member.
+- * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space.
+- * IM_REGION_SUPERSET - Region is a superset of a region that is already
+- * allocated in imalloc space.
+- */
+-static int im_region_status(unsigned long v_addr, unsigned long size,
+- struct vm_struct **vm)
+-{
+- struct vm_struct *tmp;
+-
+- for (tmp = imlist; tmp; tmp = tmp->next)
+- if (v_addr < (unsigned long) tmp->addr + tmp->size)
+- break;
+-
+- if (tmp) {
+- if (im_region_overlaps(v_addr, size, tmp))
+- return IM_REGION_OVERLAP;
+-
+- *vm = tmp;
+- if (im_region_is_subset(v_addr, size, tmp)) {
+- /* Return with tmp pointing to superset */
+- return IM_REGION_SUBSET;
+- }
+- if (im_region_is_superset(v_addr, size, tmp)) {
+- /* Return with tmp pointing to first subset */
+- return IM_REGION_SUPERSET;
+- }
+- else if (v_addr == (unsigned long) tmp->addr &&
+- size == tmp->size) {
+- /* Return with tmp pointing to exact region */
+- return IM_REGION_EXISTS;
+- }
+- }
+-
+- *vm = NULL;
+- return IM_REGION_UNUSED;
+-}
+-
+-static struct vm_struct * split_im_region(unsigned long v_addr,
+- unsigned long size, struct vm_struct *parent)
+-{
+- struct vm_struct *vm1 = NULL;
+- struct vm_struct *vm2 = NULL;
+- struct vm_struct *new_vm = NULL;
+-
+- vm1 = (struct vm_struct *) kmalloc(sizeof(*vm1), GFP_KERNEL);
+- if (vm1 == NULL) {
+- printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
+- return NULL;
+- }
+-
+- if (v_addr == (unsigned long) parent->addr) {
+- /* Use existing parent vm_struct to represent child, allocate
+- * new one for the remainder of parent range
+- */
+- vm1->size = parent->size - size;
+- vm1->addr = (void *) (v_addr + size);
+- vm1->next = parent->next;
+-
+- parent->size = size;
+- parent->next = vm1;
+- new_vm = parent;
+- } else if (v_addr + size == (unsigned long) parent->addr +
+- parent->size) {
+- /* Allocate new vm_struct to represent child, use existing
+- * parent one for remainder of parent range
+- */
+- vm1->size = size;
+- vm1->addr = (void *) v_addr;
+- vm1->next = parent->next;
+- new_vm = vm1;
+-
+- parent->size -= size;
+- parent->next = vm1;
+- } else {
+- /* Allocate two new vm_structs for the new child and
+- * uppermost remainder, and use existing parent one for the
+- * lower remainder of parent range
+- */
+- vm2 = (struct vm_struct *) kmalloc(sizeof(*vm2), GFP_KERNEL);
+- if (vm2 == NULL) {
+- printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
+- kfree(vm1);
+- return NULL;
+- }
+-
+- vm1->size = size;
+- vm1->addr = (void *) v_addr;
+- vm1->next = vm2;
+- new_vm = vm1;
+-
+- vm2->size = ((unsigned long) parent->addr + parent->size) -
+- (v_addr + size);
+- vm2->addr = (void *) v_addr + size;
+- vm2->next = parent->next;
+-
+- parent->size = v_addr - (unsigned long) parent->addr;
+- parent->next = vm1;
+- }
+-
+- return new_vm;
+-}
+-
+-static struct vm_struct * __add_new_im_area(unsigned long req_addr,
+- unsigned long size)
+-{
+- struct vm_struct **p, *tmp, *area;
+-
+- for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
+- if (req_addr + size <= (unsigned long)tmp->addr)
+- break;
+- }
+-
+- area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+- if (!area)
+- return NULL;
+- area->flags = 0;
+- area->addr = (void *)req_addr;
+- area->size = size;
+- area->next = *p;
+- *p = area;
+-
+- return area;
+-}
+-
+-static struct vm_struct * __im_get_area(unsigned long req_addr,
+- unsigned long size,
+- int criteria)
+-{
+- struct vm_struct *tmp;
+- int status;
+-
+- status = im_region_status(req_addr, size, &tmp);
+- if ((criteria & status) == 0) {
+- return NULL;
+- }
+-
+- switch (status) {
+- case IM_REGION_UNUSED:
+- tmp = __add_new_im_area(req_addr, size);
+- break;
+- case IM_REGION_SUBSET:
+- tmp = split_im_region(req_addr, size, tmp);
+- break;
+- case IM_REGION_EXISTS:
+- /* Return requested region */
+- break;
+- case IM_REGION_SUPERSET:
+- /* Return first existing subset of requested region */
+- break;
+- default:
+- printk(KERN_ERR "%s() unexpected imalloc region status\n",
+- __FUNCTION__);
+- tmp = NULL;
+- }
+-
+- return tmp;
+-}
+-
+-struct vm_struct * im_get_free_area(unsigned long size)
+-{
+- struct vm_struct *area;
+- unsigned long addr;
+-
+- down(&imlist_sem);
+- if (get_free_im_addr(size, &addr)) {
+- printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
+- __FUNCTION__, size);
+- area = NULL;
+- goto next_im_done;
+- }
+-
+- area = __im_get_area(addr, size, IM_REGION_UNUSED);
+- if (area == NULL) {
+- printk(KERN_ERR
+- "%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
+- __FUNCTION__, addr, size);
+- }
+-next_im_done:
+- up(&imlist_sem);
+- return area;
+-}
+-
+-struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
+- int criteria)
+-{
+- struct vm_struct *area;
+-
+- down(&imlist_sem);
+- area = __im_get_area(v_addr, size, criteria);
+- up(&imlist_sem);
+- return area;
+-}
+-
+-void im_free(void * addr)
+-{
+- struct vm_struct **p, *tmp;
+-
+- if (!addr)
+- return;
+- if ((unsigned long) addr & ~PAGE_MASK) {
+- printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr);
+- return;
+- }
+- down(&imlist_sem);
+- for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
+- if (tmp->addr == addr) {
+- *p = tmp->next;
+-
+- /* XXX: do we need the lock? */
+- spin_lock(&init_mm.page_table_lock);
+- unmap_vm_area(tmp);
+- spin_unlock(&init_mm.page_table_lock);
+-
+- kfree(tmp);
+- up(&imlist_sem);
+- return;
+- }
+- }
+- up(&imlist_sem);
+- printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
+- addr);
+-}
+diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/init.c
++++ /dev/null
+@@ -1,869 +0,0 @@
+-/*
+- * PowerPC version
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
+- * and Cort Dougan (PReP) (cort at cs.nmt.edu)
+- * Copyright (C) 1996 Paul Mackerras
+- * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
+- *
+- * Derived from "arch/i386/mm/init.c"
+- * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+- *
+- * Dave Engebretsen <engebret at us.ibm.com>
+- * Rework for PPC64 port.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- */
+-
+-#include <linux/config.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/types.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/stddef.h>
+-#include <linux/vmalloc.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/highmem.h>
+-#include <linux/idr.h>
+-#include <linux/nodemask.h>
+-#include <linux/module.h>
+-
+-#include <asm/pgalloc.h>
+-#include <asm/page.h>
+-#include <asm/prom.h>
+-#include <asm/lmb.h>
+-#include <asm/rtas.h>
+-#include <asm/io.h>
+-#include <asm/mmu_context.h>
+-#include <asm/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/uaccess.h>
+-#include <asm/smp.h>
+-#include <asm/machdep.h>
+-#include <asm/tlb.h>
+-#include <asm/eeh.h>
+-#include <asm/processor.h>
+-#include <asm/mmzone.h>
+-#include <asm/cputable.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/sections.h>
+-#include <asm/system.h>
+-#include <asm/iommu.h>
+-#include <asm/abs_addr.h>
+-#include <asm/vdso.h>
+-#include <asm/imalloc.h>
+-
+-#if PGTABLE_RANGE > USER_VSID_RANGE
+-#warning Limited user VSID range means pagetable space is wasted
+-#endif
+-
+-#if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
+-#warning TASK_SIZE is smaller than it needs to be.
+-#endif
+-
+-int mem_init_done;
+-unsigned long ioremap_bot = IMALLOC_BASE;
+-static unsigned long phbs_io_bot = PHBS_IO_BASE;
+-
+-extern pgd_t swapper_pg_dir[];
+-extern struct task_struct *current_set[NR_CPUS];
+-
+-unsigned long klimit = (unsigned long)_end;
+-
+-unsigned long _SDR1=0;
+-unsigned long _ASR=0;
+-
+-/* max amount of RAM to use */
+-unsigned long __max_memory;
+-
+-/* info on what we think the IO hole is */
+-unsigned long io_hole_start;
+-unsigned long io_hole_size;
+-
+-void show_mem(void)
+-{
+- unsigned long total = 0, reserved = 0;
+- unsigned long shared = 0, cached = 0;
+- struct page *page;
+- pg_data_t *pgdat;
+- unsigned long i;
+-
+- printk("Mem-info:\n");
+- show_free_areas();
+- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+- for_each_pgdat(pgdat) {
+- for (i = 0; i < pgdat->node_spanned_pages; i++) {
+- page = pgdat_page_nr(pgdat, i);
+- total++;
+- if (PageReserved(page))
+- reserved++;
+- else if (PageSwapCache(page))
+- cached++;
+- else if (page_count(page))
+- shared += page_count(page) - 1;
+- }
+- }
+- printk("%ld pages of RAM\n", total);
+- printk("%ld reserved pages\n", reserved);
+- printk("%ld pages shared\n", shared);
+- printk("%ld pages swap cached\n", cached);
+-}
+-
+-#ifdef CONFIG_PPC_ISERIES
+-
+-void __iomem *ioremap(unsigned long addr, unsigned long size)
+-{
+- return (void __iomem *)addr;
+-}
+-
+-extern void __iomem *__ioremap(unsigned long addr, unsigned long size,
+- unsigned long flags)
+-{
+- return (void __iomem *)addr;
+-}
+-
+-void iounmap(volatile void __iomem *addr)
+-{
+- return;
+-}
+-
+-#else
+-
+-/*
+- * map_io_page currently only called by __ioremap
+- * map_io_page adds an entry to the ioremap page table
+- * and adds an entry to the HPT, possibly bolting it
+- */
+-static int map_io_page(unsigned long ea, unsigned long pa, int flags)
+-{
+- pgd_t *pgdp;
+- pud_t *pudp;
+- pmd_t *pmdp;
+- pte_t *ptep;
+- unsigned long vsid;
+-
+- 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)
+- return -ENOMEM;
+- pmdp = pmd_alloc(&init_mm, pudp, ea);
+- if (!pmdp)
+- return -ENOMEM;
+- ptep = pte_alloc_kernel(&init_mm, 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;
+-
+- /*
+- * If the mm subsystem is not fully up, we cannot create a
+- * linux page table entry for this mapping. Simply bolt an
+- * entry in the hardware page table.
+- */
+- vsid = get_kernel_vsid(ea);
+- va = (vsid << 28) | (ea & 0xFFFFFFF);
+- vpn = va >> PAGE_SHIFT;
+-
+- hash = hpt_hash(vpn, 0);
+-
+- hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
+-
+- /* Panic if a pte grpup is full */
+- if (ppc_md.hpte_insert(hpteg, va, pa >> PAGE_SHIFT,
+- HPTE_V_BOLTED,
+- _PAGE_NO_CACHE|_PAGE_GUARDED|PP_RWXX)
+- == -1) {
+- panic("map_io_page: could not insert mapping");
+- }
+- }
+- return 0;
+-}
+-
+-
+-static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
+- unsigned long ea, unsigned long size,
+- unsigned long flags)
+-{
+- unsigned long i;
+-
+- if ((flags & _PAGE_PRESENT) == 0)
+- flags |= pgprot_val(PAGE_KERNEL);
+-
+- for (i = 0; i < size; i += PAGE_SIZE)
+- if (map_io_page(ea+i, pa+i, flags))
+- return NULL;
+-
+- return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+-}
+-
+-
+-void __iomem *
+-ioremap(unsigned long addr, unsigned long size)
+-{
+- return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
+-}
+-
+-void __iomem * __ioremap(unsigned long addr, unsigned long size,
+- unsigned long flags)
+-{
+- unsigned long pa, ea;
+- void __iomem *ret;
+-
+- /*
+- * Choose an address to map it to.
+- * Once the imalloc system is running, we use it.
+- * Before that, we map using addresses going
+- * up from ioremap_bot. imalloc will use
+- * the addresses from ioremap_bot through
+- * IMALLOC_END
+- *
+- */
+- pa = addr & PAGE_MASK;
+- size = PAGE_ALIGN(addr + size) - pa;
+-
+- if (size == 0)
+- return NULL;
+-
+- if (mem_init_done) {
+- struct vm_struct *area;
+- area = im_get_free_area(size);
+- if (area == NULL)
+- return NULL;
+- ea = (unsigned long)(area->addr);
+- ret = __ioremap_com(addr, pa, ea, size, flags);
+- if (!ret)
+- im_free(area->addr);
+- } else {
+- ea = ioremap_bot;
+- ret = __ioremap_com(addr, pa, ea, size, flags);
+- if (ret)
+- ioremap_bot += size;
+- }
+- return ret;
+-}
+-
+-#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
+-
+-int __ioremap_explicit(unsigned long pa, unsigned long ea,
+- unsigned long size, unsigned long flags)
+-{
+- struct vm_struct *area;
+- void __iomem *ret;
+-
+- /* For now, require page-aligned values for pa, ea, and size */
+- if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
+- !IS_PAGE_ALIGNED(size)) {
+- printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__);
+- return 1;
+- }
+-
+- if (!mem_init_done) {
+- /* Two things to consider in this case:
+- * 1) No records will be kept (imalloc, etc) that the region
+- * has been remapped
+- * 2) It won't be easy to iounmap() the region later (because
+- * of 1)
+- */
+- ;
+- } else {
+- area = im_get_area(ea, size,
+- IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
+- if (area == NULL) {
+- /* Expected when PHB-dlpar is in play */
+- return 1;
+- }
+- if (ea != (unsigned long) area->addr) {
+- printk(KERN_ERR "unexpected addr return from "
+- "im_get_area\n");
+- return 1;
+- }
+- }
+-
+- ret = __ioremap_com(pa, pa, ea, size, flags);
+- if (ret == NULL) {
+- printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
+- return 1;
+- }
+- if (ret != (void *) ea) {
+- printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * Unmap an IO region and remove it from imalloc'd list.
+- * Access to IO memory should be serialized by driver.
+- * This code is modeled after vmalloc code - unmap_vm_area()
+- *
+- * XXX what about calls before mem_init_done (ie python_countermeasures())
+- */
+-void iounmap(volatile void __iomem *token)
+-{
+- void *addr;
+-
+- if (!mem_init_done)
+- return;
+-
+- addr = (void *) ((unsigned long __force) token & PAGE_MASK);
+-
+- im_free(addr);
+-}
+-
+-static int iounmap_subset_regions(unsigned long addr, unsigned long size)
+-{
+- struct vm_struct *area;
+-
+- /* Check whether subsets of this region exist */
+- area = im_get_area(addr, size, IM_REGION_SUPERSET);
+- if (area == NULL)
+- return 1;
+-
+- while (area) {
+- iounmap((void __iomem *) area->addr);
+- area = im_get_area(addr, size,
+- IM_REGION_SUPERSET);
+- }
+-
+- return 0;
+-}
+-
+-int iounmap_explicit(volatile void __iomem *start, unsigned long size)
+-{
+- struct vm_struct *area;
+- unsigned long addr;
+- int rc;
+-
+- addr = (unsigned long __force) start & PAGE_MASK;
+-
+- /* Verify that the region either exists or is a subset of an existing
+- * region. In the latter case, split the parent region to create
+- * the exact region
+- */
+- area = im_get_area(addr, size,
+- IM_REGION_EXISTS | IM_REGION_SUBSET);
+- if (area == NULL) {
+- /* Determine whether subset regions exist. If so, unmap */
+- rc = iounmap_subset_regions(addr, size);
+- if (rc) {
+- printk(KERN_ERR
+- "%s() cannot unmap nonexistent range 0x%lx\n",
+- __FUNCTION__, addr);
+- return 1;
+- }
+- } else {
+- iounmap((void __iomem *) area->addr);
+- }
+- /*
+- * FIXME! This can't be right:
+- iounmap(area->addr);
+- * Maybe it should be "iounmap(area);"
+- */
+- return 0;
+-}
+-
+-#endif
+-
+-EXPORT_SYMBOL(ioremap);
+-EXPORT_SYMBOL(__ioremap);
+-EXPORT_SYMBOL(iounmap);
+-
+-void free_initmem(void)
+-{
+- unsigned long addr;
+-
+- addr = (unsigned long)__init_begin;
+- for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
+- memset((void *)addr, 0xcc, PAGE_SIZE);
+- ClearPageReserved(virt_to_page(addr));
+- set_page_count(virt_to_page(addr), 1);
+- free_page(addr);
+- totalram_pages++;
+- }
+- printk ("Freeing unused kernel memory: %luk freed\n",
+- ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10);
+-}
+-
+-#ifdef CONFIG_BLK_DEV_INITRD
+-void free_initrd_mem(unsigned long start, unsigned long end)
+-{
+- if (start < end)
+- printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+- for (; start < end; start += PAGE_SIZE) {
+- ClearPageReserved(virt_to_page(start));
+- set_page_count(virt_to_page(start), 1);
+- free_page(start);
+- totalram_pages++;
+- }
+-}
+-#endif
+-
+-static DEFINE_SPINLOCK(mmu_context_lock);
+-static DEFINE_IDR(mmu_context_idr);
+-
+-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+-{
+- int index;
+- int err;
+-
+-again:
+- if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
+- return -ENOMEM;
+-
+- spin_lock(&mmu_context_lock);
+- err = idr_get_new_above(&mmu_context_idr, NULL, 1, &index);
+- spin_unlock(&mmu_context_lock);
+-
+- if (err == -EAGAIN)
+- goto again;
+- else if (err)
+- return err;
+-
+- if (index > MAX_CONTEXT) {
+- idr_remove(&mmu_context_idr, index);
+- return -ENOMEM;
+- }
+-
+- mm->context.id = index;
+-
+- return 0;
+-}
+-
+-void destroy_context(struct mm_struct *mm)
+-{
+- spin_lock(&mmu_context_lock);
+- idr_remove(&mmu_context_idr, mm->context.id);
+- spin_unlock(&mmu_context_lock);
+-
+- mm->context.id = NO_CONTEXT;
+-}
+-
+-/*
+- * Do very early mm setup.
+- */
+-void __init mm_init_ppc64(void)
+-{
+-#ifndef CONFIG_PPC_ISERIES
+- unsigned long i;
+-#endif
+-
+- ppc64_boot_msg(0x100, "MM Init");
+-
+- /* This is the story of the IO hole... please, keep seated,
+- * unfortunately, we are out of oxygen masks at the moment.
+- * So we need some rough way to tell where your big IO hole
+- * is. On pmac, it's between 2G and 4G, on POWER3, it's around
+- * that area as well, on POWER4 we don't have one, etc...
+- * We need that as a "hint" when sizing the TCE table on POWER3
+- * So far, the simplest way that seem work well enough for us it
+- * to just assume that the first discontinuity in our physical
+- * RAM layout is the IO hole. That may not be correct in the future
+- * (and isn't on iSeries but then we don't care ;)
+- */
+-
+-#ifndef CONFIG_PPC_ISERIES
+- for (i = 1; i < lmb.memory.cnt; i++) {
+- unsigned long base, prevbase, prevsize;
+-
+- prevbase = lmb.memory.region[i-1].base;
+- prevsize = lmb.memory.region[i-1].size;
+- base = lmb.memory.region[i].base;
+- if (base > (prevbase + prevsize)) {
+- io_hole_start = prevbase + prevsize;
+- io_hole_size = base - (prevbase + prevsize);
+- break;
+- }
+- }
+-#endif /* CONFIG_PPC_ISERIES */
+- if (io_hole_start)
+- printk("IO Hole assumed to be %lx -> %lx\n",
+- io_hole_start, io_hole_start + io_hole_size - 1);
+-
+- ppc64_boot_msg(0x100, "MM Init Done");
+-}
+-
+-/*
+- * This is called by /dev/mem to know if a given address has to
+- * be mapped non-cacheable or not
+- */
+-int page_is_ram(unsigned long pfn)
+-{
+- int i;
+- unsigned long paddr = (pfn << PAGE_SHIFT);
+-
+- for (i=0; i < lmb.memory.cnt; i++) {
+- unsigned long base;
+-
+- base = lmb.memory.region[i].base;
+-
+- if ((paddr >= base) &&
+- (paddr < (base + lmb.memory.region[i].size))) {
+- return 1;
+- }
+- }
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(page_is_ram);
+-
+-/*
+- * Initialize the bootmem system and give it all the memory we
+- * have available.
+- */
+-#ifndef CONFIG_NEED_MULTIPLE_NODES
+-void __init do_init_bootmem(void)
+-{
+- unsigned long i;
+- unsigned long start, bootmap_pages;
+- unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT;
+- int boot_mapsize;
+-
+- /*
+- * Find an area to use for the bootmem bitmap. Calculate the size of
+- * bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE.
+- * Add 1 additional page in case the address isn't page-aligned.
+- */
+- bootmap_pages = bootmem_bootmap_pages(total_pages);
+-
+- start = lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
+- BUG_ON(!start);
+-
+- boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
+-
+- max_pfn = max_low_pfn;
+-
+- /* Add all physical memory to the bootmem map, mark each area
+- * present.
+- */
+- for (i=0; i < lmb.memory.cnt; i++)
+- free_bootmem(lmb.memory.region[i].base,
+- lmb_size_bytes(&lmb.memory, i));
+-
+- /* reserve the sections we're already using */
+- for (i=0; i < lmb.reserved.cnt; i++)
+- reserve_bootmem(lmb.reserved.region[i].base,
+- lmb_size_bytes(&lmb.reserved, i));
+-
+- for (i=0; i < lmb.memory.cnt; i++)
+- memory_present(0, lmb_start_pfn(&lmb.memory, i),
+- lmb_end_pfn(&lmb.memory, i));
+-}
+-
+-/*
+- * paging_init() sets up the page tables - in fact we've already done this.
+- */
+-void __init paging_init(void)
+-{
+- unsigned long zones_size[MAX_NR_ZONES];
+- unsigned long zholes_size[MAX_NR_ZONES];
+- unsigned long total_ram = lmb_phys_mem_size();
+- unsigned long top_of_ram = lmb_end_of_DRAM();
+-
+- printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
+- top_of_ram, total_ram);
+- printk(KERN_INFO "Memory hole size: %ldMB\n",
+- (top_of_ram - total_ram) >> 20);
+- /*
+- * All pages are DMA-able so we put them all in the DMA zone.
+- */
+- memset(zones_size, 0, sizeof(zones_size));
+- memset(zholes_size, 0, sizeof(zholes_size));
+-
+- zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
+- zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
+-
+- free_area_init_node(0, NODE_DATA(0), zones_size,
+- __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
+-}
+-#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
+-
+-static struct kcore_list kcore_vmem;
+-
+-static int __init setup_kcore(void)
+-{
+- int i;
+-
+- for (i=0; i < lmb.memory.cnt; i++) {
+- unsigned long base, size;
+- struct kcore_list *kcore_mem;
+-
+- base = lmb.memory.region[i].base;
+- size = lmb.memory.region[i].size;
+-
+- /* GFP_ATOMIC to avoid might_sleep warnings during boot */
+- kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
+- if (!kcore_mem)
+- panic("mem_init: kmalloc failed\n");
+-
+- kclist_add(kcore_mem, __va(base), size);
+- }
+-
+- kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);
+-
+- return 0;
+-}
+-module_init(setup_kcore);
+-
+-void __init mem_init(void)
+-{
+-#ifdef CONFIG_NEED_MULTIPLE_NODES
+- int nid;
+-#endif
+- pg_data_t *pgdat;
+- unsigned long i;
+- struct page *page;
+- unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize;
+-
+- num_physpages = max_low_pfn; /* RAM is assumed contiguous */
+- high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+-
+-#ifdef CONFIG_NEED_MULTIPLE_NODES
+- for_each_online_node(nid) {
+- if (NODE_DATA(nid)->node_spanned_pages != 0) {
+- printk("freeing bootmem node %x\n", nid);
+- totalram_pages +=
+- free_all_bootmem_node(NODE_DATA(nid));
+- }
+- }
+-#else
+- max_mapnr = num_physpages;
+- totalram_pages += free_all_bootmem();
+-#endif
+-
+- for_each_pgdat(pgdat) {
+- for (i = 0; i < pgdat->node_spanned_pages; i++) {
+- page = pgdat_page_nr(pgdat, i);
+- if (PageReserved(page))
+- reservedpages++;
+- }
+- }
+-
+- codesize = (unsigned long)&_etext - (unsigned long)&_stext;
+- initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
+- datasize = (unsigned long)&_edata - (unsigned long)&__init_end;
+- bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start;
+-
+- printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, "
+- "%luk reserved, %luk data, %luk bss, %luk init)\n",
+- (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
+- num_physpages << (PAGE_SHIFT-10),
+- codesize >> 10,
+- reservedpages << (PAGE_SHIFT-10),
+- datasize >> 10,
+- bsssize >> 10,
+- initsize >> 10);
+-
+- mem_init_done = 1;
+-
+- /* Initialize the vDSO */
+- vdso_init();
+-}
+-
+-/*
+- * This is called when a page has been modified by the kernel.
+- * It just marks the page as not i-cache clean. We do the i-cache
+- * flush later when the page is given to a user process, if necessary.
+- */
+-void flush_dcache_page(struct page *page)
+-{
+- if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
+- return;
+- /* avoid an atomic op if possible */
+- if (test_bit(PG_arch_1, &page->flags))
+- clear_bit(PG_arch_1, &page->flags);
+-}
+-EXPORT_SYMBOL(flush_dcache_page);
+-
+-void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
+-{
+- clear_page(page);
+-
+- if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
+- return;
+- /*
+- * We shouldnt have to do this, but some versions of glibc
+- * require it (ld.so assumes zero filled pages are icache clean)
+- * - Anton
+- */
+-
+- /* avoid an atomic op if possible */
+- if (test_bit(PG_arch_1, &pg->flags))
+- clear_bit(PG_arch_1, &pg->flags);
+-}
+-EXPORT_SYMBOL(clear_user_page);
+-
+-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+- struct page *pg)
+-{
+- copy_page(vto, vfrom);
+-
+- /*
+- * We should be able to use the following optimisation, however
+- * there are two problems.
+- * Firstly a bug in some versions of binutils meant PLT sections
+- * were not marked executable.
+- * Secondly the first word in the GOT section is blrl, used
+- * to establish the GOT address. Until recently the GOT was
+- * not marked executable.
+- * - Anton
+- */
+-#if 0
+- if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0))
+- return;
+-#endif
+-
+- if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
+- return;
+-
+- /* avoid an atomic op if possible */
+- if (test_bit(PG_arch_1, &pg->flags))
+- clear_bit(PG_arch_1, &pg->flags);
+-}
+-
+-void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+- unsigned long addr, int len)
+-{
+- unsigned long maddr;
+-
+- maddr = (unsigned long)page_address(page) + (addr & ~PAGE_MASK);
+- flush_icache_range(maddr, maddr + len);
+-}
+-EXPORT_SYMBOL(flush_icache_user_range);
+-
+-/*
+- * This is called at the end of handling a user page fault, when the
+- * fault has been handled by updating a PTE in the linux page tables.
+- * We use it to preload an HPTE into the hash table corresponding to
+- * the updated linux PTE.
+- *
+- * This must always be called with the mm->page_table_lock held
+- */
+-void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea,
+- pte_t pte)
+-{
+- unsigned long vsid;
+- void *pgdir;
+- pte_t *ptep;
+- int local = 0;
+- cpumask_t tmp;
+- unsigned long flags;
+-
+- /* handle i-cache coherency */
+- if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
+- !cpu_has_feature(CPU_FTR_NOEXECUTE)) {
+- unsigned long pfn = pte_pfn(pte);
+- if (pfn_valid(pfn)) {
+- struct page *page = pfn_to_page(pfn);
+- if (!PageReserved(page)
+- && !test_bit(PG_arch_1, &page->flags)) {
+- __flush_dcache_icache(page_address(page));
+- set_bit(PG_arch_1, &page->flags);
+- }
+- }
+- }
+-
+- /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
+- if (!pte_young(pte))
+- return;
+-
+- pgdir = vma->vm_mm->pgd;
+- if (pgdir == NULL)
+- return;
+-
+- ptep = find_linux_pte(pgdir, ea);
+- if (!ptep)
+- return;
+-
+- vsid = get_vsid(vma->vm_mm->context.id, ea);
+-
+- local_irq_save(flags);
+- tmp = cpumask_of_cpu(smp_processor_id());
+- if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
+- local = 1;
+-
+- __hash_page(ea, 0, vsid, ptep, 0x300, local);
+- local_irq_restore(flags);
+-}
+-
+-void __iomem * reserve_phb_iospace(unsigned long size)
+-{
+- void __iomem *virt_addr;
+-
+- if (phbs_io_bot >= IMALLOC_BASE)
+- panic("reserve_phb_iospace(): phb io space overflow\n");
+-
+- virt_addr = (void __iomem *) phbs_io_bot;
+- phbs_io_bot += size;
+-
+- return virt_addr;
+-}
+-
+-static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
+-{
+- memset(addr, 0, kmem_cache_size(cache));
+-}
+-
+-static const int pgtable_cache_size[2] = {
+- PTE_TABLE_SIZE, PMD_TABLE_SIZE
+-};
+-static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
+- "pgd_pte_cache", "pud_pmd_cache",
+-};
+-
+-kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
+-
+-void pgtable_cache_init(void)
+-{
+- int i;
+-
+- BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]);
+- BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]);
+- BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]);
+- BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]);
+-
+- for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {
+- int size = pgtable_cache_size[i];
+- const char *name = pgtable_cache_name[i];
+-
+- pgtable_cache[i] = kmem_cache_create(name,
+- size, size,
+- SLAB_HWCACHE_ALIGN
+- | SLAB_MUST_HWCACHE_ALIGN,
+- zero_ctor,
+- NULL);
+- if (! pgtable_cache[i])
+- panic("pgtable_cache_init(): could not create %s!\n",
+- name);
+- }
+-}
+-
+-pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
+- unsigned long size, pgprot_t vma_prot)
+-{
+- if (ppc_md.phys_mem_access_prot)
+- return ppc_md.phys_mem_access_prot(file, addr, size, vma_prot);
+-
+- if (!page_is_ram(addr >> PAGE_SHIFT))
+- vma_prot = __pgprot(pgprot_val(vma_prot)
+- | _PAGE_GUARDED | _PAGE_NO_CACHE);
+- return vma_prot;
+-}
+-EXPORT_SYMBOL(phys_mem_access_prot);
+diff --git a/arch/ppc64/mm/mmap.c b/arch/ppc64/mm/mmap.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/mmap.c
++++ /dev/null
+@@ -1,86 +0,0 @@
+-/*
+- * linux/arch/ppc64/mm/mmap.c
+- *
+- * flexible mmap layout support
+- *
+- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+- * 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
+- *
+- *
+- * Started by Ingo Molnar <mingo at elte.hu>
+- */
+-
+-#include <linux/personality.h>
+-#include <linux/mm.h>
+-
+-/*
+- * Top of mmap area (just below the process stack).
+- *
+- * Leave an at least ~128 MB hole.
+- */
+-#define MIN_GAP (128*1024*1024)
+-#define MAX_GAP (TASK_SIZE/6*5)
+-
+-static inline unsigned long mmap_base(void)
+-{
+- unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
+-
+- if (gap < MIN_GAP)
+- gap = MIN_GAP;
+- else if (gap > MAX_GAP)
+- gap = MAX_GAP;
+-
+- return TASK_SIZE - (gap & PAGE_MASK);
+-}
+-
+-static inline int mmap_is_legacy(void)
+-{
+- /*
+- * Force standard allocation for 64 bit programs.
+- */
+- if (!test_thread_flag(TIF_32BIT))
+- return 1;
+-
+- if (current->personality & ADDR_COMPAT_LAYOUT)
+- return 1;
+-
+- if (current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
+- return 1;
+-
+- return sysctl_legacy_va_layout;
+-}
+-
+-/*
+- * This function, called very early during the creation of a new
+- * process VM image, sets up which VM layout function to use:
+- */
+-void arch_pick_mmap_layout(struct mm_struct *mm)
+-{
+- /*
+- * Fall back to the standard layout if the personality
+- * bit is set, or if the expected stack growth is unlimited:
+- */
+- if (mmap_is_legacy()) {
+- mm->mmap_base = TASK_UNMAPPED_BASE;
+- mm->get_unmapped_area = arch_get_unmapped_area;
+- mm->unmap_area = arch_unmap_area;
+- } else {
+- mm->mmap_base = mmap_base();
+- mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+- mm->unmap_area = arch_unmap_area_topdown;
+- }
+-}
+diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/numa.c
++++ /dev/null
+@@ -1,779 +0,0 @@
+-/*
+- * pSeries NUMA support
+- *
+- * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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/threads.h>
+-#include <linux/bootmem.h>
+-#include <linux/init.h>
+-#include <linux/mm.h>
+-#include <linux/mmzone.h>
+-#include <linux/module.h>
+-#include <linux/nodemask.h>
+-#include <linux/cpu.h>
+-#include <linux/notifier.h>
+-#include <asm/lmb.h>
+-#include <asm/machdep.h>
+-#include <asm/abs_addr.h>
+-
+-static int numa_enabled = 1;
+-
+-static int numa_debug;
+-#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
+-
+-#ifdef DEBUG_NUMA
+-#define ARRAY_INITIALISER -1
+-#else
+-#define ARRAY_INITIALISER 0
+-#endif
+-
+-int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] =
+- ARRAY_INITIALISER};
+-char *numa_memory_lookup_table;
+-cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
+-int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0};
+-
+-struct pglist_data *node_data[MAX_NUMNODES];
+-bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
+-static int min_common_depth;
+-
+-/*
+- * We need somewhere to store start/span for each node until we have
+- * allocated the real node_data structures.
+- */
+-static struct {
+- unsigned long node_start_pfn;
+- unsigned long node_end_pfn;
+- unsigned long node_present_pages;
+-} init_node_data[MAX_NUMNODES] __initdata;
+-
+-EXPORT_SYMBOL(node_data);
+-EXPORT_SYMBOL(numa_cpu_lookup_table);
+-EXPORT_SYMBOL(numa_memory_lookup_table);
+-EXPORT_SYMBOL(numa_cpumask_lookup_table);
+-EXPORT_SYMBOL(nr_cpus_in_node);
+-
+-static inline void map_cpu_to_node(int cpu, int node)
+-{
+- numa_cpu_lookup_table[cpu] = node;
+- if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) {
+- cpu_set(cpu, numa_cpumask_lookup_table[node]);
+- nr_cpus_in_node[node]++;
+- }
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-static void unmap_cpu_from_node(unsigned long cpu)
+-{
+- int node = numa_cpu_lookup_table[cpu];
+-
+- dbg("removing cpu %lu from node %d\n", cpu, node);
+-
+- if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
+- cpu_clear(cpu, numa_cpumask_lookup_table[node]);
+- nr_cpus_in_node[node]--;
+- } else {
+- printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n",
+- cpu, node);
+- }
+-}
+-#endif /* CONFIG_HOTPLUG_CPU */
+-
+-static struct device_node * __devinit find_cpu_node(unsigned int cpu)
+-{
+- unsigned int hw_cpuid = get_hard_smp_processor_id(cpu);
+- struct device_node *cpu_node = NULL;
+- unsigned int *interrupt_server, *reg;
+- int len;
+-
+- while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) {
+- /* Try interrupt server first */
+- interrupt_server = (unsigned int *)get_property(cpu_node,
+- "ibm,ppc-interrupt-server#s", &len);
+-
+- len = len / sizeof(u32);
+-
+- if (interrupt_server && (len > 0)) {
+- while (len--) {
+- if (interrupt_server[len] == hw_cpuid)
+- return cpu_node;
+- }
+- } else {
+- reg = (unsigned int *)get_property(cpu_node,
+- "reg", &len);
+- if (reg && (len > 0) && (reg[0] == hw_cpuid))
+- return cpu_node;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-/* must hold reference to node during call */
+-static int *of_get_associativity(struct device_node *dev)
+-{
+- return (unsigned int *)get_property(dev, "ibm,associativity", NULL);
+-}
+-
+-static int of_node_numa_domain(struct device_node *device)
+-{
+- int numa_domain;
+- unsigned int *tmp;
+-
+- if (min_common_depth == -1)
+- return 0;
+-
+- tmp = of_get_associativity(device);
+- if (tmp && (tmp[0] >= min_common_depth)) {
+- numa_domain = tmp[min_common_depth];
+- } else {
+- dbg("WARNING: no NUMA information for %s\n",
+- device->full_name);
+- numa_domain = 0;
+- }
+- return numa_domain;
+-}
+-
+-/*
+- * In theory, the "ibm,associativity" property may contain multiple
+- * associativity lists because a resource may be multiply connected
+- * into the machine. This resource then has different associativity
+- * characteristics relative to its multiple connections. We ignore
+- * this for now. We also assume that all cpu and memory sets have
+- * their distances represented at a common level. This won't be
+- * true for heirarchical NUMA.
+- *
+- * In any case the ibm,associativity-reference-points should give
+- * the correct depth for a normal NUMA system.
+- *
+- * - Dave Hansen <haveblue at us.ibm.com>
+- */
+-static int __init find_min_common_depth(void)
+-{
+- int depth;
+- unsigned int *ref_points;
+- struct device_node *rtas_root;
+- unsigned int len;
+-
+- rtas_root = of_find_node_by_path("/rtas");
+-
+- if (!rtas_root)
+- return -1;
+-
+- /*
+- * this property is 2 32-bit integers, each representing a level of
+- * depth in the associativity nodes. The first is for an SMP
+- * configuration (should be all 0's) and the second is for a normal
+- * NUMA configuration.
+- */
+- ref_points = (unsigned int *)get_property(rtas_root,
+- "ibm,associativity-reference-points", &len);
+-
+- if ((len >= 1) && ref_points) {
+- depth = ref_points[1];
+- } else {
+- dbg("WARNING: could not find NUMA "
+- "associativity reference point\n");
+- depth = -1;
+- }
+- of_node_put(rtas_root);
+-
+- return depth;
+-}
+-
+-static int __init get_mem_addr_cells(void)
+-{
+- struct device_node *memory = NULL;
+- int rc;
+-
+- memory = of_find_node_by_type(memory, "memory");
+- if (!memory)
+- return 0; /* it won't matter */
+-
+- rc = prom_n_addr_cells(memory);
+- return rc;
+-}
+-
+-static int __init get_mem_size_cells(void)
+-{
+- struct device_node *memory = NULL;
+- int rc;
+-
+- memory = of_find_node_by_type(memory, "memory");
+- if (!memory)
+- return 0; /* it won't matter */
+- rc = prom_n_size_cells(memory);
+- return rc;
+-}
+-
+-static unsigned long read_n_cells(int n, unsigned int **buf)
+-{
+- unsigned long result = 0;
+-
+- while (n--) {
+- result = (result << 32) | **buf;
+- (*buf)++;
+- }
+- return result;
+-}
+-
+-/*
+- * Figure out to which domain a cpu belongs and stick it there.
+- * Return the id of the domain used.
+- */
+-static int numa_setup_cpu(unsigned long lcpu)
+-{
+- int numa_domain = 0;
+- struct device_node *cpu = find_cpu_node(lcpu);
+-
+- if (!cpu) {
+- WARN_ON(1);
+- goto out;
+- }
+-
+- numa_domain = of_node_numa_domain(cpu);
+-
+- if (numa_domain >= num_online_nodes()) {
+- /*
+- * POWER4 LPAR uses 0xffff as invalid node,
+- * dont warn in this case.
+- */
+- if (numa_domain != 0xffff)
+- printk(KERN_ERR "WARNING: cpu %ld "
+- "maps to invalid NUMA node %d\n",
+- lcpu, numa_domain);
+- numa_domain = 0;
+- }
+-out:
+- node_set_online(numa_domain);
+-
+- map_cpu_to_node(lcpu, numa_domain);
+-
+- of_node_put(cpu);
+-
+- return numa_domain;
+-}
+-
+-static int cpu_numa_callback(struct notifier_block *nfb,
+- unsigned long action,
+- void *hcpu)
+-{
+- unsigned long lcpu = (unsigned long)hcpu;
+- int ret = NOTIFY_DONE;
+-
+- switch (action) {
+- case CPU_UP_PREPARE:
+- if (min_common_depth == -1 || !numa_enabled)
+- map_cpu_to_node(lcpu, 0);
+- else
+- numa_setup_cpu(lcpu);
+- ret = NOTIFY_OK;
+- break;
+-#ifdef CONFIG_HOTPLUG_CPU
+- case CPU_DEAD:
+- case CPU_UP_CANCELED:
+- unmap_cpu_from_node(lcpu);
+- break;
+- ret = NOTIFY_OK;
+-#endif
+- }
+- return ret;
+-}
+-
+-/*
+- * Check and possibly modify a memory region to enforce the memory limit.
+- *
+- * Returns the size the region should have to enforce the memory limit.
+- * This will either be the original value of size, a truncated value,
+- * or zero. If the returned value of size is 0 the region should be
+- * discarded as it lies wholy above the memory limit.
+- */
+-static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size)
+-{
+- /*
+- * We use lmb_end_of_DRAM() in here instead of memory_limit because
+- * we've already adjusted it for the limit and it takes care of
+- * having memory holes below the limit.
+- */
+- extern unsigned long memory_limit;
+-
+- if (! memory_limit)
+- return size;
+-
+- if (start + size <= lmb_end_of_DRAM())
+- return size;
+-
+- if (start >= lmb_end_of_DRAM())
+- return 0;
+-
+- return lmb_end_of_DRAM() - start;
+-}
+-
+-static int __init parse_numa_properties(void)
+-{
+- struct device_node *cpu = NULL;
+- struct device_node *memory = NULL;
+- int addr_cells, size_cells;
+- int max_domain = 0;
+- long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT;
+- unsigned long i;
+-
+- if (numa_enabled == 0) {
+- printk(KERN_WARNING "NUMA disabled by user\n");
+- return -1;
+- }
+-
+- numa_memory_lookup_table =
+- (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
+- memset(numa_memory_lookup_table, 0, entries * sizeof(char));
+-
+- for (i = 0; i < entries ; i++)
+- numa_memory_lookup_table[i] = ARRAY_INITIALISER;
+-
+- min_common_depth = find_min_common_depth();
+-
+- dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth);
+- if (min_common_depth < 0)
+- return min_common_depth;
+-
+- max_domain = numa_setup_cpu(boot_cpuid);
+-
+- /*
+- * Even though we connect cpus to numa domains later in SMP init,
+- * we need to know the maximum node id now. This is because each
+- * node id must have NODE_DATA etc backing it.
+- * As a result of hotplug we could still have cpus appear later on
+- * with larger node ids. In that case we force the cpu into node 0.
+- */
+- for_each_cpu(i) {
+- int numa_domain;
+-
+- cpu = find_cpu_node(i);
+-
+- if (cpu) {
+- numa_domain = of_node_numa_domain(cpu);
+- of_node_put(cpu);
+-
+- if (numa_domain < MAX_NUMNODES &&
+- max_domain < numa_domain)
+- max_domain = numa_domain;
+- }
+- }
+-
+- addr_cells = get_mem_addr_cells();
+- size_cells = get_mem_size_cells();
+- memory = NULL;
+- while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+- unsigned long start;
+- unsigned long size;
+- int numa_domain;
+- int ranges;
+- unsigned int *memcell_buf;
+- unsigned int len;
+-
+- memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
+- if (!memcell_buf || len <= 0)
+- continue;
+-
+- ranges = memory->n_addrs;
+-new_range:
+- /* these are order-sensitive, and modify the buffer pointer */
+- start = read_n_cells(addr_cells, &memcell_buf);
+- size = read_n_cells(size_cells, &memcell_buf);
+-
+- start = _ALIGN_DOWN(start, MEMORY_INCREMENT);
+- size = _ALIGN_UP(size, MEMORY_INCREMENT);
+-
+- numa_domain = of_node_numa_domain(memory);
+-
+- if (numa_domain >= MAX_NUMNODES) {
+- if (numa_domain != 0xffff)
+- printk(KERN_ERR "WARNING: memory at %lx maps "
+- "to invalid NUMA node %d\n", start,
+- numa_domain);
+- numa_domain = 0;
+- }
+-
+- if (max_domain < numa_domain)
+- max_domain = numa_domain;
+-
+- if (! (size = numa_enforce_memory_limit(start, size))) {
+- if (--ranges)
+- goto new_range;
+- else
+- continue;
+- }
+-
+- /*
+- * Initialize new node struct, or add to an existing one.
+- */
+- if (init_node_data[numa_domain].node_end_pfn) {
+- if ((start / PAGE_SIZE) <
+- init_node_data[numa_domain].node_start_pfn)
+- init_node_data[numa_domain].node_start_pfn =
+- start / PAGE_SIZE;
+- if (((start / PAGE_SIZE) + (size / PAGE_SIZE)) >
+- init_node_data[numa_domain].node_end_pfn)
+- init_node_data[numa_domain].node_end_pfn =
+- (start / PAGE_SIZE) +
+- (size / PAGE_SIZE);
+-
+- init_node_data[numa_domain].node_present_pages +=
+- size / PAGE_SIZE;
+- } else {
+- node_set_online(numa_domain);
+-
+- init_node_data[numa_domain].node_start_pfn =
+- start / PAGE_SIZE;
+- init_node_data[numa_domain].node_end_pfn =
+- init_node_data[numa_domain].node_start_pfn +
+- size / PAGE_SIZE;
+- init_node_data[numa_domain].node_present_pages =
+- size / PAGE_SIZE;
+- }
+-
+- for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
+- numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
+- numa_domain;
+-
+- if (--ranges)
+- goto new_range;
+- }
+-
+- for (i = 0; i <= max_domain; i++)
+- node_set_online(i);
+-
+- return 0;
+-}
+-
+-static void __init setup_nonnuma(void)
+-{
+- unsigned long top_of_ram = lmb_end_of_DRAM();
+- unsigned long total_ram = lmb_phys_mem_size();
+- unsigned long i;
+-
+- printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
+- top_of_ram, total_ram);
+- printk(KERN_INFO "Memory hole size: %ldMB\n",
+- (top_of_ram - total_ram) >> 20);
+-
+- if (!numa_memory_lookup_table) {
+- long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT;
+- numa_memory_lookup_table =
+- (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
+- memset(numa_memory_lookup_table, 0, entries * sizeof(char));
+- for (i = 0; i < entries ; i++)
+- numa_memory_lookup_table[i] = ARRAY_INITIALISER;
+- }
+-
+- map_cpu_to_node(boot_cpuid, 0);
+-
+- node_set_online(0);
+-
+- init_node_data[0].node_start_pfn = 0;
+- init_node_data[0].node_end_pfn = lmb_end_of_DRAM() / PAGE_SIZE;
+- init_node_data[0].node_present_pages = total_ram / PAGE_SIZE;
+-
+- for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
+- numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
+-}
+-
+-static void __init dump_numa_topology(void)
+-{
+- unsigned int node;
+- unsigned int count;
+-
+- if (min_common_depth == -1 || !numa_enabled)
+- return;
+-
+- for_each_online_node(node) {
+- unsigned long i;
+-
+- printk(KERN_INFO "Node %d Memory:", node);
+-
+- count = 0;
+-
+- for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) {
+- if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) {
+- if (count == 0)
+- printk(" 0x%lx", i);
+- ++count;
+- } else {
+- if (count > 0)
+- printk("-0x%lx", i);
+- count = 0;
+- }
+- }
+-
+- if (count > 0)
+- printk("-0x%lx", i);
+- printk("\n");
+- }
+- return;
+-}
+-
+-/*
+- * Allocate some memory, satisfying the lmb or bootmem allocator where
+- * required. nid is the preferred node and end is the physical address of
+- * the highest address in the node.
+- *
+- * Returns the physical address of the memory.
+- */
+-static unsigned long careful_allocation(int nid, unsigned long size,
+- unsigned long align, unsigned long end)
+-{
+- unsigned long ret = lmb_alloc_base(size, align, end);
+-
+- /* retry over all memory */
+- if (!ret)
+- ret = lmb_alloc_base(size, align, lmb_end_of_DRAM());
+-
+- if (!ret)
+- panic("numa.c: cannot allocate %lu bytes on node %d",
+- size, nid);
+-
+- /*
+- * If the memory came from a previously allocated node, we must
+- * retry with the bootmem allocator.
+- */
+- if (pa_to_nid(ret) < nid) {
+- nid = pa_to_nid(ret);
+- ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid),
+- size, align, 0);
+-
+- if (!ret)
+- panic("numa.c: cannot allocate %lu bytes on node %d",
+- size, nid);
+-
+- ret = virt_to_abs(ret);
+-
+- dbg("alloc_bootmem %lx %lx\n", ret, size);
+- }
+-
+- return ret;
+-}
+-
+-void __init do_init_bootmem(void)
+-{
+- int nid;
+- int addr_cells, size_cells;
+- struct device_node *memory = NULL;
+- static struct notifier_block ppc64_numa_nb = {
+- .notifier_call = cpu_numa_callback,
+- .priority = 1 /* Must run before sched domains notifier. */
+- };
+-
+- min_low_pfn = 0;
+- max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
+- max_pfn = max_low_pfn;
+-
+- if (parse_numa_properties())
+- setup_nonnuma();
+- else
+- dump_numa_topology();
+-
+- register_cpu_notifier(&ppc64_numa_nb);
+-
+- for_each_online_node(nid) {
+- unsigned long start_paddr, end_paddr;
+- int i;
+- unsigned long bootmem_paddr;
+- unsigned long bootmap_pages;
+-
+- start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE;
+- end_paddr = init_node_data[nid].node_end_pfn * PAGE_SIZE;
+-
+- /* Allocate the node structure node local if possible */
+- NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid,
+- sizeof(struct pglist_data),
+- SMP_CACHE_BYTES, end_paddr);
+- NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid));
+- memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+-
+- dbg("node %d\n", nid);
+- dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
+-
+- NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+- NODE_DATA(nid)->node_start_pfn =
+- init_node_data[nid].node_start_pfn;
+- NODE_DATA(nid)->node_spanned_pages =
+- end_paddr - start_paddr;
+-
+- if (NODE_DATA(nid)->node_spanned_pages == 0)
+- continue;
+-
+- dbg("start_paddr = %lx\n", start_paddr);
+- dbg("end_paddr = %lx\n", end_paddr);
+-
+- bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT);
+-
+- bootmem_paddr = careful_allocation(nid,
+- bootmap_pages << PAGE_SHIFT,
+- PAGE_SIZE, end_paddr);
+- memset(abs_to_virt(bootmem_paddr), 0,
+- bootmap_pages << PAGE_SHIFT);
+- dbg("bootmap_paddr = %lx\n", bootmem_paddr);
+-
+- init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
+- start_paddr >> PAGE_SHIFT,
+- end_paddr >> PAGE_SHIFT);
+-
+- /*
+- * We need to do another scan of all memory sections to
+- * associate memory with the correct node.
+- */
+- addr_cells = get_mem_addr_cells();
+- size_cells = get_mem_size_cells();
+- memory = NULL;
+- while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+- unsigned long mem_start, mem_size;
+- int numa_domain, ranges;
+- unsigned int *memcell_buf;
+- unsigned int len;
+-
+- memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
+- if (!memcell_buf || len <= 0)
+- continue;
+-
+- ranges = memory->n_addrs; /* ranges in cell */
+-new_range:
+- mem_start = read_n_cells(addr_cells, &memcell_buf);
+- mem_size = read_n_cells(size_cells, &memcell_buf);
+- if (numa_enabled) {
+- numa_domain = of_node_numa_domain(memory);
+- if (numa_domain >= MAX_NUMNODES)
+- numa_domain = 0;
+- } else
+- numa_domain = 0;
+-
+- if (numa_domain != nid)
+- continue;
+-
+- mem_size = numa_enforce_memory_limit(mem_start, mem_size);
+- if (mem_size) {
+- dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
+- free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
+- }
+-
+- if (--ranges) /* process all ranges in cell */
+- goto new_range;
+- }
+-
+- /*
+- * Mark reserved regions on this node
+- */
+- for (i = 0; i < lmb.reserved.cnt; i++) {
+- unsigned long physbase = lmb.reserved.region[i].base;
+- unsigned long size = lmb.reserved.region[i].size;
+-
+- if (pa_to_nid(physbase) != nid &&
+- pa_to_nid(physbase+size-1) != nid)
+- continue;
+-
+- if (physbase < end_paddr &&
+- (physbase+size) > start_paddr) {
+- /* overlaps */
+- if (physbase < start_paddr) {
+- size -= start_paddr - physbase;
+- physbase = start_paddr;
+- }
+-
+- if (size > end_paddr - physbase)
+- size = end_paddr - physbase;
+-
+- dbg("reserve_bootmem %lx %lx\n", physbase,
+- size);
+- reserve_bootmem_node(NODE_DATA(nid), physbase,
+- size);
+- }
+- }
+- /*
+- * This loop may look famaliar, but we have to do it again
+- * after marking our reserved memory to mark memory present
+- * for sparsemem.
+- */
+- addr_cells = get_mem_addr_cells();
+- size_cells = get_mem_size_cells();
+- memory = NULL;
+- while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+- unsigned long mem_start, mem_size;
+- int numa_domain, ranges;
+- unsigned int *memcell_buf;
+- unsigned int len;
+-
+- memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
+- if (!memcell_buf || len <= 0)
+- continue;
+-
+- ranges = memory->n_addrs; /* ranges in cell */
+-new_range2:
+- mem_start = read_n_cells(addr_cells, &memcell_buf);
+- mem_size = read_n_cells(size_cells, &memcell_buf);
+- if (numa_enabled) {
+- numa_domain = of_node_numa_domain(memory);
+- if (numa_domain >= MAX_NUMNODES)
+- numa_domain = 0;
+- } else
+- numa_domain = 0;
+-
+- if (numa_domain != nid)
+- continue;
+-
+- mem_size = numa_enforce_memory_limit(mem_start, mem_size);
+- memory_present(numa_domain, mem_start >> PAGE_SHIFT,
+- (mem_start + mem_size) >> PAGE_SHIFT);
+-
+- if (--ranges) /* process all ranges in cell */
+- goto new_range2;
+- }
+-
+- }
+-}
+-
+-void __init paging_init(void)
+-{
+- unsigned long zones_size[MAX_NR_ZONES];
+- unsigned long zholes_size[MAX_NR_ZONES];
+- int nid;
+-
+- memset(zones_size, 0, sizeof(zones_size));
+- memset(zholes_size, 0, sizeof(zholes_size));
+-
+- for_each_online_node(nid) {
+- unsigned long start_pfn;
+- unsigned long end_pfn;
+-
+- start_pfn = init_node_data[nid].node_start_pfn;
+- end_pfn = init_node_data[nid].node_end_pfn;
+-
+- zones_size[ZONE_DMA] = end_pfn - start_pfn;
+- zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] -
+- init_node_data[nid].node_present_pages;
+-
+- dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
+- zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
+-
+- free_area_init_node(nid, NODE_DATA(nid), zones_size,
+- start_pfn, zholes_size);
+- }
+-}
+-
+-static int __init early_numa(char *p)
+-{
+- if (!p)
+- return 0;
+-
+- if (strstr(p, "off"))
+- numa_enabled = 0;
+-
+- if (strstr(p, "debug"))
+- numa_debug = 1;
+-
+- return 0;
+-}
+-early_param("numa", early_numa);
+diff --git a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/slb.c
++++ /dev/null
+@@ -1,158 +0,0 @@
+-/*
+- * PowerPC64 SLB support.
+- *
+- * Copyright (C) 2004 David Gibson <dwg at au.ibm.com>, IBM
+- * Based on earlier code writteh by:
+- * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
+- * Copyright (c) 2001 Dave Engebretsen
+- * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- *
+- * 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/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/paca.h>
+-#include <asm/cputable.h>
+-
+-extern void slb_allocate(unsigned long ea);
+-
+-static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot)
+-{
+- return (ea & ESID_MASK) | SLB_ESID_V | slot;
+-}
+-
+-static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags)
+-{
+- return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
+-}
+-
+-static inline void create_slbe(unsigned long ea, unsigned long flags,
+- unsigned long entry)
+-{
+- asm volatile("slbmte %0,%1" :
+- : "r" (mk_vsid_data(ea, flags)),
+- "r" (mk_esid_data(ea, entry))
+- : "memory" );
+-}
+-
+-static void slb_flush_and_rebolt(void)
+-{
+- /* If you change this make sure you change SLB_NUM_BOLTED
+- * appropriately too. */
+- unsigned long ksp_flags = SLB_VSID_KERNEL;
+- unsigned long ksp_esid_data;
+-
+- WARN_ON(!irqs_disabled());
+-
+- if (cpu_has_feature(CPU_FTR_16M_PAGE))
+- ksp_flags |= SLB_VSID_L;
+-
+- ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
+- if ((ksp_esid_data & ESID_MASK) == KERNELBASE)
+- ksp_esid_data &= ~SLB_ESID_V;
+-
+- /* We need to do this all in asm, so we're sure we don't touch
+- * the stack between the slbia and rebolting it. */
+- asm volatile("isync\n"
+- "slbia\n"
+- /* Slot 1 - first VMALLOC segment */
+- "slbmte %0,%1\n"
+- /* Slot 2 - kernel stack */
+- "slbmte %2,%3\n"
+- "isync"
+- :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)),
+- "r"(mk_esid_data(VMALLOCBASE, 1)),
+- "r"(mk_vsid_data(ksp_esid_data, ksp_flags)),
+- "r"(ksp_esid_data)
+- : "memory");
+-}
+-
+-/* Flush all user entries from the segment table of the current processor. */
+-void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
+-{
+- unsigned long offset = get_paca()->slb_cache_ptr;
+- unsigned long esid_data = 0;
+- unsigned long pc = KSTK_EIP(tsk);
+- unsigned long stack = KSTK_ESP(tsk);
+- unsigned long unmapped_base;
+-
+- if (offset <= SLB_CACHE_ENTRIES) {
+- int i;
+- asm volatile("isync" : : : "memory");
+- for (i = 0; i < offset; i++) {
+- esid_data = ((unsigned long)get_paca()->slb_cache[i]
+- << SID_SHIFT) | SLBIE_C;
+- asm volatile("slbie %0" : : "r" (esid_data));
+- }
+- asm volatile("isync" : : : "memory");
+- } else {
+- slb_flush_and_rebolt();
+- }
+-
+- /* Workaround POWER5 < DD2.1 issue */
+- if (offset == 1 || offset > SLB_CACHE_ENTRIES)
+- asm volatile("slbie %0" : : "r" (esid_data));
+-
+- get_paca()->slb_cache_ptr = 0;
+- get_paca()->context = mm->context;
+-
+- /*
+- * preload some userspace segments into the SLB.
+- */
+- if (test_tsk_thread_flag(tsk, TIF_32BIT))
+- unmapped_base = TASK_UNMAPPED_BASE_USER32;
+- else
+- unmapped_base = TASK_UNMAPPED_BASE_USER64;
+-
+- if (pc >= KERNELBASE)
+- return;
+- slb_allocate(pc);
+-
+- if (GET_ESID(pc) == GET_ESID(stack))
+- return;
+-
+- if (stack >= KERNELBASE)
+- return;
+- slb_allocate(stack);
+-
+- if ((GET_ESID(pc) == GET_ESID(unmapped_base))
+- || (GET_ESID(stack) == GET_ESID(unmapped_base)))
+- return;
+-
+- if (unmapped_base >= KERNELBASE)
+- return;
+- slb_allocate(unmapped_base);
+-}
+-
+-void slb_initialize(void)
+-{
+- /* On iSeries the bolted entries have already been set up by
+- * the hypervisor from the lparMap data in head.S */
+-#ifndef CONFIG_PPC_ISERIES
+- unsigned long flags = SLB_VSID_KERNEL;
+-
+- /* Invalidate the entire SLB (even slot 0) & all the ERATS */
+- if (cpu_has_feature(CPU_FTR_16M_PAGE))
+- flags |= SLB_VSID_L;
+-
+- asm volatile("isync":::"memory");
+- asm volatile("slbmte %0,%0"::"r" (0) : "memory");
+- asm volatile("isync; slbia; isync":::"memory");
+- create_slbe(KERNELBASE, flags, 0);
+- create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1);
+- /* We don't bolt the stack for the time being - we're in boot,
+- * so the stack is in the bolted segment. By the time it goes
+- * elsewhere, we'll call _switch() which will bolt in the new
+- * one. */
+- asm volatile("isync":::"memory");
+-#endif
+-
+- get_paca()->stab_rr = SLB_NUM_BOLTED;
+-}
+diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S
+deleted file mode 100644
+--- a/arch/ppc64/mm/slb_low.S
++++ /dev/null
+@@ -1,151 +0,0 @@
+-/*
+- * arch/ppc64/mm/slb_low.S
+- *
+- * Low-level SLB routines
+- *
+- * Copyright (C) 2004 David Gibson <dwg at au.ibm.com>, IBM
+- *
+- * Based on earlier C version:
+- * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
+- * Copyright (c) 2001 Dave Engebretsen
+- * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/config.h>
+-#include <asm/processor.h>
+-#include <asm/page.h>
+-#include <asm/mmu.h>
+-#include <asm/ppc_asm.h>
+-#include <asm/asm-offsets.h>
+-#include <asm/cputable.h>
+-
+-/* void slb_allocate(unsigned long ea);
+- *
+- * Create an SLB entry for the given EA (user or kernel).
+- * r3 = faulting address, r13 = PACA
+- * r9, r10, r11 are clobbered by this function
+- * No other registers are examined or changed.
+- */
+-_GLOBAL(slb_allocate)
+- /*
+- * First find a slot, round robin. Previously we tried to find
+- * a free slot first but that took too long. Unfortunately we
+- * dont have any LRU information to help us choose a slot.
+- */
+-#ifdef CONFIG_PPC_ISERIES
+- /*
+- * On iSeries, the "bolted" stack segment can be cast out on
+- * shared processor switch so we need to check for a miss on
+- * it and restore it to the right slot.
+- */
+- ld r9,PACAKSAVE(r13)
+- clrrdi r9,r9,28
+- clrrdi r11,r3,28
+- li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */
+- cmpld r9,r11
+- beq 3f
+-#endif /* CONFIG_PPC_ISERIES */
+-
+- ld r10,PACASTABRR(r13)
+- addi r10,r10,1
+- /* use a cpu feature mask if we ever change our slb size */
+- cmpldi r10,SLB_NUM_ENTRIES
+-
+- blt+ 4f
+- li r10,SLB_NUM_BOLTED
+-
+-4:
+- std r10,PACASTABRR(r13)
+-3:
+- /* r3 = faulting address, r10 = entry */
+-
+- srdi r9,r3,60 /* get region */
+- srdi r3,r3,28 /* get esid */
+- cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */
+-
+- rldimi r10,r3,28,0 /* r10= ESID<<28 | entry */
+- oris r10,r10,SLB_ESID_V at h /* r10 |= SLB_ESID_V */
+-
+- /* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */
+-
+- blt cr7,0f /* user or kernel? */
+-
+- /* kernel address: proto-VSID = ESID */
+- /* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
+- * this code will generate the protoVSID 0xfffffffff for the
+- * top segment. That's ok, the scramble below will translate
+- * it to VSID 0, which is reserved as a bad VSID - one which
+- * will never have any pages in it. */
+- li r11,SLB_VSID_KERNEL
+-BEGIN_FTR_SECTION
+- bne cr7,9f
+- li r11,(SLB_VSID_KERNEL|SLB_VSID_L)
+-END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
+- b 9f
+-
+-0: /* user address: proto-VSID = context<<15 | ESID */
+- srdi. r9,r3,USER_ESID_BITS
+- bne- 8f /* invalid ea bits set */
+-
+-#ifdef CONFIG_HUGETLB_PAGE
+-BEGIN_FTR_SECTION
+- lhz r9,PACAHIGHHTLBAREAS(r13)
+- srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT)
+- srd r9,r9,r11
+- lhz r11,PACALOWHTLBAREAS(r13)
+- srd r11,r11,r3
+- or r9,r9,r11
+-END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
+-#endif /* CONFIG_HUGETLB_PAGE */
+-
+- li r11,SLB_VSID_USER
+-
+-#ifdef CONFIG_HUGETLB_PAGE
+-BEGIN_FTR_SECTION
+- rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */
+-END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
+-#endif /* CONFIG_HUGETLB_PAGE */
+-
+- ld r9,PACACONTEXTID(r13)
+- rldimi r3,r9,USER_ESID_BITS,0
+-
+-9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
+- ASM_VSID_SCRAMBLE(r3,r9)
+-
+- rldimi r11,r3,SLB_VSID_SHIFT,16 /* combine VSID and flags */
+-
+- /*
+- * No need for an isync before or after this slbmte. The exception
+- * we enter with and the rfid we exit with are context synchronizing.
+- */
+- slbmte r11,r10
+-
+- bgelr cr7 /* we're done for kernel addresses */
+-
+- /* Update the slb cache */
+- lhz r3,PACASLBCACHEPTR(r13) /* offset = paca->slb_cache_ptr */
+- cmpldi r3,SLB_CACHE_ENTRIES
+- bge 1f
+-
+- /* still room in the slb cache */
+- sldi r11,r3,1 /* r11 = offset * sizeof(u16) */
+- rldicl r10,r10,36,28 /* get low 16 bits of the ESID */
+- add r11,r11,r13 /* r11 = (u16 *)paca + offset */
+- sth r10,PACASLBCACHE(r11) /* paca->slb_cache[offset] = esid */
+- addi r3,r3,1 /* offset++ */
+- b 2f
+-1: /* offset >= SLB_CACHE_ENTRIES */
+- li r3,SLB_CACHE_ENTRIES+1
+-2:
+- sth r3,PACASLBCACHEPTR(r13) /* paca->slb_cache_ptr = offset */
+- blr
+-
+-8: /* invalid EA */
+- li r3,0 /* BAD_VSID */
+- li r11,SLB_VSID_USER /* flags don't much matter */
+- b 9b
+diff --git a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/stab.c
++++ /dev/null
+@@ -1,279 +0,0 @@
+-/*
+- * PowerPC64 Segment Translation Support.
+- *
+- * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
+- * Copyright (c) 2001 Dave Engebretsen
+- *
+- * Copyright (C) 2002 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/paca.h>
+-#include <asm/cputable.h>
+-#include <asm/lmb.h>
+-#include <asm/abs_addr.h>
+-
+-struct stab_entry {
+- unsigned long esid_data;
+- unsigned long vsid_data;
+-};
+-
+-/* Both the segment table and SLB code uses the following cache */
+-#define NR_STAB_CACHE_ENTRIES 8
+-DEFINE_PER_CPU(long, stab_cache_ptr);
+-DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]);
+-
+-/*
+- * Create a segment table entry for the given esid/vsid pair.
+- */
+-static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
+-{
+- unsigned long esid_data, vsid_data;
+- unsigned long entry, group, old_esid, castout_entry, i;
+- unsigned int global_entry;
+- struct stab_entry *ste, *castout_ste;
+- unsigned long kernel_segment = (esid << SID_SHIFT) >= KERNELBASE;
+-
+- vsid_data = vsid << STE_VSID_SHIFT;
+- esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V;
+- if (! kernel_segment)
+- esid_data |= STE_ESID_KS;
+-
+- /* Search the primary group first. */
+- global_entry = (esid & 0x1f) << 3;
+- ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
+-
+- /* Find an empty entry, if one exists. */
+- for (group = 0; group < 2; group++) {
+- for (entry = 0; entry < 8; entry++, ste++) {
+- if (!(ste->esid_data & STE_ESID_V)) {
+- ste->vsid_data = vsid_data;
+- asm volatile("eieio":::"memory");
+- ste->esid_data = esid_data;
+- return (global_entry | entry);
+- }
+- }
+- /* Now search the secondary group. */
+- global_entry = ((~esid) & 0x1f) << 3;
+- ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
+- }
+-
+- /*
+- * Could not find empty entry, pick one with a round robin selection.
+- * Search all entries in the two groups.
+- */
+- castout_entry = get_paca()->stab_rr;
+- for (i = 0; i < 16; i++) {
+- if (castout_entry < 8) {
+- global_entry = (esid & 0x1f) << 3;
+- ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
+- castout_ste = ste + castout_entry;
+- } else {
+- global_entry = ((~esid) & 0x1f) << 3;
+- ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
+- castout_ste = ste + (castout_entry - 8);
+- }
+-
+- /* Dont cast out the first kernel segment */
+- if ((castout_ste->esid_data & ESID_MASK) != KERNELBASE)
+- break;
+-
+- castout_entry = (castout_entry + 1) & 0xf;
+- }
+-
+- get_paca()->stab_rr = (castout_entry + 1) & 0xf;
+-
+- /* Modify the old entry to the new value. */
+-
+- /* Force previous translations to complete. DRENG */
+- asm volatile("isync" : : : "memory");
+-
+- old_esid = castout_ste->esid_data >> SID_SHIFT;
+- castout_ste->esid_data = 0; /* Invalidate old entry */
+-
+- asm volatile("sync" : : : "memory"); /* Order update */
+-
+- castout_ste->vsid_data = vsid_data;
+- asm volatile("eieio" : : : "memory"); /* Order update */
+- castout_ste->esid_data = esid_data;
+-
+- asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT));
+- /* Ensure completion of slbie */
+- asm volatile("sync" : : : "memory");
+-
+- return (global_entry | (castout_entry & 0x7));
+-}
+-
+-/*
+- * Allocate a segment table entry for the given ea and mm
+- */
+-static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
+-{
+- unsigned long vsid;
+- unsigned char stab_entry;
+- unsigned long offset;
+-
+- /* Kernel or user address? */
+- if (ea >= KERNELBASE) {
+- vsid = get_kernel_vsid(ea);
+- } else {
+- if ((ea >= TASK_SIZE_USER64) || (! mm))
+- return 1;
+-
+- vsid = get_vsid(mm->context.id, ea);
+- }
+-
+- stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid);
+-
+- if (ea < KERNELBASE) {
+- offset = __get_cpu_var(stab_cache_ptr);
+- if (offset < NR_STAB_CACHE_ENTRIES)
+- __get_cpu_var(stab_cache[offset++]) = stab_entry;
+- else
+- offset = NR_STAB_CACHE_ENTRIES+1;
+- __get_cpu_var(stab_cache_ptr) = offset;
+-
+- /* Order update */
+- asm volatile("sync":::"memory");
+- }
+-
+- return 0;
+-}
+-
+-int ste_allocate(unsigned long ea)
+-{
+- return __ste_allocate(ea, current->mm);
+-}
+-
+-/*
+- * Do the segment table work for a context switch: flush all user
+- * entries from the table, then preload some probably useful entries
+- * for the new task
+- */
+-void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
+-{
+- struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr;
+- struct stab_entry *ste;
+- unsigned long offset = __get_cpu_var(stab_cache_ptr);
+- unsigned long pc = KSTK_EIP(tsk);
+- unsigned long stack = KSTK_ESP(tsk);
+- unsigned long unmapped_base;
+-
+- /* Force previous translations to complete. DRENG */
+- asm volatile("isync" : : : "memory");
+-
+- if (offset <= NR_STAB_CACHE_ENTRIES) {
+- int i;
+-
+- for (i = 0; i < offset; i++) {
+- ste = stab + __get_cpu_var(stab_cache[i]);
+- ste->esid_data = 0; /* invalidate entry */
+- }
+- } else {
+- unsigned long entry;
+-
+- /* Invalidate all entries. */
+- ste = stab;
+-
+- /* Never flush the first entry. */
+- ste += 1;
+- for (entry = 1;
+- entry < (PAGE_SIZE / sizeof(struct stab_entry));
+- entry++, ste++) {
+- unsigned long ea;
+- ea = ste->esid_data & ESID_MASK;
+- if (ea < KERNELBASE) {
+- ste->esid_data = 0;
+- }
+- }
+- }
+-
+- asm volatile("sync; slbia; sync":::"memory");
+-
+- __get_cpu_var(stab_cache_ptr) = 0;
+-
+- /* Now preload some entries for the new task */
+- if (test_tsk_thread_flag(tsk, TIF_32BIT))
+- unmapped_base = TASK_UNMAPPED_BASE_USER32;
+- else
+- unmapped_base = TASK_UNMAPPED_BASE_USER64;
+-
+- __ste_allocate(pc, mm);
+-
+- if (GET_ESID(pc) == GET_ESID(stack))
+- return;
+-
+- __ste_allocate(stack, mm);
+-
+- if ((GET_ESID(pc) == GET_ESID(unmapped_base))
+- || (GET_ESID(stack) == GET_ESID(unmapped_base)))
+- return;
+-
+- __ste_allocate(unmapped_base, mm);
+-
+- /* Order update */
+- asm volatile("sync" : : : "memory");
+-}
+-
+-extern void slb_initialize(void);
+-
+-/*
+- * Allocate segment tables for secondary CPUs. These must all go in
+- * the first (bolted) segment, so that do_stab_bolted won't get a
+- * recursive segment miss on the segment table itself.
+- */
+-void stabs_alloc(void)
+-{
+- int cpu;
+-
+- if (cpu_has_feature(CPU_FTR_SLB))
+- return;
+-
+- for_each_cpu(cpu) {
+- unsigned long newstab;
+-
+- if (cpu == 0)
+- continue; /* stab for CPU 0 is statically allocated */
+-
+- newstab = lmb_alloc_base(PAGE_SIZE, PAGE_SIZE, 1<<SID_SHIFT);
+- if (! newstab)
+- panic("Unable to allocate segment table for CPU %d.\n",
+- cpu);
+-
+- newstab += KERNELBASE;
+-
+- memset((void *)newstab, 0, PAGE_SIZE);
+-
+- paca[cpu].stab_addr = newstab;
+- paca[cpu].stab_real = virt_to_abs(newstab);
+- printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx virtual, 0x%lx absolute\n", cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
+- }
+-}
+-
+-/*
+- * Build an entry for the base kernel segment and put it into
+- * the segment table or SLB. All other segment table or SLB
+- * entries are faulted in.
+- */
+-void stab_initialize(unsigned long stab)
+-{
+- unsigned long vsid = get_kernel_vsid(KERNELBASE);
+-
+- if (cpu_has_feature(CPU_FTR_SLB)) {
+- slb_initialize();
+- } else {
+- asm volatile("isync; slbia; isync":::"memory");
+- make_ste(stab, GET_ESID(KERNELBASE), vsid);
+-
+- /* Order update */
+- asm volatile("sync":::"memory");
+- }
+-}
+diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
+deleted file mode 100644
+--- a/arch/ppc64/mm/tlb.c
++++ /dev/null
+@@ -1,197 +0,0 @@
+-/*
+- * This file contains the routines for flushing entries from the
+- * TLB and MMU hash table.
+- *
+- * Derived from arch/ppc64/mm/init.c:
+- * Copyright (C) 1995-1996 Gary Thomas (gdt at linuxppc.org)
+- *
+- * Modifications by Paul Mackerras (PowerMac) (paulus at cs.anu.edu.au)
+- * and Cort Dougan (PReP) (cort at cs.nmt.edu)
+- * Copyright (C) 1996 Paul Mackerras
+- * Amiga/APUS changes by Jesper Skov (jskov at cygnus.co.uk).
+- *
+- * Derived from "arch/i386/mm/init.c"
+- * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+- *
+- * Dave Engebretsen <engebret at us.ibm.com>
+- * Rework for PPC64 port.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/percpu.h>
+-#include <linux/hardirq.h>
+-#include <asm/pgalloc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/tlb.h>
+-#include <linux/highmem.h>
+-
+-DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
+-
+-/* This is declared as we are using the more or less generic
+- * include/asm-ppc64/tlb.h file -- tgall
+- */
+-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+-DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
+-unsigned long pte_freelist_forced_free;
+-
+-struct pte_freelist_batch
+-{
+- struct rcu_head rcu;
+- unsigned int index;
+- pgtable_free_t tables[0];
+-};
+-
+-DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
+-unsigned long pte_freelist_forced_free;
+-
+-#define PTE_FREELIST_SIZE \
+- ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
+- / sizeof(pgtable_free_t))
+-
+-#ifdef CONFIG_SMP
+-static void pte_free_smp_sync(void *arg)
+-{
+- /* Do nothing, just ensure we sync with all CPUs */
+-}
+-#endif
+-
+-/* This is only called when we are critically out of memory
+- * (and fail to get a page in pte_free_tlb).
+- */
+-static void pgtable_free_now(pgtable_free_t pgf)
+-{
+- pte_freelist_forced_free++;
+-
+- smp_call_function(pte_free_smp_sync, NULL, 0, 1);
+-
+- pgtable_free(pgf);
+-}
+-
+-static void pte_free_rcu_callback(struct rcu_head *head)
+-{
+- struct pte_freelist_batch *batch =
+- container_of(head, struct pte_freelist_batch, rcu);
+- unsigned int i;
+-
+- for (i = 0; i < batch->index; i++)
+- pgtable_free(batch->tables[i]);
+-
+- free_page((unsigned long)batch);
+-}
+-
+-static void pte_free_submit(struct pte_freelist_batch *batch)
+-{
+- INIT_RCU_HEAD(&batch->rcu);
+- call_rcu(&batch->rcu, pte_free_rcu_callback);
+-}
+-
+-void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
+-{
+- /* This is safe as we are holding page_table_lock */
+- cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
+- struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
+-
+- if (atomic_read(&tlb->mm->mm_users) < 2 ||
+- cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
+- pgtable_free(pgf);
+- return;
+- }
+-
+- if (*batchp == NULL) {
+- *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
+- if (*batchp == NULL) {
+- pgtable_free_now(pgf);
+- return;
+- }
+- (*batchp)->index = 0;
+- }
+- (*batchp)->tables[(*batchp)->index++] = pgf;
+- if ((*batchp)->index == PTE_FREELIST_SIZE) {
+- pte_free_submit(*batchp);
+- *batchp = NULL;
+- }
+-}
+-
+-/*
+- * Update the MMU hash table to correspond with a change to
+- * a Linux PTE. If wrprot is true, it is permissible to
+- * change the existing HPTE to read-only rather than removing it
+- * (if we remove it we should clear the _PTE_HPTEFLAGS bits).
+- */
+-void hpte_update(struct mm_struct *mm, unsigned long addr,
+- unsigned long pte, int wrprot)
+-{
+- int i;
+- unsigned long context = 0;
+- struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+-
+- if (REGION_ID(addr) == USER_REGION_ID)
+- context = mm->context.id;
+- i = batch->index;
+-
+- /*
+- * This can happen when we are in the middle of a TLB batch and
+- * we encounter memory pressure (eg copy_page_range when it tries
+- * to allocate a new pte). If we have to reclaim memory and end
+- * up scanning and resetting referenced bits then our batch context
+- * will change mid stream.
+- */
+- if (i != 0 && (context != batch->context ||
+- batch->large != pte_huge(pte))) {
+- flush_tlb_pending();
+- i = 0;
+- }
+-
+- if (i == 0) {
+- batch->context = context;
+- batch->mm = mm;
+- batch->large = pte_huge(pte);
+- }
+- batch->pte[i] = __pte(pte);
+- batch->addr[i] = addr;
+- batch->index = ++i;
+- if (i >= PPC64_TLB_BATCH_NR)
+- flush_tlb_pending();
+-}
+-
+-void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
+-{
+- int i;
+- int cpu;
+- cpumask_t tmp;
+- int local = 0;
+-
+- BUG_ON(in_interrupt());
+-
+- cpu = get_cpu();
+- i = batch->index;
+- tmp = cpumask_of_cpu(cpu);
+- if (cpus_equal(batch->mm->cpu_vm_mask, tmp))
+- local = 1;
+-
+- if (i == 1)
+- flush_hash_page(batch->context, batch->addr[0], batch->pte[0],
+- local);
+- else
+- flush_hash_range(batch->context, i, local);
+- batch->index = 0;
+- put_cpu();
+-}
+-
+-void pte_free_finish(void)
+-{
+- /* This is safe as we are holding page_table_lock */
+- struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
+-
+- if (*batchp == NULL)
+- return;
+- pte_free_submit(*batchp);
+- *batchp = NULL;
+-}
+diff --git a/arch/ppc64/oprofile/Kconfig b/arch/ppc64/oprofile/Kconfig
+deleted file mode 100644
+--- a/arch/ppc64/oprofile/Kconfig
++++ /dev/null
+@@ -1,23 +0,0 @@
+-
+-menu "Profiling support"
+- depends on EXPERIMENTAL
+-
+-config PROFILING
+- bool "Profiling support (EXPERIMENTAL)"
+- help
+- Say Y here to enable the extended profiling support mechanisms used
+- by profilers such as OProfile.
+-
+-
+-config OPROFILE
+- tristate "OProfile system profiling (EXPERIMENTAL)"
+- depends on PROFILING
+- help
+- OProfile is a profiling system capable of profiling the
+- whole system, include the kernel, kernel modules, libraries,
+- and applications.
+-
+- If unsure, say N.
+-
+-endmenu
+-
+diff --git a/arch/ppc64/oprofile/Makefile b/arch/ppc64/oprofile/Makefile
+deleted file mode 100644
+--- a/arch/ppc64/oprofile/Makefile
++++ /dev/null
+@@ -1,9 +0,0 @@
+-obj-$(CONFIG_OPROFILE) += oprofile.o
+-
+-DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
+- oprof.o cpu_buffer.o buffer_sync.o \
+- event_buffer.o oprofile_files.o \
+- oprofilefs.o oprofile_stats.o \
+- timer_int.o )
+-
+-oprofile-y := $(DRIVER_OBJS) common.o op_model_rs64.o op_model_power4.o
+diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c
+deleted file mode 100644
+--- a/arch/ppc64/oprofile/common.c
++++ /dev/null
+@@ -1,145 +0,0 @@
+-/*
+- * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * Based on alpha version.
+- *
+- * 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/oprofile.h>
+-#include <linux/init.h>
+-#include <linux/smp.h>
+-#include <linux/errno.h>
+-#include <asm/ptrace.h>
+-#include <asm/system.h>
+-#include <asm/pmc.h>
+-#include <asm/cputable.h>
+-#include <asm/oprofile_impl.h>
+-
+-static struct op_ppc64_model *model;
+-
+-static struct op_counter_config ctr[OP_MAX_COUNTER];
+-static struct op_system_config sys;
+-
+-static void op_handle_interrupt(struct pt_regs *regs)
+-{
+- model->handle_interrupt(regs, ctr);
+-}
+-
+-static int op_ppc64_setup(void)
+-{
+- int err;
+-
+- /* Grab the hardware */
+- err = reserve_pmc_hardware(op_handle_interrupt);
+- if (err)
+- return err;
+-
+- /* Pre-compute the values to stuff in the hardware registers. */
+- model->reg_setup(ctr, &sys, model->num_counters);
+-
+- /* Configure the registers on all cpus. */
+- on_each_cpu(model->cpu_setup, NULL, 0, 1);
+-
+- return 0;
+-}
+-
+-static void op_ppc64_shutdown(void)
+-{
+- release_pmc_hardware();
+-}
+-
+-static void op_ppc64_cpu_start(void *dummy)
+-{
+- model->start(ctr);
+-}
+-
+-static int op_ppc64_start(void)
+-{
+- on_each_cpu(op_ppc64_cpu_start, NULL, 0, 1);
+- return 0;
+-}
+-
+-static inline void op_ppc64_cpu_stop(void *dummy)
+-{
+- model->stop();
+-}
+-
+-static void op_ppc64_stop(void)
+-{
+- on_each_cpu(op_ppc64_cpu_stop, NULL, 0, 1);
+-}
+-
+-static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
+-{
+- int i;
+-
+- /*
+- * There is one mmcr0, mmcr1 and mmcra for setting the events for
+- * all of the counters.
+- */
+- oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
+- oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
+- oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
+-
+- for (i = 0; i < model->num_counters; ++i) {
+- struct dentry *dir;
+- char buf[3];
+-
+- snprintf(buf, sizeof buf, "%d", i);
+- dir = oprofilefs_mkdir(sb, root, buf);
+-
+- 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);
+- /*
+- * We dont support per counter user/kernel selection, but
+- * we leave the entries because userspace expects them
+- */
+- oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
+- oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
+- oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
+- }
+-
+- oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
+- oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
+- oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
+- &sys.backtrace_spinlocks);
+-
+- /* Default to tracing both kernel and user */
+- sys.enable_kernel = 1;
+- sys.enable_user = 1;
+-
+- /* Turn on backtracing through spinlocks by default */
+- sys.backtrace_spinlocks = 1;
+-
+- return 0;
+-}
+-
+-int __init oprofile_arch_init(struct oprofile_operations *ops)
+-{
+- if (!cur_cpu_spec->oprofile_model || !cur_cpu_spec->oprofile_cpu_type)
+- return -ENODEV;
+-
+- model = cur_cpu_spec->oprofile_model;
+- model->num_counters = cur_cpu_spec->num_pmcs;
+-
+- ops->cpu_type = cur_cpu_spec->oprofile_cpu_type;
+- ops->create_files = op_ppc64_create_files;
+- ops->setup = op_ppc64_setup;
+- ops->shutdown = op_ppc64_shutdown;
+- ops->start = op_ppc64_start;
+- ops->stop = op_ppc64_stop;
+-
+- printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
+- ops->cpu_type);
+-
+- return 0;
+-}
+-
+-void oprofile_arch_exit(void)
+-{
+-}
+diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c
+deleted file mode 100644
+--- a/arch/ppc64/oprofile/op_model_power4.c
++++ /dev/null
+@@ -1,309 +0,0 @@
+-/*
+- * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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/oprofile.h>
+-#include <linux/init.h>
+-#include <linux/smp.h>
+-#include <asm/ptrace.h>
+-#include <asm/system.h>
+-#include <asm/processor.h>
+-#include <asm/cputable.h>
+-#include <asm/systemcfg.h>
+-#include <asm/rtas.h>
+-#include <asm/oprofile_impl.h>
+-
+-#define dbg(args...)
+-
+-static unsigned long reset_value[OP_MAX_COUNTER];
+-
+-static int oprofile_running;
+-static int mmcra_has_sihv;
+-
+-/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
+-static u32 mmcr0_val;
+-static u64 mmcr1_val;
+-static u32 mmcra_val;
+-
+-/*
+- * Since we do not have an NMI, backtracing through spinlocks is
+- * only a best guess. In light of this, allow it to be disabled at
+- * runtime.
+- */
+-static int backtrace_spinlocks;
+-
+-static void power4_reg_setup(struct op_counter_config *ctr,
+- struct op_system_config *sys,
+- int num_ctrs)
+-{
+- int i;
+-
+- /*
+- * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above.
+- * However we disable it on all POWER4 until we verify it works
+- * (I was seeing some strange behaviour last time I tried).
+- *
+- * It has been verified to work on POWER5 so we enable it there.
+- */
+- if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
+- mmcra_has_sihv = 1;
+-
+- /*
+- * The performance counter event settings are given in the mmcr0,
+- * mmcr1 and mmcra values passed from the user in the
+- * op_system_config structure (sys variable).
+- */
+- mmcr0_val = sys->mmcr0;
+- mmcr1_val = sys->mmcr1;
+- mmcra_val = sys->mmcra;
+-
+- backtrace_spinlocks = sys->backtrace_spinlocks;
+-
+- for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
+- reset_value[i] = 0x80000000UL - ctr[i].count;
+-
+- /* setup user and kernel profiling */
+- if (sys->enable_kernel)
+- mmcr0_val &= ~MMCR0_KERNEL_DISABLE;
+- else
+- mmcr0_val |= MMCR0_KERNEL_DISABLE;
+-
+- if (sys->enable_user)
+- mmcr0_val &= ~MMCR0_PROBLEM_DISABLE;
+- else
+- mmcr0_val |= MMCR0_PROBLEM_DISABLE;
+-}
+-
+-extern void ppc64_enable_pmcs(void);
+-
+-static void power4_cpu_setup(void *unused)
+-{
+- unsigned int mmcr0 = mmcr0_val;
+- unsigned long mmcra = mmcra_val;
+-
+- ppc64_enable_pmcs();
+-
+- /* set the freeze bit */
+- mmcr0 |= MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
+- mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- mtspr(SPRN_MMCR1, mmcr1_val);
+-
+- mmcra |= MMCRA_SAMPLE_ENABLE;
+- mtspr(SPRN_MMCRA, mmcra);
+-
+- dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),
+- mfspr(SPRN_MMCR0));
+- dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(),
+- mfspr(SPRN_MMCR1));
+- dbg("setup on cpu %d, mmcra %lx\n", smp_processor_id(),
+- mfspr(SPRN_MMCRA));
+-}
+-
+-static void power4_start(struct op_counter_config *ctr)
+-{
+- int i;
+- unsigned int mmcr0;
+-
+- /* set the PMM bit (see comment below) */
+- mtmsrd(mfmsr() | MSR_PMM);
+-
+- for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
+- if (ctr[i].enabled) {
+- ctr_write(i, reset_value[i]);
+- } else {
+- ctr_write(i, 0);
+- }
+- }
+-
+- mmcr0 = mfspr(SPRN_MMCR0);
+-
+- /*
+- * We must clear the PMAO bit on some (GQ) chips. Just do it
+- * all the time
+- */
+- mmcr0 &= ~MMCR0_PMAO;
+-
+- /*
+- * now clear the freeze bit, counting will not start until we
+- * rfid from this excetion, because only at that point will
+- * the PMM bit be cleared
+- */
+- mmcr0 &= ~MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- oprofile_running = 1;
+-
+- dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
+-}
+-
+-static void power4_stop(void)
+-{
+- unsigned int mmcr0;
+-
+- /* freeze counters */
+- mmcr0 = mfspr(SPRN_MMCR0);
+- mmcr0 |= MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- oprofile_running = 0;
+-
+- dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
+-
+- mb();
+-}
+-
+-/* Fake functions used by canonicalize_pc */
+-static void __attribute_used__ hypervisor_bucket(void)
+-{
+-}
+-
+-static void __attribute_used__ rtas_bucket(void)
+-{
+-}
+-
+-static void __attribute_used__ kernel_unknown_bucket(void)
+-{
+-}
+-
+-static unsigned long check_spinlock_pc(struct pt_regs *regs,
+- unsigned long profile_pc)
+-{
+- unsigned long pc = instruction_pointer(regs);
+-
+- /*
+- * If both the SIAR (sampled instruction) and the perfmon exception
+- * occurred in a spinlock region then we account the sample to the
+- * calling function. This isnt 100% correct, we really need soft
+- * IRQ disable so we always get the perfmon exception at the
+- * point at which the SIAR is set.
+- */
+- if (backtrace_spinlocks && in_lock_functions(pc) &&
+- in_lock_functions(profile_pc))
+- return regs->link;
+- else
+- return profile_pc;
+-}
+-
+-/*
+- * On GQ and newer the MMCRA stores the HV and PR bits at the time
+- * the SIAR was sampled. We use that to work out if the SIAR was sampled in
+- * the hypervisor, our exception vectors or RTAS.
+- */
+-static unsigned long get_pc(struct pt_regs *regs)
+-{
+- unsigned long pc = mfspr(SPRN_SIAR);
+- unsigned long mmcra;
+-
+- /* Cant do much about it */
+- if (!mmcra_has_sihv)
+- return check_spinlock_pc(regs, pc);
+-
+- mmcra = mfspr(SPRN_MMCRA);
+-
+- /* Were we in the hypervisor? */
+- if ((systemcfg->platform == PLATFORM_PSERIES_LPAR) &&
+- (mmcra & MMCRA_SIHV))
+- /* function descriptor madness */
+- return *((unsigned long *)hypervisor_bucket);
+-
+- /* We were in userspace, nothing to do */
+- if (mmcra & MMCRA_SIPR)
+- return pc;
+-
+-#ifdef CONFIG_PPC_RTAS
+- /* Were we in RTAS? */
+- if (pc >= rtas.base && pc < (rtas.base + rtas.size))
+- /* function descriptor madness */
+- return *((unsigned long *)rtas_bucket);
+-#endif
+-
+- /* Were we in our exception vectors or SLB real mode miss handler? */
+- if (pc < 0x1000000UL)
+- return (unsigned long)__va(pc);
+-
+- /* Not sure where we were */
+- if (pc < KERNELBASE)
+- /* function descriptor madness */
+- return *((unsigned long *)kernel_unknown_bucket);
+-
+- return check_spinlock_pc(regs, pc);
+-}
+-
+-static int get_kernel(unsigned long pc)
+-{
+- int is_kernel;
+-
+- if (!mmcra_has_sihv) {
+- is_kernel = (pc >= KERNELBASE);
+- } else {
+- unsigned long mmcra = mfspr(SPRN_MMCRA);
+- is_kernel = ((mmcra & MMCRA_SIPR) == 0);
+- }
+-
+- return is_kernel;
+-}
+-
+-static void power4_handle_interrupt(struct pt_regs *regs,
+- struct op_counter_config *ctr)
+-{
+- unsigned long pc;
+- int is_kernel;
+- int val;
+- int i;
+- unsigned int mmcr0;
+-
+- pc = get_pc(regs);
+- is_kernel = get_kernel(pc);
+-
+- /* set the PMM bit (see comment below) */
+- mtmsrd(mfmsr() | MSR_PMM);
+-
+- for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
+- val = ctr_read(i);
+- if (val < 0) {
+- if (oprofile_running && ctr[i].enabled) {
+- oprofile_add_pc(pc, is_kernel, i);
+- ctr_write(i, reset_value[i]);
+- } else {
+- ctr_write(i, 0);
+- }
+- }
+- }
+-
+- mmcr0 = mfspr(SPRN_MMCR0);
+-
+- /* reset the perfmon trigger */
+- mmcr0 |= MMCR0_PMXE;
+-
+- /*
+- * We must clear the PMAO bit on some (GQ) chips. Just do it
+- * all the time
+- */
+- mmcr0 &= ~MMCR0_PMAO;
+-
+- /*
+- * now clear the freeze bit, counting will not start until we
+- * rfid from this exception, because only at that point will
+- * the PMM bit be cleared
+- */
+- mmcr0 &= ~MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-}
+-
+-struct op_ppc64_model op_model_power4 = {
+- .reg_setup = power4_reg_setup,
+- .cpu_setup = power4_cpu_setup,
+- .start = power4_start,
+- .stop = power4_stop,
+- .handle_interrupt = power4_handle_interrupt,
+-};
+diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c
+deleted file mode 100644
+--- a/arch/ppc64/oprofile/op_model_rs64.c
++++ /dev/null
+@@ -1,218 +0,0 @@
+-/*
+- * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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/oprofile.h>
+-#include <linux/init.h>
+-#include <linux/smp.h>
+-#include <asm/ptrace.h>
+-#include <asm/system.h>
+-#include <asm/processor.h>
+-#include <asm/cputable.h>
+-#include <asm/oprofile_impl.h>
+-
+-#define dbg(args...)
+-
+-static void ctrl_write(unsigned int i, unsigned int val)
+-{
+- unsigned int tmp = 0;
+- unsigned long shift = 0, mask = 0;
+-
+- dbg("ctrl_write %d %x\n", i, val);
+-
+- switch(i) {
+- case 0:
+- tmp = mfspr(SPRN_MMCR0);
+- shift = 6;
+- mask = 0x7F;
+- break;
+- case 1:
+- tmp = mfspr(SPRN_MMCR0);
+- shift = 0;
+- mask = 0x3F;
+- break;
+- case 2:
+- tmp = mfspr(SPRN_MMCR1);
+- shift = 31 - 4;
+- mask = 0x1F;
+- break;
+- case 3:
+- tmp = mfspr(SPRN_MMCR1);
+- shift = 31 - 9;
+- mask = 0x1F;
+- break;
+- case 4:
+- tmp = mfspr(SPRN_MMCR1);
+- shift = 31 - 14;
+- mask = 0x1F;
+- break;
+- case 5:
+- tmp = mfspr(SPRN_MMCR1);
+- shift = 31 - 19;
+- mask = 0x1F;
+- break;
+- case 6:
+- tmp = mfspr(SPRN_MMCR1);
+- shift = 31 - 24;
+- mask = 0x1F;
+- break;
+- case 7:
+- tmp = mfspr(SPRN_MMCR1);
+- shift = 31 - 28;
+- mask = 0xF;
+- break;
+- }
+-
+- tmp = tmp & ~(mask << shift);
+- tmp |= val << shift;
+-
+- switch(i) {
+- case 0:
+- case 1:
+- mtspr(SPRN_MMCR0, tmp);
+- break;
+- default:
+- mtspr(SPRN_MMCR1, tmp);
+- }
+-
+- dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0),
+- mfspr(SPRN_MMCR1));
+-}
+-
+-static unsigned long reset_value[OP_MAX_COUNTER];
+-
+-static int num_counters;
+-
+-static void rs64_reg_setup(struct op_counter_config *ctr,
+- struct op_system_config *sys,
+- int num_ctrs)
+-{
+- int i;
+-
+- num_counters = num_ctrs;
+-
+- for (i = 0; i < num_counters; ++i)
+- reset_value[i] = 0x80000000UL - ctr[i].count;
+-
+- /* XXX setup user and kernel profiling */
+-}
+-
+-static void rs64_cpu_setup(void *unused)
+-{
+- unsigned int mmcr0;
+-
+- /* reset MMCR0 and set the freeze bit */
+- mmcr0 = MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- /* reset MMCR1, MMCRA */
+- mtspr(SPRN_MMCR1, 0);
+-
+- if (cpu_has_feature(CPU_FTR_MMCRA))
+- mtspr(SPRN_MMCRA, 0);
+-
+- mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
+- /* Only applies to POWER3, but should be safe on RS64 */
+- mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),
+- mfspr(SPRN_MMCR0));
+- dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(),
+- mfspr(SPRN_MMCR1));
+-}
+-
+-static void rs64_start(struct op_counter_config *ctr)
+-{
+- int i;
+- unsigned int mmcr0;
+-
+- /* set the PMM bit (see comment below) */
+- mtmsrd(mfmsr() | MSR_PMM);
+-
+- for (i = 0; i < num_counters; ++i) {
+- if (ctr[i].enabled) {
+- ctr_write(i, reset_value[i]);
+- ctrl_write(i, ctr[i].event);
+- } else {
+- ctr_write(i, 0);
+- }
+- }
+-
+- mmcr0 = mfspr(SPRN_MMCR0);
+-
+- /*
+- * now clear the freeze bit, counting will not start until we
+- * rfid from this excetion, because only at that point will
+- * the PMM bit be cleared
+- */
+- mmcr0 &= ~MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
+-}
+-
+-static void rs64_stop(void)
+-{
+- unsigned int mmcr0;
+-
+- /* freeze counters */
+- mmcr0 = mfspr(SPRN_MMCR0);
+- mmcr0 |= MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-
+- dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
+-
+- mb();
+-}
+-
+-static void rs64_handle_interrupt(struct pt_regs *regs,
+- struct op_counter_config *ctr)
+-{
+- unsigned int mmcr0;
+- int val;
+- int i;
+- unsigned long pc = mfspr(SPRN_SIAR);
+- int is_kernel = (pc >= KERNELBASE);
+-
+- /* set the PMM bit (see comment below) */
+- mtmsrd(mfmsr() | MSR_PMM);
+-
+- for (i = 0; i < num_counters; ++i) {
+- val = ctr_read(i);
+- if (val < 0) {
+- if (ctr[i].enabled) {
+- oprofile_add_pc(pc, is_kernel, i);
+- ctr_write(i, reset_value[i]);
+- } else {
+- ctr_write(i, 0);
+- }
+- }
+- }
+-
+- mmcr0 = mfspr(SPRN_MMCR0);
+-
+- /* reset the perfmon trigger */
+- mmcr0 |= MMCR0_PMXE;
+-
+- /*
+- * now clear the freeze bit, counting will not start until we
+- * rfid from this exception, because only at that point will
+- * the PMM bit be cleared
+- */
+- mmcr0 &= ~MMCR0_FC;
+- mtspr(SPRN_MMCR0, mmcr0);
+-}
+-
+-struct op_ppc64_model op_model_rs64 = {
+- .reg_setup = rs64_reg_setup,
+- .cpu_setup = rs64_cpu_setup,
+- .start = rs64_start,
+- .stop = rs64_stop,
+- .handle_interrupt = rs64_handle_interrupt,
+-};
+diff --git a/arch/ppc64/xmon/Makefile b/arch/ppc64/xmon/Makefile
+deleted file mode 100644
+--- a/arch/ppc64/xmon/Makefile
++++ /dev/null
+@@ -1,5 +0,0 @@
+-# Makefile for xmon
+-
+-EXTRA_CFLAGS += -mno-minimal-toc
+-
+-obj-y := start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+diff --git a/arch/ppc64/xmon/ansidecl.h b/arch/ppc64/xmon/ansidecl.h
+deleted file mode 100644
+--- a/arch/ppc64/xmon/ansidecl.h
++++ /dev/null
+@@ -1,141 +0,0 @@
+-/* ANSI and traditional C compatibility macros
+- Copyright 1991, 1992 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+-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. */
+-
+-/* ANSI and traditional C compatibility macros
+-
+- ANSI C is assumed if __STDC__ is #defined.
+-
+- Macro ANSI C definition Traditional C definition
+- ----- ---- - ---------- ----------- - ----------
+- PTR `void *' `char *'
+- LONG_DOUBLE `long double' `double'
+- VOLATILE `volatile' `'
+- SIGNED `signed' `'
+- PTRCONST `void *const' `char *'
+- ANSI_PROTOTYPES 1 not defined
+-
+- CONST is also defined, but is obsolete. Just use const.
+-
+- DEFUN (name, arglist, args)
+-
+- Defines function NAME.
+-
+- ARGLIST lists the arguments, separated by commas and enclosed in
+- parentheses. ARGLIST becomes the argument list in traditional C.
+-
+- ARGS list the arguments with their types. It becomes a prototype in
+- ANSI C, and the type declarations in traditional C. Arguments should
+- be separated with `AND'. For functions with a variable number of
+- arguments, the last thing listed should be `DOTS'.
+-
+- DEFUN_VOID (name)
+-
+- Defines a function NAME, which takes no arguments.
+-
+- obsolete -- EXFUN (name, (prototype)) -- obsolete.
+-
+- Replaced by PARAMS. Do not use; will disappear someday soon.
+- Was used in external function declarations.
+- In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+- parentheses). In traditional C it is `NAME()'.
+- For a function that takes no arguments, PROTOTYPE should be `(void)'.
+-
+- PARAMS ((args))
+-
+- We could use the EXFUN macro to handle prototype declarations, but
+- the name is misleading and the result is ugly. So we just define a
+- simple macro to handle the parameter lists, as in:
+-
+- static int foo PARAMS ((int, char));
+-
+- This produces: `static int foo();' or `static int foo (int, char);'
+-
+- EXFUN would have done it like this:
+-
+- static int EXFUN (foo, (int, char));
+-
+- but the function is not external...and it's hard to visually parse
+- the function name out of the mess. EXFUN should be considered
+- obsolete; new code should be written to use PARAMS.
+-
+- For example:
+- extern int printf PARAMS ((CONST char *format DOTS));
+- int DEFUN(fprintf, (stream, format),
+- FILE *stream AND CONST char *format DOTS) { ... }
+- void DEFUN_VOID(abort) { ... }
+-*/
+-
+-#ifndef _ANSIDECL_H
+-
+-#define _ANSIDECL_H 1
+-
+-
+-/* Every source file includes this file,
+- so they will all get the switch for lint. */
+-/* LINTLIBRARY */
+-
+-
+-#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32)
+-/* All known AIX compilers implement these things (but don't always
+- define __STDC__). The RISC/OS MIPS compiler defines these things
+- in SVR4 mode, but does not define __STDC__. */
+-
+-#define PTR void *
+-#define PTRCONST void *CONST
+-#define LONG_DOUBLE long double
+-
+-#define AND ,
+-#define NOARGS void
+-#define CONST const
+-#define VOLATILE volatile
+-#define SIGNED signed
+-#define DOTS , ...
+-
+-#define EXFUN(name, proto) name proto
+-#define DEFUN(name, arglist, args) name(args)
+-#define DEFUN_VOID(name) name(void)
+-
+-#define PROTO(type, name, arglist) type name arglist
+-#define PARAMS(paramlist) paramlist
+-#define ANSI_PROTOTYPES 1
+-
+-#else /* Not ANSI C. */
+-
+-#define PTR char *
+-#define PTRCONST PTR
+-#define LONG_DOUBLE double
+-
+-#define AND ;
+-#define NOARGS
+-#define CONST
+-#ifndef const /* some systems define it in header files for non-ansi mode */
+-#define const
+-#endif
+-#define VOLATILE
+-#define SIGNED
+-#define DOTS
+-
+-#define EXFUN(name, proto) name()
+-#define DEFUN(name, arglist, args) name arglist args;
+-#define DEFUN_VOID(name) name()
+-#define PROTO(type, name, arglist) type name ()
+-#define PARAMS(paramlist) ()
+-
+-#endif /* ANSI C. */
+-
+-#endif /* ansidecl.h */
+diff --git a/arch/ppc64/xmon/nonstdio.h b/arch/ppc64/xmon/nonstdio.h
+deleted file mode 100644
+--- a/arch/ppc64/xmon/nonstdio.h
++++ /dev/null
+@@ -1,22 +0,0 @@
+-typedef int FILE;
+-extern FILE *xmon_stdin, *xmon_stdout;
+-#define EOF (-1)
+-#define stdin xmon_stdin
+-#define stdout xmon_stdout
+-#define printf xmon_printf
+-#define fprintf xmon_fprintf
+-#define fputs xmon_fputs
+-#define fgets xmon_fgets
+-#define putchar xmon_putchar
+-#define getchar xmon_getchar
+-#define putc xmon_putc
+-#define getc xmon_getc
+-#define fopen(n, m) NULL
+-#define fflush(f) do {} while (0)
+-#define fclose(f) do {} while (0)
+-extern char *fgets(char *, int, void *);
+-extern void xmon_printf(const char *, ...);
+-extern void xmon_fprintf(void *, const char *, ...);
+-extern void xmon_sprintf(char *, const char *, ...);
+-
+-#define perror(s) printf("%s: no files!\n", (s))
+diff --git a/arch/ppc64/xmon/ppc-dis.c b/arch/ppc64/xmon/ppc-dis.c
+deleted file mode 100644
+--- a/arch/ppc64/xmon/ppc-dis.c
++++ /dev/null
+@@ -1,184 +0,0 @@
+-/* ppc-dis.c -- Disassemble PowerPC instructions
+- Copyright 1994 Free Software Foundation, Inc.
+- Written by Ian Lance Taylor, Cygnus Support
+-
+-This file is part of GDB, GAS, and the GNU binutils.
+-
+-GDB, GAS, and the GNU binutils are free software; you can redistribute
+-them and/or modify them 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.
+-
+-GDB, GAS, and the GNU binutils are distributed in the hope that they
+-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 file; see the file COPYING. If not, write to the Free
+-Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+-
+-#include "nonstdio.h"
+-#include "ansidecl.h"
+-#include "ppc.h"
+-
+-extern void print_address (unsigned long memaddr);
+-
+-/* Print a PowerPC or POWER instruction. */
+-
+-int
+-print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
+-{
+- const struct powerpc_opcode *opcode;
+- const struct powerpc_opcode *opcode_end;
+- unsigned long op;
+-
+- if (dialect == 0)
+- dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
+- | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
+-
+- /* Get the major opcode of the instruction. */
+- op = PPC_OP (insn);
+-
+- /* Find the first match in the opcode table. We could speed this up
+- a bit by doing a binary search on the major opcode. */
+- opcode_end = powerpc_opcodes + powerpc_num_opcodes;
+- again:
+- for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
+- {
+- unsigned long table_op;
+- const unsigned char *opindex;
+- const struct powerpc_operand *operand;
+- int invalid;
+- int need_comma;
+- int need_paren;
+-
+- table_op = PPC_OP (opcode->opcode);
+- if (op < table_op)
+- break;
+- if (op > table_op)
+- continue;
+-
+- if ((insn & opcode->mask) != opcode->opcode
+- || (opcode->flags & dialect) == 0)
+- continue;
+-
+- /* Make two passes over the operands. First see if any of them
+- have extraction functions, and, if they do, make sure the
+- instruction is valid. */
+- invalid = 0;
+- for (opindex = opcode->operands; *opindex != 0; opindex++)
+- {
+- operand = powerpc_operands + *opindex;
+- if (operand->extract)
+- (*operand->extract) (insn, dialect, &invalid);
+- }
+- if (invalid)
+- continue;
+-
+- /* The instruction is valid. */
+- printf("%s", opcode->name);
+- if (opcode->operands[0] != 0)
+- printf("\t");
+-
+- /* Now extract and print the operands. */
+- need_comma = 0;
+- need_paren = 0;
+- for (opindex = opcode->operands; *opindex != 0; opindex++)
+- {
+- long value;
+-
+- operand = powerpc_operands + *opindex;
+-
+- /* Operands that are marked FAKE are simply ignored. We
+- already made sure that the extract function considered
+- the instruction to be valid. */
+- if ((operand->flags & PPC_OPERAND_FAKE) != 0)
+- continue;
+-
+- /* Extract the value from the instruction. */
+- if (operand->extract)
+- value = (*operand->extract) (insn, dialect, &invalid);
+- else
+- {
+- value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+- if ((operand->flags & PPC_OPERAND_SIGNED) != 0
+- && (value & (1 << (operand->bits - 1))) != 0)
+- value -= 1 << operand->bits;
+- }
+-
+- /* If the operand is optional, and the value is zero, don't
+- print anything. */
+- if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+- && (operand->flags & PPC_OPERAND_NEXT) == 0
+- && value == 0)
+- continue;
+-
+- if (need_comma)
+- {
+- printf(",");
+- need_comma = 0;
+- }
+-
+- /* Print the operand as directed by the flags. */
+- if ((operand->flags & PPC_OPERAND_GPR) != 0)
+- printf("r%ld", value);
+- else if ((operand->flags & PPC_OPERAND_FPR) != 0)
+- printf("f%ld", value);
+- else if ((operand->flags & PPC_OPERAND_VR) != 0)
+- printf("v%ld", value);
+- else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
+- print_address (memaddr + value);
+- else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+- print_address (value & 0xffffffff);
+- else if ((operand->flags & PPC_OPERAND_CR) == 0
+- || (dialect & PPC_OPCODE_PPC) == 0)
+- printf("%ld", value);
+- else
+- {
+- if (operand->bits == 3)
+- printf("cr%d", value);
+- else
+- {
+- static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
+- int cr;
+- int cc;
+-
+- cr = value >> 2;
+- if (cr != 0)
+- printf("4*cr%d+", cr);
+- cc = value & 3;
+- printf("%s", cbnames[cc]);
+- }
+- }
+-
+- if (need_paren)
+- {
+- printf(")");
+- need_paren = 0;
+- }
+-
+- if ((operand->flags & PPC_OPERAND_PARENS) == 0)
+- need_comma = 1;
+- else
+- {
+- printf("(");
+- need_paren = 1;
+- }
+- }
+-
+- /* We have found and printed an instruction; return. */
+- return 4;
+- }
+-
+- if ((dialect & PPC_OPCODE_ANY) != 0)
+- {
+- dialect = ~PPC_OPCODE_ANY;
+- goto again;
+- }
+-
+- /* We could not find a match. */
+- printf(".long 0x%lx", insn);
+-
+- return 4;
+-}
+diff --git a/arch/ppc64/xmon/ppc-opc.c b/arch/ppc64/xmon/ppc-opc.c
+deleted file mode 100644
+--- a/arch/ppc64/xmon/ppc-opc.c
++++ /dev/null
+@@ -1,4621 +0,0 @@
+-/* ppc-opc.c -- PowerPC opcode list
+- Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
+- Free Software Foundation, Inc.
+- Written by Ian Lance Taylor, Cygnus Support
+-
+- This file is part of GDB, GAS, and the GNU binutils.
+-
+- GDB, GAS, and the GNU binutils are free software; you can redistribute
+- them and/or modify them 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.
+-
+- GDB, GAS, and the GNU binutils are distributed in the hope that they
+- 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 file; see the file COPYING. If not, write to the Free
+- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+- 02111-1307, USA. */
+-
+-#include <linux/stddef.h>
+-#include "nonstdio.h"
+-#include "ppc.h"
+-
+-#define ATTRIBUTE_UNUSED
+-#define _(x) x
+-
+-/* This file holds the PowerPC opcode table. The opcode table
+- includes almost all of the extended instruction mnemonics. This
+- permits the disassembler to use them, and simplifies the assembler
+- logic, at the cost of increasing the table size. The table is
+- strictly constant data, so the compiler should be able to put it in
+- the .text section.
+-
+- This file also holds the operand table. All knowledge about
+- inserting operands into instructions and vice-versa is kept in this
+- file. */
+-
+-/* Local insertion and extraction functions. */
+-
+-static unsigned long insert_bat (unsigned long, long, int, const char **);
+-static long extract_bat (unsigned long, int, int *);
+-static unsigned long insert_bba (unsigned long, long, int, const char **);
+-static long extract_bba (unsigned long, int, int *);
+-static unsigned long insert_bd (unsigned long, long, int, const char **);
+-static long extract_bd (unsigned long, int, int *);
+-static unsigned long insert_bdm (unsigned long, long, int, const char **);
+-static long extract_bdm (unsigned long, int, int *);
+-static unsigned long insert_bdp (unsigned long, long, int, const char **);
+-static long extract_bdp (unsigned long, int, int *);
+-static unsigned long insert_bo (unsigned long, long, int, const char **);
+-static long extract_bo (unsigned long, int, int *);
+-static unsigned long insert_boe (unsigned long, long, int, const char **);
+-static long extract_boe (unsigned long, int, int *);
+-static unsigned long insert_dq (unsigned long, long, int, const char **);
+-static long extract_dq (unsigned long, int, int *);
+-static unsigned long insert_ds (unsigned long, long, int, const char **);
+-static long extract_ds (unsigned long, int, int *);
+-static unsigned long insert_de (unsigned long, long, int, const char **);
+-static long extract_de (unsigned long, int, int *);
+-static unsigned long insert_des (unsigned long, long, int, const char **);
+-static long extract_des (unsigned long, int, int *);
+-static unsigned long insert_fxm (unsigned long, long, int, const char **);
+-static long extract_fxm (unsigned long, int, int *);
+-static unsigned long insert_li (unsigned long, long, int, const char **);
+-static long extract_li (unsigned long, int, int *);
+-static unsigned long insert_mbe (unsigned long, long, int, const char **);
+-static long extract_mbe (unsigned long, int, int *);
+-static unsigned long insert_mb6 (unsigned long, long, int, const char **);
+-static long extract_mb6 (unsigned long, int, int *);
+-static unsigned long insert_nb (unsigned long, long, int, const char **);
+-static long extract_nb (unsigned long, int, int *);
+-static unsigned long insert_nsi (unsigned long, long, int, const char **);
+-static long extract_nsi (unsigned long, int, int *);
+-static unsigned long insert_ral (unsigned long, long, int, const char **);
+-static unsigned long insert_ram (unsigned long, long, int, const char **);
+-static unsigned long insert_raq (unsigned long, long, int, const char **);
+-static unsigned long insert_ras (unsigned long, long, int, const char **);
+-static unsigned long insert_rbs (unsigned long, long, int, const char **);
+-static long extract_rbs (unsigned long, int, int *);
+-static unsigned long insert_rsq (unsigned long, long, int, const char **);
+-static unsigned long insert_rtq (unsigned long, long, int, const char **);
+-static unsigned long insert_sh6 (unsigned long, long, int, const char **);
+-static long extract_sh6 (unsigned long, int, int *);
+-static unsigned long insert_spr (unsigned long, long, int, const char **);
+-static long extract_spr (unsigned long, int, int *);
+-static unsigned long insert_tbr (unsigned long, long, int, const char **);
+-static long extract_tbr (unsigned long, int, int *);
+-static unsigned long insert_ev2 (unsigned long, long, int, const char **);
+-static long extract_ev2 (unsigned long, int, int *);
+-static unsigned long insert_ev4 (unsigned long, long, int, const char **);
+-static long extract_ev4 (unsigned long, int, int *);
+-static unsigned long insert_ev8 (unsigned long, long, int, const char **);
+-static long extract_ev8 (unsigned long, int, int *);
+-
+-/* The operands table.
+-
+- The fields are bits, shift, insert, extract, flags.
+-
+- We used to put parens around the various additions, like the one
+- for BA just below. However, that caused trouble with feeble
+- compilers with a limit on depth of a parenthesized expression, like
+- (reportedly) the compiler in Microsoft Developer Studio 5. So we
+- omit the parens, since the macros are never used in a context where
+- the addition will be ambiguous. */
+-
+-const struct powerpc_operand powerpc_operands[] =
+-{
+- /* The zero index is used to indicate the end of the list of
+- operands. */
+-#define UNUSED 0
+- { 0, 0, NULL, NULL, 0 },
+-
+- /* The BA field in an XL form instruction. */
+-#define BA UNUSED + 1
+-#define BA_MASK (0x1f << 16)
+- { 5, 16, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* The BA field in an XL form instruction when it must be the same
+- as the BT field in the same instruction. */
+-#define BAT BA + 1
+- { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE },
+-
+- /* The BB field in an XL form instruction. */
+-#define BB BAT + 1
+-#define BB_MASK (0x1f << 11)
+- { 5, 11, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* The BB field in an XL form instruction when it must be the same
+- as the BA field in the same instruction. */
+-#define BBA BB + 1
+- { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE },
+-
+- /* The BD field in a B form instruction. The lower two bits are
+- forced to zero. */
+-#define BD BBA + 1
+- { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+-
+- /* The BD field in a B form instruction when absolute addressing is
+- used. */
+-#define BDA BD + 1
+- { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+-
+- /* The BD field in a B form instruction when the - modifier is used.
+- This sets the y bit of the BO field appropriately. */
+-#define BDM BDA + 1
+- { 16, 0, insert_bdm, extract_bdm,
+- PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+-
+- /* The BD field in a B form instruction when the - modifier is used
+- and absolute address is used. */
+-#define BDMA BDM + 1
+- { 16, 0, insert_bdm, extract_bdm,
+- PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+-
+- /* The BD field in a B form instruction when the + modifier is used.
+- This sets the y bit of the BO field appropriately. */
+-#define BDP BDMA + 1
+- { 16, 0, insert_bdp, extract_bdp,
+- PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+-
+- /* The BD field in a B form instruction when the + modifier is used
+- and absolute addressing is used. */
+-#define BDPA BDP + 1
+- { 16, 0, insert_bdp, extract_bdp,
+- PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+-
+- /* The BF field in an X or XL form instruction. */
+-#define BF BDPA + 1
+- { 3, 23, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* An optional BF field. This is used for comparison instructions,
+- in which an omitted BF field is taken as zero. */
+-#define OBF BF + 1
+- { 3, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+-
+- /* The BFA field in an X or XL form instruction. */
+-#define BFA OBF + 1
+- { 3, 18, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* The BI field in a B form or XL form instruction. */
+-#define BI BFA + 1
+-#define BI_MASK (0x1f << 16)
+- { 5, 16, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* The BO field in a B form instruction. Certain values are
+- illegal. */
+-#define BO BI + 1
+-#define BO_MASK (0x1f << 21)
+- { 5, 21, insert_bo, extract_bo, 0 },
+-
+- /* The BO field in a B form instruction when the + or - modifier is
+- used. This is like the BO field, but it must be even. */
+-#define BOE BO + 1
+- { 5, 21, insert_boe, extract_boe, 0 },
+-
+- /* The BT field in an X or XL form instruction. */
+-#define BT BOE + 1
+- { 5, 21, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* The condition register number portion of the BI field in a B form
+- or XL form instruction. This is used for the extended
+- conditional branch mnemonics, which set the lower two bits of the
+- BI field. This field is optional. */
+-#define CR BT + 1
+- { 3, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+-
+- /* The CRB field in an X form instruction. */
+-#define CRB CR + 1
+- { 5, 6, NULL, NULL, 0 },
+-
+- /* The CRFD field in an X form instruction. */
+-#define CRFD CRB + 1
+- { 3, 23, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* The CRFS field in an X form instruction. */
+-#define CRFS CRFD + 1
+- { 3, 0, NULL, NULL, PPC_OPERAND_CR },
+-
+- /* The CT field in an X form instruction. */
+-#define CT CRFS + 1
+- { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+-
+- /* The D field in a D form instruction. This is a displacement off
+- a register, and implies that the next operand is a register in
+- parentheses. */
+-#define D CT + 1
+- { 16, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+-
+- /* The DE field in a DE form instruction. This is like D, but is 12
+- bits only. */
+-#define DE D + 1
+- { 14, 0, insert_de, extract_de, PPC_OPERAND_PARENS },
+-
+- /* The DES field in a DES form instruction. This is like DS, but is 14
+- bits only (12 stored.) */
+-#define DES DE + 1
+- { 14, 0, insert_des, extract_des, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+-
+- /* The DQ field in a DQ form instruction. This is like D, but the
+- lower four bits are forced to zero. */
+-#define DQ DES + 1
+- { 16, 0, insert_dq, extract_dq,
+- PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DQ },
+-
+- /* The DS field in a DS form instruction. This is like D, but the
+- lower two bits are forced to zero. */
+-#define DS DQ + 1
+- { 16, 0, insert_ds, extract_ds,
+- PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DS },
+-
+- /* The E field in a wrteei instruction. */
+-#define E DS + 1
+- { 1, 15, NULL, NULL, 0 },
+-
+- /* The FL1 field in a POWER SC form instruction. */
+-#define FL1 E + 1
+- { 4, 12, NULL, NULL, 0 },
+-
+- /* The FL2 field in a POWER SC form instruction. */
+-#define FL2 FL1 + 1
+- { 3, 2, NULL, NULL, 0 },
+-
+- /* The FLM field in an XFL form instruction. */
+-#define FLM FL2 + 1
+- { 8, 17, NULL, NULL, 0 },
+-
+- /* The FRA field in an X or A form instruction. */
+-#define FRA FLM + 1
+-#define FRA_MASK (0x1f << 16)
+- { 5, 16, NULL, NULL, PPC_OPERAND_FPR },
+-
+- /* The FRB field in an X or A form instruction. */
+-#define FRB FRA + 1
+-#define FRB_MASK (0x1f << 11)
+- { 5, 11, NULL, NULL, PPC_OPERAND_FPR },
+-
+- /* The FRC field in an A form instruction. */
+-#define FRC FRB + 1
+-#define FRC_MASK (0x1f << 6)
+- { 5, 6, NULL, NULL, PPC_OPERAND_FPR },
+-
+- /* The FRS field in an X form instruction or the FRT field in a D, X
+- or A form instruction. */
+-#define FRS FRC + 1
+-#define FRT FRS
+- { 5, 21, NULL, NULL, PPC_OPERAND_FPR },
+-
+- /* The FXM field in an XFX instruction. */
+-#define FXM FRS + 1
+-#define FXM_MASK (0xff << 12)
+- { 8, 12, insert_fxm, extract_fxm, 0 },
+-
+- /* Power4 version for mfcr. */
+-#define FXM4 FXM + 1
+- { 8, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL },
+-
+- /* The L field in a D or X form instruction. */
+-#define L FXM4 + 1
+- { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+-
+- /* The LEV field in a POWER SC form instruction. */
+-#define LEV L + 1
+- { 7, 5, NULL, NULL, 0 },
+-
+- /* The LI field in an I form instruction. The lower two bits are
+- forced to zero. */
+-#define LI LEV + 1
+- { 26, 0, insert_li, extract_li, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+-
+- /* The LI field in an I form instruction when used as an absolute
+- address. */
+-#define LIA LI + 1
+- { 26, 0, insert_li, extract_li, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+-
+- /* The LS field in an X (sync) form instruction. */
+-#define LS LIA + 1
+- { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+-
+- /* The MB field in an M form instruction. */
+-#define MB LS + 1
+-#define MB_MASK (0x1f << 6)
+- { 5, 6, NULL, NULL, 0 },
+-
+- /* The ME field in an M form instruction. */
+-#define ME MB + 1
+-#define ME_MASK (0x1f << 1)
+- { 5, 1, NULL, NULL, 0 },
+-
+- /* The MB and ME fields in an M form instruction expressed a single
+- operand which is a bitmask indicating which bits to select. This
+- is a two operand form using PPC_OPERAND_NEXT. See the
+- description in opcode/ppc.h for what this means. */
+-#define MBE ME + 1
+- { 5, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
+- { 32, 0, insert_mbe, extract_mbe, 0 },
+-
+- /* The MB or ME field in an MD or MDS form instruction. The high
+- bit is wrapped to the low end. */
+-#define MB6 MBE + 2
+-#define ME6 MB6
+-#define MB6_MASK (0x3f << 5)
+- { 6, 5, insert_mb6, extract_mb6, 0 },
+-
+- /* The MO field in an mbar instruction. */
+-#define MO MB6 + 1
+- { 5, 21, NULL, NULL, 0 },
+-
+- /* The NB field in an X form instruction. The value 32 is stored as
+- 0. */
+-#define NB MO + 1
+- { 6, 11, insert_nb, extract_nb, 0 },
+-
+- /* The NSI field in a D form instruction. This is the same as the
+- SI field, only negated. */
+-#define NSI NB + 1
+- { 16, 0, insert_nsi, extract_nsi,
+- PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
+-
+- /* The RA field in an D, DS, DQ, X, XO, M, or MDS form instruction. */
+-#define RA NSI + 1
+-#define RA_MASK (0x1f << 16)
+- { 5, 16, NULL, NULL, PPC_OPERAND_GPR },
+-
+- /* The RA field in the DQ form lq instruction, which has special
+- value restrictions. */
+-#define RAQ RA + 1
+- { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR },
+-
+- /* The RA field in a D or X form instruction which is an updating
+- load, which means that the RA field may not be zero and may not
+- equal the RT field. */
+-#define RAL RAQ + 1
+- { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR },
+-
+- /* The RA field in an lmw instruction, which has special value
+- restrictions. */
+-#define RAM RAL + 1
+- { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR },
+-
+- /* The RA field in a D or X form instruction which is an updating
+- store or an updating floating point load, which means that the RA
+- field may not be zero. */
+-#define RAS RAM + 1
+- { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR },
+-
+- /* The RB field in an X, XO, M, or MDS form instruction. */
+-#define RB RAS + 1
+-#define RB_MASK (0x1f << 11)
+- { 5, 11, NULL, NULL, PPC_OPERAND_GPR },
+-
+- /* The RB field in an X form instruction when it must be the same as
+- the RS field in the instruction. This is used for extended
+- mnemonics like mr. */
+-#define RBS RB + 1
+- { 5, 1, insert_rbs, extract_rbs, PPC_OPERAND_FAKE },
+-
+- /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form
+- instruction or the RT field in a D, DS, X, XFX or XO form
+- instruction. */
+-#define RS RBS + 1
+-#define RT RS
+-#define RT_MASK (0x1f << 21)
+- { 5, 21, NULL, NULL, PPC_OPERAND_GPR },
+-
+- /* The RS field of the DS form stq instruction, which has special
+- value restrictions. */
+-#define RSQ RS + 1
+- { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR },
+-
+- /* The RT field of the DQ form lq instruction, which has special
+- value restrictions. */
+-#define RTQ RSQ + 1
+- { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR },
+-
+- /* The SH field in an X or M form instruction. */
+-#define SH RTQ + 1
+-#define SH_MASK (0x1f << 11)
+- { 5, 11, NULL, NULL, 0 },
+-
+- /* The SH field in an MD form instruction. This is split. */
+-#define SH6 SH + 1
+-#define SH6_MASK ((0x1f << 11) | (1 << 1))
+- { 6, 1, insert_sh6, extract_sh6, 0 },
+-
+- /* The SI field in a D form instruction. */
+-#define SI SH6 + 1
+- { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
+-
+- /* The SI field in a D form instruction when we accept a wide range
+- of positive values. */
+-#define SISIGNOPT SI + 1
+- { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
+-
+- /* The SPR field in an XFX form instruction. This is flipped--the
+- lower 5 bits are stored in the upper 5 and vice- versa. */
+-#define SPR SISIGNOPT + 1
+-#define PMR SPR
+-#define SPR_MASK (0x3ff << 11)
+- { 10, 11, insert_spr, extract_spr, 0 },
+-
+- /* The BAT index number in an XFX form m[ft]ibat[lu] instruction. */
+-#define SPRBAT SPR + 1
+-#define SPRBAT_MASK (0x3 << 17)
+- { 2, 17, NULL, NULL, 0 },
+-
+- /* The SPRG register number in an XFX form m[ft]sprg instruction. */
+-#define SPRG SPRBAT + 1
+-#define SPRG_MASK (0x3 << 16)
+- { 2, 16, NULL, NULL, 0 },
+-
+- /* The SR field in an X form instruction. */
+-#define SR SPRG + 1
+- { 4, 16, NULL, NULL, 0 },
+-
+- /* The STRM field in an X AltiVec form instruction. */
+-#define STRM SR + 1
+-#define STRM_MASK (0x3 << 21)
+- { 2, 21, NULL, NULL, 0 },
+-
+- /* The SV field in a POWER SC form instruction. */
+-#define SV STRM + 1
+- { 14, 2, NULL, NULL, 0 },
+-
+- /* The TBR field in an XFX form instruction. This is like the SPR
+- field, but it is optional. */
+-#define TBR SV + 1
+- { 10, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
+-
+- /* The TO field in a D or X form instruction. */
+-#define TO TBR + 1
+-#define TO_MASK (0x1f << 21)
+- { 5, 21, NULL, NULL, 0 },
+-
+- /* The U field in an X form instruction. */
+-#define U TO + 1
+- { 4, 12, NULL, NULL, 0 },
+-
+- /* The UI field in a D form instruction. */
+-#define UI U + 1
+- { 16, 0, NULL, NULL, 0 },
+-
+- /* The VA field in a VA, VX or VXR form instruction. */
+-#define VA UI + 1
+-#define VA_MASK (0x1f << 16)
+- { 5, 16, NULL, NULL, PPC_OPERAND_VR },
+-
+- /* The VB field in a VA, VX or VXR form instruction. */
+-#define VB VA + 1
+-#define VB_MASK (0x1f << 11)
+- { 5, 11, NULL, NULL, PPC_OPERAND_VR },
+-
+- /* The VC field in a VA form instruction. */
+-#define VC VB + 1
+-#define VC_MASK (0x1f << 6)
+- { 5, 6, NULL, NULL, PPC_OPERAND_VR },
+-
+- /* The VD or VS field in a VA, VX, VXR or X form instruction. */
+-#define VD VC + 1
+-#define VS VD
+-#define VD_MASK (0x1f << 21)
+- { 5, 21, NULL, NULL, PPC_OPERAND_VR },
+-
+- /* The SIMM field in a VX form instruction. */
+-#define SIMM VD + 1
+- { 5, 16, NULL, NULL, PPC_OPERAND_SIGNED},
+-
+- /* The UIMM field in a VX form instruction. */
+-#define UIMM SIMM + 1
+- { 5, 16, NULL, NULL, 0 },
+-
+- /* The SHB field in a VA form instruction. */
+-#define SHB UIMM + 1
+- { 4, 6, NULL, NULL, 0 },
+-
+- /* The other UIMM field in a EVX form instruction. */
+-#define EVUIMM SHB + 1
+- { 5, 11, NULL, NULL, 0 },
+-
+- /* The other UIMM field in a half word EVX form instruction. */
+-#define EVUIMM_2 EVUIMM + 1
+- { 32, 11, insert_ev2, extract_ev2, PPC_OPERAND_PARENS },
+-
+- /* The other UIMM field in a word EVX form instruction. */
+-#define EVUIMM_4 EVUIMM_2 + 1
+- { 32, 11, insert_ev4, extract_ev4, PPC_OPERAND_PARENS },
+-
+- /* The other UIMM field in a double EVX form instruction. */
+-#define EVUIMM_8 EVUIMM_4 + 1
+- { 32, 11, insert_ev8, extract_ev8, PPC_OPERAND_PARENS },
+-
+- /* The WS field. */
+-#define WS EVUIMM_8 + 1
+-#define WS_MASK (0x7 << 11)
+- { 3, 11, NULL, NULL, 0 },
+-
+- /* The L field in an mtmsrd instruction */
+-#define MTMSRD_L WS + 1
+- { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL },
+-
+-};
+-
+-/* The functions used to insert and extract complicated operands. */
+-
+-/* The BA field in an XL form instruction when it must be the same as
+- the BT field in the same instruction. This operand is marked FAKE.
+- The insertion function just copies the BT field into the BA field,
+- and the extraction function just checks that the fields are the
+- same. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_bat (unsigned long insn,
+- long value ATTRIBUTE_UNUSED,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | (((insn >> 21) & 0x1f) << 16);
+-}
+-
+-static long
+-extract_bat (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid)
+-{
+- if (((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f))
+- *invalid = 1;
+- return 0;
+-}
+-
+-/* The BB field in an XL form instruction when it must be the same as
+- the BA field in the same instruction. This operand is marked FAKE.
+- The insertion function just copies the BA field into the BB field,
+- and the extraction function just checks that the fields are the
+- same. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_bba (unsigned long insn,
+- long value ATTRIBUTE_UNUSED,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | (((insn >> 16) & 0x1f) << 11);
+-}
+-
+-static long
+-extract_bba (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid)
+-{
+- if (((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f))
+- *invalid = 1;
+- return 0;
+-}
+-
+-/* The BD field in a B form instruction. The lower two bits are
+- forced to zero. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_bd (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | (value & 0xfffc);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_bd (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+-}
+-
+-/* The BD field in a B form instruction when the - modifier is used.
+- This modifier means that the branch is not expected to be taken.
+- For chips built to versions of the architecture prior to version 2
+- (ie. not Power4 compatible), we set the y bit of the BO field to 1
+- if the offset is negative. When extracting, we require that the y
+- bit be 1 and that the offset be positive, since if the y bit is 0
+- we just want to print the normal form of the instruction.
+- Power4 compatible targets use two bits, "a", and "t", instead of
+- the "y" bit. "at" == 00 => no hint, "at" == 01 => unpredictable,
+- "at" == 10 => not taken, "at" == 11 => taken. The "t" bit is 00001
+- in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000
+- for branch on CTR. We only handle the taken/not-taken hint here. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_bdm (unsigned long insn,
+- long value,
+- int dialect,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- if ((dialect & PPC_OPCODE_POWER4) == 0)
+- {
+- if ((value & 0x8000) != 0)
+- insn |= 1 << 21;
+- }
+- else
+- {
+- if ((insn & (0x14 << 21)) == (0x04 << 21))
+- insn |= 0x02 << 21;
+- else if ((insn & (0x14 << 21)) == (0x10 << 21))
+- insn |= 0x08 << 21;
+- }
+- return insn | (value & 0xfffc);
+-}
+-
+-static long
+-extract_bdm (unsigned long insn,
+- int dialect,
+- int *invalid)
+-{
+- if ((dialect & PPC_OPCODE_POWER4) == 0)
+- {
+- if (((insn & (1 << 21)) == 0) != ((insn & (1 << 15)) == 0))
+- *invalid = 1;
+- }
+- else
+- {
+- if ((insn & (0x17 << 21)) != (0x06 << 21)
+- && (insn & (0x1d << 21)) != (0x18 << 21))
+- *invalid = 1;
+- }
+-
+- return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+-}
+-
+-/* The BD field in a B form instruction when the + modifier is used.
+- This is like BDM, above, except that the branch is expected to be
+- taken. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_bdp (unsigned long insn,
+- long value,
+- int dialect,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- if ((dialect & PPC_OPCODE_POWER4) == 0)
+- {
+- if ((value & 0x8000) == 0)
+- insn |= 1 << 21;
+- }
+- else
+- {
+- if ((insn & (0x14 << 21)) == (0x04 << 21))
+- insn |= 0x03 << 21;
+- else if ((insn & (0x14 << 21)) == (0x10 << 21))
+- insn |= 0x09 << 21;
+- }
+- return insn | (value & 0xfffc);
+-}
+-
+-static long
+-extract_bdp (unsigned long insn,
+- int dialect,
+- int *invalid)
+-{
+- if ((dialect & PPC_OPCODE_POWER4) == 0)
+- {
+- if (((insn & (1 << 21)) == 0) == ((insn & (1 << 15)) == 0))
+- *invalid = 1;
+- }
+- else
+- {
+- if ((insn & (0x17 << 21)) != (0x07 << 21)
+- && (insn & (0x1d << 21)) != (0x19 << 21))
+- *invalid = 1;
+- }
+-
+- return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+-}
+-
+-/* Check for legal values of a BO field. */
+-
+-static int
+-valid_bo (long value, int dialect)
+-{
+- if ((dialect & PPC_OPCODE_POWER4) == 0)
+- {
+- /* Certain encodings have bits that are required to be zero.
+- These are (z must be zero, y may be anything):
+- 001zy
+- 011zy
+- 1z00y
+- 1z01y
+- 1z1zz
+- */
+- switch (value & 0x14)
+- {
+- default:
+- case 0:
+- return 1;
+- case 0x4:
+- return (value & 0x2) == 0;
+- case 0x10:
+- return (value & 0x8) == 0;
+- case 0x14:
+- return value == 0x14;
+- }
+- }
+- else
+- {
+- /* Certain encodings have bits that are required to be zero.
+- These are (z must be zero, a & t may be anything):
+- 0000z
+- 0001z
+- 0100z
+- 0101z
+- 001at
+- 011at
+- 1a00t
+- 1a01t
+- 1z1zz
+- */
+- if ((value & 0x14) == 0)
+- return (value & 0x1) == 0;
+- else if ((value & 0x14) == 0x14)
+- return value == 0x14;
+- else
+- return 1;
+- }
+-}
+-
+-/* The BO field in a B form instruction. Warn about attempts to set
+- the field to an illegal value. */
+-
+-static unsigned long
+-insert_bo (unsigned long insn,
+- long value,
+- int dialect,
+- const char **errmsg)
+-{
+- if (!valid_bo (value, dialect))
+- *errmsg = _("invalid conditional option");
+- return insn | ((value & 0x1f) << 21);
+-}
+-
+-static long
+-extract_bo (unsigned long insn,
+- int dialect,
+- int *invalid)
+-{
+- long value;
+-
+- value = (insn >> 21) & 0x1f;
+- if (!valid_bo (value, dialect))
+- *invalid = 1;
+- return value;
+-}
+-
+-/* The BO field in a B form instruction when the + or - modifier is
+- used. This is like the BO field, but it must be even. When
+- extracting it, we force it to be even. */
+-
+-static unsigned long
+-insert_boe (unsigned long insn,
+- long value,
+- int dialect,
+- const char **errmsg)
+-{
+- if (!valid_bo (value, dialect))
+- *errmsg = _("invalid conditional option");
+- else if ((value & 1) != 0)
+- *errmsg = _("attempt to set y bit when using + or - modifier");
+-
+- return insn | ((value & 0x1f) << 21);
+-}
+-
+-static long
+-extract_boe (unsigned long insn,
+- int dialect,
+- int *invalid)
+-{
+- long value;
+-
+- value = (insn >> 21) & 0x1f;
+- if (!valid_bo (value, dialect))
+- *invalid = 1;
+- return value & 0x1e;
+-}
+-
+-/* The DQ field in a DQ form instruction. This is like D, but the
+- lower four bits are forced to zero. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_dq (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 0xf) != 0)
+- *errmsg = _("offset not a multiple of 16");
+- return insn | (value & 0xfff0);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_dq (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return ((insn & 0xfff0) ^ 0x8000) - 0x8000;
+-}
+-
+-static unsigned long
+-insert_ev2 (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 1) != 0)
+- *errmsg = _("offset not a multiple of 2");
+- if ((value > 62) != 0)
+- *errmsg = _("offset greater than 62");
+- return insn | ((value & 0x3e) << 10);
+-}
+-
+-static long
+-extract_ev2 (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return (insn >> 10) & 0x3e;
+-}
+-
+-static unsigned long
+-insert_ev4 (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 3) != 0)
+- *errmsg = _("offset not a multiple of 4");
+- if ((value > 124) != 0)
+- *errmsg = _("offset greater than 124");
+- return insn | ((value & 0x7c) << 9);
+-}
+-
+-static long
+-extract_ev4 (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return (insn >> 9) & 0x7c;
+-}
+-
+-static unsigned long
+-insert_ev8 (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 7) != 0)
+- *errmsg = _("offset not a multiple of 8");
+- if ((value > 248) != 0)
+- *errmsg = _("offset greater than 248");
+- return insn | ((value & 0xf8) << 8);
+-}
+-
+-static long
+-extract_ev8 (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return (insn >> 8) & 0xf8;
+-}
+-
+-/* The DS field in a DS form instruction. This is like D, but the
+- lower two bits are forced to zero. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_ds (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 3) != 0)
+- *errmsg = _("offset not a multiple of 4");
+- return insn | (value & 0xfffc);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_ds (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+-}
+-
+-/* The DE field in a DE form instruction. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_de (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if (value > 2047 || value < -2048)
+- *errmsg = _("offset not between -2048 and 2047");
+- return insn | ((value << 4) & 0xfff0);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_de (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return (insn & 0xfff0) >> 4;
+-}
+-
+-/* The DES field in a DES form instruction. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_des (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if (value > 8191 || value < -8192)
+- *errmsg = _("offset not between -8192 and 8191");
+- else if ((value & 3) != 0)
+- *errmsg = _("offset not a multiple of 4");
+- return insn | ((value << 2) & 0xfff0);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_des (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return (((insn >> 2) & 0x3ffc) ^ 0x2000) - 0x2000;
+-}
+-
+-/* FXM mask in mfcr and mtcrf instructions. */
+-
+-static unsigned long
+-insert_fxm (unsigned long insn,
+- long value,
+- int dialect,
+- const char **errmsg)
+-{
+- /* If the optional field on mfcr is missing that means we want to use
+- the old form of the instruction that moves the whole cr. In that
+- case we'll have VALUE zero. There doesn't seem to be a way to
+- distinguish this from the case where someone writes mfcr %r3,0. */
+- if (value == 0)
+- ;
+-
+- /* If only one bit of the FXM field is set, we can use the new form
+- of the instruction, which is faster. Unlike the Power4 branch hint
+- encoding, this is not backward compatible. */
+- else if ((dialect & PPC_OPCODE_POWER4) != 0 && (value & -value) == value)
+- insn |= 1 << 20;
+-
+- /* Any other value on mfcr is an error. */
+- else if ((insn & (0x3ff << 1)) == 19 << 1)
+- {
+- *errmsg = _("ignoring invalid mfcr mask");
+- value = 0;
+- }
+-
+- return insn | ((value & 0xff) << 12);
+-}
+-
+-static long
+-extract_fxm (unsigned long insn,
+- int dialect,
+- int *invalid)
+-{
+- long mask = (insn >> 12) & 0xff;
+-
+- /* Is this a Power4 insn? */
+- if ((insn & (1 << 20)) != 0)
+- {
+- if ((dialect & PPC_OPCODE_POWER4) == 0)
+- *invalid = 1;
+- else
+- {
+- /* Exactly one bit of MASK should be set. */
+- if (mask == 0 || (mask & -mask) != mask)
+- *invalid = 1;
+- }
+- }
+-
+- /* Check that non-power4 form of mfcr has a zero MASK. */
+- else if ((insn & (0x3ff << 1)) == 19 << 1)
+- {
+- if (mask != 0)
+- *invalid = 1;
+- }
+-
+- return mask;
+-}
+-
+-/* The LI field in an I form instruction. The lower two bits are
+- forced to zero. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_li (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 3) != 0)
+- *errmsg = _("ignoring least significant bits in branch offset");
+- return insn | (value & 0x3fffffc);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_li (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return ((insn & 0x3fffffc) ^ 0x2000000) - 0x2000000;
+-}
+-
+-/* The MB and ME fields in an M form instruction expressed as a single
+- operand which is itself a bitmask. The extraction function always
+- marks it as invalid, since we never want to recognize an
+- instruction which uses a field of this type. */
+-
+-static unsigned long
+-insert_mbe (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- unsigned long uval, mask;
+- int mb, me, mx, count, last;
+-
+- uval = value;
+-
+- if (uval == 0)
+- {
+- *errmsg = _("illegal bitmask");
+- return insn;
+- }
+-
+- mb = 0;
+- me = 32;
+- if ((uval & 1) != 0)
+- last = 1;
+- else
+- last = 0;
+- count = 0;
+-
+- /* mb: location of last 0->1 transition */
+- /* me: location of last 1->0 transition */
+- /* count: # transitions */
+-
+- for (mx = 0, mask = 1L << 31; mx < 32; ++mx, mask >>= 1)
+- {
+- if ((uval & mask) && !last)
+- {
+- ++count;
+- mb = mx;
+- last = 1;
+- }
+- else if (!(uval & mask) && last)
+- {
+- ++count;
+- me = mx;
+- last = 0;
+- }
+- }
+- if (me == 0)
+- me = 32;
+-
+- if (count != 2 && (count != 0 || ! last))
+- *errmsg = _("illegal bitmask");
+-
+- return insn | (mb << 6) | ((me - 1) << 1);
+-}
+-
+-static long
+-extract_mbe (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid)
+-{
+- long ret;
+- int mb, me;
+- int i;
+-
+- *invalid = 1;
+-
+- mb = (insn >> 6) & 0x1f;
+- me = (insn >> 1) & 0x1f;
+- if (mb < me + 1)
+- {
+- ret = 0;
+- for (i = mb; i <= me; i++)
+- ret |= 1L << (31 - i);
+- }
+- else if (mb == me + 1)
+- ret = ~0;
+- else /* (mb > me + 1) */
+- {
+- ret = ~0;
+- for (i = me + 1; i < mb; i++)
+- ret &= ~(1L << (31 - i));
+- }
+- return ret;
+-}
+-
+-/* The MB or ME field in an MD or MDS form instruction. The high bit
+- is wrapped to the low end. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_mb6 (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | ((value & 0x1f) << 6) | (value & 0x20);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_mb6 (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return ((insn >> 6) & 0x1f) | (insn & 0x20);
+-}
+-
+-/* The NB field in an X form instruction. The value 32 is stored as
+- 0. */
+-
+-static unsigned long
+-insert_nb (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if (value < 0 || value > 32)
+- *errmsg = _("value out of range");
+- if (value == 32)
+- value = 0;
+- return insn | ((value & 0x1f) << 11);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_nb (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- long ret;
+-
+- ret = (insn >> 11) & 0x1f;
+- if (ret == 0)
+- ret = 32;
+- return ret;
+-}
+-
+-/* The NSI field in a D form instruction. This is the same as the SI
+- field, only negated. The extraction function always marks it as
+- invalid, since we never want to recognize an instruction which uses
+- a field of this type. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_nsi (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | (-value & 0xffff);
+-}
+-
+-static long
+-extract_nsi (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid)
+-{
+- *invalid = 1;
+- return -(((insn & 0xffff) ^ 0x8000) - 0x8000);
+-}
+-
+-/* The RA field in a D or X form instruction which is an updating
+- load, which means that the RA field may not be zero and may not
+- equal the RT field. */
+-
+-static unsigned long
+-insert_ral (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if (value == 0
+- || (unsigned long) value == ((insn >> 21) & 0x1f))
+- *errmsg = "invalid register operand when updating";
+- return insn | ((value & 0x1f) << 16);
+-}
+-
+-/* The RA field in an lmw instruction, which has special value
+- restrictions. */
+-
+-static unsigned long
+-insert_ram (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((unsigned long) value >= ((insn >> 21) & 0x1f))
+- *errmsg = _("index register in load range");
+- return insn | ((value & 0x1f) << 16);
+-}
+-
+-/* The RA field in the DQ form lq instruction, which has special
+- value restrictions. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_raq (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- long rtvalue = (insn & RT_MASK) >> 21;
+-
+- if (value == rtvalue)
+- *errmsg = _("source and target register operands must be different");
+- return insn | ((value & 0x1f) << 16);
+-}
+-
+-/* The RA field in a D or X form instruction which is an updating
+- store or an updating floating point load, which means that the RA
+- field may not be zero. */
+-
+-static unsigned long
+-insert_ras (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if (value == 0)
+- *errmsg = _("invalid register operand when updating");
+- return insn | ((value & 0x1f) << 16);
+-}
+-
+-/* The RB field in an X form instruction when it must be the same as
+- the RS field in the instruction. This is used for extended
+- mnemonics like mr. This operand is marked FAKE. The insertion
+- function just copies the BT field into the BA field, and the
+- extraction function just checks that the fields are the same. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_rbs (unsigned long insn,
+- long value ATTRIBUTE_UNUSED,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | (((insn >> 21) & 0x1f) << 11);
+-}
+-
+-static long
+-extract_rbs (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid)
+-{
+- if (((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f))
+- *invalid = 1;
+- return 0;
+-}
+-
+-/* The RT field of the DQ form lq instruction, which has special
+- value restrictions. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_rtq (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 1) != 0)
+- *errmsg = _("target register operand must be even");
+- return insn | ((value & 0x1f) << 21);
+-}
+-
+-/* The RS field of the DS form stq instruction, which has special
+- value restrictions. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_rsq (unsigned long insn,
+- long value ATTRIBUTE_UNUSED,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg)
+-{
+- if ((value & 1) != 0)
+- *errmsg = _("source register operand must be even");
+- return insn | ((value & 0x1f) << 21);
+-}
+-
+-/* The SH field in an MD form instruction. This is split. */
+-
+-/*ARGSUSED*/
+-static unsigned long
+-insert_sh6 (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
+-}
+-
+-/*ARGSUSED*/
+-static long
+-extract_sh6 (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
+-}
+-
+-/* The SPR field in an XFX form instruction. This is flipped--the
+- lower 5 bits are stored in the upper 5 and vice- versa. */
+-
+-static unsigned long
+-insert_spr (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+-}
+-
+-static long
+-extract_spr (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+-}
+-
+-/* The TBR field in an XFX instruction. This is just like SPR, but it
+- is optional. When TBR is omitted, it must be inserted as 268 (the
+- magic number of the TB register). These functions treat 0
+- (indicating an omitted optional operand) as 268. This means that
+- ``mftb 4,0'' is not handled correctly. This does not matter very
+- much, since the architecture manual does not define mftb as
+- accepting any values other than 268 or 269. */
+-
+-#define TB (268)
+-
+-static unsigned long
+-insert_tbr (unsigned long insn,
+- long value,
+- int dialect ATTRIBUTE_UNUSED,
+- const char **errmsg ATTRIBUTE_UNUSED)
+-{
+- if (value == 0)
+- value = TB;
+- return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+-}
+-
+-static long
+-extract_tbr (unsigned long insn,
+- int dialect ATTRIBUTE_UNUSED,
+- int *invalid ATTRIBUTE_UNUSED)
+-{
+- long ret;
+-
+- ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+- if (ret == TB)
+- ret = 0;
+- return ret;
+-}
+-
+-/* Macros used to form opcodes. */
+-
+-/* The main opcode. */
+-#define OP(x) ((((unsigned long)(x)) & 0x3f) << 26)
+-#define OP_MASK OP (0x3f)
+-
+-/* The main opcode combined with a trap code in the TO field of a D
+- form instruction. Used for extended mnemonics for the trap
+- instructions. */
+-#define OPTO(x,to) (OP (x) | ((((unsigned long)(to)) & 0x1f) << 21))
+-#define OPTO_MASK (OP_MASK | TO_MASK)
+-
+-/* The main opcode combined with a comparison size bit in the L field
+- of a D form or X form instruction. Used for extended mnemonics for
+- the comparison instructions. */
+-#define OPL(x,l) (OP (x) | ((((unsigned long)(l)) & 1) << 21))
+-#define OPL_MASK OPL (0x3f,1)
+-
+-/* An A form instruction. */
+-#define A(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1) | (((unsigned long)(rc)) & 1))
+-#define A_MASK A (0x3f, 0x1f, 1)
+-
+-/* An A_MASK with the FRB field fixed. */
+-#define AFRB_MASK (A_MASK | FRB_MASK)
+-
+-/* An A_MASK with the FRC field fixed. */
+-#define AFRC_MASK (A_MASK | FRC_MASK)
+-
+-/* An A_MASK with the FRA and FRC fields fixed. */
+-#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK)
+-
+-/* A B form instruction. */
+-#define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1))
+-#define B_MASK B (0x3f, 1, 1)
+-
+-/* A B form instruction setting the BO field. */
+-#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21))
+-#define BBO_MASK BBO (0x3f, 0x1f, 1, 1)
+-
+-/* A BBO_MASK with the y bit of the BO field removed. This permits
+- matching a conditional branch regardless of the setting of the y
+- bit. Similarly for the 'at' bits used for power4 branch hints. */
+-#define Y_MASK (((unsigned long) 1) << 21)
+-#define AT1_MASK (((unsigned long) 3) << 21)
+-#define AT2_MASK (((unsigned long) 9) << 21)
+-#define BBOY_MASK (BBO_MASK &~ Y_MASK)
+-#define BBOAT_MASK (BBO_MASK &~ AT1_MASK)
+-
+-/* A B form instruction setting the BO field and the condition bits of
+- the BI field. */
+-#define BBOCB(op, bo, cb, aa, lk) \
+- (BBO ((op), (bo), (aa), (lk)) | ((((unsigned long)(cb)) & 0x3) << 16))
+-#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1)
+-
+-/* A BBOCB_MASK with the y bit of the BO field removed. */
+-#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK)
+-#define BBOATCB_MASK (BBOCB_MASK &~ AT1_MASK)
+-#define BBOAT2CB_MASK (BBOCB_MASK &~ AT2_MASK)
+-
+-/* A BBOYCB_MASK in which the BI field is fixed. */
+-#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK)
+-#define BBOATBI_MASK (BBOAT2CB_MASK | BI_MASK)
+-
+-/* An Context form instruction. */
+-#define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7))
+-#define CTX_MASK CTX(0x3f, 0x7)
+-
+-/* An User Context form instruction. */
+-#define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f))
+-#define UCTX_MASK UCTX(0x3f, 0x1f)
+-
+-/* The main opcode mask with the RA field clear. */
+-#define DRA_MASK (OP_MASK | RA_MASK)
+-
+-/* A DS form instruction. */
+-#define DSO(op, xop) (OP (op) | ((xop) & 0x3))
+-#define DS_MASK DSO (0x3f, 3)
+-
+-/* A DE form instruction. */
+-#define DEO(op, xop) (OP (op) | ((xop) & 0xf))
+-#define DE_MASK DEO (0x3e, 0xf)
+-
+-/* An EVSEL form instruction. */
+-#define EVSEL(op, xop) (OP (op) | (((unsigned long)(xop)) & 0xff) << 3)
+-#define EVSEL_MASK EVSEL(0x3f, 0xff)
+-
+-/* An M form instruction. */
+-#define M(op, rc) (OP (op) | ((rc) & 1))
+-#define M_MASK M (0x3f, 1)
+-
+-/* An M form instruction with the ME field specified. */
+-#define MME(op, me, rc) (M ((op), (rc)) | ((((unsigned long)(me)) & 0x1f) << 1))
+-
+-/* An M_MASK with the MB and ME fields fixed. */
+-#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK)
+-
+-/* An M_MASK with the SH and ME fields fixed. */
+-#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK)
+-
+-/* An MD form instruction. */
+-#define MD(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x7) << 2) | ((rc) & 1))
+-#define MD_MASK MD (0x3f, 0x7, 1)
+-
+-/* An MD_MASK with the MB field fixed. */
+-#define MDMB_MASK (MD_MASK | MB6_MASK)
+-
+-/* An MD_MASK with the SH field fixed. */
+-#define MDSH_MASK (MD_MASK | SH6_MASK)
+-
+-/* An MDS form instruction. */
+-#define MDS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0xf) << 1) | ((rc) & 1))
+-#define MDS_MASK MDS (0x3f, 0xf, 1)
+-
+-/* An MDS_MASK with the MB field fixed. */
+-#define MDSMB_MASK (MDS_MASK | MB6_MASK)
+-
+-/* An SC form instruction. */
+-#define SC(op, sa, lk) (OP (op) | ((((unsigned long)(sa)) & 1) << 1) | ((lk) & 1))
+-#define SC_MASK (OP_MASK | (((unsigned long)0x3ff) << 16) | (((unsigned long)1) << 1) | 1)
+-
+-/* An VX form instruction. */
+-#define VX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7ff))
+-
+-/* The mask for an VX form instruction. */
+-#define VX_MASK VX(0x3f, 0x7ff)
+-
+-/* An VA form instruction. */
+-#define VXA(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x03f))
+-
+-/* The mask for an VA form instruction. */
+-#define VXA_MASK VXA(0x3f, 0x3f)
+-
+-/* An VXR form instruction. */
+-#define VXR(op, xop, rc) (OP (op) | (((rc) & 1) << 10) | (((unsigned long)(xop)) & 0x3ff))
+-
+-/* The mask for a VXR form instruction. */
+-#define VXR_MASK VXR(0x3f, 0x3ff, 1)
+-
+-/* An X form instruction. */
+-#define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1))
+-
+-/* An X form instruction with the RC bit specified. */
+-#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
+-
+-/* The mask for an X form instruction. */
+-#define X_MASK XRC (0x3f, 0x3ff, 1)
+-
+-/* An X_MASK with the RA field fixed. */
+-#define XRA_MASK (X_MASK | RA_MASK)
+-
+-/* An X_MASK with the RB field fixed. */
+-#define XRB_MASK (X_MASK | RB_MASK)
+-
+-/* An X_MASK with the RT field fixed. */
+-#define XRT_MASK (X_MASK | RT_MASK)
+-
+-/* An X_MASK with the RA and RB fields fixed. */
+-#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
+-
+-/* An XRARB_MASK, but with the L bit clear. */
+-#define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16))
+-
+-/* An X_MASK with the RT and RA fields fixed. */
+-#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK)
+-
+-/* An XRTRA_MASK, but with L bit clear. */
+-#define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21))
+-
+-/* An X form comparison instruction. */
+-#define XCMPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21))
+-
+-/* The mask for an X form comparison instruction. */
+-#define XCMP_MASK (X_MASK | (((unsigned long)1) << 22))
+-
+-/* The mask for an X form comparison instruction with the L field
+- fixed. */
+-#define XCMPL_MASK (XCMP_MASK | (((unsigned long)1) << 21))
+-
+-/* An X form trap instruction with the TO field specified. */
+-#define XTO(op, xop, to) (X ((op), (xop)) | ((((unsigned long)(to)) & 0x1f) << 21))
+-#define XTO_MASK (X_MASK | TO_MASK)
+-
+-/* An X form tlb instruction with the SH field specified. */
+-#define XTLB(op, xop, sh) (X ((op), (xop)) | ((((unsigned long)(sh)) & 0x1f) << 11))
+-#define XTLB_MASK (X_MASK | SH_MASK)
+-
+-/* An X form sync instruction. */
+-#define XSYNC(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 3) << 21))
+-
+-/* An X form sync instruction with everything filled in except the LS field. */
+-#define XSYNC_MASK (0xff9fffff)
+-
+-/* An X form AltiVec dss instruction. */
+-#define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25))
+-#define XDSS_MASK XDSS(0x3f, 0x3ff, 1)
+-
+-/* An XFL form instruction. */
+-#define XFL(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1) | (((unsigned long)(rc)) & 1))
+-#define XFL_MASK (XFL (0x3f, 0x3ff, 1) | (((unsigned long)1) << 25) | (((unsigned long)1) << 16))
+-
+-/* An X form isel instruction. */
+-#define XISEL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1))
+-#define XISEL_MASK XISEL(0x3f, 0x1f)
+-
+-/* An XL form instruction with the LK field set to 0. */
+-#define XL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1))
+-
+-/* An XL form instruction which uses the LK field. */
+-#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1))
+-
+-/* The mask for an XL form instruction. */
+-#define XL_MASK XLLK (0x3f, 0x3ff, 1)
+-
+-/* An XL form instruction which explicitly sets the BO field. */
+-#define XLO(op, bo, xop, lk) \
+- (XLLK ((op), (xop), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21))
+-#define XLO_MASK (XL_MASK | BO_MASK)
+-
+-/* An XL form instruction which explicitly sets the y bit of the BO
+- field. */
+-#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | ((((unsigned long)(y)) & 1) << 21))
+-#define XLYLK_MASK (XL_MASK | Y_MASK)
+-
+-/* An XL form instruction which sets the BO field and the condition
+- bits of the BI field. */
+-#define XLOCB(op, bo, cb, xop, lk) \
+- (XLO ((op), (bo), (xop), (lk)) | ((((unsigned long)(cb)) & 3) << 16))
+-#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1)
+-
+-/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed. */
+-#define XLBB_MASK (XL_MASK | BB_MASK)
+-#define XLYBB_MASK (XLYLK_MASK | BB_MASK)
+-#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK)
+-
+-/* An XL_MASK with the BO and BB fields fixed. */
+-#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK)
+-
+-/* An XL_MASK with the BO, BI and BB fields fixed. */
+-#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK)
+-
+-/* An XO form instruction. */
+-#define XO(op, xop, oe, rc) \
+- (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1) | ((((unsigned long)(oe)) & 1) << 10) | (((unsigned long)(rc)) & 1))
+-#define XO_MASK XO (0x3f, 0x1ff, 1, 1)
+-
+-/* An XO_MASK with the RB field fixed. */
+-#define XORB_MASK (XO_MASK | RB_MASK)
+-
+-/* An XS form instruction. */
+-#define XS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 2) | (((unsigned long)(rc)) & 1))
+-#define XS_MASK XS (0x3f, 0x1ff, 1)
+-
+-/* A mask for the FXM version of an XFX form instruction. */
+-#define XFXFXM_MASK (X_MASK | (1 << 11))
+-
+-/* An XFX form instruction with the FXM field filled in. */
+-#define XFXM(op, xop, fxm) \
+- (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12))
+-
+-/* An XFX form instruction with the SPR field filled in. */
+-#define XSPR(op, xop, spr) \
+- (X ((op), (xop)) | ((((unsigned long)(spr)) & 0x1f) << 16) | ((((unsigned long)(spr)) & 0x3e0) << 6))
+-#define XSPR_MASK (X_MASK | SPR_MASK)
+-
+-/* An XFX form instruction with the SPR field filled in except for the
+- SPRBAT field. */
+-#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK)
+-
+-/* An XFX form instruction with the SPR field filled in except for the
+- SPRG field. */
+-#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK)
+-
+-/* An X form instruction with everything filled in except the E field. */
+-#define XE_MASK (0xffff7fff)
+-
+-/* An X form user context instruction. */
+-#define XUC(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f))
+-#define XUC_MASK XUC(0x3f, 0x1f)
+-
+-/* The BO encodings used in extended conditional branch mnemonics. */
+-#define BODNZF (0x0)
+-#define BODNZFP (0x1)
+-#define BODZF (0x2)
+-#define BODZFP (0x3)
+-#define BODNZT (0x8)
+-#define BODNZTP (0x9)
+-#define BODZT (0xa)
+-#define BODZTP (0xb)
+-
+-#define BOF (0x4)
+-#define BOFP (0x5)
+-#define BOFM4 (0x6)
+-#define BOFP4 (0x7)
+-#define BOT (0xc)
+-#define BOTP (0xd)
+-#define BOTM4 (0xe)
+-#define BOTP4 (0xf)
+-
+-#define BODNZ (0x10)
+-#define BODNZP (0x11)
+-#define BODZ (0x12)
+-#define BODZP (0x13)
+-#define BODNZM4 (0x18)
+-#define BODNZP4 (0x19)
+-#define BODZM4 (0x1a)
+-#define BODZP4 (0x1b)
+-
+-#define BOU (0x14)
+-
+-/* The BI condition bit encodings used in extended conditional branch
+- mnemonics. */
+-#define CBLT (0)
+-#define CBGT (1)
+-#define CBEQ (2)
+-#define CBSO (3)
+-
+-/* The TO encodings used in extended trap mnemonics. */
+-#define TOLGT (0x1)
+-#define TOLLT (0x2)
+-#define TOEQ (0x4)
+-#define TOLGE (0x5)
+-#define TOLNL (0x5)
+-#define TOLLE (0x6)
+-#define TOLNG (0x6)
+-#define TOGT (0x8)
+-#define TOGE (0xc)
+-#define TONL (0xc)
+-#define TOLT (0x10)
+-#define TOLE (0x14)
+-#define TONG (0x14)
+-#define TONE (0x18)
+-#define TOU (0x1f)
+-
+-/* Smaller names for the flags so each entry in the opcodes table will
+- fit on a single line. */
+-#undef PPC
+-#define PPC PPC_OPCODE_PPC
+-#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON
+-#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM
+-#define POWER4 PPC_OPCODE_POWER4
+-#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC
+-#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC
+-#define PPC403 PPC_OPCODE_403
+-#define PPC405 PPC403
+-#define PPC440 PPC_OPCODE_440
+-#define PPC750 PPC
+-#define PPC860 PPC
+-#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_PPC
+-#define POWER PPC_OPCODE_POWER
+-#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2
+-#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2
+-#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_32
+-#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON
+-#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_32
+-#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601
+-#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON
+-#define MFDEC1 PPC_OPCODE_POWER
+-#define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE
+-#define BOOKE PPC_OPCODE_BOOKE
+-#define BOOKE64 PPC_OPCODE_BOOKE64
+-#define CLASSIC PPC_OPCODE_CLASSIC
+-#define PPCSPE PPC_OPCODE_SPE
+-#define PPCISEL PPC_OPCODE_ISEL
+-#define PPCEFS PPC_OPCODE_EFS
+-#define PPCBRLK PPC_OPCODE_BRLOCK
+-#define PPCPMR PPC_OPCODE_PMR
+-#define PPCCHLK PPC_OPCODE_CACHELCK
+-#define PPCCHLK64 PPC_OPCODE_CACHELCK | PPC_OPCODE_BOOKE64
+-#define PPCRFMCI PPC_OPCODE_RFMCI
+-
+-/* The opcode table.
+-
+- The format of the opcode table is:
+-
+- NAME OPCODE MASK FLAGS { OPERANDS }
+-
+- NAME is the name of the instruction.
+- OPCODE is the instruction opcode.
+- MASK is the opcode mask; this is used to tell the disassembler
+- which bits in the actual opcode must match OPCODE.
+- FLAGS are flags indicated what processors support the instruction.
+- OPERANDS is the list of operands.
+-
+- The disassembler reads the table in order and prints the first
+- instruction which matches, so this table is sorted to put more
+- specific instructions before more general instructions. It is also
+- sorted by major opcode. */
+-
+-const struct powerpc_opcode powerpc_opcodes[] = {
+-{ "attn", X(0,256), X_MASK, POWER4, { 0 } },
+-{ "tdlgti", OPTO(2,TOLGT), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdllti", OPTO(2,TOLLT), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdeqi", OPTO(2,TOEQ), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdlgei", OPTO(2,TOLGE), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdlnli", OPTO(2,TOLNL), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdllei", OPTO(2,TOLLE), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdlngi", OPTO(2,TOLNG), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdgti", OPTO(2,TOGT), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdgei", OPTO(2,TOGE), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdnli", OPTO(2,TONL), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdlti", OPTO(2,TOLT), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdlei", OPTO(2,TOLE), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdngi", OPTO(2,TONG), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdnei", OPTO(2,TONE), OPTO_MASK, PPC64, { RA, SI } },
+-{ "tdi", OP(2), OP_MASK, PPC64, { TO, RA, SI } },
+-
+-{ "twlgti", OPTO(3,TOLGT), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tlgti", OPTO(3,TOLGT), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twllti", OPTO(3,TOLLT), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tllti", OPTO(3,TOLLT), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "tweqi", OPTO(3,TOEQ), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "teqi", OPTO(3,TOEQ), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twlgei", OPTO(3,TOLGE), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tlgei", OPTO(3,TOLGE), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twlnli", OPTO(3,TOLNL), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tlnli", OPTO(3,TOLNL), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twllei", OPTO(3,TOLLE), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tllei", OPTO(3,TOLLE), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twlngi", OPTO(3,TOLNG), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tlngi", OPTO(3,TOLNG), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twgti", OPTO(3,TOGT), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tgti", OPTO(3,TOGT), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twgei", OPTO(3,TOGE), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tgei", OPTO(3,TOGE), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twnli", OPTO(3,TONL), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tnli", OPTO(3,TONL), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twlti", OPTO(3,TOLT), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tlti", OPTO(3,TOLT), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twlei", OPTO(3,TOLE), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tlei", OPTO(3,TOLE), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twngi", OPTO(3,TONG), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tngi", OPTO(3,TONG), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twnei", OPTO(3,TONE), OPTO_MASK, PPCCOM, { RA, SI } },
+-{ "tnei", OPTO(3,TONE), OPTO_MASK, PWRCOM, { RA, SI } },
+-{ "twi", OP(3), OP_MASK, PPCCOM, { TO, RA, SI } },
+-{ "ti", OP(3), OP_MASK, PWRCOM, { TO, RA, SI } },
+-
+-{ "macchw", XO(4,172,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchw.", XO(4,172,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwo", XO(4,172,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwo.", XO(4,172,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchws", XO(4,236,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchws.", XO(4,236,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwso", XO(4,236,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwso.", XO(4,236,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwsu", XO(4,204,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwsu.", XO(4,204,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwsuo", XO(4,204,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwsuo.", XO(4,204,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwu", XO(4,140,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwu.", XO(4,140,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwuo", XO(4,140,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "macchwuo.", XO(4,140,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhw", XO(4,44,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhw.", XO(4,44,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwo", XO(4,44,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwo.", XO(4,44,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhws", XO(4,108,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhws.", XO(4,108,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwso", XO(4,108,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwso.", XO(4,108,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwsu", XO(4,76,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwsu.", XO(4,76,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwsuo", XO(4,76,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwsuo.", XO(4,76,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwu", XO(4,12,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwu.", XO(4,12,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwuo", XO(4,12,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "machhwuo.", XO(4,12,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhw", XO(4,428,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhw.", XO(4,428,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwo", XO(4,428,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwo.", XO(4,428,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhws", XO(4,492,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhws.", XO(4,492,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwso", XO(4,492,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwso.", XO(4,492,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwsu", XO(4,460,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwsu.", XO(4,460,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwsuo", XO(4,460,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwsuo.", XO(4,460,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwu", XO(4,396,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwu.", XO(4,396,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwuo", XO(4,396,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "maclhwuo.", XO(4,396,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulchw", XRC(4,168,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulchw.", XRC(4,168,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulchwu", XRC(4,136,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulchwu.", XRC(4,136,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulhhw", XRC(4,40,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulhhw.", XRC(4,40,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulhhwu", XRC(4,8,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mulhhwu.", XRC(4,8,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mullhw", XRC(4,424,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mullhw.", XRC(4,424,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mullhwu", XRC(4,392,0), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mullhwu.", XRC(4,392,1), X_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchw", XO(4,174,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchw.", XO(4,174,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchwo", XO(4,174,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchwo.", XO(4,174,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchws", XO(4,238,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchws.", XO(4,238,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchwso", XO(4,238,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmacchwso.", XO(4,238,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhw", XO(4,46,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhw.", XO(4,46,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhwo", XO(4,46,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhwo.", XO(4,46,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhws", XO(4,110,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhws.", XO(4,110,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhwso", XO(4,110,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmachhwso.", XO(4,110,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhw", XO(4,430,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhw.", XO(4,430,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhwo", XO(4,430,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhwo.", XO(4,430,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhws", XO(4,494,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhws.", XO(4,494,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhwso", XO(4,494,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
+-{ "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } },
+-{ "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } },
+-{ "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vaddshs", VX(4, 832), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vaddsws", VX(4, 896), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vaddubm", VX(4, 0), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vaddubs", VX(4, 512), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vadduhm", VX(4, 64), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vadduhs", VX(4, 576), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vadduwm", VX(4, 128), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vadduws", VX(4, 640), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vand", VX(4, 1028), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vandc", VX(4, 1092), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vavgsb", VX(4, 1282), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vavgsh", VX(4, 1346), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vavgsw", VX(4, 1410), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vavgub", VX(4, 1026), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vavguh", VX(4, 1090), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vavguw", VX(4, 1154), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcfsx", VX(4, 842), VX_MASK, PPCVEC, { VD, VB, UIMM } },
+-{ "vcfux", VX(4, 778), VX_MASK, PPCVEC, { VD, VB, UIMM } },
+-{ "vcmpbfp", VXR(4, 966, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpbfp.", VXR(4, 966, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpeqfp", VXR(4, 198, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpeqfp.", VXR(4, 198, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpequb", VXR(4, 6, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpequb.", VXR(4, 6, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpequh", VXR(4, 70, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpequh.", VXR(4, 70, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpequw", VXR(4, 134, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpequw.", VXR(4, 134, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgefp", VXR(4, 454, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgefp.", VXR(4, 454, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtfp", VXR(4, 710, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtfp.", VXR(4, 710, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtsb", VXR(4, 774, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtsb.", VXR(4, 774, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtsh", VXR(4, 838, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtsh.", VXR(4, 838, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtsw", VXR(4, 902, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtsw.", VXR(4, 902, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtub", VXR(4, 518, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtub.", VXR(4, 518, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtuh", VXR(4, 582, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtuh.", VXR(4, 582, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtuw", VXR(4, 646, 0), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vcmpgtuw.", VXR(4, 646, 1), VXR_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vctsxs", VX(4, 970), VX_MASK, PPCVEC, { VD, VB, UIMM } },
+-{ "vctuxs", VX(4, 906), VX_MASK, PPCVEC, { VD, VB, UIMM } },
+-{ "vexptefp", VX(4, 394), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vlogefp", VX(4, 458), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vmaddfp", VXA(4, 46), VXA_MASK, PPCVEC, { VD, VA, VC, VB } },
+-{ "vmaxfp", VX(4, 1034), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmaxsb", VX(4, 258), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmaxsh", VX(4, 322), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmaxsw", VX(4, 386), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmaxub", VX(4, 2), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmaxuh", VX(4, 66), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmaxuw", VX(4, 130), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmhaddshs", VXA(4, 32), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmhraddshs", VXA(4, 33), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vminfp", VX(4, 1098), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vminsb", VX(4, 770), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vminsh", VX(4, 834), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vminsw", VX(4, 898), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vminub", VX(4, 514), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vminuh", VX(4, 578), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vminuw", VX(4, 642), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmladduhm", VXA(4, 34), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmrghb", VX(4, 12), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmrghh", VX(4, 76), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmrghw", VX(4, 140), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmrglb", VX(4, 268), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmrglh", VX(4, 332), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmrglw", VX(4, 396), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmsummbm", VXA(4, 37), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmsumshm", VXA(4, 40), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmsumshs", VXA(4, 41), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmsumubm", VXA(4, 36), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmsumuhm", VXA(4, 38), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmsumuhs", VXA(4, 39), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vmulesb", VX(4, 776), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmulesh", VX(4, 840), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmuleub", VX(4, 520), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmuleuh", VX(4, 584), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmulosb", VX(4, 264), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmulosh", VX(4, 328), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmuloub", VX(4, 8), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vmulouh", VX(4, 72), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vnmsubfp", VXA(4, 47), VXA_MASK, PPCVEC, { VD, VA, VC, VB } },
+-{ "vnor", VX(4, 1284), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vor", VX(4, 1156), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vperm", VXA(4, 43), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vpkpx", VX(4, 782), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkshss", VX(4, 398), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkshus", VX(4, 270), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkswss", VX(4, 462), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkswus", VX(4, 334), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkuhum", VX(4, 14), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkuhus", VX(4, 142), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkuwum", VX(4, 78), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vpkuwus", VX(4, 206), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vrefp", VX(4, 266), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vrfim", VX(4, 714), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vrfin", VX(4, 522), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vrfip", VX(4, 650), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vrfiz", VX(4, 586), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vrlb", VX(4, 4), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vrlh", VX(4, 68), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vrlw", VX(4, 132), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vrsqrtefp", VX(4, 330), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vsel", VXA(4, 42), VXA_MASK, PPCVEC, { VD, VA, VB, VC } },
+-{ "vsl", VX(4, 452), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vslb", VX(4, 260), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsldoi", VXA(4, 44), VXA_MASK, PPCVEC, { VD, VA, VB, SHB } },
+-{ "vslh", VX(4, 324), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vslo", VX(4, 1036), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vslw", VX(4, 388), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vspltb", VX(4, 524), VX_MASK, PPCVEC, { VD, VB, UIMM } },
+-{ "vsplth", VX(4, 588), VX_MASK, PPCVEC, { VD, VB, UIMM } },
+-{ "vspltisb", VX(4, 780), VX_MASK, PPCVEC, { VD, SIMM } },
+-{ "vspltish", VX(4, 844), VX_MASK, PPCVEC, { VD, SIMM } },
+-{ "vspltisw", VX(4, 908), VX_MASK, PPCVEC, { VD, SIMM } },
+-{ "vspltw", VX(4, 652), VX_MASK, PPCVEC, { VD, VB, UIMM } },
+-{ "vsr", VX(4, 708), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsrab", VX(4, 772), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsrah", VX(4, 836), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsraw", VX(4, 900), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsrb", VX(4, 516), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsrh", VX(4, 580), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsro", VX(4, 1100), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsrw", VX(4, 644), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubcuw", VX(4, 1408), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubfp", VX(4, 74), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubsbs", VX(4, 1792), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubshs", VX(4, 1856), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubsws", VX(4, 1920), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsububm", VX(4, 1024), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsububs", VX(4, 1536), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubuhm", VX(4, 1088), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubuhs", VX(4, 1600), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubuwm", VX(4, 1152), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsubuws", VX(4, 1664), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsumsws", VX(4, 1928), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsum2sws", VX(4, 1672), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsum4sbs", VX(4, 1800), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsum4shs", VX(4, 1608), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vsum4ubs", VX(4, 1544), VX_MASK, PPCVEC, { VD, VA, VB } },
+-{ "vupkhpx", VX(4, 846), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vupkhsb", VX(4, 526), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vupkhsh", VX(4, 590), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vupklpx", VX(4, 974), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vupklsb", VX(4, 654), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vupklsh", VX(4, 718), VX_MASK, PPCVEC, { VD, VB } },
+-{ "vxor", VX(4, 1220), VX_MASK, PPCVEC, { VD, VA, VB } },
+-
+-{ "evaddw", VX(4, 512), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evaddiw", VX(4, 514), VX_MASK, PPCSPE, { RS, RB, UIMM } },
+-{ "evsubfw", VX(4, 516), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evsubw", VX(4, 516), VX_MASK, PPCSPE, { RS, RB, RA } },
+-{ "evsubifw", VX(4, 518), VX_MASK, PPCSPE, { RS, UIMM, RB } },
+-{ "evsubiw", VX(4, 518), VX_MASK, PPCSPE, { RS, RB, UIMM } },
+-{ "evabs", VX(4, 520), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evneg", VX(4, 521), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evextsb", VX(4, 522), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evextsh", VX(4, 523), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evrndw", VX(4, 524), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evcntlzw", VX(4, 525), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evcntlsw", VX(4, 526), VX_MASK, PPCSPE, { RS, RA } },
+-
+-{ "brinc", VX(4, 527), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evand", VX(4, 529), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evandc", VX(4, 530), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmr", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, BBA } },
+-{ "evor", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evorc", VX(4, 539), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evxor", VX(4, 534), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "eveqv", VX(4, 537), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evnand", VX(4, 542), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evnot", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, BBA } },
+-{ "evnor", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evrlw", VX(4, 552), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evrlwi", VX(4, 554), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
+-{ "evslw", VX(4, 548), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evslwi", VX(4, 550), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
+-{ "evsrws", VX(4, 545), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evsrwu", VX(4, 544), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evsrwis", VX(4, 547), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
+-{ "evsrwiu", VX(4, 546), VX_MASK, PPCSPE, { RS, RA, EVUIMM } },
+-{ "evsplati", VX(4, 553), VX_MASK, PPCSPE, { RS, SIMM } },
+-{ "evsplatfi", VX(4, 555), VX_MASK, PPCSPE, { RS, SIMM } },
+-{ "evmergehi", VX(4, 556), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmergelo", VX(4, 557), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmergehilo",VX(4,558), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmergelohi",VX(4,559), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evcmpgts", VX(4, 561), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evcmpgtu", VX(4, 560), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evcmplts", VX(4, 563), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evcmpltu", VX(4, 562), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evcmpeq", VX(4, 564), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evsel", EVSEL(4,79),EVSEL_MASK, PPCSPE, { RS, RA, RB, CRFS } },
+-
+-{ "evldd", VX(4, 769), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
+-{ "evlddx", VX(4, 768), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evldw", VX(4, 771), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
+-{ "evldwx", VX(4, 770), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evldh", VX(4, 773), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
+-{ "evldhx", VX(4, 772), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlwhe", VX(4, 785), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evlwhex", VX(4, 784), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlwhou", VX(4, 789), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evlwhoux", VX(4, 788), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlwhos", VX(4, 791), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evlwhosx", VX(4, 790), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlwwsplat",VX(4, 793), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evlwwsplatx",VX(4, 792), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlwhsplat",VX(4, 797), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evlwhsplatx",VX(4, 796), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlhhesplat",VX(4, 777), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } },
+-{ "evlhhesplatx",VX(4, 776), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlhhousplat",VX(4, 781), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } },
+-{ "evlhhousplatx",VX(4, 780), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evlhhossplat",VX(4, 783), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } },
+-{ "evlhhossplatx",VX(4, 782), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evstdd", VX(4, 801), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
+-{ "evstddx", VX(4, 800), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evstdw", VX(4, 803), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
+-{ "evstdwx", VX(4, 802), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evstdh", VX(4, 805), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } },
+-{ "evstdhx", VX(4, 804), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evstwwe", VX(4, 825), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evstwwex", VX(4, 824), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evstwwo", VX(4, 829), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evstwwox", VX(4, 828), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evstwhe", VX(4, 817), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evstwhex", VX(4, 816), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evstwho", VX(4, 821), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } },
+-{ "evstwhox", VX(4, 820), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evfsabs", VX(4, 644), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evfsnabs", VX(4, 645), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evfsneg", VX(4, 646), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evfsadd", VX(4, 640), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evfssub", VX(4, 641), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evfsmul", VX(4, 648), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evfsdiv", VX(4, 649), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evfscmpgt", VX(4, 652), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evfscmplt", VX(4, 653), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evfscmpeq", VX(4, 654), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evfststgt", VX(4, 668), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evfststlt", VX(4, 669), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evfststeq", VX(4, 670), VX_MASK, PPCSPE, { CRFD, RA, RB } },
+-{ "evfscfui", VX(4, 656), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfsctuiz", VX(4, 664), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfscfsi", VX(4, 657), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfscfuf", VX(4, 658), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfscfsf", VX(4, 659), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfsctui", VX(4, 660), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfsctsi", VX(4, 661), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfsctsiz", VX(4, 666), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfsctuf", VX(4, 662), VX_MASK, PPCSPE, { RS, RB } },
+-{ "evfsctsf", VX(4, 663), VX_MASK, PPCSPE, { RS, RB } },
+-
+-{ "efsabs", VX(4, 708), VX_MASK, PPCEFS, { RS, RA } },
+-{ "efsnabs", VX(4, 709), VX_MASK, PPCEFS, { RS, RA } },
+-{ "efsneg", VX(4, 710), VX_MASK, PPCEFS, { RS, RA } },
+-{ "efsadd", VX(4, 704), VX_MASK, PPCEFS, { RS, RA, RB } },
+-{ "efssub", VX(4, 705), VX_MASK, PPCEFS, { RS, RA, RB } },
+-{ "efsmul", VX(4, 712), VX_MASK, PPCEFS, { RS, RA, RB } },
+-{ "efsdiv", VX(4, 713), VX_MASK, PPCEFS, { RS, RA, RB } },
+-{ "efscmpgt", VX(4, 716), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+-{ "efscmplt", VX(4, 717), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+-{ "efscmpeq", VX(4, 718), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+-{ "efststgt", VX(4, 732), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+-{ "efststlt", VX(4, 733), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+-{ "efststeq", VX(4, 734), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+-{ "efscfui", VX(4, 720), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efsctuiz", VX(4, 728), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efscfsi", VX(4, 721), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efscfuf", VX(4, 722), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efscfsf", VX(4, 723), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efsctui", VX(4, 724), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efsctsi", VX(4, 725), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efsctsiz", VX(4, 730), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efsctuf", VX(4, 726), VX_MASK, PPCEFS, { RS, RB } },
+-{ "efsctsf", VX(4, 727), VX_MASK, PPCEFS, { RS, RB } },
+-
+-{ "evmhossf", VX(4, 1031), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhossfa", VX(4, 1063), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmf", VX(4, 1039), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmfa", VX(4, 1071), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmi", VX(4, 1037), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmia", VX(4, 1069), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhoumi", VX(4, 1036), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhoumia", VX(4, 1068), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhessf", VX(4, 1027), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhessfa", VX(4, 1059), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmf", VX(4, 1035), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmfa", VX(4, 1067), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmi", VX(4, 1033), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmia", VX(4, 1065), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmheumi", VX(4, 1032), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmheumia", VX(4, 1064), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmhossfaaw",VX(4, 1287), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhossiaaw",VX(4, 1285), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmfaaw",VX(4, 1295), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmiaaw",VX(4, 1293), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhousiaaw",VX(4, 1284), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhoumiaaw",VX(4, 1292), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhessfaaw",VX(4, 1283), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhessiaaw",VX(4, 1281), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmfaaw",VX(4, 1291), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmiaaw",VX(4, 1289), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmheusiaaw",VX(4, 1280), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmheumiaaw",VX(4, 1288), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmhossfanw",VX(4, 1415), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhossianw",VX(4, 1413), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmfanw",VX(4, 1423), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhosmianw",VX(4, 1421), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhousianw",VX(4, 1412), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhoumianw",VX(4, 1420), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhessfanw",VX(4, 1411), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhessianw",VX(4, 1409), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmfanw",VX(4, 1419), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhesmianw",VX(4, 1417), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmheusianw",VX(4, 1408), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmheumianw",VX(4, 1416), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmhogsmfaa",VX(4, 1327), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhogsmiaa",VX(4, 1325), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhogumiaa",VX(4, 1324), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhegsmfaa",VX(4, 1323), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhegsmiaa",VX(4, 1321), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhegumiaa",VX(4, 1320), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmhogsmfan",VX(4, 1455), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhogsmian",VX(4, 1453), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhogumian",VX(4, 1452), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhegsmfan",VX(4, 1451), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhegsmian",VX(4, 1449), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmhegumian",VX(4, 1448), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmwhssf", VX(4, 1095), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwhssfa", VX(4, 1127), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwhsmf", VX(4, 1103), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwhsmfa", VX(4, 1135), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwhsmi", VX(4, 1101), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwhsmia", VX(4, 1133), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwhumi", VX(4, 1100), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwhumia", VX(4, 1132), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmwlumi", VX(4, 1096), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwlumia", VX(4, 1128), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmwlssiaaw",VX(4, 1345), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwlsmiaaw",VX(4, 1353), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwlusiaaw",VX(4, 1344), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwlumiaaw",VX(4, 1352), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmwlssianw",VX(4, 1473), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwlsmianw",VX(4, 1481), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwlusianw",VX(4, 1472), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwlumianw",VX(4, 1480), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmwssf", VX(4, 1107), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwssfa", VX(4, 1139), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmf", VX(4, 1115), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmfa", VX(4, 1147), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmi", VX(4, 1113), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmia", VX(4, 1145), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwumi", VX(4, 1112), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwumia", VX(4, 1144), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmwssfaa", VX(4, 1363), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmfaa", VX(4, 1371), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmiaa", VX(4, 1369), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwumiaa", VX(4, 1368), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evmwssfan", VX(4, 1491), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmfan", VX(4, 1499), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwsmian", VX(4, 1497), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evmwumian", VX(4, 1496), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "evaddssiaaw",VX(4, 1217), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evaddsmiaaw",VX(4, 1225), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evaddusiaaw",VX(4, 1216), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evaddumiaaw",VX(4, 1224), VX_MASK, PPCSPE, { RS, RA } },
+-
+-{ "evsubfssiaaw",VX(4, 1219), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evsubfsmiaaw",VX(4, 1227), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evsubfusiaaw",VX(4, 1218), VX_MASK, PPCSPE, { RS, RA } },
+-{ "evsubfumiaaw",VX(4, 1226), VX_MASK, PPCSPE, { RS, RA } },
+-
+-{ "evmra", VX(4, 1220), VX_MASK, PPCSPE, { RS, RA } },
+-
+-{ "evdivws", VX(4, 1222), VX_MASK, PPCSPE, { RS, RA, RB } },
+-{ "evdivwu", VX(4, 1223), VX_MASK, PPCSPE, { RS, RA, RB } },
+-
+-{ "mulli", OP(7), OP_MASK, PPCCOM, { RT, RA, SI } },
+-{ "muli", OP(7), OP_MASK, PWRCOM, { RT, RA, SI } },
+-
+-{ "subfic", OP(8), OP_MASK, PPCCOM, { RT, RA, SI } },
+-{ "sfi", OP(8), OP_MASK, PWRCOM, { RT, RA, SI } },
+-
+-{ "dozi", OP(9), OP_MASK, M601, { RT, RA, SI } },
+-
+-{ "bce", B(9,0,0), B_MASK, BOOKE64, { BO, BI, BD } },
+-{ "bcel", B(9,0,1), B_MASK, BOOKE64, { BO, BI, BD } },
+-{ "bcea", B(9,1,0), B_MASK, BOOKE64, { BO, BI, BDA } },
+-{ "bcela", B(9,1,1), B_MASK, BOOKE64, { BO, BI, BDA } },
+-
+-{ "cmplwi", OPL(10,0), OPL_MASK, PPCCOM, { OBF, RA, UI } },
+-{ "cmpldi", OPL(10,1), OPL_MASK, PPC64, { OBF, RA, UI } },
+-{ "cmpli", OP(10), OP_MASK, PPC, { BF, L, RA, UI } },
+-{ "cmpli", OP(10), OP_MASK, PWRCOM, { BF, RA, UI } },
+-
+-{ "cmpwi", OPL(11,0), OPL_MASK, PPCCOM, { OBF, RA, SI } },
+-{ "cmpdi", OPL(11,1), OPL_MASK, PPC64, { OBF, RA, SI } },
+-{ "cmpi", OP(11), OP_MASK, PPC, { BF, L, RA, SI } },
+-{ "cmpi", OP(11), OP_MASK, PWRCOM, { BF, RA, SI } },
+-
+-{ "addic", OP(12), OP_MASK, PPCCOM, { RT, RA, SI } },
+-{ "ai", OP(12), OP_MASK, PWRCOM, { RT, RA, SI } },
+-{ "subic", OP(12), OP_MASK, PPCCOM, { RT, RA, NSI } },
+-
+-{ "addic.", OP(13), OP_MASK, PPCCOM, { RT, RA, SI } },
+-{ "ai.", OP(13), OP_MASK, PWRCOM, { RT, RA, SI } },
+-{ "subic.", OP(13), OP_MASK, PPCCOM, { RT, RA, NSI } },
+-
+-{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } },
+-{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } },
+-{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA, SI } },
+-{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA } },
+-{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA, NSI } },
+-{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA } },
+-
+-{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } },
+-{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } },
+-{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA,SISIGNOPT } },
+-{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA,SISIGNOPT } },
+-{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA, NSI } },
+-
+-{ "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } },
+-{ "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } },
+-{ "bdnz", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BD } },
+-{ "bdn", BBO(16,BODNZ,0,0), BBOATBI_MASK, PWRCOM, { BD } },
+-{ "bdnzl-", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } },
+-{ "bdnzl+", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } },
+-{ "bdnzl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BD } },
+-{ "bdnl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PWRCOM, { BD } },
+-{ "bdnza-", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } },
+-{ "bdnza+", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } },
+-{ "bdnza", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDA } },
+-{ "bdna", BBO(16,BODNZ,1,0), BBOATBI_MASK, PWRCOM, { BDA } },
+-{ "bdnzla-", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } },
+-{ "bdnzla+", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } },
+-{ "bdnzla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDA } },
+-{ "bdnla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PWRCOM, { BDA } },
+-{ "bdz-", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } },
+-{ "bdz+", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } },
+-{ "bdz", BBO(16,BODZ,0,0), BBOATBI_MASK, COM, { BD } },
+-{ "bdzl-", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } },
+-{ "bdzl+", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } },
+-{ "bdzl", BBO(16,BODZ,0,1), BBOATBI_MASK, COM, { BD } },
+-{ "bdza-", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } },
+-{ "bdza+", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } },
+-{ "bdza", BBO(16,BODZ,1,0), BBOATBI_MASK, COM, { BDA } },
+-{ "bdzla-", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } },
+-{ "bdzla+", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } },
+-{ "bdzla", BBO(16,BODZ,1,1), BBOATBI_MASK, COM, { BDA } },
+-{ "blt-", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "blt+", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "blt", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bltl-", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bltl+", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bltl", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "blta-", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "blta+", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "blta", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bltla-", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bltla+", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bltla", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bgt-", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bgt+", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bgt", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bgtl-", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bgtl+", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bgtl", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bgta-", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bgta+", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bgta", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bgtla-", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bgtla+", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bgtla", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "beq-", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "beq+", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "beq", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "beql-", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "beql+", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "beql", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "beqa-", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "beqa+", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "beqa", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "beqla-", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "beqla+", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "beqla", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bso-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bso+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bso", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bsol-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bsol+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bsol", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bsoa-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bsoa+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bsoa", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bsola-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bsola+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bsola", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bun-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bun+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bun", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } },
+-{ "bunl-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bunl+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bunl", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } },
+-{ "buna-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "buna+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "buna", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } },
+-{ "bunla-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bunla+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bunla", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } },
+-{ "bge-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bge+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bge", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bgel-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bgel+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bgel", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bgea-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bgea+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bgea", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bgela-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bgela+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bgela", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bnl-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bnl+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bnl", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bnll-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bnll+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bnll", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bnla-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnla+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnla", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bnlla-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnlla+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnlla", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "ble-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "ble+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "ble", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "blel-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "blel+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "blel", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "blea-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "blea+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "blea", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "blela-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "blela+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "blela", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bng-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bng+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bng", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bngl-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bngl+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bngl", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bnga-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnga+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnga", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bngla-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bngla+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bngla", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bne-", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bne+", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bne", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bnel-", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bnel+", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bnel", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bnea-", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnea+", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnea", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bnela-", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnela+", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnela", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bns-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bns+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bns", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bnsl-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bnsl+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bnsl", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } },
+-{ "bnsa-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnsa+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnsa", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bnsla-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnsla+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnsla", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } },
+-{ "bnu-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bnu+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bnu", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } },
+-{ "bnul-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } },
+-{ "bnul+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } },
+-{ "bnul", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } },
+-{ "bnua-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnua+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnua", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } },
+-{ "bnula-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } },
+-{ "bnula+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } },
+-{ "bnula", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } },
+-{ "bdnzt-", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdnzt+", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdnzt", BBO(16,BODNZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdnztl", BBO(16,BODNZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdnzta", BBO(16,BODNZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bdnzf-", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdnzf+", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdnzf", BBO(16,BODNZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdnzfl", BBO(16,BODNZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdnzfa", BBO(16,BODNZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bt-", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } },
+-{ "bt+", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } },
+-{ "bt", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BD } },
+-{ "bbt", BBO(16,BOT,0,0), BBOAT_MASK, PWRCOM, { BI, BD } },
+-{ "btl-", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } },
+-{ "btl+", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } },
+-{ "btl", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BD } },
+-{ "bbtl", BBO(16,BOT,0,1), BBOAT_MASK, PWRCOM, { BI, BD } },
+-{ "bta-", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } },
+-{ "bta+", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } },
+-{ "bta", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } },
+-{ "bbta", BBO(16,BOT,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } },
+-{ "btla-", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } },
+-{ "btla+", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } },
+-{ "btla", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } },
+-{ "bbtla", BBO(16,BOT,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } },
+-{ "bf-", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } },
+-{ "bf+", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } },
+-{ "bf", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BD } },
+-{ "bbf", BBO(16,BOF,0,0), BBOAT_MASK, PWRCOM, { BI, BD } },
+-{ "bfl-", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } },
+-{ "bfl+", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } },
+-{ "bfl", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BD } },
+-{ "bbfl", BBO(16,BOF,0,1), BBOAT_MASK, PWRCOM, { BI, BD } },
+-{ "bfa-", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } },
+-{ "bfa+", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } },
+-{ "bfa", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } },
+-{ "bbfa", BBO(16,BOF,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } },
+-{ "bfla-", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } },
+-{ "bfla+", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } },
+-{ "bfla", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } },
+-{ "bbfla", BBO(16,BOF,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } },
+-{ "bdzt-", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdzt+", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdzt", BBO(16,BODZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdztl-", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdztl+", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdztl", BBO(16,BODZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdzta-", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdzta+", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdzta", BBO(16,BODZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdztla", BBO(16,BODZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bdzf-", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdzf+", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdzf", BBO(16,BODZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdzfl-", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } },
+-{ "bdzfl+", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } },
+-{ "bdzfl", BBO(16,BODZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } },
+-{ "bdzfa-", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdzfa+", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdzfa", BBO(16,BODZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } },
+-{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } },
+-{ "bdzfla", BBO(16,BODZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } },
+-{ "bc-", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDM } },
+-{ "bc+", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDP } },
+-{ "bc", B(16,0,0), B_MASK, COM, { BO, BI, BD } },
+-{ "bcl-", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDM } },
+-{ "bcl+", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDP } },
+-{ "bcl", B(16,0,1), B_MASK, COM, { BO, BI, BD } },
+-{ "bca-", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDMA } },
+-{ "bca+", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDPA } },
+-{ "bca", B(16,1,0), B_MASK, COM, { BO, BI, BDA } },
+-{ "bcla-", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDMA } },
+-{ "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } },
+-{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } },
+-
+-{ "sc", SC(17,1,0), 0xffffffff, PPC, { 0 } },
+-{ "svc", SC(17,0,0), SC_MASK, POWER, { LEV, FL1, FL2 } },
+-{ "svcl", SC(17,0,1), SC_MASK, POWER, { LEV, FL1, FL2 } },
+-{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } },
+-{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } },
+-
+-{ "b", B(18,0,0), B_MASK, COM, { LI } },
+-{ "bl", B(18,0,1), B_MASK, COM, { LI } },
+-{ "ba", B(18,1,0), B_MASK, COM, { LIA } },
+-{ "bla", B(18,1,1), B_MASK, COM, { LIA } },
+-
+-{ "mcrf", XL(19,0), XLBB_MASK|(3 << 21)|(3 << 16), COM, { BF, BFA } },
+-
+-{ "blr", XLO(19,BOU,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } },
+-{ "br", XLO(19,BOU,16,0), XLBOBIBB_MASK, PWRCOM, { 0 } },
+-{ "blrl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } },
+-{ "brl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PWRCOM, { 0 } },
+-{ "bdnzlr", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } },
+-{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdnzlr-", XLO(19,BODNZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdnzlr+", XLO(19,BODNZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } },
+-{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdnzlrl-",XLO(19,BODNZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdnzlrl+",XLO(19,BODNZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bdzlr", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } },
+-{ "bdzlr-", XLO(19,BODZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdzlr-", XLO(19,BODZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bdzlr+", XLO(19,BODZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdzlr+", XLO(19,BODZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bdzlrl", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } },
+-{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdzlrl-", XLO(19,BODZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } },
+-{ "bdzlrl+", XLO(19,BODZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } },
+-{ "bltlr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bltlr-", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltlr-", XLOCB(19,BOTM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bltlr+", XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltlr+", XLOCB(19,BOTP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bltr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bltlrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltlrl-", XLOCB(19,BOTM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltlrl+", XLOCB(19,BOTP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bltrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bgtlr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgtlr-", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtlr-", XLOCB(19,BOTM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtlr+", XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtlr+", XLOCB(19,BOTP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bgtlrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtlrl-", XLOCB(19,BOTM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtlrl+", XLOCB(19,BOTP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "beqlr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "beqlr-", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqlr-", XLOCB(19,BOTM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqlr+", XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqlr+", XLOCB(19,BOTP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "beqlrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqlrl-", XLOCB(19,BOTM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqlrl+", XLOCB(19,BOTP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bsolr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bsolr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsolr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsolr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsolr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsor", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bsolrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsolrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsolrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsorl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bunlr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bunlr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunlr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bunlr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunlr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bunlrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunlrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunlrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgelr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgelr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgelr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgelr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgelr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bger", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bgelrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgelrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgelrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgerl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnllr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnllr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnllr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnllr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnllr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnlr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnllrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnllrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnllrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnlrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "blelr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "blelr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blelr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "blelr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blelr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bler", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "blelrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blelrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blelrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "blerl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnglr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnglr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnglr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnglr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnglr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bngr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnglrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnglrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnglrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bngrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnelr", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnelr-", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnelr-", XLOCB(19,BOFM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnelr+", XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnelr+", XLOCB(19,BOFP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bner", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnelrl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnelrl-", XLOCB(19,BOFM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnelrl+", XLOCB(19,BOFP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnerl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnslr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnslr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnslr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnslr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnslr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnsr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnslrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnslrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnslrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnsrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } },
+-{ "bnulr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnulr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnulr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnulr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnulr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnulrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnulrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnulrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "btlr", XLO(19,BOT,16,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "btlr-", XLO(19,BOT,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btlr-", XLO(19,BOTM4,16,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "btlr+", XLO(19,BOTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btlr+", XLO(19,BOTP4,16,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "bbtr", XLO(19,BOT,16,0), XLBOBB_MASK, PWRCOM, { BI } },
+-{ "btlrl", XLO(19,BOT,16,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "btlrl-", XLO(19,BOT,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btlrl-", XLO(19,BOTM4,16,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "btlrl+", XLO(19,BOTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btlrl+", XLO(19,BOTP4,16,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "bbtrl", XLO(19,BOT,16,1), XLBOBB_MASK, PWRCOM, { BI } },
+-{ "bflr", XLO(19,BOF,16,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bflr-", XLO(19,BOF,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bflr-", XLO(19,BOFM4,16,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "bflr+", XLO(19,BOFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bflr+", XLO(19,BOFP4,16,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "bbfr", XLO(19,BOF,16,0), XLBOBB_MASK, PWRCOM, { BI } },
+-{ "bflrl", XLO(19,BOF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bflrl-", XLO(19,BOF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bflrl-", XLO(19,BOFM4,16,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "bflrl+", XLO(19,BOFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bflrl+", XLO(19,BOFP4,16,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "bbfrl", XLO(19,BOF,16,1), XLBOBB_MASK, PWRCOM, { BI } },
+-{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdztlr", XLO(19,BODZT,16,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdzflr", XLO(19,BODZF,16,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bclr", XLLK(19,16,0), XLYBB_MASK, PPCCOM, { BO, BI } },
+-{ "bclrl", XLLK(19,16,1), XLYBB_MASK, PPCCOM, { BO, BI } },
+-{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } },
+-{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } },
+-{ "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } },
+-{ "bclrel", XLLK(19,17,1), XLBB_MASK, BOOKE64, { BO, BI } },
+-
+-{ "rfid", XL(19,18), 0xffffffff, PPC64, { 0 } },
+-
+-{ "crnot", XL(19,33), XL_MASK, PPCCOM, { BT, BA, BBA } },
+-{ "crnor", XL(19,33), XL_MASK, COM, { BT, BA, BB } },
+-{ "rfmci", X(19,38), 0xffffffff, PPCRFMCI, { 0 } },
+-
+-{ "rfi", XL(19,50), 0xffffffff, COM, { 0 } },
+-{ "rfci", XL(19,51), 0xffffffff, PPC403 | BOOKE, { 0 } },
+-
+-{ "rfsvc", XL(19,82), 0xffffffff, POWER, { 0 } },
+-
+-{ "crandc", XL(19,129), XL_MASK, COM, { BT, BA, BB } },
+-
+-{ "isync", XL(19,150), 0xffffffff, PPCCOM, { 0 } },
+-{ "ics", XL(19,150), 0xffffffff, PWRCOM, { 0 } },
+-
+-{ "crclr", XL(19,193), XL_MASK, PPCCOM, { BT, BAT, BBA } },
+-{ "crxor", XL(19,193), XL_MASK, COM, { BT, BA, BB } },
+-
+-{ "crnand", XL(19,225), XL_MASK, COM, { BT, BA, BB } },
+-
+-{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } },
+-
+-{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } },
+-{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } },
+-
+-{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } },
+-
+-{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } },
+-{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } },
+-
+-{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } },
+-{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } },
+-{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltctr-", XLOCB(19,BOTM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltctr+", XLOCB(19,BOTP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltctrl-",XLOCB(19,BOTM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bltctrl+",XLOCB(19,BOTP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtctr", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtctr-", XLOCB(19,BOTM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtctr+", XLOCB(19,BOTP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtctrl-",XLOCB(19,BOTM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgtctrl+",XLOCB(19,BOTP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqctr", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqctr-", XLOCB(19,BOTM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqctr+", XLOCB(19,BOTP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqctrl-",XLOCB(19,BOTM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "beqctrl+",XLOCB(19,BOTP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsoctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsoctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsoctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsoctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bsoctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bunctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bunctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgectr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgectr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgectr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgectrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bgectrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnlctr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnlctr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnlctr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnlctrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnlctrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "blectr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blectr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blectr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blectrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "blectrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bngctr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bngctr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bngctr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bngctrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bngctrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnectr", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnectr-", XLOCB(19,BOFM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnectr+", XLOCB(19,BOFP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnectrl-",XLOCB(19,BOFM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnectrl+",XLOCB(19,BOFP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnsctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnsctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnsctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnsctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnsctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnuctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnuctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnuctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } },
+-{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnuctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } },
+-{ "bnuctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } },
+-{ "btctr", XLO(19,BOT,528,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "btctr-", XLO(19,BOT,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btctr-", XLO(19,BOTM4,528,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "btctr+", XLO(19,BOTP,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btctr+", XLO(19,BOTP4,528,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "btctrl", XLO(19,BOT,528,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btctrl-", XLO(19,BOTM4,528,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "btctrl+", XLO(19,BOTP4,528,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "bfctr", XLO(19,BOF,528,0), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bfctr-", XLO(19,BOF,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bfctr-", XLO(19,BOFM4,528,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "bfctr+", XLO(19,BOFP,528,0), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bfctr+", XLO(19,BOFP4,528,0), XLBOBB_MASK, POWER4, { BI } },
+-{ "bfctrl", XLO(19,BOF,528,1), XLBOBB_MASK, PPCCOM, { BI } },
+-{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
+-{ "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } },
+-{ "bcctr", XLLK(19,528,0), XLYBB_MASK, PPCCOM, { BO, BI } },
+-{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bcctrl", XLLK(19,528,1), XLYBB_MASK, PPCCOM, { BO, BI } },
+-{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
+-{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } },
+-{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } },
+-{ "bcctre", XLLK(19,529,0), XLYBB_MASK, BOOKE64, { BO, BI } },
+-{ "bcctrel", XLLK(19,529,1), XLYBB_MASK, BOOKE64, { BO, BI } },
+-
+-{ "rlwimi", M(20,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
+-{ "rlimi", M(20,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
+-
+-{ "rlwimi.", M(20,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
+-{ "rlimi.", M(20,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
+-
+-{ "rotlwi", MME(21,31,0), MMBME_MASK, PPCCOM, { RA, RS, SH } },
+-{ "clrlwi", MME(21,31,0), MSHME_MASK, PPCCOM, { RA, RS, MB } },
+-{ "rlwinm", M(21,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
+-{ "rlinm", M(21,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
+-{ "rotlwi.", MME(21,31,1), MMBME_MASK, PPCCOM, { RA,RS,SH } },
+-{ "clrlwi.", MME(21,31,1), MSHME_MASK, PPCCOM, { RA, RS, MB } },
+-{ "rlwinm.", M(21,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } },
+-{ "rlinm.", M(21,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } },
+-
+-{ "rlmi", M(22,0), M_MASK, M601, { RA,RS,RB,MBE,ME } },
+-{ "rlmi.", M(22,1), M_MASK, M601, { RA,RS,RB,MBE,ME } },
+-
+-{ "be", B(22,0,0), B_MASK, BOOKE64, { LI } },
+-{ "bel", B(22,0,1), B_MASK, BOOKE64, { LI } },
+-{ "bea", B(22,1,0), B_MASK, BOOKE64, { LIA } },
+-{ "bela", B(22,1,1), B_MASK, BOOKE64, { LIA } },
+-
+-{ "rotlw", MME(23,31,0), MMBME_MASK, PPCCOM, { RA, RS, RB } },
+-{ "rlwnm", M(23,0), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } },
+-{ "rlnm", M(23,0), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } },
+-{ "rotlw.", MME(23,31,1), MMBME_MASK, PPCCOM, { RA, RS, RB } },
+-{ "rlwnm.", M(23,1), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } },
+-{ "rlnm.", M(23,1), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } },
+-
+-{ "nop", OP(24), 0xffffffff, PPCCOM, { 0 } },
+-{ "ori", OP(24), OP_MASK, PPCCOM, { RA, RS, UI } },
+-{ "oril", OP(24), OP_MASK, PWRCOM, { RA, RS, UI } },
+-
+-{ "oris", OP(25), OP_MASK, PPCCOM, { RA, RS, UI } },
+-{ "oriu", OP(25), OP_MASK, PWRCOM, { RA, RS, UI } },
+-
+-{ "xori", OP(26), OP_MASK, PPCCOM, { RA, RS, UI } },
+-{ "xoril", OP(26), OP_MASK, PWRCOM, { RA, RS, UI } },
+-
+-{ "xoris", OP(27), OP_MASK, PPCCOM, { RA, RS, UI } },
+-{ "xoriu", OP(27), OP_MASK, PWRCOM, { RA, RS, UI } },
+-
+-{ "andi.", OP(28), OP_MASK, PPCCOM, { RA, RS, UI } },
+-{ "andil.", OP(28), OP_MASK, PWRCOM, { RA, RS, UI } },
+-
+-{ "andis.", OP(29), OP_MASK, PPCCOM, { RA, RS, UI } },
+-{ "andiu.", OP(29), OP_MASK, PWRCOM, { RA, RS, UI } },
+-
+-{ "rotldi", MD(30,0,0), MDMB_MASK, PPC64, { RA, RS, SH6 } },
+-{ "clrldi", MD(30,0,0), MDSH_MASK, PPC64, { RA, RS, MB6 } },
+-{ "rldicl", MD(30,0,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
+-{ "rotldi.", MD(30,0,1), MDMB_MASK, PPC64, { RA, RS, SH6 } },
+-{ "clrldi.", MD(30,0,1), MDSH_MASK, PPC64, { RA, RS, MB6 } },
+-{ "rldicl.", MD(30,0,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
+-
+-{ "rldicr", MD(30,1,0), MD_MASK, PPC64, { RA, RS, SH6, ME6 } },
+-{ "rldicr.", MD(30,1,1), MD_MASK, PPC64, { RA, RS, SH6, ME6 } },
+-
+-{ "rldic", MD(30,2,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
+-{ "rldic.", MD(30,2,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
+-
+-{ "rldimi", MD(30,3,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
+-{ "rldimi.", MD(30,3,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } },
+-
+-{ "rotld", MDS(30,8,0), MDSMB_MASK, PPC64, { RA, RS, RB } },
+-{ "rldcl", MDS(30,8,0), MDS_MASK, PPC64, { RA, RS, RB, MB6 } },
+-{ "rotld.", MDS(30,8,1), MDSMB_MASK, PPC64, { RA, RS, RB } },
+-{ "rldcl.", MDS(30,8,1), MDS_MASK, PPC64, { RA, RS, RB, MB6 } },
+-
+-{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
+-{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
+-
+-{ "cmpw", XCMPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
+-{ "cmpd", XCMPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
+-{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } },
+-{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
+-
+-{ "twlgt", XTO(31,4,TOLGT), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tlgt", XTO(31,4,TOLGT), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twllt", XTO(31,4,TOLLT), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tllt", XTO(31,4,TOLLT), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "tweq", XTO(31,4,TOEQ), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "teq", XTO(31,4,TOEQ), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twlge", XTO(31,4,TOLGE), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tlge", XTO(31,4,TOLGE), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twlnl", XTO(31,4,TOLNL), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tlnl", XTO(31,4,TOLNL), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twlle", XTO(31,4,TOLLE), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tlle", XTO(31,4,TOLLE), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twlng", XTO(31,4,TOLNG), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tlng", XTO(31,4,TOLNG), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twgt", XTO(31,4,TOGT), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tgt", XTO(31,4,TOGT), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twge", XTO(31,4,TOGE), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tge", XTO(31,4,TOGE), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twnl", XTO(31,4,TONL), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tnl", XTO(31,4,TONL), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twlt", XTO(31,4,TOLT), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tlt", XTO(31,4,TOLT), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twle", XTO(31,4,TOLE), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tle", XTO(31,4,TOLE), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twng", XTO(31,4,TONG), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tng", XTO(31,4,TONG), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "twne", XTO(31,4,TONE), XTO_MASK, PPCCOM, { RA, RB } },
+-{ "tne", XTO(31,4,TONE), XTO_MASK, PWRCOM, { RA, RB } },
+-{ "trap", XTO(31,4,TOU), 0xffffffff, PPCCOM, { 0 } },
+-{ "tw", X(31,4), X_MASK, PPCCOM, { TO, RA, RB } },
+-{ "t", X(31,4), X_MASK, PWRCOM, { TO, RA, RB } },
+-
+-{ "subfc", XO(31,8,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sf", XO(31,8,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "subc", XO(31,8,0,0), XO_MASK, PPC, { RT, RB, RA } },
+-{ "subfc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sf.", XO(31,8,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "subc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RB, RA } },
+-{ "subfco", XO(31,8,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sfo", XO(31,8,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "subco", XO(31,8,1,0), XO_MASK, PPC, { RT, RB, RA } },
+-{ "subfco.", XO(31,8,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sfo.", XO(31,8,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "subco.", XO(31,8,1,1), XO_MASK, PPC, { RT, RB, RA } },
+-
+-{ "mulhdu", XO(31,9,0,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "mulhdu.", XO(31,9,0,1), XO_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "addc", XO(31,10,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "a", XO(31,10,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "addc.", XO(31,10,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "a.", XO(31,10,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "addco", XO(31,10,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "ao", XO(31,10,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "addco.", XO(31,10,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "ao.", XO(31,10,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "mulhwu", XO(31,11,0,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "mulhwu.", XO(31,11,0,1), XO_MASK, PPC, { RT, RA, RB } },
+-
+-{ "isellt", X(31,15), X_MASK, PPCISEL, { RT, RA, RB } },
+-{ "iselgt", X(31,47), X_MASK, PPCISEL, { RT, RA, RB } },
+-{ "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } },
+-{ "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } },
+-
+-{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4, { RT } },
+-{ "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } },
+-
+-{ "lwarx", X(31,20), X_MASK, PPC, { RT, RA, RB } },
+-
+-{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "icbt", X(31,22), X_MASK, BOOKE, { CT, RA, RB } },
+-{ "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } },
+-
+-{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA, RB } },
+-{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } },
+-{ "sl", XRC(31,24,0), X_MASK, PWRCOM, { RA, RS, RB } },
+-{ "slw.", XRC(31,24,1), X_MASK, PPCCOM, { RA, RS, RB } },
+-{ "sl.", XRC(31,24,1), X_MASK, PWRCOM, { RA, RS, RB } },
+-
+-{ "cntlzw", XRC(31,26,0), XRB_MASK, PPCCOM, { RA, RS } },
+-{ "cntlz", XRC(31,26,0), XRB_MASK, PWRCOM, { RA, RS } },
+-{ "cntlzw.", XRC(31,26,1), XRB_MASK, PPCCOM, { RA, RS } },
+-{ "cntlz.", XRC(31,26,1), XRB_MASK, PWRCOM, { RA, RS } },
+-
+-{ "sld", XRC(31,27,0), X_MASK, PPC64, { RA, RS, RB } },
+-{ "sld.", XRC(31,27,1), X_MASK, PPC64, { RA, RS, RB } },
+-
+-{ "and", XRC(31,28,0), X_MASK, COM, { RA, RS, RB } },
+-{ "and.", XRC(31,28,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "maskg", XRC(31,29,0), X_MASK, M601, { RA, RS, RB } },
+-{ "maskg.", XRC(31,29,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } },
+-
+-{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "cmplw", XCMPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
+-{ "cmpld", XCMPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
+-{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } },
+-{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
+-
+-{ "subf", XO(31,40,0,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "sub", XO(31,40,0,0), XO_MASK, PPC, { RT, RB, RA } },
+-{ "subf.", XO(31,40,0,1), XO_MASK, PPC, { RT, RA, RB } },
+-{ "sub.", XO(31,40,0,1), XO_MASK, PPC, { RT, RB, RA } },
+-{ "subfo", XO(31,40,1,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "subo", XO(31,40,1,0), XO_MASK, PPC, { RT, RB, RA } },
+-{ "subfo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RA, RB } },
+-{ "subo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RB, RA } },
+-
+-{ "ldux", X(31,53), X_MASK, PPC64, { RT, RAL, RB } },
+-
+-{ "dcbst", X(31,54), XRT_MASK, PPC, { RA, RB } },
+-
+-{ "lwzux", X(31,55), X_MASK, PPCCOM, { RT, RAL, RB } },
+-{ "lux", X(31,55), X_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "dcbste", X(31,62), XRT_MASK, BOOKE64, { RA, RB } },
+-
+-{ "lwzuxe", X(31,63), X_MASK, BOOKE64, { RT, RAL, RB } },
+-
+-{ "cntlzd", XRC(31,58,0), XRB_MASK, PPC64, { RA, RS } },
+-{ "cntlzd.", XRC(31,58,1), XRB_MASK, PPC64, { RA, RS } },
+-
+-{ "andc", XRC(31,60,0), X_MASK, COM, { RA, RS, RB } },
+-{ "andc.", XRC(31,60,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "tdlgt", XTO(31,68,TOLGT), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdllt", XTO(31,68,TOLLT), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdeq", XTO(31,68,TOEQ), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdlge", XTO(31,68,TOLGE), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdlnl", XTO(31,68,TOLNL), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdlle", XTO(31,68,TOLLE), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdlng", XTO(31,68,TOLNG), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdgt", XTO(31,68,TOGT), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdge", XTO(31,68,TOGE), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdnl", XTO(31,68,TONL), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdlt", XTO(31,68,TOLT), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdle", XTO(31,68,TOLE), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdng", XTO(31,68,TONG), XTO_MASK, PPC64, { RA, RB } },
+-{ "tdne", XTO(31,68,TONE), XTO_MASK, PPC64, { RA, RB } },
+-{ "td", X(31,68), X_MASK, PPC64, { TO, RA, RB } },
+-
+-{ "mulhd", XO(31,73,0,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "mulhd.", XO(31,73,0,1), XO_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "mulhw", XO(31,75,0,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "mulhw.", XO(31,75,0,1), XO_MASK, PPC, { RT, RA, RB } },
+-
+-{ "dlmzb", XRC(31,78,0), X_MASK, PPC403|PPC440, { RA, RS, RB } },
+-{ "dlmzb.", XRC(31,78,1), X_MASK, PPC403|PPC440, { RA, RS, RB } },
+-
+-{ "mtsrd", X(31,82), XRB_MASK|(1<<20), PPC64, { SR, RS } },
+-
+-{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } },
+-
+-{ "ldarx", X(31,84), X_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "dcbf", X(31,86), XRT_MASK, PPC, { RA, RB } },
+-
+-{ "lbzx", X(31,87), X_MASK, COM, { RT, RA, RB } },
+-
+-{ "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } },
+-
+-{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } },
+-{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } },
+-{ "nego", XO(31,104,1,0), XORB_MASK, COM, { RT, RA } },
+-{ "nego.", XO(31,104,1,1), XORB_MASK, COM, { RT, RA } },
+-
+-{ "mul", XO(31,107,0,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "mul.", XO(31,107,0,1), XO_MASK, M601, { RT, RA, RB } },
+-{ "mulo", XO(31,107,1,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "mulo.", XO(31,107,1,1), XO_MASK, M601, { RT, RA, RB } },
+-
+-{ "mtsrdin", X(31,114), XRA_MASK, PPC64, { RS, RB } },
+-
+-{ "clf", X(31,118), XTO_MASK, POWER, { RA, RB } },
+-
+-{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } },
+-
+-{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } },
+-{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } },
+-{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } },
+-{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } },
+-
+-{ "wrtee", X(31,131), XRARB_MASK, PPC403 | BOOKE, { RS } },
+-
+-{ "dcbtstls",X(31,134), X_MASK, PPCCHLK, { CT, RA, RB }},
+-
+-{ "subfe", XO(31,136,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sfe", XO(31,136,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "subfe.", XO(31,136,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sfe.", XO(31,136,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "subfeo", XO(31,136,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sfeo", XO(31,136,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "subfeo.", XO(31,136,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "sfeo.", XO(31,136,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "adde", XO(31,138,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "ae", XO(31,138,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "adde.", XO(31,138,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "ae.", XO(31,138,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "addeo", XO(31,138,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "aeo", XO(31,138,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "addeo.", XO(31,138,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "aeo.", XO(31,138,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }},
+-
+-{ "mtcr", XFXM(31,144,0xff), XRARB_MASK, COM, { RS }},
+-{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } },
+-
+-{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } },
+-
+-{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA, RB } },
+-
+-{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA, RB } },
+-
+-{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA, RB } },
+-{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } },
+-
+-{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } },
+-{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } },
+-{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } },
+-
+-{ "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }},
+-{ "dcbtlse", X(31,174), X_MASK, PPCCHLK64, { CT, RA, RB }},
+-
+-{ "mtmsrd", X(31,178), XRLARB_MASK, PPC64, { RS, MTMSRD_L } },
+-
+-{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } },
+-
+-{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } },
+-{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA, RB } },
+-
+-{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } },
+-{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } },
+-
+-{ "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } },
+-
+-{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfze", XO(31,200,0,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "subfze.", XO(31,200,0,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfze.", XO(31,200,0,1), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfzeo", XO(31,200,1,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfzeo.", XO(31,200,1,1), XORB_MASK, PWRCOM, { RT, RA } },
+-
+-{ "addze", XO(31,202,0,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "aze", XO(31,202,0,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "addze.", XO(31,202,0,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "aze.", XO(31,202,0,1), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "addzeo", XO(31,202,1,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "azeo", XO(31,202,1,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "azeo.", XO(31,202,1,1), XORB_MASK, PWRCOM, { RT, RA } },
+-
+-{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } },
+-
+-{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA, RB } },
+-
+-{ "stbx", X(31,215), X_MASK, COM, { RS, RA, RB } },
+-
+-{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } },
+-{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } },
+-{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }},
+-
+-{ "subfme", XO(31,232,0,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfme", XO(31,232,0,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "subfme.", XO(31,232,0,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfme.", XO(31,232,0,1), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfmeo", XO(31,232,1,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "sfmeo.", XO(31,232,1,1), XORB_MASK, PWRCOM, { RT, RA } },
+-
+-{ "mulld", XO(31,233,0,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "mulld.", XO(31,233,0,1), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "mulldo", XO(31,233,1,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "mulldo.", XO(31,233,1,1), XO_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "addme", XO(31,234,0,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "ame", XO(31,234,0,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "addme.", XO(31,234,0,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "ame.", XO(31,234,0,1), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "addmeo", XO(31,234,1,0), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "ameo", XO(31,234,1,0), XORB_MASK, PWRCOM, { RT, RA } },
+-{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPCCOM, { RT, RA } },
+-{ "ameo.", XO(31,234,1,1), XORB_MASK, PWRCOM, { RT, RA } },
+-
+-{ "mullw", XO(31,235,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "muls", XO(31,235,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "mullw.", XO(31,235,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "muls.", XO(31,235,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "mullwo", XO(31,235,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "mulso", XO(31,235,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "mullwo.", XO(31,235,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "mulso.", XO(31,235,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "icblce", X(31,238), X_MASK, PPCCHLK64, { CT, RA, RB }},
+-{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } },
+-{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } },
+-
+-{ "dcbtst", X(31,246), XRT_MASK, PPC, { CT, RA, RB } },
+-
+-{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } },
+-
+-{ "slliq", XRC(31,248,0), X_MASK, M601, { RA, RS, SH } },
+-{ "slliq.", XRC(31,248,1), X_MASK, M601, { RA, RS, SH } },
+-
+-{ "dcbtste", X(31,253), X_MASK, BOOKE64, { CT, RA, RB } },
+-
+-{ "stbuxe", X(31,255), X_MASK, BOOKE64, { RS, RAS, RB } },
+-
+-{ "mfdcrx", X(31,259), X_MASK, BOOKE, { RS, RA } },
+-
+-{ "doz", XO(31,264,0,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "doz.", XO(31,264,0,1), XO_MASK, M601, { RT, RA, RB } },
+-{ "dozo", XO(31,264,1,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "dozo.", XO(31,264,1,1), XO_MASK, M601, { RT, RA, RB } },
+-
+-{ "add", XO(31,266,0,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "cax", XO(31,266,0,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "add.", XO(31,266,0,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "cax.", XO(31,266,0,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "addo", XO(31,266,1,0), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "caxo", XO(31,266,1,0), XO_MASK, PWRCOM, { RT, RA, RB } },
+-{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
+-{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "tlbiel", X(31,274), XRTRA_MASK, POWER4, { RB } },
+-
+-{ "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } },
+-
+-{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } },
+-{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } },
+-
+-{ "dcbt", X(31,278), XRT_MASK, PPC, { CT, RA, RB } },
+-
+-{ "lhzx", X(31,279), X_MASK, COM, { RT, RA, RB } },
+-
+-{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } },
+-{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } },
+-
+-{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } },
+-{ "tlbi", X(31,306), XRT_MASK, POWER, { RA, RB } },
+-
+-{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } },
+-
+-{ "lhzux", X(31,311), X_MASK, COM, { RT, RAL, RB } },
+-
+-{ "xor", XRC(31,316,0), X_MASK, COM, { RA, RS, RB } },
+-{ "xor.", XRC(31,316,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "lhzuxe", X(31,319), X_MASK, BOOKE64, { RT, RAL, RB } },
+-
+-{ "mfexisr", XSPR(31,323,64), XSPR_MASK, PPC403, { RT } },
+-{ "mfexier", XSPR(31,323,66), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr0", XSPR(31,323,128), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr1", XSPR(31,323,129), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr2", XSPR(31,323,130), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr3", XSPR(31,323,131), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr4", XSPR(31,323,132), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr5", XSPR(31,323,133), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr6", XSPR(31,323,134), XSPR_MASK, PPC403, { RT } },
+-{ "mfbr7", XSPR(31,323,135), XSPR_MASK, PPC403, { RT } },
+-{ "mfbear", XSPR(31,323,144), XSPR_MASK, PPC403, { RT } },
+-{ "mfbesr", XSPR(31,323,145), XSPR_MASK, PPC403, { RT } },
+-{ "mfiocr", XSPR(31,323,160), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacr0", XSPR(31,323,192), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmact0", XSPR(31,323,193), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmada0", XSPR(31,323,194), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmasa0", XSPR(31,323,195), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacc0", XSPR(31,323,196), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacr1", XSPR(31,323,200), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmact1", XSPR(31,323,201), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmada1", XSPR(31,323,202), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmasa1", XSPR(31,323,203), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacc1", XSPR(31,323,204), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacr2", XSPR(31,323,208), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmact2", XSPR(31,323,209), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmada2", XSPR(31,323,210), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmasa2", XSPR(31,323,211), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacc2", XSPR(31,323,212), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacr3", XSPR(31,323,216), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmact3", XSPR(31,323,217), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmada3", XSPR(31,323,218), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmasa3", XSPR(31,323,219), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmacc3", XSPR(31,323,220), XSPR_MASK, PPC403, { RT } },
+-{ "mfdmasr", XSPR(31,323,224), XSPR_MASK, PPC403, { RT } },
+-{ "mfdcr", X(31,323), X_MASK, PPC403 | BOOKE, { RT, SPR } },
+-
+-{ "div", XO(31,331,0,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "div.", XO(31,331,0,1), XO_MASK, M601, { RT, RA, RB } },
+-{ "divo", XO(31,331,1,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "divo.", XO(31,331,1,1), XO_MASK, M601, { RT, RA, RB } },
+-
+-{ "mfpmr", X(31,334), X_MASK, PPCPMR, { RT, PMR }},
+-
+-{ "mfmq", XSPR(31,339,0), XSPR_MASK, M601, { RT } },
+-{ "mfxer", XSPR(31,339,1), XSPR_MASK, COM, { RT } },
+-{ "mfrtcu", XSPR(31,339,4), XSPR_MASK, COM, { RT } },
+-{ "mfrtcl", XSPR(31,339,5), XSPR_MASK, COM, { RT } },
+-{ "mfdec", XSPR(31,339,6), XSPR_MASK, MFDEC1, { RT } },
+-{ "mfdec", XSPR(31,339,22), XSPR_MASK, MFDEC2, { RT } },
+-{ "mflr", XSPR(31,339,8), XSPR_MASK, COM, { RT } },
+-{ "mfctr", XSPR(31,339,9), XSPR_MASK, COM, { RT } },
+-{ "mftid", XSPR(31,339,17), XSPR_MASK, POWER, { RT } },
+-{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, COM, { RT } },
+-{ "mfdar", XSPR(31,339,19), XSPR_MASK, COM, { RT } },
+-{ "mfsdr0", XSPR(31,339,24), XSPR_MASK, POWER, { RT } },
+-{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } },
+-{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } },
+-{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } },
+-{ "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } },
+-{ "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } },
+-{ "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } },
+-{ "mfcsrr1", XSPR(31,339,59), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdear", XSPR(31,339,61), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdear", XSPR(31,339,981), XSPR_MASK, PPC403, { RT } },
+-{ "mfesr", XSPR(31,339,62), XSPR_MASK, BOOKE, { RT } },
+-{ "mfesr", XSPR(31,339,980), XSPR_MASK, PPC403, { RT } },
+-{ "mfivpr", XSPR(31,339,63), XSPR_MASK, BOOKE, { RT } },
+-{ "mfcmpa", XSPR(31,339,144), XSPR_MASK, PPC860, { RT } },
+-{ "mfcmpb", XSPR(31,339,145), XSPR_MASK, PPC860, { RT } },
+-{ "mfcmpc", XSPR(31,339,146), XSPR_MASK, PPC860, { RT } },
+-{ "mfcmpd", XSPR(31,339,147), XSPR_MASK, PPC860, { RT } },
+-{ "mficr", XSPR(31,339,148), XSPR_MASK, PPC860, { RT } },
+-{ "mfder", XSPR(31,339,149), XSPR_MASK, PPC860, { RT } },
+-{ "mfcounta", XSPR(31,339,150), XSPR_MASK, PPC860, { RT } },
+-{ "mfcountb", XSPR(31,339,151), XSPR_MASK, PPC860, { RT } },
+-{ "mfcmpe", XSPR(31,339,152), XSPR_MASK, PPC860, { RT } },
+-{ "mfcmpf", XSPR(31,339,153), XSPR_MASK, PPC860, { RT } },
+-{ "mfcmpg", XSPR(31,339,154), XSPR_MASK, PPC860, { RT } },
+-{ "mfcmph", XSPR(31,339,155), XSPR_MASK, PPC860, { RT } },
+-{ "mflctrl1", XSPR(31,339,156), XSPR_MASK, PPC860, { RT } },
+-{ "mflctrl2", XSPR(31,339,157), XSPR_MASK, PPC860, { RT } },
+-{ "mfictrl", XSPR(31,339,158), XSPR_MASK, PPC860, { RT } },
+-{ "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } },
+-{ "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } },
+-{ "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } },
+-{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405, { RT } },
+-{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405, { RT } },
+-{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405, { RT } },
+-{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405, { RT } },
+-{ "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } },
+-{ "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
+-{ "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } },
+-{ "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
+-{ "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } },
+-{ "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } },
+-{ "mfsprg", XSPR(31,339,272), XSPRG_MASK, PPC, { RT, SPRG } },
+-{ "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } },
+-{ "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } },
+-{ "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } },
+-{ "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } },
+-{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } },
+-{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } },
+-{ "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } },
+-{ "mfpvr", XSPR(31,339,287), XSPR_MASK, PPC, { RT } },
+-{ "mfdbsr", XSPR(31,339,304), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdbsr", XSPR(31,339,1008), XSPR_MASK, PPC403, { RT } },
+-{ "mfdbcr0", XSPR(31,339,308), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdbcr0", XSPR(31,339,1010), XSPR_MASK, PPC405, { RT } },
+-{ "mfdbcr1", XSPR(31,339,309), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdbcr1", XSPR(31,339,957), XSPR_MASK, PPC405, { RT } },
+-{ "mfdbcr2", XSPR(31,339,310), XSPR_MASK, BOOKE, { RT } },
+-{ "mfiac1", XSPR(31,339,312), XSPR_MASK, BOOKE, { RT } },
+-{ "mfiac1", XSPR(31,339,1012), XSPR_MASK, PPC403, { RT } },
+-{ "mfiac2", XSPR(31,339,313), XSPR_MASK, BOOKE, { RT } },
+-{ "mfiac2", XSPR(31,339,1013), XSPR_MASK, PPC403, { RT } },
+-{ "mfiac3", XSPR(31,339,314), XSPR_MASK, BOOKE, { RT } },
+-{ "mfiac3", XSPR(31,339,948), XSPR_MASK, PPC405, { RT } },
+-{ "mfiac4", XSPR(31,339,315), XSPR_MASK, BOOKE, { RT } },
+-{ "mfiac4", XSPR(31,339,949), XSPR_MASK, PPC405, { RT } },
+-{ "mfdac1", XSPR(31,339,316), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdac1", XSPR(31,339,1014), XSPR_MASK, PPC403, { RT } },
+-{ "mfdac2", XSPR(31,339,317), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdac2", XSPR(31,339,1015), XSPR_MASK, PPC403, { RT } },
+-{ "mfdvc1", XSPR(31,339,318), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdvc1", XSPR(31,339,950), XSPR_MASK, PPC405, { RT } },
+-{ "mfdvc2", XSPR(31,339,319), XSPR_MASK, BOOKE, { RT } },
+-{ "mfdvc2", XSPR(31,339,951), XSPR_MASK, PPC405, { RT } },
+-{ "mftsr", XSPR(31,339,336), XSPR_MASK, BOOKE, { RT } },
+-{ "mftsr", XSPR(31,339,984), XSPR_MASK, PPC403, { RT } },
+-{ "mftcr", XSPR(31,339,340), XSPR_MASK, BOOKE, { RT } },
+-{ "mftcr", XSPR(31,339,986), XSPR_MASK, PPC403, { RT } },
+-{ "mfivor0", XSPR(31,339,400), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor1", XSPR(31,339,401), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor2", XSPR(31,339,402), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor3", XSPR(31,339,403), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor4", XSPR(31,339,404), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor5", XSPR(31,339,405), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor6", XSPR(31,339,406), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor7", XSPR(31,339,407), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor8", XSPR(31,339,408), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor9", XSPR(31,339,409), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor10", XSPR(31,339,410), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor11", XSPR(31,339,411), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor12", XSPR(31,339,412), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor13", XSPR(31,339,413), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor14", XSPR(31,339,414), XSPR_MASK, BOOKE, { RT } },
+-{ "mfivor15", XSPR(31,339,415), XSPR_MASK, BOOKE, { RT } },
+-{ "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } },
+-{ "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } },
+-{ "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } },
+-{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+-{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+-{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+-{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
+-{ "mfic_cst", XSPR(31,339,560), XSPR_MASK, PPC860, { RT } },
+-{ "mfic_adr", XSPR(31,339,561), XSPR_MASK, PPC860, { RT } },
+-{ "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } },
+-{ "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } },
+-{ "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } },
+-{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } },
+-{ "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } },
+-{ "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } },
+-{ "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } },
+-{ "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } },
+-{ "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } },
+-{ "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_ctr", XSPR(31,339,784), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_ap", XSPR(31,339,786), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_epn", XSPR(31,339,787), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_twc", XSPR(31,339,789), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_rpn", XSPR(31,339,790), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_ctr", XSPR(31,339,792), XSPR_MASK, PPC860, { RT } },
+-{ "mfm_casid", XSPR(31,339,793), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_ap", XSPR(31,339,794), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_epn", XSPR(31,339,795), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_twb", XSPR(31,339,796), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_twc", XSPR(31,339,797), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_rpn", XSPR(31,339,798), XSPR_MASK, PPC860, { RT } },
+-{ "mfm_tw", XSPR(31,339,799), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_dbcam", XSPR(31,339,816), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_dbram0",XSPR(31,339,817), XSPR_MASK, PPC860, { RT } },
+-{ "mfmi_dbram1",XSPR(31,339,818), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_dbcam", XSPR(31,339,824), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_dbram0",XSPR(31,339,825), XSPR_MASK, PPC860, { RT } },
+-{ "mfmd_dbram1",XSPR(31,339,826), XSPR_MASK, PPC860, { RT } },
+-{ "mfummcr0", XSPR(31,339,936), XSPR_MASK, PPC750, { RT } },
+-{ "mfupmc1", XSPR(31,339,937), XSPR_MASK, PPC750, { RT } },
+-{ "mfupmc2", XSPR(31,339,938), XSPR_MASK, PPC750, { RT } },
+-{ "mfusia", XSPR(31,339,939), XSPR_MASK, PPC750, { RT } },
+-{ "mfummcr1", XSPR(31,339,940), XSPR_MASK, PPC750, { RT } },
+-{ "mfupmc3", XSPR(31,339,941), XSPR_MASK, PPC750, { RT } },
+-{ "mfupmc4", XSPR(31,339,942), XSPR_MASK, PPC750, { RT } },
+-{ "mfzpr", XSPR(31,339,944), XSPR_MASK, PPC403, { RT } },
+-{ "mfccr0", XSPR(31,339,947), XSPR_MASK, PPC405, { RT } },
+-{ "mfmmcr0", XSPR(31,339,952), XSPR_MASK, PPC750, { RT } },
+-{ "mfpmc1", XSPR(31,339,953), XSPR_MASK, PPC750, { RT } },
+-{ "mfsgr", XSPR(31,339,953), XSPR_MASK, PPC403, { RT } },
+-{ "mfpmc2", XSPR(31,339,954), XSPR_MASK, PPC750, { RT } },
+-{ "mfdcwr", XSPR(31,339,954), XSPR_MASK, PPC403, { RT } },
+-{ "mfsia", XSPR(31,339,955), XSPR_MASK, PPC750, { RT } },
+-{ "mfsler", XSPR(31,339,955), XSPR_MASK, PPC405, { RT } },
+-{ "mfmmcr1", XSPR(31,339,956), XSPR_MASK, PPC750, { RT } },
+-{ "mfsu0r", XSPR(31,339,956), XSPR_MASK, PPC405, { RT } },
+-{ "mfpmc3", XSPR(31,339,957), XSPR_MASK, PPC750, { RT } },
+-{ "mfpmc4", XSPR(31,339,958), XSPR_MASK, PPC750, { RT } },
+-{ "mficdbdr", XSPR(31,339,979), XSPR_MASK, PPC403, { RT } },
+-{ "mfevpr", XSPR(31,339,982), XSPR_MASK, PPC403, { RT } },
+-{ "mfcdbcr", XSPR(31,339,983), XSPR_MASK, PPC403, { RT } },
+-{ "mfpit", XSPR(31,339,987), XSPR_MASK, PPC403, { RT } },
+-{ "mftbhi", XSPR(31,339,988), XSPR_MASK, PPC403, { RT } },
+-{ "mftblo", XSPR(31,339,989), XSPR_MASK, PPC403, { RT } },
+-{ "mfsrr2", XSPR(31,339,990), XSPR_MASK, PPC403, { RT } },
+-{ "mfsrr3", XSPR(31,339,991), XSPR_MASK, PPC403, { RT } },
+-{ "mfl2cr", XSPR(31,339,1017), XSPR_MASK, PPC750, { RT } },
+-{ "mfdccr", XSPR(31,339,1018), XSPR_MASK, PPC403, { RT } },
+-{ "mficcr", XSPR(31,339,1019), XSPR_MASK, PPC403, { RT } },
+-{ "mfictc", XSPR(31,339,1019), XSPR_MASK, PPC750, { RT } },
+-{ "mfpbl1", XSPR(31,339,1020), XSPR_MASK, PPC403, { RT } },
+-{ "mfthrm1", XSPR(31,339,1020), XSPR_MASK, PPC750, { RT } },
+-{ "mfpbu1", XSPR(31,339,1021), XSPR_MASK, PPC403, { RT } },
+-{ "mfthrm2", XSPR(31,339,1021), XSPR_MASK, PPC750, { RT } },
+-{ "mfpbl2", XSPR(31,339,1022), XSPR_MASK, PPC403, { RT } },
+-{ "mfthrm3", XSPR(31,339,1022), XSPR_MASK, PPC750, { RT } },
+-{ "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } },
+-{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } },
+-
+-{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
+-{ "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
+-
+-{ "lhax", X(31,343), X_MASK, COM, { RT, RA, RB } },
+-
+-{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
+-{ "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
+-
+-{ "dccci", X(31,454), XRT_MASK, PPC403|PPC440, { RA, RB } },
+-
+-{ "abs", XO(31,360,0,0), XORB_MASK, M601, { RT, RA } },
+-{ "abs.", XO(31,360,0,1), XORB_MASK, M601, { RT, RA } },
+-{ "abso", XO(31,360,1,0), XORB_MASK, M601, { RT, RA } },
+-{ "abso.", XO(31,360,1,1), XORB_MASK, M601, { RT, RA } },
+-
+-{ "divs", XO(31,363,0,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "divs.", XO(31,363,0,1), XO_MASK, M601, { RT, RA, RB } },
+-{ "divso", XO(31,363,1,0), XO_MASK, M601, { RT, RA, RB } },
+-{ "divso.", XO(31,363,1,1), XO_MASK, M601, { RT, RA, RB } },
+-
+-{ "tlbia", X(31,370), 0xffffffff, PPC, { 0 } },
+-
+-{ "lwaux", X(31,373), X_MASK, PPC64, { RT, RAL, RB } },
+-
+-{ "lhaux", X(31,375), X_MASK, COM, { RT, RAL, RB } },
+-
+-{ "lhauxe", X(31,383), X_MASK, BOOKE64, { RT, RAL, RB } },
+-
+-{ "mtdcrx", X(31,387), X_MASK, BOOKE, { RA, RS } },
+-
+-{ "dcblc", X(31,390), X_MASK, PPCCHLK, { CT, RA, RB }},
+-
+-{ "subfe64", XO(31,392,0,0), XO_MASK, BOOKE64, { RT, RA, RB } },
+-{ "subfe64o",XO(31,392,1,0), XO_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "adde64", XO(31,394,0,0), XO_MASK, BOOKE64, { RT, RA, RB } },
+-{ "adde64o", XO(31,394,1,0), XO_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "dcblce", X(31,398), X_MASK, PPCCHLK64, { CT, RA, RB }},
+-
+-{ "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } },
+-
+-{ "sthx", X(31,407), X_MASK, COM, { RS, RA, RB } },
+-
+-{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } },
+-
+-{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } },
+-
+-{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } },
+-
+-{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } },
+-
+-{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } },
+-{ "orc.", XRC(31,412,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } },
+-{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } },
+-
+-{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } },
+-
+-{ "ecowx", X(31,438), X_MASK, PPC, { RT, RA, RB } },
+-
+-{ "sthux", X(31,439), X_MASK, COM, { RS, RAS, RB } },
+-
+-{ "sthuxe", X(31,447), X_MASK, BOOKE64, { RS, RAS, RB } },
+-
+-{ "mr", XRC(31,444,0), X_MASK, COM, { RA, RS, RBS } },
+-{ "or", XRC(31,444,0), X_MASK, COM, { RA, RS, RB } },
+-{ "mr.", XRC(31,444,1), X_MASK, COM, { RA, RS, RBS } },
+-{ "or.", XRC(31,444,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "mtexisr", XSPR(31,451,64), XSPR_MASK, PPC403, { RS } },
+-{ "mtexier", XSPR(31,451,66), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr0", XSPR(31,451,128), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr1", XSPR(31,451,129), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr2", XSPR(31,451,130), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr3", XSPR(31,451,131), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr4", XSPR(31,451,132), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr5", XSPR(31,451,133), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr6", XSPR(31,451,134), XSPR_MASK, PPC403, { RS } },
+-{ "mtbr7", XSPR(31,451,135), XSPR_MASK, PPC403, { RS } },
+-{ "mtbear", XSPR(31,451,144), XSPR_MASK, PPC403, { RS } },
+-{ "mtbesr", XSPR(31,451,145), XSPR_MASK, PPC403, { RS } },
+-{ "mtiocr", XSPR(31,451,160), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacr0", XSPR(31,451,192), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmact0", XSPR(31,451,193), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmada0", XSPR(31,451,194), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmasa0", XSPR(31,451,195), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacc0", XSPR(31,451,196), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacr1", XSPR(31,451,200), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmact1", XSPR(31,451,201), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmada1", XSPR(31,451,202), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmasa1", XSPR(31,451,203), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacc1", XSPR(31,451,204), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacr2", XSPR(31,451,208), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmact2", XSPR(31,451,209), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmada2", XSPR(31,451,210), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmasa2", XSPR(31,451,211), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacc2", XSPR(31,451,212), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacr3", XSPR(31,451,216), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmact3", XSPR(31,451,217), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmada3", XSPR(31,451,218), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmasa3", XSPR(31,451,219), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmacc3", XSPR(31,451,220), XSPR_MASK, PPC403, { RS } },
+-{ "mtdmasr", XSPR(31,451,224), XSPR_MASK, PPC403, { RS } },
+-{ "mtdcr", X(31,451), X_MASK, PPC403 | BOOKE, { SPR, RS } },
+-
+-{ "subfze64",XO(31,456,0,0), XORB_MASK, BOOKE64, { RT, RA } },
+-{ "subfze64o",XO(31,456,1,0), XORB_MASK, BOOKE64, { RT, RA } },
+-
+-{ "divdu", XO(31,457,0,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "divdu.", XO(31,457,0,1), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "divduo", XO(31,457,1,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "divduo.", XO(31,457,1,1), XO_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "addze64", XO(31,458,0,0), XORB_MASK, BOOKE64, { RT, RA } },
+-{ "addze64o",XO(31,458,1,0), XORB_MASK, BOOKE64, { RT, RA } },
+-
+-{ "divwu", XO(31,459,0,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "divwu.", XO(31,459,0,1), XO_MASK, PPC, { RT, RA, RB } },
+-{ "divwuo", XO(31,459,1,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "divwuo.", XO(31,459,1,1), XO_MASK, PPC, { RT, RA, RB } },
+-
+-{ "mtmq", XSPR(31,467,0), XSPR_MASK, M601, { RS } },
+-{ "mtxer", XSPR(31,467,1), XSPR_MASK, COM, { RS } },
+-{ "mtlr", XSPR(31,467,8), XSPR_MASK, COM, { RS } },
+-{ "mtctr", XSPR(31,467,9), XSPR_MASK, COM, { RS } },
+-{ "mttid", XSPR(31,467,17), XSPR_MASK, POWER, { RS } },
+-{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, COM, { RS } },
+-{ "mtdar", XSPR(31,467,19), XSPR_MASK, COM, { RS } },
+-{ "mtrtcu", XSPR(31,467,20), XSPR_MASK, COM, { RS } },
+-{ "mtrtcl", XSPR(31,467,21), XSPR_MASK, COM, { RS } },
+-{ "mtdec", XSPR(31,467,22), XSPR_MASK, COM, { RS } },
+-{ "mtsdr0", XSPR(31,467,24), XSPR_MASK, POWER, { RS } },
+-{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } },
+-{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } },
+-{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } },
+-{ "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } },
+-{ "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } },
+-{ "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } },
+-{ "mtcsrr0", XSPR(31,467,58), XSPR_MASK, BOOKE, { RS } },
+-{ "mtcsrr1", XSPR(31,467,59), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdear", XSPR(31,467,61), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdear", XSPR(31,467,981), XSPR_MASK, PPC403, { RS } },
+-{ "mtesr", XSPR(31,467,62), XSPR_MASK, BOOKE, { RS } },
+-{ "mtesr", XSPR(31,467,980), XSPR_MASK, PPC403, { RS } },
+-{ "mtivpr", XSPR(31,467,63), XSPR_MASK, BOOKE, { RS } },
+-{ "mtcmpa", XSPR(31,467,144), XSPR_MASK, PPC860, { RS } },
+-{ "mtcmpb", XSPR(31,467,145), XSPR_MASK, PPC860, { RS } },
+-{ "mtcmpc", XSPR(31,467,146), XSPR_MASK, PPC860, { RS } },
+-{ "mtcmpd", XSPR(31,467,147), XSPR_MASK, PPC860, { RS } },
+-{ "mticr", XSPR(31,467,148), XSPR_MASK, PPC860, { RS } },
+-{ "mtder", XSPR(31,467,149), XSPR_MASK, PPC860, { RS } },
+-{ "mtcounta", XSPR(31,467,150), XSPR_MASK, PPC860, { RS } },
+-{ "mtcountb", XSPR(31,467,151), XSPR_MASK, PPC860, { RS } },
+-{ "mtcmpe", XSPR(31,467,152), XSPR_MASK, PPC860, { RS } },
+-{ "mtcmpf", XSPR(31,467,153), XSPR_MASK, PPC860, { RS } },
+-{ "mtcmpg", XSPR(31,467,154), XSPR_MASK, PPC860, { RS } },
+-{ "mtcmph", XSPR(31,467,155), XSPR_MASK, PPC860, { RS } },
+-{ "mtlctrl1", XSPR(31,467,156), XSPR_MASK, PPC860, { RS } },
+-{ "mtlctrl2", XSPR(31,467,157), XSPR_MASK, PPC860, { RS } },
+-{ "mtictrl", XSPR(31,467,158), XSPR_MASK, PPC860, { RS } },
+-{ "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } },
+-{ "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } },
+-{ "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } },
+-{ "mtsprg", XSPR(31,467,272), XSPRG_MASK,PPC, { SPRG, RS } },
+-{ "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } },
+-{ "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } },
+-{ "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } },
+-{ "mtsprg3", XSPR(31,467,275), XSPR_MASK, PPC, { RS } },
+-{ "mtsprg4", XSPR(31,467,276), XSPR_MASK, PPC405 | BOOKE, { RS } },
+-{ "mtsprg5", XSPR(31,467,277), XSPR_MASK, PPC405 | BOOKE, { RS } },
+-{ "mtsprg6", XSPR(31,467,278), XSPR_MASK, PPC405 | BOOKE, { RS } },
+-{ "mtsprg7", XSPR(31,467,279), XSPR_MASK, PPC405 | BOOKE, { RS } },
+-{ "mtasr", XSPR(31,467,280), XSPR_MASK, PPC64, { RS } },
+-{ "mtear", XSPR(31,467,282), XSPR_MASK, PPC, { RS } },
+-{ "mttbl", XSPR(31,467,284), XSPR_MASK, PPC, { RS } },
+-{ "mttbu", XSPR(31,467,285), XSPR_MASK, PPC, { RS } },
+-{ "mtdbsr", XSPR(31,467,304), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdbsr", XSPR(31,467,1008), XSPR_MASK, PPC403, { RS } },
+-{ "mtdbcr0", XSPR(31,467,308), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdbcr0", XSPR(31,467,1010), XSPR_MASK, PPC405, { RS } },
+-{ "mtdbcr1", XSPR(31,467,309), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdbcr1", XSPR(31,467,957), XSPR_MASK, PPC405, { RS } },
+-{ "mtdbcr2", XSPR(31,467,310), XSPR_MASK, BOOKE, { RS } },
+-{ "mtiac1", XSPR(31,467,312), XSPR_MASK, BOOKE, { RS } },
+-{ "mtiac1", XSPR(31,467,1012), XSPR_MASK, PPC403, { RS } },
+-{ "mtiac2", XSPR(31,467,313), XSPR_MASK, BOOKE, { RS } },
+-{ "mtiac2", XSPR(31,467,1013), XSPR_MASK, PPC403, { RS } },
+-{ "mtiac3", XSPR(31,467,314), XSPR_MASK, BOOKE, { RS } },
+-{ "mtiac3", XSPR(31,467,948), XSPR_MASK, PPC405, { RS } },
+-{ "mtiac4", XSPR(31,467,315), XSPR_MASK, BOOKE, { RS } },
+-{ "mtiac4", XSPR(31,467,949), XSPR_MASK, PPC405, { RS } },
+-{ "mtdac1", XSPR(31,467,316), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdac1", XSPR(31,467,1014), XSPR_MASK, PPC403, { RS } },
+-{ "mtdac2", XSPR(31,467,317), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdac2", XSPR(31,467,1015), XSPR_MASK, PPC403, { RS } },
+-{ "mtdvc1", XSPR(31,467,318), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdvc1", XSPR(31,467,950), XSPR_MASK, PPC405, { RS } },
+-{ "mtdvc2", XSPR(31,467,319), XSPR_MASK, BOOKE, { RS } },
+-{ "mtdvc2", XSPR(31,467,951), XSPR_MASK, PPC405, { RS } },
+-{ "mttsr", XSPR(31,467,336), XSPR_MASK, BOOKE, { RS } },
+-{ "mttsr", XSPR(31,467,984), XSPR_MASK, PPC403, { RS } },
+-{ "mttcr", XSPR(31,467,340), XSPR_MASK, BOOKE, { RS } },
+-{ "mttcr", XSPR(31,467,986), XSPR_MASK, PPC403, { RS } },
+-{ "mtivor0", XSPR(31,467,400), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor1", XSPR(31,467,401), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor2", XSPR(31,467,402), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor3", XSPR(31,467,403), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor4", XSPR(31,467,404), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor5", XSPR(31,467,405), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor6", XSPR(31,467,406), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor7", XSPR(31,467,407), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor8", XSPR(31,467,408), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor9", XSPR(31,467,409), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor10", XSPR(31,467,410), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor11", XSPR(31,467,411), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor12", XSPR(31,467,412), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor13", XSPR(31,467,413), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor14", XSPR(31,467,414), XSPR_MASK, BOOKE, { RS } },
+-{ "mtivor15", XSPR(31,467,415), XSPR_MASK, BOOKE, { RS } },
+-{ "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } },
+-{ "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } },
+-{ "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } },
+-{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+-{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+-{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+-{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
+-{ "mtmcsrr0", XSPR(31,467,570), XSPR_MASK, PPCRFMCI, { RS } },
+-{ "mtmcsrr1", XSPR(31,467,571), XSPR_MASK, PPCRFMCI, { RS } },
+-{ "mtmcsr", XSPR(31,467,572), XSPR_MASK, PPCRFMCI, { RS } },
+-{ "mtummcr0", XSPR(31,467,936), XSPR_MASK, PPC750, { RS } },
+-{ "mtupmc1", XSPR(31,467,937), XSPR_MASK, PPC750, { RS } },
+-{ "mtupmc2", XSPR(31,467,938), XSPR_MASK, PPC750, { RS } },
+-{ "mtusia", XSPR(31,467,939), XSPR_MASK, PPC750, { RS } },
+-{ "mtummcr1", XSPR(31,467,940), XSPR_MASK, PPC750, { RS } },
+-{ "mtupmc3", XSPR(31,467,941), XSPR_MASK, PPC750, { RS } },
+-{ "mtupmc4", XSPR(31,467,942), XSPR_MASK, PPC750, { RS } },
+-{ "mtzpr", XSPR(31,467,944), XSPR_MASK, PPC403, { RS } },
+-{ "mtccr0", XSPR(31,467,947), XSPR_MASK, PPC405, { RS } },
+-{ "mtmmcr0", XSPR(31,467,952), XSPR_MASK, PPC750, { RS } },
+-{ "mtsgr", XSPR(31,467,953), XSPR_MASK, PPC403, { RS } },
+-{ "mtpmc1", XSPR(31,467,953), XSPR_MASK, PPC750, { RS } },
+-{ "mtdcwr", XSPR(31,467,954), XSPR_MASK, PPC403, { RS } },
+-{ "mtpmc2", XSPR(31,467,954), XSPR_MASK, PPC750, { RS } },
+-{ "mtsler", XSPR(31,467,955), XSPR_MASK, PPC405, { RS } },
+-{ "mtsia", XSPR(31,467,955), XSPR_MASK, PPC750, { RS } },
+-{ "mtsu0r", XSPR(31,467,956), XSPR_MASK, PPC405, { RS } },
+-{ "mtmmcr1", XSPR(31,467,956), XSPR_MASK, PPC750, { RS } },
+-{ "mtpmc3", XSPR(31,467,957), XSPR_MASK, PPC750, { RS } },
+-{ "mtpmc4", XSPR(31,467,958), XSPR_MASK, PPC750, { RS } },
+-{ "mticdbdr", XSPR(31,467,979), XSPR_MASK, PPC403, { RS } },
+-{ "mtevpr", XSPR(31,467,982), XSPR_MASK, PPC403, { RS } },
+-{ "mtcdbcr", XSPR(31,467,983), XSPR_MASK, PPC403, { RS } },
+-{ "mtpit", XSPR(31,467,987), XSPR_MASK, PPC403, { RS } },
+-{ "mttbhi", XSPR(31,467,988), XSPR_MASK, PPC403, { RS } },
+-{ "mttblo", XSPR(31,467,989), XSPR_MASK, PPC403, { RS } },
+-{ "mtsrr2", XSPR(31,467,990), XSPR_MASK, PPC403, { RS } },
+-{ "mtsrr3", XSPR(31,467,991), XSPR_MASK, PPC403, { RS } },
+-{ "mtl2cr", XSPR(31,467,1017), XSPR_MASK, PPC750, { RS } },
+-{ "mtdccr", XSPR(31,467,1018), XSPR_MASK, PPC403, { RS } },
+-{ "mticcr", XSPR(31,467,1019), XSPR_MASK, PPC403, { RS } },
+-{ "mtictc", XSPR(31,467,1019), XSPR_MASK, PPC750, { RS } },
+-{ "mtpbl1", XSPR(31,467,1020), XSPR_MASK, PPC403, { RS } },
+-{ "mtthrm1", XSPR(31,467,1020), XSPR_MASK, PPC750, { RS } },
+-{ "mtpbu1", XSPR(31,467,1021), XSPR_MASK, PPC403, { RS } },
+-{ "mtthrm2", XSPR(31,467,1021), XSPR_MASK, PPC750, { RS } },
+-{ "mtpbl2", XSPR(31,467,1022), XSPR_MASK, PPC403, { RS } },
+-{ "mtthrm3", XSPR(31,467,1022), XSPR_MASK, PPC750, { RS } },
+-{ "mtpbu2", XSPR(31,467,1023), XSPR_MASK, PPC403, { RS } },
+-{ "mtspr", X(31,467), X_MASK, COM, { SPR, RS } },
+-
+-{ "dcbi", X(31,470), XRT_MASK, PPC, { RA, RB } },
+-
+-{ "nand", XRC(31,476,0), X_MASK, COM, { RA, RS, RB } },
+-{ "nand.", XRC(31,476,1), X_MASK, COM, { RA, RS, RB } },
+-
+-{ "dcbie", X(31,478), XRT_MASK, BOOKE64, { RA, RB } },
+-
+-{ "dcread", X(31,486), X_MASK, PPC403|PPC440, { RT, RA, RB }},
+-
+-{ "mtpmr", X(31,462), X_MASK, PPCPMR, { PMR, RS }},
+-
+-{ "icbtls", X(31,486), X_MASK, PPCCHLK, { CT, RA, RB }},
+-
+-{ "nabs", XO(31,488,0,0), XORB_MASK, M601, { RT, RA } },
+-{ "subfme64",XO(31,488,0,0), XORB_MASK, BOOKE64, { RT, RA } },
+-{ "nabs.", XO(31,488,0,1), XORB_MASK, M601, { RT, RA } },
+-{ "nabso", XO(31,488,1,0), XORB_MASK, M601, { RT, RA } },
+-{ "subfme64o",XO(31,488,1,0), XORB_MASK, BOOKE64, { RT, RA } },
+-{ "nabso.", XO(31,488,1,1), XORB_MASK, M601, { RT, RA } },
+-
+-{ "divd", XO(31,489,0,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "divd.", XO(31,489,0,1), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "divdo", XO(31,489,1,0), XO_MASK, PPC64, { RT, RA, RB } },
+-{ "divdo.", XO(31,489,1,1), XO_MASK, PPC64, { RT, RA, RB } },
+-
+-{ "addme64", XO(31,490,0,0), XORB_MASK, BOOKE64, { RT, RA } },
+-{ "addme64o",XO(31,490,1,0), XORB_MASK, BOOKE64, { RT, RA } },
+-
+-{ "divw", XO(31,491,0,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "divw.", XO(31,491,0,1), XO_MASK, PPC, { RT, RA, RB } },
+-{ "divwo", XO(31,491,1,0), XO_MASK, PPC, { RT, RA, RB } },
+-{ "divwo.", XO(31,491,1,1), XO_MASK, PPC, { RT, RA, RB } },
+-
+-{ "icbtlse", X(31,494), X_MASK, PPCCHLK64, { CT, RA, RB }},
+-
+-{ "slbia", X(31,498), 0xffffffff, PPC64, { 0 } },
+-
+-{ "cli", X(31,502), XRB_MASK, POWER, { RT, RA } },
+-
+-{ "stdcxe.", XRC(31,511,1), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "mcrxr", X(31,512), XRARB_MASK|(3<<21), COM, { BF } },
+-
+-{ "bblels", X(31,518), X_MASK, PPCBRLK, { 0 }},
+-{ "mcrxr64", X(31,544), XRARB_MASK|(3<<21), BOOKE64, { BF } },
+-
+-{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } },
+-
+-{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA, RB } },
+-{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA, RB } },
+-{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA, RB } },
+-
+-{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } },
+-{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } },
+-{ "srw.", XRC(31,536,1), X_MASK, PPCCOM, { RA, RS, RB } },
+-{ "sr.", XRC(31,536,1), X_MASK, PWRCOM, { RA, RS, RB } },
+-
+-{ "rrib", XRC(31,537,0), X_MASK, M601, { RA, RS, RB } },
+-{ "rrib.", XRC(31,537,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "srd", XRC(31,539,0), X_MASK, PPC64, { RA, RS, RB } },
+-{ "srd.", XRC(31,539,1), X_MASK, PPC64, { RA, RS, RB } },
+-
+-{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } },
+-{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA, RB } },
+-
+-{ "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }},
+-{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } },
+-
+-{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } },
+-
+-{ "lfsuxe", X(31,575), X_MASK, BOOKE64, { FRT, RAS, RB } },
+-
+-{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } },
+-
+-{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA, NB } },
+-{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA, NB } },
+-
+-{ "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } },
+-{ "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } },
+-{ "msync", X(31,598), 0xffffffff, BOOKE, { 0 } },
+-{ "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } },
+-{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } },
+-
+-{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA, RB } },
+-
+-{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA, RB } },
+-
+-{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "dclst", X(31,630), XRB_MASK, PWRCOM, { RS, RA } },
+-
+-{ "lfdux", X(31,631), X_MASK, COM, { FRT, RAS, RB } },
+-
+-{ "lfduxe", X(31,639), X_MASK, BOOKE64, { FRT, RAS, RB } },
+-
+-{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } },
+-
+-{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA, RB } },
+-{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA, RB } },
+-
+-{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA, RB } },
+-{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA, RB } },
+-
+-{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA, RB } },
+-
+-{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } },
+-{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } },
+-{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA, RB } },
+-
+-{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } },
+-
+-{ "sriq", XRC(31,696,0), X_MASK, M601, { RA, RS, SH } },
+-{ "sriq.", XRC(31,696,1), X_MASK, M601, { RA, RS, SH } },
+-
+-{ "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } },
+-
+-{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA, NB } },
+-{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA, NB } },
+-
+-{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA, RB } },
+-
+-{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } },
+-{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } },
+-{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA, RB } },
+-
+-{ "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } },
+-
+-{ "stfdux", X(31,759), X_MASK, COM, { FRS, RAS, RB } },
+-
+-{ "srliq", XRC(31,760,0), X_MASK, M601, { RA, RS, SH } },
+-{ "srliq.", XRC(31,760,1), X_MASK, M601, { RA, RS, SH } },
+-
+-{ "dcbae", X(31,766), XRT_MASK, BOOKE64, { RA, RB } },
+-
+-{ "stfduxe", X(31,767), X_MASK, BOOKE64, { FRS, RAS, RB } },
+-
+-{ "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } },
+-{ "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } },
+-
+-{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA, RB } },
+-
+-{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } },
+-{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } },
+-{ "sraw.", XRC(31,792,1), X_MASK, PPCCOM, { RA, RS, RB } },
+-{ "sra.", XRC(31,792,1), X_MASK, PWRCOM, { RA, RS, RB } },
+-
+-{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } },
+-{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } },
+-
+-{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA, RB } },
+-{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA, RB } },
+-
+-{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } },
+-
+-{ "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } },
+-{ "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } },
+-
+-{ "srawi", XRC(31,824,0), X_MASK, PPCCOM, { RA, RS, SH } },
+-{ "srai", XRC(31,824,0), X_MASK, PWRCOM, { RA, RS, SH } },
+-{ "srawi.", XRC(31,824,1), X_MASK, PPCCOM, { RA, RS, SH } },
+-{ "srai.", XRC(31,824,1), X_MASK, PWRCOM, { RA, RS, SH } },
+-
+-{ "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } },
+-
+-{ "mbar", X(31,854), X_MASK, BOOKE, { MO } },
+-{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } },
+-
+-{ "tlbsx", XRC(31,914,0), X_MASK, BOOKE, { RA, RB } },
+-{ "tlbsx", XRC(31,914,0), X_MASK, PPC403, { RT, RA, RB } },
+-{ "tlbsx.", XRC(31,914,1), X_MASK, BOOKE, { RA, RB } },
+-{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403, { RT, RA, RB } },
+-{ "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RA, RB } },
+-{ "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RA, RB } },
+-
+-{ "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } },
+-
+-{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA, RB } },
+-
+-{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } },
+-{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "srea", XRC(31,921,0), X_MASK, M601, { RA, RS, RB } },
+-{ "srea.", XRC(31,921,1), X_MASK, M601, { RA, RS, RB } },
+-
+-{ "extsh", XRC(31,922,0), XRB_MASK, PPCCOM, { RA, RS } },
+-{ "exts", XRC(31,922,0), XRB_MASK, PWRCOM, { RA, RS } },
+-{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } },
+-{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } },
+-
+-{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA, RB } },
+-
+-{ "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } },
+-{ "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } },
+-{ "tlbre", X(31,946), X_MASK, BOOKE, { 0 } },
+-{ "tlbre", X(31,946), X_MASK, PPC403, { RS, RA, SH } },
+-
+-{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } },
+-{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } },
+-
+-{ "extsb", XRC(31,954,0), XRB_MASK, PPC, { RA, RS} },
+-{ "extsb.", XRC(31,954,1), XRB_MASK, PPC, { RA, RS} },
+-
+-{ "stduxe", X(31,959), X_MASK, BOOKE64, { RS, RAS, RB } },
+-
+-{ "iccci", X(31,966), XRT_MASK, PPC403|PPC440, { RA, RB } },
+-
+-{ "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } },
+-{ "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } },
+-{ "tlbwe", X(31,978), X_MASK, BOOKE, { 0 } },
+-{ "tlbwe", X(31,978), X_MASK, PPC403, { RS, RA, SH } },
+-{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } },
+-
+-{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } },
+-
+-{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA, RB } },
+-
+-{ "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } },
+-{ "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } },
+-
+-{ "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } },
+-
+-{ "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } },
+-{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA, RB } },
+-
+-{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } },
+-
+-{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
+-{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
+-
+-{ "dcbze", X(31,1022), XRT_MASK, BOOKE64, { RA, RB } },
+-
+-{ "lvebx", X(31, 7), X_MASK, PPCVEC, { VD, RA, RB } },
+-{ "lvehx", X(31, 39), X_MASK, PPCVEC, { VD, RA, RB } },
+-{ "lvewx", X(31, 71), X_MASK, PPCVEC, { VD, RA, RB } },
+-{ "lvsl", X(31, 6), X_MASK, PPCVEC, { VD, RA, RB } },
+-{ "lvsr", X(31, 38), X_MASK, PPCVEC, { VD, RA, RB } },
+-{ "lvx", X(31, 103), X_MASK, PPCVEC, { VD, RA, RB } },
+-{ "lvxl", X(31, 359), X_MASK, PPCVEC, { VD, RA, RB } },
+-{ "stvebx", X(31, 135), X_MASK, PPCVEC, { VS, RA, RB } },
+-{ "stvehx", X(31, 167), X_MASK, PPCVEC, { VS, RA, RB } },
+-{ "stvewx", X(31, 199), X_MASK, PPCVEC, { VS, RA, RB } },
+-{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } },
+-{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } },
+-
+-{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA } },
+-{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA } },
+-
+-{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } },
+-{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA } },
+-
+-{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA } },
+-
+-{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } },
+-
+-{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA } },
+-{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA } },
+-
+-{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } },
+-{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA } },
+-
+-{ "stb", OP(38), OP_MASK, COM, { RS, D, RA } },
+-
+-{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } },
+-
+-{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA } },
+-
+-{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } },
+-
+-{ "lha", OP(42), OP_MASK, COM, { RT, D, RA } },
+-
+-{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } },
+-
+-{ "sth", OP(44), OP_MASK, COM, { RS, D, RA } },
+-
+-{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } },
+-
+-{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } },
+-{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA } },
+-
+-{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA } },
+-{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA } },
+-
+-{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA } },
+-
+-{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } },
+-
+-{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA } },
+-
+-{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } },
+-
+-{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA } },
+-
+-{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } },
+-
+-{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA } },
+-
+-{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } },
+-
+-{ "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } },
+-
+-{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA } },
+-
+-{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA } },
+-
+-{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA } },
+-{ "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } },
+-{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA } },
+-{ "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } },
+-{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA } },
+-{ "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } },
+-{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA } },
+-{ "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } },
+-{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA } },
+-{ "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } },
+-{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA } },
+-{ "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } },
+-{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA } },
+-{ "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } },
+-
+-{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA } },
+-
+-{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } },
+-
+-{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA } },
+-
+-{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+-{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+-
+-{ "fsubs", A(59,20,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+-{ "fsubs.", A(59,20,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+-
+-{ "fadds", A(59,21,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+-{ "fadds.", A(59,21,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
+-
+-{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
+-{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+-
+-{ "fres", A(59,24,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
+-{ "fres.", A(59,24,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+-
+-{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } },
+-{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } },
+-
+-{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-
+-{ "fmadds", A(59,29,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-{ "fmadds.", A(59,29,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-
+-{ "fnmsubs", A(59,30,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-{ "fnmsubs.",A(59,30,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-
+-{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-
+-{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } },
+-
+-{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } },
+-
+-{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA } },
+-{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA } },
+-{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA } },
+-{ "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } },
+-{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA } },
+-{ "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } },
+-{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA } },
+-{ "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } },
+-{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA } },
+-{ "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } },
+-{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA } },
+-{ "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } },
+-
+-{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA } },
+-
+-{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } },
+-
+-{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA } },
+-
+-{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
+-
+-{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } },
+-{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } },
+-
+-{ "fctiw", XRC(63,14,0), XRA_MASK, PPCCOM, { FRT, FRB } },
+-{ "fcir", XRC(63,14,0), XRA_MASK, POWER2, { FRT, FRB } },
+-{ "fctiw.", XRC(63,14,1), XRA_MASK, PPCCOM, { FRT, FRB } },
+-{ "fcir.", XRC(63,14,1), XRA_MASK, POWER2, { FRT, FRB } },
+-
+-{ "fctiwz", XRC(63,15,0), XRA_MASK, PPCCOM, { FRT, FRB } },
+-{ "fcirz", XRC(63,15,0), XRA_MASK, POWER2, { FRT, FRB } },
+-{ "fctiwz.", XRC(63,15,1), XRA_MASK, PPCCOM, { FRT, FRB } },
+-{ "fcirz.", XRC(63,15,1), XRA_MASK, POWER2, { FRT, FRB } },
+-
+-{ "fdiv", A(63,18,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
+-{ "fd", A(63,18,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
+-{ "fdiv.", A(63,18,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
+-{ "fd.", A(63,18,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
+-
+-{ "fsub", A(63,20,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
+-{ "fs", A(63,20,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
+-{ "fsub.", A(63,20,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
+-{ "fs.", A(63,20,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
+-
+-{ "fadd", A(63,21,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
+-{ "fa", A(63,21,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
+-{ "fadd.", A(63,21,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } },
+-{ "fa.", A(63,21,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } },
+-
+-{ "fsqrt", A(63,22,0), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } },
+-{ "fsqrt.", A(63,22,1), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } },
+-
+-{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+-
+-{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
+-{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
+-{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
+-{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
+-
+-{ "frsqrte", A(63,26,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
+-{ "frsqrte.",A(63,26,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+-
+-{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-{ "fmsub.", A(63,28,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fms.", A(63,28,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-
+-{ "fmadd", A(63,29,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fma", A(63,29,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-{ "fmadd.", A(63,29,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fma.", A(63,29,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-
+-{ "fnmsub", A(63,30,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fnms", A(63,30,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-{ "fnmsub.", A(63,30,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fnms.", A(63,30,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-
+-{ "fnmadd", A(63,31,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fnma", A(63,31,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-{ "fnmadd.", A(63,31,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
+-{ "fnma.", A(63,31,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
+-
+-{ "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
+-
+-{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } },
+-{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } },
+-
+-{ "fneg", XRC(63,40,0), XRA_MASK, COM, { FRT, FRB } },
+-{ "fneg.", XRC(63,40,1), XRA_MASK, COM, { FRT, FRB } },
+-
+-{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } },
+-
+-{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } },
+-{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } },
+-
+-{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } },
+-{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } },
+-
+-{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
+-{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
+-
+-{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } },
+-{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } },
+-
+-{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } },
+-{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } },
+-
+-{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } },
+-{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } },
+-
+-{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } },
+-{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } },
+-
+-{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } },
+-{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } },
+-
+-{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } },
+-{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } },
+-
+-{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } },
+-{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } },
+-
+-};
+-
+-const int powerpc_num_opcodes =
+- sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]);
+-
+-/* The macro table. This is only used by the assembler. */
+-
+-/* The expressions of the form (-x ! 31) & (x | 31) have the value 0
+- when x=0; 32-x when x is between 1 and 31; are negative if x is
+- negative; and are 32 or more otherwise. This is what you want
+- when, for instance, you are emulating a right shift by a
+- rotate-left-and-mask, because the underlying instructions support
+- shifts of size 0 but not shifts of size 32. By comparison, when
+- extracting x bits from some word you want to use just 32-x, because
+- the underlying instructions don't support extracting 0 bits but do
+- support extracting the whole word (32 bits in this case). */
+-
+-const struct powerpc_macro powerpc_macros[] = {
+-{ "extldi", 4, PPC64, "rldicr %0,%1,%3,(%2)-1" },
+-{ "extldi.", 4, PPC64, "rldicr. %0,%1,%3,(%2)-1" },
+-{ "extrdi", 4, PPC64, "rldicl %0,%1,(%2)+(%3),64-(%2)" },
+-{ "extrdi.", 4, PPC64, "rldicl. %0,%1,(%2)+(%3),64-(%2)" },
+-{ "insrdi", 4, PPC64, "rldimi %0,%1,64-((%2)+(%3)),%3" },
+-{ "insrdi.", 4, PPC64, "rldimi. %0,%1,64-((%2)+(%3)),%3" },
+-{ "rotrdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),0" },
+-{ "rotrdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),0" },
+-{ "sldi", 3, PPC64, "rldicr %0,%1,%2,63-(%2)" },
+-{ "sldi.", 3, PPC64, "rldicr. %0,%1,%2,63-(%2)" },
+-{ "srdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),%2" },
+-{ "srdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),%2" },
+-{ "clrrdi", 3, PPC64, "rldicr %0,%1,0,63-(%2)" },
+-{ "clrrdi.", 3, PPC64, "rldicr. %0,%1,0,63-(%2)" },
+-{ "clrlsldi",4, PPC64, "rldic %0,%1,%3,(%2)-(%3)" },
+-{ "clrlsldi.",4, PPC64, "rldic. %0,%1,%3,(%2)-(%3)" },
+-
+-{ "extlwi", 4, PPCCOM, "rlwinm %0,%1,%3,0,(%2)-1" },
+-{ "extlwi.", 4, PPCCOM, "rlwinm. %0,%1,%3,0,(%2)-1" },
+-{ "extrwi", 4, PPCCOM, "rlwinm %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" },
+-{ "extrwi.", 4, PPCCOM, "rlwinm. %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" },
+-{ "inslwi", 4, PPCCOM, "rlwimi %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1" },
+-{ "inslwi.", 4, PPCCOM, "rlwimi. %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1"},
+-{ "insrwi", 4, PPCCOM, "rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" },
+-{ "insrwi.", 4, PPCCOM, "rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"},
+-{ "rotrwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),0,31" },
+-{ "rotrwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),0,31" },
+-{ "slwi", 3, PPCCOM, "rlwinm %0,%1,%2,0,31-(%2)" },
+-{ "sli", 3, PWRCOM, "rlinm %0,%1,%2,0,31-(%2)" },
+-{ "slwi.", 3, PPCCOM, "rlwinm. %0,%1,%2,0,31-(%2)" },
+-{ "sli.", 3, PWRCOM, "rlinm. %0,%1,%2,0,31-(%2)" },
+-{ "srwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
+-{ "sri", 3, PWRCOM, "rlinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
+-{ "srwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
+-{ "sri.", 3, PWRCOM, "rlinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" },
+-{ "clrrwi", 3, PPCCOM, "rlwinm %0,%1,0,0,31-(%2)" },
+-{ "clrrwi.", 3, PPCCOM, "rlwinm. %0,%1,0,0,31-(%2)" },
+-{ "clrlslwi",4, PPCCOM, "rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" },
+-{ "clrlslwi.",4, PPCCOM, "rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" },
+-};
+-
+-const int powerpc_num_macros =
+- sizeof (powerpc_macros) / sizeof (powerpc_macros[0]);
+diff --git a/arch/ppc64/xmon/ppc.h b/arch/ppc64/xmon/ppc.h
+deleted file mode 100644
+--- a/arch/ppc64/xmon/ppc.h
++++ /dev/null
+@@ -1,307 +0,0 @@
+-/* ppc.h -- Header file for PowerPC opcode table
+- Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003
+- Free Software Foundation, Inc.
+- Written by Ian Lance Taylor, Cygnus Support
+-
+-This file is part of GDB, GAS, and the GNU binutils.
+-
+-GDB, GAS, and the GNU binutils are free software; you can redistribute
+-them and/or modify them under the terms of the GNU General Public
+-License as published by the Free Software Foundation; either version
+-1, or (at your option) any later version.
+-
+-GDB, GAS, and the GNU binutils are distributed in the hope that they
+-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 file; see the file COPYING. If not, write to the Free
+-Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+-
+-#ifndef PPC_H
+-#define PPC_H
+-
+-/* The opcode table is an array of struct powerpc_opcode. */
+-
+-struct powerpc_opcode
+-{
+- /* The opcode name. */
+- const char *name;
+-
+- /* The opcode itself. Those bits which will be filled in with
+- operands are zeroes. */
+- unsigned long opcode;
+-
+- /* The opcode mask. This is used by the disassembler. This is a
+- mask containing ones indicating those bits which must match the
+- opcode field, and zeroes indicating those bits which need not
+- match (and are presumably filled in by operands). */
+- unsigned long mask;
+-
+- /* One bit flags for the opcode. These are used to indicate which
+- specific processors support the instructions. The defined values
+- are listed below. */
+- unsigned long flags;
+-
+- /* An array of operand codes. Each code is an index into the
+- operand table. They appear in the order which the operands must
+- appear in assembly code, and are terminated by a zero. */
+- unsigned char operands[8];
+-};
+-
+-/* The table itself is sorted by major opcode number, and is otherwise
+- in the order in which the disassembler should consider
+- instructions. */
+-extern const struct powerpc_opcode powerpc_opcodes[];
+-extern const int powerpc_num_opcodes;
+-
+-/* Values defined for the flags field of a struct powerpc_opcode. */
+-
+-/* Opcode is defined for the PowerPC architecture. */
+-#define PPC_OPCODE_PPC 1
+-
+-/* Opcode is defined for the POWER (RS/6000) architecture. */
+-#define PPC_OPCODE_POWER 2
+-
+-/* Opcode is defined for the POWER2 (Rios 2) architecture. */
+-#define PPC_OPCODE_POWER2 4
+-
+-/* Opcode is only defined on 32 bit architectures. */
+-#define PPC_OPCODE_32 8
+-
+-/* Opcode is only defined on 64 bit architectures. */
+-#define PPC_OPCODE_64 0x10
+-
+-/* Opcode is supported by the Motorola PowerPC 601 processor. The 601
+- is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
+- but it also supports many additional POWER instructions. */
+-#define PPC_OPCODE_601 0x20
+-
+-/* Opcode is supported in both the Power and PowerPC architectures
+- (ie, compiler's -mcpu=common or assembler's -mcom). */
+-#define PPC_OPCODE_COMMON 0x40
+-
+-/* Opcode is supported for any Power or PowerPC platform (this is
+- for the assembler's -many option, and it eliminates duplicates). */
+-#define PPC_OPCODE_ANY 0x80
+-
+-/* Opcode is supported as part of the 64-bit bridge. */
+-#define PPC_OPCODE_64_BRIDGE 0x100
+-
+-/* Opcode is supported by Altivec Vector Unit */
+-#define PPC_OPCODE_ALTIVEC 0x200
+-
+-/* Opcode is supported by PowerPC 403 processor. */
+-#define PPC_OPCODE_403 0x400
+-
+-/* Opcode is supported by PowerPC BookE processor. */
+-#define PPC_OPCODE_BOOKE 0x800
+-
+-/* Opcode is only supported by 64-bit PowerPC BookE processor. */
+-#define PPC_OPCODE_BOOKE64 0x1000
+-
+-/* Opcode is supported by PowerPC 440 processor. */
+-#define PPC_OPCODE_440 0x2000
+-
+-/* Opcode is only supported by Power4 architecture. */
+-#define PPC_OPCODE_POWER4 0x4000
+-
+-/* Opcode isn't supported by Power4 architecture. */
+-#define PPC_OPCODE_NOPOWER4 0x8000
+-
+-/* Opcode is only supported by POWERPC Classic architecture. */
+-#define PPC_OPCODE_CLASSIC 0x10000
+-
+-/* Opcode is only supported by e500x2 Core. */
+-#define PPC_OPCODE_SPE 0x20000
+-
+-/* Opcode is supported by e500x2 Integer select APU. */
+-#define PPC_OPCODE_ISEL 0x40000
+-
+-/* Opcode is an e500 SPE floating point instruction. */
+-#define PPC_OPCODE_EFS 0x80000
+-
+-/* Opcode is supported by branch locking APU. */
+-#define PPC_OPCODE_BRLOCK 0x100000
+-
+-/* Opcode is supported by performance monitor APU. */
+-#define PPC_OPCODE_PMR 0x200000
+-
+-/* Opcode is supported by cache locking APU. */
+-#define PPC_OPCODE_CACHELCK 0x400000
+-
+-/* Opcode is supported by machine check APU. */
+-#define PPC_OPCODE_RFMCI 0x800000
+-
+-/* A macro to extract the major opcode from an instruction. */
+-#define PPC_OP(i) (((i) >> 26) & 0x3f)
+-
+-/* The operands table is an array of struct powerpc_operand. */
+-
+-struct powerpc_operand
+-{
+- /* The number of bits in the operand. */
+- int bits;
+-
+- /* How far the operand is left shifted in the instruction. */
+- int shift;
+-
+- /* Insertion function. This is used by the assembler. To insert an
+- operand value into an instruction, check this field.
+-
+- If it is NULL, execute
+- i |= (op & ((1 << o->bits) - 1)) << o->shift;
+- (i is the instruction which we are filling in, o is a pointer to
+- this structure, and op is the opcode value; this assumes twos
+- complement arithmetic).
+-
+- If this field is not NULL, then simply call it with the
+- instruction and the operand value. It will return the new value
+- of the instruction. If the ERRMSG argument is not NULL, then if
+- the operand value is illegal, *ERRMSG will be set to a warning
+- string (the operand will be inserted in any case). If the
+- operand value is legal, *ERRMSG will be unchanged (most operands
+- can accept any value). */
+- unsigned long (*insert)
+- (unsigned long instruction, long op, int dialect, const char **errmsg);
+-
+- /* Extraction function. This is used by the disassembler. To
+- extract this operand type from an instruction, check this field.
+-
+- If it is NULL, compute
+- op = ((i) >> o->shift) & ((1 << o->bits) - 1);
+- if ((o->flags & PPC_OPERAND_SIGNED) != 0
+- && (op & (1 << (o->bits - 1))) != 0)
+- op -= 1 << o->bits;
+- (i is the instruction, o is a pointer to this structure, and op
+- is the result; this assumes twos complement arithmetic).
+-
+- If this field is not NULL, then simply call it with the
+- instruction value. It will return the value of the operand. If
+- the INVALID argument is not NULL, *INVALID will be set to
+- non-zero if this operand type can not actually be extracted from
+- this operand (i.e., the instruction does not match). If the
+- operand is valid, *INVALID will not be changed. */
+- long (*extract) (unsigned long instruction, int dialect, int *invalid);
+-
+- /* One bit syntax flags. */
+- unsigned long flags;
+-};
+-
+-/* Elements in the table are retrieved by indexing with values from
+- the operands field of the powerpc_opcodes table. */
+-
+-extern const struct powerpc_operand powerpc_operands[];
+-
+-/* Values defined for the flags field of a struct powerpc_operand. */
+-
+-/* This operand takes signed values. */
+-#define PPC_OPERAND_SIGNED (01)
+-
+-/* This operand takes signed values, but also accepts a full positive
+- range of values when running in 32 bit mode. That is, if bits is
+- 16, it takes any value from -0x8000 to 0xffff. In 64 bit mode,
+- this flag is ignored. */
+-#define PPC_OPERAND_SIGNOPT (02)
+-
+-/* This operand does not actually exist in the assembler input. This
+- is used to support extended mnemonics such as mr, for which two
+- operands fields are identical. The assembler should call the
+- insert function with any op value. The disassembler should call
+- the extract function, ignore the return value, and check the value
+- placed in the valid argument. */
+-#define PPC_OPERAND_FAKE (04)
+-
+-/* The next operand should be wrapped in parentheses rather than
+- separated from this one by a comma. This is used for the load and
+- store instructions which want their operands to look like
+- reg,displacement(reg)
+- */
+-#define PPC_OPERAND_PARENS (010)
+-
+-/* This operand may use the symbolic names for the CR fields, which
+- are
+- lt 0 gt 1 eq 2 so 3 un 3
+- cr0 0 cr1 1 cr2 2 cr3 3
+- cr4 4 cr5 5 cr6 6 cr7 7
+- These may be combined arithmetically, as in cr2*4+gt. These are
+- only supported on the PowerPC, not the POWER. */
+-#define PPC_OPERAND_CR (020)
+-
+-/* This operand names a register. The disassembler uses this to print
+- register names with a leading 'r'. */
+-#define PPC_OPERAND_GPR (040)
+-
+-/* This operand names a floating point register. The disassembler
+- prints these with a leading 'f'. */
+-#define PPC_OPERAND_FPR (0100)
+-
+-/* This operand is a relative branch displacement. The disassembler
+- prints these symbolically if possible. */
+-#define PPC_OPERAND_RELATIVE (0200)
+-
+-/* This operand is an absolute branch address. The disassembler
+- prints these symbolically if possible. */
+-#define PPC_OPERAND_ABSOLUTE (0400)
+-
+-/* This operand is optional, and is zero if omitted. This is used for
+- the optional BF and L fields in the comparison instructions. The
+- assembler must count the number of operands remaining on the line,
+- and the number of operands remaining for the opcode, and decide
+- whether this operand is present or not. The disassembler should
+- print this operand out only if it is not zero. */
+-#define PPC_OPERAND_OPTIONAL (01000)
+-
+-/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
+- is omitted, then for the next operand use this operand value plus
+- 1, ignoring the next operand field for the opcode. This wretched
+- hack is needed because the Power rotate instructions can take
+- either 4 or 5 operands. The disassembler should print this operand
+- out regardless of the PPC_OPERAND_OPTIONAL field. */
+-#define PPC_OPERAND_NEXT (02000)
+-
+-/* This operand should be regarded as a negative number for the
+- purposes of overflow checking (i.e., the normal most negative
+- number is disallowed and one more than the normal most positive
+- number is allowed). This flag will only be set for a signed
+- operand. */
+-#define PPC_OPERAND_NEGATIVE (04000)
+-
+-/* This operand names a vector unit register. The disassembler
+- prints these with a leading 'v'. */
+-#define PPC_OPERAND_VR (010000)
+-
+-/* This operand is for the DS field in a DS form instruction. */
+-#define PPC_OPERAND_DS (020000)
+-
+-/* This operand is for the DQ field in a DQ form instruction. */
+-#define PPC_OPERAND_DQ (040000)
+-
+-/* The POWER and PowerPC assemblers use a few macros. We keep them
+- with the operands table for simplicity. The macro table is an
+- array of struct powerpc_macro. */
+-
+-struct powerpc_macro
+-{
+- /* The macro name. */
+- const char *name;
+-
+- /* The number of operands the macro takes. */
+- unsigned int operands;
+-
+- /* One bit flags for the opcode. These are used to indicate which
+- specific processors support the instructions. The values are the
+- same as those for the struct powerpc_opcode flags field. */
+- unsigned long flags;
+-
+- /* A format string to turn the macro into a normal instruction.
+- Each %N in the string is replaced with operand number N (zero
+- based). */
+- const char *format;
+-};
+-
+-extern const struct powerpc_macro powerpc_macros[];
+-extern const int powerpc_num_macros;
+-
+-#endif /* PPC_H */
+diff --git a/arch/ppc64/xmon/setjmp.S b/arch/ppc64/xmon/setjmp.S
+deleted file mode 100644
+--- a/arch/ppc64/xmon/setjmp.S
++++ /dev/null
+@@ -1,73 +0,0 @@
+-/*
+- * Copyright (C) 1996 Paul Mackerras.
+- *
+- * 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.
+- *
+- * NOTE: assert(sizeof(buf) > 184)
+- */
+-#include <asm/processor.h>
+-#include <asm/ppc_asm.h>
+-
+-_GLOBAL(xmon_setjmp)
+- mflr r0
+- std r0,0(r3)
+- std r1,8(r3)
+- std r2,16(r3)
+- mfcr r0
+- std r0,24(r3)
+- std r13,32(r3)
+- std r14,40(r3)
+- std r15,48(r3)
+- std r16,56(r3)
+- std r17,64(r3)
+- std r18,72(r3)
+- std r19,80(r3)
+- std r20,88(r3)
+- std r21,96(r3)
+- std r22,104(r3)
+- std r23,112(r3)
+- std r24,120(r3)
+- std r25,128(r3)
+- std r26,136(r3)
+- std r27,144(r3)
+- std r28,152(r3)
+- std r29,160(r3)
+- std r30,168(r3)
+- std r31,176(r3)
+- li r3,0
+- blr
+-
+-_GLOBAL(xmon_longjmp)
+- cmpdi r4,0
+- bne 1f
+- li r4,1
+-1: ld r13,32(r3)
+- ld r14,40(r3)
+- ld r15,48(r3)
+- ld r16,56(r3)
+- ld r17,64(r3)
+- ld r18,72(r3)
+- ld r19,80(r3)
+- ld r20,88(r3)
+- ld r21,96(r3)
+- ld r22,104(r3)
+- ld r23,112(r3)
+- ld r24,120(r3)
+- ld r25,128(r3)
+- ld r26,136(r3)
+- ld r27,144(r3)
+- ld r28,152(r3)
+- ld r29,160(r3)
+- ld r30,168(r3)
+- ld r31,176(r3)
+- ld r0,24(r3)
+- mtcrf 56,r0
+- ld r0,0(r3)
+- ld r1,8(r3)
+- ld r2,16(r3)
+- mtlr r0
+- mr r3,r4
+- blr
+diff --git a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c
+deleted file mode 100644
+--- a/arch/ppc64/xmon/start.c
++++ /dev/null
+@@ -1,187 +0,0 @@
+-/*
+- * Copyright (C) 1996 Paul Mackerras.
+- *
+- * 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/string.h>
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/sysrq.h>
+-#include <linux/init.h>
+-#include <asm/machdep.h>
+-#include <asm/io.h>
+-#include <asm/page.h>
+-#include <asm/prom.h>
+-#include <asm/processor.h>
+-#include <asm/udbg.h>
+-#include <asm/system.h>
+-#include "nonstdio.h"
+-
+-#ifdef CONFIG_MAGIC_SYSRQ
+-
+-static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
+- struct tty_struct *tty)
+-{
+- /* ensure xmon is enabled */
+- xmon_init(1);
+- debugger(pt_regs);
+-}
+-
+-static struct sysrq_key_op sysrq_xmon_op =
+-{
+- .handler = sysrq_handle_xmon,
+- .help_msg = "Xmon",
+- .action_msg = "Entering xmon",
+-};
+-
+-static int __init setup_xmon_sysrq(void)
+-{
+- register_sysrq_key('x', &sysrq_xmon_op);
+- return 0;
+-}
+-__initcall(setup_xmon_sysrq);
+-#endif /* CONFIG_MAGIC_SYSRQ */
+-
+-int
+-xmon_write(void *handle, void *ptr, int nb)
+-{
+- return udbg_write(ptr, nb);
+-}
+-
+-int
+-xmon_read(void *handle, void *ptr, int nb)
+-{
+- return udbg_read(ptr, nb);
+-}
+-
+-int
+-xmon_read_poll(void)
+-{
+- if (udbg_getc_poll)
+- return udbg_getc_poll();
+- return -1;
+-}
+-
+-FILE *xmon_stdin;
+-FILE *xmon_stdout;
+-
+-int
+-xmon_putc(int c, void *f)
+-{
+- char ch = c;
+-
+- if (c == '\n')
+- xmon_putc('\r', f);
+- return xmon_write(f, &ch, 1) == 1? c: -1;
+-}
+-
+-int
+-xmon_putchar(int c)
+-{
+- return xmon_putc(c, xmon_stdout);
+-}
+-
+-int
+-xmon_fputs(char *str, void *f)
+-{
+- int n = strlen(str);
+-
+- return xmon_write(f, str, n) == n? 0: -1;
+-}
+-
+-int
+-xmon_readchar(void)
+-{
+- char ch;
+-
+- for (;;) {
+- switch (xmon_read(xmon_stdin, &ch, 1)) {
+- case 1:
+- return ch;
+- case -1:
+- xmon_printf("read(stdin) returned -1\r\n", 0, 0);
+- return -1;
+- }
+- }
+-}
+-
+-static char line[256];
+-static char *lineptr;
+-static int lineleft;
+-
+-int
+-xmon_getchar(void)
+-{
+- int c;
+-
+- if (lineleft == 0) {
+- lineptr = line;
+- for (;;) {
+- c = xmon_readchar();
+- if (c == -1 || c == 4)
+- break;
+- if (c == '\r' || c == '\n') {
+- *lineptr++ = '\n';
+- xmon_putchar('\n');
+- break;
+- }
+- switch (c) {
+- case 0177:
+- case '\b':
+- if (lineptr > line) {
+- xmon_putchar('\b');
+- xmon_putchar(' ');
+- xmon_putchar('\b');
+- --lineptr;
+- }
+- break;
+- case 'U' & 0x1F:
+- while (lineptr > line) {
+- xmon_putchar('\b');
+- xmon_putchar(' ');
+- xmon_putchar('\b');
+- --lineptr;
+- }
+- break;
+- default:
+- if (lineptr >= &line[sizeof(line) - 1])
+- xmon_putchar('\a');
+- else {
+- xmon_putchar(c);
+- *lineptr++ = c;
+- }
+- }
+- }
+- lineleft = lineptr - line;
+- lineptr = line;
+- }
+- if (lineleft == 0)
+- return -1;
+- --lineleft;
+- return *lineptr++;
+-}
+-
+-char *
+-xmon_fgets(char *str, int nb, void *f)
+-{
+- char *p;
+- int c;
+-
+- for (p = str; p < str + nb - 1; ) {
+- c = xmon_getchar();
+- if (c == -1) {
+- if (p == str)
+- return NULL;
+- break;
+- }
+- *p++ = c;
+- if (c == '\n')
+- break;
+- }
+- *p = 0;
+- return str;
+-}
+diff --git a/arch/ppc64/xmon/subr_prf.c b/arch/ppc64/xmon/subr_prf.c
+deleted file mode 100644
+--- a/arch/ppc64/xmon/subr_prf.c
++++ /dev/null
+@@ -1,55 +0,0 @@
+-/*
+- * Written by Cort Dougan to replace the version originally used
+- * by Paul Mackerras, which came from NetBSD and thus had copyright
+- * conflicts with Linux.
+- *
+- * This file makes liberal use of the standard linux utility
+- * routines to reduce the size of the binary. We assume we can
+- * trust some parts of Linux inside the debugger.
+- * -- Cort (cort at cs.nmt.edu)
+- *
+- * Copyright (C) 1999 Cort Dougan.
+- *
+- * 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/kernel.h>
+-#include <linux/string.h>
+-#include <stdarg.h>
+-#include "nonstdio.h"
+-
+-extern int xmon_write(void *, void *, int);
+-
+-void
+-xmon_vfprintf(void *f, const char *fmt, va_list ap)
+-{
+- static char xmon_buf[2048];
+- int n;
+-
+- n = vsprintf(xmon_buf, fmt, ap);
+- xmon_write(f, xmon_buf, n);
+-}
+-
+-void
+-xmon_printf(const char *fmt, ...)
+-{
+- va_list ap;
+-
+- va_start(ap, fmt);
+- xmon_vfprintf(stdout, fmt, ap);
+- va_end(ap);
+-}
+-
+-void
+-xmon_fprintf(void *f, const char *fmt, ...)
+-{
+- va_list ap;
+-
+- va_start(ap, fmt);
+- xmon_vfprintf(f, fmt, ap);
+- va_end(ap);
+-}
+-
+diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
+deleted file mode 100644
+--- a/arch/ppc64/xmon/xmon.c
++++ /dev/null
+@@ -1,2514 +0,0 @@
+-/*
+- * Routines providing a simple monitor for use on the PowerMac.
+- *
+- * Copyright (C) 1996 Paul Mackerras.
+- *
+- * 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/errno.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/mm.h>
+-#include <linux/reboot.h>
+-#include <linux/delay.h>
+-#include <linux/kallsyms.h>
+-#include <linux/cpumask.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/string.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/processor.h>
+-#include <asm/pgtable.h>
+-#include <asm/mmu.h>
+-#include <asm/mmu_context.h>
+-#include <asm/paca.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/cputable.h>
+-#include <asm/rtas.h>
+-#include <asm/sstep.h>
+-#include <asm/bug.h>
+-#include <asm/hvcall.h>
+-
+-#include "nonstdio.h"
+-#include "privinst.h"
+-
+-#define scanhex xmon_scanhex
+-#define skipbl xmon_skipbl
+-
+-#ifdef CONFIG_SMP
+-cpumask_t cpus_in_xmon = CPU_MASK_NONE;
+-static unsigned long xmon_taken = 1;
+-static int xmon_owner;
+-static int xmon_gate;
+-#endif /* CONFIG_SMP */
+-
+-static unsigned long in_xmon = 0;
+-
+-static unsigned long adrs;
+-static int size = 1;
+-#define MAX_DUMP (128 * 1024)
+-static unsigned long ndump = 64;
+-static unsigned long nidump = 16;
+-static unsigned long ncsum = 4096;
+-static int termch;
+-static char tmpstr[128];
+-
+-#define JMP_BUF_LEN (184/sizeof(long))
+-static long bus_error_jmp[JMP_BUF_LEN];
+-static int catch_memory_errors;
+-static long *xmon_fault_jmp[NR_CPUS];
+-#define setjmp xmon_setjmp
+-#define longjmp xmon_longjmp
+-
+-/* Breakpoint stuff */
+-struct bpt {
+- unsigned long address;
+- unsigned int instr[2];
+- atomic_t ref_count;
+- int enabled;
+- unsigned long pad;
+-};
+-
+-/* Bits in bpt.enabled */
+-#define BP_IABR_TE 1 /* IABR translation enabled */
+-#define BP_IABR 2
+-#define BP_TRAP 8
+-#define BP_DABR 0x10
+-
+-#define NBPTS 256
+-static struct bpt bpts[NBPTS];
+-static struct bpt dabr;
+-static struct bpt *iabr;
+-static unsigned bpinstr = 0x7fe00008; /* trap */
+-
+-#define BP_NUM(bp) ((bp) - bpts + 1)
+-
+-/* Prototypes */
+-static int cmds(struct pt_regs *);
+-static int mread(unsigned long, void *, int);
+-static int mwrite(unsigned long, void *, int);
+-static int handle_fault(struct pt_regs *);
+-static void byterev(unsigned char *, int);
+-static void memex(void);
+-static int bsesc(void);
+-static void dump(void);
+-static void prdump(unsigned long, long);
+-static int ppc_inst_dump(unsigned long, long, int);
+-void print_address(unsigned long);
+-static void backtrace(struct pt_regs *);
+-static void excprint(struct pt_regs *);
+-static void prregs(struct pt_regs *);
+-static void memops(int);
+-static void memlocate(void);
+-static void memzcan(void);
+-static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
+-int skipbl(void);
+-int scanhex(unsigned long *valp);
+-static void scannl(void);
+-static int hexdigit(int);
+-void getstring(char *, int);
+-static void flush_input(void);
+-static int inchar(void);
+-static void take_input(char *);
+-static unsigned long read_spr(int);
+-static void write_spr(int, unsigned long);
+-static void super_regs(void);
+-static void remove_bpts(void);
+-static void insert_bpts(void);
+-static void remove_cpu_bpts(void);
+-static void insert_cpu_bpts(void);
+-static struct bpt *at_breakpoint(unsigned long pc);
+-static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
+-static int do_step(struct pt_regs *);
+-static void bpt_cmds(void);
+-static void cacheflush(void);
+-static int cpu_cmd(void);
+-static void csum(void);
+-static void bootcmds(void);
+-void dump_segments(void);
+-static void symbol_lookup(void);
+-static void xmon_print_symbol(unsigned long address, const char *mid,
+- const char *after);
+-static const char *getvecname(unsigned long vec);
+-
+-static void debug_trace(void);
+-
+-extern int print_insn_powerpc(unsigned long, unsigned long, int);
+-extern void printf(const char *fmt, ...);
+-extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
+-extern int xmon_putc(int c, void *f);
+-extern int putchar(int ch);
+-extern int xmon_read_poll(void);
+-extern int setjmp(long *);
+-extern void longjmp(long *, int);
+-extern unsigned long _ASR;
+-
+-#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
+-
+-#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+- || ('a' <= (c) && (c) <= 'f') \
+- || ('A' <= (c) && (c) <= 'F'))
+-#define isalnum(c) (('0' <= (c) && (c) <= '9') \
+- || ('a' <= (c) && (c) <= 'z') \
+- || ('A' <= (c) && (c) <= 'Z'))
+-#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
+-
+-static char *help_string = "\
+-Commands:\n\
+- b show breakpoints\n\
+- bd set data breakpoint\n\
+- bi set instruction breakpoint\n\
+- bc clear breakpoint\n"
+-#ifdef CONFIG_SMP
+- "\
+- c print cpus stopped in xmon\n\
+- c# try to switch to cpu number h (in hex)\n"
+-#endif
+- "\
+- C checksum\n\
+- d dump bytes\n\
+- di dump instructions\n\
+- df dump float values\n\
+- dd dump double values\n\
+- e print exception information\n\
+- f flush cache\n\
+- la lookup symbol+offset of specified address\n\
+- ls lookup address of specified symbol\n\
+- m examine/change memory\n\
+- mm move a block of memory\n\
+- ms set a block of memory\n\
+- md compare two blocks of memory\n\
+- ml locate a block of memory\n\
+- mz zero a block of memory\n\
+- mi show information about memory allocation\n\
+- p show the task list\n\
+- r print registers\n\
+- s single step\n\
+- S print special registers\n\
+- t print backtrace\n\
+- T Enable/Disable PPCDBG flags\n\
+- x exit monitor and recover\n\
+- X exit monitor and dont recover\n\
+- u dump segment table or SLB\n\
+- ? help\n"
+- "\
+- zr reboot\n\
+- zh halt\n"
+-;
+-
+-static struct pt_regs *xmon_regs;
+-
+-extern inline void sync(void)
+-{
+- asm volatile("sync; isync");
+-}
+-
+-/* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
+- A PPC stack frame looks like this:
+-
+- High Address
+- Back Chain
+- FP reg save area
+- GP reg save area
+- Local var space
+- Parameter save area (SP+48)
+- TOC save area (SP+40)
+- link editor doubleword (SP+32)
+- compiler doubleword (SP+24)
+- LR save (SP+16)
+- CR save (SP+8)
+- Back Chain (SP+0)
+-
+- Note that the LR (ret addr) may not be saved in the current frame if
+- no functions have been called from the current function.
+- */
+-
+-/*
+- * Disable surveillance (the service processor watchdog function)
+- * while we are in xmon.
+- * XXX we should re-enable it when we leave. :)
+- */
+-#define SURVEILLANCE_TOKEN 9000
+-
+-static inline void disable_surveillance(void)
+-{
+-#ifdef CONFIG_PPC_PSERIES
+- /* Since this can't be a module, args should end up below 4GB. */
+- static struct rtas_args args;
+-
+- /*
+- * At this point we have got all the cpus we can into
+- * xmon, so there is hopefully no other cpu calling RTAS
+- * at the moment, even though we don't take rtas.lock.
+- * If we did try to take rtas.lock there would be a
+- * real possibility of deadlock.
+- */
+- args.token = rtas_token("set-indicator");
+- if (args.token == RTAS_UNKNOWN_SERVICE)
+- return;
+- args.nargs = 3;
+- args.nret = 1;
+- args.rets = &args.args[3];
+- args.args[0] = SURVEILLANCE_TOKEN;
+- args.args[1] = 0;
+- args.args[2] = 0;
+- enter_rtas(__pa(&args));
+-#endif /* CONFIG_PPC_PSERIES */
+-}
+-
+-#ifdef CONFIG_SMP
+-static int xmon_speaker;
+-
+-static void get_output_lock(void)
+-{
+- int me = smp_processor_id() + 0x100;
+- int last_speaker = 0, prev;
+- long timeout;
+-
+- if (xmon_speaker == me)
+- return;
+- for (;;) {
+- if (xmon_speaker == 0) {
+- last_speaker = cmpxchg(&xmon_speaker, 0, me);
+- if (last_speaker == 0)
+- return;
+- }
+- timeout = 10000000;
+- while (xmon_speaker == last_speaker) {
+- if (--timeout > 0)
+- continue;
+- /* hostile takeover */
+- prev = cmpxchg(&xmon_speaker, last_speaker, me);
+- if (prev == last_speaker)
+- return;
+- break;
+- }
+- }
+-}
+-
+-static void release_output_lock(void)
+-{
+- xmon_speaker = 0;
+-}
+-#endif
+-
+-int xmon_core(struct pt_regs *regs, int fromipi)
+-{
+- int cmd = 0;
+- unsigned long msr;
+- struct bpt *bp;
+- long recurse_jmp[JMP_BUF_LEN];
+- unsigned long offset;
+-#ifdef CONFIG_SMP
+- int cpu;
+- int secondary;
+- unsigned long timeout;
+-#endif
+-
+- msr = get_msr();
+- set_msrd(msr & ~MSR_EE); /* disable interrupts */
+-
+- bp = in_breakpoint_table(regs->nip, &offset);
+- if (bp != NULL) {
+- regs->nip = bp->address + offset;
+- atomic_dec(&bp->ref_count);
+- }
+-
+- remove_cpu_bpts();
+-
+-#ifdef CONFIG_SMP
+- cpu = smp_processor_id();
+- if (cpu_isset(cpu, cpus_in_xmon)) {
+- get_output_lock();
+- excprint(regs);
+- printf("cpu 0x%x: Exception %lx %s in xmon, "
+- "returning to main loop\n",
+- cpu, regs->trap, getvecname(TRAP(regs)));
+- release_output_lock();
+- longjmp(xmon_fault_jmp[cpu], 1);
+- }
+-
+- if (setjmp(recurse_jmp) != 0) {
+- if (!in_xmon || !xmon_gate) {
+- get_output_lock();
+- printf("xmon: WARNING: bad recursive fault "
+- "on cpu 0x%x\n", cpu);
+- release_output_lock();
+- goto waiting;
+- }
+- secondary = !(xmon_taken && cpu == xmon_owner);
+- goto cmdloop;
+- }
+-
+- xmon_fault_jmp[cpu] = recurse_jmp;
+- cpu_set(cpu, cpus_in_xmon);
+-
+- bp = NULL;
+- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
+- bp = at_breakpoint(regs->nip);
+- if (bp || (regs->msr & MSR_RI) == 0)
+- fromipi = 0;
+-
+- if (!fromipi) {
+- get_output_lock();
+- excprint(regs);
+- if (bp) {
+- printf("cpu 0x%x stopped at breakpoint 0x%x (",
+- cpu, BP_NUM(bp));
+- xmon_print_symbol(regs->nip, " ", ")\n");
+- }
+- if ((regs->msr & MSR_RI) == 0)
+- printf("WARNING: exception is not recoverable, "
+- "can't continue\n");
+- release_output_lock();
+- }
+-
+- waiting:
+- secondary = 1;
+- while (secondary && !xmon_gate) {
+- if (in_xmon == 0) {
+- if (fromipi)
+- goto leave;
+- secondary = test_and_set_bit(0, &in_xmon);
+- }
+- barrier();
+- }
+-
+- if (!secondary && !xmon_gate) {
+- /* we are the first cpu to come in */
+- /* interrupt other cpu(s) */
+- int ncpus = num_online_cpus();
+-
+- xmon_owner = cpu;
+- mb();
+- if (ncpus > 1) {
+- smp_send_debugger_break(MSG_ALL_BUT_SELF);
+- /* wait for other cpus to come in */
+- for (timeout = 100000000; timeout != 0; --timeout) {
+- if (cpus_weight(cpus_in_xmon) >= ncpus)
+- break;
+- barrier();
+- }
+- }
+- remove_bpts();
+- disable_surveillance();
+- /* for breakpoint or single step, print the current instr. */
+- if (bp || TRAP(regs) == 0xd00)
+- ppc_inst_dump(regs->nip, 1, 0);
+- printf("enter ? for help\n");
+- mb();
+- xmon_gate = 1;
+- barrier();
+- }
+-
+- cmdloop:
+- while (in_xmon) {
+- if (secondary) {
+- if (cpu == xmon_owner) {
+- if (!test_and_set_bit(0, &xmon_taken)) {
+- secondary = 0;
+- continue;
+- }
+- /* missed it */
+- while (cpu == xmon_owner)
+- barrier();
+- }
+- barrier();
+- } else {
+- cmd = cmds(regs);
+- if (cmd != 0) {
+- /* exiting xmon */
+- insert_bpts();
+- xmon_gate = 0;
+- wmb();
+- in_xmon = 0;
+- break;
+- }
+- /* have switched to some other cpu */
+- secondary = 1;
+- }
+- }
+- leave:
+- cpu_clear(cpu, cpus_in_xmon);
+- xmon_fault_jmp[cpu] = NULL;
+-
+-#else
+- /* UP is simple... */
+- if (in_xmon) {
+- printf("Exception %lx %s in xmon, returning to main loop\n",
+- regs->trap, getvecname(TRAP(regs)));
+- longjmp(xmon_fault_jmp[0], 1);
+- }
+- if (setjmp(recurse_jmp) == 0) {
+- xmon_fault_jmp[0] = recurse_jmp;
+- in_xmon = 1;
+-
+- excprint(regs);
+- bp = at_breakpoint(regs->nip);
+- if (bp) {
+- printf("Stopped at breakpoint %x (", BP_NUM(bp));
+- xmon_print_symbol(regs->nip, " ", ")\n");
+- }
+- if ((regs->msr & MSR_RI) == 0)
+- printf("WARNING: exception is not recoverable, "
+- "can't continue\n");
+- remove_bpts();
+- disable_surveillance();
+- /* for breakpoint or single step, print the current instr. */
+- if (bp || TRAP(regs) == 0xd00)
+- ppc_inst_dump(regs->nip, 1, 0);
+- printf("enter ? for help\n");
+- }
+-
+- cmd = cmds(regs);
+-
+- insert_bpts();
+- in_xmon = 0;
+-#endif
+-
+- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
+- bp = at_breakpoint(regs->nip);
+- if (bp != NULL) {
+- int stepped = emulate_step(regs, bp->instr[0]);
+- if (stepped == 0) {
+- regs->nip = (unsigned long) &bp->instr[0];
+- atomic_inc(&bp->ref_count);
+- } else if (stepped < 0) {
+- printf("Couldn't single-step %s instruction\n",
+- (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
+- }
+- }
+- }
+-
+- insert_cpu_bpts();
+-
+- set_msrd(msr); /* restore interrupt enable */
+-
+- return cmd != 'X';
+-}
+-
+-int xmon(struct pt_regs *excp)
+-{
+- struct pt_regs regs;
+-
+- if (excp == NULL) {
+- /* Ok, grab regs as they are now.
+- This won't do a particularily good job because the
+- prologue has already been executed.
+- ToDo: We could reach back into the callers save
+- area to do a better job of representing the
+- caller's state.
+- */
+- asm volatile ("std 0,0(%0)\n\
+- std 1,8(%0)\n\
+- std 2,16(%0)\n\
+- std 3,24(%0)\n\
+- std 4,32(%0)\n\
+- std 5,40(%0)\n\
+- std 6,48(%0)\n\
+- std 7,56(%0)\n\
+- std 8,64(%0)\n\
+- std 9,72(%0)\n\
+- std 10,80(%0)\n\
+- std 11,88(%0)\n\
+- std 12,96(%0)\n\
+- std 13,104(%0)\n\
+- std 14,112(%0)\n\
+- std 15,120(%0)\n\
+- std 16,128(%0)\n\
+- std 17,136(%0)\n\
+- std 18,144(%0)\n\
+- std 19,152(%0)\n\
+- std 20,160(%0)\n\
+- std 21,168(%0)\n\
+- std 22,176(%0)\n\
+- std 23,184(%0)\n\
+- std 24,192(%0)\n\
+- std 25,200(%0)\n\
+- std 26,208(%0)\n\
+- std 27,216(%0)\n\
+- std 28,224(%0)\n\
+- std 29,232(%0)\n\
+- std 30,240(%0)\n\
+- std 31,248(%0)" : : "b" (®s));
+-
+- regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
+- regs.msr = get_msr();
+- regs.ctr = get_ctr();
+- regs.xer = get_xer();
+- regs.ccr = get_cr();
+- regs.trap = 0;
+- excp = ®s;
+- }
+- return xmon_core(excp, 0);
+-}
+-
+-int xmon_bpt(struct pt_regs *regs)
+-{
+- struct bpt *bp;
+- unsigned long offset;
+-
+- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
+- return 0;
+-
+- /* Are we at the trap at bp->instr[1] for some bp? */
+- bp = in_breakpoint_table(regs->nip, &offset);
+- if (bp != NULL && offset == 4) {
+- regs->nip = bp->address + 4;
+- atomic_dec(&bp->ref_count);
+- return 1;
+- }
+-
+- /* Are we at a breakpoint? */
+- bp = at_breakpoint(regs->nip);
+- if (!bp)
+- return 0;
+-
+- xmon_core(regs, 0);
+-
+- return 1;
+-}
+-
+-int xmon_sstep(struct pt_regs *regs)
+-{
+- if (user_mode(regs))
+- return 0;
+- xmon_core(regs, 0);
+- return 1;
+-}
+-
+-int xmon_dabr_match(struct pt_regs *regs)
+-{
+- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
+- return 0;
+- if (dabr.enabled == 0)
+- return 0;
+- xmon_core(regs, 0);
+- return 1;
+-}
+-
+-int xmon_iabr_match(struct pt_regs *regs)
+-{
+- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
+- return 0;
+- if (iabr == 0)
+- return 0;
+- xmon_core(regs, 0);
+- return 1;
+-}
+-
+-int xmon_ipi(struct pt_regs *regs)
+-{
+-#ifdef CONFIG_SMP
+- if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
+- xmon_core(regs, 1);
+-#endif
+- return 0;
+-}
+-
+-int xmon_fault_handler(struct pt_regs *regs)
+-{
+- struct bpt *bp;
+- unsigned long offset;
+-
+- if (in_xmon && catch_memory_errors)
+- handle_fault(regs); /* doesn't return */
+-
+- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
+- bp = in_breakpoint_table(regs->nip, &offset);
+- if (bp != NULL) {
+- regs->nip = bp->address + offset;
+- atomic_dec(&bp->ref_count);
+- }
+- }
+-
+- return 0;
+-}
+-
+-static struct bpt *at_breakpoint(unsigned long pc)
+-{
+- int i;
+- struct bpt *bp;
+-
+- bp = bpts;
+- for (i = 0; i < NBPTS; ++i, ++bp)
+- if (bp->enabled && pc == bp->address)
+- return bp;
+- return NULL;
+-}
+-
+-static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
+-{
+- unsigned long off;
+-
+- off = nip - (unsigned long) bpts;
+- if (off >= sizeof(bpts))
+- return NULL;
+- off %= sizeof(struct bpt);
+- if (off != offsetof(struct bpt, instr[0])
+- && off != offsetof(struct bpt, instr[1]))
+- return NULL;
+- *offp = off - offsetof(struct bpt, instr[0]);
+- return (struct bpt *) (nip - off);
+-}
+-
+-static struct bpt *new_breakpoint(unsigned long a)
+-{
+- struct bpt *bp;
+-
+- a &= ~3UL;
+- bp = at_breakpoint(a);
+- if (bp)
+- return bp;
+-
+- for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
+- if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
+- bp->address = a;
+- bp->instr[1] = bpinstr;
+- store_inst(&bp->instr[1]);
+- return bp;
+- }
+- }
+-
+- printf("Sorry, no free breakpoints. Please clear one first.\n");
+- return NULL;
+-}
+-
+-static void insert_bpts(void)
+-{
+- int i;
+- struct bpt *bp;
+-
+- bp = bpts;
+- for (i = 0; i < NBPTS; ++i, ++bp) {
+- if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
+- continue;
+- if (mread(bp->address, &bp->instr[0], 4) != 4) {
+- printf("Couldn't read instruction at %lx, "
+- "disabling breakpoint there\n", bp->address);
+- bp->enabled = 0;
+- continue;
+- }
+- if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
+- printf("Breakpoint at %lx is on an mtmsrd or rfid "
+- "instruction, disabling it\n", bp->address);
+- bp->enabled = 0;
+- continue;
+- }
+- store_inst(&bp->instr[0]);
+- if (bp->enabled & BP_IABR)
+- continue;
+- if (mwrite(bp->address, &bpinstr, 4) != 4) {
+- printf("Couldn't write instruction at %lx, "
+- "disabling breakpoint there\n", bp->address);
+- bp->enabled &= ~BP_TRAP;
+- continue;
+- }
+- store_inst((void *)bp->address);
+- }
+-}
+-
+-static void insert_cpu_bpts(void)
+-{
+- if (dabr.enabled)
+- set_dabr(dabr.address | (dabr.enabled & 7));
+- if (iabr && cpu_has_feature(CPU_FTR_IABR))
+- set_iabr(iabr->address
+- | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
+-}
+-
+-static void remove_bpts(void)
+-{
+- int i;
+- struct bpt *bp;
+- unsigned instr;
+-
+- bp = bpts;
+- for (i = 0; i < NBPTS; ++i, ++bp) {
+- if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
+- continue;
+- if (mread(bp->address, &instr, 4) == 4
+- && instr == bpinstr
+- && mwrite(bp->address, &bp->instr, 4) != 4)
+- printf("Couldn't remove breakpoint at %lx\n",
+- bp->address);
+- else
+- store_inst((void *)bp->address);
+- }
+-}
+-
+-static void remove_cpu_bpts(void)
+-{
+- set_dabr(0);
+- if (cpu_has_feature(CPU_FTR_IABR))
+- set_iabr(0);
+-}
+-
+-/* Command interpreting routine */
+-static char *last_cmd;
+-
+-static int
+-cmds(struct pt_regs *excp)
+-{
+- int cmd = 0;
+-
+- last_cmd = NULL;
+- xmon_regs = excp;
+- for(;;) {
+-#ifdef CONFIG_SMP
+- printf("%x:", smp_processor_id());
+-#endif /* CONFIG_SMP */
+- printf("mon> ");
+- fflush(stdout);
+- flush_input();
+- termch = 0;
+- cmd = skipbl();
+- if( cmd == '\n' ) {
+- if (last_cmd == NULL)
+- continue;
+- take_input(last_cmd);
+- last_cmd = NULL;
+- cmd = inchar();
+- }
+- switch (cmd) {
+- case 'm':
+- cmd = inchar();
+- switch (cmd) {
+- case 'm':
+- case 's':
+- case 'd':
+- memops(cmd);
+- break;
+- case 'l':
+- memlocate();
+- break;
+- case 'z':
+- memzcan();
+- break;
+- case 'i':
+- show_mem();
+- break;
+- default:
+- termch = cmd;
+- memex();
+- }
+- break;
+- case 'd':
+- dump();
+- break;
+- case 'l':
+- symbol_lookup();
+- break;
+- case 'r':
+- prregs(excp); /* print regs */
+- break;
+- case 'e':
+- excprint(excp);
+- break;
+- case 'S':
+- super_regs();
+- break;
+- case 't':
+- backtrace(excp);
+- break;
+- case 'f':
+- cacheflush();
+- break;
+- case 's':
+- if (do_step(excp))
+- return cmd;
+- break;
+- case 'x':
+- case 'X':
+- case EOF:
+- return cmd;
+- case '?':
+- printf(help_string);
+- break;
+- case 'p':
+- show_state();
+- break;
+- case 'b':
+- bpt_cmds();
+- break;
+- case 'C':
+- csum();
+- break;
+- case 'c':
+- if (cpu_cmd())
+- return 0;
+- break;
+- case 'z':
+- bootcmds();
+- break;
+- case 'T':
+- debug_trace();
+- break;
+- case 'u':
+- dump_segments();
+- break;
+- default:
+- printf("Unrecognized command: ");
+- do {
+- if (' ' < cmd && cmd <= '~')
+- putchar(cmd);
+- else
+- printf("\\x%x", cmd);
+- cmd = inchar();
+- } while (cmd != '\n');
+- printf(" (type ? for help)\n");
+- break;
+- }
+- }
+-}
+-
+-/*
+- * Step a single instruction.
+- * Some instructions we emulate, others we execute with MSR_SE set.
+- */
+-static int do_step(struct pt_regs *regs)
+-{
+- unsigned int instr;
+- int stepped;
+-
+- /* check we are in 64-bit kernel mode, translation enabled */
+- if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
+- if (mread(regs->nip, &instr, 4) == 4) {
+- stepped = emulate_step(regs, instr);
+- if (stepped < 0) {
+- printf("Couldn't single-step %s instruction\n",
+- (IS_RFID(instr)? "rfid": "mtmsrd"));
+- return 0;
+- }
+- if (stepped > 0) {
+- regs->trap = 0xd00 | (regs->trap & 1);
+- printf("stepped to ");
+- xmon_print_symbol(regs->nip, " ", "\n");
+- ppc_inst_dump(regs->nip, 1, 0);
+- return 0;
+- }
+- }
+- }
+- regs->msr |= MSR_SE;
+- return 1;
+-}
+-
+-static void bootcmds(void)
+-{
+- int cmd;
+-
+- cmd = inchar();
+- if (cmd == 'r')
+- ppc_md.restart(NULL);
+- else if (cmd == 'h')
+- ppc_md.halt();
+- else if (cmd == 'p')
+- ppc_md.power_off();
+-}
+-
+-static int cpu_cmd(void)
+-{
+-#ifdef CONFIG_SMP
+- unsigned long cpu;
+- int timeout;
+- int count;
+-
+- if (!scanhex(&cpu)) {
+- /* print cpus waiting or in xmon */
+- printf("cpus stopped:");
+- count = 0;
+- for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+- if (cpu_isset(cpu, cpus_in_xmon)) {
+- if (count == 0)
+- printf(" %x", cpu);
+- ++count;
+- } else {
+- if (count > 1)
+- printf("-%x", cpu - 1);
+- count = 0;
+- }
+- }
+- if (count > 1)
+- printf("-%x", NR_CPUS - 1);
+- printf("\n");
+- return 0;
+- }
+- /* try to switch to cpu specified */
+- if (!cpu_isset(cpu, cpus_in_xmon)) {
+- printf("cpu 0x%x isn't in xmon\n", cpu);
+- return 0;
+- }
+- xmon_taken = 0;
+- mb();
+- xmon_owner = cpu;
+- timeout = 10000000;
+- while (!xmon_taken) {
+- if (--timeout == 0) {
+- if (test_and_set_bit(0, &xmon_taken))
+- break;
+- /* take control back */
+- mb();
+- xmon_owner = smp_processor_id();
+- printf("cpu %u didn't take control\n", cpu);
+- return 0;
+- }
+- barrier();
+- }
+- return 1;
+-#else
+- return 0;
+-#endif /* CONFIG_SMP */
+-}
+-
+-static unsigned short fcstab[256] = {
+- 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+- 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+- 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+- 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+- 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+- 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+- 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+- 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+- 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+- 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+- 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+- 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+- 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+- 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+- 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+- 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+- 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+- 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+- 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+- 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+- 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+- 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+- 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+- 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+- 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+- 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+- 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+- 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+- 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+- 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+- 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+- 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+-};
+-
+-#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
+-
+-static void
+-csum(void)
+-{
+- unsigned int i;
+- unsigned short fcs;
+- unsigned char v;
+-
+- if (!scanhex(&adrs))
+- return;
+- if (!scanhex(&ncsum))
+- return;
+- fcs = 0xffff;
+- for (i = 0; i < ncsum; ++i) {
+- if (mread(adrs+i, &v, 1) == 0) {
+- printf("csum stopped at %x\n", adrs+i);
+- break;
+- }
+- fcs = FCS(fcs, v);
+- }
+- printf("%x\n", fcs);
+-}
+-
+-/*
+- * Check if this is a suitable place to put a breakpoint.
+- */
+-static long check_bp_loc(unsigned long addr)
+-{
+- unsigned int instr;
+-
+- addr &= ~3;
+- if (addr < KERNELBASE) {
+- printf("Breakpoints may only be placed at kernel addresses\n");
+- return 0;
+- }
+- if (!mread(addr, &instr, sizeof(instr))) {
+- printf("Can't read instruction at address %lx\n", addr);
+- return 0;
+- }
+- if (IS_MTMSRD(instr) || IS_RFID(instr)) {
+- printf("Breakpoints may not be placed on mtmsrd or rfid "
+- "instructions\n");
+- return 0;
+- }
+- return 1;
+-}
+-
+-static char *breakpoint_help_string =
+- "Breakpoint command usage:\n"
+- "b show breakpoints\n"
+- "b <addr> [cnt] set breakpoint at given instr addr\n"
+- "bc clear all breakpoints\n"
+- "bc <n/addr> clear breakpoint number n or at addr\n"
+- "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
+- "bd <addr> [cnt] set hardware data breakpoint\n"
+- "";
+-
+-static void
+-bpt_cmds(void)
+-{
+- int cmd;
+- unsigned long a;
+- int mode, i;
+- struct bpt *bp;
+- const char badaddr[] = "Only kernel addresses are permitted "
+- "for breakpoints\n";
+-
+- cmd = inchar();
+- switch (cmd) {
+- case 'd': /* bd - hardware data breakpoint */
+- mode = 7;
+- cmd = inchar();
+- if (cmd == 'r')
+- mode = 5;
+- else if (cmd == 'w')
+- mode = 6;
+- else
+- termch = cmd;
+- dabr.address = 0;
+- dabr.enabled = 0;
+- if (scanhex(&dabr.address)) {
+- if (dabr.address < KERNELBASE) {
+- printf(badaddr);
+- break;
+- }
+- dabr.address &= ~7;
+- dabr.enabled = mode | BP_DABR;
+- }
+- break;
+-
+- case 'i': /* bi - hardware instr breakpoint */
+- if (!cpu_has_feature(CPU_FTR_IABR)) {
+- printf("Hardware instruction breakpoint "
+- "not supported on this cpu\n");
+- break;
+- }
+- if (iabr) {
+- iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
+- iabr = NULL;
+- }
+- if (!scanhex(&a))
+- break;
+- if (!check_bp_loc(a))
+- break;
+- bp = new_breakpoint(a);
+- if (bp != NULL) {
+- bp->enabled |= BP_IABR | BP_IABR_TE;
+- iabr = bp;
+- }
+- break;
+-
+- case 'c':
+- if (!scanhex(&a)) {
+- /* clear all breakpoints */
+- for (i = 0; i < NBPTS; ++i)
+- bpts[i].enabled = 0;
+- iabr = NULL;
+- dabr.enabled = 0;
+- printf("All breakpoints cleared\n");
+- break;
+- }
+-
+- if (a <= NBPTS && a >= 1) {
+- /* assume a breakpoint number */
+- bp = &bpts[a-1]; /* bp nums are 1 based */
+- } else {
+- /* assume a breakpoint address */
+- bp = at_breakpoint(a);
+- if (bp == 0) {
+- printf("No breakpoint at %x\n", a);
+- break;
+- }
+- }
+-
+- printf("Cleared breakpoint %x (", BP_NUM(bp));
+- xmon_print_symbol(bp->address, " ", ")\n");
+- bp->enabled = 0;
+- break;
+-
+- default:
+- termch = cmd;
+- cmd = skipbl();
+- if (cmd == '?') {
+- printf(breakpoint_help_string);
+- break;
+- }
+- termch = cmd;
+- if (!scanhex(&a)) {
+- /* print all breakpoints */
+- printf(" type address\n");
+- if (dabr.enabled) {
+- printf(" data %.16lx [", dabr.address);
+- if (dabr.enabled & 1)
+- printf("r");
+- if (dabr.enabled & 2)
+- printf("w");
+- printf("]\n");
+- }
+- for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
+- if (!bp->enabled)
+- continue;
+- printf("%2x %s ", BP_NUM(bp),
+- (bp->enabled & BP_IABR)? "inst": "trap");
+- xmon_print_symbol(bp->address, " ", "\n");
+- }
+- break;
+- }
+-
+- if (!check_bp_loc(a))
+- break;
+- bp = new_breakpoint(a);
+- if (bp != NULL)
+- bp->enabled |= BP_TRAP;
+- break;
+- }
+-}
+-
+-/* Very cheap human name for vector lookup. */
+-static
+-const char *getvecname(unsigned long vec)
+-{
+- char *ret;
+-
+- switch (vec) {
+- case 0x100: ret = "(System Reset)"; break;
+- case 0x200: ret = "(Machine Check)"; break;
+- case 0x300: ret = "(Data Access)"; break;
+- case 0x380: ret = "(Data SLB Access)"; break;
+- case 0x400: ret = "(Instruction Access)"; break;
+- case 0x480: ret = "(Instruction SLB Access)"; break;
+- case 0x500: ret = "(Hardware Interrupt)"; break;
+- case 0x600: ret = "(Alignment)"; break;
+- case 0x700: ret = "(Program Check)"; break;
+- case 0x800: ret = "(FPU Unavailable)"; break;
+- case 0x900: ret = "(Decrementer)"; break;
+- case 0xc00: ret = "(System Call)"; break;
+- case 0xd00: ret = "(Single Step)"; break;
+- case 0xf00: ret = "(Performance Monitor)"; break;
+- case 0xf20: ret = "(Altivec Unavailable)"; break;
+- case 0x1300: ret = "(Instruction Breakpoint)"; break;
+- default: ret = "";
+- }
+- return ret;
+-}
+-
+-static void get_function_bounds(unsigned long pc, unsigned long *startp,
+- unsigned long *endp)
+-{
+- unsigned long size, offset;
+- const char *name;
+- char *modname;
+-
+- *startp = *endp = 0;
+- if (pc == 0)
+- return;
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+- name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
+- if (name != NULL) {
+- *startp = pc - offset;
+- *endp = pc - offset + size;
+- }
+- sync();
+- }
+- catch_memory_errors = 0;
+-}
+-
+-static int xmon_depth_to_print = 64;
+-
+-static void xmon_show_stack(unsigned long sp, unsigned long lr,
+- unsigned long pc)
+-{
+- unsigned long ip;
+- unsigned long newsp;
+- unsigned long marker;
+- int count = 0;
+- struct pt_regs regs;
+-
+- do {
+- if (sp < PAGE_OFFSET) {
+- if (sp != 0)
+- printf("SP (%lx) is in userspace\n", sp);
+- break;
+- }
+-
+- if (!mread(sp + 16, &ip, sizeof(unsigned long))
+- || !mread(sp, &newsp, sizeof(unsigned long))) {
+- printf("Couldn't read stack frame at %lx\n", sp);
+- break;
+- }
+-
+- /*
+- * For the first stack frame, try to work out if
+- * LR and/or the saved LR value in the bottommost
+- * stack frame are valid.
+- */
+- if ((pc | lr) != 0) {
+- unsigned long fnstart, fnend;
+- unsigned long nextip;
+- int printip = 1;
+-
+- get_function_bounds(pc, &fnstart, &fnend);
+- nextip = 0;
+- if (newsp > sp)
+- mread(newsp + 16, &nextip,
+- sizeof(unsigned long));
+- if (lr == ip) {
+- if (lr < PAGE_OFFSET
+- || (fnstart <= lr && lr < fnend))
+- printip = 0;
+- } else if (lr == nextip) {
+- printip = 0;
+- } else if (lr >= PAGE_OFFSET
+- && !(fnstart <= lr && lr < fnend)) {
+- printf("[link register ] ");
+- xmon_print_symbol(lr, " ", "\n");
+- }
+- if (printip) {
+- printf("[%.16lx] ", sp);
+- xmon_print_symbol(ip, " ", " (unreliable)\n");
+- }
+- pc = lr = 0;
+-
+- } else {
+- printf("[%.16lx] ", sp);
+- xmon_print_symbol(ip, " ", "\n");
+- }
+-
+- /* Look for "regshere" marker to see if this is
+- an exception frame. */
+- if (mread(sp + 0x60, &marker, sizeof(unsigned long))
+- && marker == 0x7265677368657265ul) {
+- if (mread(sp + 0x70, ®s, sizeof(regs))
+- != sizeof(regs)) {
+- printf("Couldn't read registers at %lx\n",
+- sp + 0x70);
+- break;
+- }
+- printf("--- Exception: %lx %s at ", regs.trap,
+- getvecname(TRAP(®s)));
+- pc = regs.nip;
+- lr = regs.link;
+- xmon_print_symbol(pc, " ", "\n");
+- }
+-
+- if (newsp == 0)
+- break;
+-
+- sp = newsp;
+- } while (count++ < xmon_depth_to_print);
+-}
+-
+-static void backtrace(struct pt_regs *excp)
+-{
+- unsigned long sp;
+-
+- if (scanhex(&sp))
+- xmon_show_stack(sp, 0, 0);
+- else
+- xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
+- scannl();
+-}
+-
+-static void print_bug_trap(struct pt_regs *regs)
+-{
+- struct bug_entry *bug;
+- unsigned long addr;
+-
+- if (regs->msr & MSR_PR)
+- return; /* not in kernel */
+- addr = regs->nip; /* address of trap instruction */
+- if (addr < PAGE_OFFSET)
+- return;
+- bug = find_bug(regs->nip);
+- if (bug == NULL)
+- return;
+- if (bug->line & BUG_WARNING_TRAP)
+- return;
+-
+- printf("kernel BUG in %s at %s:%d!\n",
+- bug->function, bug->file, (unsigned int)bug->line);
+-}
+-
+-void excprint(struct pt_regs *fp)
+-{
+- unsigned long trap;
+-
+-#ifdef CONFIG_SMP
+- printf("cpu 0x%x: ", smp_processor_id());
+-#endif /* CONFIG_SMP */
+-
+- trap = TRAP(fp);
+- printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
+- printf(" pc: ");
+- xmon_print_symbol(fp->nip, ": ", "\n");
+-
+- printf(" lr: ", fp->link);
+- xmon_print_symbol(fp->link, ": ", "\n");
+-
+- printf(" sp: %lx\n", fp->gpr[1]);
+- printf(" msr: %lx\n", fp->msr);
+-
+- if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
+- printf(" dar: %lx\n", fp->dar);
+- if (trap != 0x380)
+- printf(" dsisr: %lx\n", fp->dsisr);
+- }
+-
+- printf(" current = 0x%lx\n", current);
+- printf(" paca = 0x%lx\n", get_paca());
+- if (current) {
+- printf(" pid = %ld, comm = %s\n",
+- current->pid, current->comm);
+- }
+-
+- if (trap == 0x700)
+- print_bug_trap(fp);
+-}
+-
+-void prregs(struct pt_regs *fp)
+-{
+- int n;
+- unsigned long base;
+- struct pt_regs regs;
+-
+- if (scanhex(&base)) {
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+- regs = *(struct pt_regs *)base;
+- sync();
+- __delay(200);
+- } else {
+- catch_memory_errors = 0;
+- printf("*** Error reading registers from %.16lx\n",
+- base);
+- return;
+- }
+- catch_memory_errors = 0;
+- fp = ®s;
+- }
+-
+- if (FULL_REGS(fp)) {
+- for (n = 0; n < 16; ++n)
+- printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
+- n, fp->gpr[n], n+16, fp->gpr[n+16]);
+- } else {
+- for (n = 0; n < 7; ++n)
+- printf("R%.2ld = %.16lx R%.2ld = %.16lx\n",
+- n, fp->gpr[n], n+7, fp->gpr[n+7]);
+- }
+- printf("pc = ");
+- xmon_print_symbol(fp->nip, " ", "\n");
+- printf("lr = ");
+- xmon_print_symbol(fp->link, " ", "\n");
+- printf("msr = %.16lx cr = %.8lx\n", fp->msr, fp->ccr);
+- printf("ctr = %.16lx xer = %.16lx trap = %8lx\n",
+- fp->ctr, fp->xer, fp->trap);
+-}
+-
+-void cacheflush(void)
+-{
+- int cmd;
+- unsigned long nflush;
+-
+- cmd = inchar();
+- if (cmd != 'i')
+- termch = cmd;
+- scanhex((void *)&adrs);
+- if (termch != '\n')
+- termch = 0;
+- nflush = 1;
+- scanhex(&nflush);
+- nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+-
+- if (cmd != 'i') {
+- for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
+- cflush((void *) adrs);
+- } else {
+- for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
+- cinval((void *) adrs);
+- }
+- sync();
+- /* wait a little while to see if we get a machine check */
+- __delay(200);
+- }
+- catch_memory_errors = 0;
+-}
+-
+-unsigned long
+-read_spr(int n)
+-{
+- unsigned int instrs[2];
+- unsigned long (*code)(void);
+- unsigned long opd[3];
+- unsigned long ret = -1UL;
+-
+- instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+- instrs[1] = 0x4e800020;
+- opd[0] = (unsigned long)instrs;
+- opd[1] = 0;
+- opd[2] = 0;
+- store_inst(instrs);
+- store_inst(instrs+1);
+- code = (unsigned long (*)(void)) opd;
+-
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+-
+- ret = code();
+-
+- sync();
+- /* wait a little while to see if we get a machine check */
+- __delay(200);
+- n = size;
+- }
+-
+- return ret;
+-}
+-
+-void
+-write_spr(int n, unsigned long val)
+-{
+- unsigned int instrs[2];
+- unsigned long (*code)(unsigned long);
+- unsigned long opd[3];
+-
+- instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+- instrs[1] = 0x4e800020;
+- opd[0] = (unsigned long)instrs;
+- opd[1] = 0;
+- opd[2] = 0;
+- store_inst(instrs);
+- store_inst(instrs+1);
+- code = (unsigned long (*)(unsigned long)) opd;
+-
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+-
+- code(val);
+-
+- sync();
+- /* wait a little while to see if we get a machine check */
+- __delay(200);
+- n = size;
+- }
+-}
+-
+-static unsigned long regno;
+-extern char exc_prolog;
+-extern char dec_exc;
+-
+-void
+-super_regs(void)
+-{
+- int cmd;
+- unsigned long val;
+-#ifdef CONFIG_PPC_ISERIES
+- struct paca_struct *ptrPaca = NULL;
+- struct lppaca *ptrLpPaca = NULL;
+- struct ItLpRegSave *ptrLpRegSave = NULL;
+-#endif
+-
+- cmd = skipbl();
+- if (cmd == '\n') {
+- unsigned long sp, toc;
+- asm("mr %0,1" : "=r" (sp) :);
+- asm("mr %0,2" : "=r" (toc) :);
+-
+- printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0());
+- printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1());
+- printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2());
+- printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3());
+- printf("toc = %.16lx dar = %.16lx\n", toc, get_dar());
+- printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1());
+-#ifdef CONFIG_PPC_ISERIES
+- // Dump out relevant Paca data areas.
+- printf("Paca: \n");
+- ptrPaca = get_paca();
+-
+- printf(" Local Processor Control Area (LpPaca): \n");
+- ptrLpPaca = ptrPaca->lppaca_ptr;
+- printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
+- ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
+- printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
+- ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
+- printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
+-
+- printf(" Local Processor Register Save Area (LpRegSave): \n");
+- ptrLpRegSave = ptrPaca->reg_save_ptr;
+- printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
+- ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
+- printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
+- ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
+- printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
+- ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
+-#endif
+-
+- return;
+- }
+-
+- scanhex(®no);
+- switch (cmd) {
+- case 'w':
+- val = read_spr(regno);
+- scanhex(&val);
+- write_spr(regno, val);
+- /* fall through */
+- case 'r':
+- printf("spr %lx = %lx\n", regno, read_spr(regno));
+- break;
+- case 'm':
+- val = get_msr();
+- scanhex(&val);
+- set_msrd(val);
+- break;
+- }
+- scannl();
+-}
+-
+-/*
+- * Stuff for reading and writing memory safely
+- */
+-int
+-mread(unsigned long adrs, void *buf, int size)
+-{
+- volatile int n;
+- char *p, *q;
+-
+- n = 0;
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+- p = (char *)adrs;
+- q = (char *)buf;
+- switch (size) {
+- case 2:
+- *(short *)q = *(short *)p;
+- break;
+- case 4:
+- *(int *)q = *(int *)p;
+- break;
+- case 8:
+- *(long *)q = *(long *)p;
+- break;
+- default:
+- for( ; n < size; ++n) {
+- *q++ = *p++;
+- sync();
+- }
+- }
+- sync();
+- /* wait a little while to see if we get a machine check */
+- __delay(200);
+- n = size;
+- }
+- catch_memory_errors = 0;
+- return n;
+-}
+-
+-int
+-mwrite(unsigned long adrs, void *buf, int size)
+-{
+- volatile int n;
+- char *p, *q;
+-
+- n = 0;
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+- p = (char *) adrs;
+- q = (char *) buf;
+- switch (size) {
+- case 2:
+- *(short *)p = *(short *)q;
+- break;
+- case 4:
+- *(int *)p = *(int *)q;
+- break;
+- case 8:
+- *(long *)p = *(long *)q;
+- break;
+- default:
+- for ( ; n < size; ++n) {
+- *p++ = *q++;
+- sync();
+- }
+- }
+- sync();
+- /* wait a little while to see if we get a machine check */
+- __delay(200);
+- n = size;
+- } else {
+- printf("*** Error writing address %x\n", adrs + n);
+- }
+- catch_memory_errors = 0;
+- return n;
+-}
+-
+-static int fault_type;
+-static char *fault_chars[] = { "--", "**", "##" };
+-
+-static int
+-handle_fault(struct pt_regs *regs)
+-{
+- switch (TRAP(regs)) {
+- case 0x200:
+- fault_type = 0;
+- break;
+- case 0x300:
+- case 0x380:
+- fault_type = 1;
+- break;
+- default:
+- fault_type = 2;
+- }
+-
+- longjmp(bus_error_jmp, 1);
+-
+- return 0;
+-}
+-
+-#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
+-
+-void
+-byterev(unsigned char *val, int size)
+-{
+- int t;
+-
+- switch (size) {
+- case 2:
+- SWAP(val[0], val[1], t);
+- break;
+- case 4:
+- SWAP(val[0], val[3], t);
+- SWAP(val[1], val[2], t);
+- break;
+- case 8: /* is there really any use for this? */
+- SWAP(val[0], val[7], t);
+- SWAP(val[1], val[6], t);
+- SWAP(val[2], val[5], t);
+- SWAP(val[3], val[4], t);
+- break;
+- }
+-}
+-
+-static int brev;
+-static int mnoread;
+-
+-static char *memex_help_string =
+- "Memory examine command usage:\n"
+- "m [addr] [flags] examine/change memory\n"
+- " addr is optional. will start where left off.\n"
+- " flags may include chars from this set:\n"
+- " b modify by bytes (default)\n"
+- " w modify by words (2 byte)\n"
+- " l modify by longs (4 byte)\n"
+- " d modify by doubleword (8 byte)\n"
+- " r toggle reverse byte order mode\n"
+- " n do not read memory (for i/o spaces)\n"
+- " . ok to read (default)\n"
+- "NOTE: flags are saved as defaults\n"
+- "";
+-
+-static char *memex_subcmd_help_string =
+- "Memory examine subcommands:\n"
+- " hexval write this val to current location\n"
+- " 'string' write chars from string to this location\n"
+- " ' increment address\n"
+- " ^ decrement address\n"
+- " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
+- " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
+- " ` clear no-read flag\n"
+- " ; stay at this addr\n"
+- " v change to byte mode\n"
+- " w change to word (2 byte) mode\n"
+- " l change to long (4 byte) mode\n"
+- " u change to doubleword (8 byte) mode\n"
+- " m addr change current addr\n"
+- " n toggle no-read flag\n"
+- " r toggle byte reverse flag\n"
+- " < count back up count bytes\n"
+- " > count skip forward count bytes\n"
+- " x exit this mode\n"
+- "";
+-
+-void
+-memex(void)
+-{
+- int cmd, inc, i, nslash;
+- unsigned long n;
+- unsigned char val[16];
+-
+- scanhex((void *)&adrs);
+- cmd = skipbl();
+- if (cmd == '?') {
+- printf(memex_help_string);
+- return;
+- } else {
+- termch = cmd;
+- }
+- last_cmd = "m\n";
+- while ((cmd = skipbl()) != '\n') {
+- switch( cmd ){
+- case 'b': size = 1; break;
+- case 'w': size = 2; break;
+- case 'l': size = 4; break;
+- case 'd': size = 8; break;
+- case 'r': brev = !brev; break;
+- case 'n': mnoread = 1; break;
+- case '.': mnoread = 0; break;
+- }
+- }
+- if( size <= 0 )
+- size = 1;
+- else if( size > 8 )
+- size = 8;
+- for(;;){
+- if (!mnoread)
+- n = mread(adrs, val, size);
+- printf("%.16x%c", adrs, brev? 'r': ' ');
+- if (!mnoread) {
+- if (brev)
+- byterev(val, size);
+- putchar(' ');
+- for (i = 0; i < n; ++i)
+- printf("%.2x", val[i]);
+- for (; i < size; ++i)
+- printf("%s", fault_chars[fault_type]);
+- }
+- putchar(' ');
+- inc = size;
+- nslash = 0;
+- for(;;){
+- if( scanhex(&n) ){
+- for (i = 0; i < size; ++i)
+- val[i] = n >> (i * 8);
+- if (!brev)
+- byterev(val, size);
+- mwrite(adrs, val, size);
+- inc = size;
+- }
+- cmd = skipbl();
+- if (cmd == '\n')
+- break;
+- inc = 0;
+- switch (cmd) {
+- case '\'':
+- for(;;){
+- n = inchar();
+- if( n == '\\' )
+- n = bsesc();
+- else if( n == '\'' )
+- break;
+- for (i = 0; i < size; ++i)
+- val[i] = n >> (i * 8);
+- if (!brev)
+- byterev(val, size);
+- mwrite(adrs, val, size);
+- adrs += size;
+- }
+- adrs -= size;
+- inc = size;
+- break;
+- case ',':
+- adrs += size;
+- break;
+- case '.':
+- mnoread = 0;
+- break;
+- case ';':
+- break;
+- case 'x':
+- case EOF:
+- scannl();
+- return;
+- case 'b':
+- case 'v':
+- size = 1;
+- break;
+- case 'w':
+- size = 2;
+- break;
+- case 'l':
+- size = 4;
+- break;
+- case 'u':
+- size = 8;
+- break;
+- case '^':
+- adrs -= size;
+- break;
+- break;
+- case '/':
+- if (nslash > 0)
+- adrs -= 1 << nslash;
+- else
+- nslash = 0;
+- nslash += 4;
+- adrs += 1 << nslash;
+- break;
+- case '\\':
+- if (nslash < 0)
+- adrs += 1 << -nslash;
+- else
+- nslash = 0;
+- nslash -= 4;
+- adrs -= 1 << -nslash;
+- break;
+- case 'm':
+- scanhex((void *)&adrs);
+- break;
+- case 'n':
+- mnoread = 1;
+- break;
+- case 'r':
+- brev = !brev;
+- break;
+- case '<':
+- n = size;
+- scanhex(&n);
+- adrs -= n;
+- break;
+- case '>':
+- n = size;
+- scanhex(&n);
+- adrs += n;
+- break;
+- case '?':
+- printf(memex_subcmd_help_string);
+- break;
+- }
+- }
+- adrs += inc;
+- }
+-}
+-
+-int
+-bsesc(void)
+-{
+- int c;
+-
+- c = inchar();
+- switch( c ){
+- case 'n': c = '\n'; break;
+- case 'r': c = '\r'; break;
+- case 'b': c = '\b'; break;
+- case 't': c = '\t'; break;
+- }
+- return c;
+-}
+-
+-#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+- || ('a' <= (c) && (c) <= 'f') \
+- || ('A' <= (c) && (c) <= 'F'))
+-void
+-dump(void)
+-{
+- int c;
+-
+- c = inchar();
+- if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
+- termch = c;
+- scanhex((void *)&adrs);
+- if (termch != '\n')
+- termch = 0;
+- if (c == 'i') {
+- scanhex(&nidump);
+- if (nidump == 0)
+- nidump = 16;
+- else if (nidump > MAX_DUMP)
+- nidump = MAX_DUMP;
+- adrs += ppc_inst_dump(adrs, nidump, 1);
+- last_cmd = "di\n";
+- } else {
+- scanhex(&ndump);
+- if (ndump == 0)
+- ndump = 64;
+- else if (ndump > MAX_DUMP)
+- ndump = MAX_DUMP;
+- prdump(adrs, ndump);
+- adrs += ndump;
+- last_cmd = "d\n";
+- }
+-}
+-
+-void
+-prdump(unsigned long adrs, long ndump)
+-{
+- long n, m, c, r, nr;
+- unsigned char temp[16];
+-
+- for (n = ndump; n > 0;) {
+- printf("%.16lx", adrs);
+- putchar(' ');
+- r = n < 16? n: 16;
+- nr = mread(adrs, temp, r);
+- adrs += nr;
+- for (m = 0; m < r; ++m) {
+- if ((m & 7) == 0 && m > 0)
+- putchar(' ');
+- if (m < nr)
+- printf("%.2x", temp[m]);
+- else
+- printf("%s", fault_chars[fault_type]);
+- }
+- if (m <= 8)
+- printf(" ");
+- for (; m < 16; ++m)
+- printf(" ");
+- printf(" |");
+- for (m = 0; m < r; ++m) {
+- if (m < nr) {
+- c = temp[m];
+- putchar(' ' <= c && c <= '~'? c: '.');
+- } else
+- putchar(' ');
+- }
+- n -= r;
+- for (; m < 16; ++m)
+- putchar(' ');
+- printf("|\n");
+- if (nr < r)
+- break;
+- }
+-}
+-
+-int
+-ppc_inst_dump(unsigned long adr, long count, int praddr)
+-{
+- int nr, dotted;
+- unsigned long first_adr;
+- unsigned long inst, last_inst = 0;
+- unsigned char val[4];
+-
+- dotted = 0;
+- for (first_adr = adr; count > 0; --count, adr += 4) {
+- nr = mread(adr, val, 4);
+- if (nr == 0) {
+- if (praddr) {
+- const char *x = fault_chars[fault_type];
+- printf("%.16lx %s%s%s%s\n", adr, x, x, x, x);
+- }
+- break;
+- }
+- inst = GETWORD(val);
+- if (adr > first_adr && inst == last_inst) {
+- if (!dotted) {
+- printf(" ...\n");
+- dotted = 1;
+- }
+- continue;
+- }
+- dotted = 0;
+- last_inst = inst;
+- if (praddr)
+- printf("%.16lx %.8x", adr, inst);
+- printf("\t");
+- print_insn_powerpc(inst, adr, 0); /* always returns 4 */
+- printf("\n");
+- }
+- return adr - first_adr;
+-}
+-
+-void
+-print_address(unsigned long addr)
+-{
+- xmon_print_symbol(addr, "\t# ", "");
+-}
+-
+-
+-/*
+- * Memory operations - move, set, print differences
+- */
+-static unsigned long mdest; /* destination address */
+-static unsigned long msrc; /* source address */
+-static unsigned long mval; /* byte value to set memory to */
+-static unsigned long mcount; /* # bytes to affect */
+-static unsigned long mdiffs; /* max # differences to print */
+-
+-void
+-memops(int cmd)
+-{
+- scanhex((void *)&mdest);
+- if( termch != '\n' )
+- termch = 0;
+- scanhex((void *)(cmd == 's'? &mval: &msrc));
+- if( termch != '\n' )
+- termch = 0;
+- scanhex((void *)&mcount);
+- switch( cmd ){
+- case 'm':
+- memmove((void *)mdest, (void *)msrc, mcount);
+- break;
+- case 's':
+- memset((void *)mdest, mval, mcount);
+- break;
+- case 'd':
+- if( termch != '\n' )
+- termch = 0;
+- scanhex((void *)&mdiffs);
+- memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
+- break;
+- }
+-}
+-
+-void
+-memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
+-{
+- unsigned n, prt;
+-
+- prt = 0;
+- for( n = nb; n > 0; --n )
+- if( *p1++ != *p2++ )
+- if( ++prt <= maxpr )
+- printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
+- p1[-1], p2 - 1, p2[-1]);
+- if( prt > maxpr )
+- printf("Total of %d differences\n", prt);
+-}
+-
+-static unsigned mend;
+-static unsigned mask;
+-
+-void
+-memlocate(void)
+-{
+- unsigned a, n;
+- unsigned char val[4];
+-
+- last_cmd = "ml";
+- scanhex((void *)&mdest);
+- if (termch != '\n') {
+- termch = 0;
+- scanhex((void *)&mend);
+- if (termch != '\n') {
+- termch = 0;
+- scanhex((void *)&mval);
+- mask = ~0;
+- if (termch != '\n') termch = 0;
+- scanhex((void *)&mask);
+- }
+- }
+- n = 0;
+- for (a = mdest; a < mend; a += 4) {
+- if (mread(a, val, 4) == 4
+- && ((GETWORD(val) ^ mval) & mask) == 0) {
+- printf("%.16x: %.16x\n", a, GETWORD(val));
+- if (++n >= 10)
+- break;
+- }
+- }
+-}
+-
+-static unsigned long mskip = 0x1000;
+-static unsigned long mlim = 0xffffffff;
+-
+-void
+-memzcan(void)
+-{
+- unsigned char v;
+- unsigned a;
+- int ok, ook;
+-
+- scanhex(&mdest);
+- if (termch != '\n') termch = 0;
+- scanhex(&mskip);
+- if (termch != '\n') termch = 0;
+- scanhex(&mlim);
+- ook = 0;
+- for (a = mdest; a < mlim; a += mskip) {
+- ok = mread(a, &v, 1);
+- if (ok && !ook) {
+- printf("%.8x .. ", a);
+- fflush(stdout);
+- } else if (!ok && ook)
+- printf("%.8x\n", a - mskip);
+- ook = ok;
+- if (a + mskip < a)
+- break;
+- }
+- if (ook)
+- printf("%.8x\n", a - mskip);
+-}
+-
+-/* Input scanning routines */
+-int
+-skipbl(void)
+-{
+- int c;
+-
+- if( termch != 0 ){
+- c = termch;
+- termch = 0;
+- } else
+- c = inchar();
+- while( c == ' ' || c == '\t' )
+- c = inchar();
+- return c;
+-}
+-
+-#define N_PTREGS 44
+-static char *regnames[N_PTREGS] = {
+- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+- "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "softe",
+- "trap", "dar", "dsisr", "res"
+-};
+-
+-int
+-scanhex(unsigned long *vp)
+-{
+- int c, d;
+- unsigned long v;
+-
+- c = skipbl();
+- if (c == '%') {
+- /* parse register name */
+- char regname[8];
+- int i;
+-
+- for (i = 0; i < sizeof(regname) - 1; ++i) {
+- c = inchar();
+- if (!isalnum(c)) {
+- termch = c;
+- break;
+- }
+- regname[i] = c;
+- }
+- regname[i] = 0;
+- for (i = 0; i < N_PTREGS; ++i) {
+- if (strcmp(regnames[i], regname) == 0) {
+- if (xmon_regs == NULL) {
+- printf("regs not available\n");
+- return 0;
+- }
+- *vp = ((unsigned long *)xmon_regs)[i];
+- return 1;
+- }
+- }
+- printf("invalid register name '%%%s'\n", regname);
+- return 0;
+- }
+-
+- /* skip leading "0x" if any */
+-
+- if (c == '0') {
+- c = inchar();
+- if (c == 'x') {
+- c = inchar();
+- } else {
+- d = hexdigit(c);
+- if (d == EOF) {
+- termch = c;
+- *vp = 0;
+- return 1;
+- }
+- }
+- } else if (c == '$') {
+- int i;
+- for (i=0; i<63; i++) {
+- c = inchar();
+- if (isspace(c)) {
+- termch = c;
+- break;
+- }
+- tmpstr[i] = c;
+- }
+- tmpstr[i++] = 0;
+- *vp = 0;
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+- *vp = kallsyms_lookup_name(tmpstr);
+- sync();
+- }
+- catch_memory_errors = 0;
+- if (!(*vp)) {
+- printf("unknown symbol '%s'\n", tmpstr);
+- return 0;
+- }
+- return 1;
+- }
+-
+- d = hexdigit(c);
+- if (d == EOF) {
+- termch = c;
+- return 0;
+- }
+- v = 0;
+- do {
+- v = (v << 4) + d;
+- c = inchar();
+- d = hexdigit(c);
+- } while (d != EOF);
+- termch = c;
+- *vp = v;
+- return 1;
+-}
+-
+-void
+-scannl(void)
+-{
+- int c;
+-
+- c = termch;
+- termch = 0;
+- while( c != '\n' )
+- c = inchar();
+-}
+-
+-int
+-hexdigit(int c)
+-{
+- if( '0' <= c && c <= '9' )
+- return c - '0';
+- if( 'A' <= c && c <= 'F' )
+- return c - ('A' - 10);
+- if( 'a' <= c && c <= 'f' )
+- return c - ('a' - 10);
+- return EOF;
+-}
+-
+-void
+-getstring(char *s, int size)
+-{
+- int c;
+-
+- c = skipbl();
+- do {
+- if( size > 1 ){
+- *s++ = c;
+- --size;
+- }
+- c = inchar();
+- } while( c != ' ' && c != '\t' && c != '\n' );
+- termch = c;
+- *s = 0;
+-}
+-
+-static char line[256];
+-static char *lineptr;
+-
+-void
+-flush_input(void)
+-{
+- lineptr = NULL;
+-}
+-
+-int
+-inchar(void)
+-{
+- if (lineptr == NULL || *lineptr == 0) {
+- if (fgets(line, sizeof(line), stdin) == NULL) {
+- lineptr = NULL;
+- return EOF;
+- }
+- lineptr = line;
+- }
+- return *lineptr++;
+-}
+-
+-void
+-take_input(char *str)
+-{
+- lineptr = str;
+-}
+-
+-
+-static void
+-symbol_lookup(void)
+-{
+- int type = inchar();
+- unsigned long addr;
+- static char tmp[64];
+-
+- switch (type) {
+- case 'a':
+- if (scanhex(&addr))
+- xmon_print_symbol(addr, ": ", "\n");
+- termch = 0;
+- break;
+- case 's':
+- getstring(tmp, 64);
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+- addr = kallsyms_lookup_name(tmp);
+- if (addr)
+- printf("%s: %lx\n", tmp, addr);
+- else
+- printf("Symbol '%s' not found.\n", tmp);
+- sync();
+- }
+- catch_memory_errors = 0;
+- termch = 0;
+- break;
+- }
+-}
+-
+-
+-/* Print an address in numeric and symbolic form (if possible) */
+-static void xmon_print_symbol(unsigned long address, const char *mid,
+- const char *after)
+-{
+- char *modname;
+- const char *name = NULL;
+- unsigned long offset, size;
+-
+- printf("%.16lx", address);
+- if (setjmp(bus_error_jmp) == 0) {
+- catch_memory_errors = 1;
+- sync();
+- name = kallsyms_lookup(address, &size, &offset, &modname,
+- tmpstr);
+- sync();
+- /* wait a little while to see if we get a machine check */
+- __delay(200);
+- }
+-
+- catch_memory_errors = 0;
+-
+- if (name) {
+- printf("%s%s+%#lx/%#lx", mid, name, offset, size);
+- if (modname)
+- printf(" [%s]", modname);
+- }
+- printf("%s", after);
+-}
+-
+-static void debug_trace(void)
+-{
+- unsigned long val, cmd, on;
+-
+- cmd = skipbl();
+- if (cmd == '\n') {
+- /* show current state */
+- unsigned long i;
+- printf("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch);
+- for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) {
+- on = PPCDBG_BITVAL(i) & ppc64_debug_switch;
+- printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : "");
+- if (((i+1) % 3) == 0)
+- printf("\n");
+- }
+- printf("\n");
+- return;
+- }
+- while (cmd != '\n') {
+- on = 1; /* default if no sign given */
+- while (cmd == '+' || cmd == '-') {
+- on = (cmd == '+');
+- cmd = inchar();
+- if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */
+- ppc64_debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE;
+- printf("Setting all values to %s...\n", on ? "on" : "off");
+- if (cmd == '\n') return;
+- else cmd = skipbl();
+- }
+- else
+- termch = cmd;
+- }
+- termch = cmd; /* not +/- ... let scanhex see it */
+- scanhex((void *)&val);
+- if (val >= 64) {
+- printf("Value %x out of range:\n", val);
+- return;
+- }
+- if (on) {
+- ppc64_debug_switch |= PPCDBG_BITVAL(val);
+- printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
+- } else {
+- ppc64_debug_switch &= ~PPCDBG_BITVAL(val);
+- printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
+- }
+- cmd = skipbl();
+- }
+-}
+-
+-static void dump_slb(void)
+-{
+- int i;
+- unsigned long tmp;
+-
+- printf("SLB contents of cpu %x\n", smp_processor_id());
+-
+- for (i = 0; i < SLB_NUM_ENTRIES; i++) {
+- asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
+- printf("%02d %016lx ", i, tmp);
+-
+- asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
+- printf("%016lx\n", tmp);
+- }
+-}
+-
+-static void dump_stab(void)
+-{
+- int i;
+- unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
+-
+- printf("Segment table contents of cpu %x\n", smp_processor_id());
+-
+- for (i = 0; i < PAGE_SIZE/16; i++) {
+- unsigned long a, b;
+-
+- a = *tmp++;
+- b = *tmp++;
+-
+- if (a || b) {
+- printf("%03d %016lx ", i, a);
+- printf("%016lx\n", b);
+- }
+- }
+-}
+-
+-void xmon_init(int enable)
+-{
+- if (enable) {
+- __debugger = xmon;
+- __debugger_ipi = xmon_ipi;
+- __debugger_bpt = xmon_bpt;
+- __debugger_sstep = xmon_sstep;
+- __debugger_iabr_match = xmon_iabr_match;
+- __debugger_dabr_match = xmon_dabr_match;
+- __debugger_fault_handler = xmon_fault_handler;
+- } else {
+- __debugger = NULL;
+- __debugger_ipi = NULL;
+- __debugger_bpt = NULL;
+- __debugger_sstep = NULL;
+- __debugger_iabr_match = NULL;
+- __debugger_dabr_match = NULL;
+- __debugger_fault_handler = NULL;
+- }
+-}
+-
+-void dump_segments(void)
+-{
+- if (cpu_has_feature(CPU_FTR_SLB))
+- dump_slb();
+- else
+- dump_stab();
+-}
+diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
+--- 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(BIODASDCMFENABLE)
+ 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
+--- a/arch/s390/kernel/head.S
++++ b/arch/s390/kernel/head.S
+@@ -485,7 +485,9 @@ start:
+ #
+ .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 @@ startup:basr %r13,0
+ 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 @@ _pstart:
+ .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 @@ _pend:
+ #
+ .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 @@ _stext: basr %r13,0
+ 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
+--- a/arch/s390/kernel/head64.S
++++ b/arch/s390/kernel/head64.S
+@@ -484,6 +484,8 @@ start:
+ 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 @@ startup:basr %r13,0
+ 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 @@ _pstart:
+ .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 @@ _pend:
+ #
+ .globl _stext
+ _stext: basr %r13,0 # get base
+-.LPG2:
++.LPG3:
+ #
+ # Setup stack
+ #
+@@ -774,7 +836,7 @@ _stext: basr %r13,0
+ 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
+--- 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 @@ struct seq_operations cpuinfo_op = {
+ .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
+--- 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
+--- 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 @@ static void do_cpu_timer_interrupt(struc
+
+ 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 void internal_add_vtimer(struct v
+
+ 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 @@ int mod_virt_timer(struct vtimer_list *t
+ 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 @@ int del_virt_timer(struct vtimer_list *t
+ 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
+--- a/arch/s390/mm/ioremap.c
++++ b/arch/s390/mm/ioremap.c
+@@ -58,7 +58,7 @@ static inline int remap_area_pmd(pmd_t *
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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
+--- a/arch/sh/boards/renesas/rts7751r2d/mach.c
++++ b/arch/sh/boards/renesas/rts7751r2d/mach.c
+@@ -23,7 +23,7 @@ extern void init_rts7751r2d_IRQ(void);
+ 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/boards/superh/microdev/setup.c b/arch/sh/boards/superh/microdev/setup.c
+--- a/arch/sh/boards/superh/microdev/setup.c
++++ b/arch/sh/boards/superh/microdev/setup.c
+@@ -13,7 +13,7 @@
+
+ #include <linux/config.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/ioport.h>
+ #include <asm/io.h>
+ #include <asm/mach/irq.h>
+diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c
+--- a/arch/sh/cchips/voyagergx/consistent.c
++++ b/arch/sh/cchips/voyagergx/consistent.c
+@@ -31,7 +31,7 @@ static LIST_HEAD(voya_alloc_list);
+ #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
+--- 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
+--- 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
+--- 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
+--- a/arch/sh/kernel/ptrace.c
++++ b/arch/sh/kernel/ptrace.c
+@@ -80,7 +80,7 @@ void ptrace_disable(struct task_struct *
+ /* 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
+--- a/arch/sh/kernel/time.c
++++ b/arch/sh/kernel/time.c
+@@ -56,10 +56,6 @@ extern unsigned long wall_jiffies;
+ #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
+--- 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
+--- a/arch/sh/mm/fault.c
++++ b/arch/sh/mm/fault.c
+@@ -194,10 +194,13 @@ asmlinkage int __do_page_fault(struct pt
+ 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 @@ asmlinkage int __do_page_fault(struct pt
+ 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 @@ asmlinkage int __do_page_fault(struct pt
+
+ 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
+--- a/arch/sh/mm/hugetlbpage.c
++++ b/arch/sh/mm/hugetlbpage.c
+@@ -54,8 +54,6 @@ pte_t *huge_pte_offset(struct mm_struct
+ 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
+--- a/arch/sh/mm/ioremap.c
++++ b/arch/sh/mm/ioremap.c
+@@ -57,7 +57,7 @@ static inline int remap_area_pmd(pmd_t *
+ 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 @@ int remap_area_pages(unsigned long addre
+ 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 @@ int remap_area_pages(unsigned long addre
+ 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
+--- a/arch/sh64/kernel/ptrace.c
++++ b/arch/sh64/kernel/ptrace.c
+@@ -121,7 +121,7 @@ put_fpu_long(struct task_struct *task, u
+ 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
+--- 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 @@ int do_settimeofday(struct timespec *tv)
+
+ 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
+--- a/arch/sh64/mm/cache.c
++++ b/arch/sh64/mm/cache.c
+@@ -584,32 +584,36 @@ static void sh64_dcache_purge_phy_page(u
+ }
+ }
+
+-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 */
+- pgd = pgd_offset(mm, eaddr);
+- if (pgd_bad(*pgd)) return;
+-
+- pmd = pmd_offset(pgd, eaddr);
+- 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);
++ if (!mm)
++ return; /* No way to find physical address of page */
+
++ pgd = pgd_offset(mm, addr);
++ if (pgd_bad(*pgd))
++ return;
++
++ pmd = pmd_offset(pgd, addr);
++ if (pmd_none(*pmd) || pmd_bad(*pmd))
++ return;
++
++ 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 @@ static void sh64_dcache_purge_user_range
+ 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 @@ static void sh64_dcache_purge_user_range
+ }
+ #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 @@ void flush_cache_range(struct vm_area_st
+ 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 @@ void flush_cache_page(struct vm_area_str
+ 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
+--- a/arch/sh64/mm/hugetlbpage.c
++++ b/arch/sh64/mm/hugetlbpage.c
+@@ -54,41 +54,31 @@ pte_t *huge_pte_offset(struct mm_struct
+ 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 @@ int is_aligned_hugepage_range(unsigned l
+ 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 @@ struct page *follow_huge_pmd(struct mm_s
+ {
+ 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
+--- a/arch/sh64/mm/ioremap.c
++++ b/arch/sh64/mm/ioremap.c
+@@ -79,7 +79,7 @@ static inline int remap_area_pmd(pmd_t *
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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
+--- a/arch/sparc/kernel/pcic.c
++++ b/arch/sparc/kernel/pcic.c
+@@ -497,8 +497,8 @@ static void pcic_map_pci_device(struct l
+ * 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
+--- 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
+--- a/arch/sparc/mm/generic.c
++++ b/arch/sparc/mm/generic.c
+@@ -73,14 +73,16 @@ int io_remap_pfn_range(struct vm_area_st
+ 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 @@ int io_remap_pfn_range(struct vm_area_st
+ 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
+--- a/arch/sparc64/kernel/binfmt_aout32.c
++++ b/arch/sparc64/kernel/binfmt_aout32.c
+@@ -241,7 +241,6 @@ static int load_aout32_binary(struct lin
+ 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
+--- a/arch/sparc64/kernel/ioctl32.c
++++ b/arch/sparc64/kernel/ioctl32.c
+@@ -475,9 +475,6 @@ IOCTL_TABLE_START
+ #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
+--- a/arch/sparc64/kernel/time.c
++++ b/arch/sparc64/kernel/time.c
+@@ -55,10 +55,6 @@ unsigned long ds1287_regs = 0UL;
+
+ 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
+--- a/arch/sparc64/mm/generic.c
++++ b/arch/sparc64/mm/generic.c
+@@ -127,14 +127,16 @@ int io_remap_pfn_range(struct vm_area_st
+ 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 @@ int io_remap_pfn_range(struct vm_area_st
+ 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
+--- 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 @@ void tlb_batch_add(struct mm_struct *mm,
+
+ no_cache_flush:
+
+- if (mp->tlb_frozen)
++ if (mp->fullmm)
+ return;
+
+ nr = mp->tlb_nr;
+@@ -97,7 +96,7 @@ void flush_tlb_pgtables(struct mm_struct
+ 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
+--- a/arch/sparc64/solaris/socksys.c
++++ b/arch/sparc64/solaris/socksys.c
+@@ -49,7 +49,7 @@ IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, I
+
+ #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
+--- a/arch/sparc64/solaris/timod.c
++++ b/arch/sparc64/solaris/timod.c
+@@ -39,7 +39,7 @@ static char * page = NULL ;
+
+ #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
+--- a/arch/um/Kconfig
++++ b/arch/um/Kconfig
+@@ -27,10 +27,6 @@ config UID16
+ bool
+ default y
+
+-config RWSEM_GENERIC_SPINLOCK
+- bool
+- default y
+-
+ config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+@@ -40,6 +36,12 @@ config IRQ_RELEASE_METHOD
+ 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
+--- a/arch/um/Kconfig.x86_64
++++ b/arch/um/Kconfig.x86_64
+@@ -6,6 +6,11 @@ config 64BIT
+ 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
+--- a/arch/um/Makefile-i386
++++ b/arch/um/Makefile-i386
+@@ -29,6 +29,12 @@ endif
+
+ 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/drivers/net_kern.c b/arch/um/drivers/net_kern.c
+--- a/arch/um/drivers/net_kern.c
++++ b/arch/um/drivers/net_kern.c
+@@ -20,6 +20,7 @@
+ #include "linux/ctype.h"
+ #include "linux/bootmem.h"
+ #include "linux/ethtool.h"
++#include "linux/platform_device.h"
+ #include "asm/uaccess.h"
+ #include "user_util.h"
+ #include "kern_util.h"
+diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
+--- a/arch/um/drivers/ubd_kern.c
++++ b/arch/um/drivers/ubd_kern.c
+@@ -35,6 +35,7 @@
+ #include "linux/blkpg.h"
+ #include "linux/genhd.h"
+ #include "linux/spinlock.h"
++#include "linux/platform_device.h"
+ #include "asm/segment.h"
+ #include "asm/uaccess.h"
+ #include "asm/irq.h"
+diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
+--- a/arch/um/include/net_kern.h
++++ b/arch/um/include/net_kern.h
+@@ -6,10 +6,11 @@
+ #ifndef __UM_NET_KERN_H
+ #define __UM_NET_KERN_H
+
+-#include "linux/netdevice.h"
+-#include "linux/skbuff.h"
+-#include "linux/socket.h"
+-#include "linux/list.h"
++#include <linux/netdevice.h>
++#include <linux/platform_device.h>
++#include <linux/skbuff.h>
++#include <linux/socket.h>
++#include <linux/list.h>
+
+ struct uml_net {
+ struct list_head list;
+diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
+--- a/arch/um/include/sysdep-i386/syscalls.h
++++ b/arch/um/include/sysdep-i386/syscalls.h
+@@ -11,7 +11,6 @@ typedef long syscall_handler_t(struct pt
+ /* 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
+--- a/arch/um/include/tlb.h
++++ b/arch/um/include/tlb.h
+@@ -34,7 +34,6 @@ struct host_vm_op {
+ } 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
+--- a/arch/um/kernel/mem.c
++++ b/arch/um/kernel/mem.c
+@@ -252,7 +252,7 @@ void paging_init(void)
+ #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
+--- a/arch/um/kernel/process_kern.c
++++ b/arch/um/kernel/process_kern.c
+@@ -80,7 +80,7 @@ void free_stack(unsigned long stack, int
+ 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 @@ void *um_virt_to_phys(struct task_struct
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
++ pte_t ptent;
+
+ if(task->mm == NULL)
+ return(ERR_PTR(-EINVAL));
+@@ -238,12 +239,13 @@ void *um_virt_to_phys(struct task_struct
+ 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
+--- a/arch/um/kernel/skas/mmu.c
++++ b/arch/um/kernel/skas/mmu.c
+@@ -28,7 +28,6 @@ static int init_stub_pte(struct mm_struc
+ 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 @@ static int init_stub_pte(struct mm_struc
+ *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 @@ static int init_stub_pte(struct mm_struc
+ out_pte:
+ pmd_free(pmd);
+ out:
+- spin_unlock(&mm->page_table_lock);
+ return(-ENOMEM);
+ }
+
+@@ -147,6 +144,7 @@ void destroy_context_skas(struct mm_stru
+
+ 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
+--- 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
+--- a/arch/um/kernel/tt/tlb.c
++++ b/arch/um/kernel/tt/tlb.c
+@@ -74,42 +74,6 @@ void flush_tlb_kernel_range_tt(unsigned
+ 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
+--- a/arch/v850/kernel/ptrace.c
++++ b/arch/v850/kernel/ptrace.c
+@@ -113,7 +113,7 @@ static int set_single_step (struct task_
+ 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
+--- 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
+--- a/arch/x86_64/ia32/ia32_aout.c
++++ b/arch/x86_64/ia32/ia32_aout.c
+@@ -314,7 +314,6 @@ static int load_aout_binary(struct linux
+ 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
+--- 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 @@ static int rtc32_ioctl(unsigned fd, unsi
+ 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(0x4B51) /* KDSHWCLK -
+ 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_IRQP_SET32, rtc32_ioctl
+ 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
+--- a/arch/x86_64/kernel/i8259.c
++++ b/arch/x86_64/kernel/i8259.c
+@@ -494,7 +494,7 @@ void invalidate_interrupt7(void);
+ 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 void setup_timer(void)
+
+ 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 @@ void __init init_IRQ(void)
+ * 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
+--- a/arch/x86_64/kernel/pci-gart.c
++++ b/arch/x86_64/kernel/pci-gart.c
+@@ -187,7 +187,7 @@ static void flush_gart(struct device *de
+
+ /* 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 @@ static void *dma_alloc_pages(struct devi
+ */
+ 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
+--- a/arch/x86_64/kernel/pci-nommu.c
++++ b/arch/x86_64/kernel/pci-nommu.c
+@@ -24,7 +24,7 @@ EXPORT_SYMBOL(iommu_sac_force);
+ */
+
+ 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
+--- a/arch/x86_64/kernel/setup.c
++++ b/arch/x86_64/kernel/setup.c
+@@ -1213,7 +1213,7 @@ static int show_cpuinfo(struct seq_file
+ 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
+--- a/arch/x86_64/kernel/suspend.c
++++ b/arch/x86_64/kernel/suspend.c
+@@ -63,13 +63,12 @@ void save_processor_state(void)
+ __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 @@ extern int restore_image(void);
+
+ 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 @@ static void res_phys_pud_init(pud_t *pud
+ 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 @@ static void res_phys_pud_init(pud_t *pud
+ 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 @@ static void set_up_temporary_mappings(vo
+ 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
+--- 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 irqreturn_t timer_interrupt(int i
+ 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 @@ static int time_cpufreq_notifier(struct
+ 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 @@ void __init time_init(void)
+ 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_freq = DEFAULT_
+ 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 @@ int hpet_rtc_timer_init(void)
+ 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 @@ static void hpet_rtc_timer_reinit(void)
+ {
+ 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 @@ static void hpet_rtc_timer_reinit(void)
+ 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
+--- a/arch/x86_64/mm/ioremap.c
++++ b/arch/x86_64/mm/ioremap.c
+@@ -60,7 +60,7 @@ static inline int remap_area_pmd(pmd_t *
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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 @@ static int remap_area_pages(unsigned lon
+ 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
+--- 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
+--- 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
+--- a/arch/xtensa/kernel/ptrace.c
++++ b/arch/xtensa/kernel/ptrace.c
+@@ -45,7 +45,7 @@ void ptrace_disable(struct task_struct *
+ /* 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
+--- 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/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
+--- a/arch/xtensa/platform-iss/network.c
++++ b/arch/xtensa/platform-iss/network.c
+@@ -33,6 +33,7 @@
+ #include <linux/ethtool.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/timer.h>
++#include <linux/platform_device.h>
+
+ #include <xtensa/simcall.h>
+
+diff --git a/crypto/api.c b/crypto/api.c
+--- a/crypto/api.c
++++ b/crypto/api.c
+@@ -215,7 +215,10 @@ int crypto_register_alg(struct crypto_al
+ 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
+--- 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 @@ void crypto_hmac_init(struct crypto_tfm
+ 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 @@ void crypto_hmac_final(struct crypto_tfm
+ 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
+--- 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 hexdump(unsigned char *buf,
+ 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 @@ static void test_hash(char *algo, struct
+ 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 @@ static void test_hash(char *algo, struct
+ 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_hash(char *algo, struct
+ 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 @@ static void test_hmac(char *algo, struct
+ 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 @@ static void test_hmac(char *algo, struct
+ 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 @@ static void test_cipher(char *algo, int
+ {
+ 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 @@ static void test_cipher(char *algo, int
+ 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 @@ static void test_cipher(char *algo, int
+ 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 @@ out:
+ 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_jiffies(struct cr
+ 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 @@ static void test_crc32c(void)
+ 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
+--- 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
+--- 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 @@ static struct i2c_client_address_data ad
+ .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 @@ pcf8583_attach(struct i2c_adapter *adap,
+ 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 @@ pcf8583_attach(struct i2c_adapter *adap,
+ 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 @@ pcf8583_get_datetime(struct i2c_client *
+ {
+ 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 @@ pcf8583_set_datetime(struct i2c_client *
+ 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 @@ pcf8583_set_datetime(struct i2c_client *
+ 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 @@ pcf8583_set_datetime(struct i2c_client *
+ 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 @@ pcf8583_set_ctrl(struct i2c_client *clie
+
+ 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 @@ pcf8583_read_mem(struct i2c_client *clie
+ {
+ 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 @@ pcf8583_write_mem(struct i2c_client *cli
+ {
+ 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 @@ static __init int pcf8583_init(void)
+ 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
+--- a/drivers/acpi/acpi_memhotplug.c
++++ b/drivers/acpi/acpi_memhotplug.c
+@@ -200,8 +200,7 @@ static int acpi_memory_enable_device(str
+ * 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 @@ static int acpi_memory_disable_device(st
+ * 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
+--- 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
+--- a/drivers/acpi/sleep/main.c
++++ b/drivers/acpi/sleep/main.c
+@@ -158,7 +158,15 @@ int acpi_suspend(u32 acpi_state)
+ 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
+--- a/drivers/base/Makefile
++++ b/drivers/base/Makefile
+@@ -7,6 +7,7 @@ obj-y := core.o sys.o bus.o dd.o \
+ 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
+--- 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
+--- 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
+--- 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 @@ struct class * class_get(struct class *
+
+ void class_put(struct class * cls)
+ {
+- subsys_put(&cls->subsys);
++ if (cls)
++ subsys_put(&cls->subsys);
+ }
+
+
+@@ -165,14 +167,25 @@ void class_unregister(struct class * cls
+
+ 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 @@ static void class_dev_release(struct kob
+ 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 @@ static int class_hotplug(struct kset *ks
+ 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 @@ static ssize_t show_dev(struct class_dev
+ 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 @@ static char *make_class_name(struct clas
+
+ 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 @@ int class_device_add(struct class_device
+ 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 @@ int class_device_add(struct class_device
+ class_name);
+ }
+
++ kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
++
+ /* 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 (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);
+- up(&parent->sem);
++ class_intf->add(class_dev, class_intf);
++ up(&parent_class->sem);
+ }
+- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+
+ 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 @@ int class_device_register(struct class_d
+ /**
+ * 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 @@ struct class_device *class_device_create
+ 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 @@ error:
+
+ 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 @@ void class_device_del(struct class_devic
+ 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 @@ void class_device_del(struct class_devic
+ 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 @@ struct class_device * class_device_get(s
+
+ 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 @@ int class_interface_register(struct clas
+ 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 @@ void class_interface_unregister(struct c
+ 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
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_ho
+ .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 @@ void device_initialize(struct device *de
+ klist_children_put);
+ INIT_LIST_HEAD(&dev->dma_pools);
+ init_MUTEX(&dev->sem);
++ device_init_wakeup(dev, 0);
+ }
+
+ /**
+@@ -258,6 +266,14 @@ int device_add(struct device *dev)
+
+ 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 @@ void device_del(struct device * dev)
+
+ 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 @@ static struct device * next_device(struc
+
+ /**
+ * 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
+--- 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 @@ static void __devinit register_cpu_contr
+ }
+ 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 @@ void unregister_cpu(struct cpu *cpu, str
+ 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 @@ int __devinit register_cpu(struct cpu *c
+ 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
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -28,6 +28,7 @@ static struct device * next_device(struc
+ /**
+ * 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 @@ EXPORT_SYMBOL_GPL(driver_for_each_device
+
+ /**
+ * 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
+--- 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
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -62,14 +62,16 @@ firmware_timeout_show(struct class *clas
+ }
+
+ /**
+- * 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_show(struct class_devic
+ }
+
+ /**
+- * 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 @@ out:
+ up(&fw_lock);
+ return ret_count;
+ }
++
+ static int
+ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
+ {
+@@ -227,11 +233,13 @@ fw_realloc_buffer(struct firmware_priv *
+ }
+
+ /**
+- * 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 @@ out:
+ 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 @@ out:
+
+ /**
+ * 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 @@ request_firmware(const struct firmware *
+
+ /**
+ * 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 @@ release_firmware(const struct firmware *
+
+ /**
+ * 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_work_func(void *arg)
+ }
+
+ /**
+- * 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
+--- 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>
++
++#include "base.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);
+ /**
+ * driver_init - initialize driver model.
+ *
+@@ -39,5 +34,6 @@ void __init driver_init(void)
+ 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
+--- /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 at intel.com>
++ * Dave Hansen <haveblue at 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
+--- a/drivers/base/platform.c
++++ b/drivers/base/platform.c
+@@ -10,12 +10,15 @@
+ * information.
+ */
+
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #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 @@ static int platform_suspend(struct devic
+ {
+ 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 @@ static int platform_resume(struct device
+ {
+ 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
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -30,23 +30,6 @@ LIST_HEAD(dpm_off_irq);
+ 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 @@ static inline void device_pm_release(str
+
+ 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 @@ int device_pm_add(struct device * dev)
+
+ 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 @@ void device_pm_remove(struct device * de
+ 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
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -67,9 +67,6 @@ extern int suspend_device(struct device
+ * 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 void device_pm_remove(stru
+
+ }
+
+-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
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -36,6 +36,7 @@ void dpm_runtime_resume(struct device *
+ 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
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -48,8 +48,81 @@ static ssize_t state_store(struct device
+ 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
+--- 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
+--- a/drivers/block/Kconfig.iosched
++++ b/drivers/block/Kconfig.iosched
+@@ -38,4 +38,32 @@ config IOSCHED_CFQ
+ 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
+--- 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
+--- a/drivers/block/aoe/aoechr.c
++++ b/drivers/block/aoe/aoechr.c
+@@ -224,7 +224,7 @@ aoechr_init(void)
+ 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
+--- 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 @@ ataid_complete(struct aoedev *d, unsigne
+ 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 @@ ataid_complete(struct aoedev *d, unsigne
+ 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
+--- a/drivers/block/as-iosched.c
++++ b/drivers/block/as-iosched.c
+@@ -98,7 +98,6 @@ struct as_data {
+
+ 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 @@ static struct io_context *as_get_io_cont
+ 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 @@ static inline void as_del_arq_hash(struc
+ __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 @@ static struct request *as_find_arq_hash(
+ 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 @@ static void as_completed_request(request
+
+ 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 @@ static void as_completed_request(request
+ }
+ }
+
+-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 @@ static void as_remove_queued_request(req
+ 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 inline int as_batch_expired(struc
+ 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 @@ static void as_move_to_dispatch(struct a
+ /*
+ * 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 @@ static void as_move_to_dispatch(struct a
+ 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 @@ static void as_move_to_dispatch(struct a
+ * 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 @@ fifo_expired:
+ 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 @@ as_add_aliased_request(struct as_data *a
+ /*
+ * 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 @@ static void as_add_request(struct as_dat
+ 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 @@ static void as_add_request(struct as_dat
+ arq->state = AS_RQ_QUEUED;
+ }
+
+-static void as_deactivate_request(request_queue_t *q, struct request *rq)
++static void as_activate_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++;
+- }
++ 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_insert_request(request_queue_t *q, struct request *rq, int where)
++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_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 @@ static int as_queue_empty(request_queue_
+ {
+ 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 @@ as_merge(request_queue_t *q, struct requ
+ 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 @@ as_merge(request_queue_t *q, struct requ
+
+ 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 @@ static void as_merged_request(request_qu
+ * behind the disk head. We currently don't bother adjusting.
+ */
+ }
+-
+- if (arq->on_hash)
+- q->last_merge = req;
+ }
+
+ static void
+@@ -1763,6 +1616,7 @@ as_merged_requests(request_queue_t *q, s
+ * 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 @@ static void as_work_handler(void *data)
+ 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 @@ static void as_put_request(request_queue
+ 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 void as_put_request(request_queue
+ }
+
+ 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 @@ static int as_init_queue(request_queue_t
+ 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 @@ static struct elevator_type iosched_as =
+ .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 int __init as_init(void)
+
+ 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
+--- 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
+--- a/drivers/block/cfq-iosched.c
++++ b/drivers/block/cfq-iosched.c
+@@ -84,7 +84,6 @@ static int cfq_max_depth = 2;
+ (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 @@ CFQ_CFQQ_FNS(expired);
+ #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 @@ static inline int cfq_crq_##name(const s
+ 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 @@ static inline void cfq_del_crq_hash(stru
+ 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 @@ static struct request *cfq_find_rq_hash(
+ 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 @@ static int cfq_queue_empty(request_queue
+ {
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+
+- return !cfq_pending_requests(cfqd);
++ return !cfqd->busy_queues;
+ }
+
+ /*
+@@ -386,11 +366,6 @@ cfq_choose_req(struct cfq_data *cfqd, st
+ 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 @@ cfq_find_next_crq(struct cfq_data *cfqd,
+ 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 @@ static void cfq_resort_rr_list(struct cf
+ * 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 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, s
+ 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 @@ static void cfq_add_crq_rb(struct cfq_rq
+ * 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 void cfq_add_crq_rb(struct cfq_rq
+ 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 @@ out:
+ return NULL;
+ }
+
+-static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
++static void cfq_activate_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);
+- }
++ 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)
++static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
+ {
+- cfq_deactivate_request(q, rq);
+- list_add(&rq->queuelist, &q->queue_head);
++ struct cfq_data *cfqd = q->elevator->elevator_data;
++
++ WARN_ON(!cfqd->rq_in_driver);
++ cfqd->rq_in_driver--;
+ }
+
+-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 @@ cfq_merge(request_queue_t *q, struct req
+ 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 @@ cfq_merge(request_queue_t *q, struct req
+
+ return ELEVATOR_NO_MERGE;
+ out:
+- q->last_merge = __rq;
+-out_insert:
+ *req = __rq;
+ return ret;
+ }
+@@ -762,14 +700,12 @@ static void cfq_merged_request(request_q
+ 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 @@ cfq_merged_requests(request_queue_t *q,
+ 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 @@ static int cfq_arm_slice_timer(struct cf
+ 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 @@ __cfq_dispatch_requests(struct cfq_data
+ /*
+ * 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 @@ __cfq_dispatch_requests(struct cfq_data
+ }
+
+ 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 @@ cfq_dispatch_requests(request_queue_t *q
+
+ 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 @@ cfq_dispatch_requests(request_queue_t *q
+ 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 void cfq_exit_io_context(struct c
+ }
+
+ 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 int cfq_ioc_set_ioprio(struct io_
+
+ 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 @@ out:
+ * 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 @@ cfq_crq_enqueued(struct cfq_data *cfqd,
+ }
+ }
+
+-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 @@ static void cfq_enqueue(struct cfq_data
+
+ 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 void cfq_put_request(request_queu
+ */
+ 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 @@ cfq_set_request(request_queue_t *q, stru
+ 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 @@ static void cfq_idle_slice_timer(unsigne
+ * 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;
+@@ -2260,10 +2059,8 @@ static void cfq_put_cfqd(struct cfq_data
+ if (!atomic_dec_and_test(&cfqd->ref))
+ return;
+
+- blk_put_queue(q);
+-
+ cfq_shutdown_timer_wq(cfqd);
+- q->elevator->elevator_data = NULL;
++ blk_put_queue(q);
+
+ mempool_destroy(cfqd->crq_pool);
+ kfree(cfqd->crq_hash);
+@@ -2576,10 +2373,9 @@ static struct elevator_type iosched_cfq
+ .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 +2416,8 @@ static int __init cfq_init(void)
+
+ 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
+--- a/drivers/block/deadline-iosched.c
++++ b/drivers/block/deadline-iosched.c
+@@ -50,7 +50,6 @@ struct deadline_data {
+ * 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 @@ static inline void deadline_del_drq_hash
+ __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 @@ deadline_del_drq_rb(struct deadline_data
+ 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 @@ deadline_find_first_drq(struct deadline_
+ /*
+ * 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 @@ deadline_add_request(struct request_queu
+ 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 @@ deadline_add_request(struct request_queu
+ 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 @@ deadline_merge(request_queue_t *q, struc
+ 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 @@ deadline_merge(request_queue_t *q, struc
+
+ 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 @@ static void deadline_merged_request(requ
+ deadline_del_drq_rb(dd, drq);
+ deadline_add_drq_rb(dd, drq);
+ }
+-
+- q->last_merge = req;
+ }
+
+ static void
+@@ -452,7 +421,7 @@ deadline_move_to_dispatch(struct deadlin
+ 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 @@ static inline int deadline_check_fifo(st
+ * 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 @@ dispatch_request:
+ 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 @@ static int deadline_init_queue(request_q
+ 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 @@ static void deadline_put_request(request
+ 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 @@ static struct elevator_type iosched_dead
+ .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
+--- 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 @@ inline int elv_try_merge(struct request
+ }
+ 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 @@ static struct elevator_type *elevator_fi
+ break;
+ }
+ }
+- spin_unlock_irq(&elv_list_lock);
+
+ return e;
+ }
+@@ -120,12 +110,15 @@ static void elevator_put(struct elevator
+
+ 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 @@ static int elevator_attach(request_queue
+ 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 char chosen_elevator[16];
+
+ static void elevator_setup_default(void)
+ {
++ struct elevator_type *e;
++
+ /*
+- * check if default is set and exists
++ * If default has not been set, use the compiled-in selection.
+ */
+- if (chosen_elevator[0] && elevator_find(chosen_elevator))
+- return;
++ if (!chosen_elevator[0])
++ strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
+
+-#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 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 @@ int elevator_init(request_queue_t *q, ch
+ 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 @@ void elevator_exit(elevator_t *e)
+ 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 @@ void elv_merged_request(request_queue_t
+
+ 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 @@ void elv_merge_requests(request_queue_t
+ {
+ 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 @@ void elv_deactivate_request(request_queu
+ * 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 @@ void elv_requeue_request(request_queue_t
+ 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,59 @@ void __elv_add_request(request_queue_t *
+
+ rq->q = q;
+
+- if (!test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
+- q->elevator->ops->elevator_add_req_fn(q, rq, where);
+-
+- 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);
+- }
+- } else
++ switch (where) {
++ case ELEVATOR_INSERT_FRONT:
++ rq->flags |= REQ_SOFTBARRIER;
++
++ list_add(&rq->queuelist, &q->queue_head);
++ break;
++
++ 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);
++ /*
++ * 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.
++ */
++ blk_remove_plug(q);
++ q->request_fn(q);
++ break;
++
++ case ELEVATOR_INSERT_SORT:
++ BUG_ON(!blk_fs_request(rq));
++ rq->flags |= REQ_SORTED;
++ if (q->last_merge == NULL && rq_mergeable(rq))
++ q->last_merge = rq;
+ /*
+- * if drain is set, store the request "locally". when the drain
+- * is finished, the requests will be handed ordered to the io
+- * scheduler
++ * Some ioscheds (cfq) run q->request_fn directly, so
++ * rq cannot be accessed after calling
++ * elevator_add_req_fn.
+ */
+- list_add_tail(&rq->queuelist, &q->drain_list);
++ q->elevator->ops->elevator_add_req_fn(q, 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 +406,19 @@ void elv_add_request(request_queue_t *q,
+
+ 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 +435,30 @@ struct request *elv_next_request(request
+ 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 +470,9 @@ struct request *elv_next_request(request
+ /*
+ * 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 +495,32 @@ struct request *elv_next_request(request
+ 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 +556,7 @@ struct request *elv_former_request(reque
+ }
+
+ 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 +592,11 @@ void elv_completed_request(request_queue
+ /*
+ * 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 +624,9 @@ void elv_unregister_queue(struct request
+
+ 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 +640,27 @@ EXPORT_SYMBOL_GPL(elv_register);
+
+ 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 +671,36 @@ EXPORT_SYMBOL_GPL(elv_unregister);
+ * 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 +709,6 @@ static void elevator_switch(request_queu
+ 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 +718,10 @@ static void elevator_switch(request_queu
+ 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 +730,13 @@ fail_register:
+ * 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 +758,10 @@ ssize_t elv_iosched_store(request_queue_
+ 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 +790,12 @@ ssize_t elv_iosched_show(request_queue_t
+ 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/floppy.c b/drivers/block/floppy.c
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -177,7 +177,7 @@ static int print_unex = 1;
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/devfs_fs_kernel.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/buffer_head.h> /* for invalidate_buffers() */
+
+ /*
+diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
+--- a/drivers/block/genhd.c
++++ b/drivers/block/genhd.c
+@@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kob
+ 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 @@ static ssize_t disk_stats_read(struct ge
+ 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 disk_attribute disk_attr_s
+ };
+
+ 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
+--- a/drivers/block/ll_rw_blk.c
++++ b/drivers/block/ll_rw_blk.c
+@@ -263,8 +263,6 @@ void blk_queue_make_request(request_queu
+ 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 @@ static void blk_pre_flush_end_io(struct
+ 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 @@ static void blk_post_flush_end_io(struct
+ 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 @@ struct request *blk_start_pre_flush(requ
+ 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 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags)
+ static char *rq_flags[] = {
+ "REQ_RW",
+ "REQ_FAILFAST",
++ "REQ_SORTED",
+ "REQ_SOFTBARRIER",
+ "REQ_HARDBARRIER",
+ "REQ_CMD",
+@@ -1047,6 +1048,7 @@ static char *rq_flags[] = {
+ "REQ_STARTED",
+ "REQ_DONTPREP",
+ "REQ_QUEUED",
++ "REQ_ELVPRIV",
+ "REQ_PC",
+ "REQ_BLOCK_PC",
+ "REQ_SENSE",
+@@ -1637,9 +1639,9 @@ static int blk_init_free_list(request_qu
+
+ 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 blk_init_free_list(request_qu
+
+ 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 @@ EXPORT_SYMBOL(blk_get_queue);
+
+ 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 @@ blk_alloc_request(request_queue_t *q, in
+ */
+ 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 @@ static void __freed_request(request_queu
+ * 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 @@ static void freed_request(request_queue_
+ * 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 @@ get_rq:
+ 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 @@ get_rq:
+ * 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 @@ static struct request *get_request_wait(
+ 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 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
+ * @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 @@ void disk_round_stats(struct gendisk *di
+ {
+ 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 @@ static void __blk_put_request(request_qu
+ if (unlikely(--req->ref_count))
+ return;
+
++ elv_completed_request(q, req);
++
+ req->rq_status = RQ_INACTIVE;
+ req->rl = NULL;
+
+@@ -2463,26 +2474,25 @@ static void __blk_put_request(request_qu
+ */
+ 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)
+ {
++ unsigned long flags;
++ request_queue_t *q = req->q;
++
+ /*
+- * if req->rl isn't set, this request didnt originate from the
+- * block layer, so it's safe to just disregard it
++ * Gee, IDE calls in w/ NULL q. Fix IDE and remove the
++ * following if (q) test.
+ */
+- if (req->rl) {
+- unsigned long flags;
+- request_queue_t *q = req->q;
+-
++ 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 @@ static inline void blk_partition_remap(s
+ }
+ }
+
+-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 @@ end_io:
+ 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 @@ void exit_io_context(void)
+ * 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 @@ EXPORT_SYMBOL(current_io_context);
+ *
+ * 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
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -881,7 +881,7 @@ loop_init_xfer(struct loop_device *lo, s
+ 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
+--- a/drivers/block/noop-iosched.c
++++ b/drivers/block/noop-iosched.c
+@@ -7,57 +7,20 @@
+ #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;
+-}
+-
+-static void elevator_noop_merge_requests(request_queue_t *q, struct request *req,
+- struct request *next)
+-{
+- list_del_init(&next->queuelist);
++ rq->flags |= REQ_NOMERGE;
++ elv_dispatch_add_tail(q, rq);
+ }
+
+-static void elevator_noop_add_request(request_queue_t *q, struct request *rq,
+- int where)
++static int elevator_noop_dispatch(request_queue_t *q, int force)
+ {
+- 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
+--- 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
+--- a/drivers/block/paride/pf.c
++++ b/drivers/block/paride/pf.c
+@@ -807,10 +807,6 @@ static int pf_next_buf(void)
+ 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
+--- a/drivers/block/paride/pg.c
++++ b/drivers/block/paride/pg.c
+@@ -162,6 +162,8 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV,
+ #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 @@ static int __init pg_init(void)
+ for (unit = 0; unit < PG_UNITS; unit++) {
+ struct pg *dev = &devices[unit];
+ if (dev->present) {
+- class_device_create(pg_class, 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
+--- a/drivers/block/paride/pt.c
++++ b/drivers/block/paride/pt.c
+@@ -146,6 +146,7 @@ static int (*drives[4])[6] = {&drive0, &
+ #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 @@ static int __init pt_init(void)
+ 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 @@ static int __init pt_init(void)
+ 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
+--- a/drivers/block/rd.c
++++ b/drivers/block/rd.c
+@@ -348,7 +348,7 @@ static int rd_open(struct inode *inode,
+ 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
+--- 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 at 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 @@ MODULE_DESCRIPTION("Promise SATA SX8 blo
+ #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 @@ enum {
+
+ /* 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 @@ enum {
+ 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 @@ static const char *state_name[] = {
+
+ struct carm_port {
+ unsigned int port_no;
+- unsigned int n_queued;
+ struct gendisk *disk;
+ struct carm_host *host;
+
+@@ -448,7 +471,7 @@ static inline int carm_lookup_bucket(u32
+ for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
+ if (msg_size <= msg_sizes[i])
+ return i;
+-
++
+ return -ENOENT;
+ }
+
+@@ -509,7 +532,7 @@ static struct carm_request *carm_get_req
+ 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 @@ static struct carm_request *carm_get_req
+ 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 @@ static inline void carm_end_rq(struct ca
+ 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
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -1512,7 +1512,7 @@ static void ub_state_sense(struct ub_dev
+ 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 @@ static int ub_sync_read_cap(struct ub_de
+ 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/block/viodasd.c b/drivers/block/viodasd.c
+--- a/drivers/block/viodasd.c
++++ b/drivers/block/viodasd.c
+@@ -778,13 +778,16 @@ static struct vio_device_id viodasd_devi
+ { "viodasd", "" },
+ { "", "" }
+ };
+-
+ MODULE_DEVICE_TABLE(vio, viodasd_device_table);
++
+ static struct vio_driver viodasd_driver = {
+- .name = "viodasd",
+ .id_table = viodasd_device_table,
+ .probe = viodasd_probe,
+- .remove = viodasd_remove
++ .remove = viodasd_remove,
++ .driver = {
++ .name = "viodasd",
++ .owner = THIS_MODULE,
++ }
+ };
+
+ /*
+diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
+--- a/drivers/bluetooth/Kconfig
++++ b/drivers/bluetooth/Kconfig
+@@ -55,14 +55,6 @@ config BT_HCIUART_BCSP
+
+ 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
+--- a/drivers/bluetooth/bpa10x.c
++++ b/drivers/bluetooth/bpa10x.c
+@@ -550,6 +550,9 @@ static int bpa10x_probe(struct usb_inter
+ 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
+--- 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 at philips.com>
+-
+- Based on
+- hci_h4.c by Maxim Krasnyansky <maxk at qualcomm.com>
+- ABCSP by Carl Orsborn <cjo at 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 at philips.com>
++ * Copyright (C) 2004-2005 Marcel Holtmann <marcel at 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 @@ static u16 bcsp_crc_reverse(u16 crc)
+ rev |= (crc & 1);
+ crc = crc >> 1;
+ }
++
+ return (rev);
+ }
+
+@@ -119,6 +152,7 @@ static u16 bcsp_crc_reverse(u16 crc)
+ 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 @@ static struct sk_buff *bcsp_prepare_pkt(
+ {
+ 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 @@ static struct sk_buff *bcsp_prepare_pkt(
+ 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 @@ static struct sk_buff *bcsp_prepare_pkt(
+ /* 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 @@ static struct sk_buff *bcsp_dequeue(stru
+
+ 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 @@ static void bcsp_pkt_cull(struct bcsp_st
+ 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 @@ static void bcsp_pkt_cull(struct bcsp_st
+ 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 @@ static inline void bcsp_complete_rx_pkt(
+
+ hci_recv_frame(bcsp->rx_skb);
+ }
++
+ bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
+ bcsp->rx_skb = NULL;
+ }
+@@ -598,8 +631,8 @@ static int bcsp_recv(struct hci_uart *hu
+
+ 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 @@ static int bcsp_recv(struct hci_uart *hu
+ 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 @@ static int bcsp_open(struct hci_uart *hu
+
+ bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
+
++ if (txcrc)
++ bcsp->use_crc = 1;
++
+ return 0;
+ }
+
+@@ -718,18 +754,19 @@ static int bcsp_close(struct hci_uart *h
+ }
+
+ 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 @@ int bcsp_deinit(void)
+ 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
+--- 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 at philips.com>
+-
+- Based on
+- hci_h4.c by Maxim Krasnyansky <maxk at qualcomm.com>
+- ABCSP by Carl Orsborn <cjo at 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
+--- 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 at 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 at qualcomm.com>
++ * Copyright (C) 2004-2005 Marcel Holtmann <marcel at 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 @@ static int h4_flush(struct hci_uart *hu)
+ 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_flush(struct hci_uart *hu)
+ 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 @@ static int h4_enqueue(struct hci_uart *h
+ /* 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 @@ static inline int h4_check_data_len(stru
+ 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 @@ static inline int h4_check_data_len(stru
+ h4->rx_state = H4_W4_PACKET_TYPE;
+ h4->rx_skb = NULL;
+ h4->rx_count = 0;
++
+ return 0;
+ }
+
+@@ -228,6 +247,7 @@ static int h4_recv(struct hci_uart *hu,
+ ptr++; count--;
+ continue;
+ };
++
+ ptr++; count--;
+
+ /* Allocate packet */
+@@ -238,9 +258,11 @@ static int h4_recv(struct hci_uart *hu,
+ 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 sk_buff *h4_dequeue(struct
+ }
+
+ 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
+--- 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 at 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
+--- 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 at 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 at qualcomm.com>
++ * Copyright (C) 2004-2005 Marcel Holtmann <marcel at 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 @@ int hci_uart_register_proto(struct hci_u
+ return -EEXIST;
+
+ hup[p->id] = p;
++
+ return 0;
+ }
+
+@@ -84,6 +81,7 @@ int hci_uart_unregister_proto(struct hci
+ return -EINVAL;
+
+ hup[p->id] = NULL;
++
+ return 0;
+ }
+
+@@ -91,13 +89,14 @@ static struct hci_uart_proto *hci_uart_g
+ {
+ 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 void hci_uart_tx_complete(
+ 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 @@ int hci_uart_tx_wakeup(struct hci_uart *
+ 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 @@ restart:
+
+ 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 @@ restart:
+ 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 @@ static int hci_uart_open(struct hci_dev
+ /* Nothing to do for UART driver */
+
+ set_bit(HCI_RUNNING, &hdev->flags);
++
+ return 0;
+ }
+
+@@ -234,6 +236,7 @@ static int hci_uart_send_frame(struct sk
+ hu->proto->enqueue(hu, skb);
+
+ hci_uart_tx_wakeup(hu);
++
+ return 0;
+ }
+
+@@ -241,7 +244,8 @@ static void hci_uart_destruct(struct hci
+ {
+ struct hci_uart *hu;
+
+- if (!hdev) return;
++ if (!hdev)
++ return;
+
+ BT_DBG("%s", hdev->name);
+
+@@ -272,6 +276,7 @@ static int hci_uart_tty_open(struct tty_
+ BT_ERR("Can't allocate controll structure");
+ return -ENFILE;
+ }
++
+ memset(hu, 0, sizeof(struct hci_uart));
+
+ tty->disc_data = hu;
+@@ -280,8 +285,10 @@ static int hci_uart_tty_open(struct tty_
+ 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 int hci_uart_tty_room (struct tty
+ 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_register_dev(struct
+ 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 @@ static int hci_uart_set_proto(struct hci
+ p->close(hu);
+ return err;
+ }
++
+ return 0;
+ }
+
+@@ -463,7 +471,7 @@ static int hci_uart_set_proto(struct hci
+ * 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 @@ static int hci_uart_tty_ioctl(struct tty
+ 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,28 +510,24 @@ static int hci_uart_tty_ioctl(struct tty
+ /*
+ * 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)
++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)
++
++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 unsigned int hci_uart_tty_poll(struct tty_struct *tty,
++ struct file *filp, poll_table *wait)
+ {
+ 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 int __init hci_uart_init(void)
+ {
+ static struct tty_ldisc hci_uart_ldisc;
+@@ -534,18 +538,18 @@ static int __init hci_uart_init(void)
+ /* 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
+--- 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 at 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 at qualcomm.com>
++ * Copyright (C) 2004-2005 Marcel Holtmann <marcel at 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_proto {
+ };
+
+ struct hci_uart {
+- 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 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;
+ };
+
+ /* 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/cdrom/viocd.c b/drivers/cdrom/viocd.c
+--- a/drivers/cdrom/viocd.c
++++ b/drivers/cdrom/viocd.c
+@@ -736,13 +736,16 @@ static struct vio_device_id viocd_device
+ { "viocd", "" },
+ { "", "" }
+ };
+-
+ MODULE_DEVICE_TABLE(vio, viocd_device_table);
++
+ static struct vio_driver viocd_driver = {
+- .name = "viocd",
+ .id_table = viocd_device_table,
+ .probe = viocd_probe,
+- .remove = viocd_remove
++ .remove = viocd_remove,
++ .driver = {
++ .name = "viocd",
++ .owner = THIS_MODULE,
++ }
+ };
+
+ static int __init viocd_init(void)
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -661,7 +661,7 @@ config HW_RANDOM
+
+ 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 MAX_RAW_DEVS
+
+ 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 @@ config MMTIMER
+
+ 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
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -82,6 +82,7 @@ obj-$(CONFIG_NWFLASH) += nwflash.o
+ 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
+--- a/drivers/char/agp/Kconfig
++++ b/drivers/char/agp/Kconfig
+@@ -27,7 +27,7 @@ config AGP
+
+ 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_ALI
+
+ 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_ATI
+
+ 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_INTEL
+
+ 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_NVIDIA
+
+ 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_SIS
+
+ 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_UNINORTH
+
+ 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- a/drivers/char/cyclades.c
++++ b/drivers/char/cyclades.c
+@@ -281,7 +281,7 @@ static char rcsid[] =
+ * 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/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
+--- a/drivers/char/drm/ati_pcigart.c
++++ b/drivers/char/drm/ati_pcigart.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file ati_pcigart.h
++ * \file ati_pcigart.c
+ * ATI PCI GART support
+ *
+ * \author Gareth Hughes <gareth at valinux.com>
+@@ -52,85 +52,91 @@
+ # define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
+ # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
+
+-static unsigned long drm_ati_alloc_pcigart_table( void )
++static unsigned long drm_ati_alloc_pcigart_table(void)
+ {
+ unsigned long address;
+ struct page *page;
+ int i;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+- address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
+- if ( address == 0UL ) {
++ address = __get_free_pages(GFP_KERNEL, ATI_PCIGART_TABLE_ORDER);
++ if (address == 0UL) {
+ return 0;
+ }
+
+- page = virt_to_page( address );
++ page = virt_to_page(address);
+
+- for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
++ for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
+ get_page(page);
+- SetPageReserved( page );
++ SetPageReserved(page);
+ }
+
+- DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
++ DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
+ return address;
+ }
+
+-static void drm_ati_free_pcigart_table( unsigned long address )
++static void drm_ati_free_pcigart_table(unsigned long address)
+ {
+ struct page *page;
+ int i;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+- page = virt_to_page( address );
++ page = virt_to_page(address);
+
+- for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
++ for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
+ __put_page(page);
+- ClearPageReserved( page );
++ ClearPageReserved(page);
+ }
+
+- free_pages( address, ATI_PCIGART_TABLE_ORDER );
++ free_pages(address, ATI_PCIGART_TABLE_ORDER);
+ }
+
+-int drm_ati_pcigart_cleanup( drm_device_t *dev,
+- unsigned long addr,
+- dma_addr_t bus_addr)
++int drm_ati_pcigart_cleanup(drm_device_t * dev,
++ drm_ati_pcigart_info * gart_info)
+ {
+ drm_sg_mem_t *entry = dev->sg;
+ unsigned long pages;
+ int i;
+
+ /* we need to support large memory configurations */
+- if ( !entry ) {
+- DRM_ERROR( "no scatter/gather memory!\n" );
++ if (!entry) {
++ DRM_ERROR("no scatter/gather memory!\n");
+ return 0;
+ }
+
+- if ( bus_addr ) {
+- pci_unmap_single(dev->pdev, bus_addr,
+- ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+- PCI_DMA_TODEVICE);
++ if (gart_info->bus_addr) {
++ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
++ pci_unmap_single(dev->pdev, gart_info->bus_addr,
++ ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
++ PCI_DMA_TODEVICE);
++ }
+
+- pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
+- ? entry->pages : ATI_MAX_PCIGART_PAGES;
++ pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
++ ? entry->pages : ATI_MAX_PCIGART_PAGES;
+
+- for ( i = 0 ; i < pages ; i++ ) {
+- if ( !entry->busaddr[i] ) break;
++ for (i = 0; i < pages; i++) {
++ if (!entry->busaddr[i])
++ break;
+ pci_unmap_single(dev->pdev, entry->busaddr[i],
+ PAGE_SIZE, PCI_DMA_TODEVICE);
+ }
++
++ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
++ gart_info->bus_addr = 0;
+ }
+
+- if ( addr ) {
+- drm_ati_free_pcigart_table( addr );
++ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
++ && gart_info->addr) {
++ drm_ati_free_pcigart_table(gart_info->addr);
++ gart_info->addr = 0;
+ }
+
+ return 1;
+ }
++
+ EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
+
+-int drm_ati_pcigart_init( drm_device_t *dev,
+- unsigned long *addr,
+- dma_addr_t *bus_addr)
++int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
+ {
+ drm_sg_mem_t *entry = dev->sg;
+ unsigned long address = 0;
+@@ -138,48 +144,57 @@ int drm_ati_pcigart_init( drm_device_t *
+ u32 *pci_gart, page_base, bus_address = 0;
+ int i, j, ret = 0;
+
+- if ( !entry ) {
+- DRM_ERROR( "no scatter/gather memory!\n" );
++ if (!entry) {
++ DRM_ERROR("no scatter/gather memory!\n");
+ goto done;
+ }
+
+- address = drm_ati_alloc_pcigart_table();
+- if ( !address ) {
+- DRM_ERROR( "cannot allocate PCI GART page!\n" );
+- goto done;
+- }
++ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
++ DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
+
+- if ( !dev->pdev ) {
+- DRM_ERROR( "PCI device unknown!\n" );
+- goto done;
+- }
++ address = drm_ati_alloc_pcigart_table();
++ if (!address) {
++ DRM_ERROR("cannot allocate PCI GART page!\n");
++ goto done;
++ }
+
+- bus_address = pci_map_single(dev->pdev, (void *)address,
+- ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+- PCI_DMA_TODEVICE);
+- if (bus_address == 0) {
+- DRM_ERROR( "unable to map PCIGART pages!\n" );
+- drm_ati_free_pcigart_table( address );
+- address = 0;
+- goto done;
++ if (!dev->pdev) {
++ DRM_ERROR("PCI device unknown!\n");
++ goto done;
++ }
++
++ bus_address = pci_map_single(dev->pdev, (void *)address,
++ ATI_PCIGART_TABLE_PAGES *
++ PAGE_SIZE, PCI_DMA_TODEVICE);
++ if (bus_address == 0) {
++ DRM_ERROR("unable to map PCIGART pages!\n");
++ drm_ati_free_pcigart_table(address);
++ address = 0;
++ goto done;
++ }
++ } else {
++ address = gart_info->addr;
++ bus_address = gart_info->bus_addr;
++ DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
++ bus_address, address);
+ }
+
+- pci_gart = (u32 *)address;
++ pci_gart = (u32 *) address;
+
+- pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
+- ? entry->pages : ATI_MAX_PCIGART_PAGES;
++ pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
++ ? entry->pages : ATI_MAX_PCIGART_PAGES;
+
+- memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
++ memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32));
+
+- for ( i = 0 ; i < pages ; i++ ) {
++ for (i = 0; i < pages; i++) {
+ /* we need to support large memory configurations */
+ entry->busaddr[i] = pci_map_single(dev->pdev,
+- page_address( entry->pagelist[i] ),
+- PAGE_SIZE,
+- PCI_DMA_TODEVICE);
++ page_address(entry->
++ pagelist[i]),
++ PAGE_SIZE, PCI_DMA_TODEVICE);
+ if (entry->busaddr[i] == 0) {
+- DRM_ERROR( "unable to map PCIGART pages!\n" );
+- drm_ati_pcigart_cleanup( dev, address, bus_address );
++ DRM_ERROR("unable to map PCIGART pages!\n");
++ drm_ati_pcigart_cleanup(dev, gart_info);
+ address = 0;
+ bus_address = 0;
+ goto done;
+@@ -187,7 +202,11 @@ int drm_ati_pcigart_init( drm_device_t *
+ page_base = (u32) entry->busaddr[i];
+
+ for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+- *pci_gart++ = cpu_to_le32( page_base );
++ if (gart_info->is_pcie)
++ *pci_gart = (cpu_to_le32(page_base) >> 8) | 0xc;
++ else
++ *pci_gart = cpu_to_le32(page_base);
++ *pci_gart++;
+ page_base += ATI_PCIGART_PAGE_SIZE;
+ }
+ }
+@@ -200,9 +219,10 @@ int drm_ati_pcigart_init( drm_device_t *
+ mb();
+ #endif
+
+-done:
+- *addr = address;
+- *bus_addr = bus_address;
++ done:
++ gart_info->addr = address;
++ gart_info->bus_addr = bus_address;
+ return ret;
+ }
++
+ EXPORT_SYMBOL(drm_ati_pcigart_init);
+diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
+--- a/drivers/char/drm/drm.h
++++ b/drivers/char/drm/drm.h
+@@ -1,7 +1,7 @@
+ /**
+- * \file drm.h
++ * \file drm.h
+ * Header for the Direct Rendering Manager
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ *
+ * \par Acknowledgments:
+@@ -33,7 +33,6 @@
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+-
+ #ifndef _DRM_H_
+ #define _DRM_H_
+
+@@ -56,7 +55,7 @@
+ #define ioctl(a,b,c) xf86ioctl(a,b,c)
+ #else
+ #include <sys/ioccom.h>
+-#endif /* __FreeBSD__ && xf86ioctl */
++#endif /* __FreeBSD__ && xf86ioctl */
+ #define DRM_IOCTL_NR(n) ((n) & 0xff)
+ #define DRM_IOC_VOID IOC_VOID
+ #define DRM_IOC_READ IOC_OUT
+@@ -97,16 +96,14 @@
+ #define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
+ #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+
+-
+-typedef unsigned int drm_handle_t;
+-typedef unsigned int drm_context_t;
+-typedef unsigned int drm_drawable_t;
+-typedef unsigned int drm_magic_t;
+-
++typedef unsigned int drm_handle_t;
++typedef unsigned int drm_context_t;
++typedef unsigned int drm_drawable_t;
++typedef unsigned int drm_magic_t;
+
+ /**
+ * Cliprect.
+- *
++ *
+ * \warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well
+ *
+@@ -114,22 +111,21 @@ typedef unsigned int drm_magic_t;
+ * backwards-compatibility reasons.
+ */
+ typedef struct drm_clip_rect {
+- unsigned short x1;
+- unsigned short y1;
+- unsigned short x2;
+- unsigned short y2;
++ unsigned short x1;
++ unsigned short y1;
++ unsigned short x2;
++ unsigned short y2;
+ } drm_clip_rect_t;
+
+-
+ /**
+ * Texture region,
+ */
+ typedef struct drm_tex_region {
+- unsigned char next;
+- unsigned char prev;
+- unsigned char in_use;
+- unsigned char padding;
+- unsigned int age;
++ unsigned char next;
++ unsigned char prev;
++ unsigned char in_use;
++ unsigned char padding;
++ unsigned int age;
+ } drm_tex_region_t;
+
+ /**
+@@ -141,28 +137,26 @@ typedef struct drm_tex_region {
+ */
+ typedef struct drm_hw_lock {
+ __volatile__ unsigned int lock; /**< lock variable */
+- char padding[60]; /**< Pad to cache line */
++ char padding[60]; /**< Pad to cache line */
+ } drm_hw_lock_t;
+
+-
+ /**
+ * DRM_IOCTL_VERSION ioctl argument type.
+- *
++ *
+ * \sa drmGetVersion().
+ */
+ typedef struct drm_version {
+- int version_major; /**< Major version */
+- int version_minor; /**< Minor version */
+- int version_patchlevel;/**< Patch level */
++ int version_major; /**< Major version */
++ int version_minor; /**< Minor version */
++ int version_patchlevel; /**< Patch level */
+ size_t name_len; /**< Length of name buffer */
+- char __user *name; /**< Name of driver */
++ char __user *name; /**< Name of driver */
+ size_t date_len; /**< Length of date buffer */
+- char __user *date; /**< User-space buffer to hold date */
++ char __user *date; /**< User-space buffer to hold date */
+ size_t desc_len; /**< Length of desc buffer */
+- char __user *desc; /**< User-space buffer to hold desc */
++ char __user *desc; /**< User-space buffer to hold desc */
+ } drm_version_t;
+
+-
+ /**
+ * DRM_IOCTL_GET_UNIQUE ioctl argument type.
+ *
+@@ -170,21 +164,18 @@ typedef struct drm_version {
+ */
+ typedef struct drm_unique {
+ size_t unique_len; /**< Length of unique */
+- char __user *unique; /**< Unique name for driver instantiation */
++ char __user *unique; /**< Unique name for driver instantiation */
+ } drm_unique_t;
+
+-
+ typedef struct drm_list {
+- int count; /**< Length of user-space structures */
+- drm_version_t __user *version;
++ int count; /**< Length of user-space structures */
++ drm_version_t __user *version;
+ } drm_list_t;
+
+-
+ typedef struct drm_block {
+- int unused;
++ int unused;
+ } drm_block_t;
+
+-
+ /**
+ * DRM_IOCTL_CONTROL ioctl argument type.
+ *
+@@ -196,44 +187,40 @@ typedef struct drm_control {
+ DRM_RM_COMMAND,
+ DRM_INST_HANDLER,
+ DRM_UNINST_HANDLER
+- } func;
+- int irq;
++ } func;
++ int irq;
+ } drm_control_t;
+
+-
+ /**
+ * Type of memory to map.
+ */
+ typedef enum drm_map_type {
+- _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
+- _DRM_REGISTERS = 1, /**< no caching, no core dump */
+- _DRM_SHM = 2, /**< shared, cached */
+- _DRM_AGP = 3, /**< AGP/GART */
++ _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
++ _DRM_REGISTERS = 1, /**< no caching, no core dump */
++ _DRM_SHM = 2, /**< shared, cached */
++ _DRM_AGP = 3, /**< AGP/GART */
+ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
+- _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
++ _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
+ } drm_map_type_t;
+
+-
+ /**
+ * Memory mapping flags.
+ */
+ typedef enum drm_map_flags {
+- _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
+- _DRM_READ_ONLY = 0x02,
+- _DRM_LOCKED = 0x04, /**< shared, cached, locked */
+- _DRM_KERNEL = 0x08, /**< kernel requires access */
++ _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
++ _DRM_READ_ONLY = 0x02,
++ _DRM_LOCKED = 0x04, /**< shared, cached, locked */
++ _DRM_KERNEL = 0x08, /**< kernel requires access */
+ _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
+- _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
+- _DRM_REMOVABLE = 0x40 /**< Removable mapping */
++ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
++ _DRM_REMOVABLE = 0x40 /**< Removable mapping */
+ } drm_map_flags_t;
+
+-
+ typedef struct drm_ctx_priv_map {
+- unsigned int ctx_id; /**< Context requesting private mapping */
+- void *handle; /**< Handle of map */
++ unsigned int ctx_id; /**< Context requesting private mapping */
++ void *handle; /**< Handle of map */
+ } drm_ctx_priv_map_t;
+
+-
+ /**
+ * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
+ * argument type.
+@@ -241,30 +228,28 @@ typedef struct drm_ctx_priv_map {
+ * \sa drmAddMap().
+ */
+ typedef struct drm_map {
+- unsigned long offset; /**< Requested physical address (0 for SAREA)*/
+- unsigned long size; /**< Requested physical size (bytes) */
+- drm_map_type_t type; /**< Type of memory to map */
++ unsigned long offset; /**< Requested physical address (0 for SAREA)*/
++ unsigned long size; /**< Requested physical size (bytes) */
++ drm_map_type_t type; /**< Type of memory to map */
+ drm_map_flags_t flags; /**< Flags */
+- void *handle; /**< User-space: "Handle" to pass to mmap() */
++ void *handle; /**< User-space: "Handle" to pass to mmap() */
+ /**< Kernel-space: kernel-virtual address */
+- int mtrr; /**< MTRR slot used */
+- /* Private data */
++ int mtrr; /**< MTRR slot used */
++ /* Private data */
+ } drm_map_t;
+
+-
+ /**
+ * DRM_IOCTL_GET_CLIENT ioctl argument type.
+ */
+ typedef struct drm_client {
+- int idx; /**< Which client desired? */
+- int auth; /**< Is client authenticated? */
+- unsigned long pid; /**< Process ID */
+- unsigned long uid; /**< User ID */
+- unsigned long magic; /**< Magic */
+- unsigned long iocs; /**< Ioctl count */
++ int idx; /**< Which client desired? */
++ int auth; /**< Is client authenticated? */
++ unsigned long pid; /**< Process ID */
++ unsigned long uid; /**< User ID */
++ unsigned long magic; /**< Magic */
++ unsigned long iocs; /**< Ioctl count */
+ } drm_client_t;
+
+-
+ typedef enum {
+ _DRM_STAT_LOCK,
+ _DRM_STAT_OPENS,
+@@ -282,63 +267,58 @@ typedef enum {
+ _DRM_STAT_DMA, /**< DMA */
+ _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
+ _DRM_STAT_MISSED /**< Missed DMA opportunity */
+-
+- /* Add to the *END* of the list */
++ /* Add to the *END* of the list */
+ } drm_stat_type_t;
+
+-
+ /**
+ * DRM_IOCTL_GET_STATS ioctl argument type.
+ */
+ typedef struct drm_stats {
+ unsigned long count;
+ struct {
+- unsigned long value;
++ unsigned long value;
+ drm_stat_type_t type;
+ } data[15];
+ } drm_stats_t;
+
+-
+ /**
+ * Hardware locking flags.
+ */
+ typedef enum drm_lock_flags {
+- _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
+- _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
+- _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
+- _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
+- /* These *HALT* flags aren't supported yet
+- -- they will be used to support the
+- full-screen DGA-like mode. */
++ _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
++ _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
++ _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
++ _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
++ /* These *HALT* flags aren't supported yet
++ -- they will be used to support the
++ full-screen DGA-like mode. */
+ _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+ _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
+ } drm_lock_flags_t;
+
+-
+ /**
+ * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
+- *
++ *
+ * \sa drmGetLock() and drmUnlock().
+ */
+ typedef struct drm_lock {
+- int context;
++ int context;
+ drm_lock_flags_t flags;
+ } drm_lock_t;
+
+-
+ /**
+ * DMA flags
+ *
+- * \warning
++ * \warning
+ * These values \e must match xf86drm.h.
+ *
+ * \sa drm_dma.
+ */
+-typedef enum drm_dma_flags {
+- /* Flags for DMA buffer dispatch */
+- _DRM_DMA_BLOCK = 0x01, /**<
++typedef enum drm_dma_flags {
++ /* Flags for DMA buffer dispatch */
++ _DRM_DMA_BLOCK = 0x01, /**<
+ * Block until buffer dispatched.
+- *
++ *
+ * \note The buffer may not yet have
+ * been processed by the hardware --
+ * getting a hardware lock with the
+@@ -347,79 +327,73 @@ typedef enum drm_dma_flags {
+ * processed.
+ */
+ _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+- _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
++ _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
+
+- /* Flags for DMA buffer request */
+- _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
+- _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
+- _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
++ /* Flags for DMA buffer request */
++ _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
++ _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
++ _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
+ } drm_dma_flags_t;
+
+-
+ /**
+ * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
+ *
+ * \sa drmAddBufs().
+ */
+ typedef struct drm_buf_desc {
+- int count; /**< Number of buffers of this size */
+- int size; /**< Size in bytes */
+- int low_mark; /**< Low water mark */
+- int high_mark; /**< High water mark */
++ int count; /**< Number of buffers of this size */
++ int size; /**< Size in bytes */
++ int low_mark; /**< Low water mark */
++ int high_mark; /**< High water mark */
+ enum {
+- _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+- _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+- _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
+- _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
+- } flags;
+- unsigned long agp_start; /**<
++ _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
++ _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
++ _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
++ _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
++ } flags;
++ unsigned long agp_start; /**<
+ * Start address of where the AGP buffers are
+ * in the AGP aperture
+ */
+ } drm_buf_desc_t;
+
+-
+ /**
+ * DRM_IOCTL_INFO_BUFS ioctl argument type.
+ */
+ typedef struct drm_buf_info {
+- int count; /**< Entries in list */
++ int count; /**< Entries in list */
+ drm_buf_desc_t __user *list;
+ } drm_buf_info_t;
+
+-
+ /**
+ * DRM_IOCTL_FREE_BUFS ioctl argument type.
+ */
+ typedef struct drm_buf_free {
+- int count;
+- int __user *list;
++ int count;
++ int __user *list;
+ } drm_buf_free_t;
+
+-
+ /**
+ * Buffer information
+ *
+ * \sa drm_buf_map.
+ */
+ typedef struct drm_buf_pub {
+- int idx; /**< Index into the master buffer list */
+- int total; /**< Buffer size */
+- int used; /**< Amount of buffer in use (for DMA) */
+- void __user *address; /**< Address of buffer */
++ int idx; /**< Index into the master buffer list */
++ int total; /**< Buffer size */
++ int used; /**< Amount of buffer in use (for DMA) */
++ void __user *address; /**< Address of buffer */
+ } drm_buf_pub_t;
+
+-
+ /**
+ * DRM_IOCTL_MAP_BUFS ioctl argument type.
+ */
+ typedef struct drm_buf_map {
+- int count; /**< Length of the buffer list */
+- void __user *virtual; /**< Mmap'd area in user-virtual */
++ int count; /**< Length of the buffer list */
++ void __user *virtual; /**< Mmap'd area in user-virtual */
+ drm_buf_pub_t __user *list; /**< Buffer information */
+ } drm_buf_map_t;
+
+-
+ /**
+ * DRM_IOCTL_DMA ioctl argument type.
+ *
+@@ -428,61 +402,55 @@ typedef struct drm_buf_map {
+ * \sa drmDMA().
+ */
+ typedef struct drm_dma {
+- int context; /**< Context handle */
+- int send_count; /**< Number of buffers to send */
+- int __user *send_indices; /**< List of handles to buffers */
+- int __user *send_sizes; /**< Lengths of data to send */
++ int context; /**< Context handle */
++ int send_count; /**< Number of buffers to send */
++ int __user *send_indices; /**< List of handles to buffers */
++ int __user *send_sizes; /**< Lengths of data to send */
+ drm_dma_flags_t flags; /**< Flags */
+- int request_count; /**< Number of buffers requested */
+- int request_size; /**< Desired size for buffers */
+- int __user *request_indices; /**< Buffer information */
+- int __user *request_sizes;
+- int granted_count; /**< Number of buffers granted */
++ int request_count; /**< Number of buffers requested */
++ int request_size; /**< Desired size for buffers */
++ int __user *request_indices; /**< Buffer information */
++ int __user *request_sizes;
++ int granted_count; /**< Number of buffers granted */
+ } drm_dma_t;
+
+-
+ typedef enum {
+ _DRM_CONTEXT_PRESERVED = 0x01,
+- _DRM_CONTEXT_2DONLY = 0x02
++ _DRM_CONTEXT_2DONLY = 0x02
+ } drm_ctx_flags_t;
+
+-
+ /**
+ * DRM_IOCTL_ADD_CTX ioctl argument type.
+ *
+ * \sa drmCreateContext() and drmDestroyContext().
+ */
+ typedef struct drm_ctx {
+- drm_context_t handle;
++ drm_context_t handle;
+ drm_ctx_flags_t flags;
+ } drm_ctx_t;
+
+-
+ /**
+ * DRM_IOCTL_RES_CTX ioctl argument type.
+ */
+ typedef struct drm_ctx_res {
+- int count;
+- drm_ctx_t __user *contexts;
++ int count;
++ drm_ctx_t __user *contexts;
+ } drm_ctx_res_t;
+
+-
+ /**
+ * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
+ */
+ typedef struct drm_draw {
+- drm_drawable_t handle;
++ drm_drawable_t handle;
+ } drm_draw_t;
+
+-
+ /**
+ * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
+ */
+ typedef struct drm_auth {
+- drm_magic_t magic;
++ drm_magic_t magic;
+ } drm_auth_t;
+
+-
+ /**
+ * DRM_IOCTL_IRQ_BUSID ioctl argument type.
+ *
+@@ -495,24 +463,20 @@ typedef struct drm_irq_busid {
+ int funcnum; /**< function number */
+ } drm_irq_busid_t;
+
+-
+ typedef enum {
+- _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+- _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+- _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
++ _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
++ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
++ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
+ } drm_vblank_seq_type_t;
+
+-
+ #define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+
+-
+ struct drm_wait_vblank_request {
+ drm_vblank_seq_type_t type;
+ unsigned int sequence;
+ unsigned long signal;
+ };
+
+-
+ struct drm_wait_vblank_reply {
+ drm_vblank_seq_type_t type;
+ unsigned int sequence;
+@@ -520,7 +484,6 @@ struct drm_wait_vblank_reply {
+ long tval_usec;
+ };
+
+-
+ /**
+ * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
+ *
+@@ -531,7 +494,6 @@ typedef union drm_wait_vblank {
+ struct drm_wait_vblank_reply reply;
+ } drm_wait_vblank_t;
+
+-
+ /**
+ * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+@@ -541,7 +503,6 @@ typedef struct drm_agp_mode {
+ unsigned long mode; /**< AGP mode */
+ } drm_agp_mode_t;
+
+-
+ /**
+ * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
+ *
+@@ -550,22 +511,20 @@ typedef struct drm_agp_mode {
+ typedef struct drm_agp_buffer {
+ unsigned long size; /**< In bytes -- will round to page boundary */
+ unsigned long handle; /**< Used for binding / unbinding */
+- unsigned long type; /**< Type of memory to allocate */
+- unsigned long physical; /**< Physical used by i810 */
++ unsigned long type; /**< Type of memory to allocate */
++ unsigned long physical; /**< Physical used by i810 */
+ } drm_agp_buffer_t;
+
+-
+ /**
+ * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
+ *
+ * \sa drmAgpBind() and drmAgpUnbind().
+ */
+ typedef struct drm_agp_binding {
+- unsigned long handle; /**< From drm_agp_buffer */
++ unsigned long handle; /**< From drm_agp_buffer */
+ unsigned long offset; /**< In bytes -- will round to page boundary */
+ } drm_agp_binding_t;
+
+-
+ /**
+ * DRM_IOCTL_AGP_INFO ioctl argument type.
+ *
+@@ -574,20 +533,19 @@ typedef struct drm_agp_binding {
+ * drmAgpVendorId() and drmAgpDeviceId().
+ */
+ typedef struct drm_agp_info {
+- int agp_version_major;
+- int agp_version_minor;
+- unsigned long mode;
+- unsigned long aperture_base; /* physical address */
+- unsigned long aperture_size; /* bytes */
+- unsigned long memory_allowed; /* bytes */
+- unsigned long memory_used;
++ int agp_version_major;
++ int agp_version_minor;
++ unsigned long mode;
++ unsigned long aperture_base; /* physical address */
++ unsigned long aperture_size; /* bytes */
++ unsigned long memory_allowed; /* bytes */
++ unsigned long memory_used;
+
+- /* PCI information */
++ /* PCI information */
+ unsigned short id_vendor;
+ unsigned short id_device;
+ } drm_agp_info_t;
+
+-
+ /**
+ * DRM_IOCTL_SG_ALLOC ioctl argument type.
+ */
+@@ -606,7 +564,6 @@ typedef struct drm_set_version {
+ int drm_dd_minor;
+ } drm_set_version_t;
+
+-
+ #define DRM_IOCTL_BASE 'd'
+ #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
+ #define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
+diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
+--- a/drivers/char/drm/drmP.h
++++ b/drivers/char/drm/drmP.h
+@@ -1,7 +1,7 @@
+ /**
+- * \file drmP.h
++ * \file drmP.h
+ * Private header for Direct Rendering Manager
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+@@ -43,7 +43,7 @@
+ * before static inline funcs in wait.h. Doing this so we
+ * can build the DRM (part of PI DRI). 4/21/2000 S + B */
+ #include <asm/current.h>
+-#endif /* __alpha__ */
++#endif /* __alpha__ */
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -58,7 +58,7 @@
+ #include <linux/mm.h>
+ #include <linux/cdev.h>
+ #if defined(__alpha__) || defined(__powerpc__)
+-#include <asm/pgtable.h> /* For pte_wrprotect */
++#include <asm/pgtable.h> /* For pte_wrprotect */
+ #endif
+ #include <asm/io.h>
+ #include <asm/mman.h>
+@@ -108,7 +108,6 @@
+ #define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
+ #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
+ #define DRM_LOOPING_LIMIT 5000000
+-#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
+ #define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
+ #define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
+
+@@ -138,16 +137,15 @@
+ #define DRM_MEM_CTXLIST 21
+
+ #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+-
+-/*@}*/
+
++/*@}*/
+
+ /***********************************************************************/
+ /** \name Backward compatibility section */
+ /*@{*/
+
+ #ifndef MODULE_LICENSE
+-#define MODULE_LICENSE(x)
++#define MODULE_LICENSE(x)
+ #endif
+
+ #ifndef preempt_disable
+@@ -155,7 +153,7 @@
+ #define preempt_enable()
+ #endif
+
+-#ifndef pte_offset_map
++#ifndef pte_offset_map
+ #define pte_offset_map pte_offset
+ #define pte_unmap(pte)
+ #endif
+@@ -166,7 +164,6 @@
+
+ /*@}*/
+
+-
+ /***********************************************************************/
+ /** \name Macros to make printk easier */
+ /*@{*/
+@@ -195,7 +192,7 @@
+
+ /**
+ * Debug output.
+- *
++ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+@@ -223,14 +220,13 @@
+
+ /*@}*/
+
+-
+ /***********************************************************************/
+ /** \name Internal types and structures */
+ /*@{*/
+
+-#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+-#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
+-#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
++#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
++#define DRM_MIN(a,b) min(a,b)
++#define DRM_MAX(a,b) max(a,b)
+
+ #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
+ #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
+@@ -275,7 +271,7 @@ do { \
+ if ( copy_to_user( name, value, len ) ) \
+ return -EFAULT; \
+ }
+-
++
+ /**
+ * Ioctl function type.
+ *
+@@ -284,25 +280,25 @@ do { \
+ * \param cmd command.
+ * \param arg argument.
+ */
+-typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
++typedef int drm_ioctl_t(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
+
+ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+ typedef struct drm_ioctl_desc {
+- drm_ioctl_t *func;
+- int auth_needed;
+- int root_only;
++ drm_ioctl_t *func;
++ int auth_needed;
++ int root_only;
+ } drm_ioctl_desc_t;
+
+ typedef struct drm_devstate {
+- pid_t owner; /**< X server pid holding x_lock */
++ pid_t owner; /**< X server pid holding x_lock */
+ } drm_devstate_t;
+
+ typedef struct drm_magic_entry {
+- drm_magic_t magic;
+- struct drm_file *priv;
++ drm_magic_t magic;
++ struct drm_file *priv;
+ struct drm_magic_entry *next;
+ } drm_magic_entry_t;
+
+@@ -313,111 +309,110 @@ typedef struct drm_magic_head {
+
+ typedef struct drm_vma_entry {
+ struct vm_area_struct *vma;
+- struct drm_vma_entry *next;
+- pid_t pid;
++ struct drm_vma_entry *next;
++ pid_t pid;
+ } drm_vma_entry_t;
+
+ /**
+ * DMA buffer.
+ */
+ typedef struct drm_buf {
+- int idx; /**< Index into master buflist */
+- int total; /**< Buffer size */
+- int order; /**< log-base-2(total) */
+- int used; /**< Amount of buffer in use (for DMA) */
+- unsigned long offset; /**< Byte offset (used internally) */
+- void *address; /**< Address of buffer */
+- unsigned long bus_address; /**< Bus address of buffer */
+- struct drm_buf *next; /**< Kernel-only: used for free list */
+- __volatile__ int waiting; /**< On kernel DMA queue */
+- __volatile__ int pending; /**< On hardware DMA queue */
++ int idx; /**< Index into master buflist */
++ int total; /**< Buffer size */
++ int order; /**< log-base-2(total) */
++ int used; /**< Amount of buffer in use (for DMA) */
++ unsigned long offset; /**< Byte offset (used internally) */
++ void *address; /**< Address of buffer */
++ unsigned long bus_address; /**< Bus address of buffer */
++ struct drm_buf *next; /**< Kernel-only: used for free list */
++ __volatile__ int waiting; /**< On kernel DMA queue */
++ __volatile__ int pending; /**< On hardware DMA queue */
+ wait_queue_head_t dma_wait; /**< Processes waiting */
+- struct file *filp; /**< Pointer to holding file descr */
+- int context; /**< Kernel queue for this buffer */
+- int while_locked;/**< Dispatch this buffer while locked */
++ struct file *filp; /**< Pointer to holding file descr */
++ int context; /**< Kernel queue for this buffer */
++ int while_locked; /**< Dispatch this buffer while locked */
+ enum {
+- DRM_LIST_NONE = 0,
+- DRM_LIST_FREE = 1,
+- DRM_LIST_WAIT = 2,
+- DRM_LIST_PEND = 3,
+- DRM_LIST_PRIO = 4,
++ DRM_LIST_NONE = 0,
++ DRM_LIST_FREE = 1,
++ DRM_LIST_WAIT = 2,
++ DRM_LIST_PEND = 3,
++ DRM_LIST_PRIO = 4,
+ DRM_LIST_RECLAIM = 5
+- } list; /**< Which list we're on */
++ } list; /**< Which list we're on */
+
+- int dev_priv_size; /**< Size of buffer private storage */
+- void *dev_private; /**< Per-buffer private storage */
++ int dev_priv_size; /**< Size of buffer private storage */
++ void *dev_private; /**< Per-buffer private storage */
+ } drm_buf_t;
+
+-
+ /** bufs is one longer than it has to be */
+ typedef struct drm_waitlist {
+- int count; /**< Number of possible buffers */
+- drm_buf_t **bufs; /**< List of pointers to buffers */
+- drm_buf_t **rp; /**< Read pointer */
+- drm_buf_t **wp; /**< Write pointer */
+- drm_buf_t **end; /**< End pointer */
+- spinlock_t read_lock;
+- spinlock_t write_lock;
++ int count; /**< Number of possible buffers */
++ drm_buf_t **bufs; /**< List of pointers to buffers */
++ drm_buf_t **rp; /**< Read pointer */
++ drm_buf_t **wp; /**< Write pointer */
++ drm_buf_t **end; /**< End pointer */
++ spinlock_t read_lock;
++ spinlock_t write_lock;
+ } drm_waitlist_t;
+
+ typedef struct drm_freelist {
+- int initialized; /**< Freelist in use */
+- atomic_t count; /**< Number of free buffers */
+- drm_buf_t *next; /**< End pointer */
++ int initialized; /**< Freelist in use */
++ atomic_t count; /**< Number of free buffers */
++ drm_buf_t *next; /**< End pointer */
+
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+- int low_mark; /**< Low water mark */
+- int high_mark; /**< High water mark */
+- atomic_t wfh; /**< If waiting for high mark */
+- spinlock_t lock;
++ int low_mark; /**< Low water mark */
++ int high_mark; /**< High water mark */
++ atomic_t wfh; /**< If waiting for high mark */
++ spinlock_t lock;
+ } drm_freelist_t;
+
+ /**
+ * Buffer entry. There is one of this for each buffer size order.
+ */
+ typedef struct drm_buf_entry {
+- int buf_size; /**< size */
+- int buf_count; /**< number of buffers */
+- drm_buf_t *buflist; /**< buffer list */
+- int seg_count;
+- int page_order;
+- unsigned long *seglist;
++ int buf_size; /**< size */
++ int buf_count; /**< number of buffers */
++ drm_buf_t *buflist; /**< buffer list */
++ int seg_count;
++ int page_order;
++ unsigned long *seglist;
+
+- drm_freelist_t freelist;
++ drm_freelist_t freelist;
+ } drm_buf_entry_t;
+
+ /** File private data */
+ typedef struct drm_file {
+- int authenticated;
+- int minor;
+- pid_t pid;
+- uid_t uid;
+- drm_magic_t magic;
+- unsigned long ioctl_count;
+- struct drm_file *next;
+- struct drm_file *prev;
+- struct drm_head *head;
+- int remove_auth_on_close;
+- unsigned long lock_count;
+- void *driver_priv;
++ int authenticated;
++ int minor;
++ pid_t pid;
++ uid_t uid;
++ drm_magic_t magic;
++ unsigned long ioctl_count;
++ struct drm_file *next;
++ struct drm_file *prev;
++ struct drm_head *head;
++ int remove_auth_on_close;
++ unsigned long lock_count;
++ void *driver_priv;
+ } drm_file_t;
+
+ /** Wait queue */
+ typedef struct drm_queue {
+- atomic_t use_count; /**< Outstanding uses (+1) */
+- atomic_t finalization; /**< Finalization in progress */
+- atomic_t block_count; /**< Count of processes waiting */
+- atomic_t block_read; /**< Queue blocked for reads */
++ atomic_t use_count; /**< Outstanding uses (+1) */
++ atomic_t finalization; /**< Finalization in progress */
++ atomic_t block_count; /**< Count of processes waiting */
++ atomic_t block_read; /**< Queue blocked for reads */
+ wait_queue_head_t read_queue; /**< Processes waiting on block_read */
+- atomic_t block_write; /**< Queue blocked for writes */
++ atomic_t block_write; /**< Queue blocked for writes */
+ wait_queue_head_t write_queue; /**< Processes waiting on block_write */
+ #if 1
+- atomic_t total_queued; /**< Total queued statistic */
+- atomic_t total_flushed;/**< Total flushes statistic */
+- atomic_t total_locks; /**< Total locks statistics */
++ atomic_t total_queued; /**< Total queued statistic */
++ atomic_t total_flushed; /**< Total flushes statistic */
++ atomic_t total_locks; /**< Total locks statistics */
+ #endif
+- drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
+- drm_waitlist_t waitlist; /**< Pending buffers */
++ drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
++ drm_waitlist_t waitlist; /**< Pending buffers */
+ wait_queue_head_t flush_queue; /**< Processes waiting until flush */
+ } drm_queue_t;
+
+@@ -425,10 +420,10 @@ typedef struct drm_queue {
+ * Lock data.
+ */
+ typedef struct drm_lock_data {
+- drm_hw_lock_t *hw_lock; /**< Hardware lock */
+- struct file *filp; /**< File descr of lock holder (0=kernel) */
++ drm_hw_lock_t *hw_lock; /**< Hardware lock */
++ struct file *filp; /**< File descr of lock holder (0=kernel) */
+ wait_queue_head_t lock_queue; /**< Queue of blocked processes */
+- unsigned long lock_time; /**< Time of last lock in jiffies */
++ unsigned long lock_time; /**< Time of last lock in jiffies */
+ } drm_lock_data_t;
+
+ /**
+@@ -436,29 +431,29 @@ typedef struct drm_lock_data {
+ */
+ typedef struct drm_device_dma {
+
+- drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
+- int buf_count; /**< total number of buffers */
+- drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
+- int seg_count;
+- int page_count; /**< number of pages */
+- unsigned long *pagelist; /**< page list */
+- unsigned long byte_count;
++ drm_buf_entry_t bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */
++ int buf_count; /**< total number of buffers */
++ drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
++ int seg_count;
++ int page_count; /**< number of pages */
++ unsigned long *pagelist; /**< page list */
++ unsigned long byte_count;
+ enum {
+ _DRM_DMA_USE_AGP = 0x01,
+- _DRM_DMA_USE_SG = 0x02,
+- _DRM_DMA_USE_FB = 0x04
++ _DRM_DMA_USE_SG = 0x02,
++ _DRM_DMA_USE_FB = 0x04
+ } flags;
+
+ } drm_device_dma_t;
+
+-/**
++/**
+ * AGP memory entry. Stored as a doubly linked list.
+ */
+ typedef struct drm_agp_mem {
+- unsigned long handle; /**< handle */
+- DRM_AGP_MEM *memory;
+- unsigned long bound; /**< address */
+- int pages;
++ unsigned long handle; /**< handle */
++ DRM_AGP_MEM *memory;
++ unsigned long bound; /**< address */
++ int pages;
+ struct drm_agp_mem *prev; /**< previous entry */
+ struct drm_agp_mem *next; /**< next entry */
+ } drm_agp_mem_t;
+@@ -469,31 +464,31 @@ typedef struct drm_agp_mem {
+ * \sa drm_agp_init() and drm_device::agp.
+ */
+ typedef struct drm_agp_head {
+- DRM_AGP_KERN agp_info; /**< AGP device information */
+- drm_agp_mem_t *memory; /**< memory entries */
+- unsigned long mode; /**< AGP mode */
+- struct agp_bridge_data *bridge;
+- int enabled; /**< whether the AGP bus as been enabled */
+- int acquired; /**< whether the AGP device has been acquired */
+- unsigned long base;
+- int agp_mtrr;
+- int cant_use_aperture;
+- unsigned long page_mask;
++ DRM_AGP_KERN agp_info; /**< AGP device information */
++ drm_agp_mem_t *memory; /**< memory entries */
++ unsigned long mode; /**< AGP mode */
++ struct agp_bridge_data *bridge;
++ int enabled; /**< whether the AGP bus as been enabled */
++ int acquired; /**< whether the AGP device has been acquired */
++ unsigned long base;
++ int agp_mtrr;
++ int cant_use_aperture;
++ unsigned long page_mask;
+ } drm_agp_head_t;
+
+ /**
+ * Scatter-gather memory.
+ */
+ typedef struct drm_sg_mem {
+- unsigned long handle;
+- void *virtual;
+- int pages;
+- struct page **pagelist;
+- dma_addr_t *busaddr;
++ unsigned long handle;
++ void *virtual;
++ int pages;
++ struct page **pagelist;
++ dma_addr_t *busaddr;
+ } drm_sg_mem_t;
+
+ typedef struct drm_sigdata {
+- int context;
++ int context;
+ drm_hw_lock_t *lock;
+ } drm_sigdata_t;
+
+@@ -507,8 +502,8 @@ typedef struct drm_dma_handle {
+ * Mappings list
+ */
+ typedef struct drm_map_list {
+- struct list_head head; /**< list head */
+- drm_map_t *map; /**< mapping */
++ struct list_head head; /**< list head */
++ drm_map_t *map; /**< mapping */
+ unsigned int user_token;
+ } drm_map_list_t;
+
+@@ -518,19 +513,28 @@ typedef drm_map_t drm_local_map_t;
+ * Context handle list
+ */
+ typedef struct drm_ctx_list {
+- struct list_head head; /**< list head */
+- drm_context_t handle; /**< context handle */
+- drm_file_t *tag; /**< associated fd private data */
++ struct list_head head; /**< list head */
++ drm_context_t handle; /**< context handle */
++ drm_file_t *tag; /**< associated fd private data */
+ } drm_ctx_list_t;
+
+-
+ typedef struct drm_vbl_sig {
+- struct list_head head;
+- unsigned int sequence;
+- struct siginfo info;
+- struct task_struct *task;
++ struct list_head head;
++ unsigned int sequence;
++ struct siginfo info;
++ struct task_struct *task;
+ } drm_vbl_sig_t;
+
++/* location of GART table */
++#define DRM_ATI_GART_MAIN 1
++#define DRM_ATI_GART_FB 2
++
++typedef struct ati_pcigart_info {
++ int gart_table_location;
++ int is_pcie;
++ unsigned long addr;
++ dma_addr_t bus_addr;
++} drm_ati_pcigart_info;
+
+ /**
+ * DRM driver structure. This structure represent the common code for
+@@ -540,24 +544,26 @@ typedef struct drm_vbl_sig {
+ struct drm_device;
+
+ struct drm_driver {
+- int (*preinit)(struct drm_device *, unsigned long flags);
+- void (*prerelease)(struct drm_device *, struct file *filp);
+- void (*pretakedown)(struct drm_device *);
+- int (*postcleanup)(struct drm_device *);
+- int (*presetup)(struct drm_device *);
+- int (*postsetup)(struct drm_device *);
+- int (*dma_ioctl)( DRM_IOCTL_ARGS );
+- int (*open_helper)(struct drm_device *, drm_file_t *);
+- void (*free_filp_priv)(struct drm_device *, drm_file_t *);
+- void (*release)(struct drm_device *, struct file *filp);
+- void (*dma_ready)(struct drm_device *);
+- int (*dma_quiescent)(struct drm_device *);
+- int (*context_ctor)(struct drm_device *dev, int context);
+- int (*context_dtor)(struct drm_device *dev, int context);
+- int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
+- void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock);
+- int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+-
++ int (*preinit) (struct drm_device *, unsigned long flags);
++ void (*prerelease) (struct drm_device *, struct file * filp);
++ void (*pretakedown) (struct drm_device *);
++ int (*postcleanup) (struct drm_device *);
++ int (*presetup) (struct drm_device *);
++ int (*postsetup) (struct drm_device *);
++ int (*dma_ioctl) (DRM_IOCTL_ARGS);
++ int (*open_helper) (struct drm_device *, drm_file_t *);
++ void (*free_filp_priv) (struct drm_device *, drm_file_t *);
++ void (*release) (struct drm_device *, struct file * filp);
++ void (*dma_ready) (struct drm_device *);
++ int (*dma_quiescent) (struct drm_device *);
++ int (*context_ctor) (struct drm_device * dev, int context);
++ int (*context_dtor) (struct drm_device * dev, int context);
++ int (*kernel_context_switch) (struct drm_device * dev, int old,
++ int new);
++ void (*kernel_context_switch_unlock) (struct drm_device * dev,
++ drm_lock_t * lock);
++ int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
++
+ /**
+ * Called by \c drm_device_is_agp. Typically used to determine if a
+ * card is really attached to AGP or not.
+@@ -572,17 +578,17 @@ struct drm_driver {
+ int (*device_is_agp) (struct drm_device * dev);
+
+ /* these have to be filled in */
+-
+- int (*postinit)(struct drm_device *, unsigned long flags);
+- irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
+- void (*irq_preinstall)(struct drm_device *dev);
+- void (*irq_postinstall)(struct drm_device *dev);
+- void (*irq_uninstall)(struct drm_device *dev);
+- void (*reclaim_buffers)(struct drm_device *dev, struct file *filp);
+- unsigned long (*get_map_ofs)(drm_map_t *map);
+- unsigned long (*get_reg_ofs)(struct drm_device *dev);
+- void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
+- int (*version)(drm_version_t *version);
++
++ int (*postinit) (struct drm_device *, unsigned long flags);
++ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
++ void (*irq_preinstall) (struct drm_device * dev);
++ void (*irq_postinstall) (struct drm_device * dev);
++ void (*irq_uninstall) (struct drm_device * dev);
++ void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);
++ unsigned long (*get_map_ofs) (drm_map_t * map);
++ unsigned long (*get_reg_ofs) (struct drm_device * dev);
++ void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
++ int (*version) (drm_version_t * version);
+ u32 driver_features;
+ int dev_priv_size;
+ drm_ioctl_desc_t *ioctls;
+@@ -609,128 +615,125 @@ typedef struct drm_head {
+ * may contain multiple heads.
+ */
+ typedef struct drm_device {
+- char *unique; /**< Unique identifier: e.g., busid */
+- int unique_len; /**< Length of unique field */
+- char *devname; /**< For /proc/interrupts */
+- int if_version; /**< Highest interface version set */
++ char *unique; /**< Unique identifier: e.g., busid */
++ int unique_len; /**< Length of unique field */
++ char *devname; /**< For /proc/interrupts */
++ int if_version; /**< Highest interface version set */
+
+- int blocked; /**< Blocked due to VC switch? */
++ int blocked; /**< Blocked due to VC switch? */
+
+ /** \name Locks */
+- /*@{*/
+- spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
+- struct semaphore struct_sem; /**< For others */
+- /*@}*/
++ /*@{ */
++ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
++ struct semaphore struct_sem; /**< For others */
++ /*@} */
+
+ /** \name Usage Counters */
+- /*@{*/
+- int open_count; /**< Outstanding files open */
+- atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+- atomic_t vma_count; /**< Outstanding vma areas open */
+- int buf_use; /**< Buffers in use -- cannot alloc */
+- atomic_t buf_alloc; /**< Buffer allocation in progress */
+- /*@}*/
++ /*@{ */
++ int open_count; /**< Outstanding files open */
++ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
++ atomic_t vma_count; /**< Outstanding vma areas open */
++ int buf_use; /**< Buffers in use -- cannot alloc */
++ atomic_t buf_alloc; /**< Buffer allocation in progress */
++ /*@} */
+
+ /** \name Performance counters */
+- /*@{*/
+- unsigned long counters;
+- drm_stat_type_t types[15];
+- atomic_t counts[15];
+- /*@}*/
++ /*@{ */
++ unsigned long counters;
++ drm_stat_type_t types[15];
++ atomic_t counts[15];
++ /*@} */
+
+ /** \name Authentication */
+- /*@{*/
+- drm_file_t *file_first; /**< file list head */
+- drm_file_t *file_last; /**< file list tail */
+- drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
+- /*@}*/
++ /*@{ */
++ drm_file_t *file_first; /**< file list head */
++ drm_file_t *file_last; /**< file list tail */
++ drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
++ /*@} */
+
+ /** \name Memory management */
+- /*@{*/
+- drm_map_list_t *maplist; /**< Linked list of regions */
+- int map_count; /**< Number of mappable regions */
++ /*@{ */
++ drm_map_list_t *maplist; /**< Linked list of regions */
++ int map_count; /**< Number of mappable regions */
+
+ /** \name Context handle management */
+- /*@{*/
+- drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
+- int ctx_count; /**< Number of context handles */
+- struct semaphore ctxlist_sem; /**< For ctxlist */
+-
+- drm_map_t **context_sareas; /**< per-context SAREA's */
+- int max_context;
+-
+- drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
+- drm_lock_data_t lock; /**< Information on hardware lock */
+- /*@}*/
++ /*@{ */
++ drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
++ int ctx_count; /**< Number of context handles */
++ struct semaphore ctxlist_sem; /**< For ctxlist */
++
++ drm_map_t **context_sareas; /**< per-context SAREA's */
++ int max_context;
++
++ drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
++ drm_lock_data_t lock; /**< Information on hardware lock */
++ /*@} */
+
+ /** \name DMA queues (contexts) */
+- /*@{*/
+- int queue_count; /**< Number of active DMA queues */
+- int queue_reserved; /**< Number of reserved DMA queues */
+- int queue_slots; /**< Actual length of queuelist */
+- drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
+- drm_device_dma_t *dma; /**< Optional pointer for DMA support */
+- /*@}*/
++ /*@{ */
++ int queue_count; /**< Number of active DMA queues */
++ int queue_reserved; /**< Number of reserved DMA queues */
++ int queue_slots; /**< Actual length of queuelist */
++ drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
++ drm_device_dma_t *dma; /**< Optional pointer for DMA support */
++ /*@} */
+
+ /** \name Context support */
+- /*@{*/
+- int irq; /**< Interrupt used by board */
+- int irq_enabled; /**< True if irq handler is enabled */
++ /*@{ */
++ int irq; /**< Interrupt used by board */
++ int irq_enabled; /**< True if irq handler is enabled */
+ __volatile__ long context_flag; /**< Context swapping flag */
+ __volatile__ long interrupt_flag; /**< Interruption handler flag */
+ __volatile__ long dma_flag; /**< DMA dispatch flag */
+ struct timer_list timer; /**< Timer for delaying ctx switch */
+- wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+- int last_checked; /**< Last context checked for DMA */
+- int last_context; /**< Last current context */
+- unsigned long last_switch; /**< jiffies at last context switch */
+- /*@}*/
+-
+- struct work_struct work;
++ wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
++ int last_checked; /**< Last context checked for DMA */
++ int last_context; /**< Last current context */
++ unsigned long last_switch; /**< jiffies at last context switch */
++ /*@} */
++
++ struct work_struct work;
+ /** \name VBLANK IRQ support */
+- /*@{*/
++ /*@{ */
++
++ wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
++ atomic_t vbl_received;
++ spinlock_t vbl_lock;
++ drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
++ unsigned int vbl_pending;
++
++ /*@} */
++ cycles_t ctx_start;
++ cycles_t lck_start;
+
+- wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
+- atomic_t vbl_received;
+- spinlock_t vbl_lock;
+- drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
+- unsigned int vbl_pending;
+-
+- /*@}*/
+- cycles_t ctx_start;
+- cycles_t lck_start;
+-
+- char buf[DRM_BSZ]; /**< Output buffer */
+- char *buf_rp; /**< Read pointer */
+- char *buf_wp; /**< Write pointer */
+- char *buf_end; /**< End pointer */
+ struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+ wait_queue_head_t buf_readers; /**< Processes waiting to read */
+ wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
+
+- drm_agp_head_t *agp; /**< AGP data */
++ drm_agp_head_t *agp; /**< AGP data */
+
+- struct pci_dev *pdev; /**< PCI device structure */
+- int pci_domain; /**< PCI bus domain number */
+- int pci_bus; /**< PCI bus number */
+- int pci_slot; /**< PCI slot number */
+- int pci_func; /**< PCI function number */
++ struct pci_dev *pdev; /**< PCI device structure */
++ int pci_domain; /**< PCI bus domain number */
++ int pci_bus; /**< PCI bus number */
++ int pci_slot; /**< PCI slot number */
++ int pci_func; /**< PCI function number */
+ #ifdef __alpha__
+ struct pci_controller *hose;
+ #endif
+- drm_sg_mem_t *sg; /**< Scatter gather memory */
+- unsigned long *ctx_bitmap; /**< context bitmap */
+- void *dev_private; /**< device private data */
+- drm_sigdata_t sigdata; /**< For block_all_signals */
+- sigset_t sigmask;
++ drm_sg_mem_t *sg; /**< Scatter gather memory */
++ unsigned long *ctx_bitmap; /**< context bitmap */
++ void *dev_private; /**< device private data */
++ drm_sigdata_t sigdata; /**< For block_all_signals */
++ sigset_t sigmask;
+
+- struct drm_driver *driver;
+- drm_local_map_t *agp_buffer_map;
++ struct drm_driver *driver;
++ drm_local_map_t *agp_buffer_map;
+ unsigned int agp_buffer_token;
+ drm_head_t primary; /**< primary screen head */
+ } drm_device_t;
+
+-static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
++static __inline__ int drm_core_check_feature(struct drm_device *dev,
++ int feature)
+ {
+ return ((dev->driver->driver_features & feature) ? 1 : 0);
+ }
+@@ -738,7 +741,7 @@ static __inline__ int drm_core_check_fea
+ #if __OS_HAS_AGP
+ static inline int drm_core_has_AGP(struct drm_device *dev)
+ {
+- return drm_core_check_feature(dev, DRIVER_USE_AGP);
++ return drm_core_check_feature(dev, DRIVER_USE_AGP);
+ }
+ #else
+ #define drm_core_has_AGP(dev) (0)
+@@ -747,7 +750,7 @@ static inline int drm_core_has_AGP(struc
+ #if __OS_HAS_MTRR
+ static inline int drm_core_has_MTRR(struct drm_device *dev)
+ {
+- return drm_core_check_feature(dev, DRIVER_USE_MTRR);
++ return drm_core_check_feature(dev, DRIVER_USE_MTRR);
+ }
+ #else
+ #define drm_core_has_MTRR(dev) (0)
+@@ -758,234 +761,229 @@ static inline int drm_core_has_MTRR(stru
+ /*@{*/
+
+ /* Misc. support (drm_init.h) */
+-extern int drm_flags;
+-extern void drm_parse_options( char *s );
+-extern int drm_cpu_valid( void );
++extern int drm_flags;
++extern void drm_parse_options(char *s);
++extern int drm_cpu_valid(void);
+
+ /* Driver support (drm_drv.h) */
+-extern int drm_init(struct drm_driver *driver);
+-extern void drm_exit(struct drm_driver *driver);
+-extern int drm_ioctl(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern long drm_compat_ioctl(struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_takedown(drm_device_t * dev);
++extern int drm_init(struct drm_driver *driver);
++extern void drm_exit(struct drm_driver *driver);
++extern int drm_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern long drm_compat_ioctl(struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_takedown(drm_device_t * dev);
+
+ /* Device support (drm_fops.h) */
+-extern int drm_open(struct inode *inode, struct file *filp);
+-extern int drm_stub_open(struct inode *inode, struct file *filp);
+-extern int drm_flush(struct file *filp);
+-extern int drm_fasync(int fd, struct file *filp, int on);
+-extern int drm_release(struct inode *inode, struct file *filp);
++extern int drm_open(struct inode *inode, struct file *filp);
++extern int drm_stub_open(struct inode *inode, struct file *filp);
++extern int drm_flush(struct file *filp);
++extern int drm_fasync(int fd, struct file *filp, int on);
++extern int drm_release(struct inode *inode, struct file *filp);
+
+ /* Mapping support (drm_vm.h) */
+-extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
+-extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
++extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
++extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
+
+ /* Memory management support (drm_memory.h) */
+ #include "drm_memory.h"
+-extern void drm_mem_init(void);
+-extern int drm_mem_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data);
+-extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size,
+- int area);
++extern void drm_mem_init(void);
++extern int drm_mem_info(char *buf, char **start, off_t offset,
++ int request, int *eof, void *data);
++extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
+ extern unsigned long drm_alloc_pages(int order, int area);
+-extern void drm_free_pages(unsigned long address, int order,
+- int area);
+-extern void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev);
+-extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
+- drm_device_t *dev);
+-extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
+-
+-extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type);
+-extern int drm_free_agp(DRM_AGP_MEM *handle, int pages);
+-extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
+-extern int drm_unbind_agp(DRM_AGP_MEM *handle);
++extern void drm_free_pages(unsigned long address, int order, int area);
++extern void *drm_ioremap(unsigned long offset, unsigned long size,
++ drm_device_t * dev);
++extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
++ drm_device_t * dev);
++extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev);
++
++extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
++extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
++extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
++extern int drm_unbind_agp(DRM_AGP_MEM * handle);
+
+ /* Misc. IOCTL support (drm_ioctl.h) */
+-extern int drm_irq_by_busid(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_getunique(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_setunique(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_getmap(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_getclient(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_getstats(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_setversion(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
++extern int drm_irq_by_busid(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_getunique(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_setunique(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_getmap(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_getclient(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_getstats(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_setversion(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
+
+ /* Context IOCTL support (drm_context.h) */
+-extern int drm_resctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_addctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_modctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_getctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_switchctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_newctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_rmctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-
+-extern int drm_ctxbitmap_init( drm_device_t *dev );
+-extern void drm_ctxbitmap_cleanup( drm_device_t *dev );
+-extern void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle );
+-
+-extern int drm_setsareactx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_getsareactx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
++extern int drm_resctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_addctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_modctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_getctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_switchctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_newctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_rmctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++
++extern int drm_ctxbitmap_init(drm_device_t * dev);
++extern void drm_ctxbitmap_cleanup(drm_device_t * dev);
++extern void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle);
+
+- /* Drawable IOCTL support (drm_drawable.h) */
+-extern int drm_adddraw(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_rmdraw(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
++extern int drm_setsareactx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_getsareactx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
+
++ /* Drawable IOCTL support (drm_drawable.h) */
++extern int drm_adddraw(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_rmdraw(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
+
+ /* Authentication IOCTL support (drm_auth.h) */
+-extern int drm_getmagic(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_authmagic(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-
+- /* Placeholder for ioctls past */
+-extern int drm_noop(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
++extern int drm_getmagic(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_authmagic(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++
++ /* Placeholder for ioctls past */
++extern int drm_noop(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
+
+ /* Locking IOCTL support (drm_lock.h) */
+-extern int drm_lock(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_unlock(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_lock_take(__volatile__ unsigned int *lock,
+- unsigned int context);
+-extern int drm_lock_free(drm_device_t *dev,
+- __volatile__ unsigned int *lock,
+- unsigned int context);
++extern int drm_lock(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_unlock(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context);
++extern int drm_lock_free(drm_device_t * dev,
++ __volatile__ unsigned int *lock, unsigned int context);
+
+ /* Buffer management support (drm_bufs.h) */
+-extern int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request);
+-extern int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request);
+-extern int drm_addmap(drm_device_t *dev, unsigned int offset,
++extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
++extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
++extern int drm_addmap(drm_device_t * dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+- drm_map_flags_t flags, drm_local_map_t **map_ptr);
++ drm_map_flags_t flags, drm_local_map_t ** map_ptr);
+ extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+-extern int drm_rmmap(drm_device_t *dev, drm_local_map_t *map);
+-extern int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map);
++extern int drm_rmmap(drm_device_t * dev, drm_local_map_t * map);
++extern int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map);
+ extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+-extern int drm_order( unsigned long size );
+-extern int drm_addbufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_infobufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_markbufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_freebufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_mapbufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern unsigned long drm_get_resource_start(drm_device_t *dev,
++extern int drm_order(unsigned long size);
++extern int drm_addbufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_infobufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_markbufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_freebufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_mapbufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern unsigned long drm_get_resource_start(drm_device_t * dev,
+ unsigned int resource);
+-extern unsigned long drm_get_resource_len(drm_device_t *dev,
++extern unsigned long drm_get_resource_len(drm_device_t * dev,
+ unsigned int resource);
+
+ /* DMA support (drm_dma.h) */
+-extern int drm_dma_setup(drm_device_t *dev);
+-extern void drm_dma_takedown(drm_device_t *dev);
+-extern void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf);
+-extern void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp);
++extern int drm_dma_setup(drm_device_t * dev);
++extern void drm_dma_takedown(drm_device_t * dev);
++extern void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf);
++extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp);
+
+ /* IRQ support (drm_irq.h) */
+-extern int drm_control( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int drm_irq_uninstall( drm_device_t *dev );
+-extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS );
+-extern void drm_driver_irq_preinstall( drm_device_t *dev );
+-extern void drm_driver_irq_postinstall( drm_device_t *dev );
+-extern void drm_driver_irq_uninstall( drm_device_t *dev );
+-
+-extern int drm_wait_vblank(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
+-extern void drm_vbl_send_signals( drm_device_t *dev );
++extern int drm_control(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_irq_uninstall(drm_device_t * dev);
++extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
++extern void drm_driver_irq_preinstall(drm_device_t * dev);
++extern void drm_driver_irq_postinstall(drm_device_t * dev);
++extern void drm_driver_irq_uninstall(drm_device_t * dev);
++
++extern int drm_wait_vblank(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq);
++extern void drm_vbl_send_signals(drm_device_t * dev);
+
+ /* AGP/GART support (drm_agpsupport.h) */
+-extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
++extern drm_agp_head_t *drm_agp_init(drm_device_t * dev);
+ extern int drm_agp_acquire(drm_device_t * dev);
+ extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_agp_release(drm_device_t *dev);
++ unsigned int cmd, unsigned long arg);
++extern int drm_agp_release(drm_device_t * dev);
+ extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode);
++ unsigned int cmd, unsigned long arg);
++extern int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode);
+ extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info);
++ unsigned int cmd, unsigned long arg);
++extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info);
+ extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_agp_alloc(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_agp_free(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+-extern int drm_agp_alloc(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_agp_free(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_agp_unbind(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_agp_bind(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
+-extern int drm_agp_free_memory(DRM_AGP_MEM *handle);
+-extern int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
+-extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle);
++extern int drm_agp_unbind(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_agp_bind(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,
++ size_t pages, u32 type);
++extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
++extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
++extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
+
+ /* Stub support (drm_stub.h) */
+ extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+- struct drm_driver *driver);
++ struct drm_driver *driver);
+ extern int drm_put_dev(drm_device_t * dev);
+ extern int drm_put_head(drm_head_t * head);
+-extern unsigned int drm_debug;
+-extern unsigned int drm_cards_limit;
++extern unsigned int drm_debug;
++extern unsigned int drm_cards_limit;
+ extern drm_head_t **drm_heads;
+ extern struct drm_sysfs_class *drm_class;
+ extern struct proc_dir_entry *drm_proc_root;
+
+ /* Proc support (drm_proc.h) */
+-extern int drm_proc_init(drm_device_t *dev,
+- int minor,
+- struct proc_dir_entry *root,
+- struct proc_dir_entry **dev_root);
+-extern int drm_proc_cleanup(int minor,
+- struct proc_dir_entry *root,
+- struct proc_dir_entry *dev_root);
++extern int drm_proc_init(drm_device_t * dev,
++ int minor,
++ struct proc_dir_entry *root,
++ struct proc_dir_entry **dev_root);
++extern int drm_proc_cleanup(int minor,
++ struct proc_dir_entry *root,
++ struct proc_dir_entry *dev_root);
+
+ /* Scatter Gather Support (drm_scatter.h) */
+-extern void drm_sg_cleanup(drm_sg_mem_t *entry);
+-extern int drm_sg_alloc(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-extern int drm_sg_free(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg);
+-
+- /* ATI PCIGART support (ati_pcigart.h) */
+-extern int drm_ati_pcigart_init(drm_device_t *dev,
+- unsigned long *addr,
+- dma_addr_t *bus_addr);
+-extern int drm_ati_pcigart_cleanup(drm_device_t *dev,
+- unsigned long addr,
+- dma_addr_t bus_addr);
++extern void drm_sg_cleanup(drm_sg_mem_t * entry);
++extern int drm_sg_alloc(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int drm_sg_free(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
+
+-extern drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size,
++ /* ATI PCIGART support (ati_pcigart.h) */
++extern int drm_ati_pcigart_init(drm_device_t * dev,
++ drm_ati_pcigart_info * gart_info);
++extern int drm_ati_pcigart_cleanup(drm_device_t * dev,
++ drm_ati_pcigart_info * gart_info);
++
++extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
+ size_t align, dma_addr_t maxaddr);
+-extern void __drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
+-extern void drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
++extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
++extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
+
+ /* sysfs support (drm_sysfs.c) */
+ struct drm_sysfs_class;
+@@ -998,38 +996,41 @@ extern struct class_device *drm_sysfs_de
+ const char *fmt, ...);
+ extern void drm_sysfs_device_remove(dev_t dev);
+
+-
+ /* Inline replacements for DRM_IOREMAP macros */
+-static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
++static __inline__ void drm_core_ioremap(struct drm_map *map,
++ struct drm_device *dev)
+ {
+- map->handle = drm_ioremap( map->offset, map->size, dev );
++ map->handle = drm_ioremap(map->offset, map->size, dev);
+ }
+
+-static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
++static __inline__ void drm_core_ioremap_nocache(struct drm_map *map,
++ struct drm_device *dev)
+ {
+ map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
+ }
+
+-static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
++static __inline__ void drm_core_ioremapfree(struct drm_map *map,
++ struct drm_device *dev)
+ {
+- if ( map->handle && map->size )
+- drm_ioremapfree( map->handle, map->size, dev );
++ if (map->handle && map->size)
++ drm_ioremapfree(map->handle, map->size, dev);
+ }
+
+-static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned int token)
++static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
++ unsigned int token)
+ {
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head, head)
+- if (_entry->user_token == token)
+- return _entry->map;
++ if (_entry->user_token == token)
++ return _entry->map;
+ return NULL;
+ }
+
+-static __inline__ int drm_device_is_agp(drm_device_t *dev)
++static __inline__ int drm_device_is_agp(drm_device_t * dev)
+ {
+- if ( dev->driver->device_is_agp != NULL ) {
+- int err = (*dev->driver->device_is_agp)( dev );
+-
++ if (dev->driver->device_is_agp != NULL) {
++ int err = (*dev->driver->device_is_agp) (dev);
++
+ if (err != 2) {
+ return err;
+ }
+@@ -1038,6 +1039,11 @@ static __inline__ int drm_device_is_agp(
+ return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
+ }
+
++static __inline__ int drm_device_is_pcie(drm_device_t * dev)
++{
++ return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
++}
++
+ static __inline__ void drm_core_dropmap(struct drm_map *map)
+ {
+ }
+@@ -1068,12 +1074,12 @@ extern void *drm_calloc(size_t nmemb, si
+
+ /*@}*/
+
+-extern unsigned long drm_core_get_map_ofs(drm_map_t *map);
++extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
+ extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
+
+ #ifndef pci_pretty_name
+ #define pci_pretty_name(dev) ""
+ #endif
+
+-#endif /* __KERNEL__ */
++#endif /* __KERNEL__ */
+ #endif
+diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
+--- a/drivers/char/drm/drm_agpsupport.c
++++ b/drivers/char/drm/drm_agpsupport.c
+@@ -1,7 +1,7 @@
+ /**
+- * \file drm_agpsupport.h
++ * \file drm_agpsupport.h
+ * DRM support for AGP/GART backend
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+@@ -48,30 +48,31 @@
+ * Verifies the AGP device has been initialized and acquired and fills in the
+ * drm_agp_info structure with the information in drm_agp_head::agp_info.
+ */
+-int drm_agp_info(drm_device_t *dev, drm_agp_info_t *info)
++int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info)
+ {
+- DRM_AGP_KERN *kern;
++ DRM_AGP_KERN *kern;
+
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+
+- kern = &dev->agp->agp_info;
++ kern = &dev->agp->agp_info;
+ info->agp_version_major = kern->version.major;
+ info->agp_version_minor = kern->version.minor;
+- info->mode = kern->mode;
+- info->aperture_base = kern->aper_base;
+- info->aperture_size = kern->aper_size * 1024 * 1024;
+- info->memory_allowed = kern->max_memory << PAGE_SHIFT;
+- info->memory_used = kern->current_memory << PAGE_SHIFT;
+- info->id_vendor = kern->device->vendor;
+- info->id_device = kern->device->device;
++ info->mode = kern->mode;
++ info->aperture_base = kern->aper_base;
++ info->aperture_size = kern->aper_size * 1024 * 1024;
++ info->memory_allowed = kern->max_memory << PAGE_SHIFT;
++ info->memory_used = kern->current_memory << PAGE_SHIFT;
++ info->id_vendor = kern->device->vendor;
++ info->id_device = kern->device->device;
+
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_agp_info);
+
+ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -81,7 +82,7 @@ int drm_agp_info_ioctl(struct inode *ino
+ err = drm_agp_info(dev, &info);
+ if (err)
+ return err;
+-
++
+ if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+@@ -91,12 +92,12 @@ int drm_agp_info_ioctl(struct inode *ino
+ * Acquire the AGP device.
+ *
+ * \param dev DRM device that is to acquire AGP
+- * \return zero on success or a negative number on failure.
++ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
+ */
+-int drm_agp_acquire(drm_device_t *dev)
++int drm_agp_acquire(drm_device_t * dev)
+ {
+ if (!dev->agp)
+ return -ENODEV;
+@@ -107,6 +108,7 @@ int drm_agp_acquire(drm_device_t *dev)
+ dev->agp->acquired = 1;
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_agp_acquire);
+
+ /**
+@@ -125,8 +127,8 @@ int drm_agp_acquire_ioctl(struct inode *
+ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+-
+- return drm_agp_acquire( (drm_device_t *) priv->head->dev );
++
++ return drm_agp_acquire((drm_device_t *) priv->head->dev);
+ }
+
+ /**
+@@ -137,7 +139,7 @@ int drm_agp_acquire_ioctl(struct inode *
+ *
+ * Verifies the AGP device has been acquired and calls \c agp_backend_release.
+ */
+-int drm_agp_release(drm_device_t *dev)
++int drm_agp_release(drm_device_t * dev)
+ {
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+@@ -145,6 +147,7 @@ int drm_agp_release(drm_device_t *dev)
+ dev->agp->acquired = 0;
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_agp_release);
+
+ int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
+@@ -152,13 +155,13 @@ int drm_agp_release_ioctl(struct inode *
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+-
++
+ return drm_agp_release(dev);
+ }
+
+ /**
+ * Enable the AGP bus.
+- *
++ *
+ * \param dev DRM device that has previously acquired AGP.
+ * \param mode Requested AGP mode.
+ * \return zero on success or a negative number on failure.
+@@ -166,27 +169,27 @@ int drm_agp_release_ioctl(struct inode *
+ * Verifies the AGP device has been acquired but not enabled, and calls
+ * \c agp_enable.
+ */
+-int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
++int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode)
+ {
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+
+- dev->agp->mode = mode.mode;
++ dev->agp->mode = mode.mode;
+ agp_enable(dev->agp->bridge, mode.mode);
+- dev->agp->base = dev->agp->agp_info.aper_base;
++ dev->agp->base = dev->agp->agp_info.aper_base;
+ dev->agp->enabled = 1;
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_agp_enable);
+
+ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_mode_t mode;
+
+-
+ if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
+ return -EFAULT;
+
+@@ -201,20 +204,20 @@ int drm_agp_enable_ioctl(struct inode *i
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+- *
++ *
+ * Verifies the AGP device is present and has been acquired, allocates the
+ * memory via alloc_agp() and creates a drm_agp_mem entry for it.
+ */
+ int drm_agp_alloc(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_agp_buffer_t request;
+- drm_agp_mem_t *entry;
+- DRM_AGP_MEM *memory;
+- unsigned long pages;
+- u32 type;
++ drm_agp_mem_t *entry;
++ DRM_AGP_MEM *memory;
++ unsigned long pages;
++ u32 type;
+ drm_agp_buffer_t __user *argp = (void __user *)arg;
+
+ if (!dev->agp || !dev->agp->acquired)
+@@ -224,7 +227,7 @@ int drm_agp_alloc(struct inode *inode, s
+ if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
+ return -ENOMEM;
+
+- memset(entry, 0, sizeof(*entry));
++ memset(entry, 0, sizeof(*entry));
+
+ pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+ type = (u32) request.type;
+@@ -234,21 +237,21 @@ int drm_agp_alloc(struct inode *inode, s
+ return -ENOMEM;
+ }
+
+- entry->handle = (unsigned long)memory->key + 1;
+- entry->memory = memory;
+- entry->bound = 0;
+- entry->pages = pages;
+- entry->prev = NULL;
+- entry->next = dev->agp->memory;
++ entry->handle = (unsigned long)memory->key + 1;
++ entry->memory = memory;
++ entry->bound = 0;
++ entry->pages = pages;
++ entry->prev = NULL;
++ entry->next = dev->agp->memory;
+ if (dev->agp->memory)
+ dev->agp->memory->prev = entry;
+ dev->agp->memory = entry;
+
+- request.handle = entry->handle;
++ request.handle = entry->handle;
+ request.physical = memory->physical;
+
+ if (copy_to_user(argp, &request, sizeof(request))) {
+- dev->agp->memory = entry->next;
++ dev->agp->memory = entry->next;
+ dev->agp->memory->prev = NULL;
+ drm_free_agp(memory, pages);
+ drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+@@ -263,11 +266,11 @@ int drm_agp_alloc(struct inode *inode, s
+ * \param dev DRM device structure.
+ * \param handle AGP memory handle.
+ * \return pointer to the drm_agp_mem structure associated with \p handle.
+- *
++ *
+ * Walks through drm_agp_head::memory until finding a matching handle.
+ */
+-static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
+- unsigned long handle)
++static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
++ unsigned long handle)
+ {
+ drm_agp_mem_t *entry;
+
+@@ -291,17 +294,18 @@ static drm_agp_mem_t *drm_agp_lookup_ent
+ * entry and passes it to the unbind_agp() function.
+ */
+ int drm_agp_unbind(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_agp_binding_t request;
+- drm_agp_mem_t *entry;
++ drm_agp_mem_t *entry;
+ int ret;
+
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+- if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
++ if (copy_from_user
++ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+ if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ return -EINVAL;
+@@ -309,7 +313,7 @@ int drm_agp_unbind(struct inode *inode,
+ return -EINVAL;
+ ret = drm_unbind_agp(entry->memory);
+ if (ret == 0)
+- entry->bound = 0;
++ entry->bound = 0;
+ return ret;
+ }
+
+@@ -327,18 +331,19 @@ int drm_agp_unbind(struct inode *inode,
+ * it to bind_agp() function.
+ */
+ int drm_agp_bind(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_agp_binding_t request;
+- drm_agp_mem_t *entry;
+- int retcode;
+- int page;
++ drm_agp_mem_t *entry;
++ int retcode;
++ int page;
+
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+- if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
++ if (copy_from_user
++ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+ if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ return -EINVAL;
+@@ -368,16 +373,17 @@ int drm_agp_bind(struct inode *inode, st
+ * and unlinks from the doubly linked list it's inserted in.
+ */
+ int drm_agp_free(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_agp_buffer_t request;
+- drm_agp_mem_t *entry;
++ drm_agp_mem_t *entry;
+
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+- if (copy_from_user(&request, (drm_agp_buffer_t __user *)arg, sizeof(request)))
++ if (copy_from_user
++ (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+ if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ return -EINVAL;
+@@ -403,9 +409,9 @@ int drm_agp_free(struct inode *inode, st
+ * \return pointer to a drm_agp_head structure.
+ *
+ */
+-drm_agp_head_t *drm_agp_init(drm_device_t *dev)
++drm_agp_head_t *drm_agp_init(drm_device_t * dev)
+ {
+- drm_agp_head_t *head = NULL;
++ drm_agp_head_t *head = NULL;
+
+ if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
+ return NULL;
+@@ -433,13 +439,14 @@ drm_agp_head_t *drm_agp_init(drm_device_
+ }
+
+ /** Calls agp_allocate_memory() */
+-DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type)
++DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge,
++ size_t pages, u32 type)
+ {
+ return agp_allocate_memory(bridge, pages, type);
+ }
+
+ /** Calls agp_free_memory() */
+-int drm_agp_free_memory(DRM_AGP_MEM *handle)
++int drm_agp_free_memory(DRM_AGP_MEM * handle)
+ {
+ if (!handle)
+ return 0;
+@@ -448,20 +455,21 @@ int drm_agp_free_memory(DRM_AGP_MEM *han
+ }
+
+ /** Calls agp_bind_memory() */
+-int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start)
++int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
+ {
+ if (!handle)
+ return -EINVAL;
+ return agp_bind_memory(handle, start);
+ }
++
+ EXPORT_SYMBOL(drm_agp_bind_memory);
+
+ /** Calls agp_unbind_memory() */
+-int drm_agp_unbind_memory(DRM_AGP_MEM *handle)
++int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
+ {
+ if (!handle)
+ return -EINVAL;
+ return agp_unbind_memory(handle);
+ }
+
+-#endif /* __OS_HAS_AGP */
++#endif /* __OS_HAS_AGP */
+diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
+--- a/drivers/char/drm/drm_auth.c
++++ b/drivers/char/drm/drm_auth.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_auth.h
++ * \file drm_auth.c
+ * IOCTLs for authentication
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -46,7 +46,7 @@
+ */
+ static int drm_hash_magic(drm_magic_t magic)
+ {
+- return magic & (DRM_HASH_SIZE-1);
++ return magic & (DRM_HASH_SIZE - 1);
+ }
+
+ /**
+@@ -59,11 +59,11 @@ static int drm_hash_magic(drm_magic_t ma
+ * the one with matching magic number, while holding the drm_device::struct_sem
+ * lock.
+ */
+-static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
++static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
+ {
+- drm_file_t *retval = NULL;
++ drm_file_t *retval = NULL;
+ drm_magic_entry_t *pt;
+- int hash = drm_hash_magic(magic);
++ int hash = drm_hash_magic(magic);
+
+ down(&dev->struct_sem);
+ for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
+@@ -78,7 +78,7 @@ static drm_file_t *drm_find_file(drm_dev
+
+ /**
+ * Adds a magic number.
+- *
++ *
+ * \param dev DRM device.
+ * \param priv file private data.
+ * \param magic magic number.
+@@ -87,28 +87,30 @@ static drm_file_t *drm_find_file(drm_dev
+ * associated the magic number hash key in drm_device::magiclist, while holding
+ * the drm_device::struct_sem lock.
+ */
+-static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
++static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
++ drm_magic_t magic)
+ {
+- int hash;
++ int hash;
+ drm_magic_entry_t *entry;
+
+ DRM_DEBUG("%d\n", magic);
+
+- hash = drm_hash_magic(magic);
+- entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
+- if (!entry) return -ENOMEM;
++ hash = drm_hash_magic(magic);
++ entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
++ if (!entry)
++ return -ENOMEM;
+ memset(entry, 0, sizeof(*entry));
+ entry->magic = magic;
+- entry->priv = priv;
+- entry->next = NULL;
++ entry->priv = priv;
++ entry->next = NULL;
+
+ down(&dev->struct_sem);
+ if (dev->magiclist[hash].tail) {
+ dev->magiclist[hash].tail->next = entry;
+- dev->magiclist[hash].tail = entry;
++ dev->magiclist[hash].tail = entry;
+ } else {
+- dev->magiclist[hash].head = entry;
+- dev->magiclist[hash].tail = entry;
++ dev->magiclist[hash].head = entry;
++ dev->magiclist[hash].tail = entry;
+ }
+ up(&dev->struct_sem);
+
+@@ -117,19 +119,18 @@ static int drm_add_magic(drm_device_t *d
+
+ /**
+ * Remove a magic number.
+- *
++ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches and unlinks the entry in drm_device::magiclist with the magic
+ * number hash key, while holding the drm_device::struct_sem lock.
+ */
+-static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
++static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
+ {
+ drm_magic_entry_t *prev = NULL;
+ drm_magic_entry_t *pt;
+- int hash;
+-
++ int hash;
+
+ DRM_DEBUG("%d\n", magic);
+ hash = drm_hash_magic(magic);
+@@ -171,21 +172,22 @@ static int drm_remove_magic(drm_device_t
+ * filp.
+ */
+ int drm_getmagic(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ static drm_magic_t sequence = 0;
+ static DEFINE_SPINLOCK(lock);
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_auth_t auth;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_auth_t auth;
+
+- /* Find unique magic */
++ /* Find unique magic */
+ if (priv->magic) {
+ auth.magic = priv->magic;
+ } else {
+ do {
+ spin_lock(&lock);
+- if (!sequence) ++sequence; /* reserve 0 */
++ if (!sequence)
++ ++sequence; /* reserve 0 */
+ auth.magic = sequence++;
+ spin_unlock(&lock);
+ } while (drm_find_file(dev, auth.magic));
+@@ -194,7 +196,7 @@ int drm_getmagic(struct inode *inode, st
+ }
+
+ DRM_DEBUG("%u\n", auth.magic);
+- if (copy_to_user((drm_auth_t __user *)arg, &auth, sizeof(auth)))
++ if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -211,14 +213,14 @@ int drm_getmagic(struct inode *inode, st
+ * Checks if \p filp is associated with the magic number passed in \arg.
+ */
+ int drm_authmagic(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_auth_t auth;
+- drm_file_t *file;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_auth_t auth;
++ drm_file_t *file;
+
+- if (copy_from_user(&auth, (drm_auth_t __user *)arg, sizeof(auth)))
++ if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
+ return -EFAULT;
+ DRM_DEBUG("%u\n", auth.magic);
+ if ((file = drm_find_file(dev, auth.magic))) {
+diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
+--- a/drivers/char/drm/drm_bufs.c
++++ b/drivers/char/drm/drm_bufs.c
+@@ -1,7 +1,7 @@
+ /**
+- * \file drm_bufs.h
++ * \file drm_bufs.c
+ * Generic buffer template
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+@@ -36,20 +36,22 @@
+ #include <linux/vmalloc.h>
+ #include "drmP.h"
+
+-unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
++unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource)
+ {
+ return pci_resource_start(dev->pdev, resource);
+ }
++
+ EXPORT_SYMBOL(drm_get_resource_start);
+
+-unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
++unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource)
+ {
+ return pci_resource_len(dev->pdev, resource);
+ }
++
+ EXPORT_SYMBOL(drm_get_resource_len);
+
+-static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
+- drm_local_map_t *map)
++static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,
++ drm_local_map_t * map)
+ {
+ struct list_head *list;
+
+@@ -71,7 +73,8 @@ static drm_map_list_t *drm_find_matching
+ #define END_RANGE 0x40000000
+
+ #ifdef _LP64
+-static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev)
++static __inline__ unsigned int HandleID(unsigned long lhandle,
++ drm_device_t * dev)
+ {
+ static unsigned int map32_handle = START_RANGE;
+ unsigned int hash;
+@@ -81,12 +84,12 @@ static __inline__ unsigned int HandleID(
+ map32_handle += PAGE_SIZE;
+ if (map32_handle > END_RANGE)
+ map32_handle = START_RANGE;
+- } else
++ } else
+ hash = lhandle;
+
+ while (1) {
+ drm_map_list_t *_entry;
+- list_for_each_entry(_entry, &dev->maplist->head,head) {
++ list_for_each_entry(_entry, &dev->maplist->head, head) {
+ if (_entry->user_token == hash)
+ break;
+ }
+@@ -114,16 +117,16 @@ static __inline__ unsigned int HandleID(
+ * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
+-int drm_addmap_core(drm_device_t * dev, unsigned int offset,
+- unsigned int size, drm_map_type_t type,
+- drm_map_flags_t flags, drm_map_list_t **maplist)
++static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
++ unsigned int size, drm_map_type_t type,
++ drm_map_flags_t flags, drm_map_list_t ** maplist)
+ {
+ drm_map_t *map;
+ drm_map_list_t *list;
+ drm_dma_handle_t *dmah;
+
+- map = drm_alloc( sizeof(*map), DRM_MEM_MAPS );
+- if ( !map )
++ map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
++ if (!map)
+ return -ENOMEM;
+
+ map->offset = offset;
+@@ -135,26 +138,26 @@ int drm_addmap_core(drm_device_t * dev,
+ * book keeping information about shared memory to allow for removal
+ * when processes fork.
+ */
+- if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) {
+- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
++ if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
++ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+- DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+- map->offset, map->size, map->type );
+- if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) {
+- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
++ DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
++ map->offset, map->size, map->type);
++ if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
++ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+- map->mtrr = -1;
++ map->mtrr = -1;
+ map->handle = NULL;
+
+- switch ( map->type ) {
++ switch (map->type) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+ #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
+- if ( map->offset + map->size < map->offset ||
+- map->offset < virt_to_phys(high_memory) ) {
+- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
++ if (map->offset + map->size < map->offset ||
++ map->offset < virt_to_phys(high_memory)) {
++ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+ #endif
+@@ -169,8 +172,9 @@ int drm_addmap_core(drm_device_t * dev,
+ if (list != NULL) {
+ if (list->map->size != map->size) {
+ DRM_DEBUG("Matching maps of type %d with "
+- "mismatched sizes, (%ld vs %ld)\n",
+- map->type, map->size, list->map->size);
++ "mismatched sizes, (%ld vs %ld)\n",
++ map->type, map->size,
++ list->map->size);
+ list->map->size = map->size;
+ }
+
+@@ -180,35 +184,33 @@ int drm_addmap_core(drm_device_t * dev,
+ }
+
+ if (drm_core_has_MTRR(dev)) {
+- if ( map->type == _DRM_FRAME_BUFFER ||
+- (map->flags & _DRM_WRITE_COMBINING) ) {
+- map->mtrr = mtrr_add( map->offset, map->size,
+- MTRR_TYPE_WRCOMB, 1 );
++ if (map->type == _DRM_FRAME_BUFFER ||
++ (map->flags & _DRM_WRITE_COMBINING)) {
++ map->mtrr = mtrr_add(map->offset, map->size,
++ MTRR_TYPE_WRCOMB, 1);
+ }
+ }
+ if (map->type == _DRM_REGISTERS)
+- map->handle = drm_ioremap( map->offset, map->size,
+- dev );
++ map->handle = drm_ioremap(map->offset, map->size, dev);
+ break;
+
+ case _DRM_SHM:
+ map->handle = vmalloc_32(map->size);
+- DRM_DEBUG( "%lu %d %p\n",
+- map->size, drm_order( map->size ), map->handle );
+- if ( !map->handle ) {
+- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
++ DRM_DEBUG("%lu %d %p\n",
++ map->size, drm_order(map->size), map->handle);
++ if (!map->handle) {
++ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -ENOMEM;
+ }
+ map->offset = (unsigned long)map->handle;
+- if ( map->flags & _DRM_CONTAINS_LOCK ) {
++ if (map->flags & _DRM_CONTAINS_LOCK) {
+ /* Prevent a 2nd X Server from creating a 2nd lock */
+ if (dev->lock.hw_lock != NULL) {
+- vfree( map->handle );
+- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
++ vfree(map->handle);
++ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EBUSY;
+ }
+- dev->sigdata.lock =
+- dev->lock.hw_lock = map->handle; /* Pointer to lock */
++ dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */
+ }
+ break;
+ case _DRM_AGP:
+@@ -217,7 +219,7 @@ int drm_addmap_core(drm_device_t * dev,
+ map->offset += dev->hose->mem_space->start;
+ #endif
+ map->offset += dev->agp->base;
+- map->mtrr = dev->agp->agp_mtrr; /* for getmap */
++ map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+ }
+ break;
+ case _DRM_SCATTER_GATHER:
+@@ -227,7 +229,7 @@ int drm_addmap_core(drm_device_t * dev,
+ }
+ map->offset += (unsigned long)dev->sg->virtual;
+ break;
+- case _DRM_CONSISTENT:
++ case _DRM_CONSISTENT:
+ /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+ * As we're limiting the address to 2^32-1 (or less),
+ * casting it down to 32 bits is no problem, but we
+@@ -242,12 +244,12 @@ int drm_addmap_core(drm_device_t * dev,
+ kfree(dmah);
+ break;
+ default:
+- drm_free( map, sizeof(*map), DRM_MEM_MAPS );
++ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+
+ list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
+- if(!list) {
++ if (!list) {
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+@@ -258,18 +260,18 @@ int drm_addmap_core(drm_device_t * dev,
+ list_add(&list->head, &dev->maplist->head);
+ /* Assign a 32-bit handle */
+ /* We do it here so that dev->struct_sem protects the increment */
+- list->user_token = HandleID(map->type==_DRM_SHM
++ list->user_token = HandleID(map->type == _DRM_SHM
+ ? (unsigned long)map->handle
+ : map->offset, dev);
+- up(&dev->struct_sem);
++ up(&dev->struct_sem);
+
+ *maplist = list;
+ return 0;
+ }
+
+-int drm_addmap(drm_device_t *dev, unsigned int offset,
++int drm_addmap(drm_device_t * dev, unsigned int offset,
+ unsigned int size, drm_map_type_t type,
+- drm_map_flags_t flags, drm_local_map_t **map_ptr)
++ drm_map_flags_t flags, drm_local_map_t ** map_ptr)
+ {
+ drm_map_list_t *list;
+ int rc;
+@@ -279,6 +281,7 @@ int drm_addmap(drm_device_t *dev, unsign
+ *map_ptr = list->map;
+ return rc;
+ }
++
+ EXPORT_SYMBOL(drm_addmap);
+
+ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
+@@ -294,24 +297,25 @@ int drm_addmap_ioctl(struct inode *inode
+ if (!(filp->f_mode & 3))
+ return -EACCES; /* Require read/write */
+
+- if (copy_from_user(& map, argp, sizeof(map))) {
++ if (copy_from_user(&map, argp, sizeof(map))) {
+ return -EFAULT;
+ }
+
+ err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
+ &maplist);
+
+- if (err)
++ if (err)
+ return err;
+
+ if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
+ return -EFAULT;
+- if (put_user(maplist->user_token, &argp->handle))
++
++ /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
++ if (put_user((void *)(unsigned long)maplist->user_token, &argp->handle))
+ return -EFAULT;
+ return 0;
+ }
+
+-
+ /**
+ * Remove a map private from list and deallocate resources if the mapping
+ * isn't in use.
+@@ -328,7 +332,7 @@ int drm_addmap_ioctl(struct inode *inode
+ *
+ * \sa drm_addmap
+ */
+-int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
++int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)
+ {
+ struct list_head *list;
+ drm_map_list_t *r_list = NULL;
+@@ -359,9 +363,8 @@ int drm_rmmap_locked(drm_device_t *dev,
+ case _DRM_FRAME_BUFFER:
+ if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
+ int retcode;
+- retcode = mtrr_del(map->mtrr, map->offset,
+- map->size);
+- DRM_DEBUG ("mtrr_del=%d\n", retcode);
++ retcode = mtrr_del(map->mtrr, map->offset, map->size);
++ DRM_DEBUG("mtrr_del=%d\n", retcode);
+ }
+ break;
+ case _DRM_SHM:
+@@ -381,9 +384,10 @@ int drm_rmmap_locked(drm_device_t *dev,
+
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_rmmap_locked);
+
+-int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
++int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)
+ {
+ int ret;
+
+@@ -393,6 +397,7 @@ int drm_rmmap(drm_device_t *dev, drm_loc
+
+ return ret;
+ }
++
+ EXPORT_SYMBOL(drm_rmmap);
+
+ /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
+@@ -414,7 +419,7 @@ int drm_rmmap_ioctl(struct inode *inode,
+ struct list_head *list;
+ int ret;
+
+- if (copy_from_user(&request, (drm_map_t __user *)arg, sizeof(request))) {
++ if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
+ return -EFAULT;
+ }
+
+@@ -423,7 +428,7 @@ int drm_rmmap_ioctl(struct inode *inode,
+ drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+
+ if (r_list->map &&
+- r_list->user_token == (unsigned long) request.handle &&
++ r_list->user_token == (unsigned long)request.handle &&
+ r_list->map->flags & _DRM_REMOVABLE) {
+ map = r_list->map;
+ break;
+@@ -462,7 +467,7 @@ int drm_rmmap_ioctl(struct inode *inode,
+ *
+ * Frees any pages and buffers associated with the given entry.
+ */
+-static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
++static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
+ {
+ int i;
+
+@@ -470,30 +475,27 @@ static void drm_cleanup_buf_error(drm_de
+ for (i = 0; i < entry->seg_count; i++) {
+ if (entry->seglist[i]) {
+ drm_free_pages(entry->seglist[i],
+- entry->page_order,
+- DRM_MEM_DMA);
++ entry->page_order, DRM_MEM_DMA);
+ }
+ }
+ drm_free(entry->seglist,
+- entry->seg_count *
+- sizeof(*entry->seglist),
+- DRM_MEM_SEGS);
++ entry->seg_count *
++ sizeof(*entry->seglist), DRM_MEM_SEGS);
+
+ entry->seg_count = 0;
+ }
+
+- if (entry->buf_count) {
+- for (i = 0; i < entry->buf_count; i++) {
++ if (entry->buf_count) {
++ for (i = 0; i < entry->buf_count; i++) {
+ if (entry->buflist[i].dev_private) {
+ drm_free(entry->buflist[i].dev_private,
+- entry->buflist[i].dev_priv_size,
+- DRM_MEM_BUFS);
++ entry->buflist[i].dev_priv_size,
++ DRM_MEM_BUFS);
+ }
+ }
+ drm_free(entry->buflist,
+- entry->buf_count *
+- sizeof(*entry->buflist),
+- DRM_MEM_BUFS);
++ entry->buf_count *
++ sizeof(*entry->buflist), DRM_MEM_BUFS);
+
+ entry->buf_count = 0;
+ }
+@@ -506,12 +508,12 @@ static void drm_cleanup_buf_error(drm_de
+ * \param dev drm_device_t to which the buffers are to be added.
+ * \param request pointer to a drm_buf_desc_t describing the request.
+ * \return zero on success or a negative number on failure.
+- *
++ *
+ * After some sanity checks creates a drm_buf structure for each buffer and
+ * reallocates the buffer list of the same size order to accommodate the new
+ * buffers.
+ */
+-int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
++int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_entry_t *entry;
+@@ -528,144 +530,145 @@ int drm_addbufs_agp(drm_device_t *dev, d
+ int i;
+ drm_buf_t **temp_buflist;
+
+- if ( !dma ) return -EINVAL;
++ if (!dma)
++ return -EINVAL;
+
+ count = request->count;
+ order = drm_order(request->size);
+ size = 1 << order;
+
+- alignment = (request->flags & _DRM_PAGE_ALIGN)
+- ? PAGE_ALIGN(size) : size;
++ alignment = (request->flags & _DRM_PAGE_ALIGN)
++ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = dev->agp->base + request->agp_start;
+
+- DRM_DEBUG( "count: %d\n", count );
+- DRM_DEBUG( "order: %d\n", order );
+- DRM_DEBUG( "size: %d\n", size );
+- DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
+- DRM_DEBUG( "alignment: %d\n", alignment );
+- DRM_DEBUG( "page_order: %d\n", page_order );
+- DRM_DEBUG( "total: %d\n", total );
+-
+- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+- if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+-
+- spin_lock( &dev->count_lock );
+- if ( dev->buf_use ) {
+- spin_unlock( &dev->count_lock );
++ DRM_DEBUG("count: %d\n", count);
++ DRM_DEBUG("order: %d\n", order);
++ DRM_DEBUG("size: %d\n", size);
++ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
++ DRM_DEBUG("alignment: %d\n", alignment);
++ DRM_DEBUG("page_order: %d\n", page_order);
++ DRM_DEBUG("total: %d\n", total);
++
++ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
++ return -EINVAL;
++ if (dev->queue_count)
++ return -EBUSY; /* Not while in use */
++
++ spin_lock(&dev->count_lock);
++ if (dev->buf_use) {
++ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+- atomic_inc( &dev->buf_alloc );
+- spin_unlock( &dev->count_lock );
++ atomic_inc(&dev->buf_alloc);
++ spin_unlock(&dev->count_lock);
+
+- down( &dev->struct_sem );
++ down(&dev->struct_sem);
+ entry = &dma->bufs[order];
+- if ( entry->buf_count ) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
+- return -ENOMEM; /* May only call once for each order */
++ if (entry->buf_count) {
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
++ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
+
+- entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
+- DRM_MEM_BUFS );
+- if ( !entry->buflist ) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
++ DRM_MEM_BUFS);
++ if (!entry->buflist) {
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+- memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
++ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+- while ( entry->buf_count < count ) {
+- buf = &entry->buflist[entry->buf_count];
+- buf->idx = dma->buf_count + entry->buf_count;
+- buf->total = alignment;
+- buf->order = order;
+- buf->used = 0;
++ while (entry->buf_count < count) {
++ buf = &entry->buflist[entry->buf_count];
++ buf->idx = dma->buf_count + entry->buf_count;
++ buf->total = alignment;
++ buf->order = order;
++ buf->used = 0;
+
+- buf->offset = (dma->byte_count + offset);
++ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset);
+- buf->next = NULL;
++ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+- init_waitqueue_head( &buf->dma_wait );
+- buf->filp = NULL;
++ init_waitqueue_head(&buf->dma_wait);
++ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->driver->dev_priv_size;
+- buf->dev_private = drm_alloc( buf->dev_priv_size,
+- DRM_MEM_BUFS );
+- if(!buf->dev_private) {
++ buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
++ if (!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+- drm_cleanup_buf_error(dev,entry);
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_cleanup_buf_error(dev, entry);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+- memset( buf->dev_private, 0, buf->dev_priv_size );
++ memset(buf->dev_private, 0, buf->dev_priv_size);
+
+- DRM_DEBUG( "buffer %d @ %p\n",
+- entry->buf_count, buf->address );
++ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+- DRM_DEBUG( "byte_count: %d\n", byte_count );
++ DRM_DEBUG("byte_count: %d\n", byte_count);
+
+- temp_buflist = drm_realloc( dma->buflist,
+- dma->buf_count * sizeof(*dma->buflist),
+- (dma->buf_count + entry->buf_count)
+- * sizeof(*dma->buflist),
+- DRM_MEM_BUFS );
+- if(!temp_buflist) {
++ temp_buflist = drm_realloc(dma->buflist,
++ dma->buf_count * sizeof(*dma->buflist),
++ (dma->buf_count + entry->buf_count)
++ * sizeof(*dma->buflist), DRM_MEM_BUFS);
++ if (!temp_buflist) {
+ /* Free the entry because it isn't valid */
+- drm_cleanup_buf_error(dev,entry);
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_cleanup_buf_error(dev, entry);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+- for ( i = 0 ; i < entry->buf_count ; i++ ) {
++ for (i = 0; i < entry->buf_count; i++) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+- DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+- DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
++ DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
++ DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+- up( &dev->struct_sem );
++ up(&dev->struct_sem);
+
+ request->count = entry->buf_count;
+ request->size = size;
+
+ dma->flags = _DRM_DMA_USE_AGP;
+
+- atomic_dec( &dev->buf_alloc );
++ atomic_dec(&dev->buf_alloc);
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_addbufs_agp);
+-#endif /* __OS_HAS_AGP */
++#endif /* __OS_HAS_AGP */
+
+-int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
++int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ int count;
+@@ -684,178 +687,174 @@ int drm_addbufs_pci(drm_device_t *dev, d
+ unsigned long *temp_pagelist;
+ drm_buf_t **temp_buflist;
+
+- if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
+- if ( !dma ) return -EINVAL;
++ if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
++ return -EINVAL;
++ if (!dma)
++ return -EINVAL;
+
+ count = request->count;
+ order = drm_order(request->size);
+ size = 1 << order;
+
+- DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
+- request->count, request->size, size,
+- order, dev->queue_count );
++ DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n",
++ request->count, request->size, size, order, dev->queue_count);
+
+- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+- if ( dev->queue_count ) return -EBUSY; /* Not while in use */
++ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
++ return -EINVAL;
++ if (dev->queue_count)
++ return -EBUSY; /* Not while in use */
+
+ alignment = (request->flags & _DRM_PAGE_ALIGN)
+- ? PAGE_ALIGN(size) : size;
++ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+- spin_lock( &dev->count_lock );
+- if ( dev->buf_use ) {
+- spin_unlock( &dev->count_lock );
++ spin_lock(&dev->count_lock);
++ if (dev->buf_use) {
++ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+- atomic_inc( &dev->buf_alloc );
+- spin_unlock( &dev->count_lock );
++ atomic_inc(&dev->buf_alloc);
++ spin_unlock(&dev->count_lock);
+
+- down( &dev->struct_sem );
++ down(&dev->struct_sem);
+ entry = &dma->bufs[order];
+- if ( entry->buf_count ) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ if (entry->buf_count) {
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
+
+- entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
+- DRM_MEM_BUFS );
+- if ( !entry->buflist ) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
++ DRM_MEM_BUFS);
++ if (!entry->buflist) {
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+- memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
++ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+- entry->seglist = drm_alloc( count * sizeof(*entry->seglist),
+- DRM_MEM_SEGS );
+- if ( !entry->seglist ) {
+- drm_free( entry->buflist,
+- count * sizeof(*entry->buflist),
+- DRM_MEM_BUFS );
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
++ DRM_MEM_SEGS);
++ if (!entry->seglist) {
++ drm_free(entry->buflist,
++ count * sizeof(*entry->buflist), DRM_MEM_BUFS);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+- memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
++ memset(entry->seglist, 0, count * sizeof(*entry->seglist));
+
+ /* Keep the original pagelist until we know all the allocations
+ * have succeeded
+ */
+- temp_pagelist = drm_alloc( (dma->page_count + (count << page_order))
+- * sizeof(*dma->pagelist),
+- DRM_MEM_PAGES );
++ temp_pagelist = drm_alloc((dma->page_count + (count << page_order))
++ * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+ if (!temp_pagelist) {
+- drm_free( entry->buflist,
+- count * sizeof(*entry->buflist),
+- DRM_MEM_BUFS );
+- drm_free( entry->seglist,
+- count * sizeof(*entry->seglist),
+- DRM_MEM_SEGS );
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_free(entry->buflist,
++ count * sizeof(*entry->buflist), DRM_MEM_BUFS);
++ drm_free(entry->seglist,
++ count * sizeof(*entry->seglist), DRM_MEM_SEGS);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ memcpy(temp_pagelist,
+- dma->pagelist,
+- dma->page_count * sizeof(*dma->pagelist));
+- DRM_DEBUG( "pagelist: %d entries\n",
+- dma->page_count + (count << page_order) );
++ dma->pagelist, dma->page_count * sizeof(*dma->pagelist));
++ DRM_DEBUG("pagelist: %d entries\n",
++ dma->page_count + (count << page_order));
+
+- entry->buf_size = size;
++ entry->buf_size = size;
+ entry->page_order = page_order;
+ byte_count = 0;
+ page_count = 0;
+
+- while ( entry->buf_count < count ) {
+- page = drm_alloc_pages( page_order, DRM_MEM_DMA );
+- if ( !page ) {
++ while (entry->buf_count < count) {
++ page = drm_alloc_pages(page_order, DRM_MEM_DMA);
++ if (!page) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ entry->seg_count = count;
+ drm_cleanup_buf_error(dev, entry);
+- drm_free( temp_pagelist,
+- (dma->page_count + (count << page_order))
+- * sizeof(*dma->pagelist),
+- DRM_MEM_PAGES );
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_free(temp_pagelist,
++ (dma->page_count + (count << page_order))
++ * sizeof(*dma->pagelist), DRM_MEM_PAGES);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ entry->seglist[entry->seg_count++] = page;
+- for ( i = 0 ; i < (1 << page_order) ; i++ ) {
+- DRM_DEBUG( "page %d @ 0x%08lx\n",
+- dma->page_count + page_count,
+- page + PAGE_SIZE * i );
++ for (i = 0; i < (1 << page_order); i++) {
++ DRM_DEBUG("page %d @ 0x%08lx\n",
++ dma->page_count + page_count,
++ page + PAGE_SIZE * i);
+ temp_pagelist[dma->page_count + page_count++]
+- = page + PAGE_SIZE * i;
++ = page + PAGE_SIZE * i;
+ }
+- for ( offset = 0 ;
+- offset + size <= total && entry->buf_count < count ;
+- offset += alignment, ++entry->buf_count ) {
+- buf = &entry->buflist[entry->buf_count];
+- buf->idx = dma->buf_count + entry->buf_count;
+- buf->total = alignment;
+- buf->order = order;
+- buf->used = 0;
+- buf->offset = (dma->byte_count + byte_count + offset);
++ for (offset = 0;
++ offset + size <= total && entry->buf_count < count;
++ offset += alignment, ++entry->buf_count) {
++ buf = &entry->buflist[entry->buf_count];
++ buf->idx = dma->buf_count + entry->buf_count;
++ buf->total = alignment;
++ buf->order = order;
++ buf->used = 0;
++ buf->offset = (dma->byte_count + byte_count + offset);
+ buf->address = (void *)(page + offset);
+- buf->next = NULL;
++ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+- init_waitqueue_head( &buf->dma_wait );
+- buf->filp = NULL;
++ init_waitqueue_head(&buf->dma_wait);
++ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->driver->dev_priv_size;
+- buf->dev_private = drm_alloc( buf->dev_priv_size,
+- DRM_MEM_BUFS );
+- if(!buf->dev_private) {
++ buf->dev_private = drm_alloc(buf->dev_priv_size,
++ DRM_MEM_BUFS);
++ if (!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ entry->seg_count = count;
+- drm_cleanup_buf_error(dev,entry);
+- drm_free( temp_pagelist,
+- (dma->page_count + (count << page_order))
+- * sizeof(*dma->pagelist),
+- DRM_MEM_PAGES );
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_cleanup_buf_error(dev, entry);
++ drm_free(temp_pagelist,
++ (dma->page_count +
++ (count << page_order))
++ * sizeof(*dma->pagelist),
++ DRM_MEM_PAGES);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+- memset( buf->dev_private, 0, buf->dev_priv_size );
++ memset(buf->dev_private, 0, buf->dev_priv_size);
+
+- DRM_DEBUG( "buffer %d @ %p\n",
+- entry->buf_count, buf->address );
++ DRM_DEBUG("buffer %d @ %p\n",
++ entry->buf_count, buf->address);
+ }
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+- temp_buflist = drm_realloc( dma->buflist,
+- dma->buf_count * sizeof(*dma->buflist),
+- (dma->buf_count + entry->buf_count)
+- * sizeof(*dma->buflist),
+- DRM_MEM_BUFS );
++ temp_buflist = drm_realloc(dma->buflist,
++ dma->buf_count * sizeof(*dma->buflist),
++ (dma->buf_count + entry->buf_count)
++ * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ if (!temp_buflist) {
+ /* Free the entry because it isn't valid */
+- drm_cleanup_buf_error(dev,entry);
+- drm_free( temp_pagelist,
+- (dma->page_count + (count << page_order))
+- * sizeof(*dma->pagelist),
+- DRM_MEM_PAGES );
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_cleanup_buf_error(dev, entry);
++ drm_free(temp_pagelist,
++ (dma->page_count + (count << page_order))
++ * sizeof(*dma->pagelist), DRM_MEM_PAGES);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+- for ( i = 0 ; i < entry->buf_count ; i++ ) {
++ for (i = 0; i < entry->buf_count; i++) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+@@ -864,8 +863,8 @@ int drm_addbufs_pci(drm_device_t *dev, d
+ */
+ if (dma->page_count) {
+ drm_free(dma->pagelist,
+- dma->page_count * sizeof(*dma->pagelist),
+- DRM_MEM_PAGES);
++ dma->page_count * sizeof(*dma->pagelist),
++ DRM_MEM_PAGES);
+ }
+ dma->pagelist = temp_pagelist;
+
+@@ -874,18 +873,19 @@ int drm_addbufs_pci(drm_device_t *dev, d
+ dma->page_count += entry->seg_count << page_order;
+ dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
+
+- up( &dev->struct_sem );
++ up(&dev->struct_sem);
+
+ request->count = entry->buf_count;
+ request->size = size;
+
+- atomic_dec( &dev->buf_alloc );
++ atomic_dec(&dev->buf_alloc);
+ return 0;
+
+ }
++
+ EXPORT_SYMBOL(drm_addbufs_pci);
+
+-static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
++static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_entry_t *entry;
+@@ -902,146 +902,147 @@ static int drm_addbufs_sg(drm_device_t *
+ int i;
+ drm_buf_t **temp_buflist;
+
+- if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL;
+-
+- if ( !dma ) return -EINVAL;
++ if (!drm_core_check_feature(dev, DRIVER_SG))
++ return -EINVAL;
++
++ if (!dma)
++ return -EINVAL;
+
+ count = request->count;
+ order = drm_order(request->size);
+ size = 1 << order;
+
+- alignment = (request->flags & _DRM_PAGE_ALIGN)
+- ? PAGE_ALIGN(size) : size;
++ alignment = (request->flags & _DRM_PAGE_ALIGN)
++ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = request->agp_start;
+
+- DRM_DEBUG( "count: %d\n", count );
+- DRM_DEBUG( "order: %d\n", order );
+- DRM_DEBUG( "size: %d\n", size );
+- DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
+- DRM_DEBUG( "alignment: %d\n", alignment );
+- DRM_DEBUG( "page_order: %d\n", page_order );
+- DRM_DEBUG( "total: %d\n", total );
+-
+- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+- if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+-
+- spin_lock( &dev->count_lock );
+- if ( dev->buf_use ) {
+- spin_unlock( &dev->count_lock );
++ DRM_DEBUG("count: %d\n", count);
++ DRM_DEBUG("order: %d\n", order);
++ DRM_DEBUG("size: %d\n", size);
++ DRM_DEBUG("agp_offset: %lu\n", agp_offset);
++ DRM_DEBUG("alignment: %d\n", alignment);
++ DRM_DEBUG("page_order: %d\n", page_order);
++ DRM_DEBUG("total: %d\n", total);
++
++ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
++ return -EINVAL;
++ if (dev->queue_count)
++ return -EBUSY; /* Not while in use */
++
++ spin_lock(&dev->count_lock);
++ if (dev->buf_use) {
++ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+- atomic_inc( &dev->buf_alloc );
+- spin_unlock( &dev->count_lock );
++ atomic_inc(&dev->buf_alloc);
++ spin_unlock(&dev->count_lock);
+
+- down( &dev->struct_sem );
++ down(&dev->struct_sem);
+ entry = &dma->bufs[order];
+- if ( entry->buf_count ) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
+- return -ENOMEM; /* May only call once for each order */
++ if (entry->buf_count) {
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
++ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -EINVAL;
+ }
+
+- entry->buflist = drm_alloc( count * sizeof(*entry->buflist),
+- DRM_MEM_BUFS );
+- if ( !entry->buflist ) {
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
++ DRM_MEM_BUFS);
++ if (!entry->buflist) {
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+- memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
++ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+- while ( entry->buf_count < count ) {
+- buf = &entry->buflist[entry->buf_count];
+- buf->idx = dma->buf_count + entry->buf_count;
+- buf->total = alignment;
+- buf->order = order;
+- buf->used = 0;
++ while (entry->buf_count < count) {
++ buf = &entry->buflist[entry->buf_count];
++ buf->idx = dma->buf_count + entry->buf_count;
++ buf->total = alignment;
++ buf->order = order;
++ buf->used = 0;
+
+- buf->offset = (dma->byte_count + offset);
++ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+- buf->address = (void *)(agp_offset + offset
++ buf->address = (void *)(agp_offset + offset
+ + (unsigned long)dev->sg->virtual);
+- buf->next = NULL;
++ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+- init_waitqueue_head( &buf->dma_wait );
+- buf->filp = NULL;
++ init_waitqueue_head(&buf->dma_wait);
++ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->driver->dev_priv_size;
+- buf->dev_private = drm_alloc( buf->dev_priv_size,
+- DRM_MEM_BUFS );
+- if(!buf->dev_private) {
++ buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
++ if (!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+- drm_cleanup_buf_error(dev,entry);
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_cleanup_buf_error(dev, entry);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+
+- memset( buf->dev_private, 0, buf->dev_priv_size );
++ memset(buf->dev_private, 0, buf->dev_priv_size);
+
+- DRM_DEBUG( "buffer %d @ %p\n",
+- entry->buf_count, buf->address );
++ DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+- DRM_DEBUG( "byte_count: %d\n", byte_count );
++ DRM_DEBUG("byte_count: %d\n", byte_count);
+
+- temp_buflist = drm_realloc( dma->buflist,
+- dma->buf_count * sizeof(*dma->buflist),
+- (dma->buf_count + entry->buf_count)
+- * sizeof(*dma->buflist),
+- DRM_MEM_BUFS );
+- if(!temp_buflist) {
++ temp_buflist = drm_realloc(dma->buflist,
++ dma->buf_count * sizeof(*dma->buflist),
++ (dma->buf_count + entry->buf_count)
++ * sizeof(*dma->buflist), DRM_MEM_BUFS);
++ if (!temp_buflist) {
+ /* Free the entry because it isn't valid */
+- drm_cleanup_buf_error(dev,entry);
+- up( &dev->struct_sem );
+- atomic_dec( &dev->buf_alloc );
++ drm_cleanup_buf_error(dev, entry);
++ up(&dev->struct_sem);
++ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+- for ( i = 0 ; i < entry->buf_count ; i++ ) {
++ for (i = 0; i < entry->buf_count; i++) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+- DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+- DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
++ DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
++ DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+- up( &dev->struct_sem );
++ up(&dev->struct_sem);
+
+ request->count = entry->buf_count;
+ request->size = size;
+
+ dma->flags = _DRM_DMA_USE_SG;
+
+- atomic_dec( &dev->buf_alloc );
++ atomic_dec(&dev->buf_alloc);
+ return 0;
+ }
+
+-static int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request)
++static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_entry_t *entry;
+@@ -1060,7 +1061,7 @@ static int drm_addbufs_fb(drm_device_t *
+
+ if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
+ return -EINVAL;
+-
++
+ if (!dma)
+ return -EINVAL;
+
+@@ -1210,43 +1211,41 @@ static int drm_addbufs_fb(drm_device_t *
+ * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
+ * PCI memory respectively.
+ */
+-int drm_addbufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_addbufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_buf_desc_t request;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ int ret;
+-
++
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+- if ( copy_from_user( &request, (drm_buf_desc_t __user *)arg,
+- sizeof(request) ) )
++ if (copy_from_user(&request, (drm_buf_desc_t __user *) arg,
++ sizeof(request)))
+ return -EFAULT;
+
+ #if __OS_HAS_AGP
+- if ( request.flags & _DRM_AGP_BUFFER )
+- ret=drm_addbufs_agp(dev, &request);
++ if (request.flags & _DRM_AGP_BUFFER)
++ ret = drm_addbufs_agp(dev, &request);
+ else
+ #endif
+- if ( request.flags & _DRM_SG_BUFFER )
+- ret=drm_addbufs_sg(dev, &request);
+- else if ( request.flags & _DRM_FB_BUFFER)
+- ret=drm_addbufs_fb(dev, &request);
++ if (request.flags & _DRM_SG_BUFFER)
++ ret = drm_addbufs_sg(dev, &request);
++ else if (request.flags & _DRM_FB_BUFFER)
++ ret = drm_addbufs_fb(dev, &request);
+ else
+- ret=drm_addbufs_pci(dev, &request);
++ ret = drm_addbufs_pci(dev, &request);
+
+- if (ret==0) {
+- if (copy_to_user((void __user *)arg, &request,
+- sizeof(request))) {
++ if (ret == 0) {
++ if (copy_to_user((void __user *)arg, &request, sizeof(request))) {
+ ret = -EFAULT;
+ }
+ }
+ return ret;
+ }
+
+-
+ /**
+ * Get information about the buffer mappings.
+ *
+@@ -1264,8 +1263,8 @@ int drm_addbufs( struct inode *inode, st
+ * lock, preventing of allocating more buffers after this call. Information
+ * about each requested buffer is then copied into user space.
+ */
+-int drm_infobufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_infobufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -1278,58 +1277,61 @@ int drm_infobufs( struct inode *inode, s
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+- if ( !dma ) return -EINVAL;
++ if (!dma)
++ return -EINVAL;
+
+- spin_lock( &dev->count_lock );
+- if ( atomic_read( &dev->buf_alloc ) ) {
+- spin_unlock( &dev->count_lock );
++ spin_lock(&dev->count_lock);
++ if (atomic_read(&dev->buf_alloc)) {
++ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ ++dev->buf_use; /* Can't allocate more after this call */
+- spin_unlock( &dev->count_lock );
++ spin_unlock(&dev->count_lock);
+
+- if ( copy_from_user( &request, argp, sizeof(request) ) )
++ if (copy_from_user(&request, argp, sizeof(request)))
+ return -EFAULT;
+
+- for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+- if ( dma->bufs[i].buf_count ) ++count;
++ for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
++ if (dma->bufs[i].buf_count)
++ ++count;
+ }
+
+- DRM_DEBUG( "count = %d\n", count );
+-
+- if ( request.count >= count ) {
+- for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+- if ( dma->bufs[i].buf_count ) {
+- drm_buf_desc_t __user *to = &request.list[count];
++ DRM_DEBUG("count = %d\n", count);
++
++ if (request.count >= count) {
++ for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
++ if (dma->bufs[i].buf_count) {
++ drm_buf_desc_t __user *to =
++ &request.list[count];
+ drm_buf_entry_t *from = &dma->bufs[i];
+ drm_freelist_t *list = &dma->bufs[i].freelist;
+- if ( copy_to_user( &to->count,
+- &from->buf_count,
+- sizeof(from->buf_count) ) ||
+- copy_to_user( &to->size,
+- &from->buf_size,
+- sizeof(from->buf_size) ) ||
+- copy_to_user( &to->low_mark,
+- &list->low_mark,
+- sizeof(list->low_mark) ) ||
+- copy_to_user( &to->high_mark,
+- &list->high_mark,
+- sizeof(list->high_mark) ) )
++ if (copy_to_user(&to->count,
++ &from->buf_count,
++ sizeof(from->buf_count)) ||
++ copy_to_user(&to->size,
++ &from->buf_size,
++ sizeof(from->buf_size)) ||
++ copy_to_user(&to->low_mark,
++ &list->low_mark,
++ sizeof(list->low_mark)) ||
++ copy_to_user(&to->high_mark,
++ &list->high_mark,
++ sizeof(list->high_mark)))
+ return -EFAULT;
+
+- DRM_DEBUG( "%d %d %d %d %d\n",
+- i,
+- dma->bufs[i].buf_count,
+- dma->bufs[i].buf_size,
+- dma->bufs[i].freelist.low_mark,
+- dma->bufs[i].freelist.high_mark );
++ DRM_DEBUG("%d %d %d %d %d\n",
++ i,
++ dma->bufs[i].buf_count,
++ dma->bufs[i].buf_size,
++ dma->bufs[i].freelist.low_mark,
++ dma->bufs[i].freelist.high_mark);
+ ++count;
+ }
+ }
+ }
+ request.count = count;
+
+- if ( copy_to_user( argp, &request, sizeof(request) ) )
++ if (copy_to_user(argp, &request, sizeof(request)))
+ return -EFAULT;
+
+ return 0;
+@@ -1349,8 +1351,8 @@ int drm_infobufs( struct inode *inode, s
+ *
+ * \note This ioctl is deprecated and mostly never used.
+ */
+-int drm_markbufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_markbufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -1362,44 +1364,45 @@ int drm_markbufs( struct inode *inode, s
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+- if ( !dma ) return -EINVAL;
++ if (!dma)
++ return -EINVAL;
+
+- if ( copy_from_user( &request,
+- (drm_buf_desc_t __user *)arg,
+- sizeof(request) ) )
++ if (copy_from_user(&request,
++ (drm_buf_desc_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+- DRM_DEBUG( "%d, %d, %d\n",
+- request.size, request.low_mark, request.high_mark );
+- order = drm_order( request.size );
+- if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
++ DRM_DEBUG("%d, %d, %d\n",
++ request.size, request.low_mark, request.high_mark);
++ order = drm_order(request.size);
++ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
++ return -EINVAL;
+ entry = &dma->bufs[order];
+
+- if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
++ if (request.low_mark < 0 || request.low_mark > entry->buf_count)
+ return -EINVAL;
+- if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
++ if (request.high_mark < 0 || request.high_mark > entry->buf_count)
+ return -EINVAL;
+
+- entry->freelist.low_mark = request.low_mark;
++ entry->freelist.low_mark = request.low_mark;
+ entry->freelist.high_mark = request.high_mark;
+
+ return 0;
+ }
+
+ /**
+- * Unreserve the buffers in list, previously reserved using drmDMA.
++ * Unreserve the buffers in list, previously reserved using drmDMA.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_free structure.
+ * \return zero on success or a negative number on failure.
+- *
++ *
+ * Calls free_buffer() for each used buffer.
+ * This function is primarily used for debugging.
+ */
+-int drm_freebufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_freebufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -1412,31 +1415,29 @@ int drm_freebufs( struct inode *inode, s
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+- if ( !dma ) return -EINVAL;
++ if (!dma)
++ return -EINVAL;
+
+- if ( copy_from_user( &request,
+- (drm_buf_free_t __user *)arg,
+- sizeof(request) ) )
++ if (copy_from_user(&request,
++ (drm_buf_free_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+- DRM_DEBUG( "%d\n", request.count );
+- for ( i = 0 ; i < request.count ; i++ ) {
+- if ( copy_from_user( &idx,
+- &request.list[i],
+- sizeof(idx) ) )
++ DRM_DEBUG("%d\n", request.count);
++ for (i = 0; i < request.count; i++) {
++ if (copy_from_user(&idx, &request.list[i], sizeof(idx)))
+ return -EFAULT;
+- if ( idx < 0 || idx >= dma->buf_count ) {
+- DRM_ERROR( "Index %d (of %d max)\n",
+- idx, dma->buf_count - 1 );
++ if (idx < 0 || idx >= dma->buf_count) {
++ DRM_ERROR("Index %d (of %d max)\n",
++ idx, dma->buf_count - 1);
+ return -EINVAL;
+ }
+ buf = dma->buflist[idx];
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "Process %d freeing buffer not owned\n",
+- current->pid );
++ if (buf->filp != filp) {
++ DRM_ERROR("Process %d freeing buffer not owned\n",
++ current->pid);
+ return -EINVAL;
+ }
+- drm_free_buffer( dev, buf );
++ drm_free_buffer(dev, buf);
+ }
+
+ return 0;
+@@ -1455,8 +1456,8 @@ int drm_freebufs( struct inode *inode, s
+ * about each buffer into user space. The PCI buffers are already mapped on the
+ * addbufs_pci() call.
+ */
+-int drm_mapbufs( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_mapbufs(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -1472,86 +1473,84 @@ int drm_mapbufs( struct inode *inode, st
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+- if ( !dma ) return -EINVAL;
++ if (!dma)
++ return -EINVAL;
+
+- spin_lock( &dev->count_lock );
+- if ( atomic_read( &dev->buf_alloc ) ) {
+- spin_unlock( &dev->count_lock );
++ spin_lock(&dev->count_lock);
++ if (atomic_read(&dev->buf_alloc)) {
++ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ dev->buf_use++; /* Can't allocate more after this call */
+- spin_unlock( &dev->count_lock );
++ spin_unlock(&dev->count_lock);
+
+- if ( copy_from_user( &request, argp, sizeof(request) ) )
++ if (copy_from_user(&request, argp, sizeof(request)))
+ return -EFAULT;
+
+- if ( request.count >= dma->buf_count ) {
++ if (request.count >= dma->buf_count) {
+ if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
+- || (drm_core_check_feature(dev, DRIVER_SG)
++ || (drm_core_check_feature(dev, DRIVER_SG)
+ && (dma->flags & _DRM_DMA_USE_SG))
+ || (drm_core_check_feature(dev, DRIVER_FB_DMA)
+ && (dma->flags & _DRM_DMA_USE_FB))) {
+ drm_map_t *map = dev->agp_buffer_map;
+ unsigned long token = dev->agp_buffer_token;
+
+- if ( !map ) {
++ if (!map) {
+ retcode = -EINVAL;
+ goto done;
+ }
+
+- down_write( ¤t->mm->mmap_sem );
+- virtual = do_mmap( filp, 0, map->size,
+- PROT_READ | PROT_WRITE,
+- MAP_SHARED,
+- token );
+- up_write( ¤t->mm->mmap_sem );
++ down_write(¤t->mm->mmap_sem);
++ virtual = do_mmap(filp, 0, map->size,
++ PROT_READ | PROT_WRITE,
++ MAP_SHARED, token);
++ up_write(¤t->mm->mmap_sem);
+ } else {
+- down_write( ¤t->mm->mmap_sem );
+- virtual = do_mmap( filp, 0, dma->byte_count,
+- PROT_READ | PROT_WRITE,
+- MAP_SHARED, 0 );
+- up_write( ¤t->mm->mmap_sem );
++ down_write(¤t->mm->mmap_sem);
++ virtual = do_mmap(filp, 0, dma->byte_count,
++ PROT_READ | PROT_WRITE,
++ MAP_SHARED, 0);
++ up_write(¤t->mm->mmap_sem);
+ }
+- if ( virtual > -1024UL ) {
++ if (virtual > -1024UL) {
+ /* Real error */
+ retcode = (signed long)virtual;
+ goto done;
+ }
+ request.virtual = (void __user *)virtual;
+
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
+- if ( copy_to_user( &request.list[i].idx,
+- &dma->buflist[i]->idx,
+- sizeof(request.list[0].idx) ) ) {
++ for (i = 0; i < dma->buf_count; i++) {
++ if (copy_to_user(&request.list[i].idx,
++ &dma->buflist[i]->idx,
++ sizeof(request.list[0].idx))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+- if ( copy_to_user( &request.list[i].total,
+- &dma->buflist[i]->total,
+- sizeof(request.list[0].total) ) ) {
++ if (copy_to_user(&request.list[i].total,
++ &dma->buflist[i]->total,
++ sizeof(request.list[0].total))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+- if ( copy_to_user( &request.list[i].used,
+- &zero,
+- sizeof(zero) ) ) {
++ if (copy_to_user(&request.list[i].used,
++ &zero, sizeof(zero))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+- address = virtual + dma->buflist[i]->offset; /* *** */
+- if ( copy_to_user( &request.list[i].address,
+- &address,
+- sizeof(address) ) ) {
++ address = virtual + dma->buflist[i]->offset; /* *** */
++ if (copy_to_user(&request.list[i].address,
++ &address, sizeof(address))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ }
+ }
+- done:
++ done:
+ request.count = dma->buf_count;
+- DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
++ DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
+
+- if ( copy_to_user( argp, &request, sizeof(request) ) )
++ if (copy_to_user(argp, &request, sizeof(request)))
+ return -EFAULT;
+
+ return retcode;
+@@ -1560,23 +1559,23 @@ int drm_mapbufs( struct inode *inode, st
+ /**
+ * Compute size order. Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+- *
++ *
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
+ */
+-int drm_order( unsigned long size )
++int drm_order(unsigned long size)
+ {
+ int order;
+ unsigned long tmp;
+
+- for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
+- ;
++ for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
+
+ if (size & (size - 1))
+ ++order;
+
+ return order;
+ }
++
+ EXPORT_SYMBOL(drm_order);
+diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
+--- a/drivers/char/drm/drm_context.c
++++ b/drivers/char/drm/drm_context.c
+@@ -1,7 +1,7 @@
+ /**
+- * \file drm_context.h
++ * \file drm_context.c
+ * IOCTLs for generic contexts
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+@@ -56,25 +56,26 @@
+ * in drm_device::context_sareas, while holding the drm_device::struct_sem
+ * lock.
+ */
+-void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle )
++void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
+ {
+- if ( ctx_handle < 0 ) goto failed;
+- if ( !dev->ctx_bitmap ) goto failed;
++ if (ctx_handle < 0)
++ goto failed;
++ if (!dev->ctx_bitmap)
++ goto failed;
+
+- if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
++ if (ctx_handle < DRM_MAX_CTXBITMAP) {
+ down(&dev->struct_sem);
+- clear_bit( ctx_handle, dev->ctx_bitmap );
++ clear_bit(ctx_handle, dev->ctx_bitmap);
+ dev->context_sareas[ctx_handle] = NULL;
+ up(&dev->struct_sem);
+ return;
+ }
+-failed:
+- DRM_ERROR( "Attempt to free invalid context handle: %d\n",
+- ctx_handle );
+- return;
++ failed:
++ DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
++ return;
+ }
+
+-/**
++/**
+ * Context bitmap allocation.
+ *
+ * \param dev DRM device.
+@@ -84,29 +85,33 @@ failed:
+ * drm_device::context_sareas to accommodate the new entry while holding the
+ * drm_device::struct_sem lock.
+ */
+-static int drm_ctxbitmap_next( drm_device_t *dev )
++static int drm_ctxbitmap_next(drm_device_t * dev)
+ {
+ int bit;
+
+- if(!dev->ctx_bitmap) return -1;
++ if (!dev->ctx_bitmap)
++ return -1;
+
+ down(&dev->struct_sem);
+- bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
+- if ( bit < DRM_MAX_CTXBITMAP ) {
+- set_bit( bit, dev->ctx_bitmap );
+- DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
+- if((bit+1) > dev->max_context) {
+- dev->max_context = (bit+1);
+- if(dev->context_sareas) {
++ bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
++ if (bit < DRM_MAX_CTXBITMAP) {
++ set_bit(bit, dev->ctx_bitmap);
++ DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
++ if ((bit + 1) > dev->max_context) {
++ dev->max_context = (bit + 1);
++ if (dev->context_sareas) {
+ drm_map_t **ctx_sareas;
+
+ ctx_sareas = drm_realloc(dev->context_sareas,
+- (dev->max_context - 1) *
+- sizeof(*dev->context_sareas),
+- dev->max_context *
+- sizeof(*dev->context_sareas),
+- DRM_MEM_MAPS);
+- if(!ctx_sareas) {
++ (dev->max_context -
++ 1) *
++ sizeof(*dev->
++ context_sareas),
++ dev->max_context *
++ sizeof(*dev->
++ context_sareas),
++ DRM_MEM_MAPS);
++ if (!ctx_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ up(&dev->struct_sem);
+ return -1;
+@@ -115,11 +120,11 @@ static int drm_ctxbitmap_next( drm_devic
+ dev->context_sareas[bit] = NULL;
+ } else {
+ /* max_context == 1 at this point */
+- dev->context_sareas = drm_alloc(
+- dev->max_context *
+- sizeof(*dev->context_sareas),
+- DRM_MEM_MAPS);
+- if(!dev->context_sareas) {
++ dev->context_sareas =
++ drm_alloc(dev->max_context *
++ sizeof(*dev->context_sareas),
++ DRM_MEM_MAPS);
++ if (!dev->context_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ up(&dev->struct_sem);
+ return -1;
+@@ -142,26 +147,26 @@ static int drm_ctxbitmap_next( drm_devic
+ * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
+ * the drm_device::struct_sem lock.
+ */
+-int drm_ctxbitmap_init( drm_device_t *dev )
++int drm_ctxbitmap_init(drm_device_t * dev)
+ {
+ int i;
+- int temp;
++ int temp;
+
+ down(&dev->struct_sem);
+- dev->ctx_bitmap = (unsigned long *) drm_alloc( PAGE_SIZE,
+- DRM_MEM_CTXBITMAP );
+- if ( dev->ctx_bitmap == NULL ) {
++ dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
++ DRM_MEM_CTXBITMAP);
++ if (dev->ctx_bitmap == NULL) {
+ up(&dev->struct_sem);
+ return -ENOMEM;
+ }
+- memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
++ memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
+ dev->context_sareas = NULL;
+ dev->max_context = -1;
+ up(&dev->struct_sem);
+
+- for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+- temp = drm_ctxbitmap_next( dev );
+- DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
++ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
++ temp = drm_ctxbitmap_next(dev);
++ DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
+ }
+
+ return 0;
+@@ -175,14 +180,14 @@ int drm_ctxbitmap_init( drm_device_t *de
+ * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
+ * the drm_device::struct_sem lock.
+ */
+-void drm_ctxbitmap_cleanup( drm_device_t *dev )
++void drm_ctxbitmap_cleanup(drm_device_t * dev)
+ {
+ down(&dev->struct_sem);
+- if( dev->context_sareas ) drm_free( dev->context_sareas,
+- sizeof(*dev->context_sareas) *
+- dev->max_context,
+- DRM_MEM_MAPS );
+- drm_free( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
++ if (dev->context_sareas)
++ drm_free(dev->context_sareas,
++ sizeof(*dev->context_sareas) *
++ dev->max_context, DRM_MEM_MAPS);
++ drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
+ up(&dev->struct_sem);
+ }
+
+@@ -194,7 +199,7 @@ void drm_ctxbitmap_cleanup( drm_device_t
+
+ /**
+ * Get per-context SAREA.
+- *
++ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+@@ -205,10 +210,10 @@ void drm_ctxbitmap_cleanup( drm_device_t
+ * returns its handle.
+ */
+ int drm_getsareactx(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_ctx_priv_map_t __user *argp = (void __user *)arg;
+ drm_ctx_priv_map_t request;
+ drm_map_t *map;
+@@ -218,7 +223,8 @@ int drm_getsareactx(struct inode *inode,
+ return -EFAULT;
+
+ down(&dev->struct_sem);
+- if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
++ if (dev->max_context < 0
++ || request.ctx_id >= (unsigned)dev->max_context) {
+ up(&dev->struct_sem);
+ return -EINVAL;
+ }
+@@ -226,17 +232,17 @@ int drm_getsareactx(struct inode *inode,
+ map = dev->context_sareas[request.ctx_id];
+ up(&dev->struct_sem);
+
+- request.handle = 0;
+- list_for_each_entry(_entry, &dev->maplist->head,head) {
++ request.handle = NULL;
++ list_for_each_entry(_entry, &dev->maplist->head, head) {
+ if (_entry->map == map) {
+- request.handle = (void *)(unsigned long)_entry->user_token;
++ request.handle =
++ (void *)(unsigned long)_entry->user_token;
+ break;
+ }
+ }
+- if (request.handle == 0)
++ if (request.handle == NULL)
+ return -EINVAL;
+
+-
+ if (copy_to_user(argp, &request, sizeof(request)))
+ return -EFAULT;
+ return 0;
+@@ -244,7 +250,7 @@ int drm_getsareactx(struct inode *inode,
+
+ /**
+ * Set per-context SAREA.
+- *
++ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+@@ -255,37 +261,37 @@ int drm_getsareactx(struct inode *inode,
+ * drm_device::context_sareas with it.
+ */
+ int drm_setsareactx(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_ctx_priv_map_t request;
+ drm_map_t *map = NULL;
+ drm_map_list_t *r_list = NULL;
+ struct list_head *list;
+
+ if (copy_from_user(&request,
+- (drm_ctx_priv_map_t __user *)arg,
+- sizeof(request)))
++ (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+ down(&dev->struct_sem);
+ list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+ if (r_list->map
+- && r_list->user_token == (unsigned long) request.handle)
++ && r_list->user_token == (unsigned long)request.handle)
+ goto found;
+ }
+-bad:
++ bad:
+ up(&dev->struct_sem);
+ return -EINVAL;
+
+-found:
++ found:
+ map = r_list->map;
+- if (!map) goto bad;
++ if (!map)
++ goto bad;
+ if (dev->max_context < 0)
+ goto bad;
+- if (request.ctx_id >= (unsigned) dev->max_context)
++ if (request.ctx_id >= (unsigned)dev->max_context)
+ goto bad;
+ dev->context_sareas[request.ctx_id] = map;
+ up(&dev->struct_sem);
+@@ -308,22 +314,21 @@ found:
+ *
+ * Attempt to set drm_device::context_flag.
+ */
+-static int drm_context_switch( drm_device_t *dev, int old, int new )
++static int drm_context_switch(drm_device_t * dev, int old, int new)
+ {
+- if ( test_and_set_bit( 0, &dev->context_flag ) ) {
+- DRM_ERROR( "Reentering -- FIXME\n" );
+- return -EBUSY;
+- }
+-
++ if (test_and_set_bit(0, &dev->context_flag)) {
++ DRM_ERROR("Reentering -- FIXME\n");
++ return -EBUSY;
++ }
+
+- DRM_DEBUG( "Context switch from %d to %d\n", old, new );
++ DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+- if ( new == dev->last_context ) {
+- clear_bit( 0, &dev->context_flag );
+- return 0;
+- }
++ if (new == dev->last_context) {
++ clear_bit(0, &dev->context_flag);
++ return 0;
++ }
+
+- return 0;
++ return 0;
+ }
+
+ /**
+@@ -337,22 +342,22 @@ static int drm_context_switch( drm_devic
+ * hardware lock is held, clears the drm_device::context_flag and wakes up
+ * drm_device::context_wait.
+ */
+-static int drm_context_switch_complete( drm_device_t *dev, int new )
++static int drm_context_switch_complete(drm_device_t * dev, int new)
+ {
+- dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+- dev->last_switch = jiffies;
++ dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
++ dev->last_switch = jiffies;
+
+- if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
+- DRM_ERROR( "Lock isn't held after context switch\n" );
+- }
+-
+- /* If a context switch is ever initiated
+- when the kernel holds the lock, release
+- that lock here. */
+- clear_bit( 0, &dev->context_flag );
+- wake_up( &dev->context_wait );
++ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
++ DRM_ERROR("Lock isn't held after context switch\n");
++ }
++
++ /* If a context switch is ever initiated
++ when the kernel holds the lock, release
++ that lock here. */
++ clear_bit(0, &dev->context_flag);
++ wake_up(&dev->context_wait);
+
+- return 0;
++ return 0;
+ }
+
+ /**
+@@ -364,29 +369,28 @@ static int drm_context_switch_complete(
+ * \param arg user argument pointing to a drm_ctx_res structure.
+ * \return zero on success or a negative number on failure.
+ */
+-int drm_resctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_resctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_ctx_res_t res;
+ drm_ctx_t __user *argp = (void __user *)arg;
+ drm_ctx_t ctx;
+ int i;
+
+- if ( copy_from_user( &res, argp, sizeof(res) ) )
++ if (copy_from_user(&res, argp, sizeof(res)))
+ return -EFAULT;
+
+- if ( res.count >= DRM_RESERVED_CONTEXTS ) {
+- memset( &ctx, 0, sizeof(ctx) );
+- for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
++ if (res.count >= DRM_RESERVED_CONTEXTS) {
++ memset(&ctx, 0, sizeof(ctx));
++ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+ ctx.handle = i;
+- if ( copy_to_user( &res.contexts[i],
+- &ctx, sizeof(ctx) ) )
++ if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx)))
+ return -EFAULT;
+ }
+ }
+ res.count = DRM_RESERVED_CONTEXTS;
+
+- if ( copy_to_user( argp, &res, sizeof(res) ) )
++ if (copy_to_user(argp, &res, sizeof(res)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -402,58 +406,57 @@ int drm_resctx( struct inode *inode, str
+ *
+ * Get a new handle for the context and copy to userspace.
+ */
+-int drm_addctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_addctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+- drm_ctx_list_t * ctx_entry;
++ drm_ctx_list_t *ctx_entry;
+ drm_ctx_t __user *argp = (void __user *)arg;
+ drm_ctx_t ctx;
+
+- if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
++ if (copy_from_user(&ctx, argp, sizeof(ctx)))
+ return -EFAULT;
+
+- ctx.handle = drm_ctxbitmap_next( dev );
+- if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
+- /* Skip kernel's context and get a new one. */
+- ctx.handle = drm_ctxbitmap_next( dev );
+- }
+- DRM_DEBUG( "%d\n", ctx.handle );
+- if ( ctx.handle == -1 ) {
+- DRM_DEBUG( "Not enough free contexts.\n" );
+- /* Should this return -EBUSY instead? */
++ ctx.handle = drm_ctxbitmap_next(dev);
++ if (ctx.handle == DRM_KERNEL_CONTEXT) {
++ /* Skip kernel's context and get a new one. */
++ ctx.handle = drm_ctxbitmap_next(dev);
++ }
++ DRM_DEBUG("%d\n", ctx.handle);
++ if (ctx.handle == -1) {
++ DRM_DEBUG("Not enough free contexts.\n");
++ /* Should this return -EBUSY instead? */
+ return -ENOMEM;
+ }
+
+- if ( ctx.handle != DRM_KERNEL_CONTEXT )
+- {
++ if (ctx.handle != DRM_KERNEL_CONTEXT) {
+ if (dev->driver->context_ctor)
+ dev->driver->context_ctor(dev, ctx.handle);
+ }
+
+- ctx_entry = drm_alloc( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
+- if ( !ctx_entry ) {
++ ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);
++ if (!ctx_entry) {
+ DRM_DEBUG("out of memory\n");
+ return -ENOMEM;
+ }
+
+- INIT_LIST_HEAD( &ctx_entry->head );
++ INIT_LIST_HEAD(&ctx_entry->head);
+ ctx_entry->handle = ctx.handle;
+ ctx_entry->tag = priv;
+
+- down( &dev->ctxlist_sem );
+- list_add( &ctx_entry->head, &dev->ctxlist->head );
++ down(&dev->ctxlist_sem);
++ list_add(&ctx_entry->head, &dev->ctxlist->head);
+ ++dev->ctx_count;
+- up( &dev->ctxlist_sem );
++ up(&dev->ctxlist_sem);
+
+- if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
++ if (copy_to_user(argp, &ctx, sizeof(ctx)))
+ return -EFAULT;
+ return 0;
+ }
+
+-int drm_modctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_modctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ /* This does nothing */
+ return 0;
+@@ -468,19 +471,19 @@ int drm_modctx( struct inode *inode, str
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ */
+-int drm_getctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_getctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_ctx_t __user *argp = (void __user *)arg;
+ drm_ctx_t ctx;
+
+- if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
++ if (copy_from_user(&ctx, argp, sizeof(ctx)))
+ return -EFAULT;
+
+ /* This is 0, because we don't handle any context flags */
+ ctx.flags = 0;
+
+- if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
++ if (copy_to_user(argp, &ctx, sizeof(ctx)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -496,18 +499,18 @@ int drm_getctx( struct inode *inode, str
+ *
+ * Calls context_switch().
+ */
+-int drm_switchctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_switchctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_ctx_t ctx;
+
+- if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+
+- DRM_DEBUG( "%d\n", ctx.handle );
+- return drm_context_switch( dev, dev->last_context, ctx.handle );
++ DRM_DEBUG("%d\n", ctx.handle);
++ return drm_context_switch(dev, dev->last_context, ctx.handle);
+ }
+
+ /**
+@@ -521,18 +524,18 @@ int drm_switchctx( struct inode *inode,
+ *
+ * Calls context_switch_complete().
+ */
+-int drm_newctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_newctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_ctx_t ctx;
+
+- if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+
+- DRM_DEBUG( "%d\n", ctx.handle );
+- drm_context_switch_complete( dev, ctx.handle );
++ DRM_DEBUG("%d\n", ctx.handle);
++ drm_context_switch_complete(dev, ctx.handle);
+
+ return 0;
+ }
+@@ -548,42 +551,41 @@ int drm_newctx( struct inode *inode, str
+ *
+ * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
+ */
+-int drm_rmctx( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_rmctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_ctx_t ctx;
+
+- if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+
+- DRM_DEBUG( "%d\n", ctx.handle );
+- if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
++ DRM_DEBUG("%d\n", ctx.handle);
++ if (ctx.handle == DRM_KERNEL_CONTEXT + 1) {
+ priv->remove_auth_on_close = 1;
+ }
+- if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
++ if (ctx.handle != DRM_KERNEL_CONTEXT) {
+ if (dev->driver->context_dtor)
+ dev->driver->context_dtor(dev, ctx.handle);
+- drm_ctxbitmap_free( dev, ctx.handle );
++ drm_ctxbitmap_free(dev, ctx.handle);
+ }
+
+- down( &dev->ctxlist_sem );
+- if ( !list_empty( &dev->ctxlist->head ) ) {
++ down(&dev->ctxlist_sem);
++ if (!list_empty(&dev->ctxlist->head)) {
+ drm_ctx_list_t *pos, *n;
+
+- list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+- if ( pos->handle == ctx.handle ) {
+- list_del( &pos->head );
+- drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
++ list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
++ if (pos->handle == ctx.handle) {
++ list_del(&pos->head);
++ drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+ --dev->ctx_count;
+ }
+ }
+ }
+- up( &dev->ctxlist_sem );
++ up(&dev->ctxlist_sem);
+
+ return 0;
+ }
+
+ /*@}*/
+-
+diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
+--- a/drivers/char/drm/drm_dma.c
++++ b/drivers/char/drm/drm_dma.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_dma.h
++ * \file drm_dma.c
+ * DMA IOCTL and function support
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -37,23 +37,23 @@
+
+ /**
+ * Initialize the DMA data.
+- *
++ *
+ * \param dev DRM device.
+ * \return zero on success or a negative value on failure.
+ *
+ * Allocate and initialize a drm_device_dma structure.
+ */
+-int drm_dma_setup( drm_device_t *dev )
++int drm_dma_setup(drm_device_t * dev)
+ {
+ int i;
+
+- dev->dma = drm_alloc( sizeof(*dev->dma), DRM_MEM_DRIVER );
+- if ( !dev->dma )
++ dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER);
++ if (!dev->dma)
+ return -ENOMEM;
+
+- memset( dev->dma, 0, sizeof(*dev->dma) );
++ memset(dev->dma, 0, sizeof(*dev->dma));
+
+- for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
++ for (i = 0; i <= DRM_MAX_ORDER; i++)
+ memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
+
+ return 0;
+@@ -67,14 +67,15 @@ int drm_dma_setup( drm_device_t *dev )
+ * Free all pages associated with DMA buffers, the buffers and pages lists, and
+ * finally the the drm_device::dma structure itself.
+ */
+-void drm_dma_takedown(drm_device_t *dev)
++void drm_dma_takedown(drm_device_t * dev)
+ {
+- drm_device_dma_t *dma = dev->dma;
+- int i, j;
++ drm_device_dma_t *dma = dev->dma;
++ int i, j;
+
+- if (!dma) return;
++ if (!dma)
++ return;
+
+- /* Clear dma buffers */
++ /* Clear dma buffers */
+ for (i = 0; i <= DRM_MAX_ORDER; i++) {
+ if (dma->bufs[i].seg_count) {
+ DRM_DEBUG("order %d: buf_count = %d,"
+@@ -85,64 +86,63 @@ void drm_dma_takedown(drm_device_t *dev)
+ for (j = 0; j < dma->bufs[i].seg_count; j++) {
+ if (dma->bufs[i].seglist[j]) {
+ drm_free_pages(dma->bufs[i].seglist[j],
+- dma->bufs[i].page_order,
+- DRM_MEM_DMA);
++ dma->bufs[i].page_order,
++ DRM_MEM_DMA);
+ }
+ }
+ drm_free(dma->bufs[i].seglist,
+- dma->bufs[i].seg_count
+- * sizeof(*dma->bufs[0].seglist),
+- DRM_MEM_SEGS);
++ dma->bufs[i].seg_count
++ * sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS);
+ }
+- if (dma->bufs[i].buf_count) {
+- for (j = 0; j < dma->bufs[i].buf_count; j++) {
++ if (dma->bufs[i].buf_count) {
++ for (j = 0; j < dma->bufs[i].buf_count; j++) {
+ if (dma->bufs[i].buflist[j].dev_private) {
+- drm_free(dma->bufs[i].buflist[j].dev_private,
+- dma->bufs[i].buflist[j].dev_priv_size,
+- DRM_MEM_BUFS);
++ drm_free(dma->bufs[i].buflist[j].
++ dev_private,
++ dma->bufs[i].buflist[j].
++ dev_priv_size, DRM_MEM_BUFS);
+ }
+ }
+- drm_free(dma->bufs[i].buflist,
+- dma->bufs[i].buf_count *
+- sizeof(*dma->bufs[0].buflist),
+- DRM_MEM_BUFS);
++ drm_free(dma->bufs[i].buflist,
++ dma->bufs[i].buf_count *
++ sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS);
+ }
+ }
+
+ if (dma->buflist) {
+ drm_free(dma->buflist,
+- dma->buf_count * sizeof(*dma->buflist),
+- DRM_MEM_BUFS);
++ dma->buf_count * sizeof(*dma->buflist), DRM_MEM_BUFS);
+ }
+
+ if (dma->pagelist) {
+ drm_free(dma->pagelist,
+- dma->page_count * sizeof(*dma->pagelist),
+- DRM_MEM_PAGES);
++ dma->page_count * sizeof(*dma->pagelist),
++ DRM_MEM_PAGES);
+ }
+ drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
+ dev->dma = NULL;
+ }
+
+-
+ /**
+ * Free a buffer.
+ *
+ * \param dev DRM device.
+ * \param buf buffer to free.
+- *
++ *
+ * Resets the fields of \p buf.
+ */
+-void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
++void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
+ {
+- if (!buf) return;
++ if (!buf)
++ return;
+
+- buf->waiting = 0;
+- buf->pending = 0;
+- buf->filp = NULL;
+- buf->used = 0;
++ buf->waiting = 0;
++ buf->pending = 0;
++ buf->filp = NULL;
++ buf->used = 0;
+
+- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) {
++ if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
++ && waitqueue_active(&buf->dma_wait)) {
+ wake_up_interruptible(&buf->dma_wait);
+ }
+ }
+@@ -154,12 +154,13 @@ void drm_free_buffer(drm_device_t *dev,
+ *
+ * Frees each buffer associated with \p filp not already on the hardware.
+ */
+-void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
++void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp)
+ {
+ drm_device_dma_t *dma = dev->dma;
+- int i;
++ int i;
+
+- if (!dma) return;
++ if (!dma)
++ return;
+ for (i = 0; i < dma->buf_count; i++) {
+ if (dma->buflist[i]->filp == filp) {
+ switch (dma->buflist[i]->list) {
+@@ -176,5 +177,5 @@ void drm_core_reclaim_buffers(drm_device
+ }
+ }
+ }
+-EXPORT_SYMBOL(drm_core_reclaim_buffers);
+
++EXPORT_SYMBOL(drm_core_reclaim_buffers);
+diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
+--- a/drivers/char/drm/drm_drawable.c
++++ b/drivers/char/drm/drm_drawable.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_drawable.h
++ * \file drm_drawable.c
+ * IOCTLs for drawables
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -37,20 +37,20 @@
+
+ /** No-op. */
+ int drm_adddraw(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_draw_t draw;
+
+ draw.handle = 0; /* NOOP */
+ DRM_DEBUG("%d\n", draw.handle);
+- if (copy_to_user((drm_draw_t __user *)arg, &draw, sizeof(draw)))
++ if (copy_to_user((drm_draw_t __user *) arg, &draw, sizeof(draw)))
+ return -EFAULT;
+ return 0;
+ }
+
+ /** No-op. */
+ int drm_rmdraw(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ return 0; /* NOOP */
+ }
+diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
+--- a/drivers/char/drm/drm_drv.c
++++ b/drivers/char/drm/drm_drv.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_drv.h
++ * \file drm_drv.c
+ * Generic driver template
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -55,67 +55,67 @@ static int drm_version(struct inode *ino
+ unsigned int cmd, unsigned long arg);
+
+ /** Ioctl table */
+-static drm_ioctl_desc_t drm_ioctls[] = {
+- [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, 0, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, 0, 1 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap_ioctl,1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap_ioctl, 1, 0 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, 1, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, 1, 0 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, 1, 0 },
+-
+- [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
++static drm_ioctl_desc_t drm_ioctls[] = {
++ [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, 0, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, 0, 1},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, 1, 1},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, 1, 0},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, 1, 0},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, 1, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, 1, 0},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, 1, 1},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, 1, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, 1, 0},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, 1, 0},
++
++ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, 1, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, 1, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, 1, 0},
+ /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
+
+- [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 },
++ [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, 1, 1},
+
+ #if __OS_HAS_AGP
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire_ioctl, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release_ioctl, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable_ioctl, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info_ioctl, 1, 0 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, 1, 0},
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind, 1, 1},
+ #endif
+
+- [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 },
+- [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 },
++ [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, 1, 1},
++ [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, 1, 1},
+
+- [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0, 0 },
++ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0, 0},
+ };
+
+ #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls )
+@@ -129,17 +129,17 @@ static drm_ioctl_desc_t drm_ioctls[]
+ *
+ * \sa drm_device
+ */
+-int drm_takedown( drm_device_t *dev )
++int drm_takedown(drm_device_t * dev)
+ {
+ drm_magic_entry_t *pt, *next;
+ drm_map_list_t *r_list;
+ drm_vma_entry_t *vma, *vma_next;
+ int i;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ if (dev->driver->pretakedown)
+- dev->driver->pretakedown(dev);
++ dev->driver->pretakedown(dev);
+ DRM_DEBUG("driver pretakedown completed\n");
+
+ if (dev->unique) {
+@@ -148,95 +148,95 @@ int drm_takedown( drm_device_t *dev )
+ dev->unique_len = 0;
+ }
+
+- if ( dev->irq_enabled ) drm_irq_uninstall( dev );
++ if (dev->irq_enabled)
++ drm_irq_uninstall(dev);
+
+- down( &dev->struct_sem );
+- del_timer( &dev->timer );
++ down(&dev->struct_sem);
++ del_timer(&dev->timer);
+
+- /* Clear pid list */
+- for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
+- for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
++ /* Clear pid list */
++ for (i = 0; i < DRM_HASH_SIZE; i++) {
++ for (pt = dev->magiclist[i].head; pt; pt = next) {
+ next = pt->next;
+- drm_free( pt, sizeof(*pt), DRM_MEM_MAGIC );
++ drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ }
+ dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+ }
+
+- /* Clear AGP information */
++ /* Clear AGP information */
+ if (drm_core_has_AGP(dev) && dev->agp) {
+ drm_agp_mem_t *entry;
+ drm_agp_mem_t *nexte;
+
+- /* Remove AGP resources, but leave dev->agp
+- intact until drv_cleanup is called. */
+- for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
++ /* Remove AGP resources, but leave dev->agp
++ intact until drv_cleanup is called. */
++ for (entry = dev->agp->memory; entry; entry = nexte) {
+ nexte = entry->next;
+- if ( entry->bound ) drm_unbind_agp( entry->memory );
+- drm_free_agp( entry->memory, entry->pages );
+- drm_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
++ if (entry->bound)
++ drm_unbind_agp(entry->memory);
++ drm_free_agp(entry->memory, entry->pages);
++ drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ }
+ dev->agp->memory = NULL;
+
+ if (dev->agp->acquired)
+- drm_agp_release(dev);
++ drm_agp_release(dev);
+
+ dev->agp->acquired = 0;
+- dev->agp->enabled = 0;
++ dev->agp->enabled = 0;
+ }
+ if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
+ drm_sg_cleanup(dev->sg);
+ dev->sg = NULL;
+ }
+
+- /* Clear vma list (only built for debugging) */
+- if ( dev->vmalist ) {
+- for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
++ /* Clear vma list (only built for debugging) */
++ if (dev->vmalist) {
++ for (vma = dev->vmalist; vma; vma = vma_next) {
+ vma_next = vma->next;
+- drm_free( vma, sizeof(*vma), DRM_MEM_VMAS );
++ drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
+ }
+ dev->vmalist = NULL;
+ }
+
+- if( dev->maplist ) {
++ if (dev->maplist) {
+ while (!list_empty(&dev->maplist->head)) {
+ struct list_head *list = dev->maplist->head.next;
+ r_list = list_entry(list, drm_map_list_t, head);
+ drm_rmmap_locked(dev, r_list->map);
+ }
+- }
++ }
+
+- if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
+- for ( i = 0 ; i < dev->queue_count ; i++ ) {
+- if ( dev->queuelist[i] ) {
+- drm_free( dev->queuelist[i],
+- sizeof(*dev->queuelist[0]),
+- DRM_MEM_QUEUES );
++ if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
++ for (i = 0; i < dev->queue_count; i++) {
++ if (dev->queuelist[i]) {
++ drm_free(dev->queuelist[i],
++ sizeof(*dev->queuelist[0]),
++ DRM_MEM_QUEUES);
+ dev->queuelist[i] = NULL;
+ }
+ }
+- drm_free( dev->queuelist,
+- dev->queue_slots * sizeof(*dev->queuelist),
+- DRM_MEM_QUEUES );
++ drm_free(dev->queuelist,
++ dev->queue_slots * sizeof(*dev->queuelist),
++ DRM_MEM_QUEUES);
+ dev->queuelist = NULL;
+ }
+ dev->queue_count = 0;
+
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+- drm_dma_takedown( dev );
++ drm_dma_takedown(dev);
+
+- if ( dev->lock.hw_lock ) {
+- dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
++ if (dev->lock.hw_lock) {
++ dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
+ dev->lock.filp = NULL;
+- wake_up_interruptible( &dev->lock.lock_queue );
++ wake_up_interruptible(&dev->lock.lock_queue);
+ }
+- up( &dev->struct_sem );
++ up(&dev->struct_sem);
+
+ DRM_DEBUG("takedown completed\n");
+ return 0;
+ }
+
+-
+-
+ /**
+ * Module initialization. Called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported).
+@@ -246,26 +246,28 @@ int drm_takedown( drm_device_t *dev )
+ * Initializes an array of drm_device structures, and attempts to
+ * initialize all available devices, using consecutive minors, registering the
+ * stubs and initializing the AGP device.
+- *
++ *
+ * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
+ * after the initialization for driver customization.
+ */
+-int drm_init( struct drm_driver *driver )
++int drm_init(struct drm_driver *driver)
+ {
+ struct pci_dev *pdev = NULL;
+ struct pci_device_id *pid;
+ int i;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ drm_mem_init();
+
+- for (i=0; driver->pci_driver.id_table[i].vendor != 0; i++) {
++ for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
+ pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
+-
+- pdev=NULL;
+- /* pass back in pdev to account for multiple identical cards */
+- while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) {
++
++ pdev = NULL;
++ /* pass back in pdev to account for multiple identical cards */
++ while ((pdev =
++ pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
++ pid->subdevice, pdev)) != NULL) {
+ /* stealth mode requires a manual probe */
+ pci_dev_get(pdev);
+ drm_get_dev(pdev, pid, driver);
+@@ -273,62 +275,63 @@ int drm_init( struct drm_driver *driver
+ }
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_init);
+
+ /**
+ * Called via cleanup_module() at module unload time.
+ *
+ * Cleans up all DRM device, calling takedown().
+- *
++ *
+ * \sa drm_init
+ */
+-static void drm_cleanup( drm_device_t *dev )
++static void drm_cleanup(drm_device_t * dev)
+ {
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ if (!dev) {
+ DRM_ERROR("cleanup called no dev\n");
+ return;
+ }
+
+- drm_takedown( dev );
++ drm_takedown(dev);
+
+ if (dev->maplist) {
+ drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ dev->maplist = NULL;
+ }
+
+- drm_ctxbitmap_cleanup( dev );
+-
++ drm_ctxbitmap_cleanup(dev);
++
+ if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+ dev->agp && dev->agp->agp_mtrr >= 0) {
+ int retval;
+- retval = mtrr_del( dev->agp->agp_mtrr,
+- dev->agp->agp_info.aper_base,
+- dev->agp->agp_info.aper_size*1024*1024 );
+- DRM_DEBUG( "mtrr_del=%d\n", retval );
+- }
+-
+- if (drm_core_has_AGP(dev) && dev->agp ) {
+- drm_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
++ retval = mtrr_del(dev->agp->agp_mtrr,
++ dev->agp->agp_info.aper_base,
++ dev->agp->agp_info.aper_size * 1024 * 1024);
++ DRM_DEBUG("mtrr_del=%d\n", retval);
++ }
++
++ if (drm_core_has_AGP(dev) && dev->agp) {
++ drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
+ dev->agp = NULL;
+ }
+
+ if (dev->driver->postcleanup)
+ dev->driver->postcleanup(dev);
+-
++
+ drm_put_head(&dev->primary);
+- if ( drm_put_dev(dev) )
+- DRM_ERROR( "Cannot unload module\n" );
++ if (drm_put_dev(dev))
++ DRM_ERROR("Cannot unload module\n");
+ }
+
+-void drm_exit (struct drm_driver *driver)
++void drm_exit(struct drm_driver *driver)
+ {
+ int i;
+ drm_device_t *dev = NULL;
+ drm_head_t *head;
+-
+- DRM_DEBUG( "\n" );
++
++ DRM_DEBUG("\n");
+
+ for (i = 0; i < drm_cards_limit; i++) {
+ head = drm_heads[i];
+@@ -336,9 +339,9 @@ void drm_exit (struct drm_driver *driver
+ continue;
+ if (!head->dev)
+ continue;
+- if (head->dev->driver!=driver)
++ if (head->dev->driver != driver)
+ continue;
+- dev=head->dev;
++ dev = head->dev;
+ }
+ if (dev) {
+ /* release the pci driver */
+@@ -346,32 +349,35 @@ void drm_exit (struct drm_driver *driver
+ pci_dev_put(dev->pdev);
+ drm_cleanup(dev);
+ }
+- DRM_INFO( "Module unloaded\n" );
++ DRM_INFO("Module unloaded\n");
+ }
++
+ EXPORT_SYMBOL(drm_exit);
+
+ /** File operations structure */
+ static struct file_operations drm_stub_fops = {
+ .owner = THIS_MODULE,
+- .open = drm_stub_open
++ .open = drm_stub_open
+ };
+
+ static int __init drm_core_init(void)
+ {
+ int ret = -ENOMEM;
+-
+- drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
+- drm_heads = drm_calloc(drm_cards_limit,
+- sizeof(*drm_heads), DRM_MEM_STUB);
+- if(!drm_heads)
++
++ drm_cards_limit =
++ (drm_cards_limit <
++ DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
++ drm_heads =
++ drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
++ if (!drm_heads)
+ goto err_p1;
+-
++
+ if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+ goto err_p1;
+-
++
+ drm_class = drm_sysfs_create(THIS_MODULE, "drm");
+ if (IS_ERR(drm_class)) {
+- printk (KERN_ERR "DRM: Error creating drm class.\n");
++ printk(KERN_ERR "DRM: Error creating drm class.\n");
+ ret = PTR_ERR(drm_class);
+ goto err_p2;
+ }
+@@ -382,35 +388,31 @@ static int __init drm_core_init(void)
+ ret = -1;
+ goto err_p3;
+ }
+-
+- DRM_INFO( "Initialized %s %d.%d.%d %s\n",
+- CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL,
+- CORE_DATE);
++
++ DRM_INFO("Initialized %s %d.%d.%d %s\n",
++ CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+ return 0;
+-err_p3:
++ err_p3:
+ drm_sysfs_destroy(drm_class);
+-err_p2:
++ err_p2:
+ unregister_chrdev(DRM_MAJOR, "drm");
+ drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
+-err_p1:
++ err_p1:
+ return ret;
+ }
+
+-static void __exit drm_core_exit (void)
++static void __exit drm_core_exit(void)
+ {
+ remove_proc_entry("dri", NULL);
+ drm_sysfs_destroy(drm_class);
+
+ unregister_chrdev(DRM_MAJOR, "drm");
+
+- drm_free(drm_heads, sizeof(*drm_heads) *
+- drm_cards_limit, DRM_MEM_STUB);
++ drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
+ }
+
+-
+-module_init( drm_core_init );
+-module_exit( drm_core_exit );
+-
++module_init(drm_core_init);
++module_exit(drm_core_exit);
+
+ /**
+ * Get version information
+@@ -423,8 +425,8 @@ module_exit( drm_core_exit );
+ *
+ * Fills in the version information in \p arg.
+ */
+-static int drm_version( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++static int drm_version(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -432,21 +434,19 @@ static int drm_version( struct inode *in
+ drm_version_t version;
+ int ret;
+
+- if ( copy_from_user( &version, argp, sizeof(version) ) )
++ if (copy_from_user(&version, argp, sizeof(version)))
+ return -EFAULT;
+
+ /* version is a required function to return the personality module version */
+ if ((ret = dev->driver->version(&version)))
+ return ret;
+-
+- if ( copy_to_user( argp, &version, sizeof(version) ) )
++
++ if (copy_to_user(argp, &version, sizeof(version)))
+ return -EFAULT;
+ return 0;
+ }
+
+-
+-
+-/**
++/**
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+@@ -458,8 +458,8 @@ static int drm_version( struct inode *in
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
+ */
+-int drm_ioctl( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -468,40 +468,43 @@ int drm_ioctl( struct inode *inode, stru
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ int retcode = -EINVAL;
+
+- atomic_inc( &dev->ioctl_count );
+- atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
++ atomic_inc(&dev->ioctl_count);
++ atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
+ ++priv->ioctl_count;
+
+- DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+- current->pid, cmd, nr, (long)old_encode_dev(priv->head->device),
+- priv->authenticated );
+-
++ DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
++ current->pid, cmd, nr,
++ (long)old_encode_dev(priv->head->device),
++ priv->authenticated);
++
+ if (nr < DRIVER_IOCTL_COUNT)
+ ioctl = &drm_ioctls[nr];
+- else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
++ else if ((nr >= DRM_COMMAND_BASE)
++ && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
+ ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+ else
+ goto err_i1;
+-
++
+ func = ioctl->func;
+ /* is there a local override? */
+ if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
+ func = dev->driver->dma_ioctl;
+-
+- if ( !func ) {
+- DRM_DEBUG( "no function\n" );
++
++ if (!func) {
++ DRM_DEBUG("no function\n");
+ retcode = -EINVAL;
+- } else if ( ( ioctl->root_only && !capable( CAP_SYS_ADMIN ) )||
+- ( ioctl->auth_needed && !priv->authenticated ) ) {
++ } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) ||
++ (ioctl->auth_needed && !priv->authenticated)) {
+ retcode = -EACCES;
+ } else {
+- retcode = func( inode, filp, cmd, arg );
++ retcode = func(inode, filp, cmd, arg);
+ }
+-
+-err_i1:
+- atomic_dec( &dev->ioctl_count );
+- if (retcode) DRM_DEBUG( "ret = %x\n", retcode);
++
++ err_i1:
++ atomic_dec(&dev->ioctl_count);
++ if (retcode)
++ DRM_DEBUG("ret = %x\n", retcode);
+ return retcode;
+ }
+-EXPORT_SYMBOL(drm_ioctl);
+
++EXPORT_SYMBOL(drm_ioctl);
+diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
+--- a/drivers/char/drm/drm_fops.c
++++ b/drivers/char/drm/drm_fops.c
+@@ -1,7 +1,7 @@
+ /**
+- * \file drm_fops.h
++ * \file drm_fops.c
+ * File operations for DRM
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Daryll Strauss <daryll at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+@@ -37,49 +37,48 @@
+ #include "drmP.h"
+ #include <linux/poll.h>
+
+-static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev);
++static int drm_open_helper(struct inode *inode, struct file *filp,
++ drm_device_t * dev);
+
+-static int drm_setup( drm_device_t *dev )
++static int drm_setup(drm_device_t * dev)
+ {
+ int i;
+ int ret;
+
+- if (dev->driver->presetup)
+- {
+- ret=dev->driver->presetup(dev);
+- if (ret!=0)
++ if (dev->driver->presetup) {
++ ret = dev->driver->presetup(dev);
++ if (ret != 0)
+ return ret;
+ }
+
+- atomic_set( &dev->ioctl_count, 0 );
+- atomic_set( &dev->vma_count, 0 );
++ atomic_set(&dev->ioctl_count, 0);
++ atomic_set(&dev->vma_count, 0);
+ dev->buf_use = 0;
+- atomic_set( &dev->buf_alloc, 0 );
++ atomic_set(&dev->buf_alloc, 0);
+
+- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+- {
+- i = drm_dma_setup( dev );
+- if ( i < 0 )
++ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
++ i = drm_dma_setup(dev);
++ if (i < 0)
+ return i;
+ }
+
+- for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
+- atomic_set( &dev->counts[i], 0 );
++ for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
++ atomic_set(&dev->counts[i], 0);
+
+- for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
++ for (i = 0; i < DRM_HASH_SIZE; i++) {
+ dev->magiclist[i].head = NULL;
+ dev->magiclist[i].tail = NULL;
+ }
+
+- dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
+- DRM_MEM_CTXLIST);
+- if(dev->ctxlist == NULL) return -ENOMEM;
++ dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
++ if (dev->ctxlist == NULL)
++ return -ENOMEM;
+ memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
+ INIT_LIST_HEAD(&dev->ctxlist->head);
+
+ dev->vmalist = NULL;
+ dev->sigdata.lock = dev->lock.hw_lock = NULL;
+- init_waitqueue_head( &dev->lock.lock_queue );
++ init_waitqueue_head(&dev->lock.lock_queue);
+ dev->queue_count = 0;
+ dev->queue_reserved = 0;
+ dev->queue_slots = 0;
+@@ -91,24 +90,21 @@ static int drm_setup( drm_device_t *dev
+ dev->last_context = 0;
+ dev->last_switch = 0;
+ dev->last_checked = 0;
+- init_waitqueue_head( &dev->context_wait );
++ init_waitqueue_head(&dev->context_wait);
+ dev->if_version = 0;
+
+ dev->ctx_start = 0;
+ dev->lck_start = 0;
+
+- dev->buf_rp = dev->buf;
+- dev->buf_wp = dev->buf;
+- dev->buf_end = dev->buf + DRM_BSZ;
+ dev->buf_async = NULL;
+- init_waitqueue_head( &dev->buf_readers );
+- init_waitqueue_head( &dev->buf_writers );
++ init_waitqueue_head(&dev->buf_readers);
++ init_waitqueue_head(&dev->buf_writers);
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ /*
+ * The kernel's context could be created here, but is now created
+- * in drm_dma_enqueue. This is more resource-efficient for
++ * in drm_dma_enqueue. This is more resource-efficient for
+ * hardware that does not do DMA, but may mean that
+ * drm_select_queue fails between the time the interrupt is
+ * initialized and the time the queues are initialized.
+@@ -121,7 +117,7 @@ static int drm_setup( drm_device_t *dev
+
+ /**
+ * Open file.
+- *
++ *
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+@@ -130,7 +126,7 @@ static int drm_setup( drm_device_t *dev
+ * increments the device open count. If the open count was previous at zero,
+ * i.e., it's the first that the device is open, then calls setup().
+ */
+-int drm_open( struct inode *inode, struct file *filp )
++int drm_open(struct inode *inode, struct file *filp)
+ {
+ drm_device_t *dev = NULL;
+ int minor = iminor(inode);
+@@ -138,26 +134,27 @@ int drm_open( struct inode *inode, struc
+
+ if (!((minor >= 0) && (minor < drm_cards_limit)))
+ return -ENODEV;
+-
++
+ if (!drm_heads[minor])
+ return -ENODEV;
+
+ if (!(dev = drm_heads[minor]->dev))
+ return -ENODEV;
+-
+- retcode = drm_open_helper( inode, filp, dev );
+- if ( !retcode ) {
+- atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
+- spin_lock( &dev->count_lock );
+- if ( !dev->open_count++ ) {
+- spin_unlock( &dev->count_lock );
+- return drm_setup( dev );
++
++ retcode = drm_open_helper(inode, filp, dev);
++ if (!retcode) {
++ atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
++ spin_lock(&dev->count_lock);
++ if (!dev->open_count++) {
++ spin_unlock(&dev->count_lock);
++ return drm_setup(dev);
+ }
+- spin_unlock( &dev->count_lock );
++ spin_unlock(&dev->count_lock);
+ }
+
+ return retcode;
+ }
++
+ EXPORT_SYMBOL(drm_open);
+
+ /**
+@@ -172,7 +169,7 @@ EXPORT_SYMBOL(drm_open);
+ * data from its list and free it. Decreases the open count and if it reaches
+ * zero calls takedown().
+ */
+-int drm_release( struct inode *inode, struct file *filp )
++int drm_release(struct inode *inode, struct file *filp)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
+@@ -181,7 +178,7 @@ int drm_release( struct inode *inode, st
+ lock_kernel();
+ dev = priv->head->dev;
+
+- DRM_DEBUG( "open_count = %d\n", dev->open_count );
++ DRM_DEBUG("open_count = %d\n", dev->open_count);
+
+ if (dev->driver->prerelease)
+ dev->driver->prerelease(dev, filp);
+@@ -190,194 +187,199 @@ int drm_release( struct inode *inode, st
+ * Begin inline drm_release
+ */
+
+- DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
+- current->pid, (long)old_encode_dev(priv->head->device), dev->open_count );
++ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
++ current->pid, (long)old_encode_dev(priv->head->device),
++ dev->open_count);
++
++ if (priv->lock_count && dev->lock.hw_lock &&
++ _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
++ dev->lock.filp == filp) {
++ DRM_DEBUG("File %p released, freeing lock for context %d\n",
++ filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+
+- if ( priv->lock_count && dev->lock.hw_lock &&
+- _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
+- dev->lock.filp == filp ) {
+- DRM_DEBUG( "File %p released, freeing lock for context %d\n",
+- filp,
+- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
+-
+ if (dev->driver->release)
+ dev->driver->release(dev, filp);
+
+- drm_lock_free( dev, &dev->lock.hw_lock->lock,
+- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
++ drm_lock_free(dev, &dev->lock.hw_lock->lock,
++ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+
+- /* FIXME: may require heavy-handed reset of
+- hardware at this point, possibly
+- processed via a callback to the X
+- server. */
+- }
+- else if ( dev->driver->release && priv->lock_count && dev->lock.hw_lock ) {
++ /* FIXME: may require heavy-handed reset of
++ hardware at this point, possibly
++ processed via a callback to the X
++ server. */
++ } else if (dev->driver->release && priv->lock_count
++ && dev->lock.hw_lock) {
+ /* The lock is required to reclaim buffers */
+- DECLARE_WAITQUEUE( entry, current );
++ DECLARE_WAITQUEUE(entry, current);
+
+- add_wait_queue( &dev->lock.lock_queue, &entry );
++ add_wait_queue(&dev->lock.lock_queue, &entry);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+- if ( !dev->lock.hw_lock ) {
++ if (!dev->lock.hw_lock) {
+ /* Device has been unregistered */
+ retcode = -EINTR;
+ break;
+ }
+- if ( drm_lock_take( &dev->lock.hw_lock->lock,
+- DRM_KERNEL_CONTEXT ) ) {
+- dev->lock.filp = filp;
++ if (drm_lock_take(&dev->lock.hw_lock->lock,
++ DRM_KERNEL_CONTEXT)) {
++ dev->lock.filp = filp;
+ dev->lock.lock_time = jiffies;
+- atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
++ atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+ break; /* Got lock */
+ }
+- /* Contention */
++ /* Contention */
+ schedule();
+- if ( signal_pending( current ) ) {
++ if (signal_pending(current)) {
+ retcode = -ERESTARTSYS;
+ break;
+ }
+ }
+ __set_current_state(TASK_RUNNING);
+- remove_wait_queue( &dev->lock.lock_queue, &entry );
+- if( !retcode ) {
++ remove_wait_queue(&dev->lock.lock_queue, &entry);
++ if (!retcode) {
+ if (dev->driver->release)
+ dev->driver->release(dev, filp);
+- drm_lock_free( dev, &dev->lock.hw_lock->lock,
+- DRM_KERNEL_CONTEXT );
++ drm_lock_free(dev, &dev->lock.hw_lock->lock,
++ DRM_KERNEL_CONTEXT);
+ }
+ }
+-
+- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !dev->driver->release)
+- {
++
++ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)
++ && !dev->driver->release) {
+ dev->driver->reclaim_buffers(dev, filp);
+ }
+
+- drm_fasync( -1, filp, 0 );
++ drm_fasync(-1, filp, 0);
+
+- down( &dev->ctxlist_sem );
+- if ( dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
++ down(&dev->ctxlist_sem);
++ if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
+ drm_ctx_list_t *pos, *n;
+
+- list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+- if ( pos->tag == priv &&
+- pos->handle != DRM_KERNEL_CONTEXT ) {
++ list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
++ if (pos->tag == priv &&
++ pos->handle != DRM_KERNEL_CONTEXT) {
+ if (dev->driver->context_dtor)
+- dev->driver->context_dtor(dev, pos->handle);
++ dev->driver->context_dtor(dev,
++ pos->handle);
+
+- drm_ctxbitmap_free( dev, pos->handle );
++ drm_ctxbitmap_free(dev, pos->handle);
+
+- list_del( &pos->head );
+- drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
++ list_del(&pos->head);
++ drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+ --dev->ctx_count;
+ }
+ }
+ }
+- up( &dev->ctxlist_sem );
++ up(&dev->ctxlist_sem);
+
+- down( &dev->struct_sem );
+- if ( priv->remove_auth_on_close == 1 ) {
++ down(&dev->struct_sem);
++ if (priv->remove_auth_on_close == 1) {
+ drm_file_t *temp = dev->file_first;
+- while ( temp ) {
++ while (temp) {
+ temp->authenticated = 0;
+ temp = temp->next;
+ }
+ }
+- if ( priv->prev ) {
++ if (priv->prev) {
+ priv->prev->next = priv->next;
+ } else {
+- dev->file_first = priv->next;
++ dev->file_first = priv->next;
+ }
+- if ( priv->next ) {
++ if (priv->next) {
+ priv->next->prev = priv->prev;
+ } else {
+- dev->file_last = priv->prev;
++ dev->file_last = priv->prev;
+ }
+- up( &dev->struct_sem );
+-
++ up(&dev->struct_sem);
++
+ if (dev->driver->free_filp_priv)
+ dev->driver->free_filp_priv(dev, priv);
+
+- drm_free( priv, sizeof(*priv), DRM_MEM_FILES );
++ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+
+ /* ========================================================
+ * End inline drm_release
+ */
+
+- atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
+- spin_lock( &dev->count_lock );
+- if ( !--dev->open_count ) {
+- if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
+- DRM_ERROR( "Device busy: %d %d\n",
+- atomic_read( &dev->ioctl_count ),
+- dev->blocked );
+- spin_unlock( &dev->count_lock );
++ atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
++ spin_lock(&dev->count_lock);
++ if (!--dev->open_count) {
++ if (atomic_read(&dev->ioctl_count) || dev->blocked) {
++ DRM_ERROR("Device busy: %d %d\n",
++ atomic_read(&dev->ioctl_count), dev->blocked);
++ spin_unlock(&dev->count_lock);
+ unlock_kernel();
+ return -EBUSY;
+ }
+- spin_unlock( &dev->count_lock );
++ spin_unlock(&dev->count_lock);
+ unlock_kernel();
+- return drm_takedown( dev );
++ return drm_takedown(dev);
+ }
+- spin_unlock( &dev->count_lock );
++ spin_unlock(&dev->count_lock);
+
+ unlock_kernel();
+
+ return retcode;
+ }
++
+ EXPORT_SYMBOL(drm_release);
+
+ /**
+- * Called whenever a process opens /dev/drm.
++ * Called whenever a process opens /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param dev device.
+ * \return zero on success or a negative number on failure.
+- *
++ *
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
+-static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
++static int drm_open_helper(struct inode *inode, struct file *filp,
++ drm_device_t * dev)
+ {
+- int minor = iminor(inode);
+- drm_file_t *priv;
++ int minor = iminor(inode);
++ drm_file_t *priv;
+ int ret;
+
+- if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
+- if (!drm_cpu_valid()) return -EINVAL;
++ if (filp->f_flags & O_EXCL)
++ return -EBUSY; /* No exclusive opens */
++ if (!drm_cpu_valid())
++ return -EINVAL;
+
+ DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
+
+- priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+- if(!priv) return -ENOMEM;
++ priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
++ if (!priv)
++ return -ENOMEM;
+
+ memset(priv, 0, sizeof(*priv));
+- filp->private_data = priv;
+- priv->uid = current->euid;
+- priv->pid = current->pid;
+- priv->minor = minor;
+- priv->head = drm_heads[minor];
+- priv->ioctl_count = 0;
++ filp->private_data = priv;
++ priv->uid = current->euid;
++ priv->pid = current->pid;
++ priv->minor = minor;
++ priv->head = drm_heads[minor];
++ priv->ioctl_count = 0;
+ priv->authenticated = capable(CAP_SYS_ADMIN);
+- priv->lock_count = 0;
++ priv->lock_count = 0;
+
+ if (dev->driver->open_helper) {
+- ret=dev->driver->open_helper(dev, priv);
++ ret = dev->driver->open_helper(dev, priv);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ down(&dev->struct_sem);
+ if (!dev->file_last) {
+- priv->next = NULL;
+- priv->prev = NULL;
++ priv->next = NULL;
++ priv->prev = NULL;
+ dev->file_first = priv;
+- dev->file_last = priv;
++ dev->file_last = priv;
+ } else {
+- priv->next = NULL;
+- priv->prev = dev->file_last;
++ priv->next = NULL;
++ priv->prev = dev->file_last;
+ dev->file_last->next = priv;
+- dev->file_last = priv;
++ dev->file_last = priv;
+ }
+ up(&dev->struct_sem);
+
+@@ -394,42 +396,48 @@ static int drm_open_helper(struct inode
+ }
+ if (!dev->hose) {
+ struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+- if (b) dev->hose = b->sysdata;
++ if (b)
++ dev->hose = b->sysdata;
+ }
+ }
+ #endif
+
+ return 0;
+-out_free:
++ out_free:
+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+- filp->private_data=NULL;
++ filp->private_data = NULL;
+ return ret;
+ }
+
+ /** No-op. */
+ int drm_flush(struct file *filp)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+
+ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+- current->pid, (long)old_encode_dev(priv->head->device), dev->open_count);
++ current->pid, (long)old_encode_dev(priv->head->device),
++ dev->open_count);
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_flush);
+
+ /** No-op. */
+ int drm_fasync(int fd, struct file *filp, int on)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- int retcode;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ int retcode;
+
+- DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(priv->head->device));
++ DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
++ (long)old_encode_dev(priv->head->device));
+ retcode = fasync_helper(fd, filp, on, &dev->buf_async);
+- if (retcode < 0) return retcode;
++ if (retcode < 0)
++ return retcode;
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_fasync);
+
+ /** No-op. */
+@@ -437,5 +445,5 @@ unsigned int drm_poll(struct file *filp,
+ {
+ return 0;
+ }
+-EXPORT_SYMBOL(drm_poll);
+
++EXPORT_SYMBOL(drm_poll);
+diff --git a/drivers/char/drm/drm_init.c b/drivers/char/drm/drm_init.c
+--- a/drivers/char/drm/drm_init.c
++++ b/drivers/char/drm/drm_init.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_init.h
++ * \file drm_init.c
+ * Setup/Cleanup for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -43,10 +43,11 @@
+ int drm_cpu_valid(void)
+ {
+ #if defined(__i386__)
+- if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
++ if (boot_cpu_data.x86 == 3)
++ return 0; /* No cmpxchg on a 386 */
+ #endif
+ #if defined(__sparc__) && !defined(__sparc_v9__)
+- return 0; /* No cmpxchg before v9 sparc. */
++ return 0; /* No cmpxchg before v9 sparc. */
+ #endif
+ return 1;
+ }
+diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
+--- a/drivers/char/drm/drm_ioc32.c
++++ b/drivers/char/drm/drm_ioc32.c
+@@ -68,15 +68,15 @@
+ #define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
+
+ typedef struct drm_version_32 {
+- int version_major; /**< Major version */
+- int version_minor; /**< Minor version */
+- int version_patchlevel;/**< Patch level */
+- u32 name_len; /**< Length of name buffer */
+- u32 name; /**< Name of driver */
+- u32 date_len; /**< Length of date buffer */
+- u32 date; /**< User-space buffer to hold date */
+- u32 desc_len; /**< Length of desc buffer */
+- u32 desc; /**< User-space buffer to hold desc */
++ int version_major; /**< Major version */
++ int version_minor; /**< Minor version */
++ int version_patchlevel; /**< Patch level */
++ u32 name_len; /**< Length of name buffer */
++ u32 name; /**< Name of driver */
++ u32 date_len; /**< Length of date buffer */
++ u32 date; /**< User-space buffer to hold date */
++ u32 desc_len; /**< Length of desc buffer */
++ u32 desc; /**< User-space buffer to hold desc */
+ } drm_version32_t;
+
+ static int compat_drm_version(struct file *file, unsigned int cmd,
+@@ -86,7 +86,7 @@ static int compat_drm_version(struct fil
+ drm_version_t __user *version;
+ int err;
+
+- if (copy_from_user(&v32, (void __user *) arg, sizeof(v32)))
++ if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
+ return -EFAULT;
+
+ version = compat_alloc_user_space(sizeof(*version));
+@@ -104,7 +104,7 @@ static int compat_drm_version(struct fil
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_VERSION, (unsigned long) version);
++ DRM_IOCTL_VERSION, (unsigned long)version);
+ if (err)
+ return err;
+
+@@ -116,7 +116,7 @@ static int compat_drm_version(struct fil
+ || __get_user(v32.desc_len, &version->desc_len))
+ return -EFAULT;
+
+- if (copy_to_user((void __user *) arg, &v32, sizeof(v32)))
++ if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -133,25 +133,25 @@ static int compat_drm_getunique(struct f
+ drm_unique_t __user *u;
+ int err;
+
+- if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
++ if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
+ return -EFAULT;
+
+ u = compat_alloc_user_space(sizeof(*u));
+ if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+ return -EFAULT;
+ if (__put_user(uq32.unique_len, &u->unique_len)
+- || __put_user((void __user *)(unsigned long) uq32.unique,
++ || __put_user((void __user *)(unsigned long)uq32.unique,
+ &u->unique))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_GET_UNIQUE, (unsigned long) u);
++ DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
+ if (err)
+ return err;
+
+ if (__get_user(uq32.unique_len, &u->unique_len))
+ return -EFAULT;
+- if (copy_to_user((void __user *) arg, &uq32, sizeof(uq32)))
++ if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -162,28 +162,28 @@ static int compat_drm_setunique(struct f
+ drm_unique32_t uq32;
+ drm_unique_t __user *u;
+
+- if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
++ if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
+ return -EFAULT;
+
+ u = compat_alloc_user_space(sizeof(*u));
+ if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+ return -EFAULT;
+ if (__put_user(uq32.unique_len, &u->unique_len)
+- || __put_user((void __user *)(unsigned long) uq32.unique,
++ || __put_user((void __user *)(unsigned long)uq32.unique,
+ &u->unique))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_SET_UNIQUE, (unsigned long) u);
++ DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
+ }
+
+ typedef struct drm_map32 {
+- u32 offset; /**< Requested physical address (0 for SAREA)*/
+- u32 size; /**< Requested physical size (bytes) */
+- drm_map_type_t type; /**< Type of memory to map */
++ u32 offset; /**< Requested physical address (0 for SAREA)*/
++ u32 size; /**< Requested physical size (bytes) */
++ drm_map_type_t type; /**< Type of memory to map */
+ drm_map_flags_t flags; /**< Flags */
+- u32 handle; /**< User-space: "Handle" to pass to mmap() */
+- int mtrr; /**< MTRR slot used */
++ u32 handle; /**< User-space: "Handle" to pass to mmap() */
++ int mtrr; /**< MTRR slot used */
+ } drm_map32_t;
+
+ static int compat_drm_getmap(struct file *file, unsigned int cmd,
+@@ -205,7 +205,7 @@ static int compat_drm_getmap(struct file
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_GET_MAP, (unsigned long) map);
++ DRM_IOCTL_GET_MAP, (unsigned long)map);
+ if (err)
+ return err;
+
+@@ -217,7 +217,7 @@ static int compat_drm_getmap(struct file
+ || __get_user(m32.mtrr, &map->mtrr))
+ return -EFAULT;
+
+- m32.handle = (unsigned long) handle;
++ m32.handle = (unsigned long)handle;
+ if (copy_to_user(argp, &m32, sizeof(m32)))
+ return -EFAULT;
+ return 0;
+@@ -246,7 +246,7 @@ static int compat_drm_addmap(struct file
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_ADD_MAP, (unsigned long) map);
++ DRM_IOCTL_ADD_MAP, (unsigned long)map);
+ if (err)
+ return err;
+
+@@ -255,8 +255,8 @@ static int compat_drm_addmap(struct file
+ || __get_user(handle, &map->handle))
+ return -EFAULT;
+
+- m32.handle = (unsigned long) handle;
+- if (m32.handle != (unsigned long) handle && printk_ratelimit())
++ m32.handle = (unsigned long)handle;
++ if (m32.handle != (unsigned long)handle && printk_ratelimit())
+ printk(KERN_ERR "compat_drm_addmap truncated handle"
+ " %p for type %d offset %x\n",
+ handle, m32.type, m32.offset);
+@@ -280,20 +280,20 @@ static int compat_drm_rmmap(struct file
+ map = compat_alloc_user_space(sizeof(*map));
+ if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+ return -EFAULT;
+- if (__put_user((void *)(unsigned long) handle, &map->handle))
++ if (__put_user((void *)(unsigned long)handle, &map->handle))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RM_MAP, (unsigned long) map);
++ DRM_IOCTL_RM_MAP, (unsigned long)map);
+ }
+
+ typedef struct drm_client32 {
+- int idx; /**< Which client desired? */
+- int auth; /**< Is client authenticated? */
+- u32 pid; /**< Process ID */
+- u32 uid; /**< User ID */
+- u32 magic; /**< Magic */
+- u32 iocs; /**< Ioctl count */
++ int idx; /**< Which client desired? */
++ int auth; /**< Is client authenticated? */
++ u32 pid; /**< Process ID */
++ u32 uid; /**< User ID */
++ u32 magic; /**< Magic */
++ u32 iocs; /**< Ioctl count */
+ } drm_client32_t;
+
+ static int compat_drm_getclient(struct file *file, unsigned int cmd,
+@@ -314,7 +314,7 @@ static int compat_drm_getclient(struct f
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_GET_CLIENT, (unsigned long) client);
++ DRM_IOCTL_GET_CLIENT, (unsigned long)client);
+ if (err)
+ return err;
+
+@@ -351,7 +351,7 @@ static int compat_drm_getstats(struct fi
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_GET_STATS, (unsigned long) stats);
++ DRM_IOCTL_GET_STATS, (unsigned long)stats);
+ if (err)
+ return err;
+
+@@ -368,12 +368,12 @@ static int compat_drm_getstats(struct fi
+ }
+
+ typedef struct drm_buf_desc32 {
+- int count; /**< Number of buffers of this size */
+- int size; /**< Size in bytes */
+- int low_mark; /**< Low water mark */
+- int high_mark; /**< High water mark */
+- int flags;
+- u32 agp_start; /**< Start address in the AGP aperture */
++ int count; /**< Number of buffers of this size */
++ int size; /**< Size in bytes */
++ int low_mark; /**< Low water mark */
++ int high_mark; /**< High water mark */
++ int flags;
++ u32 agp_start; /**< Start address in the AGP aperture */
+ } drm_buf_desc32_t;
+
+ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
+@@ -395,7 +395,7 @@ static int compat_drm_addbufs(struct fil
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_ADD_BUFS, (unsigned long) buf);
++ DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
+ if (err)
+ return err;
+
+@@ -427,12 +427,12 @@ static int compat_drm_markbufs(struct fi
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_MARK_BUFS, (unsigned long) buf);
++ DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
+ }
+
+ typedef struct drm_buf_info32 {
+- int count; /**< Entries in list */
+- u32 list;
++ int count; /**< Entries in list */
++ u32 list;
+ } drm_buf_info32_t;
+
+ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
+@@ -451,7 +451,7 @@ static int compat_drm_infobufs(struct fi
+ return -EFAULT;
+
+ count = req32.count;
+- to = (drm_buf_desc32_t __user *)(unsigned long) req32.list;
++ to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
+ if (count < 0)
+ count = 0;
+ if (count > 0
+@@ -469,7 +469,7 @@ static int compat_drm_infobufs(struct fi
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_INFO_BUFS, (unsigned long) request);
++ DRM_IOCTL_INFO_BUFS, (unsigned long)request);
+ if (err)
+ return err;
+
+@@ -488,16 +488,16 @@ static int compat_drm_infobufs(struct fi
+ }
+
+ typedef struct drm_buf_pub32 {
+- int idx; /**< Index into the master buffer list */
+- int total; /**< Buffer size */
+- int used; /**< Amount of buffer in use (for DMA) */
+- u32 address; /**< Address of buffer */
++ int idx; /**< Index into the master buffer list */
++ int total; /**< Buffer size */
++ int used; /**< Amount of buffer in use (for DMA) */
++ u32 address; /**< Address of buffer */
+ } drm_buf_pub32_t;
+
+ typedef struct drm_buf_map32 {
+- int count; /**< Length of the buffer list */
+- u32 virtual; /**< Mmap'd area in user-virtual */
+- u32 list; /**< Buffer information */
++ int count; /**< Length of the buffer list */
++ u32 virtual; /**< Mmap'd area in user-virtual */
++ u32 list; /**< Buffer information */
+ } drm_buf_map32_t;
+
+ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
+@@ -531,7 +531,7 @@ static int compat_drm_mapbufs(struct fil
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_MAP_BUFS, (unsigned long) request);
++ DRM_IOCTL_MAP_BUFS, (unsigned long)request);
+ if (err)
+ return err;
+
+@@ -542,21 +542,21 @@ static int compat_drm_mapbufs(struct fil
+ if (__copy_in_user(&list32[i], &list[i],
+ offsetof(drm_buf_pub_t, address))
+ || __get_user(addr, &list[i].address)
+- || __put_user((unsigned long) addr,
++ || __put_user((unsigned long)addr,
+ &list32[i].address))
+ return -EFAULT;
+
+ if (__put_user(actual, &argp->count)
+ || __get_user(addr, &request->virtual)
+- || __put_user((unsigned long) addr, &argp->virtual))
++ || __put_user((unsigned long)addr, &argp->virtual))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ typedef struct drm_buf_free32 {
+- int count;
+- u32 list;
++ int count;
++ u32 list;
+ } drm_buf_free32_t;
+
+ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
+@@ -573,17 +573,17 @@ static int compat_drm_freebufs(struct fi
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+ return -EFAULT;
+ if (__put_user(req32.count, &request->count)
+- || __put_user((int __user *)(unsigned long) req32.list,
++ || __put_user((int __user *)(unsigned long)req32.list,
+ &request->list))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_FREE_BUFS, (unsigned long) request);
++ DRM_IOCTL_FREE_BUFS, (unsigned long)request);
+ }
+
+ typedef struct drm_ctx_priv_map32 {
+- unsigned int ctx_id; /**< Context requesting private mapping */
+- u32 handle; /**< Handle of map */
++ unsigned int ctx_id; /**< Context requesting private mapping */
++ u32 handle; /**< Handle of map */
+ } drm_ctx_priv_map32_t;
+
+ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
+@@ -600,12 +600,12 @@ static int compat_drm_setsareactx(struct
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+ return -EFAULT;
+ if (__put_user(req32.ctx_id, &request->ctx_id)
+- || __put_user((void *)(unsigned long) req32.handle,
++ || __put_user((void *)(unsigned long)req32.handle,
+ &request->handle))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_SET_SAREA_CTX, (unsigned long) request);
++ DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
+ }
+
+ static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
+@@ -628,20 +628,20 @@ static int compat_drm_getsareactx(struct
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_GET_SAREA_CTX, (unsigned long) request);
++ DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
+ if (err)
+ return err;
+
+ if (__get_user(handle, &request->handle)
+- || __put_user((unsigned long) handle, &argp->handle))
++ || __put_user((unsigned long)handle, &argp->handle))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ typedef struct drm_ctx_res32 {
+- int count;
+- u32 contexts;
++ int count;
++ u32 contexts;
+ } drm_ctx_res32_t;
+
+ static int compat_drm_resctx(struct file *file, unsigned int cmd,
+@@ -659,12 +659,12 @@ static int compat_drm_resctx(struct file
+ if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
+ return -EFAULT;
+ if (__put_user(res32.count, &res->count)
+- || __put_user((drm_ctx_t __user *)(unsigned long) res32.contexts,
++ || __put_user((drm_ctx_t __user *) (unsigned long)res32.contexts,
+ &res->contexts))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RES_CTX, (unsigned long) res);
++ DRM_IOCTL_RES_CTX, (unsigned long)res);
+ if (err)
+ return err;
+
+@@ -676,23 +676,23 @@ static int compat_drm_resctx(struct file
+ }
+
+ typedef struct drm_dma32 {
+- int context; /**< Context handle */
+- int send_count; /**< Number of buffers to send */
+- u32 send_indices; /**< List of handles to buffers */
+- u32 send_sizes; /**< Lengths of data to send */
++ int context; /**< Context handle */
++ int send_count; /**< Number of buffers to send */
++ u32 send_indices; /**< List of handles to buffers */
++ u32 send_sizes; /**< Lengths of data to send */
+ drm_dma_flags_t flags; /**< Flags */
+- int request_count; /**< Number of buffers requested */
+- int request_size; /**< Desired size for buffers */
+- u32 request_indices; /**< Buffer information */
+- u32 request_sizes;
+- int granted_count; /**< Number of buffers granted */
++ int request_count; /**< Number of buffers requested */
++ int request_size; /**< Desired size for buffers */
++ u32 request_indices; /**< Buffer information */
++ u32 request_sizes;
++ int granted_count; /**< Number of buffers granted */
+ } drm_dma32_t;
+
+ static int compat_drm_dma(struct file *file, unsigned int cmd,
+ unsigned long arg)
+ {
+ drm_dma32_t d32;
+- drm_dma32_t __user *argp = (void __user *) arg;
++ drm_dma32_t __user *argp = (void __user *)arg;
+ drm_dma_t __user *d;
+ int err;
+
+@@ -705,20 +705,20 @@ static int compat_drm_dma(struct file *f
+
+ if (__put_user(d32.context, &d->context)
+ || __put_user(d32.send_count, &d->send_count)
+- || __put_user((int __user *)(unsigned long) d32.send_indices,
++ || __put_user((int __user *)(unsigned long)d32.send_indices,
+ &d->send_indices)
+- || __put_user((int __user *)(unsigned long) d32.send_sizes,
++ || __put_user((int __user *)(unsigned long)d32.send_sizes,
+ &d->send_sizes)
+ || __put_user(d32.flags, &d->flags)
+ || __put_user(d32.request_count, &d->request_count)
+- || __put_user((int __user *)(unsigned long) d32.request_indices,
++ || __put_user((int __user *)(unsigned long)d32.request_indices,
+ &d->request_indices)
+- || __put_user((int __user *)(unsigned long) d32.request_sizes,
++ || __put_user((int __user *)(unsigned long)d32.request_sizes,
+ &d->request_sizes))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_DMA, (unsigned long) d);
++ DRM_IOCTL_DMA, (unsigned long)d);
+ if (err)
+ return err;
+
+@@ -751,19 +751,19 @@ static int compat_drm_agp_enable(struct
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_AGP_ENABLE, (unsigned long) mode);
++ DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
+ }
+
+ typedef struct drm_agp_info32 {
+- int agp_version_major;
+- int agp_version_minor;
+- u32 mode;
+- u32 aperture_base; /* physical address */
+- u32 aperture_size; /* bytes */
+- u32 memory_allowed; /* bytes */
+- u32 memory_used;
++ int agp_version_major;
++ int agp_version_minor;
++ u32 mode;
++ u32 aperture_base; /* physical address */
++ u32 aperture_size; /* bytes */
++ u32 memory_allowed; /* bytes */
++ u32 memory_used;
+
+- /* PCI information */
++ /* PCI information */
+ unsigned short id_vendor;
+ unsigned short id_device;
+ } drm_agp_info32_t;
+@@ -781,7 +781,7 @@ static int compat_drm_agp_info(struct fi
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_AGP_INFO, (unsigned long) info);
++ DRM_IOCTL_AGP_INFO, (unsigned long)info);
+ if (err)
+ return err;
+
+@@ -806,7 +806,7 @@ typedef struct drm_agp_buffer32 {
+ u32 size; /**< In bytes -- will round to page boundary */
+ u32 handle; /**< Used for binding / unbinding */
+ u32 type; /**< Type of memory to allocate */
+- u32 physical; /**< Physical used by i810 */
++ u32 physical; /**< Physical used by i810 */
+ } drm_agp_buffer32_t;
+
+ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
+@@ -827,7 +827,7 @@ static int compat_drm_agp_alloc(struct f
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_AGP_ALLOC, (unsigned long) request);
++ DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
+ if (err)
+ return err;
+
+@@ -835,7 +835,7 @@ static int compat_drm_agp_alloc(struct f
+ || __get_user(req32.physical, &request->physical)
+ || copy_to_user(argp, &req32, sizeof(req32))) {
+ drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_AGP_FREE, (unsigned long) request);
++ DRM_IOCTL_AGP_FREE, (unsigned long)request);
+ return -EFAULT;
+ }
+
+@@ -856,7 +856,7 @@ static int compat_drm_agp_free(struct fi
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_AGP_FREE, (unsigned long) request);
++ DRM_IOCTL_AGP_FREE, (unsigned long)request);
+ }
+
+ typedef struct drm_agp_binding32 {
+@@ -881,7 +881,7 @@ static int compat_drm_agp_bind(struct fi
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_AGP_BIND, (unsigned long) request);
++ DRM_IOCTL_AGP_BIND, (unsigned long)request);
+ }
+
+ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
+@@ -898,9 +898,9 @@ static int compat_drm_agp_unbind(struct
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_AGP_UNBIND, (unsigned long) request);
++ DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
+ }
+-#endif /* __OS_HAS_AGP */
++#endif /* __OS_HAS_AGP */
+
+ typedef struct drm_scatter_gather32 {
+ u32 size; /**< In bytes -- will round to page boundary */
+@@ -923,7 +923,7 @@ static int compat_drm_sg_alloc(struct fi
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_SG_ALLOC, (unsigned long) request);
++ DRM_IOCTL_SG_ALLOC, (unsigned long)request);
+ if (err)
+ return err;
+
+@@ -950,7 +950,7 @@ static int compat_drm_sg_free(struct fil
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_SG_FREE, (unsigned long) request);
++ DRM_IOCTL_SG_FREE, (unsigned long)request);
+ }
+
+ struct drm_wait_vblank_request32 {
+@@ -990,7 +990,7 @@ static int compat_drm_wait_vblank(struct
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_WAIT_VBLANK, (unsigned long) request);
++ DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
+ if (err)
+ return err;
+
+@@ -1059,11 +1059,12 @@ long drm_compat_ioctl(struct file *filp,
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+- ret = (*fn)(filp, cmd, arg);
++ ret = (*fn) (filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+ }
++
+ EXPORT_SYMBOL(drm_compat_ioctl);
+diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
+--- a/drivers/char/drm/drm_ioctl.c
++++ b/drivers/char/drm/drm_ioctl.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_ioctl.h
++ * \file drm_ioctl.c
+ * IOCTL processing for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -40,7 +40,7 @@
+
+ /**
+ * Get the bus id.
+- *
++ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+@@ -50,12 +50,12 @@
+ * Copies the bus id from drm_device::unique into user space.
+ */
+ int drm_getunique(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_unique_t __user *argp = (void __user *)arg;
+- drm_unique_t u;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_unique_t __user *argp = (void __user *)arg;
++ drm_unique_t u;
+
+ if (copy_from_user(&u, argp, sizeof(u)))
+ return -EFAULT;
+@@ -71,7 +71,7 @@ int drm_getunique(struct inode *inode, s
+
+ /**
+ * Set the bus id.
+- *
++ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+@@ -84,34 +84,39 @@ int drm_getunique(struct inode *inode, s
+ * version 1.1 or greater.
+ */
+ int drm_setunique(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_unique_t u;
+- int domain, bus, slot, func, ret;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_unique_t u;
++ int domain, bus, slot, func, ret;
+
+- if (dev->unique_len || dev->unique) return -EBUSY;
++ if (dev->unique_len || dev->unique)
++ return -EBUSY;
+
+- if (copy_from_user(&u, (drm_unique_t __user *)arg, sizeof(u)))
++ if (copy_from_user(&u, (drm_unique_t __user *) arg, sizeof(u)))
+ return -EFAULT;
+
+- if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
++ if (!u.unique_len || u.unique_len > 1024)
++ return -EINVAL;
+
+ dev->unique_len = u.unique_len;
+- dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
+- if(!dev->unique) return -ENOMEM;
++ dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
++ if (!dev->unique)
++ return -ENOMEM;
+ if (copy_from_user(dev->unique, u.unique, dev->unique_len))
+ return -EFAULT;
+
+ dev->unique[dev->unique_len] = '\0';
+
+- dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + strlen(dev->unique) + 2,
+- DRM_MEM_DRIVER);
++ dev->devname =
++ drm_alloc(strlen(dev->driver->pci_driver.name) +
++ strlen(dev->unique) + 2, DRM_MEM_DRIVER);
+ if (!dev->devname)
+ return -ENOMEM;
+
+- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
++ sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
++ dev->unique);
+
+ /* Return error if the busid submitted doesn't match the device's actual
+ * busid.
+@@ -121,18 +126,16 @@ int drm_setunique(struct inode *inode, s
+ return DRM_ERR(EINVAL);
+ domain = bus >> 8;
+ bus &= 0xff;
+-
++
+ if ((domain != dev->pci_domain) ||
+ (bus != dev->pci_bus) ||
+- (slot != dev->pci_slot) ||
+- (func != dev->pci_func))
++ (slot != dev->pci_slot) || (func != dev->pci_func))
+ return -EINVAL;
+
+ return 0;
+ }
+
+-static int
+-drm_set_busid(drm_device_t *dev)
++static int drm_set_busid(drm_device_t * dev)
+ {
+ if (dev->unique != NULL)
+ return EBUSY;
+@@ -143,19 +146,20 @@ drm_set_busid(drm_device_t *dev)
+ return ENOMEM;
+
+ snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+- dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
++ dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
+
+- dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + 2,
+- DRM_MEM_DRIVER);
++ dev->devname =
++ drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
++ 2, DRM_MEM_DRIVER);
+ if (dev->devname == NULL)
+ return ENOMEM;
+
+- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
++ sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
++ dev->unique);
+
+ return 0;
+ }
+
+-
+ /**
+ * Get a mapping information.
+ *
+@@ -163,23 +167,23 @@ drm_set_busid(drm_device_t *dev)
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_map structure.
+- *
++ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the mapping with the specified offset and copies its information
+ * into userspace
+ */
+-int drm_getmap( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_getmap(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_map_t __user *argp = (void __user *)arg;
+- drm_map_t map;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_map_t __user *argp = (void __user *)arg;
++ drm_map_t map;
+ drm_map_list_t *r_list = NULL;
+ struct list_head *list;
+- int idx;
+- int i;
++ int idx;
++ int i;
+
+ if (copy_from_user(&map, argp, sizeof(map)))
+ return -EFAULT;
+@@ -193,26 +197,27 @@ int drm_getmap( struct inode *inode, str
+
+ i = 0;
+ list_for_each(list, &dev->maplist->head) {
+- if(i == idx) {
++ if (i == idx) {
+ r_list = list_entry(list, drm_map_list_t, head);
+ break;
+ }
+ i++;
+ }
+- if(!r_list || !r_list->map) {
++ if (!r_list || !r_list->map) {
+ up(&dev->struct_sem);
+ return -EINVAL;
+ }
+
+ map.offset = r_list->map->offset;
+- map.size = r_list->map->size;
+- map.type = r_list->map->type;
+- map.flags = r_list->map->flags;
+- map.handle = (void *)(unsigned long) r_list->user_token;
+- map.mtrr = r_list->map->mtrr;
++ map.size = r_list->map->size;
++ map.type = r_list->map->type;
++ map.flags = r_list->map->flags;
++ map.handle = (void *)(unsigned long)r_list->user_token;
++ map.mtrr = r_list->map->mtrr;
+ up(&dev->struct_sem);
+
+- if (copy_to_user(argp, &map, sizeof(map))) return -EFAULT;
++ if (copy_to_user(argp, &map, sizeof(map)))
++ return -EFAULT;
+ return 0;
+ }
+
+@@ -223,83 +228,81 @@ int drm_getmap( struct inode *inode, str
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_client structure.
+- *
++ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the client with the specified index and copies its information
+ * into userspace
+ */
+-int drm_getclient( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_getclient(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_client_t __user *argp = (void __user *)arg;
+ drm_client_t client;
+- drm_file_t *pt;
+- int idx;
+- int i;
++ drm_file_t *pt;
++ int idx;
++ int i;
+
+ if (copy_from_user(&client, argp, sizeof(client)))
+ return -EFAULT;
+ idx = client.idx;
+ down(&dev->struct_sem);
+- for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
+- ;
++ for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
+
+ if (!pt) {
+ up(&dev->struct_sem);
+ return -EINVAL;
+ }
+- client.auth = pt->authenticated;
+- client.pid = pt->pid;
+- client.uid = pt->uid;
++ client.auth = pt->authenticated;
++ client.pid = pt->pid;
++ client.uid = pt->uid;
+ client.magic = pt->magic;
+- client.iocs = pt->ioctl_count;
++ client.iocs = pt->ioctl_count;
+ up(&dev->struct_sem);
+
+- if (copy_to_user((drm_client_t __user *)arg, &client, sizeof(client)))
++ if (copy_to_user((drm_client_t __user *) arg, &client, sizeof(client)))
+ return -EFAULT;
+ return 0;
+ }
+
+-/**
+- * Get statistics information.
+- *
++/**
++ * Get statistics information.
++ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_stats structure.
+- *
++ *
+ * \return zero on success or a negative number on failure.
+ */
+-int drm_getstats( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_getstats(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_stats_t stats;
+- int i;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_stats_t stats;
++ int i;
+
+ memset(&stats, 0, sizeof(stats));
+-
++
+ down(&dev->struct_sem);
+
+ for (i = 0; i < dev->counters; i++) {
+ if (dev->types[i] == _DRM_STAT_LOCK)
+ stats.data[i].value
+- = (dev->lock.hw_lock
+- ? dev->lock.hw_lock->lock : 0);
+- else
++ = (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
++ else
+ stats.data[i].value = atomic_read(&dev->counts[i]);
+- stats.data[i].type = dev->types[i];
++ stats.data[i].type = dev->types[i];
+ }
+-
++
+ stats.count = dev->counters;
+
+ up(&dev->struct_sem);
+
+- if (copy_to_user((drm_stats_t __user *)arg, &stats, sizeof(stats)))
++ if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -352,7 +355,8 @@ int drm_setversion(DRM_IOCTL_ARGS)
+
+ if (sv.drm_dd_major != -1) {
+ if (sv.drm_dd_major != version.version_major ||
+- sv.drm_dd_minor < 0 || sv.drm_dd_minor > version.version_minor)
++ sv.drm_dd_minor < 0
++ || sv.drm_dd_minor > version.version_minor)
+ return EINVAL;
+
+ if (dev->driver->set_version)
+@@ -363,7 +367,7 @@ int drm_setversion(DRM_IOCTL_ARGS)
+
+ /** No-op ioctl. */
+ int drm_noop(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ DRM_DEBUG("\n");
+ return 0;
+diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
+--- a/drivers/char/drm/drm_irq.c
++++ b/drivers/char/drm/drm_irq.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_irq.h
++ * \file drm_irq.c
+ * IRQ support
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -39,19 +39,19 @@
+
+ /**
+ * Get interrupt from bus id.
+- *
++ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_irq_busid structure.
+ * \return zero on success or a negative number on failure.
+- *
++ *
+ * Finds the PCI device with the specified bus id and gets its IRQ number.
+ * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
+ * to that of the device that this DRM instance attached to.
+ */
+ int drm_irq_by_busid(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -66,14 +66,12 @@ int drm_irq_by_busid(struct inode *inode
+
+ if ((p.busnum >> 8) != dev->pci_domain ||
+ (p.busnum & 0xff) != dev->pci_bus ||
+- p.devnum != dev->pci_slot ||
+- p.funcnum != dev->pci_func)
++ p.devnum != dev->pci_slot || p.funcnum != dev->pci_func)
+ return -EINVAL;
+
+ p.irq = dev->irq;
+
+- DRM_DEBUG("%d:%d:%d => IRQ %d\n",
+- p.busnum, p.devnum, p.funcnum, p.irq);
++ DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq);
+ if (copy_to_user(argp, &p, sizeof(p)))
+ return -EFAULT;
+ return 0;
+@@ -89,61 +87,61 @@ int drm_irq_by_busid(struct inode *inode
+ * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
+ * before and after the installation.
+ */
+-static int drm_irq_install( drm_device_t *dev )
++static int drm_irq_install(drm_device_t * dev)
+ {
+ int ret;
+- unsigned long sh_flags=0;
++ unsigned long sh_flags = 0;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return -EINVAL;
+
+- if ( dev->irq == 0 )
++ if (dev->irq == 0)
+ return -EINVAL;
+
+- down( &dev->struct_sem );
++ down(&dev->struct_sem);
+
+ /* Driver must have been initialized */
+- if ( !dev->dev_private ) {
+- up( &dev->struct_sem );
++ if (!dev->dev_private) {
++ up(&dev->struct_sem);
+ return -EINVAL;
+ }
+
+- if ( dev->irq_enabled ) {
+- up( &dev->struct_sem );
++ if (dev->irq_enabled) {
++ up(&dev->struct_sem);
+ return -EBUSY;
+ }
+ dev->irq_enabled = 1;
+- up( &dev->struct_sem );
++ up(&dev->struct_sem);
+
+- DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
++ DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
+
+ if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
+ init_waitqueue_head(&dev->vbl_queue);
+-
+- spin_lock_init( &dev->vbl_lock );
+-
+- INIT_LIST_HEAD( &dev->vbl_sigs.head );
+-
++
++ spin_lock_init(&dev->vbl_lock);
++
++ INIT_LIST_HEAD(&dev->vbl_sigs.head);
++
+ dev->vbl_pending = 0;
+ }
+
+- /* Before installing handler */
++ /* Before installing handler */
+ dev->driver->irq_preinstall(dev);
+
+- /* Install handler */
++ /* Install handler */
+ if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
+ sh_flags = SA_SHIRQ;
+-
+- ret = request_irq( dev->irq, dev->driver->irq_handler,
+- sh_flags, dev->devname, dev );
+- if ( ret < 0 ) {
+- down( &dev->struct_sem );
++
++ ret = request_irq(dev->irq, dev->driver->irq_handler,
++ sh_flags, dev->devname, dev);
++ if (ret < 0) {
++ down(&dev->struct_sem);
+ dev->irq_enabled = 0;
+- up( &dev->struct_sem );
++ up(&dev->struct_sem);
+ return ret;
+ }
+
+- /* After installing handler */
++ /* After installing handler */
+ dev->driver->irq_postinstall(dev);
+
+ return 0;
+@@ -156,29 +154,30 @@ static int drm_irq_install( drm_device_t
+ *
+ * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
+ */
+-int drm_irq_uninstall( drm_device_t *dev )
++int drm_irq_uninstall(drm_device_t * dev)
+ {
+ int irq_enabled;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return -EINVAL;
+
+- down( &dev->struct_sem );
++ down(&dev->struct_sem);
+ irq_enabled = dev->irq_enabled;
+ dev->irq_enabled = 0;
+- up( &dev->struct_sem );
++ up(&dev->struct_sem);
+
+- if ( !irq_enabled )
++ if (!irq_enabled)
+ return -EINVAL;
+
+- DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
++ DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
+
+ dev->driver->irq_uninstall(dev);
+
+- free_irq( dev->irq, dev );
++ free_irq(dev->irq, dev);
+
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_irq_uninstall);
+
+ /**
+@@ -192,30 +191,30 @@ EXPORT_SYMBOL(drm_irq_uninstall);
+ *
+ * Calls irq_install() or irq_uninstall() according to \p arg.
+ */
+-int drm_control( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_control(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_control_t ctl;
+-
++
+ /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
+
+- if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
++ if (copy_from_user(&ctl, (drm_control_t __user *) arg, sizeof(ctl)))
+ return -EFAULT;
+
+- switch ( ctl.func ) {
++ switch (ctl.func) {
+ case DRM_INST_HANDLER:
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return 0;
+ if (dev->if_version < DRM_IF_VERSION(1, 2) &&
+ ctl.irq != dev->irq)
+ return -EINVAL;
+- return drm_irq_install( dev );
++ return drm_irq_install(dev);
+ case DRM_UNINST_HANDLER:
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+ return 0;
+- return drm_irq_uninstall( dev );
++ return drm_irq_uninstall(dev);
+ default:
+ return -EINVAL;
+ }
+@@ -230,7 +229,7 @@ int drm_control( struct inode *inode, st
+ * \param data user argument, pointing to a drm_wait_vblank structure.
+ * \return zero on success or a negative number on failure.
+ *
+- * Verifies the IRQ is installed.
++ * Verifies the IRQ is installed.
+ *
+ * If a signal is requested checks if this task has already scheduled the same signal
+ * for the same vblank sequence number - nothing to be done in
+@@ -240,7 +239,7 @@ int drm_control( struct inode *inode, st
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+-int drm_wait_vblank( DRM_IOCTL_ARGS )
++int drm_wait_vblank(DRM_IOCTL_ARGS)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -256,11 +255,11 @@ int drm_wait_vblank( DRM_IOCTL_ARGS )
+ if (!dev->irq)
+ return -EINVAL;
+
+- DRM_COPY_FROM_USER_IOCTL( vblwait, argp, sizeof(vblwait) );
++ DRM_COPY_FROM_USER_IOCTL(vblwait, argp, sizeof(vblwait));
+
+- switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
++ switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) {
+ case _DRM_VBLANK_RELATIVE:
+- vblwait.request.sequence += atomic_read( &dev->vbl_received );
++ vblwait.request.sequence += atomic_read(&dev->vbl_received);
+ vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+ case _DRM_VBLANK_ABSOLUTE:
+ break;
+@@ -269,64 +268,68 @@ int drm_wait_vblank( DRM_IOCTL_ARGS )
+ }
+
+ flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+-
+- if ( flags & _DRM_VBLANK_SIGNAL ) {
++
++ if (flags & _DRM_VBLANK_SIGNAL) {
+ unsigned long irqflags;
+ drm_vbl_sig_t *vbl_sig;
+-
+- vblwait.reply.sequence = atomic_read( &dev->vbl_received );
+
+- spin_lock_irqsave( &dev->vbl_lock, irqflags );
++ vblwait.reply.sequence = atomic_read(&dev->vbl_received);
++
++ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+
+ /* Check if this task has already scheduled the same signal
+ * for the same vblank sequence number; nothing to be done in
+ * that case
+ */
+- list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
++ list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) {
+ if (vbl_sig->sequence == vblwait.request.sequence
+ && vbl_sig->info.si_signo == vblwait.request.signal
+- && vbl_sig->task == current)
+- {
+- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
++ && vbl_sig->task == current) {
++ spin_unlock_irqrestore(&dev->vbl_lock,
++ irqflags);
+ goto done;
+ }
+ }
+
+- if ( dev->vbl_pending >= 100 ) {
+- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
++ if (dev->vbl_pending >= 100) {
++ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ return -EBUSY;
+ }
+
+ dev->vbl_pending++;
+
+- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
++ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+- if ( !( vbl_sig = drm_alloc( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
++ if (!
++ (vbl_sig =
++ drm_alloc(sizeof(drm_vbl_sig_t), DRM_MEM_DRIVER))) {
+ return -ENOMEM;
+ }
+
+- memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
++ memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
+
+ vbl_sig->sequence = vblwait.request.sequence;
+ vbl_sig->info.si_signo = vblwait.request.signal;
+ vbl_sig->task = current;
+
+- spin_lock_irqsave( &dev->vbl_lock, irqflags );
++ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+
+- list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
++ list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head);
+
+- spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
++ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ } else {
+ if (dev->driver->vblank_wait)
+- ret = dev->driver->vblank_wait( dev, &vblwait.request.sequence );
++ ret =
++ dev->driver->vblank_wait(dev,
++ &vblwait.request.sequence);
+
+- do_gettimeofday( &now );
++ do_gettimeofday(&now);
+ vblwait.reply.tval_sec = now.tv_sec;
+ vblwait.reply.tval_usec = now.tv_usec;
+ }
+
+-done:
+- DRM_COPY_TO_USER_IOCTL( argp, vblwait, sizeof(vblwait) );
++ done:
++ DRM_COPY_TO_USER_IOCTL(argp, vblwait, sizeof(vblwait));
+
+ return ret;
+ }
+@@ -340,31 +343,31 @@ done:
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+-void drm_vbl_send_signals( drm_device_t *dev )
++void drm_vbl_send_signals(drm_device_t * dev)
+ {
+ struct list_head *list, *tmp;
+ drm_vbl_sig_t *vbl_sig;
+- unsigned int vbl_seq = atomic_read( &dev->vbl_received );
++ unsigned int vbl_seq = atomic_read(&dev->vbl_received);
+ unsigned long flags;
+
+- spin_lock_irqsave( &dev->vbl_lock, flags );
++ spin_lock_irqsave(&dev->vbl_lock, flags);
+
+- list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
+- vbl_sig = list_entry( list, drm_vbl_sig_t, head );
+- if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
++ list_for_each_safe(list, tmp, &dev->vbl_sigs.head) {
++ vbl_sig = list_entry(list, drm_vbl_sig_t, head);
++ if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+ vbl_sig->info.si_code = vbl_seq;
+- send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
++ send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info,
++ vbl_sig->task);
+
+- list_del( list );
++ list_del(list);
+
+- drm_free( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
++ drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER);
+
+ dev->vbl_pending--;
+ }
+ }
+
+- spin_unlock_irqrestore( &dev->vbl_lock, flags );
++ spin_unlock_irqrestore(&dev->vbl_lock, flags);
+ }
+-EXPORT_SYMBOL(drm_vbl_send_signals);
+-
+
++EXPORT_SYMBOL(drm_vbl_send_signals);
+diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
+--- a/drivers/char/drm/drm_lock.c
++++ b/drivers/char/drm/drm_lock.c
+@@ -1,7 +1,7 @@
+ /**
+- * \file drm_lock.h
++ * \file drm_lock.c
+ * IOCTLs for locking
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+@@ -35,12 +35,12 @@
+
+ #include "drmP.h"
+
+-static int drm_lock_transfer(drm_device_t *dev,
++static int drm_lock_transfer(drm_device_t * dev,
+ __volatile__ unsigned int *lock,
+ unsigned int context);
+ static int drm_notifier(void *priv);
+
+-/**
++/**
+ * Lock ioctl.
+ *
+ * \param inode device inode.
+@@ -51,91 +51,89 @@ static int drm_notifier(void *priv);
+ *
+ * Add the current task to the lock wait queue, and attempt to take to lock.
+ */
+-int drm_lock( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_lock(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- DECLARE_WAITQUEUE( entry, current );
+- drm_lock_t lock;
+- int ret = 0;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ DECLARE_WAITQUEUE(entry, current);
++ drm_lock_t lock;
++ int ret = 0;
+
+ ++priv->lock_count;
+
+- if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
++ if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+ return -EFAULT;
+
+- if ( lock.context == DRM_KERNEL_CONTEXT ) {
+- DRM_ERROR( "Process %d using kernel context %d\n",
+- current->pid, lock.context );
+- return -EINVAL;
+- }
+-
+- DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+- lock.context, current->pid,
+- dev->lock.hw_lock->lock, lock.flags );
++ if (lock.context == DRM_KERNEL_CONTEXT) {
++ DRM_ERROR("Process %d using kernel context %d\n",
++ current->pid, lock.context);
++ return -EINVAL;
++ }
++
++ DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
++ lock.context, current->pid,
++ dev->lock.hw_lock->lock, lock.flags);
+
+ if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
+- if ( lock.context < 0 )
++ if (lock.context < 0)
+ return -EINVAL;
+
+- add_wait_queue( &dev->lock.lock_queue, &entry );
++ add_wait_queue(&dev->lock.lock_queue, &entry);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+- if ( !dev->lock.hw_lock ) {
++ if (!dev->lock.hw_lock) {
+ /* Device has been unregistered */
+ ret = -EINTR;
+ break;
+ }
+- if ( drm_lock_take( &dev->lock.hw_lock->lock,
+- lock.context ) ) {
+- dev->lock.filp = filp;
++ if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
++ dev->lock.filp = filp;
+ dev->lock.lock_time = jiffies;
+- atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+- break; /* Got lock */
++ atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
++ break; /* Got lock */
+ }
+-
++
+ /* Contention */
+ schedule();
+- if ( signal_pending( current ) ) {
++ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ }
+ __set_current_state(TASK_RUNNING);
+- remove_wait_queue( &dev->lock.lock_queue, &entry );
++ remove_wait_queue(&dev->lock.lock_queue, &entry);
+
+- sigemptyset( &dev->sigmask );
+- sigaddset( &dev->sigmask, SIGSTOP );
+- sigaddset( &dev->sigmask, SIGTSTP );
+- sigaddset( &dev->sigmask, SIGTTIN );
+- sigaddset( &dev->sigmask, SIGTTOU );
++ sigemptyset(&dev->sigmask);
++ sigaddset(&dev->sigmask, SIGSTOP);
++ sigaddset(&dev->sigmask, SIGTSTP);
++ sigaddset(&dev->sigmask, SIGTTIN);
++ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+- dev->sigdata.lock = dev->lock.hw_lock;
+- block_all_signals( drm_notifier,
+- &dev->sigdata, &dev->sigmask );
+-
++ dev->sigdata.lock = dev->lock.hw_lock;
++ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
++
+ if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
+ dev->driver->dma_ready(dev);
+-
+- if ( dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
++
++ if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT))
+ return dev->driver->dma_quiescent(dev);
+-
+- /* dev->driver->kernel_context_switch isn't used by any of the x86
++
++ /* dev->driver->kernel_context_switch isn't used by any of the x86
+ * drivers but is used by the Sparc driver.
+ */
+-
+- if (dev->driver->kernel_context_switch &&
++
++ if (dev->driver->kernel_context_switch &&
+ dev->last_context != lock.context) {
+- dev->driver->kernel_context_switch(dev, dev->last_context,
+- lock.context);
++ dev->driver->kernel_context_switch(dev, dev->last_context,
++ lock.context);
+ }
+- DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
++ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+
+- return ret;
++ return ret;
+ }
+
+-/**
++/**
+ * Unlock ioctl.
+ *
+ * \param inode device inode.
+@@ -146,23 +144,23 @@ int drm_lock( struct inode *inode, struc
+ *
+ * Transfer and free the lock.
+ */
+-int drm_unlock( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_unlock(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_lock_t lock;
+
+- if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
++ if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
+ return -EFAULT;
+
+- if ( lock.context == DRM_KERNEL_CONTEXT ) {
+- DRM_ERROR( "Process %d using kernel context %d\n",
+- current->pid, lock.context );
++ if (lock.context == DRM_KERNEL_CONTEXT) {
++ DRM_ERROR("Process %d using kernel context %d\n",
++ current->pid, lock.context);
+ return -EINVAL;
+ }
+
+- atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
++ atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
+
+ /* kernel_context_switch isn't used by any of the x86 drm
+ * modules but is required by the Sparc driver.
+@@ -170,12 +168,12 @@ int drm_unlock( struct inode *inode, str
+ if (dev->driver->kernel_context_switch_unlock)
+ dev->driver->kernel_context_switch_unlock(dev, &lock);
+ else {
+- drm_lock_transfer( dev, &dev->lock.hw_lock->lock,
+- DRM_KERNEL_CONTEXT );
+-
+- if ( drm_lock_free( dev, &dev->lock.hw_lock->lock,
+- DRM_KERNEL_CONTEXT ) ) {
+- DRM_ERROR( "\n" );
++ drm_lock_transfer(dev, &dev->lock.hw_lock->lock,
++ DRM_KERNEL_CONTEXT);
++
++ if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
++ DRM_KERNEL_CONTEXT)) {
++ DRM_ERROR("\n");
+ }
+ }
+
+@@ -198,8 +196,10 @@ int drm_lock_take(__volatile__ unsigned
+
+ do {
+ old = *lock;
+- if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
+- else new = context | _DRM_LOCK_HELD;
++ if (old & _DRM_LOCK_HELD)
++ new = old | _DRM_LOCK_CONT;
++ else
++ new = context | _DRM_LOCK_HELD;
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
+ if (_DRM_LOCKING_CONTEXT(old) == context) {
+@@ -212,7 +212,7 @@ int drm_lock_take(__volatile__ unsigned
+ }
+ }
+ if (new == (context | _DRM_LOCK_HELD)) {
+- /* Have lock */
++ /* Have lock */
+ return 1;
+ }
+ return 0;
+@@ -220,8 +220,8 @@ int drm_lock_take(__volatile__ unsigned
+
+ /**
+ * This takes a lock forcibly and hands it to context. Should ONLY be used
+- * inside *_unlock to give lock to kernel before calling *_dma_schedule.
+- *
++ * inside *_unlock to give lock to kernel before calling *_dma_schedule.
++ *
+ * \param dev DRM device.
+ * \param lock lock pointer.
+ * \param context locking context.
+@@ -230,7 +230,7 @@ int drm_lock_take(__volatile__ unsigned
+ * Resets the lock file pointer.
+ * Marks the lock as held by the given context, via the \p cmpxchg instruction.
+ */
+-static int drm_lock_transfer(drm_device_t *dev,
++static int drm_lock_transfer(drm_device_t * dev,
+ __volatile__ unsigned int *lock,
+ unsigned int context)
+ {
+@@ -238,8 +238,8 @@ static int drm_lock_transfer(drm_device_
+
+ dev->lock.filp = NULL;
+ do {
+- old = *lock;
+- new = context | _DRM_LOCK_HELD;
++ old = *lock;
++ new = context | _DRM_LOCK_HELD;
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
+ return 1;
+@@ -247,30 +247,29 @@ static int drm_lock_transfer(drm_device_
+
+ /**
+ * Free lock.
+- *
++ *
+ * \param dev DRM device.
+ * \param lock lock.
+ * \param context context.
+- *
++ *
+ * Resets the lock file pointer.
+ * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
+ * waiting on the lock queue.
+ */
+-int drm_lock_free(drm_device_t *dev,
+- __volatile__ unsigned int *lock, unsigned int context)
++int drm_lock_free(drm_device_t * dev,
++ __volatile__ unsigned int *lock, unsigned int context)
+ {
+ unsigned int old, new, prev;
+
+ dev->lock.filp = NULL;
+ do {
+- old = *lock;
+- new = 0;
++ old = *lock;
++ new = 0;
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
+ if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
+ DRM_ERROR("%d freed heavyweight lock held by %d\n",
+- context,
+- _DRM_LOCKING_CONTEXT(old));
++ context, _DRM_LOCKING_CONTEXT(old));
+ return 1;
+ }
+ wake_up_interruptible(&dev->lock.lock_queue);
+@@ -290,19 +289,19 @@ int drm_lock_free(drm_device_t *dev,
+ */
+ static int drm_notifier(void *priv)
+ {
+- drm_sigdata_t *s = (drm_sigdata_t *)priv;
+- unsigned int old, new, prev;
+-
++ drm_sigdata_t *s = (drm_sigdata_t *) priv;
++ unsigned int old, new, prev;
+
+- /* Allow signal delivery if lock isn't held */
++ /* Allow signal delivery if lock isn't held */
+ if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
+- || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
++ || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context)
++ return 1;
+
+- /* Otherwise, set flag to force call to
+- drmUnlock */
++ /* Otherwise, set flag to force call to
++ drmUnlock */
+ do {
+- old = s->lock->lock;
+- new = old | _DRM_LOCK_CONT;
++ old = s->lock->lock;
++ new = old | _DRM_LOCK_CONT;
+ prev = cmpxchg(&s->lock->lock, old, new);
+ } while (prev != old);
+ return 0;
+diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
+--- a/drivers/char/drm/drm_memory.c
++++ b/drivers/char/drm/drm_memory.c
+@@ -1,12 +1,12 @@
+-/**
+- * \file drm_memory.h
++/**
++ * \file drm_memory.c
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+
+-/*
++/*
+ * Created: Thu Feb 4 14:00:34 1999 by faith at valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+@@ -48,7 +48,7 @@ void drm_mem_init(void)
+
+ /**
+ * Called when "/proc/dri/%dev%/mem" is read.
+- *
++ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+@@ -57,10 +57,10 @@ void drm_mem_init(void)
+ * \param data private data.
+ * \return number of written bytes.
+ *
+- * No-op.
++ * No-op.
+ */
+ int drm_mem_info(char *buf, char **start, off_t offset,
+- int len, int *eof, void *data)
++ int len, int *eof, void *data)
+ {
+ return 0;
+ }
+@@ -70,7 +70,8 @@ void *drm_realloc(void *oldpt, size_t ol
+ {
+ void *pt;
+
+- if (!(pt = kmalloc(size, GFP_KERNEL))) return NULL;
++ if (!(pt = kmalloc(size, GFP_KERNEL)))
++ return NULL;
+ if (oldpt && oldsize) {
+ memcpy(pt, oldpt, oldsize);
+ kfree(oldpt);
+@@ -90,21 +91,20 @@ void *drm_realloc(void *oldpt, size_t ol
+ unsigned long drm_alloc_pages(int order, int area)
+ {
+ unsigned long address;
+- unsigned long bytes = PAGE_SIZE << order;
++ unsigned long bytes = PAGE_SIZE << order;
+ unsigned long addr;
+- unsigned int sz;
++ unsigned int sz;
+
+ address = __get_free_pages(GFP_KERNEL, order);
+- if (!address)
++ if (!address)
+ return 0;
+
+- /* Zero */
++ /* Zero */
+ memset((void *)address, 0, bytes);
+
+- /* Reserve */
++ /* Reserve */
+ for (addr = address, sz = bytes;
+- sz > 0;
+- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
++ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ SetPageReserved(virt_to_page(addr));
+ }
+
+@@ -113,7 +113,7 @@ unsigned long drm_alloc_pages(int order,
+
+ /**
+ * Free pages.
+- *
++ *
+ * \param address address of the pages to free.
+ * \param order size order.
+ * \param area memory area. (Not used.)
+@@ -124,49 +124,51 @@ void drm_free_pages(unsigned long addres
+ {
+ unsigned long bytes = PAGE_SIZE << order;
+ unsigned long addr;
+- unsigned int sz;
++ unsigned int sz;
+
+- if (!address)
++ if (!address)
+ return;
+
+ /* Unreserve */
+ for (addr = address, sz = bytes;
+- sz > 0;
+- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
++ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ }
+
+ free_pages(address, order);
+ }
+
+-
+ #if __OS_HAS_AGP
+ /** Wrapper around agp_allocate_memory() */
+-DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type)
++DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
+ {
+ return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
+ }
++
+ EXPORT_SYMBOL(drm_alloc_agp);
+
+ /** Wrapper around agp_free_memory() */
+-int drm_free_agp(DRM_AGP_MEM *handle, int pages)
++int drm_free_agp(DRM_AGP_MEM * handle, int pages)
+ {
+ return drm_agp_free_memory(handle) ? 0 : -EINVAL;
+ }
++
+ EXPORT_SYMBOL(drm_free_agp);
+
+ /** Wrapper around agp_bind_memory() */
+-int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start)
++int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+ {
+ return drm_agp_bind_memory(handle, start);
+ }
++
+ EXPORT_SYMBOL(drm_bind_agp);
+
+ /** Wrapper around agp_unbind_memory() */
+-int drm_unbind_agp(DRM_AGP_MEM *handle)
++int drm_unbind_agp(DRM_AGP_MEM * handle)
+ {
+ return drm_agp_unbind_memory(handle);
+ }
++
+ EXPORT_SYMBOL(drm_unbind_agp);
+-#endif /* agp */
+-#endif /* debug_memory */
++#endif /* agp */
++#endif /* debug_memory */
+diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
+--- a/drivers/char/drm/drm_memory.h
++++ b/drivers/char/drm/drm_memory.h
+@@ -1,12 +1,12 @@
+-/**
+- * \file drm_memory.h
++/**
++ * \file drm_memory.h
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+
+-/*
++/*
+ * Created: Thu Feb 4 14:00:34 1999 by faith at valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+@@ -40,7 +40,7 @@
+
+ /**
+ * Cut down version of drm_memory_debug.h, which used to be called
+- * drm_memory.h.
++ * drm_memory.h.
+ */
+
+ #if __OS_HAS_AGP
+@@ -60,8 +60,8 @@
+ /*
+ * Find the drm_map that covers the range [offset, offset+size).
+ */
+-static inline drm_map_t *
+-drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev)
++static inline drm_map_t *drm_lookup_map(unsigned long offset,
++ unsigned long size, drm_device_t * dev)
+ {
+ struct list_head *list;
+ drm_map_list_t *r_list;
+@@ -72,16 +72,18 @@ drm_lookup_map (unsigned long offset, un
+ map = r_list->map;
+ if (!map)
+ continue;
+- if (map->offset <= offset && (offset + size) <= (map->offset + map->size))
++ if (map->offset <= offset
++ && (offset + size) <= (map->offset + map->size))
+ return map;
+ }
+ return NULL;
+ }
+
+-static inline void *
+-agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
++static inline void *agp_remap(unsigned long offset, unsigned long size,
++ drm_device_t * dev)
+ {
+- unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE;
++ unsigned long *phys_addr_map, i, num_pages =
++ PAGE_ALIGN(size) / PAGE_SIZE;
+ struct drm_agp_mem *agpmem;
+ struct page **page_map;
+ void *addr;
+@@ -94,7 +96,8 @@ agp_remap (unsigned long offset, unsigne
+
+ for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+ if (agpmem->bound <= offset
+- && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size))
++ && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
++ (offset + size))
+ break;
+ if (!agpmem)
+ return NULL;
+@@ -109,7 +112,8 @@ agp_remap (unsigned long offset, unsigne
+ if (!page_map)
+ return NULL;
+
+- phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
++ phys_addr_map =
++ agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+ for (i = 0; i < num_pages; ++i)
+ page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+ addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
+@@ -118,36 +122,38 @@ agp_remap (unsigned long offset, unsigne
+ return addr;
+ }
+
+-static inline unsigned long
+-drm_follow_page (void *vaddr)
++static inline unsigned long drm_follow_page(void *vaddr)
+ {
+- pgd_t *pgd = pgd_offset_k((unsigned long) vaddr);
+- pud_t *pud = pud_offset(pgd, (unsigned long) vaddr);
+- pmd_t *pmd = pmd_offset(pud, (unsigned long) vaddr);
+- pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr);
++ pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
++ pud_t *pud = pud_offset(pgd, (unsigned long)vaddr);
++ pmd_t *pmd = pmd_offset(pud, (unsigned long)vaddr);
++ pte_t *ptep = pte_offset_kernel(pmd, (unsigned long)vaddr);
+ return pte_pfn(*ptep) << PAGE_SHIFT;
+ }
+
+-#else /* __OS_HAS_AGP */
++#else /* __OS_HAS_AGP */
+
+-static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev)
++static inline drm_map_t *drm_lookup_map(unsigned long offset,
++ unsigned long size, drm_device_t * dev)
+ {
+- return NULL;
++ return NULL;
+ }
+
+-static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev)
++static inline void *agp_remap(unsigned long offset, unsigned long size,
++ drm_device_t * dev)
+ {
+- return NULL;
++ return NULL;
+ }
+
+-static inline unsigned long drm_follow_page (void *vaddr)
++static inline unsigned long drm_follow_page(void *vaddr)
+ {
+- return 0;
++ return 0;
+ }
+
+ #endif
+
+-static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
++static inline void *drm_ioremap(unsigned long offset, unsigned long size,
++ drm_device_t * dev)
+ {
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+@@ -158,8 +164,8 @@ static inline void *drm_ioremap(unsigned
+ return ioremap(offset, size);
+ }
+
+-static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
+- drm_device_t *dev)
++static inline void *drm_ioremap_nocache(unsigned long offset,
++ unsigned long size, drm_device_t * dev)
+ {
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+@@ -170,7 +176,8 @@ static inline void *drm_ioremap_nocache(
+ return ioremap_nocache(offset, size);
+ }
+
+-static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
++static inline void drm_ioremapfree(void *pt, unsigned long size,
++ drm_device_t * dev)
+ {
+ /*
+ * This is a bit ugly. It would be much cleaner if the DRM API would use separate
+@@ -178,12 +185,12 @@ static inline void drm_ioremapfree(void
+ * a future revision of the interface...
+ */
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
+- && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
+- {
++ && ((unsigned long)pt >= VMALLOC_START
++ && (unsigned long)pt < VMALLOC_END)) {
+ unsigned long offset;
+ drm_map_t *map;
+
+- offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK);
++ offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
+ map = drm_lookup_map(offset, size, dev);
+ if (map && map->type == _DRM_AGP) {
+ vunmap(pt);
+@@ -193,5 +200,3 @@ static inline void drm_ioremapfree(void
+
+ iounmap(pt);
+ }
+-
+-
+diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
+--- a/drivers/char/drm/drm_memory_debug.h
++++ b/drivers/char/drm/drm_memory_debug.h
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_memory.h
++ * \file drm_memory.h
+ * Memory management wrappers for DRM.
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -35,75 +35,75 @@
+ #include "drmP.h"
+
+ typedef struct drm_mem_stats {
+- const char *name;
+- int succeed_count;
+- int free_count;
+- int fail_count;
+- unsigned long bytes_allocated;
+- unsigned long bytes_freed;
++ const char *name;
++ int succeed_count;
++ int free_count;
++ int fail_count;
++ unsigned long bytes_allocated;
++ unsigned long bytes_freed;
+ } drm_mem_stats_t;
+
+ static DEFINE_SPINLOCK(DRM(mem_lock));
+-static unsigned long DRM(ram_available) = 0; /* In pages */
+-static unsigned long DRM(ram_used) = 0;
+-static drm_mem_stats_t DRM(mem_stats)[] = {
+- [DRM_MEM_DMA] = { "dmabufs" },
+- [DRM_MEM_SAREA] = { "sareas" },
+- [DRM_MEM_DRIVER] = { "driver" },
+- [DRM_MEM_MAGIC] = { "magic" },
+- [DRM_MEM_IOCTLS] = { "ioctltab" },
+- [DRM_MEM_MAPS] = { "maplist" },
+- [DRM_MEM_VMAS] = { "vmalist" },
+- [DRM_MEM_BUFS] = { "buflist" },
+- [DRM_MEM_SEGS] = { "seglist" },
+- [DRM_MEM_PAGES] = { "pagelist" },
+- [DRM_MEM_FILES] = { "files" },
+- [DRM_MEM_QUEUES] = { "queues" },
+- [DRM_MEM_CMDS] = { "commands" },
+- [DRM_MEM_MAPPINGS] = { "mappings" },
+- [DRM_MEM_BUFLISTS] = { "buflists" },
+- [DRM_MEM_AGPLISTS] = { "agplist" },
+- [DRM_MEM_SGLISTS] = { "sglist" },
+- [DRM_MEM_TOTALAGP] = { "totalagp" },
+- [DRM_MEM_BOUNDAGP] = { "boundagp" },
+- [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
+- [DRM_MEM_CTXLIST] = { "ctxlist" },
+- [DRM_MEM_STUB] = { "stub" },
+- { NULL, 0, } /* Last entry must be null */
++static unsigned long DRM(ram_available) = 0; /* In pages */
++static unsigned long DRM(ram_used) = 0;
++static drm_mem_stats_t DRM(mem_stats)[] =
++{
++ [DRM_MEM_DMA] = {
++ "dmabufs"},[DRM_MEM_SAREA] = {
++ "sareas"},[DRM_MEM_DRIVER] = {
++ "driver"},[DRM_MEM_MAGIC] = {
++ "magic"},[DRM_MEM_IOCTLS] = {
++ "ioctltab"},[DRM_MEM_MAPS] = {
++ "maplist"},[DRM_MEM_VMAS] = {
++ "vmalist"},[DRM_MEM_BUFS] = {
++ "buflist"},[DRM_MEM_SEGS] = {
++ "seglist"},[DRM_MEM_PAGES] = {
++ "pagelist"},[DRM_MEM_FILES] = {
++ "files"},[DRM_MEM_QUEUES] = {
++ "queues"},[DRM_MEM_CMDS] = {
++ "commands"},[DRM_MEM_MAPPINGS] = {
++ "mappings"},[DRM_MEM_BUFLISTS] = {
++ "buflists"},[DRM_MEM_AGPLISTS] = {
++ "agplist"},[DRM_MEM_SGLISTS] = {
++ "sglist"},[DRM_MEM_TOTALAGP] = {
++ "totalagp"},[DRM_MEM_BOUNDAGP] = {
++ "boundagp"},[DRM_MEM_CTXBITMAP] = {
++ "ctxbitmap"},[DRM_MEM_CTXLIST] = {
++ "ctxlist"},[DRM_MEM_STUB] = {
++ "stub"}, {
++ NULL, 0,} /* Last entry must be null */
+ };
+
+-void DRM(mem_init)(void)
+-{
++void DRM(mem_init) (void) {
+ drm_mem_stats_t *mem;
+- struct sysinfo si;
++ struct sysinfo si;
+
+ for (mem = DRM(mem_stats); mem->name; ++mem) {
+- mem->succeed_count = 0;
+- mem->free_count = 0;
+- mem->fail_count = 0;
++ mem->succeed_count = 0;
++ mem->free_count = 0;
++ mem->fail_count = 0;
+ mem->bytes_allocated = 0;
+- mem->bytes_freed = 0;
++ mem->bytes_freed = 0;
+ }
+
+ si_meminfo(&si);
+ DRM(ram_available) = si.totalram;
+- DRM(ram_used) = 0;
++ DRM(ram_used) = 0;
+ }
+
+ /* drm_mem_info is called whenever a process reads /dev/drm/mem. */
+
+-static int DRM(_mem_info)(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data)
+-{
++static int DRM(_mem_info) (char *buf, char **start, off_t offset,
++ int request, int *eof, void *data) {
+ drm_mem_stats_t *pt;
+- int len = 0;
++ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+- *eof = 0;
++ *eof = 0;
+ *start = &buf[offset];
+
+ DRM_PROC_PRINT(" total counts "
+@@ -129,24 +129,23 @@ static int DRM(_mem_info)(char *buf, cha
+ - (long)pt->bytes_freed);
+ }
+
+- if (len > request + offset) return request;
++ if (len > request + offset)
++ return request;
+ *eof = 1;
+ return len - offset;
+ }
+
+-int DRM(mem_info)(char *buf, char **start, off_t offset,
+- int len, int *eof, void *data)
+-{
++int DRM(mem_info) (char *buf, char **start, off_t offset,
++ int len, int *eof, void *data) {
+ int ret;
+
+ spin_lock(&DRM(mem_lock));
+- ret = DRM(_mem_info)(buf, start, offset, len, eof, data);
++ ret = DRM(_mem_info) (buf, start, offset, len, eof, data);
+ spin_unlock(&DRM(mem_lock));
+ return ret;
+ }
+
+-void *DRM(alloc)(size_t size, int area)
+-{
++void *DRM(alloc) (size_t size, int area) {
+ void *pt;
+
+ if (!size) {
+@@ -167,40 +166,40 @@ void *DRM(alloc)(size_t size, int area)
+ return pt;
+ }
+
+-void *DRM(calloc)(size_t nmemb, size_t size, int area)
+-{
++void *DRM(calloc) (size_t nmemb, size_t size, int area) {
+ void *addr;
+
+- addr = DRM(alloc)(nmemb * size, area);
++ addr = DRM(alloc) (nmemb * size, area);
+ if (addr != NULL)
+ memset((void *)addr, 0, size * nmemb);
+
+ return addr;
+ }
+
+-void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
+-{
++void *DRM(realloc) (void *oldpt, size_t oldsize, size_t size, int area) {
+ void *pt;
+
+- if (!(pt = DRM(alloc)(size, area))) return NULL;
++ if (!(pt = DRM(alloc) (size, area)))
++ return NULL;
+ if (oldpt && oldsize) {
+ memcpy(pt, oldpt, oldsize);
+- DRM(free)(oldpt, oldsize, area);
++ DRM(free) (oldpt, oldsize, area);
+ }
+ return pt;
+ }
+
+-void DRM(free)(void *pt, size_t size, int area)
+-{
++void DRM(free) (void *pt, size_t size, int area) {
+ int alloc_count;
+ int free_count;
+
+- if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
+- else kfree(pt);
++ if (!pt)
++ DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
++ else
++ kfree(pt);
+ spin_lock(&DRM(mem_lock));
+ DRM(mem_stats)[area].bytes_freed += size;
+- free_count = ++DRM(mem_stats)[area].free_count;
+- alloc_count = DRM(mem_stats)[area].succeed_count;
++ free_count = ++DRM(mem_stats)[area].free_count;
++ alloc_count = DRM(mem_stats)[area].succeed_count;
+ spin_unlock(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
+@@ -208,12 +207,11 @@ void DRM(free)(void *pt, size_t size, in
+ }
+ }
+
+-unsigned long DRM(alloc_pages)(int order, int area)
+-{
++unsigned long DRM(alloc_pages) (int order, int area) {
+ unsigned long address;
+- unsigned long bytes = PAGE_SIZE << order;
++ unsigned long bytes = PAGE_SIZE << order;
+ unsigned long addr;
+- unsigned int sz;
++ unsigned int sz;
+
+ spin_lock(&DRM(mem_lock));
+ if ((DRM(ram_used) >> PAGE_SHIFT)
+@@ -233,48 +231,44 @@ unsigned long DRM(alloc_pages)(int order
+ spin_lock(&DRM(mem_lock));
+ ++DRM(mem_stats)[area].succeed_count;
+ DRM(mem_stats)[area].bytes_allocated += bytes;
+- DRM(ram_used) += bytes;
++ DRM(ram_used) += bytes;
+ spin_unlock(&DRM(mem_lock));
+
+-
+- /* Zero outside the lock */
++ /* Zero outside the lock */
+ memset((void *)address, 0, bytes);
+
+- /* Reserve */
++ /* Reserve */
+ for (addr = address, sz = bytes;
+- sz > 0;
+- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
++ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ SetPageReserved(virt_to_page(addr));
+ }
+
+ return address;
+ }
+
+-void DRM(free_pages)(unsigned long address, int order, int area)
+-{
++void DRM(free_pages) (unsigned long address, int order, int area) {
+ unsigned long bytes = PAGE_SIZE << order;
+- int alloc_count;
+- int free_count;
++ int alloc_count;
++ int free_count;
+ unsigned long addr;
+- unsigned int sz;
++ unsigned int sz;
+
+ if (!address) {
+ DRM_MEM_ERROR(area, "Attempt to free address 0\n");
+ } else {
+- /* Unreserve */
++ /* Unreserve */
+ for (addr = address, sz = bytes;
+- sz > 0;
+- addr += PAGE_SIZE, sz -= PAGE_SIZE) {
++ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ }
+ free_pages(address, order);
+ }
+
+ spin_lock(&DRM(mem_lock));
+- free_count = ++DRM(mem_stats)[area].free_count;
+- alloc_count = DRM(mem_stats)[area].succeed_count;
++ free_count = ++DRM(mem_stats)[area].free_count;
++ alloc_count = DRM(mem_stats)[area].succeed_count;
+ DRM(mem_stats)[area].bytes_freed += bytes;
+- DRM(ram_used) -= bytes;
++ DRM(ram_used) -= bytes;
+ spin_unlock(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(area,
+@@ -283,8 +277,8 @@ void DRM(free_pages)(unsigned long addre
+ }
+ }
+
+-void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
+-{
++void *DRM(ioremap) (unsigned long offset, unsigned long size,
++ drm_device_t * dev) {
+ void *pt;
+
+ if (!size) {
+@@ -306,8 +300,8 @@ void *DRM(ioremap)(unsigned long offset,
+ return pt;
+ }
+
+-void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev)
+-{
++void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,
++ drm_device_t * dev) {
+ void *pt;
+
+ if (!size) {
+@@ -329,8 +323,7 @@ void *DRM(ioremap_nocache)(unsigned long
+ return pt;
+ }
+
+-void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
+-{
++void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {
+ int alloc_count;
+ int free_count;
+
+@@ -342,8 +335,8 @@ void DRM(ioremapfree)(void *pt, unsigned
+
+ spin_lock(&DRM(mem_lock));
+ DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
+- free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
+- alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
++ free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
++ alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
+ spin_unlock(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+@@ -354,8 +347,7 @@ void DRM(ioremapfree)(void *pt, unsigned
+
+ #if __OS_HAS_AGP
+
+-DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
+-{
++DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) {
+ DRM_AGP_MEM *handle;
+
+ if (!pages) {
+@@ -363,11 +355,11 @@ DRM_AGP_MEM *DRM(alloc_agp)(int pages, u
+ return NULL;
+ }
+
+- if ((handle = DRM(agp_allocate_memory)(pages, type))) {
++ if ((handle = DRM(agp_allocate_memory) (pages, type))) {
+ spin_lock(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
+ DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
+- += pages << PAGE_SHIFT;
++ += pages << PAGE_SHIFT;
+ spin_unlock(&DRM(mem_lock));
+ return handle;
+ }
+@@ -377,11 +369,10 @@ DRM_AGP_MEM *DRM(alloc_agp)(int pages, u
+ return NULL;
+ }
+
+-int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
+-{
+- int alloc_count;
+- int free_count;
+- int retval = -EINVAL;
++int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
++ int alloc_count;
++ int free_count;
++ int retval = -EINVAL;
+
+ if (!handle) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+@@ -389,12 +380,12 @@ int DRM(free_agp)(DRM_AGP_MEM *handle, i
+ return retval;
+ }
+
+- if (DRM(agp_free_memory)(handle)) {
++ if (DRM(agp_free_memory) (handle)) {
+ spin_lock(&DRM(mem_lock));
+- free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
+- alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
++ free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
++ alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
+ DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
+- += pages << PAGE_SHIFT;
++ += pages << PAGE_SHIFT;
+ spin_unlock(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+@@ -406,8 +397,7 @@ int DRM(free_agp)(DRM_AGP_MEM *handle, i
+ return retval;
+ }
+
+-int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
+-{
++int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) {
+ int retcode = -EINVAL;
+
+ if (!handle) {
+@@ -416,11 +406,11 @@ int DRM(bind_agp)(DRM_AGP_MEM *handle, u
+ return retcode;
+ }
+
+- if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
++ if (!(retcode = DRM(agp_bind_memory) (handle, start))) {
+ spin_lock(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
+ DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
+- += handle->page_count << PAGE_SHIFT;
++ += handle->page_count << PAGE_SHIFT;
+ spin_unlock(&DRM(mem_lock));
+ return retcode;
+ }
+@@ -430,8 +420,7 @@ int DRM(bind_agp)(DRM_AGP_MEM *handle, u
+ return retcode;
+ }
+
+-int DRM(unbind_agp)(DRM_AGP_MEM *handle)
+-{
++int DRM(unbind_agp) (DRM_AGP_MEM * handle) {
+ int alloc_count;
+ int free_count;
+ int retcode = -EINVAL;
+@@ -442,12 +431,13 @@ int DRM(unbind_agp)(DRM_AGP_MEM *handle)
+ return retcode;
+ }
+
+- if ((retcode = DRM(agp_unbind_memory)(handle))) return retcode;
++ if ((retcode = DRM(agp_unbind_memory) (handle)))
++ return retcode;
+ spin_lock(&DRM(mem_lock));
+- free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
++ free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
+ alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
+ DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
+- += handle->page_count << PAGE_SHIFT;
++ += handle->page_count << PAGE_SHIFT;
+ spin_unlock(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
+--- a/drivers/char/drm/drm_os_linux.h
++++ b/drivers/char/drm/drm_os_linux.h
+@@ -3,7 +3,6 @@
+ * OS abstraction macros.
+ */
+
+-
+ #include <linux/interrupt.h> /* For task queue support */
+ #include <linux/delay.h>
+
+@@ -47,25 +46,25 @@
+ #else
+ /* define some dummy types for non AGP supporting kernels */
+ struct no_agp_kern {
+- unsigned long aper_base;
+- unsigned long aper_size;
++ unsigned long aper_base;
++ unsigned long aper_size;
+ };
+ #define DRM_AGP_MEM int
+ #define DRM_AGP_KERN struct no_agp_kern
+ #endif
+
+ #if !(__OS_HAS_MTRR)
+-static __inline__ int mtrr_add (unsigned long base, unsigned long size,
+- unsigned int type, char increment)
++static __inline__ int mtrr_add(unsigned long base, unsigned long size,
++ unsigned int type, char increment)
+ {
+ return -ENODEV;
+ }
+
+-static __inline__ int mtrr_del (int reg, unsigned long base,
+- unsigned long size)
++static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
+ {
+ return -ENODEV;
+ }
++
+ #define MTRR_TYPE_WRCOMB 1
+
+ #endif
+@@ -99,7 +98,7 @@ static __inline__ int mtrr_del (int reg,
+
+ #define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
+
+-/**
++/**
+ * Get the pointer to the SAREA.
+ *
+ * Searches the SAREA on the mapping lists and points drm_device::sarea to it.
+@@ -143,7 +142,5 @@ do { \
+ remove_wait_queue(&(queue), &entry); \
+ } while (0)
+
+-
+ #define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
+ #define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
+-
+diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
+--- a/drivers/char/drm/drm_pci.c
++++ b/drivers/char/drm/drm_pci.c
+@@ -77,7 +77,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_devi
+ dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
+ if (!dmah)
+ return NULL;
+-
++
+ dmah->size = size;
+ dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
+
+@@ -106,6 +106,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_devi
+
+ return dmah;
+ }
++
+ EXPORT_SYMBOL(drm_pci_alloc);
+
+ /**
+@@ -113,8 +114,7 @@ EXPORT_SYMBOL(drm_pci_alloc);
+ *
+ * This function is for internal use in the Linux-specific DRM core code.
+ */
+-void
+-__drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
++void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+ {
+ #ifdef DRM_DEBUG_MEMORY
+ int area = DRM_MEM_DMA;
+@@ -150,12 +150,12 @@ __drm_pci_free(drm_device_t * dev, drm_d
+ /**
+ * \brief Free a PCI consistent memory block
+ */
+-void
+-drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
++void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
+ {
+ __drm_pci_free(dev, dmah);
+ kfree(dmah);
+ }
++
+ EXPORT_SYMBOL(drm_pci_free);
+
+ /*@}*/
+diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
+--- a/drivers/char/drm/drm_pciids.h
++++ b/drivers/char/drm/drm_pciids.h
+@@ -234,4 +234,3 @@
+ {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0, 0, 0}
+-
+diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
+--- a/drivers/char/drm/drm_proc.c
++++ b/drivers/char/drm/drm_proc.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_proc.h
++ * \file drm_proc.c
+ * /proc support for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+@@ -39,19 +39,19 @@
+
+ #include "drmP.h"
+
+-static int drm_name_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data);
+-static int drm_vm_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data);
+-static int drm_clients_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data);
+-static int drm_queues_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data);
+-static int drm_bufs_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data);
++static int drm_name_info(char *buf, char **start, off_t offset,
++ int request, int *eof, void *data);
++static int drm_vm_info(char *buf, char **start, off_t offset,
++ int request, int *eof, void *data);
++static int drm_clients_info(char *buf, char **start, off_t offset,
++ int request, int *eof, void *data);
++static int drm_queues_info(char *buf, char **start, off_t offset,
++ int request, int *eof, void *data);
++static int drm_bufs_info(char *buf, char **start, off_t offset,
++ int request, int *eof, void *data);
+ #if DRM_DEBUG_CODE
+-static int drm_vma_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data);
++static int drm_vma_info(char *buf, char **start, off_t offset,
++ int request, int *eof, void *data);
+ #endif
+
+ /**
+@@ -59,18 +59,21 @@ static int drm_vma_info(char *buf, ch
+ */
+ static struct drm_proc_list {
+ const char *name; /**< file name */
+- int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/
++ int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/
+ } drm_proc_list[] = {
+- { "name", drm_name_info },
+- { "mem", drm_mem_info },
+- { "vm", drm_vm_info },
+- { "clients", drm_clients_info },
+- { "queues", drm_queues_info },
+- { "bufs", drm_bufs_info },
++ {
++ "name", drm_name_info}, {
++ "mem", drm_mem_info}, {
++ "vm", drm_vm_info}, {
++ "clients", drm_clients_info}, {
++ "queues", drm_queues_info}, {
++ "bufs", drm_bufs_info},
+ #if DRM_DEBUG_CODE
+- { "vma", drm_vma_info },
++ {
++ "vma", drm_vma_info},
+ #endif
+ };
++
+ #define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
+
+ /**
+@@ -81,18 +84,17 @@ static struct drm_proc_list {
+ * \param root DRI proc dir entry.
+ * \param dev_root resulting DRI device proc dir entry.
+ * \return root entry pointer on success, or NULL on failure.
+- *
++ *
+ * Create the DRI proc root entry "/proc/dri", the device proc root entry
+ * "/proc/dri/%minor%/", and each entry in proc_list as
+ * "/proc/dri/%minor%/%name%".
+ */
+-int drm_proc_init(drm_device_t *dev, int minor,
+- struct proc_dir_entry *root,
+- struct proc_dir_entry **dev_root)
++int drm_proc_init(drm_device_t * dev, int minor,
++ struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
+ {
+ struct proc_dir_entry *ent;
+- int i, j;
+- char name[64];
++ int i, j;
++ char name[64];
+
+ sprintf(name, "%d", minor);
+ *dev_root = proc_mkdir(name, root);
+@@ -103,7 +105,7 @@ int drm_proc_init(drm_device_t *dev, int
+
+ for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+ ent = create_proc_entry(drm_proc_list[i].name,
+- S_IFREG|S_IRUGO, *dev_root);
++ S_IFREG | S_IRUGO, *dev_root);
+ if (!ent) {
+ DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
+ name, drm_proc_list[i].name);
+@@ -114,13 +116,12 @@ int drm_proc_init(drm_device_t *dev, int
+ return -1;
+ }
+ ent->read_proc = drm_proc_list[i].f;
+- ent->data = dev;
++ ent->data = dev;
+ }
+
+ return 0;
+ }
+
+-
+ /**
+ * Cleanup the proc filesystem resources.
+ *
+@@ -132,12 +133,13 @@ int drm_proc_init(drm_device_t *dev, int
+ * Remove all proc entries created by proc_init().
+ */
+ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
+- struct proc_dir_entry *dev_root)
++ struct proc_dir_entry *dev_root)
+ {
+- int i;
++ int i;
+ char name[64];
+
+- if (!root || !dev_root) return 0;
++ if (!root || !dev_root)
++ return 0;
+
+ for (i = 0; i < DRM_PROC_ENTRIES; i++)
+ remove_proc_entry(drm_proc_list[i].name, dev_root);
+@@ -149,7 +151,7 @@ int drm_proc_cleanup(int minor, struct p
+
+ /**
+ * Called when "/proc/dri/.../name" is read.
+- *
++ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+@@ -157,14 +159,14 @@ int drm_proc_cleanup(int minor, struct p
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+- *
++ *
+ * Prints the device name together with the bus id if available.
+ */
+ static int drm_name_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int len = 0;
++ drm_device_t *dev = (drm_device_t *) data;
++ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+@@ -172,23 +174,26 @@ static int drm_name_info(char *buf, char
+ }
+
+ *start = &buf[offset];
+- *eof = 0;
++ *eof = 0;
+
+ if (dev->unique) {
+ DRM_PROC_PRINT("%s %s %s\n",
+- dev->driver->pci_driver.name, pci_name(dev->pdev), dev->unique);
++ dev->driver->pci_driver.name,
++ pci_name(dev->pdev), dev->unique);
+ } else {
+- DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev));
++ DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
++ pci_name(dev->pdev));
+ }
+
+- if (len > request + offset) return request;
++ if (len > request + offset)
++ return request;
+ *eof = 1;
+ return len - offset;
+ }
+
+ /**
+ * Called when "/proc/dri/.../vm" is read.
+- *
++ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+@@ -196,24 +201,24 @@ static int drm_name_info(char *buf, char
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+- *
++ *
+ * Prints information about all mappings in drm_device::maplist.
+ */
+ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int len = 0;
+- drm_map_t *map;
++ drm_device_t *dev = (drm_device_t *) data;
++ int len = 0;
++ drm_map_t *map;
+ drm_map_list_t *r_list;
+ struct list_head *list;
+
+- /* Hardcoded from _DRM_FRAME_BUFFER,
+- _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
+- _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+- const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
+- const char *type;
+- int i;
++ /* Hardcoded from _DRM_FRAME_BUFFER,
++ _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
++ _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
++ const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
++ const char *type;
++ int i;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+@@ -221,36 +226,35 @@ static int drm__vm_info(char *buf, char
+ }
+
+ *start = &buf[offset];
+- *eof = 0;
++ *eof = 0;
+
+ DRM_PROC_PRINT("slot offset size type flags "
+ "address mtrr\n\n");
+ i = 0;
+- if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
++ if (dev->maplist != NULL)
++ list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+ map = r_list->map;
+- if(!map)
++ if (!map)
+ continue;
+ if (map->type < 0 || map->type > 5)
+ type = "??";
+- else
++ else
+ type = types[map->type];
+ DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ",
+ i,
+ map->offset,
+- map->size,
+- type,
+- map->flags,
+- r_list->user_token);
++ map->size, type, map->flags, r_list->user_token);
+ if (map->mtrr < 0) {
+ DRM_PROC_PRINT("none\n");
+ } else {
+ DRM_PROC_PRINT("%4d\n", map->mtrr);
+ }
+ i++;
+- }
++ }
+
+- if (len > request + offset) return request;
++ if (len > request + offset)
++ return request;
+ *eof = 1;
+ return len - offset;
+ }
+@@ -259,10 +263,10 @@ static int drm__vm_info(char *buf, char
+ * Simply calls _vm_info() while holding the drm_device::struct_sem lock.
+ */
+ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int ret;
++ drm_device_t *dev = (drm_device_t *) data;
++ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm__vm_info(buf, start, offset, request, eof, data);
+@@ -272,7 +276,7 @@ static int drm_vm_info(char *buf, char *
+
+ /**
+ * Called when "/proc/dri/.../queues" is read.
+- *
++ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+@@ -282,12 +286,12 @@ static int drm_vm_info(char *buf, char *
+ * \return number of written bytes.
+ */
+ static int drm__queues_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data)
++ int request, int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int len = 0;
+- int i;
+- drm_queue_t *q;
++ drm_device_t *dev = (drm_device_t *) data;
++ int len = 0;
++ int i;
++ drm_queue_t *q;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+@@ -295,7 +299,7 @@ static int drm__queues_info(char *buf, c
+ }
+
+ *start = &buf[offset];
+- *eof = 0;
++ *eof = 0;
+
+ DRM_PROC_PRINT(" ctx/flags use fin"
+ " blk/rw/rwf wait flushed queued"
+@@ -313,14 +317,17 @@ static int drm__queues_info(char *buf, c
+ atomic_read(&q->block_count),
+ atomic_read(&q->block_read) ? 'r' : '-',
+ atomic_read(&q->block_write) ? 'w' : '-',
+- waitqueue_active(&q->read_queue) ? 'r':'-',
+- waitqueue_active(&q->write_queue) ? 'w':'-',
+- waitqueue_active(&q->flush_queue) ? 'f':'-',
++ waitqueue_active(&q->read_queue) ? 'r' : '-',
++ waitqueue_active(&q->
++ write_queue) ? 'w' : '-',
++ waitqueue_active(&q->
++ flush_queue) ? 'f' : '-',
+ DRM_BUFCOUNT(&q->waitlist));
+ atomic_dec(&q->use_count);
+ }
+
+- if (len > request + offset) return request;
++ if (len > request + offset)
++ return request;
+ *eof = 1;
+ return len - offset;
+ }
+@@ -329,10 +336,10 @@ static int drm__queues_info(char *buf, c
+ * Simply calls _queues_info() while holding the drm_device::struct_sem lock.
+ */
+ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int ret;
++ drm_device_t *dev = (drm_device_t *) data;
++ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm__queues_info(buf, start, offset, request, eof, data);
+@@ -342,7 +349,7 @@ static int drm_queues_info(char *buf, ch
+
+ /**
+ * Called when "/proc/dri/.../bufs" is read.
+- *
++ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+@@ -352,12 +359,12 @@ static int drm_queues_info(char *buf, ch
+ * \return number of written bytes.
+ */
+ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int len = 0;
++ drm_device_t *dev = (drm_device_t *) data;
++ int len = 0;
+ drm_device_dma_t *dma = dev->dma;
+- int i;
++ int i;
+
+ if (!dma || offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+@@ -365,7 +372,7 @@ static int drm__bufs_info(char *buf, cha
+ }
+
+ *start = &buf[offset];
+- *eof = 0;
++ *eof = 0;
+
+ DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
+ for (i = 0; i <= DRM_MAX_ORDER; i++) {
+@@ -378,19 +385,21 @@ static int drm__bufs_info(char *buf, cha
+ .freelist.count),
+ dma->bufs[i].seg_count,
+ dma->bufs[i].seg_count
+- *(1 << dma->bufs[i].page_order),
++ * (1 << dma->bufs[i].page_order),
+ (dma->bufs[i].seg_count
+ * (1 << dma->bufs[i].page_order))
+ * PAGE_SIZE / 1024);
+ }
+ DRM_PROC_PRINT("\n");
+ for (i = 0; i < dma->buf_count; i++) {
+- if (i && !(i%32)) DRM_PROC_PRINT("\n");
++ if (i && !(i % 32))
++ DRM_PROC_PRINT("\n");
+ DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
+ }
+ DRM_PROC_PRINT("\n");
+
+- if (len > request + offset) return request;
++ if (len > request + offset)
++ return request;
+ *eof = 1;
+ return len - offset;
+ }
+@@ -399,10 +408,10 @@ static int drm__bufs_info(char *buf, cha
+ * Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
+ */
+ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int ret;
++ drm_device_t *dev = (drm_device_t *) data;
++ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm__bufs_info(buf, start, offset, request, eof, data);
+@@ -412,7 +421,7 @@ static int drm_bufs_info(char *buf, char
+
+ /**
+ * Called when "/proc/dri/.../clients" is read.
+- *
++ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+@@ -422,11 +431,11 @@ static int drm_bufs_info(char *buf, char
+ * \return number of written bytes.
+ */
+ static int drm__clients_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data)
++ int request, int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int len = 0;
+- drm_file_t *priv;
++ drm_device_t *dev = (drm_device_t *) data;
++ int len = 0;
++ drm_file_t *priv;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+@@ -434,7 +443,7 @@ static int drm__clients_info(char *buf,
+ }
+
+ *start = &buf[offset];
+- *eof = 0;
++ *eof = 0;
+
+ DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
+ for (priv = dev->file_first; priv; priv = priv->next) {
+@@ -442,12 +451,11 @@ static int drm__clients_info(char *buf,
+ priv->authenticated ? 'y' : 'n',
+ priv->minor,
+ priv->pid,
+- priv->uid,
+- priv->magic,
+- priv->ioctl_count);
++ priv->uid, priv->magic, priv->ioctl_count);
+ }
+
+- if (len > request + offset) return request;
++ if (len > request + offset)
++ return request;
+ *eof = 1;
+ return len - offset;
+ }
+@@ -456,10 +464,10 @@ static int drm__clients_info(char *buf,
+ * Simply calls _clients_info() while holding the drm_device::struct_sem lock.
+ */
+ static int drm_clients_info(char *buf, char **start, off_t offset,
+- int request, int *eof, void *data)
++ int request, int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int ret;
++ drm_device_t *dev = (drm_device_t *) data;
++ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm__clients_info(buf, start, offset, request, eof, data);
+@@ -470,14 +478,14 @@ static int drm_clients_info(char *buf, c
+ #if DRM_DEBUG_CODE
+
+ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int len = 0;
+- drm_vma_entry_t *pt;
++ drm_device_t *dev = (drm_device_t *) data;
++ int len = 0;
++ drm_vma_entry_t *pt;
+ struct vm_area_struct *vma;
+ #if defined(__i386__)
+- unsigned int pgprot;
++ unsigned int pgprot;
+ #endif
+
+ if (offset > DRM_PROC_LIMIT) {
+@@ -486,51 +494,53 @@ static int drm__vma_info(char *buf, char
+ }
+
+ *start = &buf[offset];
+- *eof = 0;
++ *eof = 0;
+
+ DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
+ atomic_read(&dev->vma_count),
+ high_memory, virt_to_phys(high_memory));
+ for (pt = dev->vmalist; pt; pt = pt->next) {
+- if (!(vma = pt->vma)) continue;
++ if (!(vma = pt->vma))
++ continue;
+ DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
+ pt->pid,
+ vma->vm_start,
+ vma->vm_end,
+- vma->vm_flags & VM_READ ? 'r' : '-',
+- vma->vm_flags & VM_WRITE ? 'w' : '-',
+- vma->vm_flags & VM_EXEC ? 'x' : '-',
++ vma->vm_flags & VM_READ ? 'r' : '-',
++ vma->vm_flags & VM_WRITE ? 'w' : '-',
++ vma->vm_flags & VM_EXEC ? 'x' : '-',
+ vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
+- vma->vm_flags & VM_LOCKED ? 'l' : '-',
+- vma->vm_flags & VM_IO ? 'i' : '-',
++ vma->vm_flags & VM_LOCKED ? 'l' : '-',
++ vma->vm_flags & VM_IO ? 'i' : '-',
+ VM_OFFSET(vma));
+
+ #if defined(__i386__)
+ pgprot = pgprot_val(vma->vm_page_prot);
+ DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
+- pgprot & _PAGE_PRESENT ? 'p' : '-',
+- pgprot & _PAGE_RW ? 'w' : 'r',
+- pgprot & _PAGE_USER ? 'u' : 's',
+- pgprot & _PAGE_PWT ? 't' : 'b',
+- pgprot & _PAGE_PCD ? 'u' : 'c',
++ pgprot & _PAGE_PRESENT ? 'p' : '-',
++ pgprot & _PAGE_RW ? 'w' : 'r',
++ pgprot & _PAGE_USER ? 'u' : 's',
++ pgprot & _PAGE_PWT ? 't' : 'b',
++ pgprot & _PAGE_PCD ? 'u' : 'c',
+ pgprot & _PAGE_ACCESSED ? 'a' : '-',
+- pgprot & _PAGE_DIRTY ? 'd' : '-',
+- pgprot & _PAGE_PSE ? 'm' : 'k',
+- pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
++ pgprot & _PAGE_DIRTY ? 'd' : '-',
++ pgprot & _PAGE_PSE ? 'm' : 'k',
++ pgprot & _PAGE_GLOBAL ? 'g' : 'l');
+ #endif
+ DRM_PROC_PRINT("\n");
+ }
+
+- if (len > request + offset) return request;
++ if (len > request + offset)
++ return request;
+ *eof = 1;
+ return len - offset;
+ }
+
+ static int drm_vma_info(char *buf, char **start, off_t offset, int request,
+- int *eof, void *data)
++ int *eof, void *data)
+ {
+- drm_device_t *dev = (drm_device_t *)data;
+- int ret;
++ drm_device_t *dev = (drm_device_t *) data;
++ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm__vma_info(buf, start, offset, request, eof, data);
+@@ -538,5 +548,3 @@ static int drm_vma_info(char *buf, char
+ return ret;
+ }
+ #endif
+-
+-
+diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
+--- a/drivers/char/drm/drm_sarea.h
++++ b/drivers/char/drm/drm_sarea.h
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_sarea.h
++ * \file drm_sarea.h
+ * \brief SAREA definitions
+ *
+ * \author Michel Dänzer <michel at daenzer.net>
+@@ -38,7 +38,7 @@
+ #if defined(__alpha__)
+ #define SAREA_MAX 0x2000
+ #elif defined(__ia64__)
+-#define SAREA_MAX 0x10000 /* 64kB */
++#define SAREA_MAX 0x10000 /* 64kB */
+ #else
+ /* Intel 830M driver needs at least 8k SAREA */
+ #define SAREA_MAX 0x2000
+@@ -51,28 +51,28 @@
+
+ /** SAREA drawable */
+ typedef struct drm_sarea_drawable {
+- unsigned int stamp;
+- unsigned int flags;
++ unsigned int stamp;
++ unsigned int flags;
+ } drm_sarea_drawable_t;
+
+ /** SAREA frame */
+ typedef struct drm_sarea_frame {
+- unsigned int x;
+- unsigned int y;
+- unsigned int width;
+- unsigned int height;
+- unsigned int fullscreen;
++ unsigned int x;
++ unsigned int y;
++ unsigned int width;
++ unsigned int height;
++ unsigned int fullscreen;
+ } drm_sarea_frame_t;
+
+ /** SAREA */
+ typedef struct drm_sarea {
+ /** first thing is always the DRM locking structure */
+- drm_hw_lock_t lock;
++ drm_hw_lock_t lock;
+ /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
+- drm_hw_lock_t drawable_lock;
+- drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
+- drm_sarea_frame_t frame; /**< frame */
+- drm_context_t dummy_context;
++ drm_hw_lock_t drawable_lock;
++ drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
++ drm_sarea_frame_t frame; /**< frame */
++ drm_context_t dummy_context;
+ } drm_sarea_t;
+
+-#endif /* _DRM_SAREA_H_ */
++#endif /* _DRM_SAREA_H_ */
+diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
+--- a/drivers/char/drm/drm_scatter.c
++++ b/drivers/char/drm/drm_scatter.c
+@@ -1,5 +1,5 @@
+ /**
+- * \file drm_scatter.h
++ * \file drm_scatter.c
+ * IOCTLs to manage scatter/gather memory
+ *
+ * \author Gareth Hughes <gareth at valinux.com>
+@@ -37,28 +37,24 @@
+
+ #define DEBUG_SCATTER 0
+
+-void drm_sg_cleanup( drm_sg_mem_t *entry )
++void drm_sg_cleanup(drm_sg_mem_t * entry)
+ {
+ struct page *page;
+ int i;
+
+- for ( i = 0 ; i < entry->pages ; i++ ) {
++ for (i = 0; i < entry->pages; i++) {
+ page = entry->pagelist[i];
+- if ( page )
+- ClearPageReserved( page );
++ if (page)
++ ClearPageReserved(page);
+ }
+
+- vfree( entry->virtual );
++ vfree(entry->virtual);
+
+- drm_free( entry->busaddr,
+- entry->pages * sizeof(*entry->busaddr),
+- DRM_MEM_PAGES );
+- drm_free( entry->pagelist,
+- entry->pages * sizeof(*entry->pagelist),
+- DRM_MEM_PAGES );
+- drm_free( entry,
+- sizeof(*entry),
+- DRM_MEM_SGLISTS );
++ drm_free(entry->busaddr,
++ entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
++ drm_free(entry->pagelist,
++ entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
++ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ }
+
+ #ifdef _LP64
+@@ -67,8 +63,8 @@ void drm_sg_cleanup( drm_sg_mem_t *entry
+ # define ScatterHandle(x) (unsigned int)(x)
+ #endif
+
+-int drm_sg_alloc( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_sg_alloc(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -77,75 +73,70 @@ int drm_sg_alloc( struct inode *inode, s
+ drm_sg_mem_t *entry;
+ unsigned long pages, i, j;
+
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if (!drm_core_check_feature(dev, DRIVER_SG))
+ return -EINVAL;
+
+- if ( dev->sg )
++ if (dev->sg)
+ return -EINVAL;
+
+- if ( copy_from_user( &request, argp, sizeof(request) ) )
++ if (copy_from_user(&request, argp, sizeof(request)))
+ return -EFAULT;
+
+- entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
+- if ( !entry )
++ entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
++ if (!entry)
+ return -ENOMEM;
+
+- memset( entry, 0, sizeof(*entry) );
++ memset(entry, 0, sizeof(*entry));
+
+ pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+- DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
++ DRM_DEBUG("sg size=%ld pages=%ld\n", request.size, pages);
+
+ entry->pages = pages;
+- entry->pagelist = drm_alloc( pages * sizeof(*entry->pagelist),
+- DRM_MEM_PAGES );
+- if ( !entry->pagelist ) {
+- drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS );
++ entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
++ DRM_MEM_PAGES);
++ if (!entry->pagelist) {
++ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ return -ENOMEM;
+ }
+
+ memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
+
+- entry->busaddr = drm_alloc( pages * sizeof(*entry->busaddr),
+- DRM_MEM_PAGES );
+- if ( !entry->busaddr ) {
+- drm_free( entry->pagelist,
+- entry->pages * sizeof(*entry->pagelist),
+- DRM_MEM_PAGES );
+- drm_free( entry,
+- sizeof(*entry),
+- DRM_MEM_SGLISTS );
++ entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr),
++ DRM_MEM_PAGES);
++ if (!entry->busaddr) {
++ drm_free(entry->pagelist,
++ entry->pages * sizeof(*entry->pagelist),
++ DRM_MEM_PAGES);
++ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ return -ENOMEM;
+ }
+- memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
++ memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
+
+- entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
+- if ( !entry->virtual ) {
+- drm_free( entry->busaddr,
+- entry->pages * sizeof(*entry->busaddr),
+- DRM_MEM_PAGES );
+- drm_free( entry->pagelist,
+- entry->pages * sizeof(*entry->pagelist),
+- DRM_MEM_PAGES );
+- drm_free( entry,
+- sizeof(*entry),
+- DRM_MEM_SGLISTS );
++ entry->virtual = vmalloc_32(pages << PAGE_SHIFT);
++ if (!entry->virtual) {
++ drm_free(entry->busaddr,
++ entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
++ drm_free(entry->pagelist,
++ entry->pages * sizeof(*entry->pagelist),
++ DRM_MEM_PAGES);
++ drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+ return -ENOMEM;
+ }
+
+ /* This also forces the mapping of COW pages, so our page list
+ * will be valid. Please don't remove it...
+ */
+- memset( entry->virtual, 0, pages << PAGE_SHIFT );
++ memset(entry->virtual, 0, pages << PAGE_SHIFT);
+
+ entry->handle = ScatterHandle((unsigned long)entry->virtual);
+
+- DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
+- DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
++ DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
++ DRM_DEBUG("sg alloc virtual = %p\n", entry->virtual);
+
+- for (i = (unsigned long)entry->virtual, j = 0; j < pages;
+- i += PAGE_SIZE, j++) {
++ for (i = (unsigned long)entry->virtual, j = 0; j < pages;
++ i += PAGE_SIZE, j++) {
+ entry->pagelist[j] = vmalloc_to_page((void *)i);
+ if (!entry->pagelist[j])
+ goto failed;
+@@ -154,8 +145,8 @@ int drm_sg_alloc( struct inode *inode, s
+
+ request.handle = entry->handle;
+
+- if ( copy_to_user( argp, &request, sizeof(request) ) ) {
+- drm_sg_cleanup( entry );
++ if (copy_to_user(argp, &request, sizeof(request))) {
++ drm_sg_cleanup(entry);
+ return -EFAULT;
+ }
+
+@@ -166,50 +157,50 @@ int drm_sg_alloc( struct inode *inode, s
+ * versa.
+ */
+ {
+- int error = 0;
++ int error = 0;
+
+- for ( i = 0 ; i < pages ; i++ ) {
+- unsigned long *tmp;
++ for (i = 0; i < pages; i++) {
++ unsigned long *tmp;
+
+- tmp = page_address( entry->pagelist[i] );
+- for ( j = 0 ;
+- j < PAGE_SIZE / sizeof(unsigned long) ;
+- j++, tmp++ ) {
+- *tmp = 0xcafebabe;
+- }
+- tmp = (unsigned long *)((u8 *)entry->virtual +
+- (PAGE_SIZE * i));
+- for( j = 0 ;
+- j < PAGE_SIZE / sizeof(unsigned long) ;
+- j++, tmp++ ) {
+- if ( *tmp != 0xcafebabe && error == 0 ) {
+- error = 1;
+- DRM_ERROR( "Scatter allocation error, "
+- "pagelist does not match "
+- "virtual mapping\n" );
++ tmp = page_address(entry->pagelist[i]);
++ for (j = 0;
++ j < PAGE_SIZE / sizeof(unsigned long);
++ j++, tmp++) {
++ *tmp = 0xcafebabe;
++ }
++ tmp = (unsigned long *)((u8 *) entry->virtual +
++ (PAGE_SIZE * i));
++ for (j = 0;
++ j < PAGE_SIZE / sizeof(unsigned long);
++ j++, tmp++) {
++ if (*tmp != 0xcafebabe && error == 0) {
++ error = 1;
++ DRM_ERROR("Scatter allocation error, "
++ "pagelist does not match "
++ "virtual mapping\n");
++ }
++ }
++ tmp = page_address(entry->pagelist[i]);
++ for (j = 0;
++ j < PAGE_SIZE / sizeof(unsigned long);
++ j++, tmp++) {
++ *tmp = 0;
+ }
+ }
+- tmp = page_address( entry->pagelist[i] );
+- for(j = 0 ;
+- j < PAGE_SIZE / sizeof(unsigned long) ;
+- j++, tmp++) {
+- *tmp = 0;
+- }
+- }
+- if (error == 0)
+- DRM_ERROR( "Scatter allocation matches pagelist\n" );
++ if (error == 0)
++ DRM_ERROR("Scatter allocation matches pagelist\n");
+ }
+ #endif
+
+ return 0;
+
+- failed:
+- drm_sg_cleanup( entry );
++ failed:
++ drm_sg_cleanup(entry);
+ return -ENOMEM;
+ }
+
+-int drm_sg_free( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++int drm_sg_free(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -219,20 +210,20 @@ int drm_sg_free( struct inode *inode, st
+ if (!drm_core_check_feature(dev, DRIVER_SG))
+ return -EINVAL;
+
+- if ( copy_from_user( &request,
+- (drm_scatter_gather_t __user *)arg,
+- sizeof(request) ) )
++ if (copy_from_user(&request,
++ (drm_scatter_gather_t __user *) arg,
++ sizeof(request)))
+ return -EFAULT;
+
+ entry = dev->sg;
+ dev->sg = NULL;
+
+- if ( !entry || entry->handle != request.handle )
++ if (!entry || entry->handle != request.handle)
+ return -EINVAL;
+
+- DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
++ DRM_DEBUG("sg free virtual = %p\n", entry->virtual);
+
+- drm_sg_cleanup( entry );
++ drm_sg_cleanup(entry);
+
+ return 0;
+ }
+diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
+--- a/drivers/char/drm/drm_stub.c
++++ b/drivers/char/drm/drm_stub.c
+@@ -37,11 +37,11 @@
+ #include "drm_core.h"
+
+ unsigned int drm_cards_limit = 16; /* Enough for one machine */
+-unsigned int drm_debug = 0; /* 1 to enable debug output */
++unsigned int drm_debug = 0; /* 1 to enable debug output */
+ EXPORT_SYMBOL(drm_debug);
+
+-MODULE_AUTHOR( CORE_AUTHOR );
+-MODULE_DESCRIPTION( CORE_DESC );
++MODULE_AUTHOR(CORE_AUTHOR);
++MODULE_DESCRIPTION(CORE_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+ MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
+ MODULE_PARM_DESC(debug, "Enable debug output");
+@@ -53,19 +53,21 @@ drm_head_t **drm_heads;
+ struct drm_sysfs_class *drm_class;
+ struct proc_dir_entry *drm_proc_root;
+
+-static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver)
++static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
++ const struct pci_device_id *ent,
++ struct drm_driver *driver)
+ {
+ int retcode;
+
+ spin_lock_init(&dev->count_lock);
+- init_timer( &dev->timer );
+- sema_init( &dev->struct_sem, 1 );
+- sema_init( &dev->ctxlist_sem, 1 );
++ init_timer(&dev->timer);
++ sema_init(&dev->struct_sem, 1);
++ sema_init(&dev->ctxlist_sem, 1);
+
+- dev->pdev = pdev;
++ dev->pdev = pdev;
+
+ #ifdef __alpha__
+- dev->hose = pdev->sysdata;
++ dev->hose = pdev->sysdata;
+ dev->pci_domain = dev->hose->bus->number;
+ #else
+ dev->pci_domain = 0;
+@@ -82,15 +84,15 @@ static int drm_fill_in_dev(drm_device_t
+
+ /* the DRM has 6 basic counters */
+ dev->counters = 6;
+- dev->types[0] = _DRM_STAT_LOCK;
+- dev->types[1] = _DRM_STAT_OPENS;
+- dev->types[2] = _DRM_STAT_CLOSES;
+- dev->types[3] = _DRM_STAT_IOCTLS;
+- dev->types[4] = _DRM_STAT_LOCKS;
+- dev->types[5] = _DRM_STAT_UNLOCKS;
++ dev->types[0] = _DRM_STAT_LOCK;
++ dev->types[1] = _DRM_STAT_OPENS;
++ dev->types[2] = _DRM_STAT_CLOSES;
++ dev->types[3] = _DRM_STAT_IOCTLS;
++ dev->types[4] = _DRM_STAT_LOCKS;
++ dev->types[5] = _DRM_STAT_UNLOCKS;
+
+ dev->driver = driver;
+-
++
+ if (dev->driver->preinit)
+ if ((retcode = dev->driver->preinit(dev, ent->driver_data)))
+ goto error_out_unreg;
+@@ -98,29 +100,30 @@ static int drm_fill_in_dev(drm_device_t
+ if (drm_core_has_AGP(dev)) {
+ if (drm_device_is_agp(dev))
+ dev->agp = drm_agp_init(dev);
+- if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
+- DRM_ERROR( "Cannot initialize the agpgart module.\n" );
++ if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
++ && (dev->agp == NULL)) {
++ DRM_ERROR("Cannot initialize the agpgart module.\n");
+ retcode = -EINVAL;
+ goto error_out_unreg;
+ }
+ if (drm_core_has_MTRR(dev)) {
+ if (dev->agp)
+- dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+- dev->agp->agp_info.aper_size*1024*1024,
+- MTRR_TYPE_WRCOMB,
+- 1 );
++ dev->agp->agp_mtrr =
++ mtrr_add(dev->agp->agp_info.aper_base,
++ dev->agp->agp_info.aper_size *
++ 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
+ }
+ }
+
+- retcode = drm_ctxbitmap_init( dev );
+- if( retcode ) {
+- DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
++ retcode = drm_ctxbitmap_init(dev);
++ if (retcode) {
++ DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+ goto error_out_unreg;
+ }
+
+ return 0;
+-
+-error_out_unreg:
++
++ error_out_unreg:
+ drm_takedown(dev);
+ return retcode;
+ }
+@@ -140,7 +143,7 @@ int drm_stub_open(struct inode *inode, s
+ int minor = iminor(inode);
+ int err = -ENODEV;
+ struct file_operations *old_fops;
+-
++
+ DRM_DEBUG("\n");
+
+ if (!((minor >= 0) && (minor < drm_cards_limit)))
+@@ -148,7 +151,7 @@ int drm_stub_open(struct inode *inode, s
+
+ if (!drm_heads[minor])
+ return -ENODEV;
+-
++
+ if (!(dev = drm_heads[minor]->dev))
+ return -ENODEV;
+
+@@ -174,7 +177,7 @@ int drm_stub_open(struct inode *inode, s
+ * create the proc init entry via proc_init(). This routines assigns
+ * minor numbers to secondary heads of multi-headed cards
+ */
+-static int drm_get_head(drm_device_t *dev, drm_head_t *head)
++static int drm_get_head(drm_device_t * dev, drm_head_t * head)
+ {
+ drm_head_t **heads = drm_heads;
+ int ret;
+@@ -184,26 +187,27 @@ static int drm_get_head(drm_device_t *de
+
+ for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
+ if (!*heads) {
+-
++
+ *head = (drm_head_t) {
+- .dev = dev,
+- .device = MKDEV(DRM_MAJOR, minor),
+- .minor = minor,
+- };
+-
+- if ((ret = drm_proc_init(dev, minor, drm_proc_root, &head->dev_root))) {
+- printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n");
++ .dev = dev,.device =
++ MKDEV(DRM_MAJOR, minor),.minor = minor,};
++
++ if ((ret =
++ drm_proc_init(dev, minor, drm_proc_root,
++ &head->dev_root))) {
++ printk(KERN_ERR
++ "DRM: Failed to initialize /proc/dri.\n");
+ goto err_g1;
+ }
+
+-
+ head->dev_class = drm_sysfs_device_add(drm_class,
+ MKDEV(DRM_MAJOR,
+ minor),
+ &dev->pdev->dev,
+ "card%d", minor);
+ if (IS_ERR(head->dev_class)) {
+- printk(KERN_ERR "DRM: Error sysfs_device_add.\n");
++ printk(KERN_ERR
++ "DRM: Error sysfs_device_add.\n");
+ ret = PTR_ERR(head->dev_class);
+ goto err_g2;
+ }
+@@ -215,13 +219,14 @@ static int drm_get_head(drm_device_t *de
+ }
+ DRM_ERROR("out of minors\n");
+ return -ENOMEM;
+-err_g2:
++ err_g2:
+ drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+-err_g1:
+- *head = (drm_head_t) {.dev = NULL};
++ err_g1:
++ *head = (drm_head_t) {
++ .dev = NULL};
+ return ret;
+ }
+-
++
+ /**
+ * Register.
+ *
+@@ -234,7 +239,7 @@ err_g1:
+ * Try and register, if we fail to register, backout previous work.
+ */
+ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+- struct drm_driver *driver)
++ struct drm_driver *driver)
+ {
+ drm_device_t *dev;
+ int ret;
+@@ -261,10 +266,11 @@ int drm_get_dev(struct pci_dev *pdev, co
+
+ return 0;
+
+-err_g1:
++ err_g1:
+ drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ return ret;
+ }
++
+ EXPORT_SYMBOL(drm_get_dev);
+
+ /**
+@@ -305,19 +311,19 @@ int drm_put_dev(drm_device_t * dev)
+ * last minor released.
+ *
+ */
+-int drm_put_head(drm_head_t *head)
++int drm_put_head(drm_head_t * head)
+ {
+ int minor = head->minor;
+-
++
+ DRM_DEBUG("release secondary minor %d\n", minor);
+-
++
+ drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+ drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));
+-
+- *head = (drm_head_t){.dev = NULL};
++
++ *head = (drm_head_t) {
++ .dev = NULL};
+
+ drm_heads[minor] = NULL;
+-
++
+ return 0;
+ }
+-
+diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
+--- 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/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
+--- a/drivers/char/drm/drm_vm.c
++++ b/drivers/char/drm/drm_vm.c
+@@ -1,7 +1,7 @@
+ /**
+- * \file drm_vm.h
++ * \file drm_vm.c
+ * Memory mapping for DRM
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Gareth Hughes <gareth at valinux.com>
+ */
+@@ -47,32 +47,34 @@ static void drm_vm_close(struct vm_area_
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+- *
++ *
+ * Find the right map and if it's AGP memory find the real physical page to
+ * map, get the page, increment the use count and return it.
+ */
+ #if __OS_HAS_AGP
+ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
+- unsigned long address)
++ unsigned long address)
+ {
+- drm_file_t *priv = vma->vm_file->private_data;
++ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->head->dev;
+- drm_map_t *map = NULL;
+- drm_map_list_t *r_list;
++ drm_map_t *map = NULL;
++ drm_map_list_t *r_list;
+ struct list_head *list;
+
+ /*
+- * Find the right map
+- */
++ * Find the right map
++ */
+ if (!drm_core_has_AGP(dev))
+ goto vm_nopage_error;
+
+- if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
++ if (!dev->agp || !dev->agp->cant_use_aperture)
++ goto vm_nopage_error;
+
+ list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+ map = r_list->map;
+- if (!map) continue;
++ if (!map)
++ continue;
+ if (r_list->user_token == VM_OFFSET(vma))
+ break;
+ }
+@@ -85,45 +87,47 @@ static __inline__ struct page *drm_do_vm
+
+ #ifdef __alpha__
+ /*
+- * Adjust to a bus-relative address
+- */
++ * Adjust to a bus-relative address
++ */
+ baddr -= dev->hose->mem_space->start;
+ #endif
+
+ /*
+- * It's AGP memory - find the real physical page to map
+- */
+- for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
++ * It's AGP memory - find the real physical page to map
++ */
++ for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
+ if (agpmem->bound <= baddr &&
+- agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
++ agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
+ break;
+ }
+
+- if (!agpmem) goto vm_nopage_error;
++ if (!agpmem)
++ goto vm_nopage_error;
+
+ /*
+- * Get the page, inc the use count, and return it
+- */
++ * Get the page, inc the use count, and return it
++ */
+ offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
+ page = virt_to_page(__va(agpmem->memory->memory[offset]));
+ get_page(page);
+
+- DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
+- baddr, __va(agpmem->memory->memory[offset]), offset,
+- page_count(page));
++ DRM_DEBUG
++ ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
++ baddr, __va(agpmem->memory->memory[offset]), offset,
++ page_count(page));
+
+ return page;
+- }
+-vm_nopage_error:
+- return NOPAGE_SIGBUS; /* Disallow mremap */
++ }
++ vm_nopage_error:
++ return NOPAGE_SIGBUS; /* Disallow mremap */
+ }
+-#else /* __OS_HAS_AGP */
++#else /* __OS_HAS_AGP */
+ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
+- unsigned long address)
++ unsigned long address)
+ {
+ return NOPAGE_SIGBUS;
+ }
+-#endif /* __OS_HAS_AGP */
++#endif /* __OS_HAS_AGP */
+
+ /**
+ * \c nopage method for shared virtual memory.
+@@ -131,22 +135,24 @@ static __inline__ struct page *drm_do_vm
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+- *
++ *
+ * Get the the mapping, find the real physical page to map, get the page, and
+ * return it.
+ */
+ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
+- unsigned long address)
++ unsigned long address)
+ {
+- drm_map_t *map = (drm_map_t *)vma->vm_private_data;
+- unsigned long offset;
+- unsigned long i;
+- struct page *page;
++ drm_map_t *map = (drm_map_t *) vma->vm_private_data;
++ unsigned long offset;
++ unsigned long i;
++ struct page *page;
+
+- if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+- if (!map) return NOPAGE_OOM; /* Nothing allocated */
++ if (address > vma->vm_end)
++ return NOPAGE_SIGBUS; /* Disallow mremap */
++ if (!map)
++ return NOPAGE_OOM; /* Nothing allocated */
+
+- offset = address - vma->vm_start;
++ offset = address - vma->vm_start;
+ i = (unsigned long)map->handle + offset;
+ page = (map->type == _DRM_CONSISTENT) ?
+ virt_to_page((void *)i) : vmalloc_to_page((void *)i);
+@@ -158,19 +164,18 @@ static __inline__ struct page *drm_do_vm
+ return page;
+ }
+
+-
+ /**
+ * \c close method for shared virtual memory.
+- *
++ *
+ * \param vma virtual memory area.
+- *
++ *
+ * Deletes map information if we are the last
+ * person to close a mapping and it's not in the global maplist.
+ */
+ static void drm_vm_shm_close(struct vm_area_struct *vma)
+ {
+- drm_file_t *priv = vma->vm_file->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = vma->vm_file->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_vma_entry_t *pt, *prev, *next;
+ drm_map_t *map;
+ drm_map_list_t *r_list;
+@@ -186,7 +191,8 @@ static void drm_vm_shm_close(struct vm_a
+ down(&dev->struct_sem);
+ for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
+ next = pt->next;
+- if (pt->vma->vm_private_data == map) found_maps++;
++ if (pt->vma->vm_private_data == map)
++ found_maps++;
+ if (pt->vma == vma) {
+ if (prev) {
+ prev->next = pt->next;
+@@ -199,8 +205,7 @@ static void drm_vm_shm_close(struct vm_a
+ }
+ }
+ /* We were the only map that was found */
+- if(found_maps == 1 &&
+- map->flags & _DRM_REMOVABLE) {
++ if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
+ /* Check to see if we are in the maplist, if we are not, then
+ * we delete this mappings information.
+ */
+@@ -208,10 +213,11 @@ static void drm_vm_shm_close(struct vm_a
+ list = &dev->maplist->head;
+ list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+- if (r_list->map == map) found_maps++;
++ if (r_list->map == map)
++ found_maps++;
+ }
+
+- if(!found_maps) {
++ if (!found_maps) {
+ drm_dma_handle_t dmah;
+
+ switch (map->type) {
+@@ -251,27 +257,29 @@ static void drm_vm_shm_close(struct vm_a
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+- *
++ *
+ * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
+ */
+ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
+- unsigned long address)
++ unsigned long address)
+ {
+- drm_file_t *priv = vma->vm_file->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_device_dma_t *dma = dev->dma;
+- unsigned long offset;
+- unsigned long page_nr;
+- struct page *page;
+-
+- if (!dma) return NOPAGE_SIGBUS; /* Error */
+- if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+- if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
+-
+- offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
+- page_nr = offset >> PAGE_SHIFT;
+- page = virt_to_page((dma->pagelist[page_nr] +
+- (offset & (~PAGE_MASK))));
++ drm_file_t *priv = vma->vm_file->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_device_dma_t *dma = dev->dma;
++ unsigned long offset;
++ unsigned long page_nr;
++ struct page *page;
++
++ if (!dma)
++ return NOPAGE_SIGBUS; /* Error */
++ if (address > vma->vm_end)
++ return NOPAGE_SIGBUS; /* Disallow mremap */
++ if (!dma->pagelist)
++ return NOPAGE_OOM; /* Nothing allocated */
++
++ offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
++ page_nr = offset >> PAGE_SHIFT;
++ page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));
+
+ get_page(page);
+
+@@ -285,13 +293,13 @@ static __inline__ struct page *drm_do_vm
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+- *
++ *
+ * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
+ */
+ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
+- unsigned long address)
++ unsigned long address)
+ {
+- drm_map_t *map = (drm_map_t *)vma->vm_private_data;
++ drm_map_t *map = (drm_map_t *) vma->vm_private_data;
+ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_sg_mem_t *entry = dev->sg;
+@@ -300,10 +308,12 @@ static __inline__ struct page *drm_do_vm
+ unsigned long page_offset;
+ struct page *page;
+
+- if (!entry) return NOPAGE_SIGBUS; /* Error */
+- if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+- if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
+-
++ if (!entry)
++ return NOPAGE_SIGBUS; /* Error */
++ if (address > vma->vm_end)
++ return NOPAGE_SIGBUS; /* Disallow mremap */
++ if (!entry->pagelist)
++ return NOPAGE_OOM; /* Nothing allocated */
+
+ offset = address - vma->vm_start;
+ map_offset = map->offset - (unsigned long)dev->sg->virtual;
+@@ -314,76 +324,78 @@ static __inline__ struct page *drm_do_vm
+ return page;
+ }
+
+-
+ static struct page *drm_vm_nopage(struct vm_area_struct *vma,
+- unsigned long address,
+- int *type) {
+- if (type) *type = VM_FAULT_MINOR;
++ unsigned long address, int *type)
++{
++ if (type)
++ *type = VM_FAULT_MINOR;
+ return drm_do_vm_nopage(vma, address);
+ }
+
+ static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
+- unsigned long address,
+- int *type) {
+- if (type) *type = VM_FAULT_MINOR;
++ unsigned long address, int *type)
++{
++ if (type)
++ *type = VM_FAULT_MINOR;
+ return drm_do_vm_shm_nopage(vma, address);
+ }
+
+ static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
+- unsigned long address,
+- int *type) {
+- if (type) *type = VM_FAULT_MINOR;
++ unsigned long address, int *type)
++{
++ if (type)
++ *type = VM_FAULT_MINOR;
+ return drm_do_vm_dma_nopage(vma, address);
+ }
+
+ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
+- unsigned long address,
+- int *type) {
+- if (type) *type = VM_FAULT_MINOR;
++ unsigned long address, int *type)
++{
++ if (type)
++ *type = VM_FAULT_MINOR;
+ return drm_do_vm_sg_nopage(vma, address);
+ }
+
+ /** AGP virtual memory operations */
+-static struct vm_operations_struct drm_vm_ops = {
++static struct vm_operations_struct drm_vm_ops = {
+ .nopage = drm_vm_nopage,
+- .open = drm_vm_open,
+- .close = drm_vm_close,
++ .open = drm_vm_open,
++ .close = drm_vm_close,
+ };
+
+ /** Shared virtual memory operations */
+-static struct vm_operations_struct drm_vm_shm_ops = {
++static struct vm_operations_struct drm_vm_shm_ops = {
+ .nopage = drm_vm_shm_nopage,
+- .open = drm_vm_open,
+- .close = drm_vm_shm_close,
++ .open = drm_vm_open,
++ .close = drm_vm_shm_close,
+ };
+
+ /** DMA virtual memory operations */
+-static struct vm_operations_struct drm_vm_dma_ops = {
++static struct vm_operations_struct drm_vm_dma_ops = {
+ .nopage = drm_vm_dma_nopage,
+- .open = drm_vm_open,
+- .close = drm_vm_close,
++ .open = drm_vm_open,
++ .close = drm_vm_close,
+ };
+
+ /** Scatter-gather virtual memory operations */
+-static struct vm_operations_struct drm_vm_sg_ops = {
++static struct vm_operations_struct drm_vm_sg_ops = {
+ .nopage = drm_vm_sg_nopage,
+- .open = drm_vm_open,
+- .close = drm_vm_close,
++ .open = drm_vm_open,
++ .close = drm_vm_close,
+ };
+
+-
+ /**
+ * \c open method for shared virtual memory.
+- *
++ *
+ * \param vma virtual memory area.
+- *
++ *
+ * Create a new drm_vma_entry structure as the \p vma private data entry and
+ * add it to drm_device::vmalist.
+ */
+ static void drm_vm_open(struct vm_area_struct *vma)
+ {
+- drm_file_t *priv = vma->vm_file->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = vma->vm_file->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_vma_entry_t *vma_entry;
+
+ DRM_DEBUG("0x%08lx,0x%08lx\n",
+@@ -393,26 +405,26 @@ static void drm_vm_open(struct vm_area_s
+ vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
+ if (vma_entry) {
+ down(&dev->struct_sem);
+- vma_entry->vma = vma;
++ vma_entry->vma = vma;
+ vma_entry->next = dev->vmalist;
+- vma_entry->pid = current->pid;
+- dev->vmalist = vma_entry;
++ vma_entry->pid = current->pid;
++ dev->vmalist = vma_entry;
+ up(&dev->struct_sem);
+ }
+ }
+
+ /**
+ * \c close method for all virtual memory types.
+- *
++ *
+ * \param vma virtual memory area.
+- *
++ *
+ * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
+ * free it.
+ */
+ static void drm_vm_close(struct vm_area_struct *vma)
+ {
+- drm_file_t *priv = vma->vm_file->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = vma->vm_file->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_vma_entry_t *pt, *prev;
+
+ DRM_DEBUG("0x%08lx,0x%08lx\n",
+@@ -440,43 +452,44 @@ static void drm_vm_close(struct vm_area_
+ * \param filp file pointer.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+- *
++ *
+ * Sets the virtual memory area operations structure to vm_dma_ops, the file
+ * pointer, and calls vm_open().
+ */
+ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev;
+ drm_device_dma_t *dma;
+- unsigned long length = vma->vm_end - vma->vm_start;
++ unsigned long length = vma->vm_end - vma->vm_start;
+
+ lock_kernel();
+- dev = priv->head->dev;
+- dma = dev->dma;
++ dev = priv->head->dev;
++ dma = dev->dma;
+ DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
+ vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+
+- /* Length must match exact page count */
++ /* Length must match exact page count */
+ if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+ unlock_kernel();
+
+- vma->vm_ops = &drm_vm_dma_ops;
++ vma->vm_ops = &drm_vm_dma_ops;
+
+- vma->vm_flags |= VM_RESERVED; /* Don't swap */
++ vma->vm_flags |= VM_RESERVED; /* Don't swap */
+
+- vma->vm_file = filp; /* Needed for drm_vm_open() */
++ vma->vm_file = filp; /* Needed for drm_vm_open() */
+ drm_vm_open(vma);
+ return 0;
+ }
+
+-unsigned long drm_core_get_map_ofs(drm_map_t *map)
++unsigned long drm_core_get_map_ofs(drm_map_t * map)
+ {
+ return map->offset;
+ }
++
+ EXPORT_SYMBOL(drm_core_get_map_ofs);
+
+ unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
+@@ -487,6 +500,7 @@ unsigned long drm_core_get_reg_ofs(struc
+ return 0;
+ #endif
+ }
++
+ EXPORT_SYMBOL(drm_core_get_reg_ofs);
+
+ /**
+@@ -495,7 +509,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
+ * \param filp file pointer.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+- *
++ *
+ * If the virtual memory area has no offset associated with it then it's a DMA
+ * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
+ * checks that the restricted flag is not set, sets the virtual memory operations
+@@ -504,17 +518,18 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
+ */
+ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_map_t *map = NULL;
+- drm_map_list_t *r_list;
+- unsigned long offset = 0;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_map_t *map = NULL;
++ drm_map_list_t *r_list;
++ unsigned long offset = 0;
+ struct list_head *list;
+
+ DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
+ vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+
+- if ( !priv->authenticated ) return -EACCES;
++ if (!priv->authenticated)
++ return -EACCES;
+
+ /* We check for "dma". On Apple's UniNorth, it's valid to have
+ * the AGP mapped at physical address 0
+@@ -522,61 +537,66 @@ int drm_mmap(struct file *filp, struct v
+ */
+ if (!VM_OFFSET(vma)
+ #if __OS_HAS_AGP
+- && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
++ && (!dev->agp
++ || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
+ #endif
+ )
+ return drm_mmap_dma(filp, vma);
+
+- /* A sequential search of a linked list is
+- fine here because: 1) there will only be
+- about 5-10 entries in the list and, 2) a
+- DRI client only has to do this mapping
+- once, so it doesn't have to be optimized
+- for performance, even if the list was a
+- bit longer. */
++ /* A sequential search of a linked list is
++ fine here because: 1) there will only be
++ about 5-10 entries in the list and, 2) a
++ DRI client only has to do this mapping
++ once, so it doesn't have to be optimized
++ for performance, even if the list was a
++ bit longer. */
+ list_for_each(list, &dev->maplist->head) {
+
+ r_list = list_entry(list, drm_map_list_t, head);
+ map = r_list->map;
+- if (!map) continue;
++ if (!map)
++ continue;
+ if (r_list->user_token == VM_OFFSET(vma))
+ break;
+ }
+
+- if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
++ if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
+ return -EPERM;
+
+- /* Check for valid size. */
+- if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
++ /* Check for valid size. */
++ if (map->size != vma->vm_end - vma->vm_start)
++ return -EINVAL;
+
+ if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
+ vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
+ #if defined(__i386__) || defined(__x86_64__)
+ pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+ #else
+- /* Ye gads this is ugly. With more thought
+- we could move this up higher and use
+- `protection_map' instead. */
+- vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
+- __pte(pgprot_val(vma->vm_page_prot)))));
++ /* Ye gads this is ugly. With more thought
++ we could move this up higher and use
++ `protection_map' instead. */
++ vma->vm_page_prot =
++ __pgprot(pte_val
++ (pte_wrprotect
++ (__pte(pgprot_val(vma->vm_page_prot)))));
+ #endif
+ }
+
+ switch (map->type) {
+- case _DRM_AGP:
+- if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
+- /*
+- * On some platforms we can't talk to bus dma address from the CPU, so for
+- * memory of type DRM_AGP, we'll deal with sorting out the real physical
+- * pages and mappings in nopage()
+- */
++ case _DRM_AGP:
++ if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
++ /*
++ * On some platforms we can't talk to bus dma address from the CPU, so for
++ * memory of type DRM_AGP, we'll deal with sorting out the real physical
++ * pages and mappings in nopage()
++ */
+ #if defined(__powerpc__)
+- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
++ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+ #endif
+- vma->vm_ops = &drm_vm_ops;
+- break;
+- }
+- /* fall through to _DRM_FRAME_BUFFER... */
++ vma->vm_ops = &drm_vm_ops;
++ break;
++ }
++ /* fall through to _DRM_FRAME_BUFFER... */
+ case _DRM_FRAME_BUFFER:
+ case _DRM_REGISTERS:
+ #if defined(__i386__) || defined(__x86_64__)
+@@ -591,27 +611,25 @@ int drm_mmap(struct file *filp, struct v
+ #endif
+ vma->vm_flags |= VM_IO; /* not in core dump */
+ #if defined(__ia64__)
+- if (efi_range_is_wc(vma->vm_start, vma->vm_end -
+- vma->vm_start))
++ if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
+ vma->vm_page_prot =
+- pgprot_writecombine(vma->vm_page_prot);
++ pgprot_writecombine(vma->vm_page_prot);
+ else
+- vma->vm_page_prot =
+- pgprot_noncached(vma->vm_page_prot);
++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ #endif
+ offset = dev->driver->get_reg_ofs(dev);
+ #ifdef __sparc__
+ if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+- (map->offset + offset) >> PAGE_SHIFT,
+- vma->vm_end - vma->vm_start,
+- vma->vm_page_prot))
++ (map->offset + offset) >> PAGE_SHIFT,
++ vma->vm_end - vma->vm_start,
++ vma->vm_page_prot))
+ #else
+ if (io_remap_pfn_range(vma, vma->vm_start,
+- (map->offset + offset) >> PAGE_SHIFT,
+- vma->vm_end - vma->vm_start,
+- vma->vm_page_prot))
++ (map->offset + offset) >> PAGE_SHIFT,
++ vma->vm_end - vma->vm_start,
++ vma->vm_page_prot))
+ #endif
+- return -EAGAIN;
++ return -EAGAIN;
+ DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
+ " offset = 0x%lx\n",
+ map->type,
+@@ -624,22 +642,23 @@ int drm_mmap(struct file *filp, struct v
+ * allocate in a different way */
+ vma->vm_ops = &drm_vm_shm_ops;
+ vma->vm_private_data = (void *)map;
+- /* Don't let this area swap. Change when
+- DRM_KERNEL advisory is supported. */
++ /* Don't let this area swap. Change when
++ DRM_KERNEL advisory is supported. */
+ vma->vm_flags |= VM_RESERVED;
+ break;
+ case _DRM_SCATTER_GATHER:
+ vma->vm_ops = &drm_vm_sg_ops;
+ vma->vm_private_data = (void *)map;
+ vma->vm_flags |= VM_RESERVED;
+- break;
++ break;
+ default:
+ return -EINVAL; /* This should never happen. */
+ }
+- vma->vm_flags |= VM_RESERVED; /* Don't swap */
++ vma->vm_flags |= VM_RESERVED; /* Don't swap */
+
+- vma->vm_file = filp; /* Needed for drm_vm_open() */
++ vma->vm_file = filp; /* Needed for drm_vm_open() */
+ drm_vm_open(vma);
+ return 0;
+ }
++
+ EXPORT_SYMBOL(drm_mmap);
+diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
+--- a/drivers/char/drm/ffb_context.c
++++ b/drivers/char/drm/ffb_context.c
+@@ -15,8 +15,7 @@
+
+ #include "ffb_drv.h"
+
+-static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
+-{
++static int DRM(alloc_queue) (drm_device_t * dev, int is_2d_only) {
+ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ int i;
+
+@@ -37,7 +36,7 @@ static int DRM(alloc_queue)(drm_device_t
+ return i + 1;
+ }
+
+-static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
++static void ffb_save_context(ffb_dev_priv_t * fpriv, int idx)
+ {
+ ffb_fbcPtr ffb = fpriv->regs;
+ struct ffb_hw_context *ctx;
+@@ -94,36 +93,36 @@ static void ffb_save_context(ffb_dev_pri
+
+ /* Capture rendering attributes. */
+
+- ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
+- ctx->wid = upa_readl(&ffb->wid); /* Current WID */
+- ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
+- ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
+- ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
+- ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
+- ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
+- ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
++ ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
++ ctx->wid = upa_readl(&ffb->wid); /* Current WID */
++ ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
++ ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
++ ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
++ ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
++ ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
++ ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
+ ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */
+ ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */
+ ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */
+ ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */
+- ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
+- ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
+- ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
+- ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
+- ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
++ ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
++ ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
++ ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
++ ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
++ ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
+ ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */
+ ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */
+- ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
+- ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
+- ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
++ ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
++ ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
++ ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
+ ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */
+- ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
+- ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
+- ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
+- ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
+- ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
+- ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
+- ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
++ ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
++ ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
++ ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
++ ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
++ ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
++ ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
++ ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
+
+ /* Auxiliary Clips. */
+ ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min);
+@@ -135,9 +134,9 @@ static void ffb_save_context(ffb_dev_pri
+ ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min);
+ ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max);
+
+- ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
+- ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
+- ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
++ ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
++ ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
++ ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
+ ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */
+
+ /* These registers/features only exist on FFB2 and later chips. */
+@@ -145,12 +144,12 @@ static void ffb_save_context(ffb_dev_pri
+ ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */
+ ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */
+ ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */
+- ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
+- ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
+- ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
+- ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
+- ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
+- ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
++ ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
++ ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
++ ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
++ ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
++ ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
++ ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
+
+ /* And stencil/stencilctl only exists on FFB2+ and later
+ * due to the introduction of 3DRAM-III.
+@@ -170,7 +169,7 @@ static void ffb_save_context(ffb_dev_pri
+ ctx->ucsr = upa_readl(&ffb->ucsr);
+ }
+
+-static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
++static void ffb_restore_context(ffb_dev_priv_t * fpriv, int old, int idx)
+ {
+ ffb_fbcPtr ffb = fpriv->regs;
+ struct ffb_hw_context *ctx;
+@@ -193,7 +192,7 @@ static void ffb_restore_context(ffb_dev_
+
+ upa_writel(ctx->ppc, &ffb->ppc);
+ upa_writel(ctx->wid, &ffb->wid);
+- upa_writel(ctx->fg, &ffb->fg);
++ upa_writel(ctx->fg, &ffb->fg);
+ upa_writel(ctx->bg, &ffb->bg);
+ upa_writel(ctx->xclip, &ffb->xclip);
+ upa_writel(ctx->fbc, &ffb->fbc);
+@@ -237,36 +236,36 @@ static void ffb_restore_context(ffb_dev_
+
+ /* Restore rendering attributes. */
+
+- upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
+- upa_writel(ctx->wid, &ffb->wid); /* Current WID */
+- upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
+- upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
+- upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
+- upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
+- upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
+- upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
++ upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
++ upa_writel(ctx->wid, &ffb->wid); /* Current WID */
++ upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
++ upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
++ upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
++ upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
++ upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
++ upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
+ upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */
+ upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */
+ upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */
+ upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */
+- upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
+- upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
+- upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
+- upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
+- upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
++ upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
++ upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
++ upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
++ upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
++ upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
+ upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */
+ upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */
+- upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
+- upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
+- upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
++ upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
++ upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
++ upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
+ upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */
+- upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
+- upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
+- upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
+- upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
+- upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
+- upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
+- upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
++ upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
++ upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
++ upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
++ upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
++ upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
++ upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
++ upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
+
+ /* Auxiliary Clips. */
+ upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min);
+@@ -278,9 +277,9 @@ static void ffb_restore_context(ffb_dev_
+ upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min);
+ upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max);
+
+- upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
+- upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
+- upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
++ upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
++ upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
++ upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
+ upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */
+
+ /* These registers/features only exist on FFB2 and later chips. */
+@@ -354,91 +353,87 @@ static void FFBWait(ffb_fbcPtr ffb)
+ } while (--limit);
+ }
+
+-int ffb_driver_context_switch(drm_device_t *dev, int old, int new)
++int ffb_driver_context_switch(drm_device_t * dev, int old, int new)
+ {
+ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+
+ #ifdef DRM_DMA_HISTOGRAM
+- dev->ctx_start = get_cycles();
++ dev->ctx_start = get_cycles();
+ #endif
+-
+- DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+- if (new == dev->last_context ||
+- dev->last_context == 0) {
++ DRM_DEBUG("Context switch from %d to %d\n", old, new);
++
++ if (new == dev->last_context || dev->last_context == 0) {
+ dev->last_context = new;
+- return 0;
++ return 0;
+ }
+-
++
+ FFBWait(fpriv->regs);
+ ffb_save_context(fpriv, old);
+ ffb_restore_context(fpriv, old, new);
+ FFBWait(fpriv->regs);
+-
++
+ dev->last_context = new;
+
+- return 0;
++ return 0;
+ }
+
+ int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_ctx_res_t res;
+- drm_ctx_t ctx;
+- int i;
++ drm_ctx_res_t res;
++ drm_ctx_t ctx;
++ int i;
+
+ DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
+- if (copy_from_user(&res, (drm_ctx_res_t __user *)arg, sizeof(res)))
++ if (copy_from_user(&res, (drm_ctx_res_t __user *) arg, sizeof(res)))
+ return -EFAULT;
+ if (res.count >= DRM_RESERVED_CONTEXTS) {
+ memset(&ctx, 0, sizeof(ctx));
+ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+ ctx.handle = i;
+- if (copy_to_user(&res.contexts[i],
+- &i,
+- sizeof(i)))
++ if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
+ return -EFAULT;
+ }
+ }
+ res.count = DRM_RESERVED_CONTEXTS;
+- if (copy_to_user((drm_ctx_res_t __user *)arg, &res, sizeof(res)))
++ if (copy_to_user((drm_ctx_res_t __user *) arg, &res, sizeof(res)))
+ return -EFAULT;
+ return 0;
+ }
+
+-
+ int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->dev;
+- drm_ctx_t ctx;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->dev;
++ drm_ctx_t ctx;
+ int idx;
+
+- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+- idx = DRM(alloc_queue)(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
++ idx = DRM(alloc_queue) (dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
+ if (idx < 0)
+ return -ENFILE;
+
+ DRM_DEBUG("%d\n", ctx.handle);
+ ctx.handle = idx;
+- if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
++ if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
+ return 0;
+ }
+
+ int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->dev;
+- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->dev;
++ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ struct ffb_hw_context *hwctx;
+ drm_ctx_t ctx;
+ int idx;
+
+- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+
+ idx = ctx.handle;
+@@ -458,16 +453,16 @@ int ffb_driver_modctx(struct inode *inod
+ }
+
+ int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->dev;
+- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->dev;
++ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ struct ffb_hw_context *hwctx;
+ drm_ctx_t ctx;
+ int idx;
+
+- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+
+ idx = ctx.handle;
+@@ -483,31 +478,31 @@ int ffb_driver_getctx(struct inode *inod
+ else
+ ctx.flags = 0;
+
+- if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
++ if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
+
+ return 0;
+ }
+
+-int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++int ffb_driver_switchctx(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->dev;
+- drm_ctx_t ctx;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->dev;
++ drm_ctx_t ctx;
+
+- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+ DRM_DEBUG("%d\n", ctx.handle);
+ return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
+ }
+
+ int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_ctx_t ctx;
++ drm_ctx_t ctx;
+
+- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+ DRM_DEBUG("%d\n", ctx.handle);
+
+@@ -515,15 +510,15 @@ int ffb_driver_newctx(struct inode *inod
+ }
+
+ int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_ctx_t ctx;
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->dev;
+- ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
++ drm_ctx_t ctx;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->dev;
++ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ int idx;
+
+- if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
++ if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
+ return -EFAULT;
+ DRM_DEBUG("%d\n", ctx.handle);
+
+@@ -544,7 +539,8 @@ void ffb_set_context_ioctls(void)
+ DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
+ DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
+ DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
+- DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx;
++ DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func =
++ ffb_driver_switchctx;
+ DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
+ DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
+
+diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
+--- a/drivers/char/drm/ffb_drv.c
++++ b/drivers/char/drm/ffb_drv.c
+@@ -33,13 +33,13 @@ typedef struct _ffb_position_t {
+
+ static ffb_position_t *ffb_position;
+
+-static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
++static void get_ffb_type(ffb_dev_priv_t * ffb_priv, int instance)
+ {
+ volatile unsigned char *strap_bits;
+ unsigned char val;
+
+ strap_bits = (volatile unsigned char *)
+- (ffb_priv->card_phys_base + 0x00200000UL);
++ (ffb_priv->card_phys_base + 0x00200000UL);
+
+ /* Don't ask, you have to read the value twice for whatever
+ * reason to get correct contents.
+@@ -61,7 +61,8 @@ static void get_ffb_type(ffb_dev_priv_t
+ break;
+ case (0x1 << 5) | (0x0 << 3):
+ ffb_priv->ffb_type = ffb2_prototype;
+- printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n", instance);
++ printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n",
++ instance);
+ break;
+ case (0x1 << 5) | (0x1 << 3):
+ ffb_priv->ffb_type = ffb2_vertical;
+@@ -81,12 +82,13 @@ static void get_ffb_type(ffb_dev_priv_t
+ break;
+ default:
+ ffb_priv->ffb_type = ffb2_vertical;
+- printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n", instance, val);
++ printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n",
++ instance, val);
+ break;
+ };
+ }
+
+-static void ffb_apply_upa_parent_ranges(int parent,
++static void ffb_apply_upa_parent_ranges(int parent,
+ struct linux_prom64_registers *regs)
+ {
+ struct linux_prom64_ranges ranges[PROMREG_MAX];
+@@ -97,7 +99,8 @@ static void ffb_apply_upa_parent_ranges(
+ if (strcmp(name, "upa") != 0)
+ return;
+
+- len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
++ len =
++ prom_getproperty(parent, "ranges", (void *)ranges, sizeof(ranges));
+ if (len <= 0)
+ return;
+
+@@ -117,11 +120,11 @@ static void ffb_apply_upa_parent_ranges(
+ return;
+ }
+
+-static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
++static int ffb_init_one(drm_device_t * dev, int prom_node, int parent_node,
+ int instance)
+ {
+- struct linux_prom64_registers regs[2*PROMREG_MAX];
+- ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
++ struct linux_prom64_registers regs[2 * PROMREG_MAX];
++ ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
+ int i;
+
+ ffb_priv->prom_node = prom_node;
+@@ -132,27 +135,27 @@ static int ffb_init_one(drm_device_t *de
+ ffb_apply_upa_parent_ranges(parent_node, ®s[0]);
+ ffb_priv->card_phys_base = regs[0].phys_addr;
+ ffb_priv->regs = (ffb_fbcPtr)
+- (regs[0].phys_addr + 0x00600000UL);
++ (regs[0].phys_addr + 0x00600000UL);
+ get_ffb_type(ffb_priv, instance);
+ for (i = 0; i < FFB_MAX_CTXS; i++)
+ ffb_priv->hw_state[i] = NULL;
+-
++
+ return 0;
+ }
+
+ static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev;
+- drm_map_list_t *r_list;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev;
++ drm_map_list_t *r_list;
+ struct list_head *list;
+- drm_map_t *map;
++ drm_map_t *map;
+
+ if (!priv || (dev = priv->dev) == NULL)
+ return NULL;
+
+ list_for_each(list, &dev->maplist->head) {
+- r_list = (drm_map_list_t *)list;
++ r_list = (drm_map_list_t *) list;
+ map = r_list->map;
+ if (!map)
+ continue;
+@@ -166,8 +169,7 @@ static drm_map_t *ffb_find_map(struct fi
+ unsigned long ffb_get_unmapped_area(struct file *filp,
+ unsigned long hint,
+ unsigned long len,
+- unsigned long pgoff,
+- unsigned long flags)
++ unsigned long pgoff, unsigned long flags)
+ {
+ drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
+ unsigned long addr = -ENOMEM;
+@@ -175,8 +177,7 @@ unsigned long ffb_get_unmapped_area(stru
+ if (!map)
+ return get_unmapped_area(NULL, hint, len, pgoff, flags);
+
+- if (map->type == _DRM_FRAME_BUFFER ||
+- map->type == _DRM_REGISTERS) {
++ if (map->type == _DRM_FRAME_BUFFER || map->type == _DRM_REGISTERS) {
+ #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
+ addr = get_fb_unmapped_area(filp, hint, len, pgoff, flags);
+ #else
+@@ -187,7 +188,7 @@ unsigned long ffb_get_unmapped_area(stru
+
+ addr = get_unmapped_area(NULL, hint, len + slack, pgoff, flags);
+ if (!(addr & ~PAGE_MASK)) {
+- unsigned long kvirt = (unsigned long) map->handle;
++ unsigned long kvirt = (unsigned long)map->handle;
+
+ if ((kvirt & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
+ unsigned long koff, aoff;
+@@ -207,9 +208,9 @@ unsigned long ffb_get_unmapped_area(stru
+ return addr;
+ }
+
+-static int ffb_presetup(drm_device_t *dev)
++static int ffb_presetup(drm_device_t * dev)
+ {
+- ffb_dev_priv_t *ffb_priv;
++ ffb_dev_priv_t *ffb_priv;
+ int ret = 0;
+ int i = 0;
+
+@@ -224,14 +225,11 @@ static int ffb_presetup(drm_device_t *de
+ memset(ffb_priv, 0, sizeof(*ffb_priv));
+ dev->dev_private = ffb_priv;
+
+- ret = ffb_init_one(dev,
+- ffb_position[i].node,
+- ffb_position[i].root,
+- i);
++ ret = ffb_init_one(dev, ffb_position[i].node, ffb_position[i].root, i);
+ return ret;
+ }
+
+-static void ffb_driver_release(drm_device_t *dev, struct file *filp)
++static void ffb_driver_release(drm_device_t * dev, struct file *filp)
+ {
+ ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+ int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
+@@ -239,84 +237,82 @@ static void ffb_driver_release(drm_devic
+
+ idx = context - 1;
+ if (fpriv &&
+- context != DRM_KERNEL_CONTEXT &&
+- fpriv->hw_state[idx] != NULL) {
++ context != DRM_KERNEL_CONTEXT && fpriv->hw_state[idx] != NULL) {
+ kfree(fpriv->hw_state[idx]);
+ fpriv->hw_state[idx] = NULL;
+- }
++ }
+ }
+
+-static void ffb_driver_pretakedown(drm_device_t *dev)
++static void ffb_driver_pretakedown(drm_device_t * dev)
+ {
+- if (dev->dev_private) kfree(dev->dev_private);
++ if (dev->dev_private)
++ kfree(dev->dev_private);
+ }
+
+-static int ffb_driver_postcleanup(drm_device_t *dev)
++static int ffb_driver_postcleanup(drm_device_t * dev)
+ {
+- if (ffb_position != NULL) kfree(ffb_position);
++ if (ffb_position != NULL)
++ kfree(ffb_position);
+ return 0;
+ }
+
+-static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, drm_lock_t *lock)
++static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev,
++ drm_lock_t * lock)
+ {
+ dev->lock.filp = 0;
+ {
+ __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
+ unsigned int old, new, prev, ctx;
+-
++
+ ctx = lock->context;
+ do {
+- old = *plock;
+- new = ctx;
++ old = *plock;
++ new = ctx;
+ prev = cmpxchg(plock, old, new);
+ } while (prev != old);
+ }
+ wake_up_interruptible(&dev->lock.lock_queue);
+ }
+
+-static unsigned long ffb_driver_get_map_ofs(drm_map_t *map)
++static unsigned long ffb_driver_get_map_ofs(drm_map_t * map)
+ {
+ return (map->offset & 0xffffffff);
+ }
+
+-static unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev)
++static unsigned long ffb_driver_get_reg_ofs(drm_device_t * dev)
++{
++ ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
++
++ if (ffb_priv)
++ return ffb_priv->card_phys_base;
++
++ return 0;
++}
++
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+- ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
+-
+- if (ffb_priv)
+- return ffb_priv->card_phys_base;
+-
+- return 0;
+-}
+-
+-static int postinit( struct drm_device *dev, unsigned long flags )
+-{
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->minor
+- );
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR, DRIVER_PATCHLEVEL, DRIVER_DATE, dev->minor);
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+ static drm_ioctl_desc_t ioctls[] = {
+-
++
+ };
+
+ static struct drm_driver driver = {
+@@ -335,14 +331,15 @@ static struct drm_driver driver = {
+ .ioctls = ioctls,
+ .num_ioctls = DRM_ARRAY_SIZE(ioctls),
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
+- },
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
++ }
++ ,
+ };
+
+ static int __init ffb_init(void)
+@@ -357,6 +354,6 @@ static void __exit ffb_exit(void)
+ module_init(ffb_init);
+ module_exit(ffb_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h
+--- a/drivers/char/drm/ffb_drv.h
++++ b/drivers/char/drm/ffb_drv.h
+@@ -5,7 +5,7 @@
+ */
+
+ /* Auxilliary clips. */
+-typedef struct {
++typedef struct {
+ volatile unsigned int min;
+ volatile unsigned int max;
+ } ffb_auxclip, *ffb_auxclipPtr;
+@@ -15,172 +15,265 @@ typedef struct _ffb_fbc {
+ /* Next vertex registers, on the right we list which drawops
+ * use said register and the logical name the register has in
+ * that context.
+- */ /* DESCRIPTION DRAWOP(NAME) */
+-/*0x00*/unsigned int pad1[3]; /* Reserved */
+-/*0x0c*/volatile unsigned int alpha; /* ALPHA Transparency */
+-/*0x10*/volatile unsigned int red; /* RED */
+-/*0x14*/volatile unsigned int green; /* GREEN */
+-/*0x18*/volatile unsigned int blue; /* BLUE */
+-/*0x1c*/volatile unsigned int z; /* DEPTH */
+-/*0x20*/volatile unsigned int y; /* Y triangle(DOYF) */
+- /* aadot(DYF) */
+- /* ddline(DYF) */
+- /* aaline(DYF) */
+-/*0x24*/volatile unsigned int x; /* X triangle(DOXF) */
+- /* aadot(DXF) */
+- /* ddline(DXF) */
+- /* aaline(DXF) */
+-/*0x28*/unsigned int pad2[2]; /* Reserved */
+-/*0x30*/volatile unsigned int ryf; /* Y (alias to DOYF) ddline(RYF) */
+- /* aaline(RYF) */
+- /* triangle(RYF) */
+-/*0x34*/volatile unsigned int rxf; /* X ddline(RXF) */
+- /* aaline(RXF) */
+- /* triangle(RXF) */
+-/*0x38*/unsigned int pad3[2]; /* Reserved */
+-/*0x40*/volatile unsigned int dmyf; /* Y (alias to DOYF) triangle(DMYF) */
+-/*0x44*/volatile unsigned int dmxf; /* X triangle(DMXF) */
+-/*0x48*/unsigned int pad4[2]; /* Reserved */
+-/*0x50*/volatile unsigned int ebyi; /* Y (alias to RYI) polygon(EBYI) */
+-/*0x54*/volatile unsigned int ebxi; /* X polygon(EBXI) */
+-/*0x58*/unsigned int pad5[2]; /* Reserved */
+-/*0x60*/volatile unsigned int by; /* Y brline(RYI) */
+- /* fastfill(OP) */
+- /* polygon(YI) */
+- /* rectangle(YI) */
+- /* bcopy(SRCY) */
+- /* vscroll(SRCY) */
+-/*0x64*/volatile unsigned int bx; /* X brline(RXI) */
+- /* polygon(XI) */
+- /* rectangle(XI) */
+- /* bcopy(SRCX) */
+- /* vscroll(SRCX) */
+- /* fastfill(GO) */
+-/*0x68*/volatile unsigned int dy; /* destination Y fastfill(DSTY) */
+- /* bcopy(DSRY) */
+- /* vscroll(DSRY) */
+-/*0x6c*/volatile unsigned int dx; /* destination X fastfill(DSTX) */
+- /* bcopy(DSTX) */
+- /* vscroll(DSTX) */
+-/*0x70*/volatile unsigned int bh; /* Y (alias to RYI) brline(DYI) */
+- /* dot(DYI) */
+- /* polygon(ETYI) */
+- /* Height fastfill(H) */
+- /* bcopy(H) */
+- /* vscroll(H) */
+- /* Y count fastfill(NY) */
+-/*0x74*/volatile unsigned int bw; /* X dot(DXI) */
+- /* brline(DXI) */
+- /* polygon(ETXI) */
+- /* fastfill(W) */
+- /* bcopy(W) */
+- /* vscroll(W) */
+- /* fastfill(NX) */
+-/*0x78*/unsigned int pad6[2]; /* Reserved */
+-/*0x80*/unsigned int pad7[32]; /* Reserved */
+-
++ *//* DESCRIPTION DRAWOP(NAME) */
++ /*0x00*/ unsigned int pad1[3];
++ /* Reserved */
++ /*0x0c*/ volatile unsigned int alpha;
++ /* ALPHA Transparency */
++ /*0x10*/ volatile unsigned int red;
++ /* RED */
++ /*0x14*/ volatile unsigned int green;
++ /* GREEN */
++ /*0x18*/ volatile unsigned int blue;
++ /* BLUE */
++ /*0x1c*/ volatile unsigned int z;
++ /* DEPTH */
++ /*0x20*/ volatile unsigned int y;
++ /* Y triangle(DOYF) */
++ /* aadot(DYF) */
++ /* ddline(DYF) */
++ /* aaline(DYF) */
++ /*0x24*/ volatile unsigned int x;
++ /* X triangle(DOXF) */
++ /* aadot(DXF) */
++ /* ddline(DXF) */
++ /* aaline(DXF) */
++ /*0x28*/ unsigned int pad2[2];
++ /* Reserved */
++ /*0x30*/ volatile unsigned int ryf;
++ /* Y (alias to DOYF) ddline(RYF) */
++ /* aaline(RYF) */
++ /* triangle(RYF) */
++ /*0x34*/ volatile unsigned int rxf;
++ /* X ddline(RXF) */
++ /* aaline(RXF) */
++ /* triangle(RXF) */
++ /*0x38*/ unsigned int pad3[2];
++ /* Reserved */
++ /*0x40*/ volatile unsigned int dmyf;
++ /* Y (alias to DOYF) triangle(DMYF) */
++ /*0x44*/ volatile unsigned int dmxf;
++ /* X triangle(DMXF) */
++ /*0x48*/ unsigned int pad4[2];
++ /* Reserved */
++ /*0x50*/ volatile unsigned int ebyi;
++ /* Y (alias to RYI) polygon(EBYI) */
++ /*0x54*/ volatile unsigned int ebxi;
++ /* X polygon(EBXI) */
++ /*0x58*/ unsigned int pad5[2];
++ /* Reserved */
++ /*0x60*/ volatile unsigned int by;
++ /* Y brline(RYI) */
++ /* fastfill(OP) */
++ /* polygon(YI) */
++ /* rectangle(YI) */
++ /* bcopy(SRCY) */
++ /* vscroll(SRCY) */
++ /*0x64*/ volatile unsigned int bx;
++ /* X brline(RXI) */
++ /* polygon(XI) */
++ /* rectangle(XI) */
++ /* bcopy(SRCX) */
++ /* vscroll(SRCX) */
++ /* fastfill(GO) */
++ /*0x68*/ volatile unsigned int dy;
++ /* destination Y fastfill(DSTY) */
++ /* bcopy(DSRY) */
++ /* vscroll(DSRY) */
++ /*0x6c*/ volatile unsigned int dx;
++ /* destination X fastfill(DSTX) */
++ /* bcopy(DSTX) */
++ /* vscroll(DSTX) */
++ /*0x70*/ volatile unsigned int bh;
++ /* Y (alias to RYI) brline(DYI) */
++ /* dot(DYI) */
++ /* polygon(ETYI) */
++ /* Height fastfill(H) */
++ /* bcopy(H) */
++ /* vscroll(H) */
++ /* Y count fastfill(NY) */
++ /*0x74*/ volatile unsigned int bw;
++ /* X dot(DXI) */
++ /* brline(DXI) */
++ /* polygon(ETXI) */
++ /* fastfill(W) */
++ /* bcopy(W) */
++ /* vscroll(W) */
++ /* fastfill(NX) */
++ /*0x78*/ unsigned int pad6[2];
++ /* Reserved */
++ /*0x80*/ unsigned int pad7[32];
++ /* Reserved */
++
+ /* Setup Unit's vertex state register */
+-/*100*/ volatile unsigned int suvtx;
+-/*104*/ unsigned int pad8[63]; /* Reserved */
+-
++/*100*/ volatile unsigned int suvtx;
++ /*104*/ unsigned int pad8[63];
++ /* Reserved */
++
+ /* Frame Buffer Control Registers */
+-/*200*/ volatile unsigned int ppc; /* Pixel Processor Control */
+-/*204*/ volatile unsigned int wid; /* Current WID */
+-/*208*/ volatile unsigned int fg; /* FG data */
+-/*20c*/ volatile unsigned int bg; /* BG data */
+-/*210*/ volatile unsigned int consty; /* Constant Y */
+-/*214*/ volatile unsigned int constz; /* Constant Z */
+-/*218*/ volatile unsigned int xclip; /* X Clip */
+-/*21c*/ volatile unsigned int dcss; /* Depth Cue Scale Slope */
+-/*220*/ volatile unsigned int vclipmin; /* Viewclip XY Min Bounds */
+-/*224*/ volatile unsigned int vclipmax; /* Viewclip XY Max Bounds */
+-/*228*/ volatile unsigned int vclipzmin; /* Viewclip Z Min Bounds */
+-/*22c*/ volatile unsigned int vclipzmax; /* Viewclip Z Max Bounds */
+-/*230*/ volatile unsigned int dcsf; /* Depth Cue Scale Front Bound */
+-/*234*/ volatile unsigned int dcsb; /* Depth Cue Scale Back Bound */
+-/*238*/ volatile unsigned int dczf; /* Depth Cue Z Front */
+-/*23c*/ volatile unsigned int dczb; /* Depth Cue Z Back */
+-/*240*/ unsigned int pad9; /* Reserved */
+-/*244*/ volatile unsigned int blendc; /* Alpha Blend Control */
+-/*248*/ volatile unsigned int blendc1; /* Alpha Blend Color 1 */
+-/*24c*/ volatile unsigned int blendc2; /* Alpha Blend Color 2 */
+-/*250*/ volatile unsigned int fbramitc; /* FB RAM Interleave Test Control */
+-/*254*/ volatile unsigned int fbc; /* Frame Buffer Control */
+-/*258*/ volatile unsigned int rop; /* Raster OPeration */
+-/*25c*/ volatile unsigned int cmp; /* Frame Buffer Compare */
+-/*260*/ volatile unsigned int matchab; /* Buffer AB Match Mask */
+-/*264*/ volatile unsigned int matchc; /* Buffer C(YZ) Match Mask */
+-/*268*/ volatile unsigned int magnab; /* Buffer AB Magnitude Mask */
+-/*26c*/ volatile unsigned int magnc; /* Buffer C(YZ) Magnitude Mask */
+-/*270*/ volatile unsigned int fbcfg0; /* Frame Buffer Config 0 */
+-/*274*/ volatile unsigned int fbcfg1; /* Frame Buffer Config 1 */
+-/*278*/ volatile unsigned int fbcfg2; /* Frame Buffer Config 2 */
+-/*27c*/ volatile unsigned int fbcfg3; /* Frame Buffer Config 3 */
+-/*280*/ volatile unsigned int ppcfg; /* Pixel Processor Config */
+-/*284*/ volatile unsigned int pick; /* Picking Control */
+-/*288*/ volatile unsigned int fillmode; /* FillMode */
+-/*28c*/ volatile unsigned int fbramwac; /* FB RAM Write Address Control */
+-/*290*/ volatile unsigned int pmask; /* RGB PlaneMask */
+-/*294*/ volatile unsigned int xpmask; /* X PlaneMask */
+-/*298*/ volatile unsigned int ypmask; /* Y PlaneMask */
+-/*29c*/ volatile unsigned int zpmask; /* Z PlaneMask */
+-/*2a0*/ ffb_auxclip auxclip[4]; /* Auxilliary Viewport Clip */
+-
++ /*200*/ volatile unsigned int ppc;
++ /* Pixel Processor Control */
++ /*204*/ volatile unsigned int wid;
++ /* Current WID */
++ /*208*/ volatile unsigned int fg;
++ /* FG data */
++ /*20c*/ volatile unsigned int bg;
++ /* BG data */
++ /*210*/ volatile unsigned int consty;
++ /* Constant Y */
++ /*214*/ volatile unsigned int constz;
++ /* Constant Z */
++ /*218*/ volatile unsigned int xclip;
++ /* X Clip */
++ /*21c*/ volatile unsigned int dcss;
++ /* Depth Cue Scale Slope */
++ /*220*/ volatile unsigned int vclipmin;
++ /* Viewclip XY Min Bounds */
++ /*224*/ volatile unsigned int vclipmax;
++ /* Viewclip XY Max Bounds */
++ /*228*/ volatile unsigned int vclipzmin;
++ /* Viewclip Z Min Bounds */
++ /*22c*/ volatile unsigned int vclipzmax;
++ /* Viewclip Z Max Bounds */
++ /*230*/ volatile unsigned int dcsf;
++ /* Depth Cue Scale Front Bound */
++ /*234*/ volatile unsigned int dcsb;
++ /* Depth Cue Scale Back Bound */
++ /*238*/ volatile unsigned int dczf;
++ /* Depth Cue Z Front */
++ /*23c*/ volatile unsigned int dczb;
++ /* Depth Cue Z Back */
++ /*240*/ unsigned int pad9;
++ /* Reserved */
++ /*244*/ volatile unsigned int blendc;
++ /* Alpha Blend Control */
++ /*248*/ volatile unsigned int blendc1;
++ /* Alpha Blend Color 1 */
++ /*24c*/ volatile unsigned int blendc2;
++ /* Alpha Blend Color 2 */
++ /*250*/ volatile unsigned int fbramitc;
++ /* FB RAM Interleave Test Control */
++ /*254*/ volatile unsigned int fbc;
++ /* Frame Buffer Control */
++ /*258*/ volatile unsigned int rop;
++ /* Raster OPeration */
++ /*25c*/ volatile unsigned int cmp;
++ /* Frame Buffer Compare */
++ /*260*/ volatile unsigned int matchab;
++ /* Buffer AB Match Mask */
++ /*264*/ volatile unsigned int matchc;
++ /* Buffer C(YZ) Match Mask */
++ /*268*/ volatile unsigned int magnab;
++ /* Buffer AB Magnitude Mask */
++ /*26c*/ volatile unsigned int magnc;
++ /* Buffer C(YZ) Magnitude Mask */
++ /*270*/ volatile unsigned int fbcfg0;
++ /* Frame Buffer Config 0 */
++ /*274*/ volatile unsigned int fbcfg1;
++ /* Frame Buffer Config 1 */
++ /*278*/ volatile unsigned int fbcfg2;
++ /* Frame Buffer Config 2 */
++ /*27c*/ volatile unsigned int fbcfg3;
++ /* Frame Buffer Config 3 */
++ /*280*/ volatile unsigned int ppcfg;
++ /* Pixel Processor Config */
++ /*284*/ volatile unsigned int pick;
++ /* Picking Control */
++ /*288*/ volatile unsigned int fillmode;
++ /* FillMode */
++ /*28c*/ volatile unsigned int fbramwac;
++ /* FB RAM Write Address Control */
++ /*290*/ volatile unsigned int pmask;
++ /* RGB PlaneMask */
++ /*294*/ volatile unsigned int xpmask;
++ /* X PlaneMask */
++ /*298*/ volatile unsigned int ypmask;
++ /* Y PlaneMask */
++ /*29c*/ volatile unsigned int zpmask;
++ /* Z PlaneMask */
++ /*2a0*/ ffb_auxclip auxclip[4];
++ /* Auxilliary Viewport Clip */
++
+ /* New 3dRAM III support regs */
+-/*2c0*/ volatile unsigned int rawblend2;
+-/*2c4*/ volatile unsigned int rawpreblend;
+-/*2c8*/ volatile unsigned int rawstencil;
+-/*2cc*/ volatile unsigned int rawstencilctl;
+-/*2d0*/ volatile unsigned int threedram1;
+-/*2d4*/ volatile unsigned int threedram2;
+-/*2d8*/ volatile unsigned int passin;
+-/*2dc*/ volatile unsigned int rawclrdepth;
+-/*2e0*/ volatile unsigned int rawpmask;
+-/*2e4*/ volatile unsigned int rawcsrc;
+-/*2e8*/ volatile unsigned int rawmatch;
+-/*2ec*/ volatile unsigned int rawmagn;
+-/*2f0*/ volatile unsigned int rawropblend;
+-/*2f4*/ volatile unsigned int rawcmp;
+-/*2f8*/ volatile unsigned int rawwac;
+-/*2fc*/ volatile unsigned int fbramid;
+-
+-/*300*/ volatile unsigned int drawop; /* Draw OPeration */
+-/*304*/ unsigned int pad10[2]; /* Reserved */
+-/*30c*/ volatile unsigned int lpat; /* Line Pattern control */
+-/*310*/ unsigned int pad11; /* Reserved */
+-/*314*/ volatile unsigned int fontxy; /* XY Font coordinate */
+-/*318*/ volatile unsigned int fontw; /* Font Width */
+-/*31c*/ volatile unsigned int fontinc; /* Font Increment */
+-/*320*/ volatile unsigned int font; /* Font bits */
+-/*324*/ unsigned int pad12[3]; /* Reserved */
+-/*330*/ volatile unsigned int blend2;
+-/*334*/ volatile unsigned int preblend;
+-/*338*/ volatile unsigned int stencil;
+-/*33c*/ volatile unsigned int stencilctl;
+-
+-/*340*/ unsigned int pad13[4]; /* Reserved */
+-/*350*/ volatile unsigned int dcss1; /* Depth Cue Scale Slope 1 */
+-/*354*/ volatile unsigned int dcss2; /* Depth Cue Scale Slope 2 */
+-/*358*/ volatile unsigned int dcss3; /* Depth Cue Scale Slope 3 */
+-/*35c*/ volatile unsigned int widpmask;
+-/*360*/ volatile unsigned int dcs2;
+-/*364*/ volatile unsigned int dcs3;
+-/*368*/ volatile unsigned int dcs4;
+-/*36c*/ unsigned int pad14; /* Reserved */
+-/*370*/ volatile unsigned int dcd2;
+-/*374*/ volatile unsigned int dcd3;
+-/*378*/ volatile unsigned int dcd4;
+-/*37c*/ unsigned int pad15; /* Reserved */
+-/*380*/ volatile unsigned int pattern[32]; /* area Pattern */
+-/*400*/ unsigned int pad16[8]; /* Reserved */
+-/*420*/ volatile unsigned int reset; /* chip RESET */
+-/*424*/ unsigned int pad17[247]; /* Reserved */
+-/*800*/ volatile unsigned int devid; /* Device ID */
+-/*804*/ unsigned int pad18[63]; /* Reserved */
+-/*900*/ volatile unsigned int ucsr; /* User Control & Status Register */
+-/*904*/ unsigned int pad19[31]; /* Reserved */
+-/*980*/ volatile unsigned int mer; /* Mode Enable Register */
+-/*984*/ unsigned int pad20[1439]; /* Reserved */
++/*2c0*/ volatile unsigned int rawblend2;
++/*2c4*/ volatile unsigned int rawpreblend;
++/*2c8*/ volatile unsigned int rawstencil;
++/*2cc*/ volatile unsigned int rawstencilctl;
++/*2d0*/ volatile unsigned int threedram1;
++/*2d4*/ volatile unsigned int threedram2;
++/*2d8*/ volatile unsigned int passin;
++/*2dc*/ volatile unsigned int rawclrdepth;
++/*2e0*/ volatile unsigned int rawpmask;
++/*2e4*/ volatile unsigned int rawcsrc;
++/*2e8*/ volatile unsigned int rawmatch;
++/*2ec*/ volatile unsigned int rawmagn;
++/*2f0*/ volatile unsigned int rawropblend;
++/*2f4*/ volatile unsigned int rawcmp;
++/*2f8*/ volatile unsigned int rawwac;
++/*2fc*/ volatile unsigned int fbramid;
++
++ /*300*/ volatile unsigned int drawop;
++ /* Draw OPeration */
++ /*304*/ unsigned int pad10[2];
++ /* Reserved */
++ /*30c*/ volatile unsigned int lpat;
++ /* Line Pattern control */
++ /*310*/ unsigned int pad11;
++ /* Reserved */
++ /*314*/ volatile unsigned int fontxy;
++ /* XY Font coordinate */
++ /*318*/ volatile unsigned int fontw;
++ /* Font Width */
++ /*31c*/ volatile unsigned int fontinc;
++ /* Font Increment */
++ /*320*/ volatile unsigned int font;
++ /* Font bits */
++ /*324*/ unsigned int pad12[3];
++ /* Reserved */
++/*330*/ volatile unsigned int blend2;
++/*334*/ volatile unsigned int preblend;
++/*338*/ volatile unsigned int stencil;
++/*33c*/ volatile unsigned int stencilctl;
++
++ /*340*/ unsigned int pad13[4];
++ /* Reserved */
++ /*350*/ volatile unsigned int dcss1;
++ /* Depth Cue Scale Slope 1 */
++ /*354*/ volatile unsigned int dcss2;
++ /* Depth Cue Scale Slope 2 */
++ /*358*/ volatile unsigned int dcss3;
++ /* Depth Cue Scale Slope 3 */
++/*35c*/ volatile unsigned int widpmask;
++/*360*/ volatile unsigned int dcs2;
++/*364*/ volatile unsigned int dcs3;
++/*368*/ volatile unsigned int dcs4;
++ /*36c*/ unsigned int pad14;
++ /* Reserved */
++/*370*/ volatile unsigned int dcd2;
++/*374*/ volatile unsigned int dcd3;
++/*378*/ volatile unsigned int dcd4;
++ /*37c*/ unsigned int pad15;
++ /* Reserved */
++ /*380*/ volatile unsigned int pattern[32];
++ /* area Pattern */
++ /*400*/ unsigned int pad16[8];
++ /* Reserved */
++ /*420*/ volatile unsigned int reset;
++ /* chip RESET */
++ /*424*/ unsigned int pad17[247];
++ /* Reserved */
++ /*800*/ volatile unsigned int devid;
++ /* Device ID */
++ /*804*/ unsigned int pad18[63];
++ /* Reserved */
++ /*900*/ volatile unsigned int ucsr;
++ /* User Control & Status Register */
++ /*904*/ unsigned int pad19[31];
++ /* Reserved */
++ /*980*/ volatile unsigned int mer;
++ /* Mode Enable Register */
++ /*984*/ unsigned int pad20[1439];
++ /* Reserved */
+ } ffb_fbc, *ffb_fbcPtr;
+
+ struct ffb_hw_context {
+@@ -263,16 +356,16 @@ enum ffb_chip_type {
+
+ typedef struct ffb_dev_priv {
+ /* Misc software state. */
+- int prom_node;
+- enum ffb_chip_type ffb_type;
+- u64 card_phys_base;
+- struct miscdevice miscdev;
++ int prom_node;
++ enum ffb_chip_type ffb_type;
++ u64 card_phys_base;
++ struct miscdevice miscdev;
+
+ /* Controller registers. */
+- ffb_fbcPtr regs;
++ ffb_fbcPtr regs;
+
+ /* Context table. */
+- struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
++ struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
+ } ffb_dev_priv_t;
+
+ extern unsigned long ffb_get_unmapped_area(struct file *filp,
+@@ -283,4 +376,4 @@ extern unsigned long ffb_get_unmapped_ar
+ extern void ffb_set_context_ioctls(void);
+ extern drm_ioctl_desc_t DRM(ioctls)[];
+
+-extern int ffb_driver_context_switch(drm_device_t *dev, int old, int new);
++extern int ffb_driver_context_switch(drm_device_t * dev, int old, int new);
+diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
+--- a/drivers/char/drm/i810_dma.c
++++ b/drivers/char/drm/i810_dma.c
+@@ -45,102 +45,101 @@
+ #define I810_BUF_UNMAPPED 0
+ #define I810_BUF_MAPPED 1
+
+-static drm_buf_t *i810_freelist_get(drm_device_t *dev)
++static drm_buf_t *i810_freelist_get(drm_device_t * dev)
+ {
+- drm_device_dma_t *dma = dev->dma;
+- int i;
+- int used;
++ drm_device_dma_t *dma = dev->dma;
++ int i;
++ int used;
+
+ /* Linear search might not be the best solution */
+
+- for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
++ for (i = 0; i < dma->buf_count; i++) {
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ /* In use is already a pointer */
+- used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
++ used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
+ I810_BUF_CLIENT);
+ if (used == I810_BUF_FREE) {
+ return buf;
+ }
+ }
+- return NULL;
++ return NULL;
+ }
+
+ /* This should only be called if the buffer is not sent to the hardware
+ * yet, the hardware updates in use for us once its on the ring buffer.
+ */
+
+-static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
++static int i810_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+ {
+- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+- int used;
++ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
++ int used;
+
+- /* In use is already a pointer */
+- used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
++ /* In use is already a pointer */
++ used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
+ if (used != I810_BUF_CLIENT) {
+- DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+- return -EINVAL;
++ DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
++ return -EINVAL;
+ }
+
+- return 0;
++ return 0;
+ }
+
+ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev;
+- drm_i810_private_t *dev_priv;
+- drm_buf_t *buf;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev;
++ drm_i810_private_t *dev_priv;
++ drm_buf_t *buf;
+ drm_i810_buf_priv_t *buf_priv;
+
+ lock_kernel();
+- dev = priv->head->dev;
++ dev = priv->head->dev;
+ dev_priv = dev->dev_private;
+- buf = dev_priv->mmap_buffer;
++ buf = dev_priv->mmap_buffer;
+ buf_priv = buf->dev_private;
+
+ vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+ vma->vm_file = filp;
+
+- buf_priv->currently_mapped = I810_BUF_MAPPED;
++ buf_priv->currently_mapped = I810_BUF_MAPPED;
+ unlock_kernel();
+
+ if (io_remap_pfn_range(vma, vma->vm_start,
+- VM_OFFSET(vma) >> PAGE_SHIFT,
+- vma->vm_end - vma->vm_start,
+- vma->vm_page_prot)) return -EAGAIN;
++ VM_OFFSET(vma) >> PAGE_SHIFT,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot))
++ return -EAGAIN;
+ return 0;
+ }
+
+ static struct file_operations i810_buffer_fops = {
+- .open = drm_open,
+- .flush = drm_flush,
++ .open = drm_open,
++ .flush = drm_flush,
+ .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = i810_mmap_buffers,
+- .fasync = drm_fasync,
++ .ioctl = drm_ioctl,
++ .mmap = i810_mmap_buffers,
++ .fasync = drm_fasync,
+ };
+
+-static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
++static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+- drm_i810_private_t *dev_priv = dev->dev_private;
+- struct file_operations *old_fops;
++ drm_i810_private_t *dev_priv = dev->dev_private;
++ struct file_operations *old_fops;
+ int retcode = 0;
+
+- if (buf_priv->currently_mapped == I810_BUF_MAPPED)
++ if (buf_priv->currently_mapped == I810_BUF_MAPPED)
+ return -EINVAL;
+
+- down_write( ¤t->mm->mmap_sem );
++ down_write(¤t->mm->mmap_sem);
+ old_fops = filp->f_op;
+ filp->f_op = &i810_buffer_fops;
+ dev_priv->mmap_buffer = buf;
+ buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
+- PROT_READ|PROT_WRITE,
+- MAP_SHARED,
+- buf->bus_address);
++ PROT_READ | PROT_WRITE,
++ MAP_SHARED, buf->bus_address);
+ dev_priv->mmap_buffer = NULL;
+ filp->f_op = old_fops;
+ if ((unsigned long)buf_priv->virtual > -1024UL) {
+@@ -149,12 +148,12 @@ static int i810_map_buffer(drm_buf_t *bu
+ retcode = (signed int)buf_priv->virtual;
+ buf_priv->virtual = NULL;
+ }
+- up_write( ¤t->mm->mmap_sem );
++ up_write(¤t->mm->mmap_sem);
+
+ return retcode;
+ }
+
+-static int i810_unmap_buffer(drm_buf_t *buf)
++static int i810_unmap_buffer(drm_buf_t * buf)
+ {
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ int retcode = 0;
+@@ -168,43 +167,43 @@ static int i810_unmap_buffer(drm_buf_t *
+ (size_t) buf->total);
+ up_write(¤t->mm->mmap_sem);
+
+- buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+- buf_priv->virtual = NULL;
++ buf_priv->currently_mapped = I810_BUF_UNMAPPED;
++ buf_priv->virtual = NULL;
+
+ return retcode;
+ }
+
+-static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
++static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
+ struct file *filp)
+ {
+- drm_buf_t *buf;
++ drm_buf_t *buf;
+ drm_i810_buf_priv_t *buf_priv;
+ int retcode = 0;
+
+ buf = i810_freelist_get(dev);
+ if (!buf) {
+ retcode = -ENOMEM;
+- DRM_DEBUG("retcode=%d\n", retcode);
++ DRM_DEBUG("retcode=%d\n", retcode);
+ return retcode;
+ }
+
+ retcode = i810_map_buffer(buf, filp);
+ if (retcode) {
+ i810_freelist_put(dev, buf);
+- DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
++ DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
+ return retcode;
+ }
+ buf->filp = filp;
+ buf_priv = buf->dev_private;
+ d->granted = 1;
+- d->request_idx = buf->idx;
+- d->request_size = buf->total;
+- d->virtual = buf_priv->virtual;
++ d->request_idx = buf->idx;
++ d->request_size = buf->total;
++ d->virtual = buf_priv->virtual;
+
+ return retcode;
+ }
+
+-static int i810_dma_cleanup(drm_device_t *dev)
++static int i810_dma_cleanup(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+
+@@ -217,165 +216,167 @@ static int i810_dma_cleanup(drm_device_t
+
+ if (dev->dev_private) {
+ int i;
+- drm_i810_private_t *dev_priv =
+- (drm_i810_private_t *) dev->dev_private;
++ drm_i810_private_t *dev_priv =
++ (drm_i810_private_t *) dev->dev_private;
+
+ if (dev_priv->ring.virtual_start) {
+- drm_ioremapfree((void *) dev_priv->ring.virtual_start,
+- dev_priv->ring.Size, dev);
++ drm_ioremapfree((void *)dev_priv->ring.virtual_start,
++ dev_priv->ring.Size, dev);
+ }
+- if (dev_priv->hw_status_page) {
+- pci_free_consistent(dev->pdev, PAGE_SIZE,
++ if (dev_priv->hw_status_page) {
++ pci_free_consistent(dev->pdev, PAGE_SIZE,
+ dev_priv->hw_status_page,
+ dev_priv->dma_status_page);
+- /* Need to rewrite hardware status page */
+- I810_WRITE(0x02080, 0x1ffff000);
++ /* Need to rewrite hardware status page */
++ I810_WRITE(0x02080, 0x1ffff000);
+ }
+- drm_free(dev->dev_private, sizeof(drm_i810_private_t),
++ drm_free(dev->dev_private, sizeof(drm_i810_private_t),
+ DRM_MEM_DRIVER);
+- dev->dev_private = NULL;
++ dev->dev_private = NULL;
+
+ for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
++ drm_buf_t *buf = dma->buflist[i];
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+- if ( buf_priv->kernel_virtual && buf->total )
+- drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
++ if (buf_priv->kernel_virtual && buf->total)
++ drm_ioremapfree(buf_priv->kernel_virtual,
++ buf->total, dev);
+ }
+ }
+- return 0;
++ return 0;
+ }
+
+-static int i810_wait_ring(drm_device_t *dev, int n)
++static int i810_wait_ring(drm_device_t * dev, int n)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
+- drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+- int iters = 0;
+- unsigned long end;
++ drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
++ int iters = 0;
++ unsigned long end;
+ unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+
+- end = jiffies + (HZ*3);
+- while (ring->space < n) {
+- ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+- ring->space = ring->head - (ring->tail+8);
+- if (ring->space < 0) ring->space += ring->Size;
+-
++ end = jiffies + (HZ * 3);
++ while (ring->space < n) {
++ ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
++ ring->space = ring->head - (ring->tail + 8);
++ if (ring->space < 0)
++ ring->space += ring->Size;
++
+ if (ring->head != last_head) {
+- end = jiffies + (HZ*3);
++ end = jiffies + (HZ * 3);
+ last_head = ring->head;
+ }
+-
+- iters++;
++
++ iters++;
+ if (time_before(end, jiffies)) {
+- DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+- DRM_ERROR("lockup\n");
+- goto out_wait_ring;
++ DRM_ERROR("space: %d wanted %d\n", ring->space, n);
++ DRM_ERROR("lockup\n");
++ goto out_wait_ring;
+ }
+ udelay(1);
+ }
+
+-out_wait_ring:
+- return iters;
++ out_wait_ring:
++ return iters;
+ }
+
+-static void i810_kernel_lost_context(drm_device_t *dev)
++static void i810_kernel_lost_context(drm_device_t * dev)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
+- drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
++ drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+
+- ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+- ring->tail = I810_READ(LP_RING + RING_TAIL);
+- ring->space = ring->head - (ring->tail+8);
+- if (ring->space < 0) ring->space += ring->Size;
++ ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
++ ring->tail = I810_READ(LP_RING + RING_TAIL);
++ ring->space = ring->head - (ring->tail + 8);
++ if (ring->space < 0)
++ ring->space += ring->Size;
+ }
+
+-static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
++static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
+ {
+- drm_device_dma_t *dma = dev->dma;
+- int my_idx = 24;
+- u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
+- int i;
++ drm_device_dma_t *dma = dev->dma;
++ int my_idx = 24;
++ u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
++ int i;
+
+ if (dma->buf_count > 1019) {
+- /* Not enough space in the status page for the freelist */
+- return -EINVAL;
++ /* Not enough space in the status page for the freelist */
++ return -EINVAL;
+ }
+
+- for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
++ for (i = 0; i < dma->buf_count; i++) {
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+- buf_priv->in_use = hw_status++;
+- buf_priv->my_use_idx = my_idx;
+- my_idx += 4;
++ buf_priv->in_use = hw_status++;
++ buf_priv->my_use_idx = my_idx;
++ my_idx += 4;
+
+- *buf_priv->in_use = I810_BUF_FREE;
++ *buf_priv->in_use = I810_BUF_FREE;
+
+ buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
+- buf->total, dev);
++ buf->total, dev);
+ }
+ return 0;
+ }
+
+-static int i810_dma_initialize(drm_device_t *dev,
+- drm_i810_private_t *dev_priv,
+- drm_i810_init_t *init)
++static int i810_dma_initialize(drm_device_t * dev,
++ drm_i810_private_t * dev_priv,
++ drm_i810_init_t * init)
+ {
+ struct list_head *list;
+
+- memset(dev_priv, 0, sizeof(drm_i810_private_t));
++ memset(dev_priv, 0, sizeof(drm_i810_private_t));
+
+ list_for_each(list, &dev->maplist->head) {
+ drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+ if (r_list->map &&
+ r_list->map->type == _DRM_SHM &&
+- r_list->map->flags & _DRM_CONTAINS_LOCK ) {
++ r_list->map->flags & _DRM_CONTAINS_LOCK) {
+ dev_priv->sarea_map = r_list->map;
+- break;
+- }
+- }
++ break;
++ }
++ }
+ if (!dev_priv->sarea_map) {
+ dev->dev_private = (void *)dev_priv;
+- i810_dma_cleanup(dev);
+- DRM_ERROR("can not find sarea!\n");
+- return -EINVAL;
++ i810_dma_cleanup(dev);
++ DRM_ERROR("can not find sarea!\n");
++ return -EINVAL;
+ }
+ dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+ if (!dev_priv->mmio_map) {
+ dev->dev_private = (void *)dev_priv;
+- i810_dma_cleanup(dev);
+- DRM_ERROR("can not find mmio map!\n");
+- return -EINVAL;
++ i810_dma_cleanup(dev);
++ DRM_ERROR("can not find mmio map!\n");
++ return -EINVAL;
+ }
+ dev->agp_buffer_token = init->buffers_offset;
+ dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+ if (!dev->agp_buffer_map) {
+ dev->dev_private = (void *)dev_priv;
+- i810_dma_cleanup(dev);
+- DRM_ERROR("can not find dma buffer map!\n");
+- return -EINVAL;
++ i810_dma_cleanup(dev);
++ DRM_ERROR("can not find dma buffer map!\n");
++ return -EINVAL;
+ }
+
+ dev_priv->sarea_priv = (drm_i810_sarea_t *)
+- ((u8 *)dev_priv->sarea_map->handle +
+- init->sarea_priv_offset);
++ ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
++
++ dev_priv->ring.Start = init->ring_start;
++ dev_priv->ring.End = init->ring_end;
++ dev_priv->ring.Size = init->ring_size;
++
++ dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
++ init->ring_start,
++ init->ring_size, dev);
+
+- dev_priv->ring.Start = init->ring_start;
+- dev_priv->ring.End = init->ring_end;
+- dev_priv->ring.Size = init->ring_size;
+-
+- dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
+- init->ring_start,
+- init->ring_size, dev);
+-
+- if (dev_priv->ring.virtual_start == NULL) {
+- dev->dev_private = (void *) dev_priv;
+- i810_dma_cleanup(dev);
+- DRM_ERROR("can not ioremap virtual address for"
++ if (dev_priv->ring.virtual_start == NULL) {
++ dev->dev_private = (void *)dev_priv;
++ i810_dma_cleanup(dev);
++ DRM_ERROR("can not ioremap virtual address for"
+ " ring buffer\n");
+- return -ENOMEM;
++ return -ENOMEM;
+ }
+
+- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
++ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+ dev_priv->w = init->w;
+ dev_priv->h = init->h;
+@@ -391,33 +392,33 @@ static int i810_dma_initialize(drm_devic
+ dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+ dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+
+- /* Program Hardware Status Page */
+- dev_priv->hw_status_page =
+- pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+- &dev_priv->dma_status_page);
+- if (!dev_priv->hw_status_page) {
++ /* Program Hardware Status Page */
++ dev_priv->hw_status_page =
++ pci_alloc_consistent(dev->pdev, PAGE_SIZE,
++ &dev_priv->dma_status_page);
++ if (!dev_priv->hw_status_page) {
+ dev->dev_private = (void *)dev_priv;
+ i810_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate hardware status page\n");
+ return -ENOMEM;
+ }
+- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+- DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
++ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
++ DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+ I810_WRITE(0x02080, dev_priv->dma_status_page);
+- DRM_DEBUG("Enabled hardware status page\n");
++ DRM_DEBUG("Enabled hardware status page\n");
+
+- /* Now we need to init our freelist */
++ /* Now we need to init our freelist */
+ if (i810_freelist_init(dev, dev_priv) != 0) {
+ dev->dev_private = (void *)dev_priv;
+- i810_dma_cleanup(dev);
+- DRM_ERROR("Not enough space in the status page for"
++ i810_dma_cleanup(dev);
++ DRM_ERROR("Not enough space in the status page for"
+ " the freelist\n");
+- return -ENOMEM;
++ return -ENOMEM;
+ }
+ dev->dev_private = (void *)dev_priv;
+
+- return 0;
++ return 0;
+ }
+
+ /* i810 DRM version 1.1 used a smaller init structure with different
+@@ -431,12 +432,12 @@ static int i810_dma_initialize(drm_devic
+ * If it isn't then we have a v1.1 client. Fix up params.
+ * If it is, then we have a 1.2 client... get the rest of the data.
+ */
+-static int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
++static int i810_dma_init_compat(drm_i810_init_t * init, unsigned long arg)
+ {
+
+ /* Get v1.1 init data */
+- if (copy_from_user(init, (drm_i810_pre12_init_t __user *)arg,
+- sizeof(drm_i810_pre12_init_t))) {
++ if (copy_from_user(init, (drm_i810_pre12_init_t __user *) arg,
++ sizeof(drm_i810_pre12_init_t))) {
+ return -EFAULT;
+ }
+
+@@ -444,7 +445,7 @@ static int i810_dma_init_compat(drm_i810
+
+ /* This is a v1.2 client, just get the v1.2 init data */
+ DRM_INFO("Using POST v1.2 init.\n");
+- if (copy_from_user(init, (drm_i810_init_t __user *)arg,
++ if (copy_from_user(init, (drm_i810_init_t __user *) arg,
+ sizeof(drm_i810_init_t))) {
+ return -EFAULT;
+ }
+@@ -452,246 +453,239 @@ static int i810_dma_init_compat(drm_i810
+
+ /* This is a v1.1 client, fix the params */
+ DRM_INFO("Using PRE v1.2 init.\n");
+- init->pitch_bits = init->h;
+- init->pitch = init->w;
+- init->h = init->overlay_physical;
+- init->w = init->overlay_offset;
+- init->overlay_physical = 0;
+- init->overlay_offset = 0;
++ init->pitch_bits = init->h;
++ init->pitch = init->w;
++ init->h = init->overlay_physical;
++ init->w = init->overlay_offset;
++ init->overlay_physical = 0;
++ init->overlay_offset = 0;
+ }
+
+ return 0;
+ }
+
+ static int i810_dma_init(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_i810_private_t *dev_priv;
+- drm_i810_init_t init;
+- int retcode = 0;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_i810_private_t *dev_priv;
++ drm_i810_init_t init;
++ int retcode = 0;
+
+ /* Get only the init func */
+- if (copy_from_user(&init, (void __user *)arg, sizeof(drm_i810_init_func_t)))
++ if (copy_from_user
++ (&init, (void __user *)arg, sizeof(drm_i810_init_func_t)))
+ return -EFAULT;
+
+- switch(init.func) {
+- case I810_INIT_DMA:
+- /* This case is for backward compatibility. It
+- * handles XFree 4.1.0 and 4.2.0, and has to
+- * do some parameter checking as described below.
+- * It will someday go away.
+- */
+- retcode = i810_dma_init_compat(&init, arg);
+- if (retcode)
+- return retcode;
+-
+- dev_priv = drm_alloc(sizeof(drm_i810_private_t),
+- DRM_MEM_DRIVER);
+- if (dev_priv == NULL)
+- return -ENOMEM;
+- retcode = i810_dma_initialize(dev, dev_priv, &init);
+- break;
+-
+- default:
+- case I810_INIT_DMA_1_4:
+- DRM_INFO("Using v1.4 init.\n");
+- if (copy_from_user(&init, (drm_i810_init_t __user *)arg,
+- sizeof(drm_i810_init_t))) {
+- return -EFAULT;
+- }
+- dev_priv = drm_alloc(sizeof(drm_i810_private_t),
+- DRM_MEM_DRIVER);
+- if (dev_priv == NULL)
+- return -ENOMEM;
+- retcode = i810_dma_initialize(dev, dev_priv, &init);
+- break;
+-
+- case I810_CLEANUP_DMA:
+- DRM_INFO("DMA Cleanup\n");
+- retcode = i810_dma_cleanup(dev);
+- break;
++ switch (init.func) {
++ case I810_INIT_DMA:
++ /* This case is for backward compatibility. It
++ * handles XFree 4.1.0 and 4.2.0, and has to
++ * do some parameter checking as described below.
++ * It will someday go away.
++ */
++ retcode = i810_dma_init_compat(&init, arg);
++ if (retcode)
++ return retcode;
++
++ dev_priv = drm_alloc(sizeof(drm_i810_private_t),
++ DRM_MEM_DRIVER);
++ if (dev_priv == NULL)
++ return -ENOMEM;
++ retcode = i810_dma_initialize(dev, dev_priv, &init);
++ break;
++
++ default:
++ case I810_INIT_DMA_1_4:
++ DRM_INFO("Using v1.4 init.\n");
++ if (copy_from_user(&init, (drm_i810_init_t __user *) arg,
++ sizeof(drm_i810_init_t))) {
++ return -EFAULT;
++ }
++ dev_priv = drm_alloc(sizeof(drm_i810_private_t),
++ DRM_MEM_DRIVER);
++ if (dev_priv == NULL)
++ return -ENOMEM;
++ retcode = i810_dma_initialize(dev, dev_priv, &init);
++ break;
++
++ case I810_CLEANUP_DMA:
++ DRM_INFO("DMA Cleanup\n");
++ retcode = i810_dma_cleanup(dev);
++ break;
+ }
+
+- return retcode;
++ return retcode;
+ }
+
+-
+-
+ /* Most efficient way to verify state for the i810 is as it is
+ * emitted. Non-conformant state is silently dropped.
+ *
+ * Use 'volatile' & local var tmp to force the emitted values to be
+ * identical to the verified ones.
+ */
+-static void i810EmitContextVerified( drm_device_t *dev,
+- volatile unsigned int *code )
++static void i810EmitContextVerified(drm_device_t * dev,
++ volatile unsigned int *code)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_private_t *dev_priv = dev->dev_private;
+ int i, j = 0;
+ unsigned int tmp;
+ RING_LOCALS;
+
+- BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
++ BEGIN_LP_RING(I810_CTX_SETUP_SIZE);
+
+- OUT_RING( GFX_OP_COLOR_FACTOR );
+- OUT_RING( code[I810_CTXREG_CF1] );
++ OUT_RING(GFX_OP_COLOR_FACTOR);
++ OUT_RING(code[I810_CTXREG_CF1]);
+
+- OUT_RING( GFX_OP_STIPPLE );
+- OUT_RING( code[I810_CTXREG_ST1] );
++ OUT_RING(GFX_OP_STIPPLE);
++ OUT_RING(code[I810_CTXREG_ST1]);
+
+- for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
++ for (i = 4; i < I810_CTX_SETUP_SIZE; i++) {
+ tmp = code[i];
+
+- if ((tmp & (7<<29)) == (3<<29) &&
+- (tmp & (0x1f<<24)) < (0x1d<<24))
+- {
+- OUT_RING( tmp );
++ if ((tmp & (7 << 29)) == (3 << 29) &&
++ (tmp & (0x1f << 24)) < (0x1d << 24)) {
++ OUT_RING(tmp);
+ j++;
+- }
+- else printk("constext state dropped!!!\n");
++ } else
++ printk("constext state dropped!!!\n");
+ }
+
+ if (j & 1)
+- OUT_RING( 0 );
++ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+
+-static void i810EmitTexVerified( drm_device_t *dev,
+- volatile unsigned int *code )
++static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_private_t *dev_priv = dev->dev_private;
+ int i, j = 0;
+ unsigned int tmp;
+ RING_LOCALS;
+
+- BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
++ BEGIN_LP_RING(I810_TEX_SETUP_SIZE);
+
+- OUT_RING( GFX_OP_MAP_INFO );
+- OUT_RING( code[I810_TEXREG_MI1] );
+- OUT_RING( code[I810_TEXREG_MI2] );
+- OUT_RING( code[I810_TEXREG_MI3] );
++ OUT_RING(GFX_OP_MAP_INFO);
++ OUT_RING(code[I810_TEXREG_MI1]);
++ OUT_RING(code[I810_TEXREG_MI2]);
++ OUT_RING(code[I810_TEXREG_MI3]);
+
+- for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
++ for (i = 4; i < I810_TEX_SETUP_SIZE; i++) {
+ tmp = code[i];
+
+- if ((tmp & (7<<29)) == (3<<29) &&
+- (tmp & (0x1f<<24)) < (0x1d<<24))
+- {
+- OUT_RING( tmp );
++ if ((tmp & (7 << 29)) == (3 << 29) &&
++ (tmp & (0x1f << 24)) < (0x1d << 24)) {
++ OUT_RING(tmp);
+ j++;
+- }
+- else printk("texture state dropped!!!\n");
++ } else
++ printk("texture state dropped!!!\n");
+ }
+
+ if (j & 1)
+- OUT_RING( 0 );
++ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+
+-
+ /* Need to do some additional checking when setting the dest buffer.
+ */
+-static void i810EmitDestVerified( drm_device_t *dev,
+- volatile unsigned int *code )
++static void i810EmitDestVerified(drm_device_t * dev,
++ volatile unsigned int *code)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_private_t *dev_priv = dev->dev_private;
+ unsigned int tmp;
+ RING_LOCALS;
+
+- BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
++ BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
+
+ tmp = code[I810_DESTREG_DI1];
+ if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+- OUT_RING( CMD_OP_DESTBUFFER_INFO );
+- OUT_RING( tmp );
++ OUT_RING(CMD_OP_DESTBUFFER_INFO);
++ OUT_RING(tmp);
+ } else
+- DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+- tmp, dev_priv->front_di1, dev_priv->back_di1);
++ DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
++ tmp, dev_priv->front_di1, dev_priv->back_di1);
+
+ /* invarient:
+ */
+- OUT_RING( CMD_OP_Z_BUFFER_INFO );
+- OUT_RING( dev_priv->zi1 );
++ OUT_RING(CMD_OP_Z_BUFFER_INFO);
++ OUT_RING(dev_priv->zi1);
+
+- OUT_RING( GFX_OP_DESTBUFFER_VARS );
+- OUT_RING( code[I810_DESTREG_DV1] );
++ OUT_RING(GFX_OP_DESTBUFFER_VARS);
++ OUT_RING(code[I810_DESTREG_DV1]);
+
+- OUT_RING( GFX_OP_DRAWRECT_INFO );
+- OUT_RING( code[I810_DESTREG_DR1] );
+- OUT_RING( code[I810_DESTREG_DR2] );
+- OUT_RING( code[I810_DESTREG_DR3] );
+- OUT_RING( code[I810_DESTREG_DR4] );
+- OUT_RING( 0 );
++ OUT_RING(GFX_OP_DRAWRECT_INFO);
++ OUT_RING(code[I810_DESTREG_DR1]);
++ OUT_RING(code[I810_DESTREG_DR2]);
++ OUT_RING(code[I810_DESTREG_DR3]);
++ OUT_RING(code[I810_DESTREG_DR4]);
++ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+
+-
+-
+-static void i810EmitState( drm_device_t *dev )
++static void i810EmitState(drm_device_t * dev)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
+- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+-
++
+ DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
+
+ if (dirty & I810_UPLOAD_BUFFERS) {
+- i810EmitDestVerified( dev, sarea_priv->BufferState );
++ i810EmitDestVerified(dev, sarea_priv->BufferState);
+ sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
+ }
+
+ if (dirty & I810_UPLOAD_CTX) {
+- i810EmitContextVerified( dev, sarea_priv->ContextState );
++ i810EmitContextVerified(dev, sarea_priv->ContextState);
+ sarea_priv->dirty &= ~I810_UPLOAD_CTX;
+ }
+
+ if (dirty & I810_UPLOAD_TEX0) {
+- i810EmitTexVerified( dev, sarea_priv->TexState[0] );
++ i810EmitTexVerified(dev, sarea_priv->TexState[0]);
+ sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
+ }
+
+ if (dirty & I810_UPLOAD_TEX1) {
+- i810EmitTexVerified( dev, sarea_priv->TexState[1] );
++ i810EmitTexVerified(dev, sarea_priv->TexState[1]);
+ sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
+ }
+ }
+
+-
+-
+ /* need to verify
+ */
+-static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
+- unsigned int clear_color,
+- unsigned int clear_zval )
++static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
++ unsigned int clear_color,
++ unsigned int clear_zval)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
+- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int pitch = dev_priv->pitch;
+ int cpp = 2;
+ int i;
+ RING_LOCALS;
+-
+- if ( dev_priv->current_page == 1 ) {
+- unsigned int tmp = flags;
+-
++
++ if (dev_priv->current_page == 1) {
++ unsigned int tmp = flags;
++
+ flags &= ~(I810_FRONT | I810_BACK);
+- if (tmp & I810_FRONT) flags |= I810_BACK;
+- if (tmp & I810_BACK) flags |= I810_FRONT;
++ if (tmp & I810_FRONT)
++ flags |= I810_BACK;
++ if (tmp & I810_BACK)
++ flags |= I810_FRONT;
+ }
+
+- i810_kernel_lost_context(dev);
++ i810_kernel_lost_context(dev);
+
+- if (nbox > I810_NR_SAREA_CLIPRECTS)
+- nbox = I810_NR_SAREA_CLIPRECTS;
++ if (nbox > I810_NR_SAREA_CLIPRECTS)
++ nbox = I810_NR_SAREA_CLIPRECTS;
+
+- for (i = 0 ; i < nbox ; i++, pbox++) {
++ for (i = 0; i < nbox; i++, pbox++) {
+ unsigned int x = pbox->x1;
+ unsigned int y = pbox->y1;
+ unsigned int width = (pbox->x2 - x) * cpp;
+@@ -700,52 +694,48 @@ static void i810_dma_dispatch_clear( drm
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+- pbox->x2 > dev_priv->w ||
+- pbox->y2 > dev_priv->h)
++ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+ continue;
+
+- if ( flags & I810_FRONT ) {
+- BEGIN_LP_RING( 6 );
+- OUT_RING( BR00_BITBLT_CLIENT |
+- BR00_OP_COLOR_BLT | 0x3 );
+- OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+- OUT_RING( (height << 16) | width );
+- OUT_RING( start );
+- OUT_RING( clear_color );
+- OUT_RING( 0 );
++ if (flags & I810_FRONT) {
++ BEGIN_LP_RING(6);
++ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
++ OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
++ OUT_RING((height << 16) | width);
++ OUT_RING(start);
++ OUT_RING(clear_color);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+
+- if ( flags & I810_BACK ) {
+- BEGIN_LP_RING( 6 );
+- OUT_RING( BR00_BITBLT_CLIENT |
+- BR00_OP_COLOR_BLT | 0x3 );
+- OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+- OUT_RING( (height << 16) | width );
+- OUT_RING( dev_priv->back_offset + start );
+- OUT_RING( clear_color );
+- OUT_RING( 0 );
++ if (flags & I810_BACK) {
++ BEGIN_LP_RING(6);
++ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
++ OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
++ OUT_RING((height << 16) | width);
++ OUT_RING(dev_priv->back_offset + start);
++ OUT_RING(clear_color);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+
+- if ( flags & I810_DEPTH ) {
+- BEGIN_LP_RING( 6 );
+- OUT_RING( BR00_BITBLT_CLIENT |
+- BR00_OP_COLOR_BLT | 0x3 );
+- OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+- OUT_RING( (height << 16) | width );
+- OUT_RING( dev_priv->depth_offset + start );
+- OUT_RING( clear_zval );
+- OUT_RING( 0 );
++ if (flags & I810_DEPTH) {
++ BEGIN_LP_RING(6);
++ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
++ OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
++ OUT_RING((height << 16) | width);
++ OUT_RING(dev_priv->depth_offset + start);
++ OUT_RING(clear_zval);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+ }
+ }
+
+-static void i810_dma_dispatch_swap( drm_device_t *dev )
++static void i810_dma_dispatch_swap(drm_device_t * dev)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
+- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int pitch = dev_priv->pitch;
+@@ -755,75 +745,71 @@ static void i810_dma_dispatch_swap( drm_
+
+ DRM_DEBUG("swapbuffers\n");
+
+- i810_kernel_lost_context(dev);
++ i810_kernel_lost_context(dev);
+
+- if (nbox > I810_NR_SAREA_CLIPRECTS)
+- nbox = I810_NR_SAREA_CLIPRECTS;
++ if (nbox > I810_NR_SAREA_CLIPRECTS)
++ nbox = I810_NR_SAREA_CLIPRECTS;
+
+- for (i = 0 ; i < nbox; i++, pbox++)
+- {
++ for (i = 0; i < nbox; i++, pbox++) {
+ unsigned int w = pbox->x2 - pbox->x1;
+ unsigned int h = pbox->y2 - pbox->y1;
+- unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
++ unsigned int dst = pbox->x1 * cpp + pbox->y1 * pitch;
+ unsigned int start = dst;
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+- pbox->x2 > dev_priv->w ||
+- pbox->y2 > dev_priv->h)
++ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+ continue;
+
+- BEGIN_LP_RING( 6 );
+- OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
+- OUT_RING( pitch | (0xCC << 16));
+- OUT_RING( (h << 16) | (w * cpp));
++ BEGIN_LP_RING(6);
++ OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
++ OUT_RING(pitch | (0xCC << 16));
++ OUT_RING((h << 16) | (w * cpp));
+ if (dev_priv->current_page == 0)
+- OUT_RING(dev_priv->front_offset + start);
++ OUT_RING(dev_priv->front_offset + start);
+ else
+- OUT_RING(dev_priv->back_offset + start);
+- OUT_RING( pitch );
++ OUT_RING(dev_priv->back_offset + start);
++ OUT_RING(pitch);
+ if (dev_priv->current_page == 0)
+- OUT_RING(dev_priv->back_offset + start);
++ OUT_RING(dev_priv->back_offset + start);
+ else
+- OUT_RING(dev_priv->front_offset + start);
++ OUT_RING(dev_priv->front_offset + start);
+ ADVANCE_LP_RING();
+ }
+ }
+
+-
+-static void i810_dma_dispatch_vertex(drm_device_t *dev,
+- drm_buf_t *buf,
+- int discard,
+- int used)
++static void i810_dma_dispatch_vertex(drm_device_t * dev,
++ drm_buf_t * buf, int discard, int used)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+- drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+- drm_clip_rect_t *box = sarea_priv->boxes;
+- int nbox = sarea_priv->nbox;
++ drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_clip_rect_t *box = sarea_priv->boxes;
++ int nbox = sarea_priv->nbox;
+ unsigned long address = (unsigned long)buf->bus_address;
+ unsigned long start = address - dev->agp->base;
+ int i = 0;
+- RING_LOCALS;
++ RING_LOCALS;
+
+- i810_kernel_lost_context(dev);
++ i810_kernel_lost_context(dev);
+
+- if (nbox > I810_NR_SAREA_CLIPRECTS)
++ if (nbox > I810_NR_SAREA_CLIPRECTS)
+ nbox = I810_NR_SAREA_CLIPRECTS;
+
+- if (used > 4*1024)
++ if (used > 4 * 1024)
+ used = 0;
+
+ if (sarea_priv->dirty)
+- i810EmitState( dev );
++ i810EmitState(dev);
+
+ if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+ unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
+
+- *(u32 *)buf_priv->kernel_virtual = ((GFX_OP_PRIMITIVE | prim | ((used/4)-2)));
++ *(u32 *) buf_priv->kernel_virtual =
++ ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2)));
+
+ if (used & 4) {
+- *(u32 *)((u32)buf_priv->kernel_virtual + used) = 0;
++ *(u32 *) ((u32) buf_priv->kernel_virtual + used) = 0;
+ used += 4;
+ }
+
+@@ -834,19 +820,20 @@ static void i810_dma_dispatch_vertex(drm
+ do {
+ if (i < nbox) {
+ BEGIN_LP_RING(4);
+- OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
+- SC_ENABLE );
+- OUT_RING( GFX_OP_SCISSOR_INFO );
+- OUT_RING( box[i].x1 | (box[i].y1<<16) );
+- OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
++ OUT_RING(GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
++ SC_ENABLE);
++ OUT_RING(GFX_OP_SCISSOR_INFO);
++ OUT_RING(box[i].x1 | (box[i].y1 << 16));
++ OUT_RING((box[i].x2 -
++ 1) | ((box[i].y2 - 1) << 16));
+ ADVANCE_LP_RING();
+ }
+
+ BEGIN_LP_RING(4);
+- OUT_RING( CMD_OP_BATCH_BUFFER );
+- OUT_RING( start | BB1_PROTECTED );
+- OUT_RING( start + used - 4 );
+- OUT_RING( 0 );
++ OUT_RING(CMD_OP_BATCH_BUFFER);
++ OUT_RING(start | BB1_PROTECTED);
++ OUT_RING(start + used - 4);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+ } while (++i < nbox);
+@@ -855,59 +842,59 @@ static void i810_dma_dispatch_vertex(drm
+ if (discard) {
+ dev_priv->counter++;
+
+- (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+- I810_BUF_HARDWARE);
++ (void)cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
++ I810_BUF_HARDWARE);
+
+ BEGIN_LP_RING(8);
+- OUT_RING( CMD_STORE_DWORD_IDX );
+- OUT_RING( 20 );
+- OUT_RING( dev_priv->counter );
+- OUT_RING( CMD_STORE_DWORD_IDX );
+- OUT_RING( buf_priv->my_use_idx );
+- OUT_RING( I810_BUF_FREE );
+- OUT_RING( CMD_REPORT_HEAD );
+- OUT_RING( 0 );
++ OUT_RING(CMD_STORE_DWORD_IDX);
++ OUT_RING(20);
++ OUT_RING(dev_priv->counter);
++ OUT_RING(CMD_STORE_DWORD_IDX);
++ OUT_RING(buf_priv->my_use_idx);
++ OUT_RING(I810_BUF_FREE);
++ OUT_RING(CMD_REPORT_HEAD);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+ }
+
+-static void i810_dma_dispatch_flip( drm_device_t *dev )
++static void i810_dma_dispatch_flip(drm_device_t * dev)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_private_t *dev_priv = dev->dev_private;
+ int pitch = dev_priv->pitch;
+ RING_LOCALS;
+
+- DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
+- __FUNCTION__,
+- dev_priv->current_page,
+- dev_priv->sarea_priv->pf_current_page);
+-
+- i810_kernel_lost_context(dev);
+-
+- BEGIN_LP_RING( 2 );
+- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+- OUT_RING( 0 );
++ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
++ __FUNCTION__,
++ dev_priv->current_page,
++ dev_priv->sarea_priv->pf_current_page);
++
++ i810_kernel_lost_context(dev);
++
++ BEGIN_LP_RING(2);
++ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+- BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
++ BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
+ /* On i815 at least ASYNC is buggy */
+ /* pitch<<5 is from 11.2.8 p158,
+ its the pitch / 8 then left shifted 8,
+ so (pitch >> 3) << 8 */
+- OUT_RING( CMD_OP_FRONTBUFFER_INFO | (pitch<<5) /*| ASYNC_FLIP */ );
+- if ( dev_priv->current_page == 0 ) {
+- OUT_RING( dev_priv->back_offset );
++ OUT_RING(CMD_OP_FRONTBUFFER_INFO | (pitch << 5) /*| ASYNC_FLIP */ );
++ if (dev_priv->current_page == 0) {
++ OUT_RING(dev_priv->back_offset);
+ dev_priv->current_page = 1;
+ } else {
+- OUT_RING( dev_priv->front_offset );
++ OUT_RING(dev_priv->front_offset);
+ dev_priv->current_page = 0;
+ }
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+ BEGIN_LP_RING(2);
+- OUT_RING( CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP );
+- OUT_RING( 0 );
++ OUT_RING(CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+ /* Increment the frame counter. The client-side 3D driver must
+@@ -918,46 +905,46 @@ static void i810_dma_dispatch_flip( drm_
+
+ }
+
+-static void i810_dma_quiescent(drm_device_t *dev)
++static void i810_dma_quiescent(drm_device_t * dev)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
+- RING_LOCALS;
++ drm_i810_private_t *dev_priv = dev->dev_private;
++ RING_LOCALS;
+
+ /* printk("%s\n", __FUNCTION__); */
+
+- i810_kernel_lost_context(dev);
++ i810_kernel_lost_context(dev);
+
+- BEGIN_LP_RING(4);
+- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+- OUT_RING( CMD_REPORT_HEAD );
+- OUT_RING( 0 );
+- OUT_RING( 0 );
+- ADVANCE_LP_RING();
++ BEGIN_LP_RING(4);
++ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
++ OUT_RING(CMD_REPORT_HEAD);
++ OUT_RING(0);
++ OUT_RING(0);
++ ADVANCE_LP_RING();
+
+- i810_wait_ring( dev, dev_priv->ring.Size - 8 );
++ i810_wait_ring(dev, dev_priv->ring.Size - 8);
+ }
+
+-static int i810_flush_queue(drm_device_t *dev)
++static int i810_flush_queue(drm_device_t * dev)
+ {
+- drm_i810_private_t *dev_priv = dev->dev_private;
++ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+- int i, ret = 0;
+- RING_LOCALS;
+-
++ int i, ret = 0;
++ RING_LOCALS;
++
+ /* printk("%s\n", __FUNCTION__); */
+
+- i810_kernel_lost_context(dev);
++ i810_kernel_lost_context(dev);
++
++ BEGIN_LP_RING(2);
++ OUT_RING(CMD_REPORT_HEAD);
++ OUT_RING(0);
++ ADVANCE_LP_RING();
++
++ i810_wait_ring(dev, dev_priv->ring.Size - 8);
+
+- BEGIN_LP_RING(2);
+- OUT_RING( CMD_REPORT_HEAD );
+- OUT_RING( 0 );
+- ADVANCE_LP_RING();
+-
+- i810_wait_ring( dev, dev_priv->ring.Size - 8 );
+-
+- for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
++ for (i = 0; i < dma->buf_count; i++) {
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+ int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
+ I810_BUF_FREE);
+@@ -968,24 +955,27 @@ static int i810_flush_queue(drm_device_t
+ DRM_DEBUG("still on client\n");
+ }
+
+- return ret;
++ return ret;
+ }
+
+ /* Must be called with the lock held */
+-void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
++void i810_reclaim_buffers(drm_device_t * dev, struct file *filp)
+ {
+ drm_device_dma_t *dma = dev->dma;
+- int i;
++ int i;
+
+- if (!dma) return;
+- if (!dev->dev_private) return;
+- if (!dma->buflist) return;
++ if (!dma)
++ return;
++ if (!dev->dev_private)
++ return;
++ if (!dma->buflist)
++ return;
+
+- i810_flush_queue(dev);
++ i810_flush_queue(dev);
+
+ for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+ if (buf->filp == filp && buf_priv) {
+ int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+@@ -994,7 +984,7 @@ void i810_reclaim_buffers(drm_device_t *
+ if (used == I810_BUF_CLIENT)
+ DRM_DEBUG("reclaimed from client\n");
+ if (buf_priv->currently_mapped == I810_BUF_MAPPED)
+- buf_priv->currently_mapped = I810_BUF_UNMAPPED;
++ buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+ }
+ }
+ }
+@@ -1002,29 +992,29 @@ void i810_reclaim_buffers(drm_device_t *
+ static int i810_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- i810_flush_queue(dev);
+- return 0;
++ i810_flush_queue(dev);
++ return 0;
+ }
+
+-
+ static int i810_dma_vertex(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_device_dma_t *dma = dev->dma;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+- drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+- dev_priv->sarea_priv;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
++ u32 *hw_status = dev_priv->hw_status_page;
++ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
++ dev_priv->sarea_priv;
+ drm_i810_vertex_t vertex;
+
+- if (copy_from_user(&vertex, (drm_i810_vertex_t __user *)arg, sizeof(vertex)))
++ if (copy_from_user
++ (&vertex, (drm_i810_vertex_t __user *) arg, sizeof(vertex)))
+ return -EFAULT;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+@@ -1032,48 +1022,46 @@ static int i810_dma_vertex(struct inode
+ DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
+ vertex.idx, vertex.used, vertex.discard);
+
+- if (vertex.idx < 0 || vertex.idx > dma->buf_count)
++ if (vertex.idx < 0 || vertex.idx > dma->buf_count)
+ return -EINVAL;
+
+- i810_dma_dispatch_vertex( dev,
+- dma->buflist[ vertex.idx ],
+- vertex.discard, vertex.used );
++ i810_dma_dispatch_vertex(dev,
++ dma->buflist[vertex.idx],
++ vertex.discard, vertex.used);
+
+- atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
++ atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
+ atomic_inc(&dev->counts[_DRM_STAT_DMA]);
+- sarea_priv->last_enqueue = dev_priv->counter-1;
+- sarea_priv->last_dispatch = (int) hw_status[5];
++ sarea_priv->last_enqueue = dev_priv->counter - 1;
++ sarea_priv->last_dispatch = (int)hw_status[5];
+
+ return 0;
+ }
+
+-
+-
+ static int i810_clear_bufs(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_i810_clear_t clear;
+
+- if (copy_from_user(&clear, (drm_i810_clear_t __user *)arg, sizeof(clear)))
++ if (copy_from_user
++ (&clear, (drm_i810_clear_t __user *) arg, sizeof(clear)))
+ return -EFAULT;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- /* GH: Someone's doing nasty things... */
+- if (!dev->dev_private) {
+- return -EINVAL;
+- }
+-
+- i810_dma_dispatch_clear( dev, clear.flags,
+- clear.clear_color,
+- clear.clear_depth );
+- return 0;
++ /* GH: Someone's doing nasty things... */
++ if (!dev->dev_private) {
++ return -EINVAL;
++ }
++
++ i810_dma_dispatch_clear(dev, clear.flags,
++ clear.clear_color, clear.clear_depth);
++ return 0;
+ }
+
+ static int i810_swap_bufs(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -1082,37 +1070,37 @@ static int i810_swap_bufs(struct inode *
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- i810_dma_dispatch_swap( dev );
+- return 0;
++ i810_dma_dispatch_swap(dev);
++ return 0;
+ }
+
+ static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+- drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+- dev_priv->sarea_priv;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
++ u32 *hw_status = dev_priv->hw_status_page;
++ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
++ dev_priv->sarea_priv;
+
+- sarea_priv->last_dispatch = (int) hw_status[5];
++ sarea_priv->last_dispatch = (int)hw_status[5];
+ return 0;
+ }
+
+ static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- int retcode = 0;
+- drm_i810_dma_t d;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+- drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+- dev_priv->sarea_priv;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ int retcode = 0;
++ drm_i810_dma_t d;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
++ u32 *hw_status = dev_priv->hw_status_page;
++ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
++ dev_priv->sarea_priv;
+
+- if (copy_from_user(&d, (drm_i810_dma_t __user *)arg, sizeof(d)))
++ if (copy_from_user(&d, (drm_i810_dma_t __user *) arg, sizeof(d)))
+ return -EFAULT;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+@@ -1124,29 +1112,29 @@ static int i810_getbuf(struct inode *ino
+ DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
+ current->pid, retcode, d.granted);
+
+- if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
++ if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
+ return -EFAULT;
+- sarea_priv->last_dispatch = (int) hw_status[5];
++ sarea_priv->last_dispatch = (int)hw_status[5];
+
+ return retcode;
+ }
+
+ static int i810_copybuf(struct inode *inode,
+- struct file *filp, unsigned int cmd, unsigned long arg)
++ struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ /* Never copy - 2.4.x doesn't need it */
+ return 0;
+ }
+
+ static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ /* Never copy - 2.4.x doesn't need it */
+ return 0;
+ }
+
+-static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
+- unsigned int last_render)
++static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
++ unsigned int last_render)
+ {
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+@@ -1158,19 +1146,17 @@ static void i810_dma_dispatch_mc(drm_dev
+
+ i810_kernel_lost_context(dev);
+
+- u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+- I810_BUF_HARDWARE);
++ u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
+ if (u != I810_BUF_CLIENT) {
+ DRM_DEBUG("MC found buffer that isn't mine!\n");
+ }
+
+- if (used > 4*1024)
++ if (used > 4 * 1024)
+ used = 0;
+
+ sarea_priv->dirty = 0x7f;
+
+- DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n",
+- address, used);
++ DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n", address, used);
+
+ dev_priv->counter++;
+ DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
+@@ -1181,46 +1167,45 @@ static void i810_dma_dispatch_mc(drm_dev
+
+ if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+ if (used & 4) {
+- *(u32 *)((u32)buf_priv->virtual + used) = 0;
++ *(u32 *) ((u32) buf_priv->virtual + used) = 0;
+ used += 4;
+ }
+
+ i810_unmap_buffer(buf);
+ }
+ BEGIN_LP_RING(4);
+- OUT_RING( CMD_OP_BATCH_BUFFER );
+- OUT_RING( start | BB1_PROTECTED );
+- OUT_RING( start + used - 4 );
+- OUT_RING( 0 );
++ OUT_RING(CMD_OP_BATCH_BUFFER);
++ OUT_RING(start | BB1_PROTECTED);
++ OUT_RING(start + used - 4);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+-
+ BEGIN_LP_RING(8);
+- OUT_RING( CMD_STORE_DWORD_IDX );
+- OUT_RING( buf_priv->my_use_idx );
+- OUT_RING( I810_BUF_FREE );
+- OUT_RING( 0 );
+-
+- OUT_RING( CMD_STORE_DWORD_IDX );
+- OUT_RING( 16 );
+- OUT_RING( last_render );
+- OUT_RING( 0 );
++ OUT_RING(CMD_STORE_DWORD_IDX);
++ OUT_RING(buf_priv->my_use_idx);
++ OUT_RING(I810_BUF_FREE);
++ OUT_RING(0);
++
++ OUT_RING(CMD_STORE_DWORD_IDX);
++ OUT_RING(16);
++ OUT_RING(last_render);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+
+ static int i810_dma_mc(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_device_dma_t *dma = dev->dma;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+ u32 *hw_status = dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+- dev_priv->sarea_priv;
++ dev_priv->sarea_priv;
+ drm_i810_mc_t mc;
+
+- if (copy_from_user(&mc, (drm_i810_mc_t __user *)arg, sizeof(mc)))
++ if (copy_from_user(&mc, (drm_i810_mc_t __user *) arg, sizeof(mc)))
+ return -EFAULT;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+@@ -1229,12 +1214,12 @@ static int i810_dma_mc(struct inode *ino
+ return -EINVAL;
+
+ i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
+- mc.last_render );
++ mc.last_render);
+
+ atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);
+ atomic_inc(&dev->counts[_DRM_STAT_DMA]);
+- sarea_priv->last_enqueue = dev_priv->counter-1;
+- sarea_priv->last_dispatch = (int) hw_status[5];
++ sarea_priv->last_enqueue = dev_priv->counter - 1;
++ sarea_priv->last_dispatch = (int)hw_status[5];
+
+ return 0;
+ }
+@@ -1244,22 +1229,23 @@ static int i810_rstatus(struct inode *in
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+
+- return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
++ return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
+ }
+
+ static int i810_ov0_info(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+ drm_i810_overlay_t data;
+
+ data.offset = dev_priv->overlay_offset;
+ data.physical = dev_priv->overlay_physical;
+- if (copy_to_user((drm_i810_overlay_t __user *)arg,&data,sizeof(data)))
++ if (copy_to_user
++ ((drm_i810_overlay_t __user *) arg, &data, sizeof(data)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -1269,7 +1255,7 @@ static int i810_fstatus(struct inode *in
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+@@ -1277,47 +1263,46 @@ static int i810_fstatus(struct inode *in
+ }
+
+ static int i810_ov0_flip(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+- drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
++ drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ //Tell the overlay to update
+- I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000);
++ I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
+
+ return 0;
+ }
+
+-
+ /* Not sure why this isn't set all the time:
+- */
+-static void i810_do_init_pageflip( drm_device_t *dev )
++ */
++static void i810_do_init_pageflip(drm_device_t * dev)
+ {
+ drm_i810_private_t *dev_priv = dev->dev_private;
+-
++
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+ }
+
+-static int i810_do_cleanup_pageflip( drm_device_t *dev )
++static int i810_do_cleanup_pageflip(drm_device_t * dev)
+ {
+ drm_i810_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ if (dev_priv->current_page != 0)
+- i810_dma_dispatch_flip( dev );
++ i810_dma_dispatch_flip(dev);
+
+ dev_priv->page_flipping = 0;
+ return 0;
+ }
+
+ static int i810_flip_bufs(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -1327,19 +1312,19 @@ static int i810_flip_bufs(struct inode *
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if (!dev_priv->page_flipping)
+- i810_do_init_pageflip( dev );
++ if (!dev_priv->page_flipping)
++ i810_do_init_pageflip(dev);
+
+- i810_dma_dispatch_flip( dev );
+- return 0;
++ i810_dma_dispatch_flip(dev);
++ return 0;
+ }
+
+-void i810_driver_pretakedown(drm_device_t *dev)
++void i810_driver_pretakedown(drm_device_t * dev)
+ {
+- i810_dma_cleanup( dev );
++ i810_dma_cleanup(dev);
+ }
+
+-void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp)
++void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+ {
+ if (dev->dev_private) {
+ drm_i810_private_t *dev_priv = dev->dev_private;
+@@ -1349,33 +1334,33 @@ void i810_driver_prerelease(drm_device_t
+ }
+ }
+
+-void i810_driver_release(drm_device_t *dev, struct file *filp)
++void i810_driver_release(drm_device_t * dev, struct file *filp)
+ {
+ i810_reclaim_buffers(dev, filp);
+ }
+
+-int i810_driver_dma_quiescent(drm_device_t *dev)
++int i810_driver_dma_quiescent(drm_device_t * dev)
+ {
+- i810_dma_quiescent( dev );
++ i810_dma_quiescent(dev);
+ return 0;
+ }
+
+ drm_ioctl_desc_t i810_ioctls[] = {
+- [DRM_IOCTL_NR(DRM_I810_INIT)] = { i810_dma_init, 1, 1 },
+- [DRM_IOCTL_NR(DRM_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_CLEAR)] = { i810_clear_bufs, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_FLUSH)] = { i810_flush_ioctl, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_GETAGE)] = { i810_getage, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_GETBUF)] = { i810_getbuf, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_SWAP)] = { i810_swap_bufs, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_COPY)] = { i810_copybuf, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = { i810_docopy, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = { i810_ov0_info, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = { i810_fstatus, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = { i810_ov0_flip, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_MC)] = { i810_dma_mc, 1, 1 },
+- [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = { i810_rstatus, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I810_FLIP)] = { i810_flip_bufs, 1, 0 }
++ [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, 1, 1},
++ [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, 1, 1},
++ [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, 1, 0},
++ [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, 1, 0}
+ };
+
+ int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
+diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
+--- a/drivers/char/drm/i810_drm.h
++++ b/drivers/char/drm/i810_drm.h
+@@ -19,21 +19,20 @@
+ #define I810_LOG_MIN_TEX_REGION_SIZE 16
+ #endif
+
+-#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+-#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
++#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
++#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+ #define I810_UPLOAD_CTX 0x4
+ #define I810_UPLOAD_BUFFERS 0x8
+ #define I810_UPLOAD_TEX0 0x10
+ #define I810_UPLOAD_TEX1 0x20
+ #define I810_UPLOAD_CLIPRECTS 0x40
+
+-
+ /* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer. These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+-/* Destbuffer state
++/* Destbuffer state
+ * - backbuffer linear offset and pitch -- invarient in the current dri
+ * - zbuffer linear offset and pitch -- also invarient
+ * - drawing origin in back and depth buffers.
+@@ -55,13 +54,13 @@
+ /* Context state
+ */
+ #define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
+-#define I810_CTXREG_CF1 1
+-#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
++#define I810_CTXREG_CF1 1
++#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
+ #define I810_CTXREG_ST1 3
+ #define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
+ #define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
+ #define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+-#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
++#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+ #define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+ #define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+ #define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+@@ -74,14 +73,14 @@
+ #define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
+ #define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
+ #define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
+-#define I810_CTX_SETUP_SIZE 20
++#define I810_CTX_SETUP_SIZE 20
+
+ /* Texture state (per tex unit)
+ */
+ #define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
+-#define I810_TEXREG_MI1 1
+-#define I810_TEXREG_MI2 2
+-#define I810_TEXREG_MI3 3
++#define I810_TEXREG_MI1 1
++#define I810_TEXREG_MI2 2
++#define I810_TEXREG_MI3 3
+ #define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
+ #define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
+ #define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
+@@ -98,7 +97,7 @@ typedef enum _drm_i810_init_func {
+ I810_INIT_DMA = 0x01,
+ I810_CLEANUP_DMA = 0x02,
+ I810_INIT_DMA_1_4 = 0x03
+- } drm_i810_init_func_t;
++} drm_i810_init_func_t;
+
+ /* This is the init structure after v1.2 */
+ typedef struct _drm_i810_init {
+@@ -122,7 +121,7 @@ typedef struct _drm_i810_init {
+ unsigned int w;
+ unsigned int h;
+ unsigned int pitch;
+- unsigned int pitch_bits;
++ unsigned int pitch_bits;
+ } drm_i810_init_t;
+
+ /* This is the init structure prior to v1.2 */
+@@ -140,23 +139,23 @@ typedef struct _drm_i810_pre12_init {
+ unsigned int w;
+ unsigned int h;
+ unsigned int pitch;
+- unsigned int pitch_bits;
++ unsigned int pitch_bits;
+ } drm_i810_pre12_init_t;
+
+ /* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+ typedef struct _drm_i810_tex_region {
+- unsigned char next, prev; /* indices to form a circular LRU */
++ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+ } drm_i810_tex_region_t;
+
+ typedef struct _drm_i810_sarea {
+- unsigned int ContextState[I810_CTX_SETUP_SIZE];
+- unsigned int BufferState[I810_DEST_SETUP_SIZE];
+- unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+- unsigned int dirty;
++ unsigned int ContextState[I810_CTX_SETUP_SIZE];
++ unsigned int BufferState[I810_DEST_SETUP_SIZE];
++ unsigned int TexState[2][I810_TEX_SETUP_SIZE];
++ unsigned int dirty;
+
+ unsigned int nbox;
+ drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+@@ -174,22 +173,22 @@ typedef struct _drm_i810_sarea {
+ * texture space, and can make informed decisions as to which
+ * areas to kick out. There is no need to choose whether to
+ * kick out your own texture or someone else's - simply eject
+- * them all in LRU order.
++ * them all in LRU order.
+ */
+-
+- drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1];
+- /* Last elt is sentinal */
+- int texAge; /* last time texture was uploaded */
+- int last_enqueue; /* last time a buffer was enqueued */
++
++ drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS + 1];
++ /* Last elt is sentinal */
++ int texAge; /* last time texture was uploaded */
++ int last_enqueue; /* last time a buffer was enqueued */
+ int last_dispatch; /* age of the most recently dispatched buffer */
+- int last_quiescent; /* */
++ int last_quiescent; /* */
+ int ctxOwner; /* last context to upload state */
+
+ int vertex_prim;
+
+- int pf_enabled; /* is pageflipping allowed? */
++ int pf_enabled; /* is pageflipping allowed? */
+ int pf_active;
+- int pf_current_page; /* which buffer is being displayed? */
++ int pf_current_page; /* which buffer is being displayed? */
+ } drm_i810_sarea_t;
+
+ /* WARNING: If you change any of these defines, make sure to change the
+@@ -243,13 +242,13 @@ typedef struct _drm_i810_clear {
+ * new set of cliprects.
+ */
+ typedef struct _drm_i810_vertex {
+- int idx; /* buffer index */
++ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int discard; /* client is finished with the buffer? */
+ } drm_i810_vertex_t;
+
+ typedef struct _drm_i810_copy_t {
+- int idx; /* buffer index */
++ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ void *address; /* Address to copy from */
+ } drm_i810_copy_t;
+@@ -264,7 +263,6 @@ typedef struct _drm_i810_copy_t {
+ #define PR_RECTS (0x7<<18)
+ #define PR_MASK (0x7<<18)
+
+-
+ typedef struct drm_i810_dma {
+ void *virtual;
+ int request_idx;
+@@ -273,17 +271,16 @@ typedef struct drm_i810_dma {
+ } drm_i810_dma_t;
+
+ typedef struct _drm_i810_overlay_t {
+- unsigned int offset; /* Address of the Overlay Regs */
++ unsigned int offset; /* Address of the Overlay Regs */
+ unsigned int physical;
+ } drm_i810_overlay_t;
+
+ typedef struct _drm_i810_mc {
+- int idx; /* buffer index */
+- int used; /* nr bytes in use */
+- int num_blocks; /* number of GFXBlocks */
+- int *length; /* List of lengths for GFXBlocks (FUTURE)*/
+- unsigned int last_render; /* Last Render Request */
++ int idx; /* buffer index */
++ int used; /* nr bytes in use */
++ int num_blocks; /* number of GFXBlocks */
++ int *length; /* List of lengths for GFXBlocks (FUTURE) */
++ unsigned int last_render; /* Last Render Request */
+ } drm_i810_mc_t;
+
+-
+-#endif /* _I810_DRM_H_ */
++#endif /* _I810_DRM_H_ */
+diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
+--- a/drivers/char/drm/i810_drv.c
++++ b/drivers/char/drm/i810_drv.c
+@@ -38,7 +38,7 @@
+
+ #include "drm_pciids.h"
+
+-static int postinit( struct drm_device *dev, unsigned long flags )
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+ /* i810 has 4 more counters */
+ dev->counters += 4;
+@@ -46,29 +46,27 @@ static int postinit( struct drm_device *
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+ dev->types[9] = _DRM_STAT_DMA;
+-
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -76,11 +74,10 @@ static struct pci_device_id pciidlist[]
+ i810_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t i810_ioctls[];
+-extern int i810_max_ioctl;
+-
+ static struct drm_driver driver = {
+- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
++ .driver_features =
++ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
++ DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
+ .dev_priv_size = sizeof(drm_i810_buf_priv_t),
+ .pretakedown = i810_driver_pretakedown,
+ .prerelease = i810_driver_prerelease,
+@@ -94,18 +91,20 @@ static struct drm_driver driver = {
+ .version = version,
+ .ioctls = i810_ioctls,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
+- },
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
++ }
++ ,
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- },
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
++ ,
+ };
+
+ static int __init i810_init(void)
+@@ -122,6 +121,6 @@ static void __exit i810_exit(void)
+ module_init(i810_init);
+ module_exit(i810_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
+--- a/drivers/char/drm/i810_drv.h
++++ b/drivers/char/drm/i810_drv.h
+@@ -56,14 +56,14 @@
+ #define DRIVER_PATCHLEVEL 0
+
+ typedef struct drm_i810_buf_priv {
+- u32 *in_use;
+- int my_use_idx;
++ u32 *in_use;
++ int my_use_idx;
+ int currently_mapped;
+ void *virtual;
+ void *kernel_virtual;
+ } drm_i810_buf_priv_t;
+
+-typedef struct _drm_i810_ring_buffer{
++typedef struct _drm_i810_ring_buffer {
+ int tail_mask;
+ unsigned long Start;
+ unsigned long End;
+@@ -79,16 +79,15 @@ typedef struct drm_i810_private {
+ drm_map_t *mmio_map;
+
+ drm_i810_sarea_t *sarea_priv;
+- drm_i810_ring_buffer_t ring;
++ drm_i810_ring_buffer_t ring;
+
+- void *hw_status_page;
+- unsigned long counter;
++ void *hw_status_page;
++ unsigned long counter;
+
+ dma_addr_t dma_status_page;
+
+ drm_buf_t *mmap_buffer;
+
+-
+ u32 front_di1, back_di1, zi1;
+
+ int back_offset;
+@@ -97,7 +96,7 @@ typedef struct drm_i810_private {
+ int overlay_physical;
+ int w, h;
+ int pitch;
+- int back_pitch;
++ int back_pitch;
+ int depth_pitch;
+
+ int do_boxes;
+@@ -107,21 +106,24 @@ typedef struct drm_i810_private {
+ int page_flipping;
+
+ wait_queue_head_t irq_queue;
+- atomic_t irq_received;
+- atomic_t irq_emitted;
+-
+- int front_offset;
++ atomic_t irq_received;
++ atomic_t irq_emitted;
++
++ int front_offset;
+ } drm_i810_private_t;
+
+ /* i810_dma.c */
+-extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
++extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp);
+
+-extern int i810_driver_dma_quiescent(drm_device_t *dev);
+-extern void i810_driver_release(drm_device_t *dev, struct file *filp);
+-extern void i810_driver_pretakedown(drm_device_t *dev);
+-extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
++extern int i810_driver_dma_quiescent(drm_device_t * dev);
++extern void i810_driver_release(drm_device_t * dev, struct file *filp);
++extern void i810_driver_pretakedown(drm_device_t * dev);
++extern void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+ extern int i810_driver_device_is_agp(drm_device_t * dev);
+
++extern drm_ioctl_desc_t i810_ioctls[];
++extern int i810_max_ioctl;
++
+ #define I810_BASE(reg) ((unsigned long) \
+ dev_priv->mmio_map->handle)
+ #define I810_ADDR(reg) (I810_BASE(reg) + reg)
+@@ -170,7 +172,6 @@ extern int i810_driver_device_is_agp(drm
+ #define INST_OP_FLUSH 0x02000000
+ #define INST_FLUSH_MAP_CACHE 0x00000001
+
+-
+ #define BB1_START_ADDR_MASK (~0x7)
+ #define BB1_PROTECTED (1<<0)
+ #define BB1_UNPROTECTED (0<<0)
+@@ -229,8 +230,8 @@ extern int i810_driver_device_is_agp(drm
+ #define BR00_OP_SRC_COPY_BLT 0x10C00000
+ #define BR13_SOLID_PATTERN 0x80000000
+
+-#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+-#define WAIT_FOR_PLANE_A_FLIP (1<<2)
++#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
++#define WAIT_FOR_PLANE_A_FLIP (1<<2)
+ #define WAIT_FOR_VBLANK (1<<3)
+
+ #endif
+diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
+--- a/drivers/char/drm/i830_dma.c
++++ b/drivers/char/drm/i830_dma.c
+@@ -11,11 +11,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -47,103 +47,104 @@
+ #define I830_BUF_UNMAPPED 0
+ #define I830_BUF_MAPPED 1
+
+-static drm_buf_t *i830_freelist_get(drm_device_t *dev)
++static drm_buf_t *i830_freelist_get(drm_device_t * dev)
+ {
+- drm_device_dma_t *dma = dev->dma;
+- int i;
+- int used;
+-
++ drm_device_dma_t *dma = dev->dma;
++ int i;
++ int used;
++
+ /* Linear search might not be the best solution */
+
+- for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
++ for (i = 0; i < dma->buf_count; i++) {
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+ /* In use is already a pointer */
+- used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
++ used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
+ I830_BUF_CLIENT);
+- if(used == I830_BUF_FREE) {
++ if (used == I830_BUF_FREE) {
+ return buf;
+ }
+ }
+- return NULL;
++ return NULL;
+ }
+
+ /* This should only be called if the buffer is not sent to the hardware
+ * yet, the hardware updates in use for us once its on the ring buffer.
+ */
+
+-static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
++static int i830_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+ {
+- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+- int used;
+-
+- /* In use is already a pointer */
+- used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
+- if(used != I830_BUF_CLIENT) {
+- DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+- return -EINVAL;
++ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
++ int used;
++
++ /* In use is already a pointer */
++ used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
++ if (used != I830_BUF_CLIENT) {
++ DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
++ return -EINVAL;
+ }
+-
+- return 0;
++
++ return 0;
+ }
+
+ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev;
+- drm_i830_private_t *dev_priv;
+- drm_buf_t *buf;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev;
++ drm_i830_private_t *dev_priv;
++ drm_buf_t *buf;
+ drm_i830_buf_priv_t *buf_priv;
+
+ lock_kernel();
+- dev = priv->head->dev;
++ dev = priv->head->dev;
+ dev_priv = dev->dev_private;
+- buf = dev_priv->mmap_buffer;
++ buf = dev_priv->mmap_buffer;
+ buf_priv = buf->dev_private;
+-
++
+ vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+ vma->vm_file = filp;
+-
+- buf_priv->currently_mapped = I830_BUF_MAPPED;
++
++ buf_priv->currently_mapped = I830_BUF_MAPPED;
+ unlock_kernel();
+
+ if (io_remap_pfn_range(vma, vma->vm_start,
+- VM_OFFSET(vma) >> PAGE_SHIFT,
+- vma->vm_end - vma->vm_start,
+- vma->vm_page_prot)) return -EAGAIN;
++ VM_OFFSET(vma) >> PAGE_SHIFT,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot))
++ return -EAGAIN;
+ return 0;
+ }
+
+ static struct file_operations i830_buffer_fops = {
+- .open = drm_open,
+- .flush = drm_flush,
++ .open = drm_open,
++ .flush = drm_flush,
+ .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = i830_mmap_buffers,
+- .fasync = drm_fasync,
++ .ioctl = drm_ioctl,
++ .mmap = i830_mmap_buffers,
++ .fasync = drm_fasync,
+ };
+
+-static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
++static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+- drm_i830_private_t *dev_priv = dev->dev_private;
+- struct file_operations *old_fops;
++ drm_i830_private_t *dev_priv = dev->dev_private;
++ struct file_operations *old_fops;
+ unsigned long virtual;
+ int retcode = 0;
+
+- if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL;
++ if (buf_priv->currently_mapped == I830_BUF_MAPPED)
++ return -EINVAL;
+
+- down_write( ¤t->mm->mmap_sem );
++ down_write(¤t->mm->mmap_sem);
+ old_fops = filp->f_op;
+ filp->f_op = &i830_buffer_fops;
+ dev_priv->mmap_buffer = buf;
+- virtual = do_mmap(filp, 0, buf->total, PROT_READ|PROT_WRITE,
+- MAP_SHARED, buf->bus_address);
++ virtual = do_mmap(filp, 0, buf->total, PROT_READ | PROT_WRITE,
++ MAP_SHARED, buf->bus_address);
+ dev_priv->mmap_buffer = NULL;
+ filp->f_op = old_fops;
+- if (IS_ERR((void *)virtual)) { /* ugh */
++ if (IS_ERR((void *)virtual)) { /* ugh */
+ /* Real error */
+ DRM_ERROR("mmap error\n");
+ retcode = virtual;
+@@ -151,17 +152,17 @@ static int i830_map_buffer(drm_buf_t *bu
+ } else {
+ buf_priv->virtual = (void __user *)virtual;
+ }
+- up_write( ¤t->mm->mmap_sem );
++ up_write(¤t->mm->mmap_sem);
+
+ return retcode;
+ }
+
+-static int i830_unmap_buffer(drm_buf_t *buf)
++static int i830_unmap_buffer(drm_buf_t * buf)
+ {
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+ int retcode = 0;
+
+- if(buf_priv->currently_mapped != I830_BUF_MAPPED)
++ if (buf_priv->currently_mapped != I830_BUF_MAPPED)
+ return -EINVAL;
+
+ down_write(¤t->mm->mmap_sem);
+@@ -170,43 +171,43 @@ static int i830_unmap_buffer(drm_buf_t *
+ (size_t) buf->total);
+ up_write(¤t->mm->mmap_sem);
+
+- buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+- buf_priv->virtual = NULL;
++ buf_priv->currently_mapped = I830_BUF_UNMAPPED;
++ buf_priv->virtual = NULL;
+
+ return retcode;
+ }
+
+-static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
++static int i830_dma_get_buffer(drm_device_t * dev, drm_i830_dma_t * d,
+ struct file *filp)
+ {
+- drm_buf_t *buf;
++ drm_buf_t *buf;
+ drm_i830_buf_priv_t *buf_priv;
+ int retcode = 0;
+
+ buf = i830_freelist_get(dev);
+ if (!buf) {
+ retcode = -ENOMEM;
+- DRM_DEBUG("retcode=%d\n", retcode);
++ DRM_DEBUG("retcode=%d\n", retcode);
+ return retcode;
+ }
+-
++
+ retcode = i830_map_buffer(buf, filp);
+- if(retcode) {
++ if (retcode) {
+ i830_freelist_put(dev, buf);
+- DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
++ DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
+ return retcode;
+ }
+ buf->filp = filp;
+- buf_priv = buf->dev_private;
++ buf_priv = buf->dev_private;
+ d->granted = 1;
+- d->request_idx = buf->idx;
+- d->request_size = buf->total;
+- d->virtual = buf_priv->virtual;
++ d->request_idx = buf->idx;
++ d->request_size = buf->total;
++ d->virtual = buf_priv->virtual;
+
+ return retcode;
+ }
+
+-static int i830_dma_cleanup(drm_device_t *dev)
++static int i830_dma_cleanup(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+
+@@ -214,140 +215,144 @@ static int i830_dma_cleanup(drm_device_t
+ * may not have been called from userspace and after dev_private
+ * is freed, it's too late.
+ */
+- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
++ if (dev->irq_enabled)
++ drm_irq_uninstall(dev);
+
+ if (dev->dev_private) {
+ int i;
+- drm_i830_private_t *dev_priv =
+- (drm_i830_private_t *) dev->dev_private;
+-
+- if (dev_priv->ring.virtual_start) {
+- drm_ioremapfree((void *) dev_priv->ring.virtual_start,
+- dev_priv->ring.Size, dev);
++ drm_i830_private_t *dev_priv =
++ (drm_i830_private_t *) dev->dev_private;
++
++ if (dev_priv->ring.virtual_start) {
++ drm_ioremapfree((void *)dev_priv->ring.virtual_start,
++ dev_priv->ring.Size, dev);
+ }
+- if (dev_priv->hw_status_page) {
++ if (dev_priv->hw_status_page) {
+ pci_free_consistent(dev->pdev, PAGE_SIZE,
+ dev_priv->hw_status_page,
+ dev_priv->dma_status_page);
+- /* Need to rewrite hardware status page */
+- I830_WRITE(0x02080, 0x1ffff000);
++ /* Need to rewrite hardware status page */
++ I830_WRITE(0x02080, 0x1ffff000);
+ }
+
+- drm_free(dev->dev_private, sizeof(drm_i830_private_t),
++ drm_free(dev->dev_private, sizeof(drm_i830_private_t),
+ DRM_MEM_DRIVER);
+- dev->dev_private = NULL;
++ dev->dev_private = NULL;
+
+ for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
++ drm_buf_t *buf = dma->buflist[i];
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+- if ( buf_priv->kernel_virtual && buf->total )
+- drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
++ if (buf_priv->kernel_virtual && buf->total)
++ drm_ioremapfree(buf_priv->kernel_virtual,
++ buf->total, dev);
+ }
+ }
+- return 0;
++ return 0;
+ }
+
+-int i830_wait_ring(drm_device_t *dev, int n, const char *caller)
++int i830_wait_ring(drm_device_t * dev, int n, const char *caller)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
+- drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+- int iters = 0;
+- unsigned long end;
++ drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
++ int iters = 0;
++ unsigned long end;
+ unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+
+- end = jiffies + (HZ*3);
+- while (ring->space < n) {
+- ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+- ring->space = ring->head - (ring->tail+8);
+- if (ring->space < 0) ring->space += ring->Size;
+-
++ end = jiffies + (HZ * 3);
++ while (ring->space < n) {
++ ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
++ ring->space = ring->head - (ring->tail + 8);
++ if (ring->space < 0)
++ ring->space += ring->Size;
++
+ if (ring->head != last_head) {
+- end = jiffies + (HZ*3);
++ end = jiffies + (HZ * 3);
+ last_head = ring->head;
+ }
+-
+- iters++;
+- if(time_before(end, jiffies)) {
+- DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+- DRM_ERROR("lockup\n");
+- goto out_wait_ring;
++
++ iters++;
++ if (time_before(end, jiffies)) {
++ DRM_ERROR("space: %d wanted %d\n", ring->space, n);
++ DRM_ERROR("lockup\n");
++ goto out_wait_ring;
+ }
+ udelay(1);
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
+ }
+
+-out_wait_ring:
+- return iters;
++ out_wait_ring:
++ return iters;
+ }
+
+-static void i830_kernel_lost_context(drm_device_t *dev)
++static void i830_kernel_lost_context(drm_device_t * dev)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
+- drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+-
+- ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+- ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+- ring->space = ring->head - (ring->tail+8);
+- if (ring->space < 0) ring->space += ring->Size;
++ drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
++
++ ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
++ ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
++ ring->space = ring->head - (ring->tail + 8);
++ if (ring->space < 0)
++ ring->space += ring->Size;
+
+ if (ring->head == ring->tail)
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
+ }
+
+-static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
++static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv)
+ {
+- drm_device_dma_t *dma = dev->dma;
+- int my_idx = 36;
+- u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
+- int i;
++ drm_device_dma_t *dma = dev->dma;
++ int my_idx = 36;
++ u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
++ int i;
+
+- if(dma->buf_count > 1019) {
+- /* Not enough space in the status page for the freelist */
+- return -EINVAL;
++ if (dma->buf_count > 1019) {
++ /* Not enough space in the status page for the freelist */
++ return -EINVAL;
+ }
+
+- for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
++ for (i = 0; i < dma->buf_count; i++) {
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+
+- buf_priv->in_use = hw_status++;
+- buf_priv->my_use_idx = my_idx;
+- my_idx += 4;
++ buf_priv->in_use = hw_status++;
++ buf_priv->my_use_idx = my_idx;
++ my_idx += 4;
+
+- *buf_priv->in_use = I830_BUF_FREE;
++ *buf_priv->in_use = I830_BUF_FREE;
+
+- buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
+- buf->total, dev);
++ buf_priv->kernel_virtual = drm_ioremap(buf->bus_address,
++ buf->total, dev);
+ }
+ return 0;
+ }
+
+-static int i830_dma_initialize(drm_device_t *dev,
+- drm_i830_private_t *dev_priv,
+- drm_i830_init_t *init)
++static int i830_dma_initialize(drm_device_t * dev,
++ drm_i830_private_t * dev_priv,
++ drm_i830_init_t * init)
+ {
+ struct list_head *list;
+
+- memset(dev_priv, 0, sizeof(drm_i830_private_t));
++ memset(dev_priv, 0, sizeof(drm_i830_private_t));
+
+ list_for_each(list, &dev->maplist->head) {
+ drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+- if( r_list->map &&
++ if (r_list->map &&
+ r_list->map->type == _DRM_SHM &&
+- r_list->map->flags & _DRM_CONTAINS_LOCK ) {
++ r_list->map->flags & _DRM_CONTAINS_LOCK) {
+ dev_priv->sarea_map = r_list->map;
+- break;
+- }
+- }
++ break;
++ }
++ }
+
+- if(!dev_priv->sarea_map) {
++ if (!dev_priv->sarea_map) {
+ dev->dev_private = (void *)dev_priv;
+ i830_dma_cleanup(dev);
+ DRM_ERROR("can not find sarea!\n");
+ return -EINVAL;
+ }
+ dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+- if(!dev_priv->mmio_map) {
++ if (!dev_priv->mmio_map) {
+ dev->dev_private = (void *)dev_priv;
+ i830_dma_cleanup(dev);
+ DRM_ERROR("can not find mmio map!\n");
+@@ -355,7 +360,7 @@ static int i830_dma_initialize(drm_devic
+ }
+ dev->agp_buffer_token = init->buffers_offset;
+ dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+- if(!dev->agp_buffer_map) {
++ if (!dev->agp_buffer_map) {
+ dev->dev_private = (void *)dev_priv;
+ i830_dma_cleanup(dev);
+ DRM_ERROR("can not find dma buffer map!\n");
+@@ -363,27 +368,26 @@ static int i830_dma_initialize(drm_devic
+ }
+
+ dev_priv->sarea_priv = (drm_i830_sarea_t *)
+- ((u8 *)dev_priv->sarea_map->handle +
+- init->sarea_priv_offset);
++ ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
+
+- dev_priv->ring.Start = init->ring_start;
+- dev_priv->ring.End = init->ring_end;
+- dev_priv->ring.Size = init->ring_size;
+-
+- dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
+- init->ring_start,
+- init->ring_size, dev);
+-
+- if (dev_priv->ring.virtual_start == NULL) {
+- dev->dev_private = (void *) dev_priv;
+- i830_dma_cleanup(dev);
+- DRM_ERROR("can not ioremap virtual address for"
++ dev_priv->ring.Start = init->ring_start;
++ dev_priv->ring.End = init->ring_end;
++ dev_priv->ring.Size = init->ring_size;
++
++ dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base +
++ init->ring_start,
++ init->ring_size, dev);
++
++ if (dev_priv->ring.virtual_start == NULL) {
++ dev->dev_private = (void *)dev_priv;
++ i830_dma_cleanup(dev);
++ DRM_ERROR("can not ioremap virtual address for"
+ " ring buffer\n");
+- return -ENOMEM;
++ return -ENOMEM;
+ }
+
+- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+-
++ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
++
+ dev_priv->w = init->w;
+ dev_priv->h = init->h;
+ dev_priv->pitch = init->pitch;
+@@ -395,10 +399,10 @@ static int i830_dma_initialize(drm_devic
+ dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+ dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+
+- DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
++ DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
+ DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
+- DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
+- DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
++ DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
++ DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
+
+ dev_priv->cpp = init->cpp;
+ /* We are using separate values as placeholders for mechanisms for
+@@ -410,63 +414,64 @@ static int i830_dma_initialize(drm_devic
+ dev_priv->do_boxes = 0;
+ dev_priv->use_mi_batchbuffer_start = 0;
+
+- /* Program Hardware Status Page */
+- dev_priv->hw_status_page =
+- pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+- &dev_priv->dma_status_page);
+- if (!dev_priv->hw_status_page) {
++ /* Program Hardware Status Page */
++ dev_priv->hw_status_page =
++ pci_alloc_consistent(dev->pdev, PAGE_SIZE,
++ &dev_priv->dma_status_page);
++ if (!dev_priv->hw_status_page) {
+ dev->dev_private = (void *)dev_priv;
+ i830_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate hardware status page\n");
+ return -ENOMEM;
+ }
+- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
++ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+-
+- I830_WRITE(0x02080, dev_priv->dma_status_page);
++
++ I830_WRITE(0x02080, dev_priv->dma_status_page);
+ DRM_DEBUG("Enabled hardware status page\n");
+-
+- /* Now we need to init our freelist */
+- if(i830_freelist_init(dev, dev_priv) != 0) {
++
++ /* Now we need to init our freelist */
++ if (i830_freelist_init(dev, dev_priv) != 0) {
+ dev->dev_private = (void *)dev_priv;
+- i830_dma_cleanup(dev);
+- DRM_ERROR("Not enough space in the status page for"
++ i830_dma_cleanup(dev);
++ DRM_ERROR("Not enough space in the status page for"
+ " the freelist\n");
+- return -ENOMEM;
++ return -ENOMEM;
+ }
+ dev->dev_private = (void *)dev_priv;
+
+- return 0;
++ return 0;
+ }
+
+ static int i830_dma_init(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_i830_private_t *dev_priv;
+- drm_i830_init_t init;
+- int retcode = 0;
+-
+- if (copy_from_user(&init, (void * __user) arg, sizeof(init)))
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_i830_private_t *dev_priv;
++ drm_i830_init_t init;
++ int retcode = 0;
++
++ if (copy_from_user(&init, (void *__user)arg, sizeof(init)))
+ return -EFAULT;
+-
+- switch(init.func) {
+- case I830_INIT_DMA:
+- dev_priv = drm_alloc(sizeof(drm_i830_private_t),
+- DRM_MEM_DRIVER);
+- if(dev_priv == NULL) return -ENOMEM;
+- retcode = i830_dma_initialize(dev, dev_priv, &init);
+- break;
+- case I830_CLEANUP_DMA:
+- retcode = i830_dma_cleanup(dev);
+- break;
+- default:
+- retcode = -EINVAL;
+- break;
++
++ switch (init.func) {
++ case I830_INIT_DMA:
++ dev_priv = drm_alloc(sizeof(drm_i830_private_t),
++ DRM_MEM_DRIVER);
++ if (dev_priv == NULL)
++ return -ENOMEM;
++ retcode = i830_dma_initialize(dev, dev_priv, &init);
++ break;
++ case I830_CLEANUP_DMA:
++ retcode = i830_dma_cleanup(dev);
++ break;
++ default:
++ retcode = -EINVAL;
++ break;
+ }
+-
+- return retcode;
++
++ return retcode;
+ }
+
+ #define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+@@ -476,92 +481,89 @@ static int i830_dma_init(struct inode *i
+ /* Most efficient way to verify state for the i830 is as it is
+ * emitted. Non-conformant state is silently dropped.
+ */
+-static void i830EmitContextVerified( drm_device_t *dev,
+- unsigned int *code )
++static void i830EmitContextVerified(drm_device_t * dev, unsigned int *code)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ int i, j = 0;
+ unsigned int tmp;
+ RING_LOCALS;
+
+- BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 );
++ BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4);
+
+- for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) {
++ for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) {
+ tmp = code[i];
+- if ((tmp & (7<<29)) == CMD_3D &&
+- (tmp & (0x1f<<24)) < (0x1d<<24)) {
+- OUT_RING( tmp );
++ if ((tmp & (7 << 29)) == CMD_3D &&
++ (tmp & (0x1f << 24)) < (0x1d << 24)) {
++ OUT_RING(tmp);
+ j++;
+ } else {
+ DRM_ERROR("Skipping %d\n", i);
+ }
+ }
+
+- OUT_RING( STATE3D_CONST_BLEND_COLOR_CMD );
+- OUT_RING( code[I830_CTXREG_BLENDCOLR] );
++ OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD);
++ OUT_RING(code[I830_CTXREG_BLENDCOLR]);
+ j += 2;
+
+- for ( i = I830_CTXREG_VF ; i < I830_CTXREG_MCSB0 ; i++ ) {
++ for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) {
+ tmp = code[i];
+- if ((tmp & (7<<29)) == CMD_3D &&
+- (tmp & (0x1f<<24)) < (0x1d<<24)) {
+- OUT_RING( tmp );
++ if ((tmp & (7 << 29)) == CMD_3D &&
++ (tmp & (0x1f << 24)) < (0x1d << 24)) {
++ OUT_RING(tmp);
+ j++;
+ } else {
+ DRM_ERROR("Skipping %d\n", i);
+ }
+ }
+
+- OUT_RING( STATE3D_MAP_COORD_SETBIND_CMD );
+- OUT_RING( code[I830_CTXREG_MCSB1] );
++ OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD);
++ OUT_RING(code[I830_CTXREG_MCSB1]);
+ j += 2;
+
+- if (j & 1)
+- OUT_RING( 0 );
++ if (j & 1)
++ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+
+-static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code )
++static void i830EmitTexVerified(drm_device_t * dev, unsigned int *code)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ int i, j = 0;
+ unsigned int tmp;
+ RING_LOCALS;
+
+ if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
+- (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) ==
+- (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) {
++ (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) ==
++ (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) {
+
+- BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
++ BEGIN_LP_RING(I830_TEX_SETUP_SIZE);
+
+- OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */
+- OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */
+- OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */
+- OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */
+- OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */
+- OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */
+-
+- for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
++ OUT_RING(code[I830_TEXREG_MI0]); /* TM0LI */
++ OUT_RING(code[I830_TEXREG_MI1]); /* TM0S0 */
++ OUT_RING(code[I830_TEXREG_MI2]); /* TM0S1 */
++ OUT_RING(code[I830_TEXREG_MI3]); /* TM0S2 */
++ OUT_RING(code[I830_TEXREG_MI4]); /* TM0S3 */
++ OUT_RING(code[I830_TEXREG_MI5]); /* TM0S4 */
++
++ for (i = 6; i < I830_TEX_SETUP_SIZE; i++) {
+ tmp = code[i];
+- OUT_RING( tmp );
++ OUT_RING(tmp);
+ j++;
+- }
++ }
+
+- if (j & 1)
+- OUT_RING( 0 );
++ if (j & 1)
++ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+- }
+- else
++ } else
+ printk("rejected packet %x\n", code[0]);
+ }
+
+-static void i830EmitTexBlendVerified( drm_device_t *dev,
+- unsigned int *code,
+- unsigned int num)
++static void i830EmitTexBlendVerified(drm_device_t * dev,
++ unsigned int *code, unsigned int num)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ int i, j = 0;
+ unsigned int tmp;
+ RING_LOCALS;
+@@ -569,59 +571,54 @@ static void i830EmitTexBlendVerified( dr
+ if (!num)
+ return;
+
+- BEGIN_LP_RING( num + 1 );
++ BEGIN_LP_RING(num + 1);
+
+- for ( i = 0 ; i < num ; i++ ) {
++ for (i = 0; i < num; i++) {
+ tmp = code[i];
+- OUT_RING( tmp );
++ OUT_RING(tmp);
+ j++;
+ }
+
+- if (j & 1)
+- OUT_RING( 0 );
++ if (j & 1)
++ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+
+-static void i830EmitTexPalette( drm_device_t *dev,
+- unsigned int *palette,
+- int number,
+- int is_shared )
++static void i830EmitTexPalette(drm_device_t * dev,
++ unsigned int *palette, int number, int is_shared)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ int i;
+ RING_LOCALS;
+
+ return;
+
+- BEGIN_LP_RING( 258 );
++ BEGIN_LP_RING(258);
+
+- if(is_shared == 1) {
++ if (is_shared == 1) {
+ OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
+- MAP_PALETTE_NUM(0) |
+- MAP_PALETTE_BOTH);
++ MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH);
+ } else {
+ OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
+ }
+- for(i = 0; i < 256; i++) {
++ for (i = 0; i < 256; i++) {
+ OUT_RING(palette[i]);
+ }
+ OUT_RING(0);
+- /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop!
++ /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop!
+ */
+ }
+
+ /* Need to do some additional checking when setting the dest buffer.
+ */
+-static void i830EmitDestVerified( drm_device_t *dev,
+- unsigned int *code )
+-{
+- drm_i830_private_t *dev_priv = dev->dev_private;
++static void i830EmitDestVerified(drm_device_t * dev, unsigned int *code)
++{
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ unsigned int tmp;
+ RING_LOCALS;
+
+- BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 );
+-
++ BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10);
+
+ tmp = code[I830_DESTREG_CBUFADDR];
+ if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+@@ -630,18 +627,18 @@ static void i830EmitDestVerified( drm_de
+ OUT_RING(0);
+ }
+
+- OUT_RING( CMD_OP_DESTBUFFER_INFO );
+- OUT_RING( BUF_3D_ID_COLOR_BACK |
+- BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
+- BUF_3D_USE_FENCE);
+- OUT_RING( tmp );
+- OUT_RING( 0 );
+-
+- OUT_RING( CMD_OP_DESTBUFFER_INFO );
+- OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
+- BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
+- OUT_RING( dev_priv->zi1 );
+- OUT_RING( 0 );
++ OUT_RING(CMD_OP_DESTBUFFER_INFO);
++ OUT_RING(BUF_3D_ID_COLOR_BACK |
++ BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
++ BUF_3D_USE_FENCE);
++ OUT_RING(tmp);
++ OUT_RING(0);
++
++ OUT_RING(CMD_OP_DESTBUFFER_INFO);
++ OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
++ BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
++ OUT_RING(dev_priv->zi1);
++ OUT_RING(0);
+ } else {
+ DRM_ERROR("bad di1 %x (allow %x or %x)\n",
+ tmp, dev_priv->front_di1, dev_priv->back_di1);
+@@ -650,83 +647,80 @@ static void i830EmitDestVerified( drm_de
+ /* invarient:
+ */
+
++ OUT_RING(GFX_OP_DESTBUFFER_VARS);
++ OUT_RING(code[I830_DESTREG_DV1]);
+
+- OUT_RING( GFX_OP_DESTBUFFER_VARS );
+- OUT_RING( code[I830_DESTREG_DV1] );
+-
+- OUT_RING( GFX_OP_DRAWRECT_INFO );
+- OUT_RING( code[I830_DESTREG_DR1] );
+- OUT_RING( code[I830_DESTREG_DR2] );
+- OUT_RING( code[I830_DESTREG_DR3] );
+- OUT_RING( code[I830_DESTREG_DR4] );
++ OUT_RING(GFX_OP_DRAWRECT_INFO);
++ OUT_RING(code[I830_DESTREG_DR1]);
++ OUT_RING(code[I830_DESTREG_DR2]);
++ OUT_RING(code[I830_DESTREG_DR3]);
++ OUT_RING(code[I830_DESTREG_DR4]);
+
+ /* Need to verify this */
+ tmp = code[I830_DESTREG_SENABLE];
+- if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
+- OUT_RING( tmp );
++ if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
++ OUT_RING(tmp);
+ } else {
+ DRM_ERROR("bad scissor enable\n");
+- OUT_RING( 0 );
++ OUT_RING(0);
+ }
+
+- OUT_RING( GFX_OP_SCISSOR_RECT );
+- OUT_RING( code[I830_DESTREG_SR1] );
+- OUT_RING( code[I830_DESTREG_SR2] );
+- OUT_RING( 0 );
++ OUT_RING(GFX_OP_SCISSOR_RECT);
++ OUT_RING(code[I830_DESTREG_SR1]);
++ OUT_RING(code[I830_DESTREG_SR2]);
++ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+
+-static void i830EmitStippleVerified( drm_device_t *dev,
+- unsigned int *code )
++static void i830EmitStippleVerified(drm_device_t * dev, unsigned int *code)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+- BEGIN_LP_RING( 2 );
+- OUT_RING( GFX_OP_STIPPLE );
+- OUT_RING( code[1] );
+- ADVANCE_LP_RING();
++ BEGIN_LP_RING(2);
++ OUT_RING(GFX_OP_STIPPLE);
++ OUT_RING(code[1]);
++ ADVANCE_LP_RING();
+ }
+
+-
+-static void i830EmitState( drm_device_t *dev )
++static void i830EmitState(drm_device_t * dev)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
+- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+ DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
+
+ if (dirty & I830_UPLOAD_BUFFERS) {
+- i830EmitDestVerified( dev, sarea_priv->BufferState );
++ i830EmitDestVerified(dev, sarea_priv->BufferState);
+ sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
+ }
+
+ if (dirty & I830_UPLOAD_CTX) {
+- i830EmitContextVerified( dev, sarea_priv->ContextState );
++ i830EmitContextVerified(dev, sarea_priv->ContextState);
+ sarea_priv->dirty &= ~I830_UPLOAD_CTX;
+ }
+
+ if (dirty & I830_UPLOAD_TEX0) {
+- i830EmitTexVerified( dev, sarea_priv->TexState[0] );
++ i830EmitTexVerified(dev, sarea_priv->TexState[0]);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
+ }
+
+ if (dirty & I830_UPLOAD_TEX1) {
+- i830EmitTexVerified( dev, sarea_priv->TexState[1] );
++ i830EmitTexVerified(dev, sarea_priv->TexState[1]);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
+ }
+
+ if (dirty & I830_UPLOAD_TEXBLEND0) {
+- i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[0],
+- sarea_priv->TexBlendStateWordsUsed[0]);
++ i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0],
++ sarea_priv->TexBlendStateWordsUsed[0]);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
+ }
+
+ if (dirty & I830_UPLOAD_TEXBLEND1) {
+- i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[1],
+- sarea_priv->TexBlendStateWordsUsed[1]);
++ i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1],
++ sarea_priv->TexBlendStateWordsUsed[1]);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
+ }
+
+@@ -759,36 +753,32 @@ static void i830EmitState( drm_device_t
+ /* 1.3:
+ */
+ if (dirty & I830_UPLOAD_STIPPLE) {
+- i830EmitStippleVerified( dev,
+- sarea_priv->StippleState);
++ i830EmitStippleVerified(dev, sarea_priv->StippleState);
+ sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
+ }
+
+ if (dirty & I830_UPLOAD_TEX2) {
+- i830EmitTexVerified( dev, sarea_priv->TexState2 );
++ i830EmitTexVerified(dev, sarea_priv->TexState2);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
+ }
+
+ if (dirty & I830_UPLOAD_TEX3) {
+- i830EmitTexVerified( dev, sarea_priv->TexState3 );
++ i830EmitTexVerified(dev, sarea_priv->TexState3);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
+ }
+
+-
+ if (dirty & I830_UPLOAD_TEXBLEND2) {
+- i830EmitTexBlendVerified(
+- dev,
+- sarea_priv->TexBlendState2,
+- sarea_priv->TexBlendStateWordsUsed2);
++ i830EmitTexBlendVerified(dev,
++ sarea_priv->TexBlendState2,
++ sarea_priv->TexBlendStateWordsUsed2);
+
+ sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
+ }
+
+ if (dirty & I830_UPLOAD_TEXBLEND3) {
+- i830EmitTexBlendVerified(
+- dev,
+- sarea_priv->TexBlendState3,
+- sarea_priv->TexBlendStateWordsUsed3);
++ i830EmitTexBlendVerified(dev,
++ sarea_priv->TexBlendState3,
++ sarea_priv->TexBlendStateWordsUsed3);
+ sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
+ }
+ }
+@@ -797,97 +787,96 @@ static void i830EmitState( drm_device_t
+ * Performance monitoring functions
+ */
+
+-static void i830_fill_box( drm_device_t *dev,
+- int x, int y, int w, int h,
+- int r, int g, int b )
++static void i830_fill_box(drm_device_t * dev,
++ int x, int y, int w, int h, int r, int g, int b)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ u32 color;
+ unsigned int BR13, CMD;
+ RING_LOCALS;
+
+- BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24);
++ BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24);
+ CMD = XY_COLOR_BLT_CMD;
+ x += dev_priv->sarea_priv->boxes[0].x1;
+ y += dev_priv->sarea_priv->boxes[0].y1;
+
+ if (dev_priv->cpp == 4) {
+- BR13 |= (1<<25);
++ BR13 |= (1 << 25);
+ CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
+- color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
++ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ } else {
+ color = (((r & 0xf8) << 8) |
+- ((g & 0xfc) << 3) |
+- ((b & 0xf8) >> 3));
++ ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+ }
+
+- BEGIN_LP_RING( 6 );
+- OUT_RING( CMD );
+- OUT_RING( BR13 );
+- OUT_RING( (y << 16) | x );
+- OUT_RING( ((y+h) << 16) | (x+w) );
+-
+- if ( dev_priv->current_page == 1 ) {
+- OUT_RING( dev_priv->front_offset );
+- } else {
+- OUT_RING( dev_priv->back_offset );
+- }
++ BEGIN_LP_RING(6);
++ OUT_RING(CMD);
++ OUT_RING(BR13);
++ OUT_RING((y << 16) | x);
++ OUT_RING(((y + h) << 16) | (x + w));
+
+- OUT_RING( color );
++ if (dev_priv->current_page == 1) {
++ OUT_RING(dev_priv->front_offset);
++ } else {
++ OUT_RING(dev_priv->back_offset);
++ }
++
++ OUT_RING(color);
+ ADVANCE_LP_RING();
+ }
+
+-static void i830_cp_performance_boxes( drm_device_t *dev )
++static void i830_cp_performance_boxes(drm_device_t * dev)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+
+ /* Purple box for page flipping
+ */
+- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP )
+- i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 );
++ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP)
++ i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255);
+
+ /* Red box if we have to wait for idle at any point
+ */
+- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT )
+- i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 );
++ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT)
++ i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0);
+
+ /* Blue box: lost context?
+ */
+- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT )
+- i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 );
++ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT)
++ i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255);
+
+ /* Yellow box for texture swaps
+ */
+- if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD )
+- i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 );
++ if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD)
++ i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0);
+
+ /* Green box if hardware never idles (as far as we can tell)
+ */
+- if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) )
+- i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 );
+-
++ if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY))
++ i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0);
+
+- /* Draw bars indicating number of buffers allocated
++ /* Draw bars indicating number of buffers allocated
+ * (not a great measure, easily confused)
+ */
+ if (dev_priv->dma_used) {
+ int bar = dev_priv->dma_used / 10240;
+- if (bar > 100) bar = 100;
+- if (bar < 1) bar = 1;
+- i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 );
++ if (bar > 100)
++ bar = 100;
++ if (bar < 1)
++ bar = 1;
++ i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128);
+ dev_priv->dma_used = 0;
+ }
+
+ dev_priv->sarea_priv->perf_boxes = 0;
+ }
+
+-static void i830_dma_dispatch_clear( drm_device_t *dev, int flags,
++static void i830_dma_dispatch_clear(drm_device_t * dev, int flags,
+ unsigned int clear_color,
+ unsigned int clear_zval,
+ unsigned int clear_depthmask)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
+- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int pitch = dev_priv->pitch;
+@@ -896,90 +885,90 @@ static void i830_dma_dispatch_clear( drm
+ unsigned int BR13, CMD, D_CMD;
+ RING_LOCALS;
+
+-
+- if ( dev_priv->current_page == 1 ) {
++ if (dev_priv->current_page == 1) {
+ unsigned int tmp = flags;
+
+ flags &= ~(I830_FRONT | I830_BACK);
+- if ( tmp & I830_FRONT ) flags |= I830_BACK;
+- if ( tmp & I830_BACK ) flags |= I830_FRONT;
++ if (tmp & I830_FRONT)
++ flags |= I830_BACK;
++ if (tmp & I830_BACK)
++ flags |= I830_FRONT;
+ }
+
+- i830_kernel_lost_context(dev);
++ i830_kernel_lost_context(dev);
+
+- switch(cpp) {
+- case 2:
+- BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
++ switch (cpp) {
++ case 2:
++ BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
+ D_CMD = CMD = XY_COLOR_BLT_CMD;
+ break;
+ case 4:
+- BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
+- CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
++ BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
++ CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
+ XY_COLOR_BLT_WRITE_RGB);
+ D_CMD = XY_COLOR_BLT_CMD;
+- if(clear_depthmask & 0x00ffffff)
++ if (clear_depthmask & 0x00ffffff)
+ D_CMD |= XY_COLOR_BLT_WRITE_RGB;
+- if(clear_depthmask & 0xff000000)
++ if (clear_depthmask & 0xff000000)
+ D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
+ break;
+ default:
+- BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
++ BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
+ D_CMD = CMD = XY_COLOR_BLT_CMD;
+ break;
+ }
+
+- if (nbox > I830_NR_SAREA_CLIPRECTS)
+- nbox = I830_NR_SAREA_CLIPRECTS;
++ if (nbox > I830_NR_SAREA_CLIPRECTS)
++ nbox = I830_NR_SAREA_CLIPRECTS;
+
+- for (i = 0 ; i < nbox ; i++, pbox++) {
++ for (i = 0; i < nbox; i++, pbox++) {
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+- pbox->x2 > dev_priv->w ||
+- pbox->y2 > dev_priv->h)
++ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+ continue;
+
+- if ( flags & I830_FRONT ) {
+- DRM_DEBUG("clear front\n");
+- BEGIN_LP_RING( 6 );
+- OUT_RING( CMD );
+- OUT_RING( BR13 );
+- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
+- OUT_RING( dev_priv->front_offset );
+- OUT_RING( clear_color );
++ if (flags & I830_FRONT) {
++ DRM_DEBUG("clear front\n");
++ BEGIN_LP_RING(6);
++ OUT_RING(CMD);
++ OUT_RING(BR13);
++ OUT_RING((pbox->y1 << 16) | pbox->x1);
++ OUT_RING((pbox->y2 << 16) | pbox->x2);
++ OUT_RING(dev_priv->front_offset);
++ OUT_RING(clear_color);
+ ADVANCE_LP_RING();
+ }
+
+- if ( flags & I830_BACK ) {
++ if (flags & I830_BACK) {
+ DRM_DEBUG("clear back\n");
+- BEGIN_LP_RING( 6 );
+- OUT_RING( CMD );
+- OUT_RING( BR13 );
+- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
+- OUT_RING( dev_priv->back_offset );
+- OUT_RING( clear_color );
++ BEGIN_LP_RING(6);
++ OUT_RING(CMD);
++ OUT_RING(BR13);
++ OUT_RING((pbox->y1 << 16) | pbox->x1);
++ OUT_RING((pbox->y2 << 16) | pbox->x2);
++ OUT_RING(dev_priv->back_offset);
++ OUT_RING(clear_color);
+ ADVANCE_LP_RING();
+ }
+
+- if ( flags & I830_DEPTH ) {
++ if (flags & I830_DEPTH) {
+ DRM_DEBUG("clear depth\n");
+- BEGIN_LP_RING( 6 );
+- OUT_RING( D_CMD );
+- OUT_RING( BR13 );
+- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
+- OUT_RING( dev_priv->depth_offset );
+- OUT_RING( clear_zval );
++ BEGIN_LP_RING(6);
++ OUT_RING(D_CMD);
++ OUT_RING(BR13);
++ OUT_RING((pbox->y1 << 16) | pbox->x1);
++ OUT_RING((pbox->y2 << 16) | pbox->x2);
++ OUT_RING(dev_priv->depth_offset);
++ OUT_RING(clear_zval);
+ ADVANCE_LP_RING();
+ }
+ }
+ }
+
+-static void i830_dma_dispatch_swap( drm_device_t *dev )
++static void i830_dma_dispatch_swap(drm_device_t * dev)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
+- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int pitch = dev_priv->pitch;
+@@ -990,202 +979,192 @@ static void i830_dma_dispatch_swap( drm_
+
+ DRM_DEBUG("swapbuffers\n");
+
+- i830_kernel_lost_context(dev);
++ i830_kernel_lost_context(dev);
+
+ if (dev_priv->do_boxes)
+- i830_cp_performance_boxes( dev );
++ i830_cp_performance_boxes(dev);
+
+- switch(cpp) {
+- case 2:
+- BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
++ switch (cpp) {
++ case 2:
++ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
+ case 4:
+- BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
++ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
+ CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ break;
+ default:
+- BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
++ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
+ }
+
++ if (nbox > I830_NR_SAREA_CLIPRECTS)
++ nbox = I830_NR_SAREA_CLIPRECTS;
+
+- if (nbox > I830_NR_SAREA_CLIPRECTS)
+- nbox = I830_NR_SAREA_CLIPRECTS;
+-
+- for (i = 0 ; i < nbox; i++, pbox++)
+- {
++ for (i = 0; i < nbox; i++, pbox++) {
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+- pbox->x2 > dev_priv->w ||
+- pbox->y2 > dev_priv->h)
++ pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+ continue;
+-
++
+ DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+- pbox->x1, pbox->y1,
+- pbox->x2, pbox->y2);
++ pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+
+- BEGIN_LP_RING( 8 );
+- OUT_RING( CMD );
+- OUT_RING( BR13 );
+- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+- OUT_RING( (pbox->y2 << 16) | pbox->x2 );
++ BEGIN_LP_RING(8);
++ OUT_RING(CMD);
++ OUT_RING(BR13);
++ OUT_RING((pbox->y1 << 16) | pbox->x1);
++ OUT_RING((pbox->y2 << 16) | pbox->x2);
+
+- if (dev_priv->current_page == 0)
+- OUT_RING( dev_priv->front_offset );
++ if (dev_priv->current_page == 0)
++ OUT_RING(dev_priv->front_offset);
+ else
+- OUT_RING( dev_priv->back_offset );
++ OUT_RING(dev_priv->back_offset);
+
+- OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+- OUT_RING( BR13 & 0xffff );
++ OUT_RING((pbox->y1 << 16) | pbox->x1);
++ OUT_RING(BR13 & 0xffff);
+
+- if (dev_priv->current_page == 0)
+- OUT_RING( dev_priv->back_offset );
++ if (dev_priv->current_page == 0)
++ OUT_RING(dev_priv->back_offset);
+ else
+- OUT_RING( dev_priv->front_offset );
++ OUT_RING(dev_priv->front_offset);
+
+ ADVANCE_LP_RING();
+ }
+ }
+
+-static void i830_dma_dispatch_flip( drm_device_t *dev )
++static void i830_dma_dispatch_flip(drm_device_t * dev)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+- DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
+- __FUNCTION__,
+- dev_priv->current_page,
+- dev_priv->sarea_priv->pf_current_page);
++ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
++ __FUNCTION__,
++ dev_priv->current_page,
++ dev_priv->sarea_priv->pf_current_page);
+
+- i830_kernel_lost_context(dev);
++ i830_kernel_lost_context(dev);
+
+ if (dev_priv->do_boxes) {
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
+- i830_cp_performance_boxes( dev );
++ i830_cp_performance_boxes(dev);
+ }
+
+-
+- BEGIN_LP_RING( 2 );
+- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+- OUT_RING( 0 );
++ BEGIN_LP_RING(2);
++ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+- BEGIN_LP_RING( 6 );
+- OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP );
+- OUT_RING( 0 );
+- if ( dev_priv->current_page == 0 ) {
+- OUT_RING( dev_priv->back_offset );
++ BEGIN_LP_RING(6);
++ OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
++ OUT_RING(0);
++ if (dev_priv->current_page == 0) {
++ OUT_RING(dev_priv->back_offset);
+ dev_priv->current_page = 1;
+ } else {
+- OUT_RING( dev_priv->front_offset );
++ OUT_RING(dev_priv->front_offset);
+ dev_priv->current_page = 0;
+ }
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+
+-
+- BEGIN_LP_RING( 2 );
+- OUT_RING( MI_WAIT_FOR_EVENT |
+- MI_WAIT_FOR_PLANE_A_FLIP );
+- OUT_RING( 0 );
++ BEGIN_LP_RING(2);
++ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+-
+
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+ }
+
+-static void i830_dma_dispatch_vertex(drm_device_t *dev,
+- drm_buf_t *buf,
+- int discard,
+- int used)
++static void i830_dma_dispatch_vertex(drm_device_t * dev,
++ drm_buf_t * buf, int discard, int used)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+- drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+- drm_clip_rect_t *box = sarea_priv->boxes;
+- int nbox = sarea_priv->nbox;
++ drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ drm_clip_rect_t *box = sarea_priv->boxes;
++ int nbox = sarea_priv->nbox;
+ unsigned long address = (unsigned long)buf->bus_address;
+- unsigned long start = address - dev->agp->base;
++ unsigned long start = address - dev->agp->base;
+ int i = 0, u;
+- RING_LOCALS;
++ RING_LOCALS;
+
+- i830_kernel_lost_context(dev);
++ i830_kernel_lost_context(dev);
+
+- if (nbox > I830_NR_SAREA_CLIPRECTS)
++ if (nbox > I830_NR_SAREA_CLIPRECTS)
+ nbox = I830_NR_SAREA_CLIPRECTS;
+
+ if (discard) {
+- u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
++ u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+ I830_BUF_HARDWARE);
+- if(u != I830_BUF_CLIENT) {
++ if (u != I830_BUF_CLIENT) {
+ DRM_DEBUG("xxxx 2\n");
+ }
+ }
+
+- if (used > 4*1023)
++ if (used > 4 * 1023)
+ used = 0;
+
+ if (sarea_priv->dirty)
+- i830EmitState( dev );
++ i830EmitState(dev);
+
+- DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
++ DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
+ address, used, nbox);
+
+- dev_priv->counter++;
+- DRM_DEBUG( "dispatch counter : %ld\n", dev_priv->counter);
+- DRM_DEBUG( "i830_dma_dispatch\n");
+- DRM_DEBUG( "start : %lx\n", start);
+- DRM_DEBUG( "used : %d\n", used);
+- DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4);
++ dev_priv->counter++;
++ DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
++ DRM_DEBUG("i830_dma_dispatch\n");
++ DRM_DEBUG("start : %lx\n", start);
++ DRM_DEBUG("used : %d\n", used);
++ DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
+
+ if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
+ u32 *vp = buf_priv->kernel_virtual;
+
+ vp[0] = (GFX_OP_PRIMITIVE |
+- sarea_priv->vertex_prim |
+- ((used/4)-2));
++ sarea_priv->vertex_prim | ((used / 4) - 2));
+
+ if (dev_priv->use_mi_batchbuffer_start) {
+- vp[used/4] = MI_BATCH_BUFFER_END;
+- used += 4;
++ vp[used / 4] = MI_BATCH_BUFFER_END;
++ used += 4;
+ }
+-
++
+ if (used & 4) {
+- vp[used/4] = 0;
++ vp[used / 4] = 0;
+ used += 4;
+ }
+
+ i830_unmap_buffer(buf);
+ }
+-
++
+ if (used) {
+ do {
+ if (i < nbox) {
+ BEGIN_LP_RING(6);
+- OUT_RING( GFX_OP_DRAWRECT_INFO );
+- OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] );
+- OUT_RING( box[i].x1 | (box[i].y1<<16) );
+- OUT_RING( box[i].x2 | (box[i].y2<<16) );
+- OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] );
+- OUT_RING( 0 );
++ OUT_RING(GFX_OP_DRAWRECT_INFO);
++ OUT_RING(sarea_priv->
++ BufferState[I830_DESTREG_DR1]);
++ OUT_RING(box[i].x1 | (box[i].y1 << 16));
++ OUT_RING(box[i].x2 | (box[i].y2 << 16));
++ OUT_RING(sarea_priv->
++ BufferState[I830_DESTREG_DR4]);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+
+ if (dev_priv->use_mi_batchbuffer_start) {
+ BEGIN_LP_RING(2);
+- OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );
+- OUT_RING( start | MI_BATCH_NON_SECURE );
++ OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
++ OUT_RING(start | MI_BATCH_NON_SECURE);
+ ADVANCE_LP_RING();
+- }
+- else {
++ } else {
+ BEGIN_LP_RING(4);
+- OUT_RING( MI_BATCH_BUFFER );
+- OUT_RING( start | MI_BATCH_NON_SECURE );
+- OUT_RING( start + used - 4 );
+- OUT_RING( 0 );
++ OUT_RING(MI_BATCH_BUFFER);
++ OUT_RING(start | MI_BATCH_NON_SECURE);
++ OUT_RING(start + used - 4);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+
+@@ -1195,61 +1174,60 @@ static void i830_dma_dispatch_vertex(drm
+ if (discard) {
+ dev_priv->counter++;
+
+- (void) cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+- I830_BUF_HARDWARE);
++ (void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
++ I830_BUF_HARDWARE);
+
+ BEGIN_LP_RING(8);
+- OUT_RING( CMD_STORE_DWORD_IDX );
+- OUT_RING( 20 );
+- OUT_RING( dev_priv->counter );
+- OUT_RING( CMD_STORE_DWORD_IDX );
+- OUT_RING( buf_priv->my_use_idx );
+- OUT_RING( I830_BUF_FREE );
+- OUT_RING( CMD_REPORT_HEAD );
+- OUT_RING( 0 );
++ OUT_RING(CMD_STORE_DWORD_IDX);
++ OUT_RING(20);
++ OUT_RING(dev_priv->counter);
++ OUT_RING(CMD_STORE_DWORD_IDX);
++ OUT_RING(buf_priv->my_use_idx);
++ OUT_RING(I830_BUF_FREE);
++ OUT_RING(CMD_REPORT_HEAD);
++ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
+ }
+
+-
+-static void i830_dma_quiescent(drm_device_t *dev)
++static void i830_dma_quiescent(drm_device_t * dev)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
+- RING_LOCALS;
++ drm_i830_private_t *dev_priv = dev->dev_private;
++ RING_LOCALS;
+
+- i830_kernel_lost_context(dev);
++ i830_kernel_lost_context(dev);
+
+- BEGIN_LP_RING(4);
+- OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+- OUT_RING( CMD_REPORT_HEAD );
+- OUT_RING( 0 );
+- OUT_RING( 0 );
+- ADVANCE_LP_RING();
++ BEGIN_LP_RING(4);
++ OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
++ OUT_RING(CMD_REPORT_HEAD);
++ OUT_RING(0);
++ OUT_RING(0);
++ ADVANCE_LP_RING();
+
+- i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
++ i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+ }
+
+-static int i830_flush_queue(drm_device_t *dev)
++static int i830_flush_queue(drm_device_t * dev)
+ {
+- drm_i830_private_t *dev_priv = dev->dev_private;
++ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+- int i, ret = 0;
+- RING_LOCALS;
+-
+- i830_kernel_lost_context(dev);
+-
+- BEGIN_LP_RING(2);
+- OUT_RING( CMD_REPORT_HEAD );
+- OUT_RING( 0 );
+- ADVANCE_LP_RING();
+-
+- i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
+-
+- for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+-
+- int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
++ int i, ret = 0;
++ RING_LOCALS;
++
++ i830_kernel_lost_context(dev);
++
++ BEGIN_LP_RING(2);
++ OUT_RING(CMD_REPORT_HEAD);
++ OUT_RING(0);
++ ADVANCE_LP_RING();
++
++ i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
++
++ for (i = 0; i < dma->buf_count; i++) {
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
++
++ int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
+ I830_BUF_FREE);
+
+ if (used == I830_BUF_HARDWARE)
+@@ -1258,62 +1236,66 @@ static int i830_flush_queue(drm_device_t
+ DRM_DEBUG("still on client\n");
+ }
+
+- return ret;
++ return ret;
+ }
+
+ /* Must be called with the lock held */
+-void i830_reclaim_buffers(drm_device_t *dev, struct file *filp)
++void i830_reclaim_buffers(drm_device_t * dev, struct file *filp)
+ {
+ drm_device_dma_t *dma = dev->dma;
+- int i;
++ int i;
+
+- if (!dma) return;
+- if (!dev->dev_private) return;
+- if (!dma->buflist) return;
++ if (!dma)
++ return;
++ if (!dev->dev_private)
++ return;
++ if (!dma->buflist)
++ return;
+
+- i830_flush_queue(dev);
++ i830_flush_queue(dev);
+
+ for (i = 0; i < dma->buf_count; i++) {
+- drm_buf_t *buf = dma->buflist[ i ];
+- drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+-
++ drm_buf_t *buf = dma->buflist[i];
++ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
++
+ if (buf->filp == filp && buf_priv) {
+- int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
++ int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+ I830_BUF_FREE);
+
+ if (used == I830_BUF_CLIENT)
+ DRM_DEBUG("reclaimed from client\n");
+- if(buf_priv->currently_mapped == I830_BUF_MAPPED)
+- buf_priv->currently_mapped = I830_BUF_UNMAPPED;
++ if (buf_priv->currently_mapped == I830_BUF_MAPPED)
++ buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+ }
+ }
+ }
+
+-static int i830_flush_ioctl(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++static int i830_flush_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- i830_flush_queue(dev);
+- return 0;
++ i830_flush_queue(dev);
++ return 0;
+ }
+
+ static int i830_dma_vertex(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_device_dma_t *dma = dev->dma;
+- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+- drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+- dev_priv->sarea_priv;
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
++ u32 *hw_status = dev_priv->hw_status_page;
++ drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
++ dev_priv->sarea_priv;
+ drm_i830_vertex_t vertex;
+
+- if (copy_from_user(&vertex, (drm_i830_vertex_t __user *)arg, sizeof(vertex)))
++ if (copy_from_user
++ (&vertex, (drm_i830_vertex_t __user *) arg, sizeof(vertex)))
+ return -EFAULT;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+@@ -1321,15 +1303,16 @@ static int i830_dma_vertex(struct inode
+ DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
+ vertex.idx, vertex.used, vertex.discard);
+
+- if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
++ if (vertex.idx < 0 || vertex.idx > dma->buf_count)
++ return -EINVAL;
++
++ i830_dma_dispatch_vertex(dev,
++ dma->buflist[vertex.idx],
++ vertex.discard, vertex.used);
++
++ sarea_priv->last_enqueue = dev_priv->counter - 1;
++ sarea_priv->last_dispatch = (int)hw_status[5];
+
+- i830_dma_dispatch_vertex( dev,
+- dma->buflist[ vertex.idx ],
+- vertex.discard, vertex.used );
+-
+- sarea_priv->last_enqueue = dev_priv->counter-1;
+- sarea_priv->last_dispatch = (int) hw_status[5];
+-
+ return 0;
+ }
+
+@@ -1340,9 +1323,10 @@ static int i830_clear_bufs(struct inode
+ drm_device_t *dev = priv->head->dev;
+ drm_i830_clear_t clear;
+
+- if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))
++ if (copy_from_user
++ (&clear, (drm_i830_clear_t __user *) arg, sizeof(clear)))
+ return -EFAULT;
+-
++
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ /* GH: Someone's doing nasty things... */
+@@ -1350,11 +1334,10 @@ static int i830_clear_bufs(struct inode
+ return -EINVAL;
+ }
+
+- i830_dma_dispatch_clear( dev, clear.flags,
+- clear.clear_color,
+- clear.clear_depth,
+- clear.clear_depthmask);
+- return 0;
++ i830_dma_dispatch_clear(dev, clear.flags,
++ clear.clear_color,
++ clear.clear_depth, clear.clear_depthmask);
++ return 0;
+ }
+
+ static int i830_swap_bufs(struct inode *inode, struct file *filp,
+@@ -1362,20 +1345,18 @@ static int i830_swap_bufs(struct inode *
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+-
++
+ DRM_DEBUG("i830_swap_bufs\n");
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- i830_dma_dispatch_swap( dev );
+- return 0;
++ i830_dma_dispatch_swap(dev);
++ return 0;
+ }
+
+-
+-
+ /* Not sure why this isn't set all the time:
+- */
+-static void i830_do_init_pageflip( drm_device_t *dev )
++ */
++static void i830_do_init_pageflip(drm_device_t * dev)
+ {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+@@ -1385,20 +1366,20 @@ static void i830_do_init_pageflip( drm_d
+ dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+ }
+
+-static int i830_do_cleanup_pageflip( drm_device_t *dev )
++static int i830_do_cleanup_pageflip(drm_device_t * dev)
+ {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+ if (dev_priv->current_page != 0)
+- i830_dma_dispatch_flip( dev );
++ i830_dma_dispatch_flip(dev);
+
+ dev_priv->page_flipping = 0;
+ return 0;
+ }
+
+ static int i830_flip_bufs(struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg)
++ unsigned int cmd, unsigned long arg)
+ {
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+@@ -1408,45 +1389,45 @@ static int i830_flip_bufs(struct inode *
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if (!dev_priv->page_flipping)
+- i830_do_init_pageflip( dev );
++ if (!dev_priv->page_flipping)
++ i830_do_init_pageflip(dev);
+
+- i830_dma_dispatch_flip( dev );
+- return 0;
++ i830_dma_dispatch_flip(dev);
++ return 0;
+ }
+
+ static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+- drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+- dev_priv->sarea_priv;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
++ u32 *hw_status = dev_priv->hw_status_page;
++ drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
++ dev_priv->sarea_priv;
+
+- sarea_priv->last_dispatch = (int) hw_status[5];
++ sarea_priv->last_dispatch = (int)hw_status[5];
+ return 0;
+ }
+
+ static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
+- int retcode = 0;
+- drm_i830_dma_t d;
+- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+- drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+- dev_priv->sarea_priv;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
++ int retcode = 0;
++ drm_i830_dma_t d;
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
++ u32 *hw_status = dev_priv->hw_status_page;
++ drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
++ dev_priv->sarea_priv;
+
+ DRM_DEBUG("getbuf\n");
+- if (copy_from_user(&d, (drm_i830_dma_t __user *)arg, sizeof(d)))
++ if (copy_from_user(&d, (drm_i830_dma_t __user *) arg, sizeof(d)))
+ return -EFAULT;
+-
++
+ LOCK_TEST_WITH_RETURN(dev, filp);
+-
++
+ d.granted = 0;
+
+ retcode = i830_dma_get_buffer(dev, &d, filp);
+@@ -1454,46 +1435,45 @@ static int i830_getbuf(struct inode *ino
+ DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
+ current->pid, retcode, d.granted);
+
+- if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
++ if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
+ return -EFAULT;
+- sarea_priv->last_dispatch = (int) hw_status[5];
++ sarea_priv->last_dispatch = (int)hw_status[5];
+
+ return retcode;
+ }
+
+ static int i830_copybuf(struct inode *inode,
+- struct file *filp, unsigned int cmd, unsigned long arg)
++ struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ /* Never copy - 2.4.x doesn't need it */
+ return 0;
+ }
+
+ static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ return 0;
+ }
+
+-
+-
+-static int i830_getparam( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++static int i830_getparam(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_getparam_t param;
+ int value;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+- if (copy_from_user(¶m, (drm_i830_getparam_t __user *)arg, sizeof(param) ))
++ if (copy_from_user
++ (¶m, (drm_i830_getparam_t __user *) arg, sizeof(param)))
+ return -EFAULT;
+
+- switch( param.param ) {
++ switch (param.param) {
+ case I830_PARAM_IRQ_ACTIVE:
+ value = dev->irq_enabled;
+ break;
+@@ -1501,32 +1481,32 @@ static int i830_getparam( struct inode *
+ return -EINVAL;
+ }
+
+- if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
+- DRM_ERROR( "copy_to_user\n" );
++ if (copy_to_user(param.value, &value, sizeof(int))) {
++ DRM_ERROR("copy_to_user\n");
+ return -EFAULT;
+ }
+-
++
+ return 0;
+ }
+
+-
+-static int i830_setparam( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg )
++static int i830_setparam(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_setparam_t param;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+- if (copy_from_user(¶m, (drm_i830_setparam_t __user *)arg, sizeof(param) ))
++ if (copy_from_user
++ (¶m, (drm_i830_setparam_t __user *) arg, sizeof(param)))
+ return -EFAULT;
+
+- switch( param.param ) {
++ switch (param.param) {
+ case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
+ dev_priv->use_mi_batchbuffer_start = param.value;
+ break;
+@@ -1537,13 +1517,12 @@ static int i830_setparam( struct inode *
+ return 0;
+ }
+
+-
+-void i830_driver_pretakedown(drm_device_t *dev)
++void i830_driver_pretakedown(drm_device_t * dev)
+ {
+- i830_dma_cleanup( dev );
++ i830_dma_cleanup(dev);
+ }
+
+-void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp)
++void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+ {
+ if (dev->dev_private) {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+@@ -1553,32 +1532,32 @@ void i830_driver_prerelease(drm_device_t
+ }
+ }
+
+-void i830_driver_release(drm_device_t *dev, struct file *filp)
++void i830_driver_release(drm_device_t * dev, struct file *filp)
+ {
+ i830_reclaim_buffers(dev, filp);
+ }
+
+-int i830_driver_dma_quiescent(drm_device_t *dev)
++int i830_driver_dma_quiescent(drm_device_t * dev)
+ {
+- i830_dma_quiescent( dev );
++ i830_dma_quiescent(dev);
+ return 0;
+ }
+
+ drm_ioctl_desc_t i830_ioctls[] = {
+- [DRM_IOCTL_NR(DRM_I830_INIT)] = { i830_dma_init, 1, 1 },
+- [DRM_IOCTL_NR(DRM_I830_VERTEX)] = { i830_dma_vertex, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_CLEAR)] = { i830_clear_bufs, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_FLUSH)] = { i830_flush_ioctl, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_GETAGE)] = { i830_getage, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_GETBUF)] = { i830_getbuf, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_SWAP)] = { i830_swap_bufs, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_COPY)] = { i830_copybuf, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = { i830_docopy, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_FLIP)] = { i830_flip_bufs, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = { i830_irq_emit, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = { i830_irq_wait, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = { i830_getparam, 1, 0 },
+- [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = { i830_setparam, 1, 0 }
++ [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, 1, 1},
++ [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, 1, 0},
++ [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, 1, 0}
+ };
+
+ int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
+diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
+--- a/drivers/char/drm/i830_drm.h
++++ b/drivers/char/drm/i830_drm.h
+@@ -33,14 +33,14 @@
+ #define I830_UPLOAD_CTX 0x1
+ #define I830_UPLOAD_BUFFERS 0x2
+ #define I830_UPLOAD_CLIPRECTS 0x4
+-#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
+-#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
+-#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
+-#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
+-#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
+-#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
+-#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
+-#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
++#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
++#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
++#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
++#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
++#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
++#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
++#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
++#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
+ #define I830_UPLOAD_TEX_N_IMAGE(n) (0x100 << (n * 2))
+ #define I830_UPLOAD_TEX_N_CUBE(n) (0x200 << (n * 2))
+ #define I830_UPLOAD_TEXIMAGE_MASK 0xff00
+@@ -65,7 +65,7 @@
+ * or in a piecewise fashion as required.
+ */
+
+-/* Destbuffer state
++/* Destbuffer state
+ * - backbuffer linear offset and pitch -- invarient in the current dri
+ * - zbuffer linear offset and pitch -- also invarient
+ * - drawing origin in back and depth buffers.
+@@ -103,7 +103,7 @@
+ #define I830_CTXREG_AA 9
+ #define I830_CTXREG_FOGCOLOR 10
+ #define I830_CTXREG_BLENDCOLR0 11
+-#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
++#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
+ #define I830_CTXREG_VF 13
+ #define I830_CTXREG_VF2 14
+ #define I830_CTXREG_MCSB0 15
+@@ -111,12 +111,11 @@
+ #define I830_CTX_SETUP_SIZE 17
+
+ /* 1.3: Stipple state
+- */
++ */
+ #define I830_STPREG_ST0 0
+ #define I830_STPREG_ST1 1
+ #define I830_STP_SETUP_SIZE 2
+
+-
+ /* Texture state (per tex unit)
+ */
+
+@@ -132,23 +131,23 @@
+ #define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */
+ #define I830_TEX_SETUP_SIZE 10
+
+-#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
++#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
+ #define I830_TEXREG_TM0S0 1
+ #define I830_TEXREG_TM0S1 2
+ #define I830_TEXREG_TM0S2 3
+ #define I830_TEXREG_TM0S3 4
+ #define I830_TEXREG_TM0S4 5
+-#define I830_TEXREG_NOP0 6 /* noop */
+-#define I830_TEXREG_NOP1 7 /* noop */
+-#define I830_TEXREG_NOP2 8 /* noop */
+-#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
++#define I830_TEXREG_NOP0 6 /* noop */
++#define I830_TEXREG_NOP1 7 /* noop */
++#define I830_TEXREG_NOP2 8 /* noop */
++#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
+ #define __I830_TEX_SETUP_SIZE 10
+
+ #define I830_FRONT 0x1
+ #define I830_BACK 0x2
+ #define I830_DEPTH 0x4
+
+-#endif /* _I830_DEFINES_ */
++#endif /* _I830_DEFINES_ */
+
+ typedef struct _drm_i830_init {
+ enum {
+@@ -177,19 +176,19 @@ typedef struct _drm_i830_init {
+ * structure as well */
+
+ typedef struct _drm_i830_tex_region {
+- unsigned char next, prev; /* indices to form a circular LRU */
++ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+ } drm_i830_tex_region_t;
+
+ typedef struct _drm_i830_sarea {
+ unsigned int ContextState[I830_CTX_SETUP_SIZE];
+- unsigned int BufferState[I830_DEST_SETUP_SIZE];
++ unsigned int BufferState[I830_DEST_SETUP_SIZE];
+ unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
+ unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
+ unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
+ unsigned int Palette[2][256];
+- unsigned int dirty;
++ unsigned int dirty;
+
+ unsigned int nbox;
+ drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
+@@ -207,26 +206,26 @@ typedef struct _drm_i830_sarea {
+ * texture space, and can make informed decisions as to which
+ * areas to kick out. There is no need to choose whether to
+ * kick out your own texture or someone else's - simply eject
+- * them all in LRU order.
++ * them all in LRU order.
+ */
+
+- drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS+1];
+- /* Last elt is sentinal */
+- int texAge; /* last time texture was uploaded */
+- int last_enqueue; /* last time a buffer was enqueued */
++ drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS + 1];
++ /* Last elt is sentinal */
++ int texAge; /* last time texture was uploaded */
++ int last_enqueue; /* last time a buffer was enqueued */
+ int last_dispatch; /* age of the most recently dispatched buffer */
+- int last_quiescent; /* */
++ int last_quiescent; /* */
+ int ctxOwner; /* last context to upload state */
+
+ int vertex_prim;
+
+- int pf_enabled; /* is pageflipping allowed? */
+- int pf_active;
+- int pf_current_page; /* which buffer is being displayed? */
+-
+- int perf_boxes; /* performance boxes to be displayed */
+-
+- /* Here's the state for texunits 2,3:
++ int pf_enabled; /* is pageflipping allowed? */
++ int pf_active;
++ int pf_current_page; /* which buffer is being displayed? */
++
++ int perf_boxes; /* performance boxes to be displayed */
++
++ /* Here's the state for texunits 2,3:
+ */
+ unsigned int TexState2[I830_TEX_SETUP_SIZE];
+ unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
+@@ -241,12 +240,11 @@ typedef struct _drm_i830_sarea {
+
+ /* Flags for perf_boxes
+ */
+-#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
+-#define I830_BOX_FLIP 0x2 /* populated by kernel */
+-#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
+-#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
+-#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
+-
++#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
++#define I830_BOX_FLIP 0x2 /* populated by kernel */
++#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
++#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
++#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
+
+ /* I830 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+@@ -289,23 +287,21 @@ typedef struct _drm_i830_clear {
+ unsigned int clear_depthmask;
+ } drm_i830_clear_t;
+
+-
+-
+ /* These may be placeholders if we have more cliprects than
+ * I830_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
+ * false, indicating that the buffer will be dispatched again with a
+ * new set of cliprects.
+ */
+ typedef struct _drm_i830_vertex {
+- int idx; /* buffer index */
++ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int discard; /* client is finished with the buffer? */
+ } drm_i830_vertex_t;
+
+ typedef struct _drm_i830_copy_t {
+- int idx; /* buffer index */
++ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+- void __user *address; /* Address to copy from */
++ void __user *address; /* Address to copy from */
+ } drm_i830_copy_t;
+
+ typedef struct drm_i830_dma {
+@@ -315,7 +311,6 @@ typedef struct drm_i830_dma {
+ int granted;
+ } drm_i830_dma_t;
+
+-
+ /* 1.3: Userspace can request & wait on irq's:
+ */
+ typedef struct drm_i830_irq_emit {
+@@ -326,7 +321,6 @@ typedef struct drm_i830_irq_wait {
+ int irq_seq;
+ } drm_i830_irq_wait_t;
+
+-
+ /* 1.3: New ioctl to query kernel params:
+ */
+ #define I830_PARAM_IRQ_ACTIVE 1
+@@ -336,7 +330,6 @@ typedef struct drm_i830_getparam {
+ int __user *value;
+ } drm_i830_getparam_t;
+
+-
+ /* 1.3: New ioctl to set kernel params:
+ */
+ #define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
+@@ -346,5 +339,4 @@ typedef struct drm_i830_setparam {
+ int value;
+ } drm_i830_setparam_t;
+
+-
+-#endif /* _I830_DRM_H_ */
++#endif /* _I830_DRM_H_ */
+diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
+--- a/drivers/char/drm/i830_drv.c
++++ b/drivers/char/drm/i830_drv.c
+@@ -40,36 +40,34 @@
+
+ #include "drm_pciids.h"
+
+-static int postinit( struct drm_device *dev, unsigned long flags )
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+ dev->counters += 4;
+ dev->types[6] = _DRM_STAT_IRQ;
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+ dev->types[9] = _DRM_STAT_DMA;
+-
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -77,11 +75,10 @@ static struct pci_device_id pciidlist[]
+ i830_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t i830_ioctls[];
+-extern int i830_max_ioctl;
+-
+ static struct drm_driver driver = {
+- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
++ .driver_features =
++ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
++ DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
+ #if USE_IRQS
+ .driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
+ #endif
+@@ -104,18 +101,19 @@ static struct drm_driver driver = {
+ .version = version,
+ .ioctls = i830_ioctls,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
+- },
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
++ }
++ ,
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+
+ };
+
+@@ -133,6 +131,6 @@ static void __exit i830_exit(void)
+ module_init(i830_init);
+ module_exit(i830_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
+--- a/drivers/char/drm/i830_drv.h
++++ b/drivers/char/drm/i830_drv.h
+@@ -11,11 +11,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -63,14 +63,14 @@
+ #define USE_IRQS 0
+
+ typedef struct drm_i830_buf_priv {
+- u32 *in_use;
+- int my_use_idx;
++ u32 *in_use;
++ int my_use_idx;
+ int currently_mapped;
+ void __user *virtual;
+ void *kernel_virtual;
+ } drm_i830_buf_priv_t;
+
+-typedef struct _drm_i830_ring_buffer{
++typedef struct _drm_i830_ring_buffer {
+ int tail_mask;
+ unsigned long Start;
+ unsigned long End;
+@@ -86,17 +86,17 @@ typedef struct drm_i830_private {
+ drm_map_t *mmio_map;
+
+ drm_i830_sarea_t *sarea_priv;
+- drm_i830_ring_buffer_t ring;
++ drm_i830_ring_buffer_t ring;
+
+- void * hw_status_page;
+- unsigned long counter;
++ void *hw_status_page;
++ unsigned long counter;
+
+ dma_addr_t dma_status_page;
+
+ drm_buf_t *mmap_buffer;
+-
++
+ u32 front_di1, back_di1, zi1;
+-
++
+ int back_offset;
+ int depth_offset;
+ int front_offset;
+@@ -113,43 +113,39 @@ typedef struct drm_i830_private {
+ int page_flipping;
+
+ wait_queue_head_t irq_queue;
+- atomic_t irq_received;
+- atomic_t irq_emitted;
++ atomic_t irq_received;
++ atomic_t irq_emitted;
+
+ int use_mi_batchbuffer_start;
+
+ } drm_i830_private_t;
+
++extern drm_ioctl_desc_t i830_ioctls[];
++extern int i830_max_ioctl;
++
+ /* i830_dma.c */
+-extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
++extern void i830_reclaim_buffers(drm_device_t * dev, struct file *filp);
+
+ /* i830_irq.c */
+-extern int i830_irq_emit( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-extern int i830_irq_wait( struct inode *inode, struct file *filp,
+- unsigned int cmd, unsigned long arg );
+-
+-extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
+-extern void i830_driver_irq_preinstall( drm_device_t *dev );
+-extern void i830_driver_irq_postinstall( drm_device_t *dev );
+-extern void i830_driver_irq_uninstall( drm_device_t *dev );
+-extern void i830_driver_pretakedown(drm_device_t *dev);
+-extern void i830_driver_release(drm_device_t *dev, struct file *filp);
+-extern int i830_driver_dma_quiescent(drm_device_t *dev);
+-extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
++extern int i830_irq_emit(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++extern int i830_irq_wait(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg);
++
++extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
++extern void i830_driver_irq_preinstall(drm_device_t * dev);
++extern void i830_driver_irq_postinstall(drm_device_t * dev);
++extern void i830_driver_irq_uninstall(drm_device_t * dev);
++extern void i830_driver_pretakedown(drm_device_t * dev);
++extern void i830_driver_release(drm_device_t * dev, struct file *filp);
++extern int i830_driver_dma_quiescent(drm_device_t * dev);
++extern void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+ extern int i830_driver_device_is_agp(drm_device_t * dev);
+
+-#define I830_BASE(reg) ((unsigned long) \
+- dev_priv->mmio_map->handle)
+-#define I830_ADDR(reg) (I830_BASE(reg) + reg)
+-#define I830_DEREF(reg) *(__volatile__ unsigned int *)I830_ADDR(reg)
+-#define I830_READ(reg) readl((volatile u32 *)I830_ADDR(reg))
+-#define I830_WRITE(reg,val) writel(val, (volatile u32 *)I830_ADDR(reg))
+-#define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg)
+-#define I830_READ16(reg) I830_DEREF16(reg)
+-#define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0)
+-
+-
++#define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
++#define I830_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
++#define I830_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
++#define I830_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
+
+ #define I830_VERBOSE 0
+
+@@ -168,7 +164,6 @@ extern int i830_driver_device_is_agp(drm
+ virt = dev_priv->ring.virtual_start; \
+ } while (0)
+
+-
+ #define OUT_RING(n) do { \
+ if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
+ *(volatile unsigned int *)(virt + outring) = n; \
+@@ -184,8 +179,7 @@ extern int i830_driver_device_is_agp(drm
+ I830_WRITE(LP_RING + RING_TAIL, outring); \
+ } while(0)
+
+-extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
+-
++extern int i830_wait_ring(drm_device_t * dev, int n, const char *caller);
+
+ #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
+ #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
+@@ -200,7 +194,6 @@ extern int i830_wait_ring(drm_device_t *
+ #define INST_OP_FLUSH 0x02000000
+ #define INST_FLUSH_MAP_CACHE 0x00000001
+
+-
+ #define BB1_START_ADDR_MASK (~0x7)
+ #define BB1_PROTECTED (1<<0)
+ #define BB1_UNPROTECTED (0<<0)
+@@ -213,7 +206,6 @@ extern int i830_wait_ring(drm_device_t *
+
+ #define I830_IRQ_RESERVED ((1<<13)|(3<<2))
+
+-
+ #define LP_RING 0x2030
+ #define HP_RING 0x2040
+ #define RING_TAIL 0x00
+@@ -225,7 +217,7 @@ extern int i830_wait_ring(drm_device_t *
+ #define RING_START 0x08
+ #define START_ADDR 0x0xFFFFF000
+ #define RING_LEN 0x0C
+-#define RING_NR_PAGES 0x001FF000
++#define RING_NR_PAGES 0x001FF000
+ #define RING_REPORT_MASK 0x00000006
+ #define RING_REPORT_64K 0x00000002
+ #define RING_REPORT_128K 0x00000004
+@@ -291,10 +283,9 @@ extern int i830_wait_ring(drm_device_t *
+ #define MI_BATCH_NON_SECURE (1)
+
+ #define MI_WAIT_FOR_EVENT ((0x3<<23))
+-#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
+-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
++#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
++#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+
+ #define MI_LOAD_SCAN_LINES_INCL ((0x12<<23))
+
+ #endif
+-
+diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
+--- a/drivers/char/drm/i830_irq.c
++++ b/drivers/char/drm/i830_irq.c
+@@ -9,11 +9,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -33,28 +33,27 @@
+ #include <linux/interrupt.h> /* For task queue support */
+ #include <linux/delay.h>
+
+-
+-irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
++irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+- drm_device_t *dev = (drm_device_t *)arg;
+- drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+- u16 temp;
++ drm_device_t *dev = (drm_device_t *) arg;
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
++ u16 temp;
+
+- temp = I830_READ16(I830REG_INT_IDENTITY_R);
++ temp = I830_READ16(I830REG_INT_IDENTITY_R);
+ DRM_DEBUG("%x\n", temp);
+
+- if ( !( temp & 2 ) )
++ if (!(temp & 2))
+ return IRQ_NONE;
+
+- I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
++ I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
+
+ atomic_inc(&dev_priv->irq_received);
+- wake_up_interruptible(&dev_priv->irq_queue);
++ wake_up_interruptible(&dev_priv->irq_queue);
+
+ return IRQ_HANDLED;
+ }
+
+-static int i830_emit_irq(drm_device_t *dev)
++static int i830_emit_irq(drm_device_t * dev)
+ {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+@@ -63,27 +62,25 @@ static int i830_emit_irq(drm_device_t *d
+
+ atomic_inc(&dev_priv->irq_emitted);
+
+- BEGIN_LP_RING(2);
+- OUT_RING( 0 );
+- OUT_RING( GFX_OP_USER_INTERRUPT );
+- ADVANCE_LP_RING();
++ BEGIN_LP_RING(2);
++ OUT_RING(0);
++ OUT_RING(GFX_OP_USER_INTERRUPT);
++ ADVANCE_LP_RING();
+
+ return atomic_read(&dev_priv->irq_emitted);
+ }
+
+-
+-static int i830_wait_irq(drm_device_t *dev, int irq_nr)
++static int i830_wait_irq(drm_device_t * dev, int irq_nr)
+ {
+- drm_i830_private_t *dev_priv =
+- (drm_i830_private_t *)dev->dev_private;
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+ DECLARE_WAITQUEUE(entry, current);
+- unsigned long end = jiffies + HZ*3;
++ unsigned long end = jiffies + HZ * 3;
+ int ret = 0;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+- if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+- return 0;
++ if (atomic_read(&dev_priv->irq_received) >= irq_nr)
++ return 0;
+
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
+
+@@ -91,21 +88,21 @@ static int i830_wait_irq(drm_device_t *d
+
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+- if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+- break;
+- if((signed)(end - jiffies) <= 0) {
++ if (atomic_read(&dev_priv->irq_received) >= irq_nr)
++ break;
++ if ((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
+- I830_READ16( I830REG_INT_IDENTITY_R ),
+- I830_READ16( I830REG_INT_MASK_R ),
+- I830_READ16( I830REG_INT_ENABLE_R ),
+- I830_READ16( I830REG_HWSTAM ));
++ I830_READ16(I830REG_INT_IDENTITY_R),
++ I830_READ16(I830REG_INT_MASK_R),
++ I830_READ16(I830REG_INT_ENABLE_R),
++ I830_READ16(I830REG_HWSTAM));
+
+- ret = -EBUSY; /* Lockup? Missed irq? */
++ ret = -EBUSY; /* Lockup? Missed irq? */
+ break;
+ }
+- schedule_timeout(HZ*3);
+- if (signal_pending(current)) {
+- ret = -EINTR;
++ schedule_timeout(HZ * 3);
++ if (signal_pending(current)) {
++ ret = -EINTR;
+ break;
+ }
+ }
+@@ -115,89 +112,87 @@ static int i830_wait_irq(drm_device_t *d
+ return ret;
+ }
+
+-
+ /* Needs the lock as it touches the ring.
+ */
+-int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg )
++int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_irq_emit_t emit;
+ int result;
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+- if (copy_from_user( &emit, (drm_i830_irq_emit_t __user *)arg, sizeof(emit) ))
++ if (copy_from_user
++ (&emit, (drm_i830_irq_emit_t __user *) arg, sizeof(emit)))
+ return -EFAULT;
+
+- result = i830_emit_irq( dev );
++ result = i830_emit_irq(dev);
+
+- if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) {
+- DRM_ERROR( "copy_to_user\n" );
++ if (copy_to_user(emit.irq_seq, &result, sizeof(int))) {
++ DRM_ERROR("copy_to_user\n");
+ return -EFAULT;
+ }
+
+ return 0;
+ }
+
+-
+ /* Doesn't need the hardware lock.
+ */
+-int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg )
++int i830_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
+ {
+- drm_file_t *priv = filp->private_data;
+- drm_device_t *dev = priv->head->dev;
++ drm_file_t *priv = filp->private_data;
++ drm_device_t *dev = priv->head->dev;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ drm_i830_irq_wait_t irqwait;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+- if (copy_from_user( &irqwait, (drm_i830_irq_wait_t __user *)arg,
+- sizeof(irqwait) ))
++ if (copy_from_user(&irqwait, (drm_i830_irq_wait_t __user *) arg,
++ sizeof(irqwait)))
+ return -EFAULT;
+
+- return i830_wait_irq( dev, irqwait.irq_seq );
++ return i830_wait_irq(dev, irqwait.irq_seq);
+ }
+
+-
+ /* drm_dma.h hooks
+ */
+-void i830_driver_irq_preinstall( drm_device_t *dev ) {
+- drm_i830_private_t *dev_priv =
+- (drm_i830_private_t *)dev->dev_private;
+-
+- I830_WRITE16( I830REG_HWSTAM, 0xffff );
+- I830_WRITE16( I830REG_INT_MASK_R, 0x0 );
+- I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
++void i830_driver_irq_preinstall(drm_device_t * dev)
++{
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
++
++ I830_WRITE16(I830REG_HWSTAM, 0xffff);
++ I830_WRITE16(I830REG_INT_MASK_R, 0x0);
++ I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
+ atomic_set(&dev_priv->irq_received, 0);
+ atomic_set(&dev_priv->irq_emitted, 0);
+ init_waitqueue_head(&dev_priv->irq_queue);
+ }
+
+-void i830_driver_irq_postinstall( drm_device_t *dev ) {
+- drm_i830_private_t *dev_priv =
+- (drm_i830_private_t *)dev->dev_private;
++void i830_driver_irq_postinstall(drm_device_t * dev)
++{
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+
+- I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
++ I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
+ }
+
+-void i830_driver_irq_uninstall( drm_device_t *dev ) {
+- drm_i830_private_t *dev_priv =
+- (drm_i830_private_t *)dev->dev_private;
++void i830_driver_irq_uninstall(drm_device_t * dev)
++{
++ drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+ if (!dev_priv)
+ return;
+
+- I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
+- I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
++ I830_WRITE16(I830REG_INT_MASK_R, 0xffff);
++ I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
+ }
+diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
+--- a/drivers/char/drm/i915_dma.c
++++ b/drivers/char/drm/i915_dma.c
+@@ -85,14 +85,14 @@ static int i915_dma_cleanup(drm_device_t
+ * is freed, it's too late.
+ */
+ if (dev->irq)
+- drm_irq_uninstall (dev);
++ drm_irq_uninstall(dev);
+
+ if (dev->dev_private) {
+ drm_i915_private_t *dev_priv =
+ (drm_i915_private_t *) dev->dev_private;
+
+ if (dev_priv->ring.virtual_start) {
+- drm_core_ioremapfree( &dev_priv->ring.map, dev);
++ drm_core_ioremapfree(&dev_priv->ring.map, dev);
+ }
+
+ if (dev_priv->status_page_dmah) {
+@@ -101,8 +101,8 @@ static int i915_dma_cleanup(drm_device_t
+ I915_WRITE(0x02080, 0x1ffff000);
+ }
+
+- drm_free (dev->dev_private, sizeof(drm_i915_private_t),
+- DRM_MEM_DRIVER);
++ drm_free(dev->dev_private, sizeof(drm_i915_private_t),
++ DRM_MEM_DRIVER);
+
+ dev->dev_private = NULL;
+ }
+@@ -146,7 +146,7 @@ static int i915_initialize(drm_device_t
+ dev_priv->ring.map.flags = 0;
+ dev_priv->ring.map.mtrr = 0;
+
+- drm_core_ioremap( &dev_priv->ring.map, dev );
++ drm_core_ioremap(&dev_priv->ring.map, dev);
+
+ if (dev_priv->ring.map.handle == NULL) {
+ dev->dev_private = (void *)dev_priv;
+@@ -243,8 +243,8 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
+
+ switch (init.func) {
+ case I915_INIT_DMA:
+- dev_priv = drm_alloc (sizeof(drm_i915_private_t),
+- DRM_MEM_DRIVER);
++ dev_priv = drm_alloc(sizeof(drm_i915_private_t),
++ DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return DRM_ERR(ENOMEM);
+ retcode = i915_initialize(dev, dev_priv, &init);
+@@ -297,7 +297,7 @@ static int do_validate_cmd(int cmd)
+ case 0x1c:
+ return 1;
+ case 0x1d:
+- switch ((cmd>>16)&0xff) {
++ switch ((cmd >> 16) & 0xff) {
+ case 0x3:
+ return (cmd & 0x1f) + 2;
+ case 0x4:
+@@ -699,20 +699,20 @@ static int i915_setparam(DRM_IOCTL_ARGS)
+ return 0;
+ }
+
+-void i915_driver_pretakedown(drm_device_t *dev)
++void i915_driver_pretakedown(drm_device_t * dev)
+ {
+- if ( dev->dev_private ) {
++ if (dev->dev_private) {
+ drm_i915_private_t *dev_priv = dev->dev_private;
+- i915_mem_takedown( &(dev_priv->agp_heap) );
+- }
+- i915_dma_cleanup( dev );
++ i915_mem_takedown(&(dev_priv->agp_heap));
++ }
++ i915_dma_cleanup(dev);
+ }
+
+-void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
++void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+ {
+- if ( dev->dev_private ) {
++ if (dev->dev_private) {
+ drm_i915_private_t *dev_priv = dev->dev_private;
+- i915_mem_release( dev, filp, dev_priv->agp_heap );
++ i915_mem_release(dev, filp, dev_priv->agp_heap);
+ }
+ }
+
+diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
+--- a/drivers/char/drm/i915_drv.c
++++ b/drivers/char/drm/i915_drv.c
+@@ -34,36 +34,34 @@
+
+ #include "drm_pciids.h"
+
+-static int postinit( struct drm_device *dev, unsigned long flags )
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+ dev->counters += 4;
+ dev->types[6] = _DRM_STAT_IRQ;
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+ dev->types[9] = _DRM_STAT_DMA;
+-
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -71,12 +69,10 @@ static struct pci_device_id pciidlist[]
+ i915_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t i915_ioctls[];
+-extern int i915_max_ioctl;
+-
+ static struct drm_driver driver = {
+- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
++ .driver_features =
++ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
++ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ .pretakedown = i915_driver_pretakedown,
+ .prerelease = i915_driver_prerelease,
+ .device_is_agp = i915_driver_device_is_agp,
+@@ -91,21 +87,21 @@ static struct drm_driver driver = {
+ .version = version,
+ .ioctls = i915_ioctls,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
+ #ifdef CONFIG_COMPAT
+- .compat_ioctl = i915_compat_ioctl,
++ .compat_ioctl = i915_compat_ioctl,
+ #endif
+- },
++ },
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init i915_init(void)
+@@ -122,6 +118,6 @@ static void __exit i915_exit(void)
+ module_init(i915_init);
+ module_exit(i915_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
+--- a/drivers/char/drm/i915_drv.h
++++ b/drivers/char/drm/i915_drv.h
+@@ -99,20 +99,23 @@ typedef struct drm_i915_private {
+ struct mem_block *agp_heap;
+ } drm_i915_private_t;
+
++extern drm_ioctl_desc_t i915_ioctls[];
++extern int i915_max_ioctl;
++
+ /* i915_dma.c */
+ extern void i915_kernel_lost_context(drm_device_t * dev);
+-extern void i915_driver_pretakedown(drm_device_t *dev);
+-extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+-extern int i915_driver_device_is_agp(drm_device_t *dev);
++extern void i915_driver_pretakedown(drm_device_t * dev);
++extern void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp);
++extern int i915_driver_device_is_agp(drm_device_t * dev);
+
+ /* i915_irq.c */
+ extern int i915_irq_emit(DRM_IOCTL_ARGS);
+ extern int i915_irq_wait(DRM_IOCTL_ARGS);
+
+ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
+-extern void i915_driver_irq_preinstall(drm_device_t *dev);
+-extern void i915_driver_irq_postinstall(drm_device_t *dev);
+-extern void i915_driver_irq_uninstall(drm_device_t *dev);
++extern void i915_driver_irq_preinstall(drm_device_t * dev);
++extern void i915_driver_irq_postinstall(drm_device_t * dev);
++extern void i915_driver_irq_uninstall(drm_device_t * dev);
+
+ /* i915_mem.c */
+ extern int i915_mem_alloc(DRM_IOCTL_ARGS);
+@@ -125,7 +128,6 @@ extern void i915_mem_release(drm_device_
+ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+-
+ #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
+ #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
+ #define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
+diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
+--- a/drivers/char/drm/i915_ioc32.c
++++ b/drivers/char/drm/i915_ioc32.c
+@@ -3,7 +3,7 @@
+ *
+ * 32-bit ioctl compatibility routines for the i915 DRM.
+ *
+- * \author Alan Hourihane <alanh at fairlite.demon.co.uk>
++ * \author Alan Hourihane <alanh at fairlite.demon.co.uk>
+ *
+ *
+ * Copyright (C) Paul Mackerras 2005
+@@ -42,51 +42,55 @@ typedef struct _drm_i915_batchbuffer32 {
+ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
+ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
+ int num_cliprects; /* mulitpass with multiple cliprects? */
+- u32 cliprects; /* pointer to userspace cliprects */
++ u32 cliprects; /* pointer to userspace cliprects */
+ } drm_i915_batchbuffer32_t;
+
+ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ drm_i915_batchbuffer32_t batchbuffer32;
+ drm_i915_batchbuffer_t __user *batchbuffer;
+-
+- if (copy_from_user(&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
++
++ if (copy_from_user
++ (&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
+ return -EFAULT;
+-
++
+ batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
+ if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
+ || __put_user(batchbuffer32.start, &batchbuffer->start)
+ || __put_user(batchbuffer32.used, &batchbuffer->used)
+ || __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
+ || __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
+- || __put_user(batchbuffer32.num_cliprects, &batchbuffer->num_cliprects)
++ || __put_user(batchbuffer32.num_cliprects,
++ &batchbuffer->num_cliprects)
+ || __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
+ &batchbuffer->cliprects))
+ return -EFAULT;
+-
++
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_I915_BATCHBUFFER, (unsigned long) batchbuffer);
++ DRM_IOCTL_I915_BATCHBUFFER,
++ (unsigned long)batchbuffer);
+ }
+
+ typedef struct _drm_i915_cmdbuffer32 {
+- u32 buf; /* pointer to userspace command buffer */
++ u32 buf; /* pointer to userspace command buffer */
+ int sz; /* nr bytes in buf */
+ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
+ int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
+ int num_cliprects; /* mulitpass with multiple cliprects? */
+- u32 cliprects; /* pointer to userspace cliprects */
++ u32 cliprects; /* pointer to userspace cliprects */
+ } drm_i915_cmdbuffer32_t;
+
+ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ drm_i915_cmdbuffer32_t cmdbuffer32;
+ drm_i915_cmdbuffer_t __user *cmdbuffer;
+-
+- if (copy_from_user(&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
++
++ if (copy_from_user
++ (&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
+ return -EFAULT;
+-
++
+ cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
+ if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
+ || __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
+@@ -98,9 +102,9 @@ static int compat_i915_cmdbuffer(struct
+ || __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
+ &cmdbuffer->cliprects))
+ return -EFAULT;
+-
++
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_I915_CMDBUFFER, (unsigned long) cmdbuffer);
++ DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
+ }
+
+ typedef struct drm_i915_irq_emit32 {
+@@ -108,12 +112,12 @@ typedef struct drm_i915_irq_emit32 {
+ } drm_i915_irq_emit32_t;
+
+ static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ drm_i915_irq_emit32_t req32;
+ drm_i915_irq_emit_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -123,7 +127,7 @@ static int compat_i915_irq_emit(struct f
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_I915_IRQ_EMIT, (unsigned long) request);
++ DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
+ }
+ typedef struct drm_i915_getparam32 {
+ int param;
+@@ -131,12 +135,12 @@ typedef struct drm_i915_getparam32 {
+ } drm_i915_getparam32_t;
+
+ static int compat_i915_getparam(struct file *file, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ drm_i915_getparam32_t req32;
+ drm_i915_getparam_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -147,7 +151,7 @@ static int compat_i915_getparam(struct f
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_I915_GETPARAM, (unsigned long) request);
++ DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
+ }
+
+ typedef struct drm_i915_mem_alloc32 {
+@@ -158,12 +162,12 @@ typedef struct drm_i915_mem_alloc32 {
+ } drm_i915_mem_alloc32_t;
+
+ static int compat_i915_alloc(struct file *file, unsigned int cmd,
+- unsigned long arg)
++ unsigned long arg)
+ {
+ drm_i915_mem_alloc32_t req32;
+ drm_i915_mem_alloc_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -176,10 +180,9 @@ static int compat_i915_alloc(struct file
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_I915_ALLOC, (unsigned long) request);
++ DRM_IOCTL_I915_ALLOC, (unsigned long)request);
+ }
+
+-
+ drm_ioctl_compat_t *i915_compat_ioctls[] = {
+ [DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
+ [DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
+@@ -197,8 +200,7 @@ drm_ioctl_compat_t *i915_compat_ioctls[]
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+-long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+@@ -206,13 +208,13 @@ long i915_compat_ioctl(struct file *filp
+
+ if (nr < DRM_COMMAND_BASE)
+ return drm_compat_ioctl(filp, cmd, arg);
+-
++
+ if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
+ fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+- ret = (*fn)(filp, cmd, arg);
++ ret = (*fn) (filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
+--- a/drivers/char/drm/i915_mem.c
++++ b/drivers/char/drm/i915_mem.c
+@@ -86,7 +86,7 @@ static void mark_block(drm_device_t * de
+ }
+
+ /* Very simple allocator for agp memory, working on a static range
+- * already mapped into each client's address space.
++ * already mapped into each client's address space.
+ */
+
+ static struct mem_block *split_block(struct mem_block *p, int start, int size,
+@@ -94,7 +94,8 @@ static struct mem_block *split_block(str
+ {
+ /* Maybe cut off the start of an existing block */
+ if (start > p->start) {
+- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
++ struct mem_block *newblock =
++ drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+ if (!newblock)
+ goto out;
+ newblock->start = start;
+@@ -110,7 +111,8 @@ static struct mem_block *split_block(str
+
+ /* Maybe cut off the end of an existing block */
+ if (size < p->size) {
+- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
++ struct mem_block *newblock =
++ drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+ if (!newblock)
+ goto out;
+ newblock->start = start + size;
+diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
+--- a/drivers/char/drm/mga_dma.c
++++ b/drivers/char/drm/mga_dma.c
+@@ -28,7 +28,7 @@
+ /**
+ * \file mga_dma.c
+ * DMA support for MGA G200 / G400.
+- *
++ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Jeff Hartmann <jhartmann at valinux.com>
+ * \author Keith Whitwell <keith at tungstengraphics.com>
+@@ -44,40 +44,40 @@
+ #define MGA_DEFAULT_USEC_TIMEOUT 10000
+ #define MGA_FREELIST_DEBUG 0
+
+-static int mga_do_cleanup_dma( drm_device_t *dev );
++static int mga_do_cleanup_dma(drm_device_t * dev);
+
+ /* ================================================================
+ * Engine control
+ */
+
+-int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
++int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
+ {
+ u32 status = 0;
+ int i;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
+- if ( status == MGA_ENDPRDMASTS ) {
+- MGA_WRITE8( MGA_CRTC_INDEX, 0 );
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
++ if (status == MGA_ENDPRDMASTS) {
++ MGA_WRITE8(MGA_CRTC_INDEX, 0);
+ return 0;
+ }
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ #if MGA_DMA_DEBUG
+- DRM_ERROR( "failed!\n" );
+- DRM_INFO( " status=0x%08x\n", status );
++ DRM_ERROR("failed!\n");
++ DRM_INFO(" status=0x%08x\n", status);
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-static int mga_do_dma_reset( drm_mga_private_t *dev_priv )
++static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ /* The primary DMA stream should look like new right about now.
+ */
+@@ -100,24 +100,25 @@ static int mga_do_dma_reset( drm_mga_pri
+ * Primary DMA stream
+ */
+
+-void mga_do_dma_flush( drm_mga_private_t *dev_priv )
++void mga_do_dma_flush(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+ u32 head, tail;
+ u32 status = 0;
+ int i;
+- DMA_LOCALS;
+- DRM_DEBUG( "\n" );
++ DMA_LOCALS;
++ DRM_DEBUG("\n");
+
+- /* We need to wait so that we can do an safe flush */
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
+- if ( status == MGA_ENDPRDMASTS ) break;
+- DRM_UDELAY( 1 );
++ /* We need to wait so that we can do an safe flush */
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
++ if (status == MGA_ENDPRDMASTS)
++ break;
++ DRM_UDELAY(1);
+ }
+
+- if ( primary->tail == primary->last_flush ) {
+- DRM_DEBUG( " bailing out...\n" );
++ if (primary->tail == primary->last_flush) {
++ DRM_DEBUG(" bailing out...\n");
+ return;
+ }
+
+@@ -127,48 +128,46 @@ void mga_do_dma_flush( drm_mga_private_t
+ * actually (partially?) reads the first of these commands.
+ * See page 4-16 in the G400 manual, middle of the page or so.
+ */
+- BEGIN_DMA( 1 );
++ BEGIN_DMA(1);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000 );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+ ADVANCE_DMA();
+
+ primary->last_flush = primary->tail;
+
+- head = MGA_READ( MGA_PRIMADDRESS );
++ head = MGA_READ(MGA_PRIMADDRESS);
+
+- if ( head <= tail ) {
++ if (head <= tail) {
+ primary->space = primary->size - primary->tail;
+ } else {
+ primary->space = head - tail;
+ }
+
+- DRM_DEBUG( " head = 0x%06lx\n", head - dev_priv->primary->offset );
+- DRM_DEBUG( " tail = 0x%06lx\n", tail - dev_priv->primary->offset );
+- DRM_DEBUG( " space = 0x%06x\n", primary->space );
++ DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset);
++ DRM_DEBUG(" tail = 0x%06lx\n", tail - dev_priv->primary->offset);
++ DRM_DEBUG(" space = 0x%06x\n", primary->space);
+
+ mga_flush_write_combine();
+ MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
+
+- DRM_DEBUG( "done.\n" );
++ DRM_DEBUG("done.\n");
+ }
+
+-void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
++void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+ u32 head, tail;
+ DMA_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ BEGIN_DMA_WRAP();
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000 );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+ ADVANCE_DMA();
+
+@@ -178,45 +177,43 @@ void mga_do_dma_wrap_start( drm_mga_priv
+ primary->last_flush = 0;
+ primary->last_wrap++;
+
+- head = MGA_READ( MGA_PRIMADDRESS );
++ head = MGA_READ(MGA_PRIMADDRESS);
+
+- if ( head == dev_priv->primary->offset ) {
++ if (head == dev_priv->primary->offset) {
+ primary->space = primary->size;
+ } else {
+ primary->space = head - dev_priv->primary->offset;
+ }
+
+- DRM_DEBUG( " head = 0x%06lx\n",
+- head - dev_priv->primary->offset );
+- DRM_DEBUG( " tail = 0x%06x\n", primary->tail );
+- DRM_DEBUG( " wrap = %d\n", primary->last_wrap );
+- DRM_DEBUG( " space = 0x%06x\n", primary->space );
++ DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset);
++ DRM_DEBUG(" tail = 0x%06x\n", primary->tail);
++ DRM_DEBUG(" wrap = %d\n", primary->last_wrap);
++ DRM_DEBUG(" space = 0x%06x\n", primary->space);
+
+ mga_flush_write_combine();
+ MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
+
+- set_bit( 0, &primary->wrapped );
+- DRM_DEBUG( "done.\n" );
++ set_bit(0, &primary->wrapped);
++ DRM_DEBUG("done.\n");
+ }
+
+-void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
++void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ u32 head = dev_priv->primary->offset;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ sarea_priv->last_wrap++;
+- DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap );
++ DRM_DEBUG(" wrap = %d\n", sarea_priv->last_wrap);
+
+ mga_flush_write_combine();
+- MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
++ MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL);
+
+- clear_bit( 0, &primary->wrapped );
+- DRM_DEBUG( "done.\n" );
++ clear_bit(0, &primary->wrapped);
++ DRM_DEBUG("done.\n");
+ }
+
+-
+ /* ================================================================
+ * Freelist management
+ */
+@@ -225,63 +222,61 @@ void mga_do_dma_wrap_end( drm_mga_privat
+ #define MGA_BUFFER_FREE 0
+
+ #if MGA_FREELIST_DEBUG
+-static void mga_freelist_print( drm_device_t *dev )
++static void mga_freelist_print(drm_device_t * dev)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_freelist_t *entry;
+
+- DRM_INFO( "\n" );
+- DRM_INFO( "current dispatch: last=0x%x done=0x%x\n",
+- dev_priv->sarea_priv->last_dispatch,
+- (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
+- dev_priv->primary->offset) );
+- DRM_INFO( "current freelist:\n" );
+-
+- for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
+- DRM_INFO( " %p idx=%2d age=0x%x 0x%06lx\n",
+- entry, entry->buf->idx, entry->age.head,
+- entry->age.head - dev_priv->primary->offset );
++ DRM_INFO("\n");
++ DRM_INFO("current dispatch: last=0x%x done=0x%x\n",
++ dev_priv->sarea_priv->last_dispatch,
++ (unsigned int)(MGA_READ(MGA_PRIMADDRESS) -
++ dev_priv->primary->offset));
++ DRM_INFO("current freelist:\n");
++
++ for (entry = dev_priv->head->next; entry; entry = entry->next) {
++ DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n",
++ entry, entry->buf->idx, entry->age.head,
++ entry->age.head - dev_priv->primary->offset);
+ }
+- DRM_INFO( "\n" );
++ DRM_INFO("\n");
+ }
+ #endif
+
+-static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
++static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_freelist_t *entry;
+ int i;
+- DRM_DEBUG( "count=%d\n", dma->buf_count );
++ DRM_DEBUG("count=%d\n", dma->buf_count);
+
+- dev_priv->head = drm_alloc( sizeof(drm_mga_freelist_t),
+- DRM_MEM_DRIVER );
+- if ( dev_priv->head == NULL )
++ dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
++ if (dev_priv->head == NULL)
+ return DRM_ERR(ENOMEM);
+
+- memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
+- SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
++ memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
++ SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
+
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
++ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+- buf_priv = buf->dev_private;
++ buf_priv = buf->dev_private;
+
+- entry = drm_alloc( sizeof(drm_mga_freelist_t),
+- DRM_MEM_DRIVER );
+- if ( entry == NULL )
++ entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
++ if (entry == NULL)
+ return DRM_ERR(ENOMEM);
+
+- memset( entry, 0, sizeof(drm_mga_freelist_t) );
++ memset(entry, 0, sizeof(drm_mga_freelist_t));
+
+ entry->next = dev_priv->head->next;
+ entry->prev = dev_priv->head;
+- SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
++ SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
+ entry->buf = buf;
+
+- if ( dev_priv->head->next != NULL )
++ if (dev_priv->head->next != NULL)
+ dev_priv->head->next->prev = entry;
+- if ( entry->next == NULL )
++ if (entry->next == NULL)
+ dev_priv->tail = entry;
+
+ buf_priv->list_entry = entry;
+@@ -294,17 +289,17 @@ static int mga_freelist_init( drm_device
+ return 0;
+ }
+
+-static void mga_freelist_cleanup( drm_device_t *dev )
++static void mga_freelist_cleanup(drm_device_t * dev)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_freelist_t *entry;
+ drm_mga_freelist_t *next;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ entry = dev_priv->head;
+- while ( entry ) {
++ while (entry) {
+ next = entry->next;
+- drm_free( entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER );
++ drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+ entry = next;
+ }
+
+@@ -314,71 +309,69 @@ static void mga_freelist_cleanup( drm_de
+ #if 0
+ /* FIXME: Still needed?
+ */
+-static void mga_freelist_reset( drm_device_t *dev )
++static void mga_freelist_reset(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ int i;
+
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
++ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+- buf_priv = buf->dev_private;
+- SET_AGE( &buf_priv->list_entry->age,
+- MGA_BUFFER_FREE, 0 );
++ buf_priv = buf->dev_private;
++ SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0);
+ }
+ }
+ #endif
+
+-static drm_buf_t *mga_freelist_get( drm_device_t *dev )
++static drm_buf_t *mga_freelist_get(drm_device_t * dev)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_freelist_t *next;
+ drm_mga_freelist_t *prev;
+ drm_mga_freelist_t *tail = dev_priv->tail;
+ u32 head, wrap;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- head = MGA_READ( MGA_PRIMADDRESS );
++ head = MGA_READ(MGA_PRIMADDRESS);
+ wrap = dev_priv->sarea_priv->last_wrap;
+
+- DRM_DEBUG( " tail=0x%06lx %d\n",
+- tail->age.head ?
+- tail->age.head - dev_priv->primary->offset : 0,
+- tail->age.wrap );
+- DRM_DEBUG( " head=0x%06lx %d\n",
+- head - dev_priv->primary->offset, wrap );
++ DRM_DEBUG(" tail=0x%06lx %d\n",
++ tail->age.head ?
++ tail->age.head - dev_priv->primary->offset : 0,
++ tail->age.wrap);
++ DRM_DEBUG(" head=0x%06lx %d\n",
++ head - dev_priv->primary->offset, wrap);
+
+- if ( TEST_AGE( &tail->age, head, wrap ) ) {
++ if (TEST_AGE(&tail->age, head, wrap)) {
+ prev = dev_priv->tail->prev;
+ next = dev_priv->tail;
+ prev->next = NULL;
+ next->prev = next->next = NULL;
+ dev_priv->tail = prev;
+- SET_AGE( &next->age, MGA_BUFFER_USED, 0 );
++ SET_AGE(&next->age, MGA_BUFFER_USED, 0);
+ return next->buf;
+ }
+
+- DRM_DEBUG( "returning NULL!\n" );
++ DRM_DEBUG("returning NULL!\n");
+ return NULL;
+ }
+
+-int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
++int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_freelist_t *head, *entry, *prev;
+
+- DRM_DEBUG( "age=0x%06lx wrap=%d\n",
+- buf_priv->list_entry->age.head -
+- dev_priv->primary->offset,
+- buf_priv->list_entry->age.wrap );
++ DRM_DEBUG("age=0x%06lx wrap=%d\n",
++ buf_priv->list_entry->age.head -
++ dev_priv->primary->offset, buf_priv->list_entry->age.wrap);
+
+ entry = buf_priv->list_entry;
+ head = dev_priv->head;
+
+- if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
+- SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
++ if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) {
++ SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
+ prev = dev_priv->tail;
+ prev->next = entry;
+ entry->prev = prev;
+@@ -394,15 +387,13 @@ int mga_freelist_put( drm_device_t *dev,
+ return 0;
+ }
+
+-
+ /* ================================================================
+ * DMA initialization, cleanup
+ */
+
+-
+-int mga_driver_preinit(drm_device_t *dev, unsigned long flags)
++int mga_driver_preinit(drm_device_t * dev, unsigned long flags)
+ {
+- drm_mga_private_t * dev_priv;
++ drm_mga_private_t *dev_priv;
+
+ dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ if (!dev_priv)
+@@ -420,7 +411,7 @@ int mga_driver_preinit(drm_device_t *dev
+ #if __OS_HAS_AGP
+ /**
+ * Bootstrap the driver for AGP DMA.
+- *
++ *
+ * \todo
+ * Investigate whether there is any benifit to storing the WARP microcode in
+ * AGP memory. If not, the microcode may as well always be put in PCI
+@@ -436,18 +427,18 @@ int mga_driver_preinit(drm_device_t *dev
+ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+ {
+- drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
++ drm_mga_private_t *const dev_priv =
++ (drm_mga_private_t *) dev->dev_private;
+ unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+ int err;
+- unsigned offset;
++ unsigned offset;
+ const unsigned secondary_size = dma_bs->secondary_bin_count
+- * dma_bs->secondary_bin_size;
++ * dma_bs->secondary_bin_size;
+ const unsigned agp_size = (dma_bs->agp_size << 20);
+ drm_buf_desc_t req;
+ drm_agp_mode_t mode;
+ drm_agp_info_t info;
+
+-
+ /* Acquire AGP. */
+ err = drm_agp_acquire(dev);
+ if (err) {
+@@ -468,7 +459,6 @@ static int mga_do_agp_dma_bootstrap(drm_
+ return err;
+ }
+
+-
+ /* In addition to the usual AGP mode configuration, the G200 AGP cards
+ * need to have the AGP mode "manually" set.
+ */
+@@ -476,24 +466,22 @@ static int mga_do_agp_dma_bootstrap(drm_
+ if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
+ if (mode.mode & 0x02) {
+ MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
+- }
+- else {
++ } else {
+ MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
+ }
+ }
+
+-
+ /* Allocate and bind AGP memory. */
+ dev_priv->agp_pages = agp_size / PAGE_SIZE;
+- dev_priv->agp_mem = drm_alloc_agp( dev, dev_priv->agp_pages, 0 );
++ dev_priv->agp_mem = drm_alloc_agp(dev, dev_priv->agp_pages, 0);
+ if (dev_priv->agp_mem == NULL) {
+ dev_priv->agp_pages = 0;
+ DRM_ERROR("Unable to allocate %uMB AGP memory\n",
+ dma_bs->agp_size);
+ return DRM_ERR(ENOMEM);
+ }
+-
+- err = drm_bind_agp( dev_priv->agp_mem, 0 );
++
++ err = drm_bind_agp(dev_priv->agp_mem, 0);
+ if (err) {
+ DRM_ERROR("Unable to bind AGP memory\n");
+ return err;
+@@ -506,44 +494,44 @@ static int mga_do_agp_dma_bootstrap(drm_
+ warp_size = PAGE_SIZE;
+
+ offset = 0;
+- err = drm_addmap( dev, offset, warp_size,
+- _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp );
++ err = drm_addmap(dev, offset, warp_size,
++ _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);
+ if (err) {
+ DRM_ERROR("Unable to map WARP microcode\n");
+ return err;
+ }
+
+ offset += warp_size;
+- err = drm_addmap( dev, offset, dma_bs->primary_size,
+- _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary );
++ err = drm_addmap(dev, offset, dma_bs->primary_size,
++ _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary);
+ if (err) {
+ DRM_ERROR("Unable to map primary DMA region\n");
+ return err;
+ }
+
+ offset += dma_bs->primary_size;
+- err = drm_addmap( dev, offset, secondary_size,
+- _DRM_AGP, 0, & dev->agp_buffer_map );
++ err = drm_addmap(dev, offset, secondary_size,
++ _DRM_AGP, 0, &dev->agp_buffer_map);
+ if (err) {
+ DRM_ERROR("Unable to map secondary DMA region\n");
+ return err;
+ }
+
+- (void) memset( &req, 0, sizeof(req) );
++ (void)memset(&req, 0, sizeof(req));
+ req.count = dma_bs->secondary_bin_count;
+ req.size = dma_bs->secondary_bin_size;
+ req.flags = _DRM_AGP_BUFFER;
+ req.agp_start = offset;
+
+- err = drm_addbufs_agp( dev, & req );
++ err = drm_addbufs_agp(dev, &req);
+ if (err) {
+ DRM_ERROR("Unable to add secondary DMA buffers\n");
+ return err;
+ }
+
+ offset += secondary_size;
+- err = drm_addmap( dev, offset, agp_size - offset,
+- _DRM_AGP, 0, & dev_priv->agp_textures );
++ err = drm_addmap(dev, offset, agp_size - offset,
++ _DRM_AGP, 0, &dev_priv->agp_textures);
+ if (err) {
+ DRM_ERROR("Unable to map AGP texture region\n");
+ return err;
+@@ -577,7 +565,7 @@ static int mga_do_agp_dma_bootstrap(drm_
+
+ /**
+ * Bootstrap the driver for PCI DMA.
+- *
++ *
+ * \todo
+ * The algorithm for decreasing the size of the primary DMA buffer could be
+ * better. The size should be rounded up to the nearest page size, then
+@@ -586,20 +574,20 @@ static int mga_do_agp_dma_bootstrap(drm_
+ * \todo
+ * Determine whether the maximum address passed to drm_pci_alloc is correct.
+ * The same goes for drm_addbufs_pci.
+- *
++ *
+ * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
+ */
+ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+ {
+- drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
++ drm_mga_private_t *const dev_priv =
++ (drm_mga_private_t *) dev->dev_private;
+ unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+ unsigned int primary_size;
+ unsigned int bin_count;
+ int err;
+ drm_buf_desc_t req;
+
+-
+ if (dev->dma == NULL) {
+ DRM_ERROR("dev->dma is NULL\n");
+ return DRM_ERR(EFAULT);
+@@ -624,9 +612,8 @@ static int mga_do_pci_dma_bootstrap(drm_
+ * alignment of the primary or secondary DMA buffers.
+ */
+
+- for ( primary_size = dma_bs->primary_size
+- ; primary_size != 0
+- ; primary_size >>= 1 ) {
++ for (primary_size = dma_bs->primary_size; primary_size != 0;
++ primary_size >>= 1) {
+ /* The proper alignment for this mapping is 0x04 */
+ err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
+ _DRM_READ_ONLY, &dev_priv->primary);
+@@ -641,24 +628,23 @@ static int mga_do_pci_dma_bootstrap(drm_
+
+ if (dev_priv->primary->size != dma_bs->primary_size) {
+ DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
+- dma_bs->primary_size,
+- (unsigned) dev_priv->primary->size);
++ dma_bs->primary_size,
++ (unsigned)dev_priv->primary->size);
+ dma_bs->primary_size = dev_priv->primary->size;
+ }
+
+- for ( bin_count = dma_bs->secondary_bin_count
+- ; bin_count > 0
+- ; bin_count-- ) {
+- (void) memset( &req, 0, sizeof(req) );
++ for (bin_count = dma_bs->secondary_bin_count; bin_count > 0;
++ bin_count--) {
++ (void)memset(&req, 0, sizeof(req));
+ req.count = bin_count;
+ req.size = dma_bs->secondary_bin_size;
+
+- err = drm_addbufs_pci( dev, & req );
++ err = drm_addbufs_pci(dev, &req);
+ if (!err) {
+ break;
+ }
+ }
+-
++
+ if (bin_count == 0) {
+ DRM_ERROR("Unable to add secondary DMA buffers\n");
+ return err;
+@@ -680,38 +666,34 @@ static int mga_do_pci_dma_bootstrap(drm_
+ return 0;
+ }
+
+-
+ static int mga_do_dma_bootstrap(drm_device_t * dev,
+ drm_mga_dma_bootstrap_t * dma_bs)
+ {
+ const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+ int err;
+- drm_mga_private_t * const dev_priv =
+- (drm_mga_private_t *) dev->dev_private;
+-
++ drm_mga_private_t *const dev_priv =
++ (drm_mga_private_t *) dev->dev_private;
+
+ dev_priv->used_new_dma_init = 1;
+
+ /* The first steps are the same for both PCI and AGP based DMA. Map
+ * the cards MMIO registers and map a status page.
+ */
+- err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size,
+- _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio );
++ err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,
++ _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);
+ if (err) {
+ DRM_ERROR("Unable to map MMIO region\n");
+ return err;
+ }
+
+-
+- err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM,
+- _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
+- & dev_priv->status );
++ err = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
++ _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
++ &dev_priv->status);
+ if (err) {
+ DRM_ERROR("Unable to map status region\n");
+ return err;
+ }
+
+-
+ /* The DMA initialization procedure is slightly different for PCI and
+ * AGP cards. AGP cards just allocate a large block of AGP memory and
+ * carve off portions of it for internal uses. The remaining memory
+@@ -720,7 +702,7 @@ static int mga_do_dma_bootstrap(drm_devi
+ if (is_agp) {
+ err = mga_do_agp_dma_bootstrap(dev, dma_bs);
+ }
+-
++
+ /* If we attempted to initialize the card for AGP DMA but failed,
+ * clean-up any mess that may have been created.
+ */
+@@ -729,7 +711,6 @@ static int mga_do_dma_bootstrap(drm_devi
+ mga_do_cleanup_dma(dev);
+ }
+
+-
+ /* Not only do we want to try and initialized PCI cards for PCI DMA,
+ * but we also try to initialized AGP cards that could not be
+ * initialized for AGP DMA. This covers the case where we have an AGP
+@@ -742,7 +723,6 @@ static int mga_do_dma_bootstrap(drm_devi
+ err = mga_do_pci_dma_bootstrap(dev, dma_bs);
+ }
+
+-
+ return err;
+ }
+
+@@ -752,45 +732,42 @@ int mga_dma_bootstrap(DRM_IOCTL_ARGS)
+ drm_mga_dma_bootstrap_t bootstrap;
+ int err;
+
+-
+ DRM_COPY_FROM_USER_IOCTL(bootstrap,
+ (drm_mga_dma_bootstrap_t __user *) data,
+ sizeof(bootstrap));
+
+- err = mga_do_dma_bootstrap(dev, & bootstrap);
+- if (! err) {
++ err = mga_do_dma_bootstrap(dev, &bootstrap);
++ if (!err) {
+ static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
+- const drm_mga_private_t * const dev_priv =
+- (drm_mga_private_t *) dev->dev_private;
++ const drm_mga_private_t *const dev_priv =
++ (drm_mga_private_t *) dev->dev_private;
+
+ if (dev_priv->agp_textures != NULL) {
+- bootstrap.texture_handle = dev_priv->agp_textures->offset;
++ bootstrap.texture_handle =
++ dev_priv->agp_textures->offset;
+ bootstrap.texture_size = dev_priv->agp_textures->size;
+- }
+- else {
++ } else {
+ bootstrap.texture_handle = 0;
+ bootstrap.texture_size = 0;
+ }
+
+- bootstrap.agp_mode = modes[ bootstrap.agp_mode & 0x07 ];
+- if (DRM_COPY_TO_USER( (void __user *) data, & bootstrap,
++ bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
++ if (DRM_COPY_TO_USER((void __user *)data, &bootstrap,
+ sizeof(bootstrap))) {
+ err = DRM_ERR(EFAULT);
+ }
+- }
+- else {
++ } else {
+ mga_do_cleanup_dma(dev);
+ }
+
+ return err;
+ }
+
+-static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
++static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
+ {
+ drm_mga_private_t *dev_priv;
+ int ret;
+- DRM_DEBUG( "\n" );
+-
++ DRM_DEBUG("\n");
+
+ dev_priv = dev->dev_private;
+
+@@ -799,17 +776,17 @@ static int mga_do_init_dma( drm_device_t
+ } else {
+ dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
+ }
+- dev_priv->maccess = init->maccess;
++ dev_priv->maccess = init->maccess;
+
+- dev_priv->fb_cpp = init->fb_cpp;
+- dev_priv->front_offset = init->front_offset;
+- dev_priv->front_pitch = init->front_pitch;
+- dev_priv->back_offset = init->back_offset;
+- dev_priv->back_pitch = init->back_pitch;
+-
+- dev_priv->depth_cpp = init->depth_cpp;
+- dev_priv->depth_offset = init->depth_offset;
+- dev_priv->depth_pitch = init->depth_pitch;
++ dev_priv->fb_cpp = init->fb_cpp;
++ dev_priv->front_offset = init->front_offset;
++ dev_priv->front_pitch = init->front_pitch;
++ dev_priv->back_offset = init->back_offset;
++ dev_priv->back_pitch = init->back_pitch;
++
++ dev_priv->depth_cpp = init->depth_cpp;
++ dev_priv->depth_offset = init->depth_offset;
++ dev_priv->depth_pitch = init->depth_pitch;
+
+ /* FIXME: Need to support AGP textures...
+ */
+@@ -823,7 +800,7 @@ static int mga_do_init_dma( drm_device_t
+ return DRM_ERR(EINVAL);
+ }
+
+- if (! dev_priv->used_new_dma_init) {
++ if (!dev_priv->used_new_dma_init) {
+
+ dev_priv->dma_access = MGA_PAGPXFER;
+ dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+@@ -849,7 +826,8 @@ static int mga_do_init_dma( drm_device_t
+ return DRM_ERR(EINVAL);
+ }
+ dev->agp_buffer_token = init->buffers_offset;
+- dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
++ dev->agp_buffer_map =
++ drm_core_findmap(dev, init->buffers_offset);
+ if (!dev->agp_buffer_map) {
+ DRM_ERROR("failed to find dma buffer region!\n");
+ return DRM_ERR(EINVAL);
+@@ -861,8 +839,8 @@ static int mga_do_init_dma( drm_device_t
+ }
+
+ dev_priv->sarea_priv =
+- (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
+- init->sarea_priv_offset);
++ (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle +
++ init->sarea_priv_offset);
+
+ if (!dev_priv->warp->handle ||
+ !dev_priv->primary->handle ||
+@@ -885,23 +863,20 @@ static int mga_do_init_dma( drm_device_t
+ return ret;
+ }
+
+- dev_priv->prim.status = (u32 *)dev_priv->status->handle;
++ dev_priv->prim.status = (u32 *) dev_priv->status->handle;
+
+- mga_do_wait_for_idle( dev_priv );
++ mga_do_wait_for_idle(dev_priv);
+
+ /* Init the primary DMA registers.
+ */
+- MGA_WRITE( MGA_PRIMADDRESS,
+- dev_priv->primary->offset | MGA_DMA_GENERAL );
++ MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL);
+ #if 0
+- MGA_WRITE( MGA_PRIMPTR,
+- virt_to_bus((void *)dev_priv->prim.status) |
+- MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */
+- MGA_PRIMPTREN1 ); /* DWGSYNC */
++ MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */
++ MGA_PRIMPTREN1); /* DWGSYNC */
+ #endif
+
+- dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
+- dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
++ dev_priv->prim.start = (u8 *) dev_priv->primary->handle;
++ dev_priv->prim.end = ((u8 *) dev_priv->primary->handle
+ + dev_priv->primary->size);
+ dev_priv->prim.size = dev_priv->primary->size;
+
+@@ -929,7 +904,7 @@ static int mga_do_init_dma( drm_device_t
+ return 0;
+ }
+
+-static int mga_do_cleanup_dma( drm_device_t *dev )
++static int mga_do_cleanup_dma(drm_device_t * dev)
+ {
+ int err = 0;
+ DRM_DEBUG("\n");
+@@ -938,16 +913,17 @@ static int mga_do_cleanup_dma( drm_devic
+ * may not have been called from userspace and after dev_private
+ * is freed, it's too late.
+ */
+- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
++ if (dev->irq_enabled)
++ drm_irq_uninstall(dev);
+
+- if ( dev->dev_private ) {
++ if (dev->dev_private) {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+
+- if ((dev_priv->warp != NULL)
++ if ((dev_priv->warp != NULL)
+ && (dev_priv->warp->type != _DRM_CONSISTENT))
+ drm_core_ioremapfree(dev_priv->warp, dev);
+
+- if ((dev_priv->primary != NULL)
++ if ((dev_priv->primary != NULL)
+ && (dev_priv->primary->type != _DRM_CONSISTENT))
+ drm_core_ioremapfree(dev_priv->primary, dev);
+
+@@ -960,7 +936,8 @@ static int mga_do_cleanup_dma( drm_devic
+ dev_priv->agp_textures = NULL;
+ drm_unbind_agp(dev_priv->agp_mem);
+
+- drm_free_agp(dev_priv->agp_mem, dev_priv->agp_pages);
++ drm_free_agp(dev_priv->agp_mem,
++ dev_priv->agp_pages);
+ dev_priv->agp_pages = 0;
+ dev_priv->agp_mem = NULL;
+ }
+@@ -982,7 +959,8 @@ static int mga_do_cleanup_dma( drm_devic
+
+ memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
+ dev_priv->warp_pipe = 0;
+- memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
++ memset(dev_priv->warp_pipe_phys, 0,
++ sizeof(dev_priv->warp_pipe_phys));
+
+ if (dev_priv->head != NULL) {
+ mga_freelist_cleanup(dev);
+@@ -992,103 +970,102 @@ static int mga_do_cleanup_dma( drm_devic
+ return err;
+ }
+
+-int mga_dma_init( DRM_IOCTL_ARGS )
++int mga_dma_init(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_mga_init_t init;
+ int err;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
+ sizeof(init));
+
+- switch ( init.func ) {
++ switch (init.func) {
+ case MGA_INIT_DMA:
+ err = mga_do_init_dma(dev, &init);
+ if (err) {
+- (void) mga_do_cleanup_dma(dev);
++ (void)mga_do_cleanup_dma(dev);
+ }
+ return err;
+ case MGA_CLEANUP_DMA:
+- return mga_do_cleanup_dma( dev );
++ return mga_do_cleanup_dma(dev);
+ }
+
+ return DRM_ERR(EINVAL);
+ }
+
+-
+ /* ================================================================
+ * Primary DMA stream management
+ */
+
+-int mga_dma_flush( DRM_IOCTL_ARGS )
++int mga_dma_flush(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
++ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ drm_lock_t lock;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t __user *)data, sizeof(lock) );
++ DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
++ sizeof(lock));
+
+- DRM_DEBUG( "%s%s%s\n",
+- (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
+- (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
+- (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" );
++ DRM_DEBUG("%s%s%s\n",
++ (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
++ (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
++ (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
+
+- WRAP_WAIT_WITH_RETURN( dev_priv );
++ WRAP_WAIT_WITH_RETURN(dev_priv);
+
+- if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
+- mga_do_dma_flush( dev_priv );
++ if (lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
++ mga_do_dma_flush(dev_priv);
+ }
+
+- if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
++ if (lock.flags & _DRM_LOCK_QUIESCENT) {
+ #if MGA_DMA_DEBUG
+- int ret = mga_do_wait_for_idle( dev_priv );
+- if ( ret < 0 )
+- DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
++ int ret = mga_do_wait_for_idle(dev_priv);
++ if (ret < 0)
++ DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
+ return ret;
+ #else
+- return mga_do_wait_for_idle( dev_priv );
++ return mga_do_wait_for_idle(dev_priv);
+ #endif
+ } else {
+ return 0;
+ }
+ }
+
+-int mga_dma_reset( DRM_IOCTL_ARGS )
++int mga_dma_reset(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
++ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- return mga_do_dma_reset( dev_priv );
++ return mga_do_dma_reset(dev_priv);
+ }
+
+-
+ /* ================================================================
+ * DMA buffer management
+ */
+
+-static int mga_dma_get_buffers( DRMFILE filp,
+- drm_device_t *dev, drm_dma_t *d )
++static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+ {
+ drm_buf_t *buf;
+ int i;
+
+- for ( i = d->granted_count ; i < d->request_count ; i++ ) {
+- buf = mga_freelist_get( dev );
+- if ( !buf ) return DRM_ERR(EAGAIN);
++ for (i = d->granted_count; i < d->request_count; i++) {
++ buf = mga_freelist_get(dev);
++ if (!buf)
++ return DRM_ERR(EAGAIN);
+
+ buf->filp = filp;
+
+- if ( DRM_COPY_TO_USER( &d->request_indices[i],
+- &buf->idx, sizeof(buf->idx) ) )
++ if (DRM_COPY_TO_USER(&d->request_indices[i],
++ &buf->idx, sizeof(buf->idx)))
+ return DRM_ERR(EFAULT);
+- if ( DRM_COPY_TO_USER( &d->request_sizes[i],
+- &buf->total, sizeof(buf->total) ) )
++ if (DRM_COPY_TO_USER(&d->request_sizes[i],
++ &buf->total, sizeof(buf->total)))
+ return DRM_ERR(EFAULT);
+
+ d->granted_count++;
+@@ -1096,44 +1073,44 @@ static int mga_dma_get_buffers( DRMFILE
+ return 0;
+ }
+
+-int mga_dma_buffers( DRM_IOCTL_ARGS )
++int mga_dma_buffers(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+- drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
++ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ drm_dma_t __user *argp = (void __user *)data;
+ drm_dma_t d;
+ int ret = 0;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
++ DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+
+ /* Please don't send us buffers.
+ */
+- if ( d.send_count != 0 ) {
+- DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
+- DRM_CURRENTPID, d.send_count );
++ if (d.send_count != 0) {
++ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
++ DRM_CURRENTPID, d.send_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* We'll send you buffers.
+ */
+- if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
+- DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
+- DRM_CURRENTPID, d.request_count, dma->buf_count );
++ if (d.request_count < 0 || d.request_count > dma->buf_count) {
++ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
++ DRM_CURRENTPID, d.request_count, dma->buf_count);
+ return DRM_ERR(EINVAL);
+ }
+
+- WRAP_TEST_WITH_RETURN( dev_priv );
++ WRAP_TEST_WITH_RETURN(dev_priv);
+
+ d.granted_count = 0;
+
+- if ( d.request_count ) {
+- ret = mga_dma_get_buffers( filp, dev, &d );
++ if (d.request_count) {
++ ret = mga_dma_get_buffers(filp, dev, &d);
+ }
+
+- DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );
++ DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
+
+ return ret;
+ }
+@@ -1154,11 +1131,11 @@ int mga_driver_postcleanup(drm_device_t
+ */
+ void mga_driver_pretakedown(drm_device_t * dev)
+ {
+- mga_do_cleanup_dma( dev );
++ mga_do_cleanup_dma(dev);
+ }
+
+-int mga_driver_dma_quiescent(drm_device_t *dev)
++int mga_driver_dma_quiescent(drm_device_t * dev)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+- return mga_do_wait_for_idle( dev_priv );
++ return mga_do_wait_for_idle(dev_priv);
+ }
+diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
+--- a/drivers/char/drm/mga_drm.h
++++ b/drivers/char/drm/mga_drm.h
+@@ -44,10 +44,10 @@
+
+ /* WARP pipe flags
+ */
+-#define MGA_F 0x1 /* fog */
+-#define MGA_A 0x2 /* alpha */
+-#define MGA_S 0x4 /* specular */
+-#define MGA_T2 0x8 /* multitexture */
++#define MGA_F 0x1 /* fog */
++#define MGA_A 0x2 /* alpha */
++#define MGA_S 0x4 /* specular */
++#define MGA_T2 0x8 /* multitexture */
+
+ #define MGA_WARP_TGZ 0
+ #define MGA_WARP_TGZF (MGA_F)
+@@ -66,14 +66,14 @@
+ #define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
+ #define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A)
+
+-#define MGA_MAX_G200_PIPES 8 /* no multitex */
++#define MGA_MAX_G200_PIPES 8 /* no multitex */
+ #define MGA_MAX_G400_PIPES 16
+ #define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
+-#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
++#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
+
+ #define MGA_CARD_TYPE_G200 1
+ #define MGA_CARD_TYPE_G400 2
+-#define MGA_CARD_TYPE_G450 3 /* not currently used */
++#define MGA_CARD_TYPE_G450 3 /* not currently used */
+ #define MGA_CARD_TYPE_G550 4
+
+ #define MGA_FRONT 0x1
+@@ -86,14 +86,14 @@
+ #define MGA_UPLOAD_TEX0 0x2
+ #define MGA_UPLOAD_TEX1 0x4
+ #define MGA_UPLOAD_PIPE 0x8
+-#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
+-#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
++#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
++#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
+ #define MGA_UPLOAD_2D 0x40
+-#define MGA_WAIT_AGE 0x80 /* handled client-side */
+-#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
++#define MGA_WAIT_AGE 0x80 /* handled client-side */
++#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
+ #if 0
+-#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
+- quiescent */
++#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
++ quiescent */
+ #endif
+
+ /* 32 buffers of 64k each, total 2 meg.
+@@ -120,8 +120,7 @@
+
+ #define DRM_MGA_IDLE_RETRY 2048
+
+-#endif /* __MGA_SAREA_DEFINES__ */
+-
++#endif /* __MGA_SAREA_DEFINES__ */
+
+ /* Setup registers for 3D context
+ */
+@@ -165,25 +164,25 @@ typedef struct {
+ /* General aging mechanism
+ */
+ typedef struct {
+- unsigned int head; /* Position of head pointer */
+- unsigned int wrap; /* Primary DMA wrap count */
++ unsigned int head; /* Position of head pointer */
++ unsigned int wrap; /* Primary DMA wrap count */
+ } drm_mga_age_t;
+
+ typedef struct _drm_mga_sarea {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex dma buffer.
+ */
+- drm_mga_context_regs_t context_state;
+- drm_mga_server_regs_t server_state;
+- drm_mga_texture_regs_t tex_state[2];
+- unsigned int warp_pipe;
+- unsigned int dirty;
+- unsigned int vertsize;
++ drm_mga_context_regs_t context_state;
++ drm_mga_server_regs_t server_state;
++ drm_mga_texture_regs_t tex_state[2];
++ unsigned int warp_pipe;
++ unsigned int dirty;
++ unsigned int vertsize;
+
+ /* The current cliprects, or a subset thereof.
+ */
+- drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
+- unsigned int nbox;
++ drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
++ unsigned int nbox;
+
+ /* Information about the most recently used 3d drawable. The
+ * client fills in the req_* fields, the server fills in the
+@@ -192,18 +191,18 @@ typedef struct _drm_mga_sarea {
+ * The client clears the exported_drawable field before
+ * clobbering the boxes data.
+ */
+- unsigned int req_drawable; /* the X drawable id */
+- unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
++ unsigned int req_drawable; /* the X drawable id */
++ unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
+
+- unsigned int exported_drawable;
++ unsigned int exported_drawable;
+ unsigned int exported_index;
+- unsigned int exported_stamp;
+- unsigned int exported_buffers;
+- unsigned int exported_nfront;
+- unsigned int exported_nback;
++ unsigned int exported_stamp;
++ unsigned int exported_buffers;
++ unsigned int exported_nfront;
++ unsigned int exported_nback;
+ int exported_back_x, exported_front_x, exported_w;
+ int exported_back_y, exported_front_y, exported_h;
+- drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
++ drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+
+ /* Counters for aging textures and for client-side throttling.
+ */
+@@ -211,21 +210,20 @@ typedef struct _drm_mga_sarea {
+ unsigned int last_wrap;
+
+ drm_mga_age_t last_frame;
+- unsigned int last_enqueue; /* last time a buffer was enqueued */
++ unsigned int last_enqueue; /* last time a buffer was enqueued */
+ unsigned int last_dispatch; /* age of the most recently dispatched buffer */
+- unsigned int last_quiescent; /* */
++ unsigned int last_quiescent; /* */
+
+ /* LRU lists for texture memory in agp space and on the card.
+ */
+- drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
++ drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
+ unsigned int texAge[MGA_NR_TEX_HEAPS];
+
+ /* Mechanism to validate card state.
+ */
+- int ctxOwner;
++ int ctxOwner;
+ } drm_mga_sarea_t;
+
+-
+ /* MGA specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+@@ -247,7 +245,6 @@ typedef struct _drm_mga_sarea {
+ #define DRM_MGA_WAIT_FENCE 0x0b
+ #define DRM_MGA_DMA_BOOTSTRAP 0x0c
+
+-
+ #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
+ #define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
+ #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET)
+@@ -263,33 +260,33 @@ typedef struct _drm_mga_sarea {
+ #define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
+
+ typedef struct _drm_mga_warp_index {
+- int installed;
+- unsigned long phys_addr;
+- int size;
++ int installed;
++ unsigned long phys_addr;
++ int size;
+ } drm_mga_warp_index_t;
+
+ typedef struct drm_mga_init {
+- enum {
+- MGA_INIT_DMA = 0x01,
+- MGA_CLEANUP_DMA = 0x02
++ enum {
++ MGA_INIT_DMA = 0x01,
++ MGA_CLEANUP_DMA = 0x02
+ } func;
+
+- unsigned long sarea_priv_offset;
++ unsigned long sarea_priv_offset;
+
+ int chipset;
+- int sgram;
++ int sgram;
+
+ unsigned int maccess;
+
+- unsigned int fb_cpp;
++ unsigned int fb_cpp;
+ unsigned int front_offset, front_pitch;
+- unsigned int back_offset, back_pitch;
++ unsigned int back_offset, back_pitch;
+
+- unsigned int depth_cpp;
+- unsigned int depth_offset, depth_pitch;
++ unsigned int depth_cpp;
++ unsigned int depth_offset, depth_pitch;
+
+- unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+- unsigned int texture_size[MGA_NR_TEX_HEAPS];
++ unsigned int texture_offset[MGA_NR_TEX_HEAPS];
++ unsigned int texture_size[MGA_NR_TEX_HEAPS];
+
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+@@ -302,64 +299,59 @@ typedef struct drm_mga_init {
+ typedef struct drm_mga_dma_bootstrap {
+ /**
+ * \name AGP texture region
+- *
++ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
+ * be filled in with the actual AGP texture settings.
+- *
++ *
+ * \warning
+ * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
+ * is zero, it means that PCI memory (most likely through the use of
+ * an IOMMU) is being used for "AGP" textures.
+ */
+- /*@{*/
++ /*@{ */
+ unsigned long texture_handle; /**< Handle used to map AGP textures. */
+- uint32_t texture_size; /**< Size of the AGP texture region. */
+- /*@}*/
+-
++ uint32_t texture_size; /**< Size of the AGP texture region. */
++ /*@} */
+
+ /**
+ * Requested size of the primary DMA region.
+- *
++ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual AGP mode. If AGP was not available
+ */
+ uint32_t primary_size;
+
+-
+ /**
+ * Requested number of secondary DMA buffers.
+- *
++ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual number of secondary DMA buffers
+ * allocated. Particularly when PCI DMA is used, this may be
+ * (subtantially) less than the number requested.
+ */
+ uint32_t secondary_bin_count;
+-
+-
++
+ /**
+ * Requested size of each secondary DMA buffer.
+- *
++ *
+ * While the kernel \b is free to reduce
+ * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
+ * to reduce dma_mga_dma_bootstrap::secondary_bin_size.
+ */
+ uint32_t secondary_bin_size;
+
+-
+ /**
+ * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X,
+ * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is
+ * zero, it means that PCI DMA should be used, even if AGP is
+ * possible.
+- *
++ *
+ * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+ * filled in with the actual AGP mode. If AGP was not available
+ * (i.e., PCI DMA was used), this value will be zero.
+ */
+ uint32_t agp_mode;
+
+-
+ /**
+ * Desired AGP GART size, measured in megabytes.
+ */
+@@ -375,16 +367,16 @@ typedef struct drm_mga_clear {
+ } drm_mga_clear_t;
+
+ typedef struct drm_mga_vertex {
+- int idx; /* buffer to queue */
+- int used; /* bytes in use */
+- int discard; /* client finished with buffer? */
++ int idx; /* buffer to queue */
++ int used; /* bytes in use */
++ int discard; /* client finished with buffer? */
+ } drm_mga_vertex_t;
+
+ typedef struct drm_mga_indices {
+- int idx; /* buffer to queue */
++ int idx; /* buffer to queue */
+ unsigned int start;
+ unsigned int end;
+- int discard; /* client finished with buffer? */
++ int discard; /* client finished with buffer? */
+ } drm_mga_indices_t;
+
+ typedef struct drm_mga_iload {
+@@ -400,12 +392,12 @@ typedef struct _drm_mga_blit {
+ int src_pitch, dst_pitch;
+ int delta_sx, delta_sy;
+ int delta_dx, delta_dy;
+- int height, ydir; /* flip image vertically */
++ int height, ydir; /* flip image vertically */
+ int source_pitch, dest_pitch;
+ } drm_mga_blit_t;
+
+ /* 3.1: An ioctl to get parameters that aren't available to the 3d
+- * client any other way.
++ * client any other way.
+ */
+ #define MGA_PARAM_IRQ_NR 1
+
+diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
+--- a/drivers/char/drm/mga_drv.c
++++ b/drivers/char/drm/mga_drv.c
+@@ -35,14 +35,13 @@
+ #include "mga_drm.h"
+ #include "mga_drv.h"
+
+-
+ #include "drm_pciids.h"
+
+ static int mga_driver_device_is_agp(drm_device_t * dev);
+-static int postinit( struct drm_device *dev, unsigned long flags )
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+- drm_mga_private_t * const dev_priv =
+- (drm_mga_private_t *) dev->dev_private;
++ drm_mga_private_t *const dev_priv =
++ (drm_mga_private_t *) dev->dev_private;
+
+ dev_priv->mmio_base = pci_resource_start(dev->pdev, 1);
+ dev_priv->mmio_size = pci_resource_len(dev->pdev, 1);
+@@ -52,28 +51,26 @@ static int postinit( struct drm_device *
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -81,11 +78,11 @@ static struct pci_device_id pciidlist[]
+ mga_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t mga_ioctls[];
+-extern int mga_max_ioctl;
+-
+ static struct drm_driver driver = {
+- .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
++ .driver_features =
++ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
++ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
++ DRIVER_IRQ_VBL,
+ .preinit = mga_driver_preinit,
+ .postcleanup = mga_driver_postcleanup,
+ .pretakedown = mga_driver_pretakedown,
+@@ -104,21 +101,21 @@ static struct drm_driver driver = {
+ .ioctls = mga_ioctls,
+ .dma_ioctl = mga_dma_buffers,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
+ #ifdef CONFIG_COMPAT
+- .compat_ioctl = mga_compat_ioctl,
++ .compat_ioctl = mga_compat_ioctl,
+ #endif
+- },
++ },
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init mga_init(void)
+@@ -135,8 +132,8 @@ static void __exit mga_exit(void)
+ module_init(mga_init);
+ module_exit(mga_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+
+ /**
+@@ -151,10 +148,9 @@ MODULE_LICENSE("GPL and additional right
+ * \returns
+ * If the device is a PCI G450, zero is returned. Otherwise 2 is returned.
+ */
+-int mga_driver_device_is_agp(drm_device_t * dev)
++static int mga_driver_device_is_agp(drm_device_t * dev)
+ {
+- const struct pci_dev * const pdev = dev->pdev;
+-
++ const struct pci_dev *const pdev = dev->pdev;
+
+ /* There are PCI versions of the G450. These cards have the
+ * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
+@@ -164,10 +160,10 @@ int mga_driver_device_is_agp(drm_device_
+ * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
+ * device.
+ */
+-
+- if ( (pdev->device == 0x0525)
+- && (pdev->bus->self->vendor == 0x3388)
+- && (pdev->bus->self->device == 0x0021) ) {
++
++ if ((pdev->device == 0x0525)
++ && (pdev->bus->self->vendor == 0x3388)
++ && (pdev->bus->self->device == 0x0021)) {
+ return 0;
+ }
+
+diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
+--- a/drivers/char/drm/mga_drv.h
++++ b/drivers/char/drm/mga_drv.h
+@@ -62,14 +62,14 @@ typedef struct drm_mga_primary_buffer {
+ } drm_mga_primary_buffer_t;
+
+ typedef struct drm_mga_freelist {
+- struct drm_mga_freelist *next;
+- struct drm_mga_freelist *prev;
++ struct drm_mga_freelist *next;
++ struct drm_mga_freelist *prev;
+ drm_mga_age_t age;
+- drm_buf_t *buf;
++ drm_buf_t *buf;
+ } drm_mga_freelist_t;
+
+ typedef struct {
+- drm_mga_freelist_t *list_entry;
++ drm_mga_freelist_t *list_entry;
+ int discard;
+ int dispatched;
+ } drm_mga_buf_priv_t;
+@@ -78,8 +78,8 @@ typedef struct drm_mga_private {
+ drm_mga_primary_buffer_t prim;
+ drm_mga_sarea_t *sarea_priv;
+
+- drm_mga_freelist_t *head;
+- drm_mga_freelist_t *tail;
++ drm_mga_freelist_t *head;
++ drm_mga_freelist_t *tail;
+
+ unsigned int warp_pipe;
+ unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
+@@ -109,13 +109,13 @@ typedef struct drm_mga_private {
+
+ /**
+ * \name MMIO region parameters.
+- *
++ *
+ * \sa drm_mga_private_t::mmio
+ */
+- /*@{*/
+- u32 mmio_base; /**< Bus address of base of MMIO. */
+- u32 mmio_size; /**< Size of the MMIO region. */
+- /*@}*/
++ /*@{ */
++ u32 mmio_base; /**< Bus address of base of MMIO. */
++ u32 mmio_size; /**< Size of the MMIO region. */
++ /*@} */
+
+ u32 clear_cmd;
+ u32 maccess;
+@@ -143,11 +143,14 @@ typedef struct drm_mga_private {
+ drm_local_map_t *warp;
+ drm_local_map_t *primary;
+ drm_local_map_t *agp_textures;
+-
++
+ DRM_AGP_MEM *agp_mem;
+ unsigned int agp_pages;
+ } drm_mga_private_t;
+
++extern drm_ioctl_desc_t mga_ioctls[];
++extern int mga_max_ioctl;
++
+ /* mga_dma.c */
+ extern int mga_driver_preinit(drm_device_t * dev, unsigned long flags);
+ extern int mga_dma_bootstrap(DRM_IOCTL_ARGS);
+@@ -165,7 +168,7 @@ extern void mga_do_dma_flush(drm_mga_pri
+ extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
+ extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
+
+-extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
++extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+
+ /* mga_warp.c */
+ extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
+@@ -196,7 +199,7 @@ extern long mga_compat_ioctl(struct file
+ #define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
+ #define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
+
+-static inline u32 _MGA_READ(u32 *addr)
++static inline u32 _MGA_READ(u32 * addr)
+ {
+ DRM_MEMORYBARRIER();
+ return *(volatile u32 *)addr;
+@@ -218,8 +221,6 @@ static inline u32 _MGA_READ(u32 *addr)
+ #define DMAREG1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
+ #define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
+
+-
+-
+ /* ================================================================
+ * Helper macross...
+ */
+@@ -261,7 +262,6 @@ do { \
+ } \
+ } while (0)
+
+-
+ /* ================================================================
+ * Primary DMA command stream
+ */
+@@ -346,7 +346,6 @@ do { \
+ write += DMA_BLOCK_SIZE; \
+ } while (0)
+
+-
+ /* Buffer aging via primary DMA stream head pointer.
+ */
+
+@@ -373,7 +372,6 @@ do { \
+ } \
+ } while (0)
+
+-
+ #define MGA_ENGINE_IDLE_MASK (MGA_SOFTRAPEN | \
+ MGA_DWGENGSTS | \
+ MGA_ENDPRDMASTS)
+@@ -382,8 +380,6 @@ do { \
+
+ #define MGA_DMA_DEBUG 0
+
+-
+-
+ /* A reduced set of the mga registers.
+ */
+ #define MGA_CRTC_INDEX 0x1fd4
+@@ -644,7 +640,6 @@ do { \
+ # define MGA_G400_WR_MAGIC (1 << 6)
+ # define MGA_G400_WR56_MAGIC 0x46480000 /* 12800.0f */
+
+-
+ #define MGA_ILOAD_ALIGN 64
+ #define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1)
+
+@@ -679,10 +674,10 @@ do { \
+
+ /* Simple idle test.
+ */
+-static __inline__ int mga_is_idle( drm_mga_private_t *dev_priv )
++static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
+ {
+- u32 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
+- return ( status == MGA_ENDPRDMASTS );
++ u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
++ return (status == MGA_ENDPRDMASTS);
+ }
+
+ #endif
+diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
+--- a/drivers/char/drm/mga_ioc32.c
++++ b/drivers/char/drm/mga_ioc32.c
+@@ -39,17 +39,17 @@
+
+ typedef struct drm32_mga_init {
+ int func;
+- u32 sarea_priv_offset;
++ u32 sarea_priv_offset;
+ int chipset;
+- int sgram;
++ int sgram;
+ unsigned int maccess;
+- unsigned int fb_cpp;
++ unsigned int fb_cpp;
+ unsigned int front_offset, front_pitch;
+- unsigned int back_offset, back_pitch;
+- unsigned int depth_cpp;
+- unsigned int depth_offset, depth_pitch;
+- unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+- unsigned int texture_size[MGA_NR_TEX_HEAPS];
++ unsigned int back_offset, back_pitch;
++ unsigned int depth_cpp;
++ unsigned int depth_offset, depth_pitch;
++ unsigned int texture_offset[MGA_NR_TEX_HEAPS];
++ unsigned int texture_size[MGA_NR_TEX_HEAPS];
+ u32 fb_offset;
+ u32 mmio_offset;
+ u32 status_offset;
+@@ -64,10 +64,10 @@ static int compat_mga_init(struct file *
+ drm_mga_init32_t init32;
+ drm_mga_init_t __user *init;
+ int err = 0, i;
+-
++
+ if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+ return -EFAULT;
+-
++
+ init = compat_alloc_user_space(sizeof(*init));
+ if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+ || __put_user(init32.func, &init->func)
+@@ -90,42 +90,43 @@ static int compat_mga_init(struct file *
+ || __put_user(init32.primary_offset, &init->primary_offset)
+ || __put_user(init32.buffers_offset, &init->buffers_offset))
+ return -EFAULT;
+-
+- for (i=0; i<MGA_NR_TEX_HEAPS; i++)
+- {
+- err |= __put_user(init32.texture_offset[i], &init->texture_offset[i]);
+- err |= __put_user(init32.texture_size[i], &init->texture_size[i]);
++
++ for (i = 0; i < MGA_NR_TEX_HEAPS; i++) {
++ err |=
++ __put_user(init32.texture_offset[i],
++ &init->texture_offset[i]);
++ err |=
++ __put_user(init32.texture_size[i], &init->texture_size[i]);
+ }
+ if (err)
+ return -EFAULT;
+-
++
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_MGA_INIT, (unsigned long) init);
++ DRM_IOCTL_MGA_INIT, (unsigned long)init);
+ }
+
+-
+ typedef struct drm_mga_getparam32 {
+ int param;
+ u32 value;
+ } drm_mga_getparam32_t;
+
+-
+ static int compat_mga_getparam(struct file *file, unsigned int cmd,
+ unsigned long arg)
+ {
+ drm_mga_getparam32_t getparam32;
+ drm_mga_getparam_t __user *getparam;
+-
++
+ if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
+ return -EFAULT;
+
+ getparam = compat_alloc_user_space(sizeof(*getparam));
+ if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
+ || __put_user(getparam32.param, &getparam->param)
+- || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
++ || __put_user((void __user *)(unsigned long)getparam32.value,
++ &getparam->value))
+ return -EFAULT;
+
+- return drm_ioctl(file->f_dentry->d_inode, file,
++ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
+ }
+
+@@ -182,14 +183,12 @@ static int compat_mga_dma_bootstrap(stru
+ &dma_bootstrap->secondary_bin_count)
+ || __get_user(dma_bootstrap32.secondary_bin_size,
+ &dma_bootstrap->secondary_bin_size)
+- || __get_user(dma_bootstrap32.agp_mode,
+- &dma_bootstrap->agp_mode)
+- || __get_user(dma_bootstrap32.agp_size,
+- &dma_bootstrap->agp_size))
++ || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
++ || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+ return -EFAULT;
+
+ if (copy_to_user((void __user *)arg, &dma_bootstrap32,
+- sizeof(dma_bootstrap32)))
++ sizeof(dma_bootstrap32)))
+ return -EFAULT;
+
+ return 0;
+@@ -210,8 +209,7 @@ drm_ioctl_compat_t *mga_compat_ioctls[]
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+-long mga_compat_ioctl(struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+@@ -219,13 +217,13 @@ long mga_compat_ioctl(struct file *filp,
+
+ if (nr < DRM_COMMAND_BASE)
+ return drm_compat_ioctl(filp, cmd, arg);
+-
++
+ if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
+ fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+- ret = (*fn)(filp, cmd, arg);
++ ret = (*fn) (filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
+--- a/drivers/char/drm/mga_irq.c
++++ b/drivers/char/drm/mga_irq.c
+@@ -1,7 +1,7 @@
+ /* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+- *
++ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+@@ -35,19 +35,18 @@
+ #include "mga_drm.h"
+ #include "mga_drv.h"
+
+-irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS )
++irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ drm_device_t *dev = (drm_device_t *) arg;
+- drm_mga_private_t *dev_priv =
+- (drm_mga_private_t *)dev->dev_private;
++ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ int status;
+ int handled = 0;
+
+ status = MGA_READ(MGA_STATUS);
+
+ /* VBLANK interrupt */
+- if ( status & MGA_VLINEPEN ) {
+- MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
++ if (status & MGA_VLINEPEN) {
++ MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
+ atomic_inc(&dev->vbl_received);
+ DRM_WAKEUP(&dev->vbl_queue);
+ drm_vbl_send_signals(dev);
+@@ -57,15 +56,14 @@ irqreturn_t mga_driver_irq_handler( DRM_
+ /* SOFTRAP interrupt */
+ if (status & MGA_SOFTRAPEN) {
+ const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
+- const u32 prim_end = MGA_READ(MGA_PRIMEND);
+-
++ const u32 prim_end = MGA_READ(MGA_PRIMEND);
+
+ MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
+
+ /* In addition to clearing the interrupt-pending bit, we
+ * have to write to MGA_PRIMEND to re-start the DMA operation.
+ */
+- if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) {
++ if ((prim_start & ~0x03) != (prim_end & ~0x03)) {
+ MGA_WRITE(MGA_PRIMEND, prim_end);
+ }
+
+@@ -74,24 +72,24 @@ irqreturn_t mga_driver_irq_handler( DRM_
+ handled = 1;
+ }
+
+- if ( handled ) {
++ if (handled) {
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+ }
+
+-int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
++int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+ {
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ /* Assume that the user has missed the current sequence number
+ * by about a day rather than she wants to wait for years
+- * using vertical blanks...
++ * using vertical blanks...
+ */
+- DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
+- ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+- - *sequence ) <= (1<<23) ) );
++ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
++ (((cur_vblank = atomic_read(&dev->vbl_received))
++ - *sequence) <= (1 << 23)));
+
+ *sequence = cur_vblank;
+
+@@ -122,29 +120,29 @@ void mga_driver_irq_preinstall(drm_devic
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+ /* Disable *all* interrupts */
+- MGA_WRITE( MGA_IEN, 0 );
++ MGA_WRITE(MGA_IEN, 0);
+ /* Clear bits if they're already high */
+- MGA_WRITE( MGA_ICLEAR, ~0 );
++ MGA_WRITE(MGA_ICLEAR, ~0);
+ }
+
+ void mga_driver_irq_postinstall(drm_device_t * dev)
+ {
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+- DRM_INIT_WAITQUEUE( &dev_priv->fence_queue );
++ DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+
+ /* Turn on vertical blank interrupt and soft trap interrupt. */
+ MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+ }
+
+-void mga_driver_irq_uninstall( drm_device_t *dev ) {
+- drm_mga_private_t *dev_priv =
+- (drm_mga_private_t *)dev->dev_private;
++void mga_driver_irq_uninstall(drm_device_t * dev)
++{
++ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+ MGA_WRITE(MGA_IEN, 0);
+-
++
+ dev->irq_enabled = 0;
+ }
+diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
+--- a/drivers/char/drm/mga_state.c
++++ b/drivers/char/drm/mga_state.c
+@@ -41,15 +41,15 @@
+ * DMA hardware state programming functions
+ */
+
+-static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
+- drm_clip_rect_t *box )
++static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
++ drm_clip_rect_t * box)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ unsigned int pitch = dev_priv->front_pitch;
+ DMA_LOCALS;
+
+- BEGIN_DMA( 2 );
++ BEGIN_DMA(2);
+
+ /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
+ */
+@@ -61,101 +61,90 @@ static void mga_emit_clip_rect( drm_mga_
+ }
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+- MGA_YTOP, box->y1 * pitch,
+- MGA_YBOT, (box->y2 - 1) * pitch);
++ MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch);
+
+ ADVANCE_DMA();
+ }
+
+-static __inline__ void mga_g200_emit_context( drm_mga_private_t *dev_priv )
++static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ DMA_LOCALS;
+
+- BEGIN_DMA( 3 );
++ BEGIN_DMA(3);
+
+- DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
+- MGA_MACCESS, ctx->maccess,
+- MGA_PLNWT, ctx->plnwt,
+- MGA_DWGCTL, ctx->dwgctl );
+-
+- DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
+- MGA_FOGCOL, ctx->fogcolor,
+- MGA_WFLAG, ctx->wflag,
+- MGA_ZORG, dev_priv->depth_offset );
+-
+- DMA_BLOCK( MGA_FCOL, ctx->fcol,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000 );
++ DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
++ MGA_MACCESS, ctx->maccess,
++ MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
++
++ DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
++ MGA_FOGCOL, ctx->fogcolor,
++ MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
++
++ DMA_BLOCK(MGA_FCOL, ctx->fcol,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+ ADVANCE_DMA();
+ }
+
+-static __inline__ void mga_g400_emit_context( drm_mga_private_t *dev_priv )
++static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ DMA_LOCALS;
+
+- BEGIN_DMA( 4 );
++ BEGIN_DMA(4);
+
+- DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
+- MGA_MACCESS, ctx->maccess,
+- MGA_PLNWT, ctx->plnwt,
+- MGA_DWGCTL, ctx->dwgctl );
+-
+- DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
+- MGA_FOGCOL, ctx->fogcolor,
+- MGA_WFLAG, ctx->wflag,
+- MGA_ZORG, dev_priv->depth_offset );
+-
+- DMA_BLOCK( MGA_WFLAG1, ctx->wflag,
+- MGA_TDUALSTAGE0, ctx->tdualstage0,
+- MGA_TDUALSTAGE1, ctx->tdualstage1,
+- MGA_FCOL, ctx->fcol );
+-
+- DMA_BLOCK( MGA_STENCIL, ctx->stencil,
+- MGA_STENCILCTL, ctx->stencilctl,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000 );
++ DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
++ MGA_MACCESS, ctx->maccess,
++ MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
++
++ DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
++ MGA_FOGCOL, ctx->fogcolor,
++ MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
++
++ DMA_BLOCK(MGA_WFLAG1, ctx->wflag,
++ MGA_TDUALSTAGE0, ctx->tdualstage0,
++ MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol);
++
++ DMA_BLOCK(MGA_STENCIL, ctx->stencil,
++ MGA_STENCILCTL, ctx->stencilctl,
++ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+ ADVANCE_DMA();
+ }
+
+-static __inline__ void mga_g200_emit_tex0( drm_mga_private_t *dev_priv )
++static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ DMA_LOCALS;
+
+- BEGIN_DMA( 4 );
++ BEGIN_DMA(4);
+
+- DMA_BLOCK( MGA_TEXCTL2, tex->texctl2,
+- MGA_TEXCTL, tex->texctl,
+- MGA_TEXFILTER, tex->texfilter,
+- MGA_TEXBORDERCOL, tex->texbordercol );
+-
+- DMA_BLOCK( MGA_TEXORG, tex->texorg,
+- MGA_TEXORG1, tex->texorg1,
+- MGA_TEXORG2, tex->texorg2,
+- MGA_TEXORG3, tex->texorg3 );
+-
+- DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
+- MGA_TEXWIDTH, tex->texwidth,
+- MGA_TEXHEIGHT, tex->texheight,
+- MGA_WR24, tex->texwidth );
+-
+- DMA_BLOCK( MGA_WR34, tex->texheight,
+- MGA_TEXTRANS, 0x0000ffff,
+- MGA_TEXTRANSHIGH, 0x0000ffff,
+- MGA_DMAPAD, 0x00000000 );
++ DMA_BLOCK(MGA_TEXCTL2, tex->texctl2,
++ MGA_TEXCTL, tex->texctl,
++ MGA_TEXFILTER, tex->texfilter,
++ MGA_TEXBORDERCOL, tex->texbordercol);
++
++ DMA_BLOCK(MGA_TEXORG, tex->texorg,
++ MGA_TEXORG1, tex->texorg1,
++ MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
++
++ DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
++ MGA_TEXWIDTH, tex->texwidth,
++ MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth);
++
++ DMA_BLOCK(MGA_WR34, tex->texheight,
++ MGA_TEXTRANS, 0x0000ffff,
++ MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000);
+
+ ADVANCE_DMA();
+ }
+
+-static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
++static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+@@ -164,42 +153,38 @@ static __inline__ void mga_g400_emit_tex
+ /* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
+ /* tex->texctl, tex->texctl2); */
+
+- BEGIN_DMA( 6 );
++ BEGIN_DMA(6);
+
+- DMA_BLOCK( MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
+- MGA_TEXCTL, tex->texctl,
+- MGA_TEXFILTER, tex->texfilter,
+- MGA_TEXBORDERCOL, tex->texbordercol );
+-
+- DMA_BLOCK( MGA_TEXORG, tex->texorg,
+- MGA_TEXORG1, tex->texorg1,
+- MGA_TEXORG2, tex->texorg2,
+- MGA_TEXORG3, tex->texorg3 );
+-
+- DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
+- MGA_TEXWIDTH, tex->texwidth,
+- MGA_TEXHEIGHT, tex->texheight,
+- MGA_WR49, 0x00000000 );
+-
+- DMA_BLOCK( MGA_WR57, 0x00000000,
+- MGA_WR53, 0x00000000,
+- MGA_WR61, 0x00000000,
+- MGA_WR52, MGA_G400_WR_MAGIC );
+-
+- DMA_BLOCK( MGA_WR60, MGA_G400_WR_MAGIC,
+- MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
+- MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
+- MGA_DMAPAD, 0x00000000 );
+-
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_TEXTRANS, 0x0000ffff,
+- MGA_TEXTRANSHIGH, 0x0000ffff );
++ DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
++ MGA_TEXCTL, tex->texctl,
++ MGA_TEXFILTER, tex->texfilter,
++ MGA_TEXBORDERCOL, tex->texbordercol);
++
++ DMA_BLOCK(MGA_TEXORG, tex->texorg,
++ MGA_TEXORG1, tex->texorg1,
++ MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
++
++ DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
++ MGA_TEXWIDTH, tex->texwidth,
++ MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
++
++ DMA_BLOCK(MGA_WR57, 0x00000000,
++ MGA_WR53, 0x00000000,
++ MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC);
++
++ DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC,
++ MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
++ MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
++ MGA_DMAPAD, 0x00000000);
++
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff);
+
+ ADVANCE_DMA();
+ }
+
+-static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
++static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
+@@ -208,55 +193,51 @@ static __inline__ void mga_g400_emit_tex
+ /* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */
+ /* tex->texctl, tex->texctl2); */
+
+- BEGIN_DMA( 5 );
++ BEGIN_DMA(5);
+
+- DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 |
+- MGA_MAP1_ENABLE |
+- MGA_G400_TC2_MAGIC),
+- MGA_TEXCTL, tex->texctl,
+- MGA_TEXFILTER, tex->texfilter,
+- MGA_TEXBORDERCOL, tex->texbordercol );
+-
+- DMA_BLOCK( MGA_TEXORG, tex->texorg,
+- MGA_TEXORG1, tex->texorg1,
+- MGA_TEXORG2, tex->texorg2,
+- MGA_TEXORG3, tex->texorg3 );
+-
+- DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
+- MGA_TEXWIDTH, tex->texwidth,
+- MGA_TEXHEIGHT, tex->texheight,
+- MGA_WR49, 0x00000000 );
+-
+- DMA_BLOCK( MGA_WR57, 0x00000000,
+- MGA_WR53, 0x00000000,
+- MGA_WR61, 0x00000000,
+- MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC );
+-
+- DMA_BLOCK( MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
+- MGA_TEXTRANS, 0x0000ffff,
+- MGA_TEXTRANSHIGH, 0x0000ffff,
+- MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC );
++ DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 |
++ MGA_MAP1_ENABLE |
++ MGA_G400_TC2_MAGIC),
++ MGA_TEXCTL, tex->texctl,
++ MGA_TEXFILTER, tex->texfilter,
++ MGA_TEXBORDERCOL, tex->texbordercol);
++
++ DMA_BLOCK(MGA_TEXORG, tex->texorg,
++ MGA_TEXORG1, tex->texorg1,
++ MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
++
++ DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
++ MGA_TEXWIDTH, tex->texwidth,
++ MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
++
++ DMA_BLOCK(MGA_WR57, 0x00000000,
++ MGA_WR53, 0x00000000,
++ MGA_WR61, 0x00000000,
++ MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC);
++
++ DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
++ MGA_TEXTRANS, 0x0000ffff,
++ MGA_TEXTRANSHIGH, 0x0000ffff,
++ MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC);
+
+ ADVANCE_DMA();
+ }
+
+-static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
++static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->warp_pipe;
+ DMA_LOCALS;
+
+- BEGIN_DMA( 3 );
++ BEGIN_DMA(3);
+
+- DMA_BLOCK( MGA_WIADDR, MGA_WMODE_SUSPEND,
+- MGA_WVRTXSZ, 0x00000007,
+- MGA_WFLAG, 0x00000000,
+- MGA_WR24, 0x00000000 );
+-
+- DMA_BLOCK( MGA_WR25, 0x00000100,
+- MGA_WR34, 0x00000000,
+- MGA_WR42, 0x0000ffff,
+- MGA_WR60, 0x0000ffff );
++ DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND,
++ MGA_WVRTXSZ, 0x00000007,
++ MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000);
++
++ DMA_BLOCK(MGA_WR25, 0x00000100,
++ MGA_WR34, 0x00000000,
++ MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff);
+
+ /* Padding required to to hardware bug.
+ */
+@@ -269,7 +250,7 @@ static __inline__ void mga_g200_emit_pip
+ ADVANCE_DMA();
+ }
+
+-static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
++static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->warp_pipe;
+@@ -277,68 +258,64 @@ static __inline__ void mga_g400_emit_pip
+
+ /* printk("mga_g400_emit_pipe %x\n", pipe); */
+
+- BEGIN_DMA( 10 );
++ BEGIN_DMA(10);
+
+- DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000 );
+-
+- if ( pipe & MGA_T2 ) {
+- DMA_BLOCK( MGA_WVRTXSZ, 0x00001e09,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000 );
+-
+- DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
+- MGA_WACCEPTSEQ, 0x00000000,
+- MGA_WACCEPTSEQ, 0x00000000,
+- MGA_WACCEPTSEQ, 0x1e000000 );
++ DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
++
++ if (pipe & MGA_T2) {
++ DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
++
++ DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
++ MGA_WACCEPTSEQ, 0x00000000,
++ MGA_WACCEPTSEQ, 0x00000000,
++ MGA_WACCEPTSEQ, 0x1e000000);
+ } else {
+- if ( dev_priv->warp_pipe & MGA_T2 ) {
++ if (dev_priv->warp_pipe & MGA_T2) {
+ /* Flush the WARP pipe */
+- DMA_BLOCK( MGA_YDST, 0x00000000,
+- MGA_FXLEFT, 0x00000000,
+- MGA_FXRIGHT, 0x00000001,
+- MGA_DWGCTL, MGA_DWGCTL_FLUSH );
+-
+- DMA_BLOCK( MGA_LEN + MGA_EXEC, 0x00000001,
+- MGA_DWGSYNC, 0x00007000,
+- MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+- MGA_LEN + MGA_EXEC, 0x00000000 );
+-
+- DMA_BLOCK( MGA_TEXCTL2, (MGA_DUALTEX |
+- MGA_G400_TC2_MAGIC),
+- MGA_LEN + MGA_EXEC, 0x00000000,
+- MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+- MGA_DMAPAD, 0x00000000 );
++ DMA_BLOCK(MGA_YDST, 0x00000000,
++ MGA_FXLEFT, 0x00000000,
++ MGA_FXRIGHT, 0x00000001,
++ MGA_DWGCTL, MGA_DWGCTL_FLUSH);
++
++ DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001,
++ MGA_DWGSYNC, 0x00007000,
++ MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
++ MGA_LEN + MGA_EXEC, 0x00000000);
++
++ DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX |
++ MGA_G400_TC2_MAGIC),
++ MGA_LEN + MGA_EXEC, 0x00000000,
++ MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
++ MGA_DMAPAD, 0x00000000);
+ }
+
+- DMA_BLOCK( MGA_WVRTXSZ, 0x00001807,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000 );
+-
+- DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
+- MGA_WACCEPTSEQ, 0x00000000,
+- MGA_WACCEPTSEQ, 0x00000000,
+- MGA_WACCEPTSEQ, 0x18000000 );
+- }
+-
+- DMA_BLOCK( MGA_WFLAG, 0x00000000,
+- MGA_WFLAG1, 0x00000000,
+- MGA_WR56, MGA_G400_WR56_MAGIC,
+- MGA_DMAPAD, 0x00000000 );
+-
+- DMA_BLOCK( MGA_WR49, 0x00000000, /* tex0 */
+- MGA_WR57, 0x00000000, /* tex0 */
+- MGA_WR53, 0x00000000, /* tex1 */
+- MGA_WR61, 0x00000000 ); /* tex1 */
+-
+- DMA_BLOCK( MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */
+- MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */
+- MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */
+- MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */
++ DMA_BLOCK(MGA_WVRTXSZ, 0x00001807,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
++
++ DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
++ MGA_WACCEPTSEQ, 0x00000000,
++ MGA_WACCEPTSEQ, 0x00000000,
++ MGA_WACCEPTSEQ, 0x18000000);
++ }
++
++ DMA_BLOCK(MGA_WFLAG, 0x00000000,
++ MGA_WFLAG1, 0x00000000,
++ MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000);
++
++ DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0 */
++ MGA_WR57, 0x00000000, /* tex0 */
++ MGA_WR53, 0x00000000, /* tex1 */
++ MGA_WR61, 0x00000000); /* tex1 */
++
++ DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */
++ MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */
++ MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */
++ MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height */
+
+ /* Padding required to to hardware bug */
+ DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+@@ -350,71 +327,70 @@ static __inline__ void mga_g400_emit_pip
+ ADVANCE_DMA();
+ }
+
+-static void mga_g200_emit_state( drm_mga_private_t *dev_priv )
++static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+- if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
+- mga_g200_emit_pipe( dev_priv );
++ if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
++ mga_g200_emit_pipe(dev_priv);
+ dev_priv->warp_pipe = sarea_priv->warp_pipe;
+ }
+
+- if ( dirty & MGA_UPLOAD_CONTEXT ) {
+- mga_g200_emit_context( dev_priv );
++ if (dirty & MGA_UPLOAD_CONTEXT) {
++ mga_g200_emit_context(dev_priv);
+ sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+ }
+
+- if ( dirty & MGA_UPLOAD_TEX0 ) {
+- mga_g200_emit_tex0( dev_priv );
++ if (dirty & MGA_UPLOAD_TEX0) {
++ mga_g200_emit_tex0(dev_priv);
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+ }
+ }
+
+-static void mga_g400_emit_state( drm_mga_private_t *dev_priv )
++static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+ int multitex = sarea_priv->warp_pipe & MGA_T2;
+
+- if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
+- mga_g400_emit_pipe( dev_priv );
++ if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
++ mga_g400_emit_pipe(dev_priv);
+ dev_priv->warp_pipe = sarea_priv->warp_pipe;
+ }
+
+- if ( dirty & MGA_UPLOAD_CONTEXT ) {
+- mga_g400_emit_context( dev_priv );
++ if (dirty & MGA_UPLOAD_CONTEXT) {
++ mga_g400_emit_context(dev_priv);
+ sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+ }
+
+- if ( dirty & MGA_UPLOAD_TEX0 ) {
+- mga_g400_emit_tex0( dev_priv );
++ if (dirty & MGA_UPLOAD_TEX0) {
++ mga_g400_emit_tex0(dev_priv);
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+ }
+
+- if ( (dirty & MGA_UPLOAD_TEX1) && multitex ) {
+- mga_g400_emit_tex1( dev_priv );
++ if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
++ mga_g400_emit_tex1(dev_priv);
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
+ }
+ }
+
+-
+ /* ================================================================
+ * SAREA state verification
+ */
+
+ /* Disallow all write destinations except the front and backbuffer.
+ */
+-static int mga_verify_context( drm_mga_private_t *dev_priv )
++static int mga_verify_context(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+
+- if ( ctx->dstorg != dev_priv->front_offset &&
+- ctx->dstorg != dev_priv->back_offset ) {
+- DRM_ERROR( "*** bad DSTORG: %x (front %x, back %x)\n\n",
+- ctx->dstorg, dev_priv->front_offset,
+- dev_priv->back_offset );
++ if (ctx->dstorg != dev_priv->front_offset &&
++ ctx->dstorg != dev_priv->back_offset) {
++ DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n",
++ ctx->dstorg, dev_priv->front_offset,
++ dev_priv->back_offset);
+ ctx->dstorg = 0;
+ return DRM_ERR(EINVAL);
+ }
+@@ -424,7 +400,7 @@ static int mga_verify_context( drm_mga_p
+
+ /* Disallow texture reads from PCI space.
+ */
+-static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
++static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
+@@ -432,9 +408,8 @@ static int mga_verify_tex( drm_mga_priva
+
+ org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
+
+- if ( org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI) ) {
+- DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n",
+- tex->texorg, unit );
++ if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
++ DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
+ tex->texorg = 0;
+ return DRM_ERR(EINVAL);
+ }
+@@ -442,73 +417,70 @@ static int mga_verify_tex( drm_mga_priva
+ return 0;
+ }
+
+-static int mga_verify_state( drm_mga_private_t *dev_priv )
++static int mga_verify_state(drm_mga_private_t * dev_priv)
+ {
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+ int ret = 0;
+
+- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+- if ( dirty & MGA_UPLOAD_CONTEXT )
+- ret |= mga_verify_context( dev_priv );
++ if (dirty & MGA_UPLOAD_CONTEXT)
++ ret |= mga_verify_context(dev_priv);
+
+- if ( dirty & MGA_UPLOAD_TEX0 )
+- ret |= mga_verify_tex( dev_priv, 0 );
++ if (dirty & MGA_UPLOAD_TEX0)
++ ret |= mga_verify_tex(dev_priv, 0);
+
+ if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+ if (dirty & MGA_UPLOAD_TEX1)
+ ret |= mga_verify_tex(dev_priv, 1);
+
+- if ( dirty & MGA_UPLOAD_PIPE )
+- ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
++ if (dirty & MGA_UPLOAD_PIPE)
++ ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES);
+ } else {
+- if ( dirty & MGA_UPLOAD_PIPE )
+- ret |= ( sarea_priv->warp_pipe > MGA_MAX_G200_PIPES );
++ if (dirty & MGA_UPLOAD_PIPE)
++ ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES);
+ }
+
+- return ( ret == 0 );
++ return (ret == 0);
+ }
+
+-static int mga_verify_iload( drm_mga_private_t *dev_priv,
+- unsigned int dstorg, unsigned int length )
++static int mga_verify_iload(drm_mga_private_t * dev_priv,
++ unsigned int dstorg, unsigned int length)
+ {
+- if ( dstorg < dev_priv->texture_offset ||
+- dstorg + length > (dev_priv->texture_offset +
+- dev_priv->texture_size) ) {
+- DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg );
++ if (dstorg < dev_priv->texture_offset ||
++ dstorg + length > (dev_priv->texture_offset +
++ dev_priv->texture_size)) {
++ DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( length & MGA_ILOAD_MASK ) {
+- DRM_ERROR( "*** bad iload length: 0x%x\n",
+- length & MGA_ILOAD_MASK );
++ if (length & MGA_ILOAD_MASK) {
++ DRM_ERROR("*** bad iload length: 0x%x\n",
++ length & MGA_ILOAD_MASK);
+ return DRM_ERR(EINVAL);
+ }
+
+ return 0;
+ }
+
+-static int mga_verify_blit( drm_mga_private_t *dev_priv,
+- unsigned int srcorg, unsigned int dstorg )
++static int mga_verify_blit(drm_mga_private_t * dev_priv,
++ unsigned int srcorg, unsigned int dstorg)
+ {
+- if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
+- (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) {
+- DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n",
+- srcorg, dstorg );
++ if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
++ (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
++ DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
+ return DRM_ERR(EINVAL);
+ }
+ return 0;
+ }
+
+-
+ /* ================================================================
+ *
+ */
+
+-static void mga_dma_dispatch_clear( drm_device_t *dev,
+- drm_mga_clear_t *clear )
++static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -517,92 +489,86 @@ static void mga_dma_dispatch_clear( drm_
+ int nbox = sarea_priv->nbox;
+ int i;
+ DMA_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- BEGIN_DMA( 1 );
++ BEGIN_DMA(1);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DWGSYNC, 0x00007100,
+- MGA_DWGSYNC, 0x00007000 );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
+
+ ADVANCE_DMA();
+
+- for ( i = 0 ; i < nbox ; i++ ) {
++ for (i = 0; i < nbox; i++) {
+ drm_clip_rect_t *box = &pbox[i];
+ u32 height = box->y2 - box->y1;
+
+- DRM_DEBUG( " from=%d,%d to=%d,%d\n",
+- box->x1, box->y1, box->x2, box->y2 );
++ DRM_DEBUG(" from=%d,%d to=%d,%d\n",
++ box->x1, box->y1, box->x2, box->y2);
+
+- if ( clear->flags & MGA_FRONT ) {
+- BEGIN_DMA( 2 );
++ if (clear->flags & MGA_FRONT) {
++ BEGIN_DMA(2);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_PLNWT, clear->color_mask,
+- MGA_YDSTLEN, (box->y1 << 16) | height,
+- MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+-
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_FCOL, clear->clear_color,
+- MGA_DSTORG, dev_priv->front_offset,
+- MGA_DWGCTL + MGA_EXEC,
+- dev_priv->clear_cmd );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_PLNWT, clear->color_mask,
++ MGA_YDSTLEN, (box->y1 << 16) | height,
++ MGA_FXBNDRY, (box->x2 << 16) | box->x1);
++
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_FCOL, clear->clear_color,
++ MGA_DSTORG, dev_priv->front_offset,
++ MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+ ADVANCE_DMA();
+ }
+
++ if (clear->flags & MGA_BACK) {
++ BEGIN_DMA(2);
+
+- if ( clear->flags & MGA_BACK ) {
+- BEGIN_DMA( 2 );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_PLNWT, clear->color_mask,
++ MGA_YDSTLEN, (box->y1 << 16) | height,
++ MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_PLNWT, clear->color_mask,
+- MGA_YDSTLEN, (box->y1 << 16) | height,
+- MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+-
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_FCOL, clear->clear_color,
+- MGA_DSTORG, dev_priv->back_offset,
+- MGA_DWGCTL + MGA_EXEC,
+- dev_priv->clear_cmd );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_FCOL, clear->clear_color,
++ MGA_DSTORG, dev_priv->back_offset,
++ MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+ ADVANCE_DMA();
+ }
+
+- if ( clear->flags & MGA_DEPTH ) {
+- BEGIN_DMA( 2 );
++ if (clear->flags & MGA_DEPTH) {
++ BEGIN_DMA(2);
++
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_PLNWT, clear->depth_mask,
++ MGA_YDSTLEN, (box->y1 << 16) | height,
++ MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_PLNWT, clear->depth_mask,
+- MGA_YDSTLEN, (box->y1 << 16) | height,
+- MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+-
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_FCOL, clear->clear_depth,
+- MGA_DSTORG, dev_priv->depth_offset,
+- MGA_DWGCTL + MGA_EXEC,
+- dev_priv->clear_cmd );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_FCOL, clear->clear_depth,
++ MGA_DSTORG, dev_priv->depth_offset,
++ MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+ ADVANCE_DMA();
+ }
+
+ }
+
+- BEGIN_DMA( 1 );
++ BEGIN_DMA(1);
+
+ /* Force reset of DWGCTL */
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_PLNWT, ctx->plnwt,
+- MGA_DWGCTL, ctx->dwgctl );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
+
+ ADVANCE_DMA();
+
+ FLUSH_DMA();
+ }
+
+-static void mga_dma_dispatch_swap( drm_device_t *dev )
++static void mga_dma_dispatch_swap(drm_device_t * dev)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -611,56 +577,52 @@ static void mga_dma_dispatch_swap( drm_d
+ int nbox = sarea_priv->nbox;
+ int i;
+ DMA_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ sarea_priv->last_frame.head = dev_priv->prim.tail;
+ sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
+
+- BEGIN_DMA( 4 + nbox );
++ BEGIN_DMA(4 + nbox);
++
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DWGSYNC, 0x00007100,
+- MGA_DWGSYNC, 0x00007000 );
+-
+- DMA_BLOCK( MGA_DSTORG, dev_priv->front_offset,
+- MGA_MACCESS, dev_priv->maccess,
+- MGA_SRCORG, dev_priv->back_offset,
+- MGA_AR5, dev_priv->front_pitch );
+-
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_PLNWT, 0xffffffff,
+- MGA_DWGCTL, MGA_DWGCTL_COPY );
++ DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset,
++ MGA_MACCESS, dev_priv->maccess,
++ MGA_SRCORG, dev_priv->back_offset,
++ MGA_AR5, dev_priv->front_pitch);
+
+- for ( i = 0 ; i < nbox ; i++ ) {
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
++
++ for (i = 0; i < nbox; i++) {
+ drm_clip_rect_t *box = &pbox[i];
+ u32 height = box->y2 - box->y1;
+ u32 start = box->y1 * dev_priv->front_pitch;
+
+- DRM_DEBUG( " from=%d,%d to=%d,%d\n",
+- box->x1, box->y1, box->x2, box->y2 );
++ DRM_DEBUG(" from=%d,%d to=%d,%d\n",
++ box->x1, box->y1, box->x2, box->y2);
+
+- DMA_BLOCK( MGA_AR0, start + box->x2 - 1,
+- MGA_AR3, start + box->x1,
+- MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+- MGA_YDSTLEN + MGA_EXEC,
+- (box->y1 << 16) | height );
++ DMA_BLOCK(MGA_AR0, start + box->x2 - 1,
++ MGA_AR3, start + box->x1,
++ MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
++ MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height);
+ }
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_PLNWT, ctx->plnwt,
+- MGA_SRCORG, dev_priv->front_offset,
+- MGA_DWGCTL, ctx->dwgctl );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_PLNWT, ctx->plnwt,
++ MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl);
+
+ ADVANCE_DMA();
+
+ FLUSH_DMA();
+
+- DRM_DEBUG( "%s... done.\n", __FUNCTION__ );
++ DRM_DEBUG("%s... done.\n", __FUNCTION__);
+ }
+
+-static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
++static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+@@ -669,20 +631,20 @@ static void mga_dma_dispatch_vertex( drm
+ u32 length = (u32) buf->used;
+ int i = 0;
+ DMA_LOCALS;
+- DRM_DEBUG( "vertex: buf=%d used=%d\n", buf->idx, buf->used );
++ DRM_DEBUG("vertex: buf=%d used=%d\n", buf->idx, buf->used);
+
+- if ( buf->used ) {
++ if (buf->used) {
+ buf_priv->dispatched = 1;
+
+- MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
++ MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
+
+ do {
+- if ( i < sarea_priv->nbox ) {
+- mga_emit_clip_rect( dev_priv,
+- &sarea_priv->boxes[i] );
++ if (i < sarea_priv->nbox) {
++ mga_emit_clip_rect(dev_priv,
++ &sarea_priv->boxes[i]);
+ }
+
+- BEGIN_DMA( 1 );
++ BEGIN_DMA(1);
+
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+@@ -692,23 +654,23 @@ static void mga_dma_dispatch_vertex( drm
+ dev_priv->dma_access));
+
+ ADVANCE_DMA();
+- } while ( ++i < sarea_priv->nbox );
++ } while (++i < sarea_priv->nbox);
+ }
+
+- if ( buf_priv->discard ) {
+- AGE_BUFFER( buf_priv );
++ if (buf_priv->discard) {
++ AGE_BUFFER(buf_priv);
+ buf->pending = 0;
+ buf->used = 0;
+ buf_priv->dispatched = 0;
+
+- mga_freelist_put( dev, buf );
++ mga_freelist_put(dev, buf);
+ }
+
+ FLUSH_DMA();
+ }
+
+-static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
+- unsigned int start, unsigned int end )
++static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
++ unsigned int start, unsigned int end)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+@@ -716,20 +678,20 @@ static void mga_dma_dispatch_indices( dr
+ u32 address = (u32) buf->bus_address;
+ int i = 0;
+ DMA_LOCALS;
+- DRM_DEBUG( "indices: buf=%d start=%d end=%d\n", buf->idx, start, end );
++ DRM_DEBUG("indices: buf=%d start=%d end=%d\n", buf->idx, start, end);
+
+- if ( start != end ) {
++ if (start != end) {
+ buf_priv->dispatched = 1;
+
+- MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
++ MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
+
+ do {
+- if ( i < sarea_priv->nbox ) {
+- mga_emit_clip_rect( dev_priv,
+- &sarea_priv->boxes[i] );
++ if (i < sarea_priv->nbox) {
++ mga_emit_clip_rect(dev_priv,
++ &sarea_priv->boxes[i]);
+ }
+
+- BEGIN_DMA( 1 );
++ BEGIN_DMA(1);
+
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+@@ -738,16 +700,16 @@ static void mga_dma_dispatch_indices( dr
+ dev_priv->dma_access));
+
+ ADVANCE_DMA();
+- } while ( ++i < sarea_priv->nbox );
++ } while (++i < sarea_priv->nbox);
+ }
+
+- if ( buf_priv->discard ) {
+- AGE_BUFFER( buf_priv );
++ if (buf_priv->discard) {
++ AGE_BUFFER(buf_priv);
+ buf->pending = 0;
+ buf->used = 0;
+ buf_priv->dispatched = 0;
+
+- mga_freelist_put( dev, buf );
++ mga_freelist_put(dev, buf);
+ }
+
+ FLUSH_DMA();
+@@ -756,61 +718,55 @@ static void mga_dma_dispatch_indices( dr
+ /* This copies a 64 byte aligned agp region to the frambuffer with a
+ * standard blit, the ioctl needs to do checking.
+ */
+-static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
+- unsigned int dstorg, unsigned int length )
++static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
++ unsigned int dstorg, unsigned int length)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
+- u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
++ u32 srcorg =
++ buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
+ u32 y2;
+ DMA_LOCALS;
+- DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used );
++ DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
+
+ y2 = length / 64;
+
+- BEGIN_DMA( 5 );
++ BEGIN_DMA(5);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DWGSYNC, 0x00007100,
+- MGA_DWGSYNC, 0x00007000 );
+-
+- DMA_BLOCK( MGA_DSTORG, dstorg,
+- MGA_MACCESS, 0x00000000,
+- MGA_SRCORG, srcorg,
+- MGA_AR5, 64 );
+-
+- DMA_BLOCK( MGA_PITCH, 64,
+- MGA_PLNWT, 0xffffffff,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DWGCTL, MGA_DWGCTL_COPY );
+-
+- DMA_BLOCK( MGA_AR0, 63,
+- MGA_AR3, 0,
+- MGA_FXBNDRY, (63 << 16) | 0,
+- MGA_YDSTLEN + MGA_EXEC, y2 );
+-
+- DMA_BLOCK( MGA_PLNWT, ctx->plnwt,
+- MGA_SRCORG, dev_priv->front_offset,
+- MGA_PITCH, dev_priv->front_pitch,
+- MGA_DWGSYNC, 0x00007000 );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
++
++ DMA_BLOCK(MGA_DSTORG, dstorg,
++ MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64);
++
++ DMA_BLOCK(MGA_PITCH, 64,
++ MGA_PLNWT, 0xffffffff,
++ MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY);
++
++ DMA_BLOCK(MGA_AR0, 63,
++ MGA_AR3, 0,
++ MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2);
++
++ DMA_BLOCK(MGA_PLNWT, ctx->plnwt,
++ MGA_SRCORG, dev_priv->front_offset,
++ MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000);
+
+ ADVANCE_DMA();
+
+- AGE_BUFFER( buf_priv );
++ AGE_BUFFER(buf_priv);
+
+ buf->pending = 0;
+ buf->used = 0;
+ buf_priv->dispatched = 0;
+
+- mga_freelist_put( dev, buf );
++ mga_freelist_put(dev, buf);
+
+ FLUSH_DMA();
+ }
+
+-static void mga_dma_dispatch_blit( drm_device_t *dev,
+- drm_mga_blit_t *blit )
++static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
+ {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -819,26 +775,24 @@ static void mga_dma_dispatch_blit( drm_d
+ int nbox = sarea_priv->nbox;
+ u32 scandir = 0, i;
+ DMA_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- BEGIN_DMA( 4 + nbox );
++ BEGIN_DMA(4 + nbox);
++
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_DMAPAD, 0x00000000,
++ MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
+
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_DWGSYNC, 0x00007100,
+- MGA_DWGSYNC, 0x00007000 );
+-
+- DMA_BLOCK( MGA_DWGCTL, MGA_DWGCTL_COPY,
+- MGA_PLNWT, blit->planemask,
+- MGA_SRCORG, blit->srcorg,
+- MGA_DSTORG, blit->dstorg );
+-
+- DMA_BLOCK( MGA_SGN, scandir,
+- MGA_MACCESS, dev_priv->maccess,
+- MGA_AR5, blit->ydir * blit->src_pitch,
+- MGA_PITCH, blit->dst_pitch );
++ DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY,
++ MGA_PLNWT, blit->planemask,
++ MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg);
++
++ DMA_BLOCK(MGA_SGN, scandir,
++ MGA_MACCESS, dev_priv->maccess,
++ MGA_AR5, blit->ydir * blit->src_pitch,
++ MGA_PITCH, blit->dst_pitch);
+
+- for ( i = 0 ; i < nbox ; i++ ) {
++ for (i = 0; i < nbox; i++) {
+ int srcx = pbox[i].x1 + blit->delta_sx;
+ int srcy = pbox[i].y1 + blit->delta_sy;
+ int dstx = pbox[i].x1 + blit->delta_dx;
+@@ -847,52 +801,51 @@ static void mga_dma_dispatch_blit( drm_d
+ int w = pbox[i].x2 - pbox[i].x1 - 1;
+ int start;
+
+- if ( blit->ydir == -1 ) {
++ if (blit->ydir == -1) {
+ srcy = blit->height - srcy - 1;
+ }
+
+ start = srcy * blit->src_pitch + srcx;
+
+- DMA_BLOCK( MGA_AR0, start + w,
+- MGA_AR3, start,
+- MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
+- MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h );
++ DMA_BLOCK(MGA_AR0, start + w,
++ MGA_AR3, start,
++ MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
++ MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h);
+ }
+
+ /* Do something to flush AGP?
+ */
+
+ /* Force reset of DWGCTL */
+- DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+- MGA_PLNWT, ctx->plnwt,
+- MGA_PITCH, dev_priv->front_pitch,
+- MGA_DWGCTL, ctx->dwgctl );
++ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
++ MGA_PLNWT, ctx->plnwt,
++ MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl);
+
+ ADVANCE_DMA();
+ }
+
+-
+ /* ================================================================
+ *
+ */
+
+-static int mga_dma_clear( DRM_IOCTL_ARGS )
++static int mga_dma_clear(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_clear_t clear;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( clear, (drm_mga_clear_t __user *)data, sizeof(clear) );
++ DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data,
++ sizeof(clear));
+
+- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+- WRAP_TEST_WITH_RETURN( dev_priv );
++ WRAP_TEST_WITH_RETURN(dev_priv);
+
+- mga_dma_dispatch_clear( dev, &clear );
++ mga_dma_dispatch_clear(dev, &clear);
+
+ /* Make sure we restore the 3D state next time.
+ */
+@@ -901,20 +854,20 @@ static int mga_dma_clear( DRM_IOCTL_ARGS
+ return 0;
+ }
+
+-static int mga_dma_swap( DRM_IOCTL_ARGS )
++static int mga_dma_swap(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+- WRAP_TEST_WITH_RETURN( dev_priv );
++ WRAP_TEST_WITH_RETURN(dev_priv);
+
+- mga_dma_dispatch_swap( dev );
++ mga_dma_dispatch_swap(dev);
+
+ /* Make sure we restore the 3D state next time.
+ */
+@@ -923,7 +876,7 @@ static int mga_dma_swap( DRM_IOCTL_ARGS
+ return 0;
+ }
+
+-static int mga_dma_vertex( DRM_IOCTL_ARGS )
++static int mga_dma_vertex(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+@@ -932,37 +885,38 @@ static int mga_dma_vertex( DRM_IOCTL_ARG
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_vertex_t vertex;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( vertex,
+- (drm_mga_vertex_t __user *)data,
+- sizeof(vertex) );
++ DRM_COPY_FROM_USER_IOCTL(vertex,
++ (drm_mga_vertex_t __user *) data,
++ sizeof(vertex));
+
+- if(vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_ERR(EINVAL);
++ if (vertex.idx < 0 || vertex.idx > dma->buf_count)
++ return DRM_ERR(EINVAL);
+ buf = dma->buflist[vertex.idx];
+ buf_priv = buf->dev_private;
+
+ buf->used = vertex.used;
+ buf_priv->discard = vertex.discard;
+
+- if ( !mga_verify_state( dev_priv ) ) {
+- if ( vertex.discard ) {
+- if ( buf_priv->dispatched == 1 )
+- AGE_BUFFER( buf_priv );
++ if (!mga_verify_state(dev_priv)) {
++ if (vertex.discard) {
++ if (buf_priv->dispatched == 1)
++ AGE_BUFFER(buf_priv);
+ buf_priv->dispatched = 0;
+- mga_freelist_put( dev, buf );
++ mga_freelist_put(dev, buf);
+ }
+ return DRM_ERR(EINVAL);
+ }
+
+- WRAP_TEST_WITH_RETURN( dev_priv );
++ WRAP_TEST_WITH_RETURN(dev_priv);
+
+- mga_dma_dispatch_vertex( dev, buf );
++ mga_dma_dispatch_vertex(dev, buf);
+
+ return 0;
+ }
+
+-static int mga_dma_indices( DRM_IOCTL_ARGS )
++static int mga_dma_indices(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+@@ -971,37 +925,38 @@ static int mga_dma_indices( DRM_IOCTL_AR
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_indices_t indices;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( indices,
+- (drm_mga_indices_t __user *)data,
+- sizeof(indices) );
++ DRM_COPY_FROM_USER_IOCTL(indices,
++ (drm_mga_indices_t __user *) data,
++ sizeof(indices));
+
+- if(indices.idx < 0 || indices.idx > dma->buf_count) return DRM_ERR(EINVAL);
++ if (indices.idx < 0 || indices.idx > dma->buf_count)
++ return DRM_ERR(EINVAL);
+
+ buf = dma->buflist[indices.idx];
+ buf_priv = buf->dev_private;
+
+ buf_priv->discard = indices.discard;
+
+- if ( !mga_verify_state( dev_priv ) ) {
+- if ( indices.discard ) {
+- if ( buf_priv->dispatched == 1 )
+- AGE_BUFFER( buf_priv );
++ if (!mga_verify_state(dev_priv)) {
++ if (indices.discard) {
++ if (buf_priv->dispatched == 1)
++ AGE_BUFFER(buf_priv);
+ buf_priv->dispatched = 0;
+- mga_freelist_put( dev, buf );
++ mga_freelist_put(dev, buf);
+ }
+ return DRM_ERR(EINVAL);
+ }
+
+- WRAP_TEST_WITH_RETURN( dev_priv );
++ WRAP_TEST_WITH_RETURN(dev_priv);
+
+- mga_dma_dispatch_indices( dev, buf, indices.start, indices.end );
++ mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
+
+ return 0;
+ }
+
+-static int mga_dma_iload( DRM_IOCTL_ARGS )
++static int mga_dma_iload(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+@@ -1009,32 +964,34 @@ static int mga_dma_iload( DRM_IOCTL_ARGS
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_iload_t iload;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( iload, (drm_mga_iload_t __user *)data, sizeof(iload) );
++ DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data,
++ sizeof(iload));
+
+ #if 0
+- if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {
+- if ( MGA_DMA_DEBUG )
+- DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
++ if (mga_do_wait_for_idle(dev_priv) < 0) {
++ if (MGA_DMA_DEBUG)
++ DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
+ return DRM_ERR(EBUSY);
+ }
+ #endif
+- if(iload.idx < 0 || iload.idx > dma->buf_count) return DRM_ERR(EINVAL);
++ if (iload.idx < 0 || iload.idx > dma->buf_count)
++ return DRM_ERR(EINVAL);
+
+ buf = dma->buflist[iload.idx];
+ buf_priv = buf->dev_private;
+
+- if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) {
+- mga_freelist_put( dev, buf );
++ if (mga_verify_iload(dev_priv, iload.dstorg, iload.length)) {
++ mga_freelist_put(dev, buf);
+ return DRM_ERR(EINVAL);
+ }
+
+- WRAP_TEST_WITH_RETURN( dev_priv );
++ WRAP_TEST_WITH_RETURN(dev_priv);
+
+- mga_dma_dispatch_iload( dev, buf, iload.dstorg, iload.length );
++ mga_dma_dispatch_iload(dev, buf, iload.dstorg, iload.length);
+
+ /* Make sure we restore the 3D state next time.
+ */
+@@ -1043,27 +1000,28 @@ static int mga_dma_iload( DRM_IOCTL_ARGS
+ return 0;
+ }
+
+-static int mga_dma_blit( DRM_IOCTL_ARGS )
++static int mga_dma_blit(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_blit_t blit;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( blit, (drm_mga_blit_t __user *)data, sizeof(blit) );
++ DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data,
++ sizeof(blit));
+
+- if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+- if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) )
++ if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg))
+ return DRM_ERR(EINVAL);
+
+- WRAP_TEST_WITH_RETURN( dev_priv );
++ WRAP_TEST_WITH_RETURN(dev_priv);
+
+- mga_dma_dispatch_blit( dev, &blit );
++ mga_dma_dispatch_blit(dev, &blit);
+
+ /* Make sure we restore the 3D state next time.
+ */
+@@ -1072,24 +1030,24 @@ static int mga_dma_blit( DRM_IOCTL_ARGS
+ return 0;
+ }
+
+-static int mga_getparam( DRM_IOCTL_ARGS )
++static int mga_getparam(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_getparam_t param;
+ int value;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t __user *)data,
+- sizeof(param) );
++ DRM_COPY_FROM_USER_IOCTL(param, (drm_mga_getparam_t __user *) data,
++ sizeof(param));
+
+- DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
++ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+- switch( param.param ) {
++ switch (param.param) {
+ case MGA_PARAM_IRQ_NR:
+ value = dev->irq;
+ break;
+@@ -1100,11 +1058,11 @@ static int mga_getparam( DRM_IOCTL_ARGS
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+- DRM_ERROR( "copy_to_user\n" );
++ if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
++ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+-
++
+ return 0;
+ }
+
+@@ -1132,11 +1090,10 @@ static int mga_set_fence(DRM_IOCTL_ARGS)
+ BEGIN_DMA(1);
+ DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+- MGA_DMAPAD, 0x00000000,
+- MGA_SOFTRAP, 0x00000000);
++ MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000);
+ ADVANCE_DMA();
+
+- if (DRM_COPY_TO_USER( (u32 __user *) data, & temp, sizeof(u32))) {
++ if (DRM_COPY_TO_USER((u32 __user *) data, &temp, sizeof(u32))) {
+ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+@@ -1159,9 +1116,9 @@ static int mga_wait_fence(DRM_IOCTL_ARGS
+
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+- mga_driver_fence_wait(dev, & fence);
++ mga_driver_fence_wait(dev, &fence);
+
+- if (DRM_COPY_TO_USER( (u32 __user *) data, & fence, sizeof(u32))) {
++ if (DRM_COPY_TO_USER((u32 __user *) data, &fence, sizeof(u32))) {
+ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+@@ -1183,7 +1140,6 @@ drm_ioctl_desc_t mga_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, 1, 0},
+ [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, 1, 1},
+-
+ };
+
+ int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
+diff --git a/drivers/char/drm/mga_ucode.h b/drivers/char/drm/mga_ucode.h
+--- a/drivers/char/drm/mga_ucode.h
++++ b/drivers/char/drm/mga_ucode.h
+@@ -40,11606 +40,11606 @@
+
+ static unsigned char warp_g200_tgz[] = {
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x72, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x72, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x60, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x60, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x03, 0x80, 0x0A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x0A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x57, 0x39, 0x20, 0xE9,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x57, 0x39, 0x20, 0xE9,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0x2B, 0x32, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0xB3, 0x05,
+-0x00, 0xE0,
+-0x16, 0x28, 0x20, 0xE9,
++ 0xB3, 0x05,
++ 0x00, 0xE0,
++ 0x16, 0x28, 0x20, 0xE9,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x1E, 0x2B, 0x20, 0xE9,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x1E, 0x2B, 0x20, 0xE9,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x85, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x85, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x84, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x84, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x82, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x82, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x7F, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x7F, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g200_tgza[] = {
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x7D, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x7D, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x6B, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x6B, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2D, 0x44, 0x4C, 0xB6,
+-0x25, 0x44, 0x54, 0xB6,
++ 0x2D, 0x44, 0x4C, 0xB6,
++ 0x25, 0x44, 0x54, 0xB6,
+
+-0x03, 0x80, 0x2A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x2A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x2D, 0x20,
+-0x25, 0x20,
+-0x07, 0xC0, 0x44, 0xC6,
++ 0x2D, 0x20,
++ 0x25, 0x20,
++ 0x07, 0xC0, 0x44, 0xC6,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x1F, 0x62, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x62, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x3F, 0x3D, 0x5D, 0x9F,
+-0x00, 0xE0,
+-0x07, 0x20,
++ 0x3F, 0x3D, 0x5D, 0x9F,
++ 0x00, 0xE0,
++ 0x07, 0x20,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0xB3, 0x05,
+-0x00, 0xE0,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x05,
++ 0x00, 0xE0,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0x26, 0x1F, 0xDF,
+-0x9D, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x26, 0x1F, 0xDF,
++ 0x9D, 0x1F, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x9E, 0x3F, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x9E, 0x3F, 0x4F, 0xE9,
+
+-0x07, 0x07, 0x1F, 0xAF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x07, 0x07, 0x1F, 0xAF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x9C, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x57, 0x39, 0x20, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x57, 0x39, 0x20, 0xE9,
+
+-0x16, 0x28, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x16, 0x28, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0x1E, 0x2B, 0x20, 0xE9,
+-0x2B, 0x32, 0x20, 0xE9,
++ 0x1E, 0x2B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
+
+-0x1C, 0x23, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x23, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x7A, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x7A, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x79, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x79, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x77, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x77, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x74, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x74, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g200_tgzaf[] = {
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x83, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x83, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x21, 0x45, 0x80, 0xE8,
+-0x1A, 0x4D, 0x80, 0xE8,
++ 0x21, 0x45, 0x80, 0xE8,
++ 0x1A, 0x4D, 0x80, 0xE8,
+
+-0x31, 0x55, 0x80, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x55, 0x80, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x6F, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x6F, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0D, 0x21, 0x1A, 0xB6,
+-0x05, 0x21, 0x31, 0xB6,
++ 0x0D, 0x21, 0x1A, 0xB6,
++ 0x05, 0x21, 0x31, 0xB6,
+
+-0x2D, 0x44, 0x4C, 0xB6,
+-0x25, 0x44, 0x54, 0xB6,
++ 0x2D, 0x44, 0x4C, 0xB6,
++ 0x25, 0x44, 0x54, 0xB6,
+
+-0x03, 0x80, 0x2A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x2A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x0D, 0x20,
+-0x05, 0x20,
+-0x2F, 0xC0, 0x21, 0xC6,
++ 0x0D, 0x20,
++ 0x05, 0x20,
++ 0x2F, 0xC0, 0x21, 0xC6,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x07, 0xC0, 0x44, 0xC6,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x07, 0xC0, 0x44, 0xC6,
+
+-0x17, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x2D, 0x20,
++ 0x17, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x2D, 0x20,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0xE0,
+-0x2F, 0x20,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0xE0,
++ 0x2F, 0x20,
+
+-0x1F, 0x62, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x07, 0x20,
++ 0x1F, 0x62, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x07, 0x20,
+
+-0x3F, 0x3D, 0x5D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0x3D, 0x5D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0xB3, 0x05,
+-0x00, 0xE0,
+-0x17, 0x26, 0x17, 0xDF,
++ 0xB3, 0x05,
++ 0x00, 0xE0,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x35, 0x17, 0x4F, 0xE9,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x35, 0x17, 0x4F, 0xE9,
+
+-0x1F, 0x26, 0x1F, 0xDF,
+-0x9D, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x26, 0x1F, 0xDF,
++ 0x9D, 0x1F, 0x4F, 0xE9,
+
+-0x9E, 0x3F, 0x4F, 0xE9,
+-0x39, 0x37, 0x4F, 0xE9,
++ 0x9E, 0x3F, 0x4F, 0xE9,
++ 0x39, 0x37, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x17, 0xAF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x2F, 0x2F, 0x17, 0xAF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x07, 0x07, 0x1F, 0xAF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x07, 0x07, 0x1F, 0xAF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x31, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x9C, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x57, 0x39, 0x20, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x57, 0x39, 0x20, 0xE9,
+
+-0x16, 0x28, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x16, 0x28, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0x1E, 0x2B, 0x20, 0xE9,
+-0x2B, 0x32, 0x20, 0xE9,
++ 0x1E, 0x2B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
+
+-0x1C, 0x23, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x23, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x74, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x74, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x73, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x73, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x71, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x71, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6E, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x6E, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g200_tgzf[] = {
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x7F, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x7F, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x21, 0x45, 0x80, 0xE8,
+-0x1A, 0x4D, 0x80, 0xE8,
++ 0x21, 0x45, 0x80, 0xE8,
++ 0x1A, 0x4D, 0x80, 0xE8,
+
+-0x31, 0x55, 0x80, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x55, 0x80, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x6B, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x6B, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0D, 0x21, 0x1A, 0xB6,
+-0x05, 0x21, 0x31, 0xB6,
++ 0x0D, 0x21, 0x1A, 0xB6,
++ 0x05, 0x21, 0x31, 0xB6,
+
+-0x03, 0x80, 0x2A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x2A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x0D, 0x20,
+-0x05, 0x20,
+-0x2F, 0xC0, 0x21, 0xC6,
++ 0x0D, 0x20,
++ 0x05, 0x20,
++ 0x2F, 0xC0, 0x21, 0xC6,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x17, 0x50, 0x56, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x17, 0x50, 0x56, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0xE0,
+-0x2F, 0x20,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0xE0,
++ 0x2F, 0x20,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0xB3, 0x05,
+-0x00, 0xE0,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x05,
++ 0x00, 0xE0,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x17, 0x26, 0x17, 0xDF,
+-0x35, 0x17, 0x4F, 0xE9,
++ 0x17, 0x26, 0x17, 0xDF,
++ 0x35, 0x17, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x39, 0x37, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x39, 0x37, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x17, 0xAF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x2F, 0x2F, 0x17, 0xAF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x31, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x57, 0x39, 0x20, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x57, 0x39, 0x20, 0xE9,
+
+-0x16, 0x28, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x16, 0x28, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0x1E, 0x2B, 0x20, 0xE9,
+-0x2B, 0x32, 0x20, 0xE9,
++ 0x1E, 0x2B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
+
+-0x1C, 0x23, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x23, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x78, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x78, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x77, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x77, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x75, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x75, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x72, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x72, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g200_tgzs[] = {
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x8B, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x21, 0x45, 0x80, 0xE8,
+-0x1A, 0x4D, 0x80, 0xE8,
++ 0x21, 0x45, 0x80, 0xE8,
++ 0x1A, 0x4D, 0x80, 0xE8,
+
+-0x31, 0x55, 0x80, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x55, 0x80, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x77, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x77, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2D, 0x21, 0x1A, 0xB0,
+-0x25, 0x21, 0x31, 0xB0,
++ 0x2D, 0x21, 0x1A, 0xB0,
++ 0x25, 0x21, 0x31, 0xB0,
+
+-0x0D, 0x21, 0x1A, 0xB2,
+-0x05, 0x21, 0x31, 0xB2,
++ 0x0D, 0x21, 0x1A, 0xB2,
++ 0x05, 0x21, 0x31, 0xB2,
+
+-0x03, 0x80, 0x2A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x2A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x2D, 0x20,
+-0x25, 0x20,
+-0x05, 0x20,
+-0x0D, 0x20,
++ 0x2D, 0x20,
++ 0x25, 0x20,
++ 0x05, 0x20,
++ 0x0D, 0x20,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x2F, 0xC0, 0x21, 0xC0,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x2F, 0xC0, 0x21, 0xC0,
+
+-0x16, 0x42, 0x56, 0x9F,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x16, 0x42, 0x56, 0x9F,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x1E, 0x62, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0x62, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x21, 0x31, 0xB4,
+-0x2D, 0x21, 0x1A, 0xB4,
++ 0x25, 0x21, 0x31, 0xB4,
++ 0x2D, 0x21, 0x1A, 0xB4,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0x05,
+-0x00, 0xE0,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x33, 0x05,
++ 0x00, 0xE0,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0xE0,
+-0x2F, 0x20,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0xE0,
++ 0x2F, 0x20,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x1E, 0x26, 0x1E, 0xDF,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x1E, 0x26, 0x1E, 0xDF,
+
+-0xA7, 0x1E, 0x4F, 0xE9,
+-0x17, 0x26, 0x16, 0xDF,
++ 0xA7, 0x1E, 0x4F, 0xE9,
++ 0x17, 0x26, 0x16, 0xDF,
+
+-0x2D, 0x20,
+-0x00, 0xE0,
+-0xA8, 0x3F, 0x4F, 0xE9,
++ 0x2D, 0x20,
++ 0x00, 0xE0,
++ 0xA8, 0x3F, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x1E, 0xAF,
+-0x25, 0x20,
+-0x00, 0xE0,
++ 0x2F, 0x2F, 0x1E, 0xAF,
++ 0x25, 0x20,
++ 0x00, 0xE0,
+
+-0xA4, 0x16, 0x4F, 0xE9,
+-0x0F, 0xC0, 0x21, 0xC2,
++ 0xA4, 0x16, 0x4F, 0xE9,
++ 0x0F, 0xC0, 0x21, 0xC2,
+
+-0xA6, 0x80, 0x4F, 0xE9,
+-0x1F, 0x62, 0x57, 0x9F,
++ 0xA6, 0x80, 0x4F, 0xE9,
++ 0x1F, 0x62, 0x57, 0x9F,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0xE0,
+-0x8F, 0x20,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0xE0,
++ 0x8F, 0x20,
+
+-0xA5, 0x37, 0x4F, 0xE9,
+-0x0F, 0x17, 0x0F, 0xAF,
++ 0xA5, 0x37, 0x4F, 0xE9,
++ 0x0F, 0x17, 0x0F, 0xAF,
+
+-0x06, 0xC0, 0x21, 0xC4,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x06, 0xC0, 0x21, 0xC4,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0xA3, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0xA3, 0x80, 0x4F, 0xE9,
+
+-0x06, 0x20,
+-0x00, 0xE0,
+-0x1F, 0x26, 0x1F, 0xDF,
++ 0x06, 0x20,
++ 0x00, 0xE0,
++ 0x1F, 0x26, 0x1F, 0xDF,
+
+-0xA1, 0x1F, 0x4F, 0xE9,
+-0xA2, 0x3F, 0x4F, 0xE9,
++ 0xA1, 0x1F, 0x4F, 0xE9,
++ 0xA2, 0x3F, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x06, 0x06, 0x1F, 0xAF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x06, 0x06, 0x1F, 0xAF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x57, 0x39, 0x20, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x57, 0x39, 0x20, 0xE9,
+
+-0x16, 0x28, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x16, 0x28, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0x1E, 0x2B, 0x20, 0xE9,
+-0x2B, 0x32, 0x20, 0xE9,
++ 0x1E, 0x2B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
+
+-0x1C, 0x23, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x23, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x6C, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x6C, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6B, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x6B, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x69, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x69, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x66, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g200_tgzsa[] = {
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x8F, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x8F, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x21, 0x45, 0x80, 0xE8,
+-0x1A, 0x4D, 0x80, 0xE8,
++ 0x21, 0x45, 0x80, 0xE8,
++ 0x1A, 0x4D, 0x80, 0xE8,
+
+-0x31, 0x55, 0x80, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x55, 0x80, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x7B, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x7B, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2D, 0x21, 0x1A, 0xB0,
+-0x25, 0x21, 0x31, 0xB0,
++ 0x2D, 0x21, 0x1A, 0xB0,
++ 0x25, 0x21, 0x31, 0xB0,
+
+-0x0D, 0x21, 0x1A, 0xB2,
+-0x05, 0x21, 0x31, 0xB2,
++ 0x0D, 0x21, 0x1A, 0xB2,
++ 0x05, 0x21, 0x31, 0xB2,
+
+-0x03, 0x80, 0x2A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x2A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x2D, 0x20,
+-0x25, 0x20,
+-0x05, 0x20,
+-0x0D, 0x20,
++ 0x2D, 0x20,
++ 0x25, 0x20,
++ 0x05, 0x20,
++ 0x0D, 0x20,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x2F, 0xC0, 0x21, 0xC0,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x2F, 0xC0, 0x21, 0xC0,
+
+-0x16, 0x42, 0x56, 0x9F,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x16, 0x42, 0x56, 0x9F,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x1E, 0x62, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0x62, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x21, 0x31, 0xB4,
+-0x2D, 0x21, 0x1A, 0xB4,
++ 0x25, 0x21, 0x31, 0xB4,
++ 0x2D, 0x21, 0x1A, 0xB4,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0x05,
+-0x00, 0xE0,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x33, 0x05,
++ 0x00, 0xE0,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0x0D, 0x44, 0x4C, 0xB6,
+-0x05, 0x44, 0x54, 0xB6,
++ 0x0D, 0x44, 0x4C, 0xB6,
++ 0x05, 0x44, 0x54, 0xB6,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0xE0,
+-0x2F, 0x20,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0xE0,
++ 0x2F, 0x20,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x1E, 0x26, 0x1E, 0xDF,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x1E, 0x26, 0x1E, 0xDF,
+
+-0xA7, 0x1E, 0x4F, 0xE9,
+-0x17, 0x26, 0x16, 0xDF,
++ 0xA7, 0x1E, 0x4F, 0xE9,
++ 0x17, 0x26, 0x16, 0xDF,
+
+-0x2D, 0x20,
+-0x00, 0xE0,
+-0xA8, 0x3F, 0x4F, 0xE9,
++ 0x2D, 0x20,
++ 0x00, 0xE0,
++ 0xA8, 0x3F, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x1E, 0xAF,
+-0x25, 0x20,
+-0x00, 0xE0,
++ 0x2F, 0x2F, 0x1E, 0xAF,
++ 0x25, 0x20,
++ 0x00, 0xE0,
+
+-0xA4, 0x16, 0x4F, 0xE9,
+-0x0F, 0xC0, 0x21, 0xC2,
++ 0xA4, 0x16, 0x4F, 0xE9,
++ 0x0F, 0xC0, 0x21, 0xC2,
+
+-0xA6, 0x80, 0x4F, 0xE9,
+-0x1F, 0x62, 0x57, 0x9F,
++ 0xA6, 0x80, 0x4F, 0xE9,
++ 0x1F, 0x62, 0x57, 0x9F,
+
+-0x0D, 0x20,
+-0x05, 0x20,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x20,
++ 0x05, 0x20,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0xE0,
+-0x0F, 0x20,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0xE0,
++ 0x0F, 0x20,
+
+-0x17, 0x50, 0x56, 0x9F,
+-0xA5, 0x37, 0x4F, 0xE9,
++ 0x17, 0x50, 0x56, 0x9F,
++ 0xA5, 0x37, 0x4F, 0xE9,
+
+-0x06, 0xC0, 0x21, 0xC4,
+-0x0F, 0x17, 0x0F, 0xAF,
++ 0x06, 0xC0, 0x21, 0xC4,
++ 0x0F, 0x17, 0x0F, 0xAF,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2F, 0xC0, 0x44, 0xC6,
+-0xA3, 0x80, 0x4F, 0xE9,
++ 0x2F, 0xC0, 0x44, 0xC6,
++ 0xA3, 0x80, 0x4F, 0xE9,
+
+-0x06, 0x20,
+-0x00, 0xE0,
+-0x1F, 0x26, 0x1F, 0xDF,
++ 0x06, 0x20,
++ 0x00, 0xE0,
++ 0x1F, 0x26, 0x1F, 0xDF,
+
+-0x17, 0x26, 0x17, 0xDF,
+-0x9D, 0x17, 0x4F, 0xE9,
++ 0x17, 0x26, 0x17, 0xDF,
++ 0x9D, 0x17, 0x4F, 0xE9,
+
+-0xA1, 0x1F, 0x4F, 0xE9,
+-0xA2, 0x3F, 0x4F, 0xE9,
++ 0xA1, 0x1F, 0x4F, 0xE9,
++ 0xA2, 0x3F, 0x4F, 0xE9,
+
+-0x06, 0x06, 0x1F, 0xAF,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0x06, 0x06, 0x1F, 0xAF,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x9E, 0x37, 0x4F, 0xE9,
+-0x2F, 0x17, 0x2F, 0xAF,
++ 0x9E, 0x37, 0x4F, 0xE9,
++ 0x2F, 0x17, 0x2F, 0xAF,
+
+-0xA0, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x9C, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x80, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x57, 0x39, 0x20, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x57, 0x39, 0x20, 0xE9,
+
+-0x16, 0x28, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x16, 0x28, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0x1E, 0x2B, 0x20, 0xE9,
+-0x2B, 0x32, 0x20, 0xE9,
++ 0x1E, 0x2B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
+
+-0x1C, 0x23, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x23, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x68, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x68, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x67, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x67, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x65, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x65, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x62, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x62, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g200_tgzsaf[] = {
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x94, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x94, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x21, 0x45, 0x80, 0xE8,
+-0x1A, 0x4D, 0x80, 0xE8,
++ 0x21, 0x45, 0x80, 0xE8,
++ 0x1A, 0x4D, 0x80, 0xE8,
+
+-0x31, 0x55, 0x80, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x55, 0x80, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x80, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x80, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2D, 0x21, 0x1A, 0xB0,
+-0x25, 0x21, 0x31, 0xB0,
++ 0x2D, 0x21, 0x1A, 0xB0,
++ 0x25, 0x21, 0x31, 0xB0,
+
+-0x0D, 0x21, 0x1A, 0xB2,
+-0x05, 0x21, 0x31, 0xB2,
++ 0x0D, 0x21, 0x1A, 0xB2,
++ 0x05, 0x21, 0x31, 0xB2,
+
+-0x03, 0x80, 0x2A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x2A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x2D, 0x20,
+-0x25, 0x20,
+-0x05, 0x20,
+-0x0D, 0x20,
++ 0x2D, 0x20,
++ 0x25, 0x20,
++ 0x05, 0x20,
++ 0x0D, 0x20,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x2F, 0xC0, 0x21, 0xC0,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x2F, 0xC0, 0x21, 0xC0,
+
+-0x16, 0x42, 0x56, 0x9F,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x16, 0x42, 0x56, 0x9F,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x1E, 0x62, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0x62, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x21, 0x31, 0xB4,
+-0x2D, 0x21, 0x1A, 0xB4,
++ 0x25, 0x21, 0x31, 0xB4,
++ 0x2D, 0x21, 0x1A, 0xB4,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0x05,
+-0x00, 0xE0,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x33, 0x05,
++ 0x00, 0xE0,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0x0D, 0x21, 0x1A, 0xB6,
+-0x05, 0x21, 0x31, 0xB6,
++ 0x0D, 0x21, 0x1A, 0xB6,
++ 0x05, 0x21, 0x31, 0xB6,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0xE0,
+-0x2F, 0x20,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0xE0,
++ 0x2F, 0x20,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x1E, 0x26, 0x1E, 0xDF,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x1E, 0x26, 0x1E, 0xDF,
+
+-0xA7, 0x1E, 0x4F, 0xE9,
+-0x17, 0x26, 0x16, 0xDF,
++ 0xA7, 0x1E, 0x4F, 0xE9,
++ 0x17, 0x26, 0x16, 0xDF,
+
+-0x2D, 0x20,
+-0x00, 0xE0,
+-0xA8, 0x3F, 0x4F, 0xE9,
++ 0x2D, 0x20,
++ 0x00, 0xE0,
++ 0xA8, 0x3F, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x1E, 0xAF,
+-0x25, 0x20,
+-0x00, 0xE0,
++ 0x2F, 0x2F, 0x1E, 0xAF,
++ 0x25, 0x20,
++ 0x00, 0xE0,
+
+-0xA4, 0x16, 0x4F, 0xE9,
+-0x0F, 0xC0, 0x21, 0xC2,
++ 0xA4, 0x16, 0x4F, 0xE9,
++ 0x0F, 0xC0, 0x21, 0xC2,
+
+-0xA6, 0x80, 0x4F, 0xE9,
+-0x1F, 0x62, 0x57, 0x9F,
++ 0xA6, 0x80, 0x4F, 0xE9,
++ 0x1F, 0x62, 0x57, 0x9F,
+
+-0x0D, 0x20,
+-0x05, 0x20,
+-0x2F, 0xC0, 0x21, 0xC6,
++ 0x0D, 0x20,
++ 0x05, 0x20,
++ 0x2F, 0xC0, 0x21, 0xC6,
+
+-0x2D, 0x44, 0x4C, 0xB6,
+-0x25, 0x44, 0x54, 0xB6,
++ 0x2D, 0x44, 0x4C, 0xB6,
++ 0x25, 0x44, 0x54, 0xB6,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0xE0,
+-0x0F, 0x20,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0xE0,
++ 0x0F, 0x20,
+
+-0x2D, 0x20,
+-0x25, 0x20,
+-0x07, 0xC0, 0x44, 0xC6,
++ 0x2D, 0x20,
++ 0x25, 0x20,
++ 0x07, 0xC0, 0x44, 0xC6,
+
+-0x17, 0x50, 0x56, 0x9F,
+-0xA5, 0x37, 0x4F, 0xE9,
++ 0x17, 0x50, 0x56, 0x9F,
++ 0xA5, 0x37, 0x4F, 0xE9,
+
+-0x06, 0xC0, 0x21, 0xC4,
+-0x0F, 0x17, 0x0F, 0xAF,
++ 0x06, 0xC0, 0x21, 0xC4,
++ 0x0F, 0x17, 0x0F, 0xAF,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1E, 0x62, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0x62, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x3E, 0x3D, 0x5D, 0x9F,
+-0x00, 0xE0,
+-0x07, 0x20,
++ 0x3E, 0x3D, 0x5D, 0x9F,
++ 0x00, 0xE0,
++ 0x07, 0x20,
+
+-0x2F, 0x20,
+-0x00, 0xE0,
+-0xA3, 0x0F, 0x4F, 0xE9,
++ 0x2F, 0x20,
++ 0x00, 0xE0,
++ 0xA3, 0x0F, 0x4F, 0xE9,
+
+-0x06, 0x20,
+-0x00, 0xE0,
+-0x1F, 0x26, 0x1F, 0xDF,
++ 0x06, 0x20,
++ 0x00, 0xE0,
++ 0x1F, 0x26, 0x1F, 0xDF,
+
+-0x17, 0x26, 0x17, 0xDF,
+-0xA1, 0x1F, 0x4F, 0xE9,
++ 0x17, 0x26, 0x17, 0xDF,
++ 0xA1, 0x1F, 0x4F, 0xE9,
+
+-0x1E, 0x26, 0x1E, 0xDF,
+-0x9D, 0x1E, 0x4F, 0xE9,
++ 0x1E, 0x26, 0x1E, 0xDF,
++ 0x9D, 0x1E, 0x4F, 0xE9,
+
+-0x35, 0x17, 0x4F, 0xE9,
+-0xA2, 0x3F, 0x4F, 0xE9,
++ 0x35, 0x17, 0x4F, 0xE9,
++ 0xA2, 0x3F, 0x4F, 0xE9,
+
+-0x06, 0x06, 0x1F, 0xAF,
+-0x39, 0x37, 0x4F, 0xE9,
++ 0x06, 0x06, 0x1F, 0xAF,
++ 0x39, 0x37, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x17, 0xAF,
+-0x07, 0x07, 0x1E, 0xAF,
++ 0x2F, 0x2F, 0x17, 0xAF,
++ 0x07, 0x07, 0x1E, 0xAF,
+
+-0xA0, 0x80, 0x4F, 0xE9,
+-0x9E, 0x3E, 0x4F, 0xE9,
++ 0xA0, 0x80, 0x4F, 0xE9,
++ 0x9E, 0x3E, 0x4F, 0xE9,
+
+-0x31, 0x80, 0x4F, 0xE9,
+-0x9C, 0x80, 0x4F, 0xE9,
++ 0x31, 0x80, 0x4F, 0xE9,
++ 0x9C, 0x80, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x57, 0x39, 0x20, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x57, 0x39, 0x20, 0xE9,
+
+-0x16, 0x28, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x16, 0x28, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0x1E, 0x2B, 0x20, 0xE9,
+-0x2B, 0x32, 0x20, 0xE9,
++ 0x1E, 0x2B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
+
+-0x1C, 0x23, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x23, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x63, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x63, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x62, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x62, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x60, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x60, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x5D, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x5D, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g200_tgzsf[] = {
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x98, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x98, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x81, 0x04,
+-0x89, 0x04,
+-0x01, 0x04,
+-0x09, 0x04,
++ 0x81, 0x04,
++ 0x89, 0x04,
++ 0x01, 0x04,
++ 0x09, 0x04,
+
+-0xC9, 0x41, 0xC0, 0xEC,
+-0x11, 0x04,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC0, 0xEC,
++ 0x11, 0x04,
++ 0x00, 0xE0,
+
+-0x41, 0xCC, 0x41, 0xCD,
+-0x49, 0xCC, 0x49, 0xCD,
++ 0x41, 0xCC, 0x41, 0xCD,
++ 0x49, 0xCC, 0x49, 0xCD,
+
+-0xD1, 0x41, 0xC0, 0xEC,
+-0x51, 0xCC, 0x51, 0xCD,
++ 0xD1, 0x41, 0xC0, 0xEC,
++ 0x51, 0xCC, 0x51, 0xCD,
+
+-0x80, 0x04,
+-0x10, 0x04,
+-0x08, 0x04,
+-0x00, 0xE0,
++ 0x80, 0x04,
++ 0x10, 0x04,
++ 0x08, 0x04,
++ 0x00, 0xE0,
+
+-0x00, 0xCC, 0xC0, 0xCD,
+-0xD1, 0x49, 0xC0, 0xEC,
++ 0x00, 0xCC, 0xC0, 0xCD,
++ 0xD1, 0x49, 0xC0, 0xEC,
+
+-0x8A, 0x1F, 0x20, 0xE9,
+-0x8B, 0x3F, 0x20, 0xE9,
++ 0x8A, 0x1F, 0x20, 0xE9,
++ 0x8B, 0x3F, 0x20, 0xE9,
+
+-0x41, 0x3C, 0x41, 0xAD,
+-0x49, 0x3C, 0x49, 0xAD,
++ 0x41, 0x3C, 0x41, 0xAD,
++ 0x49, 0x3C, 0x49, 0xAD,
+
+-0x10, 0xCC, 0x10, 0xCD,
+-0x08, 0xCC, 0x08, 0xCD,
++ 0x10, 0xCC, 0x10, 0xCD,
++ 0x08, 0xCC, 0x08, 0xCD,
+
+-0xB9, 0x41, 0x49, 0xBB,
+-0x1F, 0xF0, 0x41, 0xCD,
++ 0xB9, 0x41, 0x49, 0xBB,
++ 0x1F, 0xF0, 0x41, 0xCD,
+
+-0x51, 0x3C, 0x51, 0xAD,
+-0x00, 0x98, 0x80, 0xE9,
++ 0x51, 0x3C, 0x51, 0xAD,
++ 0x00, 0x98, 0x80, 0xE9,
+
+-0x8F, 0x80, 0x07, 0xEA,
+-0x24, 0x1F, 0x20, 0xE9,
++ 0x8F, 0x80, 0x07, 0xEA,
++ 0x24, 0x1F, 0x20, 0xE9,
+
+-0x21, 0x45, 0x80, 0xE8,
+-0x1A, 0x4D, 0x80, 0xE8,
++ 0x21, 0x45, 0x80, 0xE8,
++ 0x1A, 0x4D, 0x80, 0xE8,
+
+-0x31, 0x55, 0x80, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x55, 0x80, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0x41, 0x49, 0xBD,
+-0x1D, 0x41, 0x51, 0xBD,
++ 0x15, 0x41, 0x49, 0xBD,
++ 0x1D, 0x41, 0x51, 0xBD,
+
+-0x2E, 0x41, 0x2A, 0xB8,
+-0x34, 0x53, 0xA0, 0xE8,
++ 0x2E, 0x41, 0x2A, 0xB8,
++ 0x34, 0x53, 0xA0, 0xE8,
+
+-0x15, 0x30,
+-0x1D, 0x30,
+-0x58, 0xE3,
+-0x00, 0xE0,
++ 0x15, 0x30,
++ 0x1D, 0x30,
++ 0x58, 0xE3,
++ 0x00, 0xE0,
+
+-0xB5, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0xB5, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x24, 0x43, 0xA0, 0xE8,
+-0x2C, 0x4B, 0xA0, 0xE8,
++ 0x24, 0x43, 0xA0, 0xE8,
++ 0x2C, 0x4B, 0xA0, 0xE8,
+
+-0x15, 0x72,
+-0x09, 0xE3,
+-0x00, 0xE0,
+-0x1D, 0x72,
++ 0x15, 0x72,
++ 0x09, 0xE3,
++ 0x00, 0xE0,
++ 0x1D, 0x72,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0x97, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0x97, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x6C, 0x64, 0xC8, 0xEC,
+-0x98, 0xE1,
+-0xB5, 0x05,
++ 0x6C, 0x64, 0xC8, 0xEC,
++ 0x98, 0xE1,
++ 0xB5, 0x05,
+
+-0xBD, 0x05,
+-0x2E, 0x30,
+-0x32, 0xC0, 0xA0, 0xE8,
++ 0xBD, 0x05,
++ 0x2E, 0x30,
++ 0x32, 0xC0, 0xA0, 0xE8,
+
+-0x33, 0xC0, 0xA0, 0xE8,
+-0x74, 0x64, 0xC8, 0xEC,
++ 0x33, 0xC0, 0xA0, 0xE8,
++ 0x74, 0x64, 0xC8, 0xEC,
+
+-0x40, 0x3C, 0x40, 0xAD,
+-0x32, 0x6A,
+-0x2A, 0x30,
++ 0x40, 0x3C, 0x40, 0xAD,
++ 0x32, 0x6A,
++ 0x2A, 0x30,
+
+-0x20, 0x73,
+-0x33, 0x6A,
+-0x00, 0xE0,
+-0x28, 0x73,
++ 0x20, 0x73,
++ 0x33, 0x6A,
++ 0x00, 0xE0,
++ 0x28, 0x73,
+
+-0x1C, 0x72,
+-0x83, 0xE2,
+-0x7B, 0x80, 0x15, 0xEA,
++ 0x1C, 0x72,
++ 0x83, 0xE2,
++ 0x7B, 0x80, 0x15, 0xEA,
+
+-0xB8, 0x3D, 0x28, 0xDF,
+-0x30, 0x35, 0x20, 0xDF,
++ 0xB8, 0x3D, 0x28, 0xDF,
++ 0x30, 0x35, 0x20, 0xDF,
+
+-0x40, 0x30,
+-0x00, 0xE0,
+-0xCC, 0xE2,
+-0x64, 0x72,
++ 0x40, 0x30,
++ 0x00, 0xE0,
++ 0xCC, 0xE2,
++ 0x64, 0x72,
+
+-0x25, 0x42, 0x52, 0xBF,
+-0x2D, 0x42, 0x4A, 0xBF,
++ 0x25, 0x42, 0x52, 0xBF,
++ 0x2D, 0x42, 0x4A, 0xBF,
+
+-0x30, 0x2E, 0x30, 0xDF,
+-0x38, 0x2E, 0x38, 0xDF,
++ 0x30, 0x2E, 0x30, 0xDF,
++ 0x38, 0x2E, 0x38, 0xDF,
+
+-0x18, 0x1D, 0x45, 0xE9,
+-0x1E, 0x15, 0x45, 0xE9,
++ 0x18, 0x1D, 0x45, 0xE9,
++ 0x1E, 0x15, 0x45, 0xE9,
+
+-0x2B, 0x49, 0x51, 0xBD,
+-0x00, 0xE0,
+-0x1F, 0x73,
++ 0x2B, 0x49, 0x51, 0xBD,
++ 0x00, 0xE0,
++ 0x1F, 0x73,
+
+-0x38, 0x38, 0x40, 0xAF,
+-0x30, 0x30, 0x40, 0xAF,
++ 0x38, 0x38, 0x40, 0xAF,
++ 0x30, 0x30, 0x40, 0xAF,
+
+-0x24, 0x1F, 0x24, 0xDF,
+-0x1D, 0x32, 0x20, 0xE9,
++ 0x24, 0x1F, 0x24, 0xDF,
++ 0x1D, 0x32, 0x20, 0xE9,
+
+-0x2C, 0x1F, 0x2C, 0xDF,
+-0x1A, 0x33, 0x20, 0xE9,
++ 0x2C, 0x1F, 0x2C, 0xDF,
++ 0x1A, 0x33, 0x20, 0xE9,
+
+-0xB0, 0x10,
+-0x08, 0xE3,
+-0x40, 0x10,
+-0xB8, 0x10,
++ 0xB0, 0x10,
++ 0x08, 0xE3,
++ 0x40, 0x10,
++ 0xB8, 0x10,
+
+-0x26, 0xF0, 0x30, 0xCD,
+-0x2F, 0xF0, 0x38, 0xCD,
++ 0x26, 0xF0, 0x30, 0xCD,
++ 0x2F, 0xF0, 0x38, 0xCD,
+
+-0x2B, 0x80, 0x20, 0xE9,
+-0x2A, 0x80, 0x20, 0xE9,
++ 0x2B, 0x80, 0x20, 0xE9,
++ 0x2A, 0x80, 0x20, 0xE9,
+
+-0xA6, 0x20,
+-0x88, 0xE2,
+-0x00, 0xE0,
+-0xAF, 0x20,
++ 0xA6, 0x20,
++ 0x88, 0xE2,
++ 0x00, 0xE0,
++ 0xAF, 0x20,
+
+-0x28, 0x2A, 0x26, 0xAF,
+-0x20, 0x2A, 0xC0, 0xAF,
++ 0x28, 0x2A, 0x26, 0xAF,
++ 0x20, 0x2A, 0xC0, 0xAF,
+
+-0x34, 0x1F, 0x34, 0xDF,
+-0x46, 0x24, 0x46, 0xDF,
++ 0x34, 0x1F, 0x34, 0xDF,
++ 0x46, 0x24, 0x46, 0xDF,
+
+-0x28, 0x30, 0x80, 0xBF,
+-0x20, 0x38, 0x80, 0xBF,
++ 0x28, 0x30, 0x80, 0xBF,
++ 0x20, 0x38, 0x80, 0xBF,
+
+-0x47, 0x24, 0x47, 0xDF,
+-0x4E, 0x2C, 0x4E, 0xDF,
++ 0x47, 0x24, 0x47, 0xDF,
++ 0x4E, 0x2C, 0x4E, 0xDF,
+
+-0x4F, 0x2C, 0x4F, 0xDF,
+-0x56, 0x34, 0x56, 0xDF,
++ 0x4F, 0x2C, 0x4F, 0xDF,
++ 0x56, 0x34, 0x56, 0xDF,
+
+-0x28, 0x15, 0x28, 0xDF,
+-0x20, 0x1D, 0x20, 0xDF,
++ 0x28, 0x15, 0x28, 0xDF,
++ 0x20, 0x1D, 0x20, 0xDF,
+
+-0x57, 0x34, 0x57, 0xDF,
+-0x00, 0xE0,
+-0x1D, 0x05,
++ 0x57, 0x34, 0x57, 0xDF,
++ 0x00, 0xE0,
++ 0x1D, 0x05,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x89, 0xE2,
+-0x2B, 0x30,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x89, 0xE2,
++ 0x2B, 0x30,
+
+-0x3F, 0xC1, 0x1D, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0xC1, 0x1D, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x68,
+-0xBF, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x68,
++ 0xBF, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x20, 0xC0, 0x20, 0xAF,
+-0x28, 0x05,
+-0x97, 0x74,
++ 0x20, 0xC0, 0x20, 0xAF,
++ 0x28, 0x05,
++ 0x97, 0x74,
+
+-0x00, 0xE0,
+-0x2A, 0x10,
+-0x16, 0xC0, 0x20, 0xE9,
++ 0x00, 0xE0,
++ 0x2A, 0x10,
++ 0x16, 0xC0, 0x20, 0xE9,
+
+-0x04, 0x80, 0x10, 0xEA,
+-0x8C, 0xE2,
+-0x95, 0x05,
++ 0x04, 0x80, 0x10, 0xEA,
++ 0x8C, 0xE2,
++ 0x95, 0x05,
+
+-0x28, 0xC1, 0x28, 0xAD,
+-0x1F, 0xC1, 0x15, 0xBD,
++ 0x28, 0xC1, 0x28, 0xAD,
++ 0x1F, 0xC1, 0x15, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA8, 0x67,
+-0x9F, 0x6B,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA8, 0x67,
++ 0x9F, 0x6B,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x28, 0xC0, 0x28, 0xAD,
+-0x1D, 0x25,
+-0x20, 0x05,
++ 0x28, 0xC0, 0x28, 0xAD,
++ 0x1D, 0x25,
++ 0x20, 0x05,
+
+-0x28, 0x32, 0x80, 0xAD,
+-0x40, 0x2A, 0x40, 0xBD,
++ 0x28, 0x32, 0x80, 0xAD,
++ 0x40, 0x2A, 0x40, 0xBD,
+
+-0x1C, 0x80, 0x20, 0xE9,
+-0x20, 0x33, 0x20, 0xAD,
++ 0x1C, 0x80, 0x20, 0xE9,
++ 0x20, 0x33, 0x20, 0xAD,
+
+-0x20, 0x73,
+-0x00, 0xE0,
+-0xB6, 0x49, 0x51, 0xBB,
++ 0x20, 0x73,
++ 0x00, 0xE0,
++ 0xB6, 0x49, 0x51, 0xBB,
+
+-0x26, 0x2F, 0xB0, 0xE8,
+-0x19, 0x20, 0x20, 0xE9,
++ 0x26, 0x2F, 0xB0, 0xE8,
++ 0x19, 0x20, 0x20, 0xE9,
+
+-0x35, 0x20, 0x35, 0xDF,
+-0x3D, 0x20, 0x3D, 0xDF,
++ 0x35, 0x20, 0x35, 0xDF,
++ 0x3D, 0x20, 0x3D, 0xDF,
+
+-0x15, 0x20, 0x15, 0xDF,
+-0x1D, 0x20, 0x1D, 0xDF,
++ 0x15, 0x20, 0x15, 0xDF,
++ 0x1D, 0x20, 0x1D, 0xDF,
+
+-0x26, 0xD0, 0x26, 0xCD,
+-0x29, 0x49, 0x2A, 0xB8,
++ 0x26, 0xD0, 0x26, 0xCD,
++ 0x29, 0x49, 0x2A, 0xB8,
+
+-0x26, 0x40, 0x80, 0xBD,
+-0x3B, 0x48, 0x50, 0xBD,
++ 0x26, 0x40, 0x80, 0xBD,
++ 0x3B, 0x48, 0x50, 0xBD,
+
+-0x3E, 0x54, 0x57, 0x9F,
+-0x00, 0xE0,
+-0x82, 0xE1,
++ 0x3E, 0x54, 0x57, 0x9F,
++ 0x00, 0xE0,
++ 0x82, 0xE1,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x26, 0x30,
+-0x29, 0x30,
+-0x48, 0x3C, 0x48, 0xAD,
++ 0x26, 0x30,
++ 0x29, 0x30,
++ 0x48, 0x3C, 0x48, 0xAD,
+
+-0x2B, 0x72,
+-0xC2, 0xE1,
+-0x2C, 0xC0, 0x44, 0xC2,
++ 0x2B, 0x72,
++ 0xC2, 0xE1,
++ 0x2C, 0xC0, 0x44, 0xC2,
+
+-0x05, 0x24, 0x34, 0xBF,
+-0x0D, 0x24, 0x2C, 0xBF,
++ 0x05, 0x24, 0x34, 0xBF,
++ 0x0D, 0x24, 0x2C, 0xBF,
+
+-0x2D, 0x46, 0x4E, 0xBF,
+-0x25, 0x46, 0x56, 0xBF,
++ 0x2D, 0x46, 0x4E, 0xBF,
++ 0x25, 0x46, 0x56, 0xBF,
+
+-0x20, 0x1D, 0x6F, 0x8F,
+-0x32, 0x3E, 0x5F, 0xE9,
++ 0x20, 0x1D, 0x6F, 0x8F,
++ 0x32, 0x3E, 0x5F, 0xE9,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x30,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x30,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x33, 0x1E, 0x5F, 0xE9,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x33, 0x1E, 0x5F, 0xE9,
+
+-0x05, 0x44, 0x54, 0xB2,
+-0x0D, 0x44, 0x4C, 0xB2,
++ 0x05, 0x44, 0x54, 0xB2,
++ 0x0D, 0x44, 0x4C, 0xB2,
+
+-0x19, 0xC0, 0xB0, 0xE8,
+-0x34, 0xC0, 0x44, 0xC4,
++ 0x19, 0xC0, 0xB0, 0xE8,
++ 0x34, 0xC0, 0x44, 0xC4,
+
+-0x33, 0x73,
+-0x00, 0xE0,
+-0x3E, 0x62, 0x57, 0x9F,
++ 0x33, 0x73,
++ 0x00, 0xE0,
++ 0x3E, 0x62, 0x57, 0x9F,
+
+-0x1E, 0xAF, 0x59, 0x9F,
+-0x00, 0xE0,
+-0x0D, 0x20,
++ 0x1E, 0xAF, 0x59, 0x9F,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
+
+-0x84, 0x3E, 0x58, 0xE9,
+-0x28, 0x1D, 0x6F, 0x8F,
++ 0x84, 0x3E, 0x58, 0xE9,
++ 0x28, 0x1D, 0x6F, 0x8F,
+
+-0x05, 0x20,
+-0x00, 0xE0,
+-0x85, 0x1E, 0x58, 0xE9,
++ 0x05, 0x20,
++ 0x00, 0xE0,
++ 0x85, 0x1E, 0x58, 0xE9,
+
+-0x9B, 0x3B, 0x33, 0xDF,
+-0x20, 0x20, 0x42, 0xAF,
++ 0x9B, 0x3B, 0x33, 0xDF,
++ 0x20, 0x20, 0x42, 0xAF,
+
+-0x30, 0x42, 0x56, 0x9F,
+-0x80, 0x3E, 0x57, 0xE9,
++ 0x30, 0x42, 0x56, 0x9F,
++ 0x80, 0x3E, 0x57, 0xE9,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x30, 0x80, 0x5F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x30, 0x80, 0x5F, 0xE9,
+
+-0x28, 0x28, 0x24, 0xAF,
+-0x81, 0x1E, 0x57, 0xE9,
++ 0x28, 0x28, 0x24, 0xAF,
++ 0x81, 0x1E, 0x57, 0xE9,
+
+-0x05, 0x47, 0x57, 0xBF,
+-0x0D, 0x47, 0x4F, 0xBF,
++ 0x05, 0x47, 0x57, 0xBF,
++ 0x0D, 0x47, 0x4F, 0xBF,
+
+-0x88, 0x80, 0x58, 0xE9,
+-0x1B, 0x29, 0x1B, 0xDF,
++ 0x88, 0x80, 0x58, 0xE9,
++ 0x1B, 0x29, 0x1B, 0xDF,
+
+-0x30, 0x1D, 0x6F, 0x8F,
+-0x3A, 0x30, 0x4F, 0xE9,
++ 0x30, 0x1D, 0x6F, 0x8F,
++ 0x3A, 0x30, 0x4F, 0xE9,
+
+-0x1C, 0x30, 0x26, 0xDF,
+-0x09, 0xE3,
+-0x3B, 0x05,
++ 0x1C, 0x30, 0x26, 0xDF,
++ 0x09, 0xE3,
++ 0x3B, 0x05,
+
+-0x3E, 0x50, 0x56, 0x9F,
+-0x3B, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x50, 0x56, 0x9F,
++ 0x3B, 0x3F, 0x4F, 0xE9,
+
+-0x1E, 0x8F, 0x51, 0x9F,
+-0x00, 0xE0,
+-0xAC, 0x20,
++ 0x1E, 0x8F, 0x51, 0x9F,
++ 0x00, 0xE0,
++ 0xAC, 0x20,
+
+-0x2D, 0x44, 0x4C, 0xB4,
+-0x2C, 0x1C, 0xC0, 0xAF,
++ 0x2D, 0x44, 0x4C, 0xB4,
++ 0x2C, 0x1C, 0xC0, 0xAF,
+
+-0x25, 0x44, 0x54, 0xB4,
+-0x00, 0xE0,
+-0xC8, 0x30,
++ 0x25, 0x44, 0x54, 0xB4,
++ 0x00, 0xE0,
++ 0xC8, 0x30,
+
+-0x30, 0x46, 0x30, 0xAF,
+-0x1B, 0x1B, 0x48, 0xAF,
++ 0x30, 0x46, 0x30, 0xAF,
++ 0x1B, 0x1B, 0x48, 0xAF,
+
+-0x00, 0xE0,
+-0x25, 0x20,
+-0x38, 0x2C, 0x4F, 0xE9,
++ 0x00, 0xE0,
++ 0x25, 0x20,
++ 0x38, 0x2C, 0x4F, 0xE9,
+
+-0x86, 0x80, 0x57, 0xE9,
+-0x38, 0x1D, 0x6F, 0x8F,
++ 0x86, 0x80, 0x57, 0xE9,
++ 0x38, 0x1D, 0x6F, 0x8F,
+
+-0x28, 0x74,
+-0x00, 0xE0,
+-0x0D, 0x44, 0x4C, 0xB0,
++ 0x28, 0x74,
++ 0x00, 0xE0,
++ 0x0D, 0x44, 0x4C, 0xB0,
+
+-0x05, 0x44, 0x54, 0xB0,
+-0x2D, 0x20,
+-0x9B, 0x10,
++ 0x05, 0x44, 0x54, 0xB0,
++ 0x2D, 0x20,
++ 0x9B, 0x10,
+
+-0x82, 0x3E, 0x57, 0xE9,
+-0x32, 0xF0, 0x1B, 0xCD,
++ 0x82, 0x3E, 0x57, 0xE9,
++ 0x32, 0xF0, 0x1B, 0xCD,
+
+-0x1E, 0xBD, 0x59, 0x9F,
+-0x83, 0x1E, 0x57, 0xE9,
++ 0x1E, 0xBD, 0x59, 0x9F,
++ 0x83, 0x1E, 0x57, 0xE9,
+
+-0x38, 0x47, 0x38, 0xAF,
+-0x34, 0x20,
+-0x2A, 0x30,
++ 0x38, 0x47, 0x38, 0xAF,
++ 0x34, 0x20,
++ 0x2A, 0x30,
+
+-0x00, 0xE0,
+-0x0D, 0x20,
+-0x32, 0x20,
+-0x05, 0x20,
++ 0x00, 0xE0,
++ 0x0D, 0x20,
++ 0x32, 0x20,
++ 0x05, 0x20,
+
+-0x87, 0x80, 0x57, 0xE9,
+-0x1F, 0x54, 0x57, 0x9F,
++ 0x87, 0x80, 0x57, 0xE9,
++ 0x1F, 0x54, 0x57, 0x9F,
+
+-0x17, 0x42, 0x56, 0x9F,
+-0x00, 0xE0,
+-0x3B, 0x6A,
++ 0x17, 0x42, 0x56, 0x9F,
++ 0x00, 0xE0,
++ 0x3B, 0x6A,
+
+-0x3F, 0x8F, 0x51, 0x9F,
+-0x37, 0x1E, 0x4F, 0xE9,
++ 0x3F, 0x8F, 0x51, 0x9F,
++ 0x37, 0x1E, 0x4F, 0xE9,
+
+-0x37, 0x32, 0x2A, 0xAF,
+-0x00, 0xE0,
+-0x32, 0x00,
++ 0x37, 0x32, 0x2A, 0xAF,
++ 0x00, 0xE0,
++ 0x32, 0x00,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x27, 0xC0, 0x44, 0xC0,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x27, 0xC0, 0x44, 0xC0,
+
+-0x36, 0x1F, 0x4F, 0xE9,
+-0x1F, 0x1F, 0x26, 0xDF,
++ 0x36, 0x1F, 0x4F, 0xE9,
++ 0x1F, 0x1F, 0x26, 0xDF,
+
+-0x37, 0x1B, 0x37, 0xBF,
+-0x17, 0x26, 0x17, 0xDF,
++ 0x37, 0x1B, 0x37, 0xBF,
++ 0x17, 0x26, 0x17, 0xDF,
+
+-0x3E, 0x17, 0x4F, 0xE9,
+-0x3F, 0x3F, 0x4F, 0xE9,
++ 0x3E, 0x17, 0x4F, 0xE9,
++ 0x3F, 0x3F, 0x4F, 0xE9,
+
+-0x34, 0x1F, 0x34, 0xAF,
+-0x2B, 0x05,
+-0xA7, 0x20,
++ 0x34, 0x1F, 0x34, 0xAF,
++ 0x2B, 0x05,
++ 0xA7, 0x20,
+
+-0x33, 0x2B, 0x37, 0xDF,
+-0x27, 0x17, 0xC0, 0xAF,
++ 0x33, 0x2B, 0x37, 0xDF,
++ 0x27, 0x17, 0xC0, 0xAF,
+
+-0x34, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x34, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2D, 0x21, 0x1A, 0xB0,
+-0x25, 0x21, 0x31, 0xB0,
++ 0x2D, 0x21, 0x1A, 0xB0,
++ 0x25, 0x21, 0x31, 0xB0,
+
+-0x0D, 0x21, 0x1A, 0xB2,
+-0x05, 0x21, 0x31, 0xB2,
++ 0x0D, 0x21, 0x1A, 0xB2,
++ 0x05, 0x21, 0x31, 0xB2,
+
+-0x03, 0x80, 0x2A, 0xEA,
+-0x17, 0xC1, 0x2B, 0xBD,
++ 0x03, 0x80, 0x2A, 0xEA,
++ 0x17, 0xC1, 0x2B, 0xBD,
+
+-0x2D, 0x20,
+-0x25, 0x20,
+-0x05, 0x20,
+-0x0D, 0x20,
++ 0x2D, 0x20,
++ 0x25, 0x20,
++ 0x05, 0x20,
++ 0x0D, 0x20,
+
+-0xB3, 0x68,
+-0x97, 0x25,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0x68,
++ 0x97, 0x25,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0xC0, 0x33, 0xAF,
+-0x2F, 0xC0, 0x21, 0xC0,
++ 0x33, 0xC0, 0x33, 0xAF,
++ 0x2F, 0xC0, 0x21, 0xC0,
+
+-0x16, 0x42, 0x56, 0x9F,
+-0x3C, 0x27, 0x4F, 0xE9,
++ 0x16, 0x42, 0x56, 0x9F,
++ 0x3C, 0x27, 0x4F, 0xE9,
+
+-0x1E, 0x62, 0x57, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1E, 0x62, 0x57, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x21, 0x31, 0xB4,
+-0x2D, 0x21, 0x1A, 0xB4,
++ 0x25, 0x21, 0x31, 0xB4,
++ 0x2D, 0x21, 0x1A, 0xB4,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x33, 0x05,
+-0x00, 0xE0,
+-0x28, 0x19, 0x60, 0xEC,
++ 0x33, 0x05,
++ 0x00, 0xE0,
++ 0x28, 0x19, 0x60, 0xEC,
+
+-0x0D, 0x21, 0x1A, 0xB6,
+-0x05, 0x21, 0x31, 0xB6,
++ 0x0D, 0x21, 0x1A, 0xB6,
++ 0x05, 0x21, 0x31, 0xB6,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0xE0,
+-0x2F, 0x20,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0xE0,
++ 0x2F, 0x20,
+
+-0x23, 0x3B, 0x33, 0xAD,
+-0x1E, 0x26, 0x1E, 0xDF,
++ 0x23, 0x3B, 0x33, 0xAD,
++ 0x1E, 0x26, 0x1E, 0xDF,
+
+-0xA7, 0x1E, 0x4F, 0xE9,
+-0x17, 0x26, 0x16, 0xDF,
++ 0xA7, 0x1E, 0x4F, 0xE9,
++ 0x17, 0x26, 0x16, 0xDF,
+
+-0x2D, 0x20,
+-0x00, 0xE0,
+-0xA8, 0x3F, 0x4F, 0xE9,
++ 0x2D, 0x20,
++ 0x00, 0xE0,
++ 0xA8, 0x3F, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x1E, 0xAF,
+-0x25, 0x20,
+-0x00, 0xE0,
++ 0x2F, 0x2F, 0x1E, 0xAF,
++ 0x25, 0x20,
++ 0x00, 0xE0,
+
+-0xA4, 0x16, 0x4F, 0xE9,
+-0x0F, 0xC0, 0x21, 0xC2,
++ 0xA4, 0x16, 0x4F, 0xE9,
++ 0x0F, 0xC0, 0x21, 0xC2,
+
+-0xA6, 0x80, 0x4F, 0xE9,
+-0x1F, 0x62, 0x57, 0x9F,
++ 0xA6, 0x80, 0x4F, 0xE9,
++ 0x1F, 0x62, 0x57, 0x9F,
+
+-0x0D, 0x20,
+-0x05, 0x20,
+-0x2F, 0xC0, 0x21, 0xC6,
++ 0x0D, 0x20,
++ 0x05, 0x20,
++ 0x2F, 0xC0, 0x21, 0xC6,
+
+-0x3F, 0x2F, 0x5D, 0x9F,
+-0x00, 0xE0,
+-0x0F, 0x20,
++ 0x3F, 0x2F, 0x5D, 0x9F,
++ 0x00, 0xE0,
++ 0x0F, 0x20,
+
+-0x17, 0x50, 0x56, 0x9F,
+-0xA5, 0x37, 0x4F, 0xE9,
++ 0x17, 0x50, 0x56, 0x9F,
++ 0xA5, 0x37, 0x4F, 0xE9,
+
+-0x06, 0xC0, 0x21, 0xC4,
+-0x0F, 0x17, 0x0F, 0xAF,
++ 0x06, 0xC0, 0x21, 0xC4,
++ 0x0F, 0x17, 0x0F, 0xAF,
+
+-0x37, 0x0F, 0x5C, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x37, 0x0F, 0x5C, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2F, 0x20,
+-0x00, 0xE0,
+-0xA3, 0x80, 0x4F, 0xE9,
++ 0x2F, 0x20,
++ 0x00, 0xE0,
++ 0xA3, 0x80, 0x4F, 0xE9,
+
+-0x06, 0x20,
+-0x00, 0xE0,
+-0x1F, 0x26, 0x1F, 0xDF,
++ 0x06, 0x20,
++ 0x00, 0xE0,
++ 0x1F, 0x26, 0x1F, 0xDF,
+
+-0x17, 0x26, 0x17, 0xDF,
+-0x35, 0x17, 0x4F, 0xE9,
++ 0x17, 0x26, 0x17, 0xDF,
++ 0x35, 0x17, 0x4F, 0xE9,
+
+-0xA1, 0x1F, 0x4F, 0xE9,
+-0xA2, 0x3F, 0x4F, 0xE9,
++ 0xA1, 0x1F, 0x4F, 0xE9,
++ 0xA2, 0x3F, 0x4F, 0xE9,
+
+-0x06, 0x06, 0x1F, 0xAF,
+-0x39, 0x37, 0x4F, 0xE9,
++ 0x06, 0x06, 0x1F, 0xAF,
++ 0x39, 0x37, 0x4F, 0xE9,
+
+-0x2F, 0x2F, 0x17, 0xAF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x2F, 0x2F, 0x17, 0xAF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xA0, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA0, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x31, 0x80, 0x4F, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x80, 0x4F, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x57, 0x39, 0x20, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x57, 0x39, 0x20, 0xE9,
+
+-0x16, 0x28, 0x20, 0xE9,
+-0x1D, 0x3B, 0x20, 0xE9,
++ 0x16, 0x28, 0x20, 0xE9,
++ 0x1D, 0x3B, 0x20, 0xE9,
+
+-0x1E, 0x2B, 0x20, 0xE9,
+-0x2B, 0x32, 0x20, 0xE9,
++ 0x1E, 0x2B, 0x20, 0xE9,
++ 0x2B, 0x32, 0x20, 0xE9,
+
+-0x1C, 0x23, 0x20, 0xE9,
+-0x57, 0x36, 0x20, 0xE9,
++ 0x1C, 0x23, 0x20, 0xE9,
++ 0x57, 0x36, 0x20, 0xE9,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x40, 0x40, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x40, 0x40, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x90, 0xE2,
+-0x00, 0xE0,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x90, 0xE2,
++ 0x00, 0xE0,
+
+-0x68, 0xFF, 0x20, 0xEA,
+-0x19, 0xC8, 0xC1, 0xCD,
++ 0x68, 0xFF, 0x20, 0xEA,
++ 0x19, 0xC8, 0xC1, 0xCD,
+
+-0x1F, 0xD7, 0x18, 0xBD,
+-0x3F, 0xD7, 0x22, 0xBD,
++ 0x1F, 0xD7, 0x18, 0xBD,
++ 0x3F, 0xD7, 0x22, 0xBD,
+
+-0x9F, 0x41, 0x49, 0xBD,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9F, 0x41, 0x49, 0xBD,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x25, 0x41, 0x49, 0xBD,
+-0x2D, 0x41, 0x51, 0xBD,
++ 0x25, 0x41, 0x49, 0xBD,
++ 0x2D, 0x41, 0x51, 0xBD,
+
+-0x0D, 0x80, 0x07, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x0D, 0x80, 0x07, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x35, 0x40, 0x48, 0xBD,
+-0x3D, 0x40, 0x50, 0xBD,
++ 0x35, 0x40, 0x48, 0xBD,
++ 0x3D, 0x40, 0x50, 0xBD,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x25, 0x30,
+-0x2D, 0x30,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x25, 0x30,
++ 0x2D, 0x30,
+
+-0x35, 0x30,
+-0xB5, 0x30,
+-0xBD, 0x30,
+-0x3D, 0x30,
++ 0x35, 0x30,
++ 0xB5, 0x30,
++ 0xBD, 0x30,
++ 0x3D, 0x30,
+
+-0x9C, 0xA7, 0x5B, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x9C, 0xA7, 0x5B, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x67, 0xFF, 0x0A, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x67, 0xFF, 0x0A, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC9, 0x41, 0xC8, 0xEC,
+-0x42, 0xE1,
+-0x00, 0xE0,
++ 0xC9, 0x41, 0xC8, 0xEC,
++ 0x42, 0xE1,
++ 0x00, 0xE0,
+
+-0x65, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x65, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xC8, 0x40, 0xC0, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC8, 0x40, 0xC0, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x62, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x62, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+ };
+
+ static unsigned char warp_g400_t2gz[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x78, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x78, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x69, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x69, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x34, 0x80, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x34, 0x80, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x25, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x25, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x3D, 0xCF, 0x74, 0xC2,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x3D, 0xCF, 0x74, 0xC2,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2A, 0x44, 0x54, 0xB4,
+-0x1A, 0x44, 0x64, 0xB4,
++ 0x2A, 0x44, 0x54, 0xB4,
++ 0x1A, 0x44, 0x64, 0xB4,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x9F, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x9F, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xBE, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xBE, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x7D, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x7D, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_t2gza[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x7C, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x7C, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x6D, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x6D, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x34, 0x80, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x34, 0x80, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x29, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x29, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x0F, 0xCF, 0x74, 0xC6,
+-0x3D, 0xCF, 0x74, 0xC2,
++ 0x0F, 0xCF, 0x74, 0xC6,
++ 0x3D, 0xCF, 0x74, 0xC2,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x0F, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x54, 0xB4,
+-0x02, 0x44, 0x64, 0xB4,
++ 0x0A, 0x44, 0x54, 0xB4,
++ 0x02, 0x44, 0x64, 0xB4,
+
+-0x2A, 0x44, 0x54, 0xB6,
+-0x1A, 0x44, 0x64, 0xB6,
++ 0x2A, 0x44, 0x54, 0xB6,
++ 0x1A, 0x44, 0x64, 0xB6,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x20,
+-0x02, 0x20,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x36, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x36, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x37, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x37, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x9B, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x9B, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xBA, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xBA, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x79, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x79, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_t2gzaf[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x81, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x81, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x72, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x72, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x2E, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x2E, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x3D, 0xCF, 0x74, 0xC2,
+-0x0F, 0xCF, 0x74, 0xC6,
++ 0x3D, 0xCF, 0x74, 0xC2,
++ 0x0F, 0xCF, 0x74, 0xC6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x0F, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x54, 0xB4,
+-0x02, 0x44, 0x64, 0xB4,
++ 0x0A, 0x44, 0x54, 0xB4,
++ 0x02, 0x44, 0x64, 0xB4,
+
+-0x2A, 0x44, 0x54, 0xB6,
+-0x1A, 0x44, 0x64, 0xB6,
++ 0x2A, 0x44, 0x54, 0xB6,
++ 0x1A, 0x44, 0x64, 0xB6,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x20,
+-0x02, 0x20,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x3D, 0xCF, 0x75, 0xC6,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3D, 0xCF, 0x75, 0xC6,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x45, 0x55, 0xB6,
+-0x02, 0x45, 0x65, 0xB6,
++ 0x0A, 0x45, 0x55, 0xB6,
++ 0x02, 0x45, 0x65, 0xB6,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x3D, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x31, 0x3D, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x38, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x96, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x96, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xB5, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB5, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x74, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x74, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_t2gzf[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x7D, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x7D, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x6E, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x6E, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x34, 0x80, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x34, 0x80, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0F, 0xCF, 0x75, 0xC6,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x0F, 0xCF, 0x75, 0xC6,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x28, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x28, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x3D, 0xCF, 0x74, 0xC2,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x3D, 0xCF, 0x74, 0xC2,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x31, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x31, 0x0F, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x54, 0xB4,
+-0x02, 0x44, 0x64, 0xB4,
++ 0x0A, 0x44, 0x54, 0xB4,
++ 0x02, 0x44, 0x64, 0xB4,
+
+-0x2A, 0x45, 0x55, 0xB6,
+-0x1A, 0x45, 0x65, 0xB6,
++ 0x2A, 0x45, 0x55, 0xB6,
++ 0x1A, 0x45, 0x65, 0xB6,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x20,
+-0x02, 0x20,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x36, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x36, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x37, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x37, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x9A, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x9A, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xBB, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xBB, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x78, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x78, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_t2gzs[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x85, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x85, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x76, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x76, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x0F, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x0F, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x31, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x31, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x0F, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0F, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB4,
+-0x1A, 0x44, 0x64, 0xB4,
++ 0x2A, 0x44, 0x54, 0xB4,
++ 0x1A, 0x44, 0x64, 0xB4,
+
+-0x0A, 0x45, 0x55, 0xB0,
+-0x02, 0x45, 0x65, 0xB0,
++ 0x0A, 0x45, 0x55, 0xB0,
++ 0x02, 0x45, 0x65, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x55, 0xB2,
+-0x1A, 0x45, 0x65, 0xB2,
++ 0x2A, 0x45, 0x55, 0xB2,
++ 0x1A, 0x45, 0x65, 0xB2,
+
+-0x0A, 0x45, 0x55, 0xB4,
+-0x02, 0x45, 0x65, 0xB4,
++ 0x0A, 0x45, 0x55, 0xB4,
++ 0x02, 0x45, 0x65, 0xB4,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x20,
+-0x1A, 0x20,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0xA7, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0xA7, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x92, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x92, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xB2, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB2, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x70, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x70, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_t2gzsa[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x8A, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x8A, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x7B, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x7B, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x0F, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x0F, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x36, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x36, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x0F, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0F, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB4,
+-0x1A, 0x44, 0x64, 0xB4,
++ 0x2A, 0x44, 0x54, 0xB4,
++ 0x1A, 0x44, 0x64, 0xB4,
+
+-0x0A, 0x45, 0x55, 0xB0,
+-0x02, 0x45, 0x65, 0xB0,
++ 0x0A, 0x45, 0x55, 0xB0,
++ 0x02, 0x45, 0x65, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x55, 0xB2,
+-0x1A, 0x45, 0x65, 0xB2,
++ 0x2A, 0x45, 0x55, 0xB2,
++ 0x1A, 0x45, 0x65, 0xB2,
+
+-0x0A, 0x45, 0x55, 0xB4,
+-0x02, 0x45, 0x65, 0xB4,
++ 0x0A, 0x45, 0x55, 0xB4,
++ 0x02, 0x45, 0x65, 0xB4,
+
+-0x0F, 0xCF, 0x74, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0F, 0xCF, 0x74, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA7, 0x30, 0x4F, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA7, 0x30, 0x4F, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB6,
+-0x1A, 0x44, 0x64, 0xB6,
++ 0x2A, 0x44, 0x54, 0xB6,
++ 0x1A, 0x44, 0x64, 0xB6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x8D, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x8D, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xAD, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xAD, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x6B, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x6B, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_t2gzsaf[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x8E, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x8E, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x7F, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x7F, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x0F, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x0F, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x3A, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x3A, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x0F, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0F, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB4,
+-0x1A, 0x44, 0x64, 0xB4,
++ 0x2A, 0x44, 0x54, 0xB4,
++ 0x1A, 0x44, 0x64, 0xB4,
+
+-0x0A, 0x45, 0x55, 0xB0,
+-0x02, 0x45, 0x65, 0xB0,
++ 0x0A, 0x45, 0x55, 0xB0,
++ 0x02, 0x45, 0x65, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x55, 0xB2,
+-0x1A, 0x45, 0x65, 0xB2,
++ 0x2A, 0x45, 0x55, 0xB2,
++ 0x1A, 0x45, 0x65, 0xB2,
+
+-0x0A, 0x45, 0x55, 0xB4,
+-0x02, 0x45, 0x65, 0xB4,
++ 0x0A, 0x45, 0x55, 0xB4,
++ 0x02, 0x45, 0x65, 0xB4,
+
+-0x0F, 0xCF, 0x74, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0F, 0xCF, 0x74, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA7, 0x30, 0x4F, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA7, 0x30, 0x4F, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB6,
+-0x1A, 0x44, 0x64, 0xB6,
++ 0x2A, 0x44, 0x54, 0xB6,
++ 0x1A, 0x44, 0x64, 0xB6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x45, 0x55, 0xB6,
+-0x02, 0x45, 0x65, 0xB6,
++ 0x0A, 0x45, 0x55, 0xB6,
++ 0x02, 0x45, 0x65, 0xB6,
+
+-0x3D, 0xCF, 0x75, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x3D, 0xCF, 0x75, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x3D, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x31, 0x3D, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x89, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x89, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xA9, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xA9, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x67, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x67, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_t2gzsf[] = {
+
+-0x00, 0x8A, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x8A, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x0A, 0x40, 0x50, 0xBF,
+-0x2A, 0x40, 0x60, 0xBF,
++ 0x0A, 0x40, 0x50, 0xBF,
++ 0x2A, 0x40, 0x60, 0xBF,
+
+-0x32, 0x41, 0x51, 0xBF,
+-0x3A, 0x41, 0x61, 0xBF,
++ 0x32, 0x41, 0x51, 0xBF,
++ 0x3A, 0x41, 0x61, 0xBF,
+
+-0xC3, 0x6B,
+-0xD3, 0x6B,
+-0x00, 0x8A, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xD3, 0x6B,
++ 0x00, 0x8A, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x23, 0x9F,
+-0x00, 0xE0,
+-0x51, 0x04,
++ 0xAD, 0xEE, 0x23, 0x9F,
++ 0x00, 0xE0,
++ 0x51, 0x04,
+
+-0x90, 0xE2,
+-0x61, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x61, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x51, 0x41, 0xE0, 0xEC,
+-0x39, 0x67, 0xB1, 0xE8,
++ 0x51, 0x41, 0xE0, 0xEC,
++ 0x39, 0x67, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x63, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x63, 0xA0, 0xE8,
+
+-0x61, 0x41, 0xE0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x61, 0x41, 0xE0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x8A, 0x80, 0x15, 0xEA,
+-0x10, 0x04,
+-0x20, 0x04,
++ 0x8A, 0x80, 0x15, 0xEA,
++ 0x10, 0x04,
++ 0x20, 0x04,
+
+-0x61, 0x51, 0xE0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x61, 0x51, 0xE0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x52, 0xBF,
+-0x0F, 0x52, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x52, 0xBF,
++ 0x0F, 0x52, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x62, 0xBF,
+-0x1E, 0x51, 0x60, 0xEA,
++ 0x1A, 0x42, 0x62, 0xBF,
++ 0x1E, 0x51, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x0E, 0x61, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x0E, 0x61, 0x60, 0xEA,
+
+-0x32, 0x40, 0x50, 0xBD,
+-0x22, 0x40, 0x60, 0xBD,
++ 0x32, 0x40, 0x50, 0xBD,
++ 0x22, 0x40, 0x60, 0xBD,
+
+-0x12, 0x41, 0x51, 0xBD,
+-0x3A, 0x41, 0x61, 0xBD,
++ 0x12, 0x41, 0x51, 0xBD,
++ 0x3A, 0x41, 0x61, 0xBD,
+
+-0xBF, 0x2F, 0x0E, 0xBD,
+-0x97, 0xE2,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x0E, 0xBD,
++ 0x97, 0xE2,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x35, 0x48, 0xB1, 0xE8,
+-0x3D, 0x59, 0xB1, 0xE8,
++ 0x35, 0x48, 0xB1, 0xE8,
++ 0x3D, 0x59, 0xB1, 0xE8,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x56, 0x31, 0x56, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x66, 0x31, 0x66, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x66, 0x31, 0x66, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x57, 0x39, 0x57, 0xBF,
+-0x67, 0x39, 0x67, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
++ 0x67, 0x39, 0x67, 0xBF,
+
+-0x7B, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x7B, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x35, 0x00,
+-0x3D, 0x00,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x35, 0x00,
++ 0x3D, 0x00,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0x8D, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0x8D, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x75, 0xF8, 0xEC,
+-0x35, 0x20,
+-0x3D, 0x20,
++ 0x43, 0x75, 0xF8, 0xEC,
++ 0x35, 0x20,
++ 0x3D, 0x20,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x53, 0x53, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x53, 0x53, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x0E, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x0E, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x48, 0x35, 0x48, 0xBF,
+-0x58, 0x35, 0x58, 0xBF,
++ 0x48, 0x35, 0x48, 0xBF,
++ 0x58, 0x35, 0x58, 0xBF,
+
+-0x68, 0x35, 0x68, 0xBF,
+-0x49, 0x3D, 0x49, 0xBF,
++ 0x68, 0x35, 0x68, 0xBF,
++ 0x49, 0x3D, 0x49, 0xBF,
+
+-0x59, 0x3D, 0x59, 0xBF,
+-0x69, 0x3D, 0x69, 0xBF,
++ 0x59, 0x3D, 0x59, 0xBF,
++ 0x69, 0x3D, 0x69, 0xBF,
+
+-0x63, 0x63, 0x2D, 0xDF,
+-0x4D, 0x7D, 0xF8, 0xEC,
++ 0x63, 0x63, 0x2D, 0xDF,
++ 0x4D, 0x7D, 0xF8, 0xEC,
+
+-0x59, 0xE3,
+-0x00, 0xE0,
+-0xB8, 0x38, 0x33, 0xBF,
++ 0x59, 0xE3,
++ 0x00, 0xE0,
++ 0xB8, 0x38, 0x33, 0xBF,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x18, 0x3A, 0x41, 0xE9,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x18, 0x3A, 0x41, 0xE9,
+
+-0x3F, 0x53, 0xA0, 0xE8,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x3F, 0x53, 0xA0, 0xE8,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x63, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x63, 0xA0, 0xE8,
+
+-0x50, 0x70, 0xF8, 0xEC,
+-0x2B, 0x50, 0x3C, 0xE9,
++ 0x50, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x50, 0x3C, 0xE9,
+
+-0x1F, 0x0F, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x0F, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x59, 0x78, 0xF8, 0xEC,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x59, 0x78, 0xF8, 0xEC,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x56, 0x3F, 0x56, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x56, 0x3F, 0x56, 0xDF,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x66, 0x3D, 0x66, 0xDF,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x66, 0x3D, 0x66, 0xDF,
+
+-0x1D, 0x32, 0x41, 0xE9,
+-0x67, 0x3D, 0x67, 0xDF,
++ 0x1D, 0x32, 0x41, 0xE9,
++ 0x67, 0x3D, 0x67, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3F, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3F, 0x57, 0xDF,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x59, 0x3F, 0x59, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x59, 0x3F, 0x59, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x69, 0x3D, 0x69, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x69, 0x3D, 0x69, 0xDF,
+
+-0x48, 0x37, 0x48, 0xDF,
+-0x58, 0x3F, 0x58, 0xDF,
++ 0x48, 0x37, 0x48, 0xDF,
++ 0x58, 0x3F, 0x58, 0xDF,
+
+-0x68, 0x3D, 0x68, 0xDF,
+-0x49, 0x37, 0x49, 0xDF,
++ 0x68, 0x3D, 0x68, 0xDF,
++ 0x49, 0x37, 0x49, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x0F, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x0F, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x54, 0xB0,
+-0x02, 0x44, 0x64, 0xB0,
++ 0x0A, 0x44, 0x54, 0xB0,
++ 0x02, 0x44, 0x64, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB2,
+-0x1A, 0x44, 0x64, 0xB2,
++ 0x2A, 0x44, 0x54, 0xB2,
++ 0x1A, 0x44, 0x64, 0xB2,
+
+-0x36, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x36, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x0F, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0F, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x54, 0xB4,
+-0x1A, 0x44, 0x64, 0xB4,
++ 0x2A, 0x44, 0x54, 0xB4,
++ 0x1A, 0x44, 0x64, 0xB4,
+
+-0x0A, 0x45, 0x55, 0xB0,
+-0x02, 0x45, 0x65, 0xB0,
++ 0x0A, 0x45, 0x55, 0xB0,
++ 0x02, 0x45, 0x65, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x55, 0xB2,
+-0x1A, 0x45, 0x65, 0xB2,
++ 0x2A, 0x45, 0x55, 0xB2,
++ 0x1A, 0x45, 0x65, 0xB2,
+
+-0x0A, 0x45, 0x55, 0xB4,
+-0x02, 0x45, 0x65, 0xB4,
++ 0x0A, 0x45, 0x55, 0xB4,
++ 0x02, 0x45, 0x65, 0xB4,
+
+-0x0F, 0xCF, 0x75, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0F, 0xCF, 0x75, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA7, 0x30, 0x4F, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA7, 0x30, 0x4F, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x31, 0x0F, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x31, 0x0F, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x55, 0xB6,
+-0x1A, 0x45, 0x65, 0xB6,
++ 0x2A, 0x45, 0x55, 0xB6,
++ 0x1A, 0x45, 0x65, 0xB6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x56, 0xBF,
+-0x1A, 0x46, 0x66, 0xBF,
++ 0x2A, 0x46, 0x56, 0xBF,
++ 0x1A, 0x46, 0x66, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x57, 0xBF,
+-0x02, 0x47, 0x67, 0xBF,
++ 0x0A, 0x47, 0x57, 0xBF,
++ 0x02, 0x47, 0x67, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x53, 0xBF,
+-0x1A, 0x43, 0x63, 0xBF,
++ 0x2A, 0x43, 0x53, 0xBF,
++ 0x1A, 0x43, 0x63, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x48, 0x58, 0xBF,
+-0x02, 0x48, 0x68, 0xBF,
++ 0x0A, 0x48, 0x58, 0xBF,
++ 0x02, 0x48, 0x68, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x2A, 0x49, 0x59, 0xBF,
+-0x1A, 0x49, 0x69, 0xBF,
++ 0x2A, 0x49, 0x59, 0xBF,
++ 0x1A, 0x49, 0x69, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x82, 0x30, 0x57, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x82, 0x30, 0x57, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x83, 0x38, 0x57, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x83, 0x38, 0x57, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x84, 0x31, 0x5E, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x84, 0x31, 0x5E, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x85, 0x39, 0x5E, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x85, 0x39, 0x5E, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x87, 0x77, 0x57, 0xE9,
+-0x8B, 0x3E, 0xBF, 0xEA,
++ 0x87, 0x77, 0x57, 0xE9,
++ 0x8B, 0x3E, 0xBF, 0xEA,
+
+-0x80, 0x30, 0x57, 0xE9,
+-0x81, 0x38, 0x57, 0xE9,
++ 0x80, 0x30, 0x57, 0xE9,
++ 0x81, 0x38, 0x57, 0xE9,
+
+-0x82, 0x31, 0x57, 0xE9,
+-0x86, 0x78, 0x57, 0xE9,
++ 0x82, 0x31, 0x57, 0xE9,
++ 0x86, 0x78, 0x57, 0xE9,
+
+-0x83, 0x39, 0x57, 0xE9,
+-0x87, 0x79, 0x57, 0xE9,
++ 0x83, 0x39, 0x57, 0xE9,
++ 0x87, 0x79, 0x57, 0xE9,
+
+-0x30, 0x1F, 0x5F, 0xE9,
+-0x8A, 0x34, 0x20, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
++ 0x8A, 0x34, 0x20, 0xE9,
+
+-0x8B, 0x3C, 0x20, 0xE9,
+-0x37, 0x50, 0x60, 0xBD,
++ 0x8B, 0x3C, 0x20, 0xE9,
++ 0x37, 0x50, 0x60, 0xBD,
+
+-0x57, 0x0D, 0x20, 0xE9,
+-0x35, 0x51, 0x61, 0xBD,
++ 0x57, 0x0D, 0x20, 0xE9,
++ 0x35, 0x51, 0x61, 0xBD,
+
+-0x2B, 0x50, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x50, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x0E, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x0E, 0x77,
+
+-0x24, 0x51, 0x20, 0xE9,
+-0x8D, 0xFF, 0x20, 0xEA,
++ 0x24, 0x51, 0x20, 0xE9,
++ 0x8D, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x0E, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x0E, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x0B, 0x46, 0xA0, 0xE8,
+-0x1B, 0x56, 0xA0, 0xE8,
++ 0x0B, 0x46, 0xA0, 0xE8,
++ 0x1B, 0x56, 0xA0, 0xE8,
+
+-0x2B, 0x66, 0xA0, 0xE8,
+-0x0C, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x66, 0xA0, 0xE8,
++ 0x0C, 0x47, 0xA0, 0xE8,
+
+-0x1C, 0x57, 0xA0, 0xE8,
+-0x2C, 0x67, 0xA0, 0xE8,
++ 0x1C, 0x57, 0xA0, 0xE8,
++ 0x2C, 0x67, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x57, 0x80, 0x57, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x57, 0x80, 0x57, 0xCF,
+
+-0x66, 0x33, 0x66, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x66, 0x33, 0x66, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x67, 0x3B, 0x67, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x67, 0x3B, 0x67, 0xCF,
+
+-0x0B, 0x48, 0xA0, 0xE8,
+-0x1B, 0x58, 0xA0, 0xE8,
++ 0x0B, 0x48, 0xA0, 0xE8,
++ 0x1B, 0x58, 0xA0, 0xE8,
+
+-0x2B, 0x68, 0xA0, 0xE8,
+-0x0C, 0x49, 0xA0, 0xE8,
++ 0x2B, 0x68, 0xA0, 0xE8,
++ 0x0C, 0x49, 0xA0, 0xE8,
+
+-0x1C, 0x59, 0xA0, 0xE8,
+-0x2C, 0x69, 0xA0, 0xE8,
++ 0x1C, 0x59, 0xA0, 0xE8,
++ 0x2C, 0x69, 0xA0, 0xE8,
+
+-0x0B, 0x00,
+-0x1B, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x0B, 0x00,
++ 0x1B, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x0C, 0x00,
+-0x1C, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x0C, 0x00,
++ 0x1C, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x0B, 0x65,
+-0x1B, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x0B, 0x65,
++ 0x1B, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x0C, 0x65,
+-0x1C, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x0C, 0x65,
++ 0x1C, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x0B, 0x1B, 0x60, 0xEC,
+-0x34, 0xD7, 0x34, 0xAD,
++ 0x0B, 0x1B, 0x60, 0xEC,
++ 0x34, 0xD7, 0x34, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x0C, 0x1C, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x0C, 0x1C, 0x60, 0xEC,
+
+-0x3C, 0xD7, 0x3C, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3C, 0xD7, 0x3C, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x0B, 0x2B, 0xDE, 0xE8,
+-0x1B, 0x80, 0xDE, 0xE8,
++ 0x0B, 0x2B, 0xDE, 0xE8,
++ 0x1B, 0x80, 0xDE, 0xE8,
+
+-0x34, 0x80, 0x34, 0xBD,
+-0x3C, 0x80, 0x3C, 0xBD,
++ 0x34, 0x80, 0x34, 0xBD,
++ 0x3C, 0x80, 0x3C, 0xBD,
+
+-0x33, 0xD7, 0x0B, 0xBD,
+-0x3B, 0xD7, 0x1B, 0xBD,
++ 0x33, 0xD7, 0x0B, 0xBD,
++ 0x3B, 0xD7, 0x1B, 0xBD,
+
+-0x48, 0x80, 0x48, 0xCF,
+-0x59, 0x80, 0x59, 0xCF,
++ 0x48, 0x80, 0x48, 0xCF,
++ 0x59, 0x80, 0x59, 0xCF,
+
+-0x68, 0x33, 0x68, 0xCF,
+-0x49, 0x3B, 0x49, 0xCF,
++ 0x68, 0x33, 0x68, 0xCF,
++ 0x49, 0x3B, 0x49, 0xCF,
+
+-0xAD, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xAD, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x58, 0x33, 0x58, 0xCF,
+-0x69, 0x3B, 0x69, 0xCF,
++ 0x58, 0x33, 0x58, 0xCF,
++ 0x69, 0x3B, 0x69, 0xCF,
+
+-0x6B, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x6B, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgz[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x58, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x58, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x4A, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x4A, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x34, 0x80, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x34, 0x80, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x1D, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x1D, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x3D, 0xCF, 0x74, 0xC2,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x3D, 0xCF, 0x74, 0xC2,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x2A, 0x44, 0x4C, 0xB4,
+-0x1A, 0x44, 0x54, 0xB4,
++ 0x2A, 0x44, 0x4C, 0xB4,
++ 0x1A, 0x44, 0x54, 0xB4,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0xAF, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0xAF, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xD6, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xD6, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x9D, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x9D, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgza[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x5C, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x5C, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x4E, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x4E, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x34, 0x80, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x34, 0x80, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x27, 0xCF, 0x74, 0xC6,
+-0x3D, 0xCF, 0x74, 0xC2,
++ 0x27, 0xCF, 0x74, 0xC6,
++ 0x3D, 0xCF, 0x74, 0xC2,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x20, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x20, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x27, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x4C, 0xB4,
+-0x02, 0x44, 0x54, 0xB4,
++ 0x0A, 0x44, 0x4C, 0xB4,
++ 0x02, 0x44, 0x54, 0xB4,
+
+-0x2A, 0x44, 0x4C, 0xB6,
+-0x1A, 0x44, 0x54, 0xB6,
++ 0x2A, 0x44, 0x4C, 0xB6,
++ 0x1A, 0x44, 0x54, 0xB6,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x20,
+-0x02, 0x20,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x36, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x36, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x37, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x37, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0xAB, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0xAB, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xD3, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xD3, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x99, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x99, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgzaf[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x61, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x61, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x53, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x53, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x26, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x26, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x3D, 0xCF, 0x74, 0xC2,
+-0x27, 0xCF, 0x74, 0xC6,
++ 0x3D, 0xCF, 0x74, 0xC2,
++ 0x27, 0xCF, 0x74, 0xC6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x27, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x4C, 0xB4,
+-0x02, 0x44, 0x54, 0xB4,
++ 0x0A, 0x44, 0x4C, 0xB4,
++ 0x02, 0x44, 0x54, 0xB4,
+
+-0x2A, 0x44, 0x4C, 0xB6,
+-0x1A, 0x44, 0x54, 0xB6,
++ 0x2A, 0x44, 0x4C, 0xB6,
++ 0x1A, 0x44, 0x54, 0xB6,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x20,
+-0x02, 0x20,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x3D, 0xCF, 0x75, 0xC6,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x3D, 0xCF, 0x75, 0xC6,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x45, 0x4D, 0xB6,
+-0x02, 0x45, 0x55, 0xB6,
++ 0x0A, 0x45, 0x4D, 0xB6,
++ 0x02, 0x45, 0x55, 0xB6,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x3D, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x31, 0x3D, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x38, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x38, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0xA6, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0xA6, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xCD, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xCD, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x94, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x94, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgzf[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x5D, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x5D, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x4F, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x4F, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x34, 0x80, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x34, 0x80, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x27, 0xCF, 0x75, 0xC6,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x27, 0xCF, 0x75, 0xC6,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x20, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x20, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x3D, 0xCF, 0x74, 0xC2,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x3D, 0xCF, 0x74, 0xC2,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x31, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x31, 0x27, 0x20, 0xE9,
+
+-0x0A, 0x44, 0x4C, 0xB4,
+-0x02, 0x44, 0x54, 0xB4,
++ 0x0A, 0x44, 0x4C, 0xB4,
++ 0x02, 0x44, 0x54, 0xB4,
+
+-0x2A, 0x45, 0x4D, 0xB6,
+-0x1A, 0x45, 0x55, 0xB6,
++ 0x2A, 0x45, 0x4D, 0xB6,
++ 0x1A, 0x45, 0x55, 0xB6,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x38, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x38, 0x3D, 0x20, 0xE9,
+
+-0x0A, 0x20,
+-0x02, 0x20,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x36, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x36, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x37, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x37, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0xAA, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0xAA, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xD3, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xD3, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x98, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x98, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgzs[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x65, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x65, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x57, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x57, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x27, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x27, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x29, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x29, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x27, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x27, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB4,
+-0x1A, 0x44, 0x54, 0xB4,
++ 0x2A, 0x44, 0x4C, 0xB4,
++ 0x1A, 0x44, 0x54, 0xB4,
+
+-0x0A, 0x45, 0x4D, 0xB0,
+-0x02, 0x45, 0x55, 0xB0,
++ 0x0A, 0x45, 0x4D, 0xB0,
++ 0x02, 0x45, 0x55, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x4D, 0xB2,
+-0x1A, 0x45, 0x55, 0xB2,
++ 0x2A, 0x45, 0x4D, 0xB2,
++ 0x1A, 0x45, 0x55, 0xB2,
+
+-0x0A, 0x45, 0x4D, 0xB4,
+-0x02, 0x45, 0x55, 0xB4,
++ 0x0A, 0x45, 0x4D, 0xB4,
++ 0x02, 0x45, 0x55, 0xB4,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x20,
+-0x02, 0x20,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x0A, 0x20,
++ 0x02, 0x20,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0xA7, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0xA7, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0xA2, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0xA2, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xCA, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xCA, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x90, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x90, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgzsa[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x6A, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x6A, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x5C, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x5C, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x27, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x27, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x2E, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x2E, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x27, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x27, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB4,
+-0x1A, 0x44, 0x54, 0xB4,
++ 0x2A, 0x44, 0x4C, 0xB4,
++ 0x1A, 0x44, 0x54, 0xB4,
+
+-0x0A, 0x45, 0x4D, 0xB0,
+-0x02, 0x45, 0x55, 0xB0,
++ 0x0A, 0x45, 0x4D, 0xB0,
++ 0x02, 0x45, 0x55, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x4D, 0xB2,
+-0x1A, 0x45, 0x55, 0xB2,
++ 0x2A, 0x45, 0x4D, 0xB2,
++ 0x1A, 0x45, 0x55, 0xB2,
+
+-0x0A, 0x45, 0x4D, 0xB4,
+-0x02, 0x45, 0x55, 0xB4,
++ 0x0A, 0x45, 0x4D, 0xB4,
++ 0x02, 0x45, 0x55, 0xB4,
+
+-0x27, 0xCF, 0x74, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x27, 0xCF, 0x74, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA7, 0x30, 0x4F, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA7, 0x30, 0x4F, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB6,
+-0x1A, 0x44, 0x54, 0xB6,
++ 0x2A, 0x44, 0x4C, 0xB6,
++ 0x1A, 0x44, 0x54, 0xB6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0x9D, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0x9D, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xC5, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC5, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x8B, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x8B, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgzsaf[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x6E, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x6E, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x60, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x60, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x27, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x27, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x32, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x32, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x27, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x27, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB4,
+-0x1A, 0x44, 0x54, 0xB4,
++ 0x2A, 0x44, 0x4C, 0xB4,
++ 0x1A, 0x44, 0x54, 0xB4,
+
+-0x0A, 0x45, 0x4D, 0xB0,
+-0x02, 0x45, 0x55, 0xB0,
++ 0x0A, 0x45, 0x4D, 0xB0,
++ 0x02, 0x45, 0x55, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x4D, 0xB2,
+-0x1A, 0x45, 0x55, 0xB2,
++ 0x2A, 0x45, 0x4D, 0xB2,
++ 0x1A, 0x45, 0x55, 0xB2,
+
+-0x0A, 0x45, 0x4D, 0xB4,
+-0x02, 0x45, 0x55, 0xB4,
++ 0x0A, 0x45, 0x4D, 0xB4,
++ 0x02, 0x45, 0x55, 0xB4,
+
+-0x27, 0xCF, 0x74, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x27, 0xCF, 0x74, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA7, 0x30, 0x4F, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA7, 0x30, 0x4F, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9C, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9C, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB6,
+-0x1A, 0x44, 0x54, 0xB6,
++ 0x2A, 0x44, 0x4C, 0xB6,
++ 0x1A, 0x44, 0x54, 0xB6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x45, 0x4D, 0xB6,
+-0x02, 0x45, 0x55, 0xB6,
++ 0x0A, 0x45, 0x4D, 0xB6,
++ 0x02, 0x45, 0x55, 0xB6,
+
+-0x3D, 0xCF, 0x75, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x3D, 0xCF, 0x75, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x3D, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x31, 0x3D, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x9D, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x9D, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x9E, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x9E, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x30, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x30, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x38, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x38, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0x99, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0x99, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xC1, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC1, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x87, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x87, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+
+ static unsigned char warp_g400_tgzsf[] = {
+
+-0x00, 0x88, 0x98, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x88, 0x98, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+-0xFF, 0x80, 0xC0, 0xE9,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xFF, 0x80, 0xC0, 0xE9,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x22, 0x40, 0x48, 0xBF,
+-0x2A, 0x40, 0x50, 0xBF,
++ 0x22, 0x40, 0x48, 0xBF,
++ 0x2A, 0x40, 0x50, 0xBF,
+
+-0x32, 0x41, 0x49, 0xBF,
+-0x3A, 0x41, 0x51, 0xBF,
++ 0x32, 0x41, 0x49, 0xBF,
++ 0x3A, 0x41, 0x51, 0xBF,
+
+-0xC3, 0x6B,
+-0xCB, 0x6B,
+-0x00, 0x88, 0x98, 0xE9,
++ 0xC3, 0x6B,
++ 0xCB, 0x6B,
++ 0x00, 0x88, 0x98, 0xE9,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x96, 0xE2,
+-0x41, 0x04,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x96, 0xE2,
++ 0x41, 0x04,
+
+-0x7B, 0x43, 0xA0, 0xE8,
+-0x73, 0x4B, 0xA0, 0xE8,
++ 0x7B, 0x43, 0xA0, 0xE8,
++ 0x73, 0x4B, 0xA0, 0xE8,
+
+-0xAD, 0xEE, 0x29, 0x9F,
+-0x00, 0xE0,
+-0x49, 0x04,
++ 0xAD, 0xEE, 0x29, 0x9F,
++ 0x00, 0xE0,
++ 0x49, 0x04,
+
+-0x90, 0xE2,
+-0x51, 0x04,
+-0x31, 0x46, 0xB1, 0xE8,
++ 0x90, 0xE2,
++ 0x51, 0x04,
++ 0x31, 0x46, 0xB1, 0xE8,
+
+-0x49, 0x41, 0xC0, 0xEC,
+-0x39, 0x57, 0xB1, 0xE8,
++ 0x49, 0x41, 0xC0, 0xEC,
++ 0x39, 0x57, 0xB1, 0xE8,
+
+-0x00, 0x04,
+-0x46, 0xE2,
+-0x73, 0x53, 0xA0, 0xE8,
++ 0x00, 0x04,
++ 0x46, 0xE2,
++ 0x73, 0x53, 0xA0, 0xE8,
+
+-0x51, 0x41, 0xC0, 0xEC,
+-0x31, 0x00,
+-0x39, 0x00,
++ 0x51, 0x41, 0xC0, 0xEC,
++ 0x31, 0x00,
++ 0x39, 0x00,
+
+-0x6A, 0x80, 0x15, 0xEA,
+-0x08, 0x04,
+-0x10, 0x04,
++ 0x6A, 0x80, 0x15, 0xEA,
++ 0x08, 0x04,
++ 0x10, 0x04,
+
+-0x51, 0x49, 0xC0, 0xEC,
+-0x2F, 0x41, 0x60, 0xEA,
++ 0x51, 0x49, 0xC0, 0xEC,
++ 0x2F, 0x41, 0x60, 0xEA,
+
+-0x31, 0x20,
+-0x39, 0x20,
+-0x1F, 0x42, 0xA0, 0xE8,
++ 0x31, 0x20,
++ 0x39, 0x20,
++ 0x1F, 0x42, 0xA0, 0xE8,
+
+-0x2A, 0x42, 0x4A, 0xBF,
+-0x27, 0x4A, 0xA0, 0xE8,
++ 0x2A, 0x42, 0x4A, 0xBF,
++ 0x27, 0x4A, 0xA0, 0xE8,
+
+-0x1A, 0x42, 0x52, 0xBF,
+-0x1E, 0x49, 0x60, 0xEA,
++ 0x1A, 0x42, 0x52, 0xBF,
++ 0x1E, 0x49, 0x60, 0xEA,
+
+-0x73, 0x7B, 0xC8, 0xEC,
+-0x26, 0x51, 0x60, 0xEA,
++ 0x73, 0x7B, 0xC8, 0xEC,
++ 0x26, 0x51, 0x60, 0xEA,
+
+-0x32, 0x40, 0x48, 0xBD,
+-0x22, 0x40, 0x50, 0xBD,
++ 0x32, 0x40, 0x48, 0xBD,
++ 0x22, 0x40, 0x50, 0xBD,
+
+-0x12, 0x41, 0x49, 0xBD,
+-0x3A, 0x41, 0x51, 0xBD,
++ 0x12, 0x41, 0x49, 0xBD,
++ 0x3A, 0x41, 0x51, 0xBD,
+
+-0xBF, 0x2F, 0x26, 0xBD,
+-0x00, 0xE0,
+-0x7B, 0x72,
++ 0xBF, 0x2F, 0x26, 0xBD,
++ 0x00, 0xE0,
++ 0x7B, 0x72,
+
+-0x32, 0x20,
+-0x22, 0x20,
+-0x12, 0x20,
+-0x3A, 0x20,
++ 0x32, 0x20,
++ 0x22, 0x20,
++ 0x12, 0x20,
++ 0x3A, 0x20,
+
+-0x46, 0x31, 0x46, 0xBF,
+-0x4E, 0x31, 0x4E, 0xBF,
++ 0x46, 0x31, 0x46, 0xBF,
++ 0x4E, 0x31, 0x4E, 0xBF,
+
+-0xB3, 0xE2, 0x2D, 0x9F,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xB3, 0xE2, 0x2D, 0x9F,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x56, 0x31, 0x56, 0xBF,
+-0x47, 0x39, 0x47, 0xBF,
++ 0x56, 0x31, 0x56, 0xBF,
++ 0x47, 0x39, 0x47, 0xBF,
+
+-0x4F, 0x39, 0x4F, 0xBF,
+-0x57, 0x39, 0x57, 0xBF,
++ 0x4F, 0x39, 0x4F, 0xBF,
++ 0x57, 0x39, 0x57, 0xBF,
+
+-0x5C, 0x80, 0x07, 0xEA,
+-0x24, 0x41, 0x20, 0xE9,
++ 0x5C, 0x80, 0x07, 0xEA,
++ 0x24, 0x41, 0x20, 0xE9,
+
+-0x42, 0x73, 0xF8, 0xEC,
+-0x00, 0xE0,
+-0x2D, 0x73,
++ 0x42, 0x73, 0xF8, 0xEC,
++ 0x00, 0xE0,
++ 0x2D, 0x73,
+
+-0x33, 0x72,
+-0x0C, 0xE3,
+-0xA5, 0x2F, 0x1E, 0xBD,
++ 0x33, 0x72,
++ 0x0C, 0xE3,
++ 0xA5, 0x2F, 0x1E, 0xBD,
+
+-0x43, 0x43, 0x2D, 0xDF,
+-0x4B, 0x4B, 0x2D, 0xDF,
++ 0x43, 0x43, 0x2D, 0xDF,
++ 0x4B, 0x4B, 0x2D, 0xDF,
+
+-0xAE, 0x1E, 0x26, 0xBD,
+-0x58, 0xE3,
+-0x33, 0x66,
++ 0xAE, 0x1E, 0x26, 0xBD,
++ 0x58, 0xE3,
++ 0x33, 0x66,
+
+-0x53, 0x53, 0x2D, 0xDF,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x53, 0x53, 0x2D, 0xDF,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0xB8, 0x38, 0x33, 0xBF,
+-0x00, 0xE0,
+-0x59, 0xE3,
++ 0xB8, 0x38, 0x33, 0xBF,
++ 0x00, 0xE0,
++ 0x59, 0xE3,
+
+-0x1E, 0x12, 0x41, 0xE9,
+-0x1A, 0x22, 0x41, 0xE9,
++ 0x1E, 0x12, 0x41, 0xE9,
++ 0x1A, 0x22, 0x41, 0xE9,
+
+-0x2B, 0x40, 0x3D, 0xE9,
+-0x3F, 0x4B, 0xA0, 0xE8,
++ 0x2B, 0x40, 0x3D, 0xE9,
++ 0x3F, 0x4B, 0xA0, 0xE8,
+
+-0x2D, 0x73,
+-0x30, 0x76,
+-0x05, 0x80, 0x3D, 0xEA,
++ 0x2D, 0x73,
++ 0x30, 0x76,
++ 0x05, 0x80, 0x3D, 0xEA,
+
+-0x37, 0x43, 0xA0, 0xE8,
+-0x3D, 0x53, 0xA0, 0xE8,
++ 0x37, 0x43, 0xA0, 0xE8,
++ 0x3D, 0x53, 0xA0, 0xE8,
+
+-0x48, 0x70, 0xF8, 0xEC,
+-0x2B, 0x48, 0x3C, 0xE9,
++ 0x48, 0x70, 0xF8, 0xEC,
++ 0x2B, 0x48, 0x3C, 0xE9,
+
+-0x1F, 0x27, 0xBC, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x1F, 0x27, 0xBC, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x15, 0xC0, 0x20, 0xE9,
+-0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
++ 0x15, 0xC0, 0x20, 0xE9,
+
+-0x18, 0x3A, 0x41, 0xE9,
+-0x1D, 0x32, 0x41, 0xE9,
++ 0x18, 0x3A, 0x41, 0xE9,
++ 0x1D, 0x32, 0x41, 0xE9,
+
+-0x2A, 0x40, 0x20, 0xE9,
+-0x56, 0x3D, 0x56, 0xDF,
++ 0x2A, 0x40, 0x20, 0xE9,
++ 0x56, 0x3D, 0x56, 0xDF,
+
+-0x46, 0x37, 0x46, 0xDF,
+-0x4E, 0x3F, 0x4E, 0xDF,
++ 0x46, 0x37, 0x46, 0xDF,
++ 0x4E, 0x3F, 0x4E, 0xDF,
+
+-0x16, 0x30, 0x20, 0xE9,
+-0x4F, 0x3F, 0x4F, 0xDF,
++ 0x16, 0x30, 0x20, 0xE9,
++ 0x4F, 0x3F, 0x4F, 0xDF,
+
+-0x47, 0x37, 0x47, 0xDF,
+-0x57, 0x3D, 0x57, 0xDF,
++ 0x47, 0x37, 0x47, 0xDF,
++ 0x57, 0x3D, 0x57, 0xDF,
+
+-0x32, 0x32, 0x2D, 0xDF,
+-0x22, 0x22, 0x2D, 0xDF,
++ 0x32, 0x32, 0x2D, 0xDF,
++ 0x22, 0x22, 0x2D, 0xDF,
+
+-0x12, 0x12, 0x2D, 0xDF,
+-0x3A, 0x3A, 0x2D, 0xDF,
++ 0x12, 0x12, 0x2D, 0xDF,
++ 0x3A, 0x3A, 0x2D, 0xDF,
+
+-0x27, 0xCF, 0x74, 0xC2,
+-0x37, 0xCF, 0x74, 0xC4,
++ 0x27, 0xCF, 0x74, 0xC2,
++ 0x37, 0xCF, 0x74, 0xC4,
+
+-0x0A, 0x44, 0x4C, 0xB0,
+-0x02, 0x44, 0x54, 0xB0,
++ 0x0A, 0x44, 0x4C, 0xB0,
++ 0x02, 0x44, 0x54, 0xB0,
+
+-0x3D, 0xCF, 0x74, 0xC0,
+-0x34, 0x37, 0x20, 0xE9,
++ 0x3D, 0xCF, 0x74, 0xC0,
++ 0x34, 0x37, 0x20, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x38, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x38, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3C, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3C, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB2,
+-0x1A, 0x44, 0x54, 0xB2,
++ 0x2A, 0x44, 0x4C, 0xB2,
++ 0x1A, 0x44, 0x54, 0xB2,
+
+-0x2E, 0x80, 0x3A, 0xEA,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0x2E, 0x80, 0x3A, 0xEA,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x27, 0xCF, 0x75, 0xC0,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x27, 0xCF, 0x75, 0xC0,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x32, 0x31, 0x5F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x32, 0x31, 0x5F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x33, 0x39, 0x5F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x33, 0x39, 0x5F, 0xE9,
+
+-0x3D, 0xCF, 0x75, 0xC2,
+-0x37, 0xCF, 0x75, 0xC4,
++ 0x3D, 0xCF, 0x75, 0xC2,
++ 0x37, 0xCF, 0x75, 0xC4,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA6, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA6, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA3, 0x3D, 0x20, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA3, 0x3D, 0x20, 0xE9,
+
+-0x2A, 0x44, 0x4C, 0xB4,
+-0x1A, 0x44, 0x54, 0xB4,
++ 0x2A, 0x44, 0x4C, 0xB4,
++ 0x1A, 0x44, 0x54, 0xB4,
+
+-0x0A, 0x45, 0x4D, 0xB0,
+-0x02, 0x45, 0x55, 0xB0,
++ 0x0A, 0x45, 0x4D, 0xB0,
++ 0x02, 0x45, 0x55, 0xB0,
+
+-0x88, 0x73, 0x5E, 0xE9,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x88, 0x73, 0x5E, 0xE9,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA0, 0x37, 0x20, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA0, 0x37, 0x20, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x3E, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x3E, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x3F, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x3F, 0x38, 0x4F, 0xE9,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x3A, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x3A, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x3B, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x3B, 0x39, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x4D, 0xB2,
+-0x1A, 0x45, 0x55, 0xB2,
++ 0x2A, 0x45, 0x4D, 0xB2,
++ 0x1A, 0x45, 0x55, 0xB2,
+
+-0x0A, 0x45, 0x4D, 0xB4,
+-0x02, 0x45, 0x55, 0xB4,
++ 0x0A, 0x45, 0x4D, 0xB4,
++ 0x02, 0x45, 0x55, 0xB4,
+
+-0x27, 0xCF, 0x75, 0xC6,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x27, 0xCF, 0x75, 0xC6,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0xA7, 0x30, 0x4F, 0xE9,
+-0x0A, 0x20,
+-0x02, 0x20,
++ 0xA7, 0x30, 0x4F, 0xE9,
++ 0x0A, 0x20,
++ 0x02, 0x20,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x31, 0x27, 0x20, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x31, 0x27, 0x20, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA8, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA8, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x45, 0x4D, 0xB6,
+-0x1A, 0x45, 0x55, 0xB6,
++ 0x2A, 0x45, 0x4D, 0xB6,
++ 0x1A, 0x45, 0x55, 0xB6,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x36, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x36, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x37, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x37, 0x39, 0x4F, 0xE9,
+
+-0x00, 0x80, 0x00, 0xE8,
+-0x2A, 0x20,
+-0x1A, 0x20,
++ 0x00, 0x80, 0x00, 0xE8,
++ 0x2A, 0x20,
++ 0x1A, 0x20,
+
+-0x2A, 0x46, 0x4E, 0xBF,
+-0x1A, 0x46, 0x56, 0xBF,
++ 0x2A, 0x46, 0x4E, 0xBF,
++ 0x1A, 0x46, 0x56, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA4, 0x31, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA4, 0x31, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA5, 0x39, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA5, 0x39, 0x4F, 0xE9,
+
+-0x0A, 0x47, 0x4F, 0xBF,
+-0x02, 0x47, 0x57, 0xBF,
++ 0x0A, 0x47, 0x4F, 0xBF,
++ 0x02, 0x47, 0x57, 0xBF,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0xA1, 0x30, 0x4F, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0xA1, 0x30, 0x4F, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0xA2, 0x38, 0x4F, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0xA2, 0x38, 0x4F, 0xE9,
+
+-0x2A, 0x43, 0x4B, 0xBF,
+-0x1A, 0x43, 0x53, 0xBF,
++ 0x2A, 0x43, 0x4B, 0xBF,
++ 0x1A, 0x43, 0x53, 0xBF,
+
+-0x30, 0x50, 0x2E, 0x9F,
+-0x35, 0x31, 0x4F, 0xE9,
++ 0x30, 0x50, 0x2E, 0x9F,
++ 0x35, 0x31, 0x4F, 0xE9,
+
+-0x38, 0x21, 0x2C, 0x9F,
+-0x39, 0x39, 0x4F, 0xE9,
++ 0x38, 0x21, 0x2C, 0x9F,
++ 0x39, 0x39, 0x4F, 0xE9,
+
+-0x31, 0x53, 0x2F, 0x9F,
+-0x80, 0x31, 0x57, 0xE9,
++ 0x31, 0x53, 0x2F, 0x9F,
++ 0x80, 0x31, 0x57, 0xE9,
+
+-0x39, 0xE5, 0x2C, 0x9F,
+-0x81, 0x39, 0x57, 0xE9,
++ 0x39, 0xE5, 0x2C, 0x9F,
++ 0x81, 0x39, 0x57, 0xE9,
+
+-0x37, 0x48, 0x50, 0xBD,
+-0x8A, 0x36, 0x20, 0xE9,
++ 0x37, 0x48, 0x50, 0xBD,
++ 0x8A, 0x36, 0x20, 0xE9,
+
+-0x86, 0x76, 0x57, 0xE9,
+-0x8B, 0x3E, 0x20, 0xE9,
++ 0x86, 0x76, 0x57, 0xE9,
++ 0x8B, 0x3E, 0x20, 0xE9,
+
+-0x82, 0x30, 0x57, 0xE9,
+-0x87, 0x77, 0x57, 0xE9,
++ 0x82, 0x30, 0x57, 0xE9,
++ 0x87, 0x77, 0x57, 0xE9,
+
+-0x83, 0x38, 0x57, 0xE9,
+-0x35, 0x49, 0x51, 0xBD,
++ 0x83, 0x38, 0x57, 0xE9,
++ 0x35, 0x49, 0x51, 0xBD,
+
+-0x84, 0x31, 0x5E, 0xE9,
+-0x30, 0x1F, 0x5F, 0xE9,
++ 0x84, 0x31, 0x5E, 0xE9,
++ 0x30, 0x1F, 0x5F, 0xE9,
+
+-0x85, 0x39, 0x5E, 0xE9,
+-0x57, 0x25, 0x20, 0xE9,
++ 0x85, 0x39, 0x5E, 0xE9,
++ 0x57, 0x25, 0x20, 0xE9,
+
+-0x2B, 0x48, 0x20, 0xE9,
+-0x1D, 0x37, 0xE1, 0xEA,
++ 0x2B, 0x48, 0x20, 0xE9,
++ 0x1D, 0x37, 0xE1, 0xEA,
+
+-0x1E, 0x35, 0xE1, 0xEA,
+-0x00, 0xE0,
+-0x26, 0x77,
++ 0x1E, 0x35, 0xE1, 0xEA,
++ 0x00, 0xE0,
++ 0x26, 0x77,
+
+-0x24, 0x49, 0x20, 0xE9,
+-0x9D, 0xFF, 0x20, 0xEA,
++ 0x24, 0x49, 0x20, 0xE9,
++ 0x9D, 0xFF, 0x20, 0xEA,
+
+-0x16, 0x26, 0x20, 0xE9,
+-0x57, 0x2E, 0xBF, 0xEA,
++ 0x16, 0x26, 0x20, 0xE9,
++ 0x57, 0x2E, 0xBF, 0xEA,
+
+-0x1C, 0x46, 0xA0, 0xE8,
+-0x23, 0x4E, 0xA0, 0xE8,
++ 0x1C, 0x46, 0xA0, 0xE8,
++ 0x23, 0x4E, 0xA0, 0xE8,
+
+-0x2B, 0x56, 0xA0, 0xE8,
+-0x1D, 0x47, 0xA0, 0xE8,
++ 0x2B, 0x56, 0xA0, 0xE8,
++ 0x1D, 0x47, 0xA0, 0xE8,
+
+-0x24, 0x4F, 0xA0, 0xE8,
+-0x2C, 0x57, 0xA0, 0xE8,
++ 0x24, 0x4F, 0xA0, 0xE8,
++ 0x2C, 0x57, 0xA0, 0xE8,
+
+-0x1C, 0x00,
+-0x23, 0x00,
+-0x2B, 0x00,
+-0x00, 0xE0,
++ 0x1C, 0x00,
++ 0x23, 0x00,
++ 0x2B, 0x00,
++ 0x00, 0xE0,
+
+-0x1D, 0x00,
+-0x24, 0x00,
+-0x2C, 0x00,
+-0x00, 0xE0,
++ 0x1D, 0x00,
++ 0x24, 0x00,
++ 0x2C, 0x00,
++ 0x00, 0xE0,
+
+-0x1C, 0x65,
+-0x23, 0x65,
+-0x2B, 0x65,
+-0x00, 0xE0,
++ 0x1C, 0x65,
++ 0x23, 0x65,
++ 0x2B, 0x65,
++ 0x00, 0xE0,
+
+-0x1D, 0x65,
+-0x24, 0x65,
+-0x2C, 0x65,
+-0x00, 0xE0,
++ 0x1D, 0x65,
++ 0x24, 0x65,
++ 0x2C, 0x65,
++ 0x00, 0xE0,
+
+-0x1C, 0x23, 0x60, 0xEC,
+-0x36, 0xD7, 0x36, 0xAD,
++ 0x1C, 0x23, 0x60, 0xEC,
++ 0x36, 0xD7, 0x36, 0xAD,
+
+-0x2B, 0x80, 0x60, 0xEC,
+-0x1D, 0x24, 0x60, 0xEC,
++ 0x2B, 0x80, 0x60, 0xEC,
++ 0x1D, 0x24, 0x60, 0xEC,
+
+-0x3E, 0xD7, 0x3E, 0xAD,
+-0x2C, 0x80, 0x60, 0xEC,
++ 0x3E, 0xD7, 0x3E, 0xAD,
++ 0x2C, 0x80, 0x60, 0xEC,
+
+-0x1C, 0x2B, 0xDE, 0xE8,
+-0x23, 0x80, 0xDE, 0xE8,
++ 0x1C, 0x2B, 0xDE, 0xE8,
++ 0x23, 0x80, 0xDE, 0xE8,
+
+-0x36, 0x80, 0x36, 0xBD,
+-0x3E, 0x80, 0x3E, 0xBD,
++ 0x36, 0x80, 0x36, 0xBD,
++ 0x3E, 0x80, 0x3E, 0xBD,
+
+-0x33, 0xD7, 0x1C, 0xBD,
+-0x3B, 0xD7, 0x23, 0xBD,
++ 0x33, 0xD7, 0x1C, 0xBD,
++ 0x3B, 0xD7, 0x23, 0xBD,
+
+-0x46, 0x80, 0x46, 0xCF,
+-0x4F, 0x80, 0x4F, 0xCF,
++ 0x46, 0x80, 0x46, 0xCF,
++ 0x4F, 0x80, 0x4F, 0xCF,
+
+-0x56, 0x33, 0x56, 0xCF,
+-0x47, 0x3B, 0x47, 0xCF,
++ 0x56, 0x33, 0x56, 0xCF,
++ 0x47, 0x3B, 0x47, 0xCF,
+
+-0xC5, 0xFF, 0x20, 0xEA,
+-0x00, 0x80, 0x00, 0xE8,
++ 0xC5, 0xFF, 0x20, 0xEA,
++ 0x00, 0x80, 0x00, 0xE8,
+
+-0x4E, 0x33, 0x4E, 0xCF,
+-0x57, 0x3B, 0x57, 0xCF,
++ 0x4E, 0x33, 0x4E, 0xCF,
++ 0x57, 0x3B, 0x57, 0xCF,
+
+-0x8B, 0xFF, 0x20, 0xEA,
+-0x57, 0xC0, 0xBF, 0xEA,
++ 0x8B, 0xFF, 0x20, 0xEA,
++ 0x57, 0xC0, 0xBF, 0xEA,
+
+-0x00, 0x80, 0xA0, 0xE9,
+-0x00, 0x00, 0xD8, 0xEC,
++ 0x00, 0x80, 0xA0, 0xE9,
++ 0x00, 0x00, 0xD8, 0xEC,
+
+ };
+diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c
+--- a/drivers/char/drm/mga_warp.c
++++ b/drivers/char/drm/mga_warp.c
+@@ -33,8 +33,7 @@
+ #include "mga_drv.h"
+ #include "mga_ucode.h"
+
+-
+-#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
++#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
+
+ #define WARP_UCODE_SIZE( which ) \
+ ((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
+@@ -49,33 +48,30 @@ do { \
+ } while (0)
+
+ static const unsigned int mga_warp_g400_microcode_size =
+- (WARP_UCODE_SIZE(warp_g400_tgz) +
+- WARP_UCODE_SIZE(warp_g400_tgza) +
+- WARP_UCODE_SIZE(warp_g400_tgzaf) +
+- WARP_UCODE_SIZE(warp_g400_tgzf) +
+- WARP_UCODE_SIZE(warp_g400_tgzs) +
+- WARP_UCODE_SIZE(warp_g400_tgzsa) +
+- WARP_UCODE_SIZE(warp_g400_tgzsaf) +
+- WARP_UCODE_SIZE(warp_g400_tgzsf) +
+- WARP_UCODE_SIZE(warp_g400_t2gz) +
+- WARP_UCODE_SIZE(warp_g400_t2gza) +
+- WARP_UCODE_SIZE(warp_g400_t2gzaf) +
+- WARP_UCODE_SIZE(warp_g400_t2gzf) +
+- WARP_UCODE_SIZE(warp_g400_t2gzs) +
+- WARP_UCODE_SIZE(warp_g400_t2gzsa) +
+- WARP_UCODE_SIZE(warp_g400_t2gzsaf) +
+- WARP_UCODE_SIZE(warp_g400_t2gzsf));
++ (WARP_UCODE_SIZE(warp_g400_tgz) +
++ WARP_UCODE_SIZE(warp_g400_tgza) +
++ WARP_UCODE_SIZE(warp_g400_tgzaf) +
++ WARP_UCODE_SIZE(warp_g400_tgzf) +
++ WARP_UCODE_SIZE(warp_g400_tgzs) +
++ WARP_UCODE_SIZE(warp_g400_tgzsa) +
++ WARP_UCODE_SIZE(warp_g400_tgzsaf) +
++ WARP_UCODE_SIZE(warp_g400_tgzsf) +
++ WARP_UCODE_SIZE(warp_g400_t2gz) +
++ WARP_UCODE_SIZE(warp_g400_t2gza) +
++ WARP_UCODE_SIZE(warp_g400_t2gzaf) +
++ WARP_UCODE_SIZE(warp_g400_t2gzf) +
++ WARP_UCODE_SIZE(warp_g400_t2gzs) +
++ WARP_UCODE_SIZE(warp_g400_t2gzsa) +
++ WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf));
+
+ static const unsigned int mga_warp_g200_microcode_size =
+- (WARP_UCODE_SIZE(warp_g200_tgz) +
+- WARP_UCODE_SIZE(warp_g200_tgza) +
+- WARP_UCODE_SIZE(warp_g200_tgzaf) +
+- WARP_UCODE_SIZE(warp_g200_tgzf) +
+- WARP_UCODE_SIZE(warp_g200_tgzs) +
+- WARP_UCODE_SIZE(warp_g200_tgzsa) +
+- WARP_UCODE_SIZE(warp_g200_tgzsaf) +
+- WARP_UCODE_SIZE(warp_g200_tgzsf));
+-
++ (WARP_UCODE_SIZE(warp_g200_tgz) +
++ WARP_UCODE_SIZE(warp_g200_tgza) +
++ WARP_UCODE_SIZE(warp_g200_tgzaf) +
++ WARP_UCODE_SIZE(warp_g200_tgzf) +
++ WARP_UCODE_SIZE(warp_g200_tgzs) +
++ WARP_UCODE_SIZE(warp_g200_tgzsa) +
++ WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf));
+
+ unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
+ {
+@@ -90,36 +86,35 @@ unsigned int mga_warp_microcode_size(con
+ }
+ }
+
+-static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv )
++static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
+ {
+ unsigned char *vcbase = dev_priv->warp->handle;
+ unsigned long pcbase = dev_priv->warp->offset;
+
+- memset( dev_priv->warp_pipe_phys, 0,
+- sizeof(dev_priv->warp_pipe_phys) );
++ memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+- WARP_UCODE_INSTALL( warp_g400_tgz, MGA_WARP_TGZ );
+- WARP_UCODE_INSTALL( warp_g400_tgzf, MGA_WARP_TGZF );
+- WARP_UCODE_INSTALL( warp_g400_tgza, MGA_WARP_TGZA );
+- WARP_UCODE_INSTALL( warp_g400_tgzaf, MGA_WARP_TGZAF );
+- WARP_UCODE_INSTALL( warp_g400_tgzs, MGA_WARP_TGZS );
+- WARP_UCODE_INSTALL( warp_g400_tgzsf, MGA_WARP_TGZSF );
+- WARP_UCODE_INSTALL( warp_g400_tgzsa, MGA_WARP_TGZSA );
+- WARP_UCODE_INSTALL( warp_g400_tgzsaf, MGA_WARP_TGZSAF );
+-
+- WARP_UCODE_INSTALL( warp_g400_t2gz, MGA_WARP_T2GZ );
+- WARP_UCODE_INSTALL( warp_g400_t2gzf, MGA_WARP_T2GZF );
+- WARP_UCODE_INSTALL( warp_g400_t2gza, MGA_WARP_T2GZA );
+- WARP_UCODE_INSTALL( warp_g400_t2gzaf, MGA_WARP_T2GZAF );
+- WARP_UCODE_INSTALL( warp_g400_t2gzs, MGA_WARP_T2GZS );
+- WARP_UCODE_INSTALL( warp_g400_t2gzsf, MGA_WARP_T2GZSF );
+- WARP_UCODE_INSTALL( warp_g400_t2gzsa, MGA_WARP_T2GZSA );
+- WARP_UCODE_INSTALL( warp_g400_t2gzsaf, MGA_WARP_T2GZSAF );
++ WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
++ WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
++ WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
++ WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
++ WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
++ WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
++ WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
++ WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
++
++ WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
++ WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
++ WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
++ WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
++ WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
++ WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
++ WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
++ WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
+
+ return 0;
+ }
+
+-static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv )
++static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
+ {
+ unsigned char *vcbase = dev_priv->warp->handle;
+ unsigned long pcbase = dev_priv->warp->offset;
+@@ -138,7 +133,7 @@ static int mga_warp_install_g200_microco
+ return 0;
+ }
+
+-int mga_warp_install_microcode( drm_mga_private_t *dev_priv )
++int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+ {
+ const unsigned int size = mga_warp_microcode_size(dev_priv);
+
+@@ -154,7 +149,7 @@ int mga_warp_install_microcode( drm_mga_
+ case MGA_CARD_TYPE_G550:
+ return mga_warp_install_g400_microcode(dev_priv);
+ case MGA_CARD_TYPE_G200:
+- return mga_warp_install_g200_microcode( dev_priv );
++ return mga_warp_install_g200_microcode(dev_priv);
+ default:
+ return DRM_ERR(EINVAL);
+ }
+@@ -162,13 +157,13 @@ int mga_warp_install_microcode( drm_mga_
+
+ #define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
+
+-int mga_warp_init( drm_mga_private_t *dev_priv )
++int mga_warp_init(drm_mga_private_t * dev_priv)
+ {
+ u32 wmisc;
+
+ /* FIXME: Get rid of these damned magic numbers...
+ */
+- switch ( dev_priv->chipset ) {
++ switch (dev_priv->chipset) {
+ case MGA_CARD_TYPE_G400:
+ case MGA_CARD_TYPE_G550:
+ MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
+@@ -177,21 +172,20 @@ int mga_warp_init( drm_mga_private_t *de
+ MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
+ break;
+ case MGA_CARD_TYPE_G200:
+- MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND );
+- MGA_WRITE( MGA_WGETMSB, 0x1606 );
+- MGA_WRITE( MGA_WVRTXSZ, 7 );
++ MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND);
++ MGA_WRITE(MGA_WGETMSB, 0x1606);
++ MGA_WRITE(MGA_WVRTXSZ, 7);
+ break;
+ default:
+ return DRM_ERR(EINVAL);
+ }
+
+- MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
+- MGA_WMASTER_ENABLE |
+- MGA_WCACHEFLUSH_ENABLE) );
+- wmisc = MGA_READ( MGA_WMISC );
+- if ( wmisc != WMISC_EXPECTED ) {
+- DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n",
+- wmisc, WMISC_EXPECTED );
++ MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
++ MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE));
++ wmisc = MGA_READ(MGA_WMISC);
++ if (wmisc != WMISC_EXPECTED) {
++ DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
++ wmisc, WMISC_EXPECTED);
+ return DRM_ERR(EINVAL);
+ }
+
+diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
+--- a/drivers/char/drm/r128_cce.c
++++ b/drivers/char/drm/r128_cce.c
+@@ -80,7 +80,7 @@ static u32 r128_cce_microcode[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+-static int R128_READ_PLL(drm_device_t *dev, int addr)
++static int R128_READ_PLL(drm_device_t * dev, int addr)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+@@ -89,106 +89,105 @@ static int R128_READ_PLL(drm_device_t *d
+ }
+
+ #if R128_FIFO_DEBUG
+-static void r128_status( drm_r128_private_t *dev_priv )
++static void r128_status(drm_r128_private_t * dev_priv)
+ {
+- printk( "GUI_STAT = 0x%08x\n",
+- (unsigned int)R128_READ( R128_GUI_STAT ) );
+- printk( "PM4_STAT = 0x%08x\n",
+- (unsigned int)R128_READ( R128_PM4_STAT ) );
+- printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n",
+- (unsigned int)R128_READ( R128_PM4_BUFFER_DL_WPTR ) );
+- printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n",
+- (unsigned int)R128_READ( R128_PM4_BUFFER_DL_RPTR ) );
+- printk( "PM4_MICRO_CNTL = 0x%08x\n",
+- (unsigned int)R128_READ( R128_PM4_MICRO_CNTL ) );
+- printk( "PM4_BUFFER_CNTL = 0x%08x\n",
+- (unsigned int)R128_READ( R128_PM4_BUFFER_CNTL ) );
++ printk("GUI_STAT = 0x%08x\n",
++ (unsigned int)R128_READ(R128_GUI_STAT));
++ printk("PM4_STAT = 0x%08x\n",
++ (unsigned int)R128_READ(R128_PM4_STAT));
++ printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
++ (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
++ printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
++ (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
++ printk("PM4_MICRO_CNTL = 0x%08x\n",
++ (unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
++ printk("PM4_BUFFER_CNTL = 0x%08x\n",
++ (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
+ }
+ #endif
+
+-
+ /* ================================================================
+ * Engine, FIFO control
+ */
+
+-static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv )
++static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv)
+ {
+ u32 tmp;
+ int i;
+
+- tmp = R128_READ( R128_PC_NGUI_CTLSTAT ) | R128_PC_FLUSH_ALL;
+- R128_WRITE( R128_PC_NGUI_CTLSTAT, tmp );
++ tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
++ R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) {
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) {
+ return 0;
+ }
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ #if R128_FIFO_DEBUG
+- DRM_ERROR( "failed!\n" );
++ DRM_ERROR("failed!\n");
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
++static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
+ {
+ int i;
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- int slots = R128_READ( R128_GUI_STAT ) & R128_GUI_FIFOCNT_MASK;
+- if ( slots >= entries ) return 0;
+- DRM_UDELAY( 1 );
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
++ if (slots >= entries)
++ return 0;
++ DRM_UDELAY(1);
+ }
+
+ #if R128_FIFO_DEBUG
+- DRM_ERROR( "failed!\n" );
++ DRM_ERROR("failed!\n");
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
++static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
+ {
+ int i, ret;
+
+- ret = r128_do_wait_for_fifo( dev_priv, 64 );
+- if ( ret ) return ret;
+-
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
+- r128_do_pixcache_flush( dev_priv );
++ ret = r128_do_wait_for_fifo(dev_priv, 64);
++ if (ret)
++ return ret;
++
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
++ r128_do_pixcache_flush(dev_priv);
+ return 0;
+ }
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ #if R128_FIFO_DEBUG
+- DRM_ERROR( "failed!\n" );
++ DRM_ERROR("failed!\n");
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-
+ /* ================================================================
+ * CCE control, initialization
+ */
+
+ /* Load the microcode for the CCE */
+-static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
++static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
+ {
+ int i;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- r128_do_wait_for_idle( dev_priv );
++ r128_do_wait_for_idle(dev_priv);
+
+- R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
+- for ( i = 0 ; i < 256 ; i++ ) {
+- R128_WRITE( R128_PM4_MICROCODE_DATAH,
+- r128_cce_microcode[i * 2] );
+- R128_WRITE( R128_PM4_MICROCODE_DATAL,
+- r128_cce_microcode[i * 2 + 1] );
++ R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
++ for (i = 0; i < 256; i++) {
++ R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
++ R128_WRITE(R128_PM4_MICROCODE_DATAL,
++ r128_cce_microcode[i * 2 + 1]);
+ }
+ }
+
+@@ -196,51 +195,51 @@ static void r128_cce_load_microcode( drm
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+-static void r128_do_cce_flush( drm_r128_private_t *dev_priv )
++static void r128_do_cce_flush(drm_r128_private_t * dev_priv)
+ {
+ u32 tmp;
+
+- tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR ) | R128_PM4_BUFFER_DL_DONE;
+- R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp );
++ tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE;
++ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp);
+ }
+
+ /* Wait for the CCE to go idle.
+ */
+-int r128_do_cce_idle( drm_r128_private_t *dev_priv )
++int r128_do_cce_idle(drm_r128_private_t * dev_priv)
+ {
+ int i;
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- if ( GET_RING_HEAD( dev_priv ) == dev_priv->ring.tail ) {
+- int pm4stat = R128_READ( R128_PM4_STAT );
+- if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
+- dev_priv->cce_fifo_size ) &&
+- !(pm4stat & (R128_PM4_BUSY |
+- R128_PM4_GUI_ACTIVE)) ) {
+- return r128_do_pixcache_flush( dev_priv );
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) {
++ int pm4stat = R128_READ(R128_PM4_STAT);
++ if (((pm4stat & R128_PM4_FIFOCNT_MASK) >=
++ dev_priv->cce_fifo_size) &&
++ !(pm4stat & (R128_PM4_BUSY |
++ R128_PM4_GUI_ACTIVE))) {
++ return r128_do_pixcache_flush(dev_priv);
+ }
+ }
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ #if R128_FIFO_DEBUG
+- DRM_ERROR( "failed!\n" );
+- r128_status( dev_priv );
++ DRM_ERROR("failed!\n");
++ r128_status(dev_priv);
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+ /* Start the Concurrent Command Engine.
+ */
+-static void r128_do_cce_start( drm_r128_private_t *dev_priv )
++static void r128_do_cce_start(drm_r128_private_t * dev_priv)
+ {
+- r128_do_wait_for_idle( dev_priv );
++ r128_do_wait_for_idle(dev_priv);
+
+- R128_WRITE( R128_PM4_BUFFER_CNTL,
+- dev_priv->cce_mode | dev_priv->ring.size_l2qw
+- | R128_PM4_BUFFER_CNTL_NOUPDATE );
+- R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
+- R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
++ R128_WRITE(R128_PM4_BUFFER_CNTL,
++ dev_priv->cce_mode | dev_priv->ring.size_l2qw
++ | R128_PM4_BUFFER_CNTL_NOUPDATE);
++ R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */
++ R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
+
+ dev_priv->cce_running = 1;
+ }
+@@ -249,10 +248,10 @@ static void r128_do_cce_start( drm_r128_
+ * commands, so you must wait for the CCE command stream to complete
+ * before calling this routine.
+ */
+-static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
++static void r128_do_cce_reset(drm_r128_private_t * dev_priv)
+ {
+- R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
+- R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
++ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
++ R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
+ dev_priv->ring.tail = 0;
+ }
+
+@@ -260,122 +259,120 @@ static void r128_do_cce_reset( drm_r128_
+ * commands, so you must flush the command stream and wait for the CCE
+ * to go idle before calling this routine.
+ */
+-static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
++static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
+ {
+- R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
+- R128_WRITE( R128_PM4_BUFFER_CNTL,
+- R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE );
++ R128_WRITE(R128_PM4_MICRO_CNTL, 0);
++ R128_WRITE(R128_PM4_BUFFER_CNTL,
++ R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
+
+ dev_priv->cce_running = 0;
+ }
+
+ /* Reset the engine. This will stop the CCE if it is running.
+ */
+-static int r128_do_engine_reset( drm_device_t *dev )
++static int r128_do_engine_reset(drm_device_t * dev)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
+
+- r128_do_pixcache_flush( dev_priv );
++ r128_do_pixcache_flush(dev_priv);
+
+- clock_cntl_index = R128_READ( R128_CLOCK_CNTL_INDEX );
+- mclk_cntl = R128_READ_PLL( dev, R128_MCLK_CNTL );
++ clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
++ mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
+
+- R128_WRITE_PLL( R128_MCLK_CNTL,
+- mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP );
++ R128_WRITE_PLL(R128_MCLK_CNTL,
++ mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
+
+- gen_reset_cntl = R128_READ( R128_GEN_RESET_CNTL );
++ gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
+
+ /* Taken from the sample code - do not change */
+- R128_WRITE( R128_GEN_RESET_CNTL,
+- gen_reset_cntl | R128_SOFT_RESET_GUI );
+- R128_READ( R128_GEN_RESET_CNTL );
+- R128_WRITE( R128_GEN_RESET_CNTL,
+- gen_reset_cntl & ~R128_SOFT_RESET_GUI );
+- R128_READ( R128_GEN_RESET_CNTL );
+-
+- R128_WRITE_PLL( R128_MCLK_CNTL, mclk_cntl );
+- R128_WRITE( R128_CLOCK_CNTL_INDEX, clock_cntl_index );
+- R128_WRITE( R128_GEN_RESET_CNTL, gen_reset_cntl );
++ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
++ R128_READ(R128_GEN_RESET_CNTL);
++ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
++ R128_READ(R128_GEN_RESET_CNTL);
++
++ R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
++ R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
++ R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
+
+ /* Reset the CCE ring */
+- r128_do_cce_reset( dev_priv );
++ r128_do_cce_reset(dev_priv);
+
+ /* The CCE is no longer running after an engine reset */
+ dev_priv->cce_running = 0;
+
+ /* Reset any pending vertex, indirect buffers */
+- r128_freelist_reset( dev );
++ r128_freelist_reset(dev);
+
+ return 0;
+ }
+
+-static void r128_cce_init_ring_buffer( drm_device_t *dev,
+- drm_r128_private_t *dev_priv )
++static void r128_cce_init_ring_buffer(drm_device_t * dev,
++ drm_r128_private_t * dev_priv)
+ {
+ u32 ring_start;
+ u32 tmp;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ /* The manual (p. 2) says this address is in "VM space". This
+ * means it's an offset from the start of AGP space.
+ */
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci )
++ if (!dev_priv->is_pci)
+ ring_start = dev_priv->cce_ring->offset - dev->agp->base;
+ else
+ #endif
+- ring_start = dev_priv->cce_ring->offset -
+- (unsigned long)dev->sg->virtual;
++ ring_start = dev_priv->cce_ring->offset -
++ (unsigned long)dev->sg->virtual;
+
+- R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
++ R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
+
+- R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
+- R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
++ R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
++ R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
+
+ /* Set watermark control */
+- R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
+- ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
+- | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT)
+- | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT)
+- | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT) );
++ R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
++ ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
++ | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
++ | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
++ | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
+
+ /* Force read. Why? Because it's in the examples... */
+- R128_READ( R128_PM4_BUFFER_ADDR );
++ R128_READ(R128_PM4_BUFFER_ADDR);
+
+ /* Turn on bus mastering */
+- tmp = R128_READ( R128_BUS_CNTL ) & ~R128_BUS_MASTER_DIS;
+- R128_WRITE( R128_BUS_CNTL, tmp );
++ tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
++ R128_WRITE(R128_BUS_CNTL, tmp);
+ }
+
+-static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
++static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
+ {
+ drm_r128_private_t *dev_priv;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- dev_priv = drm_alloc( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
+- if ( dev_priv == NULL )
++ dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
++ if (dev_priv == NULL)
+ return DRM_ERR(ENOMEM);
+
+- memset( dev_priv, 0, sizeof(drm_r128_private_t) );
++ memset(dev_priv, 0, sizeof(drm_r128_private_t));
+
+ dev_priv->is_pci = init->is_pci;
+
+- if ( dev_priv->is_pci && !dev->sg ) {
+- DRM_ERROR( "PCI GART memory not allocated!\n" );
++ if (dev_priv->is_pci && !dev->sg) {
++ DRM_ERROR("PCI GART memory not allocated!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+ dev_priv->usec_timeout = init->usec_timeout;
+- if ( dev_priv->usec_timeout < 1 ||
+- dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
+- DRM_DEBUG( "TIMEOUT problem!\n" );
++ if (dev_priv->usec_timeout < 1 ||
++ dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
++ DRM_DEBUG("TIMEOUT problem!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -383,23 +380,23 @@ static int r128_do_init_cce( drm_device_
+
+ /* GH: Simple idle check.
+ */
+- atomic_set( &dev_priv->idle_count, 0 );
++ atomic_set(&dev_priv->idle_count, 0);
+
+ /* We don't support anything other than bus-mastering ring mode,
+ * but the ring can be in either AGP or PCI space for the ring
+ * read pointer.
+ */
+- if ( ( init->cce_mode != R128_PM4_192BM ) &&
+- ( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
+- ( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
+- ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
+- DRM_DEBUG( "Bad cce_mode!\n" );
++ if ((init->cce_mode != R128_PM4_192BM) &&
++ (init->cce_mode != R128_PM4_128BM_64INDBM) &&
++ (init->cce_mode != R128_PM4_64BM_128INDBM) &&
++ (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
++ DRM_DEBUG("Bad cce_mode!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+- switch ( init->cce_mode ) {
++ switch (init->cce_mode) {
+ case R128_PM4_NONPM4:
+ dev_priv->cce_fifo_size = 0;
+ break;
+@@ -420,7 +417,7 @@ static int r128_do_init_cce( drm_device_
+ break;
+ }
+
+- switch ( init->fb_bpp ) {
++ switch (init->fb_bpp) {
+ case 16:
+ dev_priv->color_fmt = R128_DATATYPE_RGB565;
+ break;
+@@ -429,12 +426,12 @@ static int r128_do_init_cce( drm_device_
+ dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
+ break;
+ }
+- dev_priv->front_offset = init->front_offset;
+- dev_priv->front_pitch = init->front_pitch;
+- dev_priv->back_offset = init->back_offset;
+- dev_priv->back_pitch = init->back_pitch;
++ dev_priv->front_offset = init->front_offset;
++ dev_priv->front_pitch = init->front_pitch;
++ dev_priv->back_offset = init->back_offset;
++ dev_priv->back_pitch = init->back_pitch;
+
+- switch ( init->depth_bpp ) {
++ switch (init->depth_bpp) {
+ case 16:
+ dev_priv->depth_fmt = R128_DATATYPE_RGB565;
+ break;
+@@ -444,218 +441,223 @@ static int r128_do_init_cce( drm_device_
+ dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
+ break;
+ }
+- dev_priv->depth_offset = init->depth_offset;
+- dev_priv->depth_pitch = init->depth_pitch;
+- dev_priv->span_offset = init->span_offset;
++ dev_priv->depth_offset = init->depth_offset;
++ dev_priv->depth_pitch = init->depth_pitch;
++ dev_priv->span_offset = init->span_offset;
+
+- dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch/8) << 21) |
++ dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
+ (dev_priv->front_offset >> 5));
+- dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch/8) << 21) |
++ dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
+ (dev_priv->back_offset >> 5));
+- dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
++ dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
+ (dev_priv->depth_offset >> 5) |
+ R128_DST_TILE);
+- dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
++ dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
+ (dev_priv->span_offset >> 5));
+
+ DRM_GETSAREA();
+-
+- if(!dev_priv->sarea) {
++
++ if (!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+ dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+- if(!dev_priv->mmio) {
++ if (!dev_priv->mmio) {
+ DRM_ERROR("could not find mmio region!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
+- if(!dev_priv->cce_ring) {
++ if (!dev_priv->cce_ring) {
+ DRM_ERROR("could not find cce ring region!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
+- if(!dev_priv->ring_rptr) {
++ if (!dev_priv->ring_rptr) {
+ DRM_ERROR("could not find ring read pointer!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+ dev->agp_buffer_token = init->buffers_offset;
+ dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+- if(!dev->agp_buffer_map) {
++ if (!dev->agp_buffer_map) {
+ DRM_ERROR("could not find dma buffer region!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( !dev_priv->is_pci ) {
+- dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset);
+- if(!dev_priv->agp_textures) {
++ if (!dev_priv->is_pci) {
++ dev_priv->agp_textures =
++ drm_core_findmap(dev, init->agp_textures_offset);
++ if (!dev_priv->agp_textures) {
+ DRM_ERROR("could not find agp texture region!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ dev_priv->sarea_priv =
+- (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
+- init->sarea_priv_offset);
++ (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
++ init->sarea_priv_offset);
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
+- drm_core_ioremap( dev_priv->cce_ring, dev );
+- drm_core_ioremap( dev_priv->ring_rptr, dev );
+- drm_core_ioremap( dev->agp_buffer_map, dev );
+- if(!dev_priv->cce_ring->handle ||
+- !dev_priv->ring_rptr->handle ||
+- !dev->agp_buffer_map->handle) {
++ if (!dev_priv->is_pci) {
++ drm_core_ioremap(dev_priv->cce_ring, dev);
++ drm_core_ioremap(dev_priv->ring_rptr, dev);
++ drm_core_ioremap(dev->agp_buffer_map, dev);
++ if (!dev_priv->cce_ring->handle ||
++ !dev_priv->ring_rptr->handle ||
++ !dev->agp_buffer_map->handle) {
+ DRM_ERROR("Could not ioremap agp regions!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(ENOMEM);
+ }
+ } else
+ #endif
+ {
+- dev_priv->cce_ring->handle =
+- (void *)dev_priv->cce_ring->offset;
++ dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset;
+ dev_priv->ring_rptr->handle =
+- (void *)dev_priv->ring_rptr->offset;
+- dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
++ (void *)dev_priv->ring_rptr->offset;
++ dev->agp_buffer_map->handle =
++ (void *)dev->agp_buffer_map->offset;
+ }
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci )
++ if (!dev_priv->is_pci)
+ dev_priv->cce_buffers_offset = dev->agp->base;
+ else
+ #endif
+ dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
+
+- dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
+- dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
++ dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle;
++ dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
+ + init->ring_size / sizeof(u32));
+ dev_priv->ring.size = init->ring_size;
+- dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
++ dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+
+- dev_priv->ring.tail_mask =
+- (dev_priv->ring.size / sizeof(u32)) - 1;
++ dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+
+ dev_priv->ring.high_mark = 128;
+
+ dev_priv->sarea_priv->last_frame = 0;
+- R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
++ R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+
+ dev_priv->sarea_priv->last_dispatch = 0;
+- R128_WRITE( R128_LAST_DISPATCH_REG,
+- dev_priv->sarea_priv->last_dispatch );
++ R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
+
+ #if __OS_HAS_AGP
+- if ( dev_priv->is_pci ) {
++ if (dev_priv->is_pci) {
+ #endif
+- if (!drm_ati_pcigart_init( dev, &dev_priv->phys_pci_gart,
+- &dev_priv->bus_pci_gart) ) {
+- DRM_ERROR( "failed to init PCI GART!\n" );
++ dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
++ dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0;
++ dev_priv->gart_info.is_pcie = 0;
++ if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
++ DRM_ERROR("failed to init PCI GART!\n");
+ dev->dev_private = (void *)dev_priv;
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ return DRM_ERR(ENOMEM);
+ }
+- R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
++ R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
+ #if __OS_HAS_AGP
+ }
+ #endif
+
+- r128_cce_init_ring_buffer( dev, dev_priv );
+- r128_cce_load_microcode( dev_priv );
++ r128_cce_init_ring_buffer(dev, dev_priv);
++ r128_cce_load_microcode(dev_priv);
+
+ dev->dev_private = (void *)dev_priv;
+
+- r128_do_engine_reset( dev );
++ r128_do_engine_reset(dev);
+
+ return 0;
+ }
+
+-int r128_do_cleanup_cce( drm_device_t *dev )
++int r128_do_cleanup_cce(drm_device_t * dev)
+ {
+
+ /* Make sure interrupts are disabled here because the uninstall ioctl
+ * may not have been called from userspace and after dev_private
+ * is freed, it's too late.
+ */
+- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
++ if (dev->irq_enabled)
++ drm_irq_uninstall(dev);
+
+- if ( dev->dev_private ) {
++ if (dev->dev_private) {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
+- if ( dev_priv->cce_ring != NULL )
+- drm_core_ioremapfree( dev_priv->cce_ring, dev );
+- if ( dev_priv->ring_rptr != NULL )
+- drm_core_ioremapfree( dev_priv->ring_rptr, dev );
+- if ( dev->agp_buffer_map != NULL )
+- drm_core_ioremapfree( dev->agp_buffer_map, dev );
++ if (!dev_priv->is_pci) {
++ if (dev_priv->cce_ring != NULL)
++ drm_core_ioremapfree(dev_priv->cce_ring, dev);
++ if (dev_priv->ring_rptr != NULL)
++ drm_core_ioremapfree(dev_priv->ring_rptr, dev);
++ if (dev->agp_buffer_map != NULL)
++ drm_core_ioremapfree(dev->agp_buffer_map, dev);
+ } else
+ #endif
+ {
+- if (!drm_ati_pcigart_cleanup( dev,
+- dev_priv->phys_pci_gart,
+- dev_priv->bus_pci_gart ))
+- DRM_ERROR( "failed to cleanup PCI GART!\n" );
++ if (dev_priv->gart_info.bus_addr)
++ if (!drm_ati_pcigart_cleanup(dev,
++ &dev_priv->
++ gart_info))
++ DRM_ERROR
++ ("failed to cleanup PCI GART!\n");
+ }
+
+- drm_free( dev->dev_private, sizeof(drm_r128_private_t),
+- DRM_MEM_DRIVER );
++ drm_free(dev->dev_private, sizeof(drm_r128_private_t),
++ DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+ }
+
+-int r128_cce_init( DRM_IOCTL_ARGS )
++int r128_cce_init(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_init_t init;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t __user *)data, sizeof(init) );
++ DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data,
++ sizeof(init));
+
+- switch ( init.func ) {
++ switch (init.func) {
+ case R128_INIT_CCE:
+- return r128_do_init_cce( dev, &init );
++ return r128_do_init_cce(dev, &init);
+ case R128_CLEANUP_CCE:
+- return r128_do_cleanup_cce( dev );
++ return r128_do_cleanup_cce(dev);
+ }
+
+ return DRM_ERR(EINVAL);
+ }
+
+-int r128_cce_start( DRM_IOCTL_ARGS )
++int r128_cce_start(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) {
+- DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ );
++ if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
++ DRM_DEBUG("%s while CCE running\n", __FUNCTION__);
+ return 0;
+ }
+
+- r128_do_cce_start( dev_priv );
++ r128_do_cce_start(dev_priv);
+
+ return 0;
+ }
+@@ -663,61 +665,63 @@ int r128_cce_start( DRM_IOCTL_ARGS )
+ /* Stop the CCE. The engine must have been idled before calling this
+ * routine.
+ */
+-int r128_cce_stop( DRM_IOCTL_ARGS )
++int r128_cce_stop(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_cce_stop_t stop;
+ int ret;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *)data, sizeof(stop) );
++ DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data,
++ sizeof(stop));
+
+ /* Flush any pending CCE commands. This ensures any outstanding
+ * commands are exectuted by the engine before we turn it off.
+ */
+- if ( stop.flush ) {
+- r128_do_cce_flush( dev_priv );
++ if (stop.flush) {
++ r128_do_cce_flush(dev_priv);
+ }
+
+ /* If we fail to make the engine go idle, we return an error
+ * code so that the DRM ioctl wrapper can try again.
+ */
+- if ( stop.idle ) {
+- ret = r128_do_cce_idle( dev_priv );
+- if ( ret ) return ret;
++ if (stop.idle) {
++ ret = r128_do_cce_idle(dev_priv);
++ if (ret)
++ return ret;
+ }
+
+ /* Finally, we can turn off the CCE. If the engine isn't idle,
+ * we will get some dropped triangles as they won't be fully
+ * rendered before the CCE is shut down.
+ */
+- r128_do_cce_stop( dev_priv );
++ r128_do_cce_stop(dev_priv);
+
+ /* Reset the engine */
+- r128_do_engine_reset( dev );
++ r128_do_engine_reset(dev);
+
+ return 0;
+ }
+
+ /* Just reset the CCE ring. Called as part of an X Server engine reset.
+ */
+-int r128_cce_reset( DRM_IOCTL_ARGS )
++int r128_cce_reset(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_DEBUG("%s called before init done\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- r128_do_cce_reset( dev_priv );
++ r128_do_cce_reset(dev_priv);
+
+ /* The CCE is no longer running after an engine reset */
+ dev_priv->cce_running = 0;
+@@ -725,37 +729,36 @@ int r128_cce_reset( DRM_IOCTL_ARGS )
+ return 0;
+ }
+
+-int r128_cce_idle( DRM_IOCTL_ARGS )
++int r128_cce_idle(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( dev_priv->cce_running ) {
+- r128_do_cce_flush( dev_priv );
++ if (dev_priv->cce_running) {
++ r128_do_cce_flush(dev_priv);
+ }
+
+- return r128_do_cce_idle( dev_priv );
++ return r128_do_cce_idle(dev_priv);
+ }
+
+-int r128_engine_reset( DRM_IOCTL_ARGS )
++int r128_engine_reset(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- return r128_do_engine_reset( dev );
++ return r128_do_engine_reset(dev);
+ }
+
+-int r128_fullscreen( DRM_IOCTL_ARGS )
++int r128_fullscreen(DRM_IOCTL_ARGS)
+ {
+ return DRM_ERR(EINVAL);
+ }
+
+-
+ /* ================================================================
+ * Freelist management
+ */
+@@ -763,7 +766,7 @@ int r128_fullscreen( DRM_IOCTL_ARGS )
+ #define R128_BUFFER_FREE 0
+
+ #if 0
+-static int r128_freelist_init( drm_device_t *dev )
++static int r128_freelist_init(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+@@ -772,27 +775,26 @@ static int r128_freelist_init( drm_devic
+ drm_r128_freelist_t *entry;
+ int i;
+
+- dev_priv->head = drm_alloc( sizeof(drm_r128_freelist_t),
+- DRM_MEM_DRIVER );
+- if ( dev_priv->head == NULL )
++ dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
++ if (dev_priv->head == NULL)
+ return DRM_ERR(ENOMEM);
+
+- memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) );
++ memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
+ dev_priv->head->age = R128_BUFFER_USED;
+
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
++ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+
+- entry = drm_alloc( sizeof(drm_r128_freelist_t),
+- DRM_MEM_DRIVER );
+- if ( !entry ) return DRM_ERR(ENOMEM);
++ entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
++ if (!entry)
++ return DRM_ERR(ENOMEM);
+
+ entry->age = R128_BUFFER_FREE;
+ entry->buf = buf;
+ entry->prev = dev_priv->head;
+ entry->next = dev_priv->head->next;
+- if ( !entry->next )
++ if (!entry->next)
+ dev_priv->tail = entry;
+
+ buf_priv->discard = 0;
+@@ -801,7 +803,7 @@ static int r128_freelist_init( drm_devic
+
+ dev_priv->head->next = entry;
+
+- if ( dev_priv->head->next )
++ if (dev_priv->head->next)
+ dev_priv->head->next->prev = entry;
+ }
+
+@@ -810,7 +812,7 @@ static int r128_freelist_init( drm_devic
+ }
+ #endif
+
+-static drm_buf_t *r128_freelist_get( drm_device_t *dev )
++static drm_buf_t *r128_freelist_get(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+@@ -820,20 +822,20 @@ static drm_buf_t *r128_freelist_get( drm
+
+ /* FIXME: Optimize -- use freelist code */
+
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
++ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+- if ( buf->filp == 0 )
++ if (buf->filp == 0)
+ return buf;
+ }
+
+- for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
+- u32 done_age = R128_READ( R128_LAST_DISPATCH_REG );
++ for (t = 0; t < dev_priv->usec_timeout; t++) {
++ u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
+
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
++ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+- if ( buf->pending && buf_priv->age <= done_age ) {
++ if (buf->pending && buf_priv->age <= done_age) {
+ /* The buffer has been processed, so it
+ * can now be used.
+ */
+@@ -841,63 +843,63 @@ static drm_buf_t *r128_freelist_get( drm
+ return buf;
+ }
+ }
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+- DRM_DEBUG( "returning NULL!\n" );
++ DRM_DEBUG("returning NULL!\n");
+ return NULL;
+ }
+
+-void r128_freelist_reset( drm_device_t *dev )
++void r128_freelist_reset(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
++ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ buf_priv->age = 0;
+ }
+ }
+
+-
+ /* ================================================================
+ * CCE command submission
+ */
+
+-int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
++int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
+ {
+ drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+ int i;
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- r128_update_ring_snapshot( dev_priv );
+- if ( ring->space >= n )
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ r128_update_ring_snapshot(dev_priv);
++ if (ring->space >= n)
+ return 0;
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ /* FIXME: This is being ignored... */
+- DRM_ERROR( "failed!\n" );
++ DRM_ERROR("failed!\n");
+ return DRM_ERR(EBUSY);
+ }
+
+-static int r128_cce_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
++static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+ {
+ int i;
+ drm_buf_t *buf;
+
+- for ( i = d->granted_count ; i < d->request_count ; i++ ) {
+- buf = r128_freelist_get( dev );
+- if ( !buf ) return DRM_ERR(EAGAIN);
++ for (i = d->granted_count; i < d->request_count; i++) {
++ buf = r128_freelist_get(dev);
++ if (!buf)
++ return DRM_ERR(EAGAIN);
+
+ buf->filp = filp;
+
+- if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
+- sizeof(buf->idx) ) )
++ if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
++ sizeof(buf->idx)))
+ return DRM_ERR(EFAULT);
+- if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
+- sizeof(buf->total) ) )
++ if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
++ sizeof(buf->total)))
+ return DRM_ERR(EFAULT);
+
+ d->granted_count++;
+@@ -905,7 +907,7 @@ static int r128_cce_get_buffers( DRMFILE
+ return 0;
+ }
+
+-int r128_cce_buffers( DRM_IOCTL_ARGS )
++int r128_cce_buffers(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+@@ -913,33 +915,33 @@ int r128_cce_buffers( DRM_IOCTL_ARGS )
+ drm_dma_t __user *argp = (void __user *)data;
+ drm_dma_t d;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
++ DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+
+ /* Please don't send us buffers.
+ */
+- if ( d.send_count != 0 ) {
+- DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
+- DRM_CURRENTPID, d.send_count );
++ if (d.send_count != 0) {
++ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
++ DRM_CURRENTPID, d.send_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* We'll send you buffers.
+ */
+- if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
+- DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
+- DRM_CURRENTPID, d.request_count, dma->buf_count );
++ if (d.request_count < 0 || d.request_count > dma->buf_count) {
++ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
++ DRM_CURRENTPID, d.request_count, dma->buf_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ d.granted_count = 0;
+
+- if ( d.request_count ) {
+- ret = r128_cce_get_buffers( filp, dev, &d );
++ if (d.request_count) {
++ ret = r128_cce_get_buffers(filp, dev, &d);
+ }
+
+- DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d) );
++ DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
+
+ return ret;
+ }
+diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
+--- a/drivers/char/drm/r128_drm.h
++++ b/drivers/char/drm/r128_drm.h
+@@ -93,7 +93,7 @@
+ #define R128_MAX_TEXTURE_LEVELS 11
+ #define R128_MAX_TEXTURE_UNITS 2
+
+-#endif /* __R128_SAREA_DEFINES__ */
++#endif /* __R128_SAREA_DEFINES__ */
+
+ typedef struct {
+ /* Context state - can be written in one large chunk */
+@@ -140,7 +140,6 @@ typedef struct {
+ unsigned int tex_border_color;
+ } drm_r128_texture_regs_t;
+
+-
+ typedef struct drm_r128_sarea {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+@@ -161,14 +160,13 @@ typedef struct drm_r128_sarea {
+ unsigned int last_frame;
+ unsigned int last_dispatch;
+
+- drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
++ drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
+ unsigned int tex_age[R128_NR_TEX_HEAPS];
+ int ctx_owner;
+- int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
+- int pfCurrentPage; /* which buffer is being displayed? */
++ int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
++ int pfCurrentPage; /* which buffer is being displayed? */
+ } drm_r128_sarea_t;
+
+-
+ /* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmR128.h)
+ */
+@@ -220,7 +218,7 @@ typedef struct drm_r128_sarea {
+
+ typedef struct drm_r128_init {
+ enum {
+- R128_INIT_CCE = 0x01,
++ R128_INIT_CCE = 0x01,
+ R128_CLEANUP_CCE = 0x02
+ } func;
+ #if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
+@@ -278,9 +276,9 @@ typedef struct drm_r128_clear {
+
+ typedef struct drm_r128_vertex {
+ int prim;
+- int idx; /* Index of vertex buffer */
+- int count; /* Number of vertices in buffer */
+- int discard; /* Client finished with buffer? */
++ int idx; /* Index of vertex buffer */
++ int count; /* Number of vertices in buffer */
++ int discard; /* Client finished with buffer? */
+ } drm_r128_vertex_t;
+
+ typedef struct drm_r128_indices {
+@@ -288,7 +286,7 @@ typedef struct drm_r128_indices {
+ int idx;
+ int start;
+ int end;
+- int discard; /* Client finished with buffer? */
++ int discard; /* Client finished with buffer? */
+ } drm_r128_indices_t;
+
+ typedef struct drm_r128_blit {
+@@ -302,10 +300,10 @@ typedef struct drm_r128_blit {
+
+ typedef struct drm_r128_depth {
+ enum {
+- R128_WRITE_SPAN = 0x01,
+- R128_WRITE_PIXELS = 0x02,
+- R128_READ_SPAN = 0x03,
+- R128_READ_PIXELS = 0x04
++ R128_WRITE_SPAN = 0x01,
++ R128_WRITE_PIXELS = 0x02,
++ R128_READ_SPAN = 0x03,
++ R128_READ_PIXELS = 0x04
+ } func;
+ int n;
+ int __user *x;
+@@ -327,13 +325,13 @@ typedef struct drm_r128_indirect {
+
+ typedef struct drm_r128_fullscreen {
+ enum {
+- R128_INIT_FULLSCREEN = 0x01,
++ R128_INIT_FULLSCREEN = 0x01,
+ R128_CLEANUP_FULLSCREEN = 0x02
+ } func;
+ } drm_r128_fullscreen_t;
+
+ /* 2.3: An ioctl to get parameters that aren't available to the 3d
+- * client any other way.
++ * client any other way.
+ */
+ #define R128_PARAM_IRQ_NR 1
+
+diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
+--- a/drivers/char/drm/r128_drv.c
++++ b/drivers/char/drm/r128_drv.c
+@@ -37,30 +37,28 @@
+
+ #include "drm_pciids.h"
+
+-static int postinit( struct drm_device *dev, unsigned long flags )
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -68,11 +66,11 @@ static struct pci_device_id pciidlist[]
+ r128_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t r128_ioctls[];
+-extern int r128_max_ioctl;
+-
+ static struct drm_driver driver = {
+- .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
++ .driver_features =
++ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
++ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
++ DRIVER_IRQ_VBL,
+ .dev_priv_size = sizeof(drm_r128_buf_priv_t),
+ .prerelease = r128_driver_prerelease,
+ .pretakedown = r128_driver_pretakedown,
+@@ -89,21 +87,22 @@ static struct drm_driver driver = {
+ .ioctls = r128_ioctls,
+ .dma_ioctl = r128_cce_buffers,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
+ #ifdef CONFIG_COMPAT
+- .compat_ioctl = r128_compat_ioctl,
++ .compat_ioctl = r128_compat_ioctl,
+ #endif
+- },
++ }
++ ,
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init r128_init(void)
+@@ -120,6 +119,6 @@ static void __exit r128_exit(void)
+ module_init(r128_init);
+ module_exit(r128_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
+--- a/drivers/char/drm/r128_drv.h
++++ b/drivers/char/drm/r128_drv.h
+@@ -52,14 +52,13 @@
+ #define DRIVER_MINOR 5
+ #define DRIVER_PATCHLEVEL 0
+
+-
+ #define GET_RING_HEAD(dev_priv) R128_READ( R128_PM4_BUFFER_DL_RPTR )
+
+ typedef struct drm_r128_freelist {
+- unsigned int age;
+- drm_buf_t *buf;
+- struct drm_r128_freelist *next;
+- struct drm_r128_freelist *prev;
++ unsigned int age;
++ drm_buf_t *buf;
++ struct drm_r128_freelist *next;
++ struct drm_r128_freelist *prev;
+ } drm_r128_freelist_t;
+
+ typedef struct drm_r128_ring_buffer {
+@@ -83,13 +82,11 @@ typedef struct drm_r128_private {
+ int cce_fifo_size;
+ int cce_running;
+
+- drm_r128_freelist_t *head;
+- drm_r128_freelist_t *tail;
++ drm_r128_freelist_t *head;
++ drm_r128_freelist_t *tail;
+
+ int usec_timeout;
+ int is_pci;
+- unsigned long phys_pci_gart;
+- dma_addr_t bus_pci_gart;
+ unsigned long cce_buffers_offset;
+
+ atomic_t idle_count;
+@@ -120,6 +117,7 @@ typedef struct drm_r128_private {
+ drm_local_map_t *cce_ring;
+ drm_local_map_t *ring_rptr;
+ drm_local_map_t *agp_textures;
++ drm_ati_pcigart_info gart_info;
+ } drm_r128_private_t;
+
+ typedef struct drm_r128_buf_priv {
+@@ -127,34 +125,37 @@ typedef struct drm_r128_buf_priv {
+ int prim;
+ int discard;
+ int dispatched;
+- drm_r128_freelist_t *list_entry;
++ drm_r128_freelist_t *list_entry;
+ } drm_r128_buf_priv_t;
+
++extern drm_ioctl_desc_t r128_ioctls[];
++extern int r128_max_ioctl;
++
+ /* r128_cce.c */
+-extern int r128_cce_init( DRM_IOCTL_ARGS );
+-extern int r128_cce_start( DRM_IOCTL_ARGS );
+-extern int r128_cce_stop( DRM_IOCTL_ARGS );
+-extern int r128_cce_reset( DRM_IOCTL_ARGS );
+-extern int r128_cce_idle( DRM_IOCTL_ARGS );
+-extern int r128_engine_reset( DRM_IOCTL_ARGS );
+-extern int r128_fullscreen( DRM_IOCTL_ARGS );
+-extern int r128_cce_buffers( DRM_IOCTL_ARGS );
+-
+-extern void r128_freelist_reset( drm_device_t *dev );
+-
+-extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
+-
+-extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
+-extern int r128_do_cleanup_cce( drm_device_t *dev );
+-
+-extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+-
+-extern irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS );
+-extern void r128_driver_irq_preinstall( drm_device_t *dev );
+-extern void r128_driver_irq_postinstall( drm_device_t *dev );
+-extern void r128_driver_irq_uninstall( drm_device_t *dev );
+-extern void r128_driver_pretakedown(drm_device_t *dev);
+-extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp);
++extern int r128_cce_init(DRM_IOCTL_ARGS);
++extern int r128_cce_start(DRM_IOCTL_ARGS);
++extern int r128_cce_stop(DRM_IOCTL_ARGS);
++extern int r128_cce_reset(DRM_IOCTL_ARGS);
++extern int r128_cce_idle(DRM_IOCTL_ARGS);
++extern int r128_engine_reset(DRM_IOCTL_ARGS);
++extern int r128_fullscreen(DRM_IOCTL_ARGS);
++extern int r128_cce_buffers(DRM_IOCTL_ARGS);
++
++extern void r128_freelist_reset(drm_device_t * dev);
++
++extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
++
++extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
++extern int r128_do_cleanup_cce(drm_device_t * dev);
++
++extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
++
++extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
++extern void r128_driver_irq_preinstall(drm_device_t * dev);
++extern void r128_driver_irq_postinstall(drm_device_t * dev);
++extern void r128_driver_irq_uninstall(drm_device_t * dev);
++extern void r128_driver_pretakedown(drm_device_t * dev);
++extern void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+
+ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+@@ -266,7 +267,6 @@ extern long r128_compat_ioctl(struct fil
+ # define R128_EVENT_CRTC_OFFSET (1 << 0)
+ #define R128_WINDOW_XY_OFFSET 0x1bcc
+
+-
+ /* CCE registers
+ */
+ #define R128_PM4_BUFFER_OFFSET 0x0700
+@@ -317,7 +317,6 @@ extern long r128_compat_ioctl(struct fil
+ #define R128_PM4_FIFO_DATA_EVEN 0x1000
+ #define R128_PM4_FIFO_DATA_ODD 0x1004
+
+-
+ /* CCE command packets
+ */
+ #define R128_CCE_PACKET0 0x00000000
+@@ -395,7 +394,6 @@ do { \
+ R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
+ } while (0)
+
+-
+ #define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \
+ ((n) << 16) | ((reg) >> 2))
+ #define CCE_PACKET1( reg0, reg1 ) (R128_CCE_PACKET1 | \
+@@ -404,13 +402,11 @@ do { \
+ #define CCE_PACKET3( pkt, n ) (R128_CCE_PACKET3 | \
+ (pkt) | ((n) << 16))
+
+-
+-static __inline__ void
+-r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
++static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+- ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32);
+- if ( ring->space <= 0 )
++ ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
++ if (ring->space <= 0)
+ ring->space += ring->size;
+ }
+
+@@ -451,7 +447,6 @@ do { \
+ OUT_RING( R128_EVENT_CRTC_OFFSET ); \
+ } while (0)
+
+-
+ /* ================================================================
+ * Ring control
+ */
+@@ -521,4 +516,4 @@ do { \
+ write &= tail_mask; \
+ } while (0)
+
+-#endif /* __R128_DRV_H__ */
++#endif /* __R128_DRV_H__ */
+diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
+--- a/drivers/char/drm/r128_ioc32.c
++++ b/drivers/char/drm/r128_ioc32.c
+@@ -65,10 +65,10 @@ static int compat_r128_init(struct file
+ {
+ drm_r128_init32_t init32;
+ drm_r128_init_t __user *init;
+-
++
+ if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+ return -EFAULT;
+-
++
+ init = compat_alloc_user_space(sizeof(*init));
+ if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+ || __put_user(init32.func, &init->func)
+@@ -92,14 +92,14 @@ static int compat_r128_init(struct file
+ || __put_user(init32.ring_offset, &init->ring_offset)
+ || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
+ || __put_user(init32.buffers_offset, &init->buffers_offset)
+- || __put_user(init32.agp_textures_offset, &init->agp_textures_offset))
++ || __put_user(init32.agp_textures_offset,
++ &init->agp_textures_offset))
+ return -EFAULT;
+-
++
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_R128_INIT, (unsigned long)init);
+ }
+
+-
+ typedef struct drm_r128_depth32 {
+ int func;
+ int n;
+@@ -124,13 +124,15 @@ static int compat_r128_depth(struct file
+ || __put_user(depth32.n, &depth->n)
+ || __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
+ || __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
+- || __put_user((unsigned int __user *)(unsigned long)depth32.buffer, &depth->buffer)
+- || __put_user((unsigned char __user *)(unsigned long)depth32.mask, &depth->mask))
++ || __put_user((unsigned int __user *)(unsigned long)depth32.buffer,
++ &depth->buffer)
++ || __put_user((unsigned char __user *)(unsigned long)depth32.mask,
++ &depth->mask))
+ return -EFAULT;
+-
++
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+-
++ DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
++
+ }
+
+ typedef struct drm_r128_stipple32 {
+@@ -148,7 +150,8 @@ static int compat_r128_stipple(struct fi
+
+ stipple = compat_alloc_user_space(sizeof(*stipple));
+ if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
+- || __put_user((unsigned int __user *)(unsigned long)stipple32.mask, &stipple->mask))
++ || __put_user((unsigned int __user *)(unsigned long)stipple32.mask,
++ &stipple->mask))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+@@ -172,9 +175,10 @@ static int compat_r128_getparam(struct f
+ getparam = compat_alloc_user_space(sizeof(*getparam));
+ if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
+ || __put_user(getparam32.param, &getparam->param)
+- || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
++ || __put_user((void __user *)(unsigned long)getparam32.value,
++ &getparam->value))
+ return -EFAULT;
+-
++
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
+ }
+@@ -195,8 +199,7 @@ drm_ioctl_compat_t *r128_compat_ioctls[]
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+-long r128_compat_ioctl(struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+@@ -210,7 +213,7 @@ long r128_compat_ioctl(struct file *filp
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+- ret = (*fn)(filp, cmd, arg);
++ ret = (*fn) (filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
+--- a/drivers/char/drm/r128_irq.c
++++ b/drivers/char/drm/r128_irq.c
+@@ -1,7 +1,7 @@
+ /* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+- *
++ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+@@ -35,68 +35,67 @@
+ #include "r128_drm.h"
+ #include "r128_drv.h"
+
+-irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS )
++irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ drm_device_t *dev = (drm_device_t *) arg;
+- drm_r128_private_t *dev_priv =
+- (drm_r128_private_t *)dev->dev_private;
++ drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+ int status;
+
+- status = R128_READ( R128_GEN_INT_STATUS );
+-
++ status = R128_READ(R128_GEN_INT_STATUS);
++
+ /* VBLANK interrupt */
+- if ( status & R128_CRTC_VBLANK_INT ) {
+- R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
++ if (status & R128_CRTC_VBLANK_INT) {
++ R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+ atomic_inc(&dev->vbl_received);
+ DRM_WAKEUP(&dev->vbl_queue);
+- drm_vbl_send_signals( dev );
++ drm_vbl_send_signals(dev);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+ }
+
+-int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
++int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+ {
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ /* Assume that the user has missed the current sequence number
+ * by about a day rather than she wants to wait for years
+- * using vertical blanks...
++ * using vertical blanks...
+ */
+- DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
+- ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+- - *sequence ) <= (1<<23) ) );
++ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
++ (((cur_vblank = atomic_read(&dev->vbl_received))
++ - *sequence) <= (1 << 23)));
+
+ *sequence = cur_vblank;
+
+ return ret;
+ }
+
+-void r128_driver_irq_preinstall( drm_device_t *dev ) {
+- drm_r128_private_t *dev_priv =
+- (drm_r128_private_t *)dev->dev_private;
++void r128_driver_irq_preinstall(drm_device_t * dev)
++{
++ drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+
+ /* Disable *all* interrupts */
+- R128_WRITE( R128_GEN_INT_CNTL, 0 );
++ R128_WRITE(R128_GEN_INT_CNTL, 0);
+ /* Clear vblank bit if it's already high */
+- R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
++ R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+ }
+
+-void r128_driver_irq_postinstall( drm_device_t *dev ) {
+- drm_r128_private_t *dev_priv =
+- (drm_r128_private_t *)dev->dev_private;
++void r128_driver_irq_postinstall(drm_device_t * dev)
++{
++ drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+
+ /* Turn on VBL interrupt */
+- R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN );
++ R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+ }
+
+-void r128_driver_irq_uninstall( drm_device_t *dev ) {
+- drm_r128_private_t *dev_priv =
+- (drm_r128_private_t *)dev->dev_private;
++void r128_driver_irq_uninstall(drm_device_t * dev)
++{
++ drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+- R128_WRITE( R128_GEN_INT_CNTL, 0 );
++ R128_WRITE(R128_GEN_INT_CNTL, 0);
+ }
+diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
+--- a/drivers/char/drm/r128_state.c
++++ b/drivers/char/drm/r128_state.c
+@@ -32,235 +32,233 @@
+ #include "r128_drm.h"
+ #include "r128_drv.h"
+
+-
+ /* ================================================================
+ * CCE hardware state programming functions
+ */
+
+-static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
+- drm_clip_rect_t *boxes, int count )
++static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
++ drm_clip_rect_t * boxes, int count)
+ {
+ u32 aux_sc_cntl = 0x00000000;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( (count < 3? count: 3) * 5 + 2 );
++ BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
+
+- if ( count >= 1 ) {
+- OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
+- OUT_RING( boxes[0].x1 );
+- OUT_RING( boxes[0].x2 - 1 );
+- OUT_RING( boxes[0].y1 );
+- OUT_RING( boxes[0].y2 - 1 );
++ if (count >= 1) {
++ OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
++ OUT_RING(boxes[0].x1);
++ OUT_RING(boxes[0].x2 - 1);
++ OUT_RING(boxes[0].y1);
++ OUT_RING(boxes[0].y2 - 1);
+
+ aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
+ }
+- if ( count >= 2 ) {
+- OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
+- OUT_RING( boxes[1].x1 );
+- OUT_RING( boxes[1].x2 - 1 );
+- OUT_RING( boxes[1].y1 );
+- OUT_RING( boxes[1].y2 - 1 );
++ if (count >= 2) {
++ OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
++ OUT_RING(boxes[1].x1);
++ OUT_RING(boxes[1].x2 - 1);
++ OUT_RING(boxes[1].y1);
++ OUT_RING(boxes[1].y2 - 1);
+
+ aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
+ }
+- if ( count >= 3 ) {
+- OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
+- OUT_RING( boxes[2].x1 );
+- OUT_RING( boxes[2].x2 - 1 );
+- OUT_RING( boxes[2].y1 );
+- OUT_RING( boxes[2].y2 - 1 );
++ if (count >= 3) {
++ OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
++ OUT_RING(boxes[2].x1);
++ OUT_RING(boxes[2].x2 - 1);
++ OUT_RING(boxes[2].y1);
++ OUT_RING(boxes[2].y2 - 1);
+
+ aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
+ }
+
+- OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
+- OUT_RING( aux_sc_cntl );
++ OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
++ OUT_RING(aux_sc_cntl);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
+- OUT_RING( ctx->scale_3d_cntl );
++ OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
++ OUT_RING(ctx->scale_3d_cntl);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( 13 );
++ BEGIN_RING(13);
+
+- OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
+- OUT_RING( ctx->dst_pitch_offset_c );
+- OUT_RING( ctx->dp_gui_master_cntl_c );
+- OUT_RING( ctx->sc_top_left_c );
+- OUT_RING( ctx->sc_bottom_right_c );
+- OUT_RING( ctx->z_offset_c );
+- OUT_RING( ctx->z_pitch_c );
+- OUT_RING( ctx->z_sten_cntl_c );
+- OUT_RING( ctx->tex_cntl_c );
+- OUT_RING( ctx->misc_3d_state_cntl_reg );
+- OUT_RING( ctx->texture_clr_cmp_clr_c );
+- OUT_RING( ctx->texture_clr_cmp_msk_c );
+- OUT_RING( ctx->fog_color_c );
++ OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
++ OUT_RING(ctx->dst_pitch_offset_c);
++ OUT_RING(ctx->dp_gui_master_cntl_c);
++ OUT_RING(ctx->sc_top_left_c);
++ OUT_RING(ctx->sc_bottom_right_c);
++ OUT_RING(ctx->z_offset_c);
++ OUT_RING(ctx->z_pitch_c);
++ OUT_RING(ctx->z_sten_cntl_c);
++ OUT_RING(ctx->tex_cntl_c);
++ OUT_RING(ctx->misc_3d_state_cntl_reg);
++ OUT_RING(ctx->texture_clr_cmp_clr_c);
++ OUT_RING(ctx->texture_clr_cmp_msk_c);
++ OUT_RING(ctx->fog_color_c);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( 3 );
++ BEGIN_RING(3);
+
+- OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
+- OUT_RING( ctx->setup_cntl );
+- OUT_RING( ctx->pm4_vc_fpu_setup );
++ OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
++ OUT_RING(ctx->setup_cntl);
++ OUT_RING(ctx->pm4_vc_fpu_setup);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( 5 );
++ BEGIN_RING(5);
+
+- OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
+- OUT_RING( ctx->dp_write_mask );
++ OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
++ OUT_RING(ctx->dp_write_mask);
+
+- OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
+- OUT_RING( ctx->sten_ref_mask_c );
+- OUT_RING( ctx->plane_3d_mask_c );
++ OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
++ OUT_RING(ctx->sten_ref_mask_c);
++ OUT_RING(ctx->plane_3d_mask_c);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
+- OUT_RING( ctx->window_xy_offset );
++ OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
++ OUT_RING(ctx->window_xy_offset);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
++ BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
+
+- OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
+- 2 + R128_MAX_TEXTURE_LEVELS ) );
+- OUT_RING( tex->tex_cntl );
+- OUT_RING( tex->tex_combine_cntl );
+- OUT_RING( ctx->tex_size_pitch_c );
+- for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+- OUT_RING( tex->tex_offset[i] );
+- }
+-
+- OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
+- OUT_RING( ctx->constant_color_c );
+- OUT_RING( tex->tex_border_color );
++ OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
++ 2 + R128_MAX_TEXTURE_LEVELS));
++ OUT_RING(tex->tex_cntl);
++ OUT_RING(tex->tex_combine_cntl);
++ OUT_RING(ctx->tex_size_pitch_c);
++ for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
++ OUT_RING(tex->tex_offset[i]);
++ }
++
++ OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
++ OUT_RING(ctx->constant_color_c);
++ OUT_RING(tex->tex_border_color);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( " %s\n", __FUNCTION__ );
++ DRM_DEBUG(" %s\n", __FUNCTION__);
+
+- BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
++ BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
+
+- OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
+- 1 + R128_MAX_TEXTURE_LEVELS ) );
+- OUT_RING( tex->tex_cntl );
+- OUT_RING( tex->tex_combine_cntl );
+- for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+- OUT_RING( tex->tex_offset[i] );
++ OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
++ OUT_RING(tex->tex_cntl);
++ OUT_RING(tex->tex_combine_cntl);
++ for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
++ OUT_RING(tex->tex_offset[i]);
+ }
+
+- OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
+- OUT_RING( tex->tex_border_color );
++ OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
++ OUT_RING(tex->tex_border_color);
+
+ ADVANCE_RING();
+ }
+
+-static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
++static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv)
+ {
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+- DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
++ DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
+
+- if ( dirty & R128_UPLOAD_CORE ) {
+- r128_emit_core( dev_priv );
++ if (dirty & R128_UPLOAD_CORE) {
++ r128_emit_core(dev_priv);
+ sarea_priv->dirty &= ~R128_UPLOAD_CORE;
+ }
+
+- if ( dirty & R128_UPLOAD_CONTEXT ) {
+- r128_emit_context( dev_priv );
++ if (dirty & R128_UPLOAD_CONTEXT) {
++ r128_emit_context(dev_priv);
+ sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
+ }
+
+- if ( dirty & R128_UPLOAD_SETUP ) {
+- r128_emit_setup( dev_priv );
++ if (dirty & R128_UPLOAD_SETUP) {
++ r128_emit_setup(dev_priv);
+ sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
+ }
+
+- if ( dirty & R128_UPLOAD_MASKS ) {
+- r128_emit_masks( dev_priv );
++ if (dirty & R128_UPLOAD_MASKS) {
++ r128_emit_masks(dev_priv);
+ sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
+ }
+
+- if ( dirty & R128_UPLOAD_WINDOW ) {
+- r128_emit_window( dev_priv );
++ if (dirty & R128_UPLOAD_WINDOW) {
++ r128_emit_window(dev_priv);
+ sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
+ }
+
+- if ( dirty & R128_UPLOAD_TEX0 ) {
+- r128_emit_tex0( dev_priv );
++ if (dirty & R128_UPLOAD_TEX0) {
++ r128_emit_tex0(dev_priv);
+ sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
+ }
+
+- if ( dirty & R128_UPLOAD_TEX1 ) {
+- r128_emit_tex1( dev_priv );
++ if (dirty & R128_UPLOAD_TEX1) {
++ r128_emit_tex1(dev_priv);
+ sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
+ }
+
+@@ -270,26 +268,23 @@ static __inline__ void r128_emit_state(
+ sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
+ }
+
+-
+ #if R128_PERFORMANCE_BOXES
+ /* ================================================================
+ * Performance monitoring functions
+ */
+
+-static void r128_clear_box( drm_r128_private_t *dev_priv,
+- int x, int y, int w, int h,
+- int r, int g, int b )
++static void r128_clear_box(drm_r128_private_t * dev_priv,
++ int x, int y, int w, int h, int r, int g, int b)
+ {
+ u32 pitch, offset;
+ u32 fb_bpp, color;
+ RING_LOCALS;
+
+- switch ( dev_priv->fb_bpp ) {
++ switch (dev_priv->fb_bpp) {
+ case 16:
+ fb_bpp = R128_GMC_DST_16BPP;
+ color = (((r & 0xf8) << 8) |
+- ((g & 0xfc) << 3) |
+- ((b & 0xf8) >> 3));
++ ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+ break;
+ case 24:
+ fb_bpp = R128_GMC_DST_24BPP;
+@@ -297,7 +292,7 @@ static void r128_clear_box( drm_r128_pri
+ break;
+ case 32:
+ fb_bpp = R128_GMC_DST_32BPP;
+- color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
++ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ break;
+ default:
+ return;
+@@ -306,60 +301,58 @@ static void r128_clear_box( drm_r128_pri
+ offset = dev_priv->back_offset;
+ pitch = dev_priv->back_pitch >> 3;
+
+- BEGIN_RING( 6 );
++ BEGIN_RING(6);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- fb_bpp |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_AUX_CLIP_DIS );
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ fb_bpp |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
+
+- OUT_RING( (pitch << 21) | (offset >> 5) );
+- OUT_RING( color );
++ OUT_RING((pitch << 21) | (offset >> 5));
++ OUT_RING(color);
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+
+-static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
++static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv)
+ {
+- if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
+- r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
++ if (atomic_read(&dev_priv->idle_count) == 0) {
++ r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
+ } else {
+- atomic_set( &dev_priv->idle_count, 0 );
++ atomic_set(&dev_priv->idle_count, 0);
+ }
+ }
+
+ #endif
+
+-
+ /* ================================================================
+ * CCE command dispatch functions
+ */
+
+-static void r128_print_dirty( const char *msg, unsigned int flags )
++static void r128_print_dirty(const char *msg, unsigned int flags)
+ {
+- DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+- msg,
+- flags,
+- (flags & R128_UPLOAD_CORE) ? "core, " : "",
+- (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
+- (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
+- (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
+- (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
+- (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
+- (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
+- (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+- (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
++ DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
++ msg,
++ flags,
++ (flags & R128_UPLOAD_CORE) ? "core, " : "",
++ (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
++ (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
++ (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
++ (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
++ (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
++ (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
++ (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
++ (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
+ }
+
+-static void r128_cce_dispatch_clear( drm_device_t *dev,
+- drm_r128_clear_t *clear )
++static void r128_cce_dispatch_clear(drm_device_t * dev,
++ drm_r128_clear_t * clear)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -368,102 +361,103 @@ static void r128_cce_dispatch_clear( drm
+ unsigned int flags = clear->flags;
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+- if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
++ if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+ unsigned int tmp = flags;
+
+ flags &= ~(R128_FRONT | R128_BACK);
+- if ( tmp & R128_FRONT ) flags |= R128_BACK;
+- if ( tmp & R128_BACK ) flags |= R128_FRONT;
++ if (tmp & R128_FRONT)
++ flags |= R128_BACK;
++ if (tmp & R128_BACK)
++ flags |= R128_FRONT;
+ }
+
+- for ( i = 0 ; i < nbox ; i++ ) {
++ for (i = 0; i < nbox; i++) {
+ int x = pbox[i].x1;
+ int y = pbox[i].y1;
+ int w = pbox[i].x2 - x;
+ int h = pbox[i].y2 - y;
+
+- DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
+- pbox[i].x1, pbox[i].y1, pbox[i].x2,
+- pbox[i].y2, flags );
++ DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
++ pbox[i].x1, pbox[i].y1, pbox[i].x2,
++ pbox[i].y2, flags);
+
+- if ( flags & (R128_FRONT | R128_BACK) ) {
+- BEGIN_RING( 2 );
++ if (flags & (R128_FRONT | R128_BACK)) {
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
+- OUT_RING( clear->color_mask );
++ OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
++ OUT_RING(clear->color_mask);
+
+ ADVANCE_RING();
+ }
+
+- if ( flags & R128_FRONT ) {
+- BEGIN_RING( 6 );
++ if (flags & R128_FRONT) {
++ BEGIN_RING(6);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->color_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_AUX_CLIP_DIS );
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->color_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_AUX_CLIP_DIS);
+
+- OUT_RING( dev_priv->front_pitch_offset_c );
+- OUT_RING( clear->clear_color );
++ OUT_RING(dev_priv->front_pitch_offset_c);
++ OUT_RING(clear->clear_color);
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+
+- if ( flags & R128_BACK ) {
+- BEGIN_RING( 6 );
++ if (flags & R128_BACK) {
++ BEGIN_RING(6);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->color_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_AUX_CLIP_DIS );
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->color_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_AUX_CLIP_DIS);
+
+- OUT_RING( dev_priv->back_pitch_offset_c );
+- OUT_RING( clear->clear_color );
++ OUT_RING(dev_priv->back_pitch_offset_c);
++ OUT_RING(clear->clear_color);
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+
+- if ( flags & R128_DEPTH ) {
+- BEGIN_RING( 6 );
++ if (flags & R128_DEPTH) {
++ BEGIN_RING(6);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->depth_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_AUX_CLIP_DIS |
+- R128_GMC_WR_MSK_DIS );
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->depth_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
+
+- OUT_RING( dev_priv->depth_pitch_offset_c );
+- OUT_RING( clear->clear_depth );
++ OUT_RING(dev_priv->depth_pitch_offset_c);
++ OUT_RING(clear->clear_depth);
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+ }
+ }
+
+-static void r128_cce_dispatch_swap( drm_device_t *dev )
++static void r128_cce_dispatch_swap(drm_device_t * dev)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -471,48 +465,46 @@ static void r128_cce_dispatch_swap( drm_
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ #if R128_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+- r128_cce_performance_boxes( dev_priv );
++ r128_cce_performance_boxes(dev_priv);
+ #endif
+
+- for ( i = 0 ; i < nbox ; i++ ) {
++ for (i = 0; i < nbox; i++) {
+ int x = pbox[i].x1;
+ int y = pbox[i].y1;
+ int w = pbox[i].x2 - x;
+ int h = pbox[i].y2 - y;
+
+- BEGIN_RING( 7 );
++ BEGIN_RING(7);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
+- OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+- R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_NONE |
+- (dev_priv->color_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_S |
+- R128_DP_SRC_SOURCE_MEMORY |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_AUX_CLIP_DIS |
+- R128_GMC_WR_MSK_DIS );
++ OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
++ OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
++ R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_NONE |
++ (dev_priv->color_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_S |
++ R128_DP_SRC_SOURCE_MEMORY |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
+
+ /* Make this work even if front & back are flipped:
+ */
+ if (dev_priv->current_page == 0) {
+- OUT_RING( dev_priv->back_pitch_offset_c );
+- OUT_RING( dev_priv->front_pitch_offset_c );
+- }
+- else {
+- OUT_RING( dev_priv->front_pitch_offset_c );
+- OUT_RING( dev_priv->back_pitch_offset_c );
++ OUT_RING(dev_priv->back_pitch_offset_c);
++ OUT_RING(dev_priv->front_pitch_offset_c);
++ } else {
++ OUT_RING(dev_priv->front_pitch_offset_c);
++ OUT_RING(dev_priv->back_pitch_offset_c);
+ }
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ OUT_RING((x << 16) | y);
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+@@ -523,38 +515,37 @@ static void r128_cce_dispatch_swap( drm_
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
+- OUT_RING( dev_priv->sarea_priv->last_frame );
++ OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
++ OUT_RING(dev_priv->sarea_priv->last_frame);
+
+ ADVANCE_RING();
+ }
+
+-static void r128_cce_dispatch_flip( drm_device_t *dev )
++static void r128_cce_dispatch_flip(drm_device_t * dev)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+- DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+- __FUNCTION__,
+- dev_priv->current_page,
+- dev_priv->sarea_priv->pfCurrentPage);
++ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
++ __FUNCTION__,
++ dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+
+ #if R128_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+- r128_cce_performance_boxes( dev_priv );
++ r128_cce_performance_boxes(dev_priv);
+ #endif
+
+- BEGIN_RING( 4 );
++ BEGIN_RING(4);
+
+ R128_WAIT_UNTIL_PAGE_FLIPPED();
+- OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
++ OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
+
+- if ( dev_priv->current_page == 0 ) {
+- OUT_RING( dev_priv->back_offset );
++ if (dev_priv->current_page == 0) {
++ OUT_RING(dev_priv->back_offset);
+ } else {
+- OUT_RING( dev_priv->front_offset );
++ OUT_RING(dev_priv->front_offset);
+ }
+
+ ADVANCE_RING();
+@@ -565,18 +556,17 @@ static void r128_cce_dispatch_flip( drm_
+ */
+ dev_priv->sarea_priv->last_frame++;
+ dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
+- 1 - dev_priv->current_page;
++ 1 - dev_priv->current_page;
+
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
+- OUT_RING( dev_priv->sarea_priv->last_frame );
++ OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
++ OUT_RING(dev_priv->sarea_priv->last_frame);
+
+ ADVANCE_RING();
+ }
+
+-static void r128_cce_dispatch_vertex( drm_device_t *dev,
+- drm_buf_t *buf )
++static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+@@ -587,50 +577,50 @@ static void r128_cce_dispatch_vertex( dr
+ int prim = buf_priv->prim;
+ int i = 0;
+ RING_LOCALS;
+- DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox );
++ DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
+
+- if ( 0 )
+- r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
++ if (0)
++ r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
+
+- if ( buf->used ) {
++ if (buf->used) {
+ buf_priv->dispatched = 1;
+
+- if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
+- r128_emit_state( dev_priv );
++ if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
++ r128_emit_state(dev_priv);
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+- if ( i < sarea_priv->nbox ) {
+- r128_emit_clip_rects( dev_priv,
+- &sarea_priv->boxes[i],
+- sarea_priv->nbox - i );
++ if (i < sarea_priv->nbox) {
++ r128_emit_clip_rects(dev_priv,
++ &sarea_priv->boxes[i],
++ sarea_priv->nbox - i);
+ }
+
+ /* Emit the vertex buffer rendering commands */
+- BEGIN_RING( 5 );
++ BEGIN_RING(5);
+
+- OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+- OUT_RING( offset );
+- OUT_RING( size );
+- OUT_RING( format );
+- OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
+- (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
++ OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
++ OUT_RING(offset);
++ OUT_RING(size);
++ OUT_RING(format);
++ OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
++ (size << R128_CCE_VC_CNTL_NUM_SHIFT));
+
+ ADVANCE_RING();
+
+ i += 3;
+- } while ( i < sarea_priv->nbox );
++ } while (i < sarea_priv->nbox);
+ }
+
+- if ( buf_priv->discard ) {
++ if (buf_priv->discard) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
+- OUT_RING( buf_priv->age );
++ OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
++ OUT_RING(buf_priv->age);
+
+ ADVANCE_RING();
+
+@@ -646,17 +636,15 @@ static void r128_cce_dispatch_vertex( dr
+ sarea_priv->nbox = 0;
+ }
+
+-static void r128_cce_dispatch_indirect( drm_device_t *dev,
+- drm_buf_t *buf,
+- int start, int end )
++static void r128_cce_dispatch_indirect(drm_device_t * dev,
++ drm_buf_t * buf, int start, int end)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ RING_LOCALS;
+- DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
+- buf->idx, start, end );
++ DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
+
+- if ( start != end ) {
++ if (start != end) {
+ int offset = buf->bus_address + start;
+ int dwords = (end - start + 3) / sizeof(u32);
+
+@@ -664,33 +652,33 @@ static void r128_cce_dispatch_indirect(
+ * dwords, so if we've been given an odd number we must
+ * pad the data with a Type-2 CCE packet.
+ */
+- if ( dwords & 1 ) {
++ if (dwords & 1) {
+ u32 *data = (u32 *)
+- ((char *)dev->agp_buffer_map->handle
+- + buf->offset + start);
+- data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
++ ((char *)dev->agp_buffer_map->handle
++ + buf->offset + start);
++ data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
+ }
+
+ buf_priv->dispatched = 1;
+
+ /* Fire off the indirect buffer */
+- BEGIN_RING( 3 );
++ BEGIN_RING(3);
+
+- OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
+- OUT_RING( offset );
+- OUT_RING( dwords );
++ OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
++ OUT_RING(offset);
++ OUT_RING(dwords);
+
+ ADVANCE_RING();
+ }
+
+- if ( buf_priv->discard ) {
++ if (buf_priv->discard) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the indirect buffer age */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
+- OUT_RING( buf_priv->age );
++ OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
++ OUT_RING(buf_priv->age);
+
+ ADVANCE_RING();
+
+@@ -703,10 +691,9 @@ static void r128_cce_dispatch_indirect(
+ dev_priv->sarea_priv->last_dispatch++;
+ }
+
+-static void r128_cce_dispatch_indices( drm_device_t *dev,
+- drm_buf_t *buf,
+- int start, int end,
+- int count )
++static void r128_cce_dispatch_indices(drm_device_t * dev,
++ drm_buf_t * buf,
++ int start, int end, int count)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+@@ -718,62 +705,62 @@ static void r128_cce_dispatch_indices( d
+ int dwords;
+ int i = 0;
+ RING_LOCALS;
+- DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
++ DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
+
+- if ( 0 )
+- r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
++ if (0)
++ r128_print_dirty("dispatch_indices", sarea_priv->dirty);
+
+- if ( start != end ) {
++ if (start != end) {
+ buf_priv->dispatched = 1;
+
+- if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
+- r128_emit_state( dev_priv );
++ if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
++ r128_emit_state(dev_priv);
+ }
+
+ dwords = (end - start + 3) / sizeof(u32);
+
+- data = (u32 *)((char *)dev->agp_buffer_map->handle
+- + buf->offset + start);
++ data = (u32 *) ((char *)dev->agp_buffer_map->handle
++ + buf->offset + start);
+
+- data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
+- dwords-2 ) );
++ data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
++ dwords - 2));
+
+- data[1] = cpu_to_le32( offset );
+- data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
+- data[3] = cpu_to_le32( format );
+- data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
+- (count << 16)) );
++ data[1] = cpu_to_le32(offset);
++ data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
++ data[3] = cpu_to_le32(format);
++ data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
++ (count << 16)));
+
+- if ( count & 0x1 ) {
++ if (count & 0x1) {
+ #ifdef __LITTLE_ENDIAN
+- data[dwords-1] &= 0x0000ffff;
++ data[dwords - 1] &= 0x0000ffff;
+ #else
+- data[dwords-1] &= 0xffff0000;
++ data[dwords - 1] &= 0xffff0000;
+ #endif
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+- if ( i < sarea_priv->nbox ) {
+- r128_emit_clip_rects( dev_priv,
+- &sarea_priv->boxes[i],
+- sarea_priv->nbox - i );
++ if (i < sarea_priv->nbox) {
++ r128_emit_clip_rects(dev_priv,
++ &sarea_priv->boxes[i],
++ sarea_priv->nbox - i);
+ }
+
+- r128_cce_dispatch_indirect( dev, buf, start, end );
++ r128_cce_dispatch_indirect(dev, buf, start, end);
+
+ i += 3;
+- } while ( i < sarea_priv->nbox );
++ } while (i < sarea_priv->nbox);
+ }
+
+- if ( buf_priv->discard ) {
++ if (buf_priv->discard) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
+- OUT_RING( buf_priv->age );
++ OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
++ OUT_RING(buf_priv->age);
+
+ ADVANCE_RING();
+
+@@ -788,9 +775,8 @@ static void r128_cce_dispatch_indices( d
+ sarea_priv->nbox = 0;
+ }
+
+-static int r128_cce_dispatch_blit( DRMFILE filp,
+- drm_device_t *dev,
+- drm_r128_blit_t *blit )
++static int r128_cce_dispatch_blit(DRMFILE filp,
++ drm_device_t * dev, drm_r128_blit_t * blit)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+@@ -799,13 +785,13 @@ static int r128_cce_dispatch_blit( DRMFI
+ u32 *data;
+ int dword_shift, dwords;
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ /* The compiler won't optimize away a division by a variable,
+ * even if the only legal values are powers of two. Thus, we'll
+ * use a shift instead.
+ */
+- switch ( blit->format ) {
++ switch (blit->format) {
+ case R128_DATATYPE_ARGB8888:
+ dword_shift = 0;
+ break;
+@@ -821,7 +807,7 @@ static int r128_cce_dispatch_blit( DRMFI
+ dword_shift = 2;
+ break;
+ default:
+- DRM_ERROR( "invalid blit format %d\n", blit->format );
++ DRM_ERROR("invalid blit format %d\n", blit->format);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -830,10 +816,10 @@ static int r128_cce_dispatch_blit( DRMFI
+ * data from the host data blit, otherwise part of the texture
+ * image may be corrupted.
+ */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
+- OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
++ OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
++ OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
+
+ ADVANCE_RING();
+
+@@ -842,13 +828,13 @@ static int r128_cce_dispatch_blit( DRMFI
+ buf = dma->buflist[blit->idx];
+ buf_priv = buf->dev_private;
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", blit->idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", blit->idx);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -856,45 +842,43 @@ static int r128_cce_dispatch_blit( DRMFI
+
+ dwords = (blit->width * blit->height) >> dword_shift;
+
+- data = (u32 *)((char *)dev->agp_buffer_map->handle + buf->offset);
++ data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+
+- data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
+- data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_NONE |
+- (blit->format << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_S |
+- R128_DP_SRC_SOURCE_HOST_DATA |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_AUX_CLIP_DIS |
+- R128_GMC_WR_MSK_DIS) );
+-
+- data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
+- data[3] = cpu_to_le32( 0xffffffff );
+- data[4] = cpu_to_le32( 0xffffffff );
+- data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
+- data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
+- data[7] = cpu_to_le32( dwords );
++ data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
++ data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_NONE |
++ (blit->format << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_S |
++ R128_DP_SRC_SOURCE_HOST_DATA |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
++
++ data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
++ data[3] = cpu_to_le32(0xffffffff);
++ data[4] = cpu_to_le32(0xffffffff);
++ data[5] = cpu_to_le32((blit->y << 16) | blit->x);
++ data[6] = cpu_to_le32((blit->height << 16) | blit->width);
++ data[7] = cpu_to_le32(dwords);
+
+ buf->used = (dwords + 8) * sizeof(u32);
+
+- r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
++ r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
+
+ /* Flush the pixel cache after the blit completes. This ensures
+ * the texture data is written out to memory before rendering
+ * continues.
+ */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
+- OUT_RING( R128_PC_FLUSH_GUI );
++ OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
++ OUT_RING(R128_PC_FLUSH_GUI);
+
+ ADVANCE_RING();
+
+ return 0;
+ }
+
+-
+ /* ================================================================
+ * Tiled depth buffer management
+ *
+@@ -902,8 +886,8 @@ static int r128_cce_dispatch_blit( DRMFI
+ * have hardware stencil support.
+ */
+
+-static int r128_cce_dispatch_write_span( drm_device_t *dev,
+- drm_r128_depth_t *depth )
++static int r128_cce_dispatch_write_span(drm_device_t * dev,
++ drm_r128_depth_t * depth)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, x, y;
+@@ -911,95 +895,95 @@ static int r128_cce_dispatch_write_span(
+ u8 *mask;
+ int i, buffer_size, mask_size;
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ count = depth->n;
+ if (count > 4096 || count <= 0)
+ return DRM_ERR(EMSGSIZE);
+
+- if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
++ if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
+ return DRM_ERR(EFAULT);
+ }
+- if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
++ if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
+ return DRM_ERR(EFAULT);
+ }
+
+ buffer_size = depth->n * sizeof(u32);
+- buffer = drm_alloc( buffer_size, DRM_MEM_BUFS );
+- if ( buffer == NULL )
++ buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
++ if (buffer == NULL)
+ return DRM_ERR(ENOMEM);
+- if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS);
++ if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+
+ mask_size = depth->n * sizeof(u8);
+- if ( depth->mask ) {
+- mask = drm_alloc( mask_size, DRM_MEM_BUFS );
+- if ( mask == NULL ) {
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
++ if (depth->mask) {
++ mask = drm_alloc(mask_size, DRM_MEM_BUFS);
++ if (mask == NULL) {
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ return DRM_ERR(ENOMEM);
+ }
+- if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
+- drm_free( mask, mask_size, DRM_MEM_BUFS );
++ if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
++ drm_free(mask, mask_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+
+- for ( i = 0 ; i < count ; i++, x++ ) {
+- if ( mask[i] ) {
+- BEGIN_RING( 6 );
+-
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->depth_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_WR_MSK_DIS );
++ for (i = 0; i < count; i++, x++) {
++ if (mask[i]) {
++ BEGIN_RING(6);
++
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->depth_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_WR_MSK_DIS);
+
+- OUT_RING( dev_priv->depth_pitch_offset_c );
+- OUT_RING( buffer[i] );
++ OUT_RING(dev_priv->depth_pitch_offset_c);
++ OUT_RING(buffer[i]);
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (1 << 16) | 1 );
++ OUT_RING((x << 16) | y);
++ OUT_RING((1 << 16) | 1);
+
+ ADVANCE_RING();
+ }
+ }
+
+- drm_free( mask, mask_size, DRM_MEM_BUFS );
++ drm_free(mask, mask_size, DRM_MEM_BUFS);
+ } else {
+- for ( i = 0 ; i < count ; i++, x++ ) {
+- BEGIN_RING( 6 );
++ for (i = 0; i < count; i++, x++) {
++ BEGIN_RING(6);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->depth_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_WR_MSK_DIS );
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->depth_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_WR_MSK_DIS);
+
+- OUT_RING( dev_priv->depth_pitch_offset_c );
+- OUT_RING( buffer[i] );
++ OUT_RING(dev_priv->depth_pitch_offset_c);
++ OUT_RING(buffer[i]);
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (1 << 16) | 1 );
++ OUT_RING((x << 16) | y);
++ OUT_RING((1 << 16) | 1);
+
+ ADVANCE_RING();
+ }
+ }
+
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+
+ return 0;
+ }
+
+-static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
+- drm_r128_depth_t *depth )
++static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
++ drm_r128_depth_t * depth)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, *x, *y;
+@@ -1007,7 +991,7 @@ static int r128_cce_dispatch_write_pixel
+ u8 *mask;
+ int i, xbuf_size, ybuf_size, buffer_size, mask_size;
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ count = depth->n;
+ if (count > 4096 || count <= 0)
+@@ -1015,270 +999,266 @@ static int r128_cce_dispatch_write_pixel
+
+ xbuf_size = count * sizeof(*x);
+ ybuf_size = count * sizeof(*y);
+- x = drm_alloc( xbuf_size, DRM_MEM_BUFS );
+- if ( x == NULL ) {
++ x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
++ if (x == NULL) {
+ return DRM_ERR(ENOMEM);
+ }
+- y = drm_alloc( ybuf_size, DRM_MEM_BUFS );
+- if ( y == NULL ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
++ y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
++ if (y == NULL) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ return DRM_ERR(ENOMEM);
+ }
+- if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
++ if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+- if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
++ if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+
+ buffer_size = depth->n * sizeof(u32);
+- buffer = drm_alloc( buffer_size, DRM_MEM_BUFS );
+- if ( buffer == NULL ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
++ buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
++ if (buffer == NULL) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ return DRM_ERR(ENOMEM);
+ }
+- if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
++ if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+
+- if ( depth->mask ) {
++ if (depth->mask) {
+ mask_size = depth->n * sizeof(u8);
+- mask = drm_alloc( mask_size, DRM_MEM_BUFS );
+- if ( mask == NULL ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
++ mask = drm_alloc(mask_size, DRM_MEM_BUFS);
++ if (mask == NULL) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+ return DRM_ERR(ENOMEM);
+ }
+- if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
+- drm_free( mask, mask_size, DRM_MEM_BUFS );
++ if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
++ drm_free(mask, mask_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+
+- for ( i = 0 ; i < count ; i++ ) {
+- if ( mask[i] ) {
+- BEGIN_RING( 6 );
+-
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->depth_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_WR_MSK_DIS );
++ for (i = 0; i < count; i++) {
++ if (mask[i]) {
++ BEGIN_RING(6);
++
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->depth_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_WR_MSK_DIS);
+
+- OUT_RING( dev_priv->depth_pitch_offset_c );
+- OUT_RING( buffer[i] );
++ OUT_RING(dev_priv->depth_pitch_offset_c);
++ OUT_RING(buffer[i]);
+
+- OUT_RING( (x[i] << 16) | y[i] );
+- OUT_RING( (1 << 16) | 1 );
++ OUT_RING((x[i] << 16) | y[i]);
++ OUT_RING((1 << 16) | 1);
+
+ ADVANCE_RING();
+ }
+ }
+
+- drm_free( mask, mask_size, DRM_MEM_BUFS );
++ drm_free(mask, mask_size, DRM_MEM_BUFS);
+ } else {
+- for ( i = 0 ; i < count ; i++ ) {
+- BEGIN_RING( 6 );
++ for (i = 0; i < count; i++) {
++ BEGIN_RING(6);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->depth_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_P |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_WR_MSK_DIS );
++ OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
++ OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->depth_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_P |
++ R128_GMC_CLR_CMP_CNTL_DIS |
++ R128_GMC_WR_MSK_DIS);
+
+- OUT_RING( dev_priv->depth_pitch_offset_c );
+- OUT_RING( buffer[i] );
++ OUT_RING(dev_priv->depth_pitch_offset_c);
++ OUT_RING(buffer[i]);
+
+- OUT_RING( (x[i] << 16) | y[i] );
+- OUT_RING( (1 << 16) | 1 );
++ OUT_RING((x[i] << 16) | y[i]);
++ OUT_RING((1 << 16) | 1);
+
+ ADVANCE_RING();
+ }
+ }
+
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
+- drm_free( buffer, buffer_size, DRM_MEM_BUFS );
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
++ drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+
+ return 0;
+ }
+
+-static int r128_cce_dispatch_read_span( drm_device_t *dev,
+- drm_r128_depth_t *depth )
++static int r128_cce_dispatch_read_span(drm_device_t * dev,
++ drm_r128_depth_t * depth)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, x, y;
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ count = depth->n;
+ if (count > 4096 || count <= 0)
+ return DRM_ERR(EMSGSIZE);
+
+- if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
++ if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
+ return DRM_ERR(EFAULT);
+ }
+- if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
++ if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
+ return DRM_ERR(EFAULT);
+ }
+
+- BEGIN_RING( 7 );
++ BEGIN_RING(7);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
+- OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+- R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_NONE |
+- (dev_priv->depth_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_S |
+- R128_DP_SRC_SOURCE_MEMORY |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_WR_MSK_DIS );
+-
+- OUT_RING( dev_priv->depth_pitch_offset_c );
+- OUT_RING( dev_priv->span_pitch_offset_c );
+-
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (0 << 16) | 0 );
+- OUT_RING( (count << 16) | 1 );
++ OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
++ OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
++ R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_NONE |
++ (dev_priv->depth_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_S |
++ R128_DP_SRC_SOURCE_MEMORY |
++ R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
++
++ OUT_RING(dev_priv->depth_pitch_offset_c);
++ OUT_RING(dev_priv->span_pitch_offset_c);
++
++ OUT_RING((x << 16) | y);
++ OUT_RING((0 << 16) | 0);
++ OUT_RING((count << 16) | 1);
+
+ ADVANCE_RING();
+
+ return 0;
+ }
+
+-static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
+- drm_r128_depth_t *depth )
++static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
++ drm_r128_depth_t * depth)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, *x, *y;
+ int i, xbuf_size, ybuf_size;
+ RING_LOCALS;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ count = depth->n;
+ if (count > 4096 || count <= 0)
+ return DRM_ERR(EMSGSIZE);
+
+- if ( count > dev_priv->depth_pitch ) {
++ if (count > dev_priv->depth_pitch) {
+ count = dev_priv->depth_pitch;
+ }
+
+ xbuf_size = count * sizeof(*x);
+ ybuf_size = count * sizeof(*y);
+- x = drm_alloc( xbuf_size, DRM_MEM_BUFS );
+- if ( x == NULL ) {
++ x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
++ if (x == NULL) {
+ return DRM_ERR(ENOMEM);
+ }
+- y = drm_alloc( ybuf_size, DRM_MEM_BUFS );
+- if ( y == NULL ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
++ y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
++ if (y == NULL) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
+ return DRM_ERR(ENOMEM);
+ }
+- if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
++ if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+- if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) {
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
++ if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+ return DRM_ERR(EFAULT);
+ }
+
+- for ( i = 0 ; i < count ; i++ ) {
+- BEGIN_RING( 7 );
++ for (i = 0; i < count; i++) {
++ BEGIN_RING(7);
+
+- OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
+- OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+- R128_GMC_DST_PITCH_OFFSET_CNTL |
+- R128_GMC_BRUSH_NONE |
+- (dev_priv->depth_fmt << 8) |
+- R128_GMC_SRC_DATATYPE_COLOR |
+- R128_ROP3_S |
+- R128_DP_SRC_SOURCE_MEMORY |
+- R128_GMC_CLR_CMP_CNTL_DIS |
+- R128_GMC_WR_MSK_DIS );
+-
+- OUT_RING( dev_priv->depth_pitch_offset_c );
+- OUT_RING( dev_priv->span_pitch_offset_c );
+-
+- OUT_RING( (x[i] << 16) | y[i] );
+- OUT_RING( (i << 16) | 0 );
+- OUT_RING( (1 << 16) | 1 );
++ OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
++ OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
++ R128_GMC_DST_PITCH_OFFSET_CNTL |
++ R128_GMC_BRUSH_NONE |
++ (dev_priv->depth_fmt << 8) |
++ R128_GMC_SRC_DATATYPE_COLOR |
++ R128_ROP3_S |
++ R128_DP_SRC_SOURCE_MEMORY |
++ R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
++
++ OUT_RING(dev_priv->depth_pitch_offset_c);
++ OUT_RING(dev_priv->span_pitch_offset_c);
++
++ OUT_RING((x[i] << 16) | y[i]);
++ OUT_RING((i << 16) | 0);
++ OUT_RING((1 << 16) | 1);
+
+ ADVANCE_RING();
+ }
+
+- drm_free( x, xbuf_size, DRM_MEM_BUFS );
+- drm_free( y, ybuf_size, DRM_MEM_BUFS );
++ drm_free(x, xbuf_size, DRM_MEM_BUFS);
++ drm_free(y, ybuf_size, DRM_MEM_BUFS);
+
+ return 0;
+ }
+
+-
+ /* ================================================================
+ * Polygon stipple
+ */
+
+-static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
++static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+- BEGIN_RING( 33 );
++ BEGIN_RING(33);
+
+- OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
+- for ( i = 0 ; i < 32 ; i++ ) {
+- OUT_RING( stipple[i] );
++ OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
++ for (i = 0; i < 32; i++) {
++ OUT_RING(stipple[i]);
+ }
+
+ ADVANCE_RING();
+ }
+
+-
+ /* ================================================================
+ * IOCTL functions
+ */
+
+-static int r128_cce_clear( DRM_IOCTL_ARGS )
++static int r128_cce_clear(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_clear_t clear;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t __user *) data,
+- sizeof(clear) );
++ DRM_COPY_FROM_USER_IOCTL(clear, (drm_r128_clear_t __user *) data,
++ sizeof(clear));
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+- r128_cce_dispatch_clear( dev, &clear );
++ r128_cce_dispatch_clear(dev, &clear);
+ COMMIT_RING();
+
+ /* Make sure we restore the 3D state next time.
+@@ -1288,17 +1268,17 @@ static int r128_cce_clear( DRM_IOCTL_ARG
+ return 0;
+ }
+
+-static int r128_do_init_pageflip( drm_device_t *dev )
++static int r128_do_init_pageflip(drm_device_t * dev)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET );
+- dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
++ dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
++ dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
+
+- R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
+- R128_WRITE( R128_CRTC_OFFSET_CNTL,
+- dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
++ R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
++ R128_WRITE(R128_CRTC_OFFSET_CNTL,
++ dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
+
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+@@ -1307,16 +1287,16 @@ static int r128_do_init_pageflip( drm_de
+ return 0;
+ }
+
+-static int r128_do_cleanup_pageflip( drm_device_t *dev )
++static int r128_do_cleanup_pageflip(drm_device_t * dev)
+ {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset );
+- R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
++ R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
++ R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
+
+ if (dev_priv->current_page != 0) {
+- r128_cce_dispatch_flip( dev );
++ r128_cce_dispatch_flip(dev);
+ COMMIT_RING();
+ }
+
+@@ -1325,43 +1305,43 @@ static int r128_do_cleanup_pageflip( drm
+ }
+
+ /* Swapping and flipping are different operations, need different ioctls.
+- * They can & should be intermixed to support multiple 3d windows.
++ * They can & should be intermixed to support multiple 3d windows.
+ */
+
+-static int r128_cce_flip( DRM_IOCTL_ARGS )
++static int r128_cce_flip(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- if (!dev_priv->page_flipping)
+- r128_do_init_pageflip( dev );
++ if (!dev_priv->page_flipping)
++ r128_do_init_pageflip(dev);
+
+- r128_cce_dispatch_flip( dev );
++ r128_cce_dispatch_flip(dev);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int r128_cce_swap( DRM_IOCTL_ARGS )
++static int r128_cce_swap(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+- DRM_DEBUG( "%s\n", __FUNCTION__ );
++ DRM_DEBUG("%s\n", __FUNCTION__);
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+- r128_cce_dispatch_swap( dev );
++ r128_cce_dispatch_swap(dev);
+ dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
+ R128_UPLOAD_MASKS);
+
+@@ -1369,7 +1349,7 @@ static int r128_cce_swap( DRM_IOCTL_ARGS
+ return 0;
+ }
+
+-static int r128_cce_vertex( DRM_IOCTL_ARGS )
++static int r128_cce_vertex(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+@@ -1378,44 +1358,43 @@ static int r128_cce_vertex( DRM_IOCTL_AR
+ drm_r128_buf_priv_t *buf_priv;
+ drm_r128_vertex_t vertex;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t __user *) data,
+- sizeof(vertex) );
++ DRM_COPY_FROM_USER_IOCTL(vertex, (drm_r128_vertex_t __user *) data,
++ sizeof(vertex));
+
+- DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
+- DRM_CURRENTPID,
+- vertex.idx, vertex.count, vertex.discard );
++ DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
++ DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
+
+- if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- vertex.idx, dma->buf_count - 1 );
++ if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ vertex.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+- if ( vertex.prim < 0 ||
+- vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
+- DRM_ERROR( "buffer prim %d\n", vertex.prim );
++ if (vertex.prim < 0 ||
++ vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
++ DRM_ERROR("buffer prim %d\n", vertex.prim);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+ buf = dma->buflist[vertex.idx];
+ buf_priv = buf->dev_private;
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", vertex.idx);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -1423,13 +1402,13 @@ static int r128_cce_vertex( DRM_IOCTL_AR
+ buf_priv->prim = vertex.prim;
+ buf_priv->discard = vertex.discard;
+
+- r128_cce_dispatch_vertex( dev, buf );
++ r128_cce_dispatch_vertex(dev, buf);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int r128_cce_indices( DRM_IOCTL_ARGS )
++static int r128_cce_indices(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+@@ -1439,55 +1418,54 @@ static int r128_cce_indices( DRM_IOCTL_A
+ drm_r128_indices_t elts;
+ int count;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t __user *) data,
+- sizeof(elts) );
++ DRM_COPY_FROM_USER_IOCTL(elts, (drm_r128_indices_t __user *) data,
++ sizeof(elts));
+
+- DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
+- elts.idx, elts.start, elts.end, elts.discard );
++ DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
++ elts.idx, elts.start, elts.end, elts.discard);
+
+- if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- elts.idx, dma->buf_count - 1 );
++ if (elts.idx < 0 || elts.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ elts.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+- if ( elts.prim < 0 ||
+- elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
+- DRM_ERROR( "buffer prim %d\n", elts.prim );
++ if (elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
++ DRM_ERROR("buffer prim %d\n", elts.prim);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+ buf = dma->buflist[elts.idx];
+ buf_priv = buf->dev_private;
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", elts.idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", elts.idx);
+ return DRM_ERR(EINVAL);
+ }
+
+ count = (elts.end - elts.start) / sizeof(u16);
+ elts.start -= R128_INDEX_PRIM_OFFSET;
+
+- if ( elts.start & 0x7 ) {
+- DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
++ if (elts.start & 0x7) {
++ DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
+ return DRM_ERR(EINVAL);
+ }
+- if ( elts.start < buf->used ) {
+- DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
++ if (elts.start < buf->used) {
++ DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -1495,13 +1473,13 @@ static int r128_cce_indices( DRM_IOCTL_A
+ buf_priv->prim = elts.prim;
+ buf_priv->discard = elts.discard;
+
+- r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
++ r128_cce_dispatch_indices(dev, buf, elts.start, elts.end, count);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int r128_cce_blit( DRM_IOCTL_ARGS )
++static int r128_cce_blit(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+@@ -1509,55 +1487,55 @@ static int r128_cce_blit( DRM_IOCTL_ARGS
+ drm_r128_blit_t blit;
+ int ret;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t __user *) data,
+- sizeof(blit) );
++ DRM_COPY_FROM_USER_IOCTL(blit, (drm_r128_blit_t __user *) data,
++ sizeof(blit));
+
+- DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx );
++ DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit.idx);
+
+- if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- blit.idx, dma->buf_count - 1 );
++ if (blit.idx < 0 || blit.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ blit.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+- ret = r128_cce_dispatch_blit( filp, dev, &blit );
++ ret = r128_cce_dispatch_blit(filp, dev, &blit);
+
+ COMMIT_RING();
+ return ret;
+ }
+
+-static int r128_cce_depth( DRM_IOCTL_ARGS )
++static int r128_cce_depth(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_depth_t depth;
+ int ret;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t __user *) data,
+- sizeof(depth) );
++ DRM_COPY_FROM_USER_IOCTL(depth, (drm_r128_depth_t __user *) data,
++ sizeof(depth));
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+ ret = DRM_ERR(EINVAL);
+- switch ( depth.func ) {
++ switch (depth.func) {
+ case R128_WRITE_SPAN:
+- ret = r128_cce_dispatch_write_span( dev, &depth );
++ ret = r128_cce_dispatch_write_span(dev, &depth);
+ break;
+ case R128_WRITE_PIXELS:
+- ret = r128_cce_dispatch_write_pixels( dev, &depth );
++ ret = r128_cce_dispatch_write_pixels(dev, &depth);
+ break;
+ case R128_READ_SPAN:
+- ret = r128_cce_dispatch_read_span( dev, &depth );
++ ret = r128_cce_dispatch_read_span(dev, &depth);
+ break;
+ case R128_READ_PIXELS:
+- ret = r128_cce_dispatch_read_pixels( dev, &depth );
++ ret = r128_cce_dispatch_read_pixels(dev, &depth);
+ break;
+ }
+
+@@ -1565,31 +1543,30 @@ static int r128_cce_depth( DRM_IOCTL_ARG
+ return ret;
+ }
+
+-static int r128_cce_stipple( DRM_IOCTL_ARGS )
++static int r128_cce_stipple(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_stipple_t stipple;
+ u32 mask[32];
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t __user *) data,
+- sizeof(stipple) );
++ DRM_COPY_FROM_USER_IOCTL(stipple, (drm_r128_stipple_t __user *) data,
++ sizeof(stipple));
+
+- if ( DRM_COPY_FROM_USER( &mask, stipple.mask,
+- 32 * sizeof(u32) ) )
+- return DRM_ERR( EFAULT );
++ if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
++ return DRM_ERR(EFAULT);
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- r128_cce_dispatch_stipple( dev, mask );
++ r128_cce_dispatch_stipple(dev, mask);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int r128_cce_indirect( DRM_IOCTL_ARGS )
++static int r128_cce_indirect(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+@@ -1601,47 +1578,46 @@ static int r128_cce_indirect( DRM_IOCTL_
+ RING_LOCALS;
+ #endif
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t __user *) data,
+- sizeof(indirect) );
++ DRM_COPY_FROM_USER_IOCTL(indirect, (drm_r128_indirect_t __user *) data,
++ sizeof(indirect));
+
+- DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+- indirect.idx, indirect.start,
+- indirect.end, indirect.discard );
++ DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
++ indirect.idx, indirect.start, indirect.end, indirect.discard);
+
+- if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- indirect.idx, dma->buf_count - 1 );
++ if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ indirect.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+ buf = dma->buflist[indirect.idx];
+ buf_priv = buf->dev_private;
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", indirect.idx);
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( indirect.start < buf->used ) {
+- DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+- indirect.start, buf->used );
++ if (indirect.start < buf->used) {
++ DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
++ indirect.start, buf->used);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+ buf->used = indirect.end;
+ buf_priv->discard = indirect.discard;
+@@ -1650,7 +1626,7 @@ static int r128_cce_indirect( DRM_IOCTL_
+ /* Wait for the 3D stream to idle before the indirect buffer
+ * containing 2D acceleration commands is processed.
+ */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ #endif
+@@ -1659,30 +1635,30 @@ static int r128_cce_indirect( DRM_IOCTL_
+ * X server. This is insecure and is thus only available to
+ * privileged clients.
+ */
+- r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
++ r128_cce_dispatch_indirect(dev, buf, indirect.start, indirect.end);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int r128_getparam( DRM_IOCTL_ARGS )
++static int r128_getparam(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_getparam_t param;
+ int value;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t __user *)data,
+- sizeof(param) );
++ DRM_COPY_FROM_USER_IOCTL(param, (drm_r128_getparam_t __user *) data,
++ sizeof(param));
+
+- DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
++ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+- switch( param.param ) {
++ switch (param.param) {
+ case R128_PARAM_IRQ_NR:
+ value = dev->irq;
+ break;
+@@ -1690,47 +1666,47 @@ static int r128_getparam( DRM_IOCTL_ARGS
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+- DRM_ERROR( "copy_to_user\n" );
++ if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
++ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+-
++
+ return 0;
+ }
+
+-void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp)
++void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+ {
+- if ( dev->dev_private ) {
++ if (dev->dev_private) {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+- if ( dev_priv->page_flipping ) {
+- r128_do_cleanup_pageflip( dev );
++ if (dev_priv->page_flipping) {
++ r128_do_cleanup_pageflip(dev);
+ }
+- }
++ }
+ }
+
+-void r128_driver_pretakedown(drm_device_t *dev)
++void r128_driver_pretakedown(drm_device_t * dev)
+ {
+- r128_do_cleanup_cce( dev );
++ r128_do_cleanup_cce(dev);
+ }
+
+ drm_ioctl_desc_t r128_ioctls[] = {
+- [DRM_IOCTL_NR(DRM_R128_INIT)] = { r128_cce_init, 1, 1 },
+- [DRM_IOCTL_NR(DRM_R128_CCE_START)] = { r128_cce_start, 1, 1 },
+- [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 },
+- [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 },
+- [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_RESET)] = { r128_engine_reset, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_SWAP)] = { r128_cce_swap, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_FLIP)] = { r128_cce_flip, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_CLEAR)] = { r128_cce_clear, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_VERTEX)] = { r128_cce_vertex, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_INDICES)] = { r128_cce_indices, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_BLIT)] = { r128_cce_blit, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_DEPTH)] = { r128_cce_depth, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 },
+- [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 },
+- [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = { r128_getparam, 1, 0 },
++ [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, 1, 1},
++ [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, 1, 1},
++ [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, 1, 1},
++ [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, 1, 1},
++ [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, 1, 0},
++ [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, 1, 1},
++ [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, 1, 0},
+ };
+
+ int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
+diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
+--- a/drivers/char/drm/r300_cmdbuf.c
++++ b/drivers/char/drm/r300_cmdbuf.c
+@@ -37,7 +37,6 @@
+ #include "radeon_drv.h"
+ #include "r300_reg.h"
+
+-
+ #define R300_SIMULTANEOUS_CLIPRECTS 4
+
+ /* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
+@@ -49,14 +48,12 @@ static const int r300_cliprect_cntl[4] =
+ 0xFFFE
+ };
+
+-
+ /**
+ * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
+ * buffer, starting with index n.
+ */
+-static int r300_emit_cliprects(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf,
+- int n)
++static int r300_emit_cliprects(drm_radeon_private_t * dev_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf, int n)
+ {
+ drm_clip_rect_t box;
+ int nr;
+@@ -70,38 +67,47 @@ static int r300_emit_cliprects(drm_radeo
+ DRM_DEBUG("%i cliprects\n", nr);
+
+ if (nr) {
+- BEGIN_RING(6 + nr*2);
+- OUT_RING( CP_PACKET0( R300_RE_CLIPRECT_TL_0, nr*2 - 1 ) );
++ BEGIN_RING(6 + nr * 2);
++ OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
+
+- for(i = 0; i < nr; ++i) {
+- if (DRM_COPY_FROM_USER_UNCHECKED(&box, &cmdbuf->boxes[n+i], sizeof(box))) {
++ for (i = 0; i < nr; ++i) {
++ if (DRM_COPY_FROM_USER_UNCHECKED
++ (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
+ DRM_ERROR("copy cliprect faulted\n");
+ return DRM_ERR(EFAULT);
+ }
+
+- box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+- box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+- box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+- box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
++ box.x1 =
++ (box.x1 +
++ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
++ box.y1 =
++ (box.y1 +
++ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
++ box.x2 =
++ (box.x2 +
++ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
++ box.y2 =
++ (box.y2 +
++ R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+
+ OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
+- (box.y1 << R300_CLIPRECT_Y_SHIFT));
++ (box.y1 << R300_CLIPRECT_Y_SHIFT));
+ OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
+- (box.y2 << R300_CLIPRECT_Y_SHIFT));
++ (box.y2 << R300_CLIPRECT_Y_SHIFT));
+ }
+
+- OUT_RING_REG( R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr-1] );
++ OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
+
+ /* TODO/SECURITY: Force scissors to a safe value, otherwise the
+- * client might be able to trample over memory.
+- * The impact should be very limited, but I'd rather be safe than
+- * sorry.
+- */
+- OUT_RING( CP_PACKET0( R300_RE_SCISSORS_TL, 1 ) );
+- OUT_RING( 0 );
+- OUT_RING( R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK );
++ * client might be able to trample over memory.
++ * The impact should be very limited, but I'd rather be safe than
++ * sorry.
++ */
++ OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
++ OUT_RING(0);
++ OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
+ ADVANCE_RING();
+- } else {
++ } else {
+ /* Why we allow zero cliprect rendering:
+ * There are some commands in a command buffer that must be submitted
+ * even when there are no cliprects, e.g. DMA buffer discard
+@@ -118,28 +124,27 @@ static int r300_emit_cliprects(drm_radeo
+ * can't produce any fragments.
+ */
+ BEGIN_RING(2);
+- OUT_RING_REG( R300_RE_CLIPRECT_CNTL, 0 );
++ OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
+ ADVANCE_RING();
+- }
++ }
+
+ return 0;
+ }
+
+-u8 r300_reg_flags[0x10000>>2];
+-
++static u8 r300_reg_flags[0x10000 >> 2];
+
+ void r300_init_reg_flags(void)
+ {
+ int i;
+- memset(r300_reg_flags, 0, 0x10000>>2);
+- #define ADD_RANGE_MARK(reg, count,mark) \
++ memset(r300_reg_flags, 0, 0x10000 >> 2);
++#define ADD_RANGE_MARK(reg, count,mark) \
+ for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
+ r300_reg_flags[i]|=(mark);
+-
+- #define MARK_SAFE 1
+- #define MARK_CHECK_OFFSET 2
+-
+- #define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE)
++
++#define MARK_SAFE 1
++#define MARK_CHECK_OFFSET 2
++
++#define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE)
+
+ /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
+ ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
+@@ -193,15 +198,15 @@ void r300_init_reg_flags(void)
+ ADD_RANGE(R300_RB3D_CBLEND, 2);
+ ADD_RANGE(R300_RB3D_COLORMASK, 1);
+ ADD_RANGE(0x4E10, 3);
+- ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */
++ ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */
+ ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
+ ADD_RANGE(0x4E50, 9);
+ ADD_RANGE(0x4E88, 1);
+ ADD_RANGE(0x4EA0, 2);
+ ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
+ ADD_RANGE(0x4F10, 4);
+- ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
+- ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
++ ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
++ ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
+ ADD_RANGE(0x4F28, 1);
+ ADD_RANGE(0x4F30, 2);
+ ADD_RANGE(0x4F44, 1);
+@@ -211,7 +216,7 @@ void r300_init_reg_flags(void)
+ ADD_RANGE(R300_TX_UNK1_0, 16);
+ ADD_RANGE(R300_TX_SIZE_0, 16);
+ ADD_RANGE(R300_TX_FORMAT_0, 16);
+- /* Texture offset is dangerous and needs more checking */
++ /* Texture offset is dangerous and needs more checking */
+ ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
+ ADD_RANGE(R300_TX_UNK4_0, 16);
+ ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
+@@ -224,33 +229,41 @@ void r300_init_reg_flags(void)
+
+ }
+
+-static __inline__ int r300_check_range(unsigned reg, int count)
++static __inline__ int r300_check_range(unsigned reg, int count)
+ {
+ int i;
+- if(reg & ~0xffff)return -1;
+- for(i=(reg>>2);i<(reg>>2)+count;i++)
+- if(r300_reg_flags[i]!=MARK_SAFE)return 1;
++ if (reg & ~0xffff)
++ return -1;
++ for (i = (reg >> 2); i < (reg >> 2) + count; i++)
++ if (r300_reg_flags[i] != MARK_SAFE)
++ return 1;
+ return 0;
+ }
+
+ /* we expect offsets passed to the framebuffer to be either within video memory or
+- within AGP space */
+-static __inline__ int r300_check_offset(drm_radeon_private_t* dev_priv, u32 offset)
++ within AGP space */
++static __inline__ int r300_check_offset(drm_radeon_private_t * dev_priv,
++ u32 offset)
+ {
+ /* we realy want to check against end of video aperture
+- but this value is not being kept.
+- This code is correct for now (does the same thing as the
+- code that sets MC_FB_LOCATION) in radeon_cp.c */
+- if((offset>=dev_priv->fb_location) &&
+- (offset<dev_priv->gart_vm_start))return 0;
+- if((offset>=dev_priv->gart_vm_start) &&
+- (offset<dev_priv->gart_vm_start+dev_priv->gart_size))return 0;
++ but this value is not being kept.
++ This code is correct for now (does the same thing as the
++ code that sets MC_FB_LOCATION) in radeon_cp.c */
++ if ((offset >= dev_priv->fb_location) &&
++ (offset < dev_priv->gart_vm_start))
++ return 0;
++ if ((offset >= dev_priv->gart_vm_start) &&
++ (offset < dev_priv->gart_vm_start + dev_priv->gart_size))
++ return 0;
+ return 1;
+ }
+
+-static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf,
+- drm_r300_cmd_header_t header)
++static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
++ dev_priv,
++ drm_radeon_kcmd_buffer_t
++ * cmdbuf,
++ drm_r300_cmd_header_t
++ header)
+ {
+ int reg;
+ int sz;
+@@ -260,35 +273,40 @@ static __inline__ int r300_emit_carefull
+
+ sz = header.packet0.count;
+ reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+-
+- if((sz>64)||(sz<0)){
+- DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", reg, sz);
++
++ if ((sz > 64) || (sz < 0)) {
++ DRM_ERROR
++ ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
++ reg, sz);
+ return DRM_ERR(EINVAL);
+- }
+- for(i=0;i<sz;i++){
+- values[i]=((int __user*)cmdbuf->buf)[i];
+- switch(r300_reg_flags[(reg>>2)+i]){
++ }
++ for (i = 0; i < sz; i++) {
++ values[i] = ((int *)cmdbuf->buf)[i];
++ switch (r300_reg_flags[(reg >> 2) + i]) {
+ case MARK_SAFE:
+ break;
+ case MARK_CHECK_OFFSET:
+- if(r300_check_offset(dev_priv, (u32)values[i])){
+- DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n", reg, sz);
++ if (r300_check_offset(dev_priv, (u32) values[i])) {
++ DRM_ERROR
++ ("Offset failed range check (reg=%04x sz=%d)\n",
++ reg, sz);
+ return DRM_ERR(EINVAL);
+- }
++ }
+ break;
+ default:
+- DRM_ERROR("Register %04x failed check as flag=%02x\n", reg+i*4, r300_reg_flags[(reg>>2)+i]);
++ DRM_ERROR("Register %04x failed check as flag=%02x\n",
++ reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
+ return DRM_ERR(EINVAL);
+- }
+ }
+-
+- BEGIN_RING(1+sz);
+- OUT_RING( CP_PACKET0( reg, sz-1 ) );
+- OUT_RING_TABLE( values, sz );
++ }
++
++ BEGIN_RING(1 + sz);
++ OUT_RING(CP_PACKET0(reg, sz - 1));
++ OUT_RING_TABLE(values, sz);
+ ADVANCE_RING();
+
+- cmdbuf->buf += sz*4;
+- cmdbuf->bufsz -= sz*4;
++ cmdbuf->buf += sz * 4;
++ cmdbuf->bufsz -= sz * 4;
+
+ return 0;
+ }
+@@ -299,9 +317,9 @@ static __inline__ int r300_emit_carefull
+ *
+ * Note that checks are performed on contents and addresses of the registers
+ */
+-static __inline__ int r300_emit_packet0(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf,
+- drm_r300_cmd_header_t header)
++static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf,
++ drm_r300_cmd_header_t header)
+ {
+ int reg;
+ int sz;
+@@ -313,39 +331,40 @@ static __inline__ int r300_emit_packet0(
+ if (!sz)
+ return 0;
+
+- if (sz*4 > cmdbuf->bufsz)
++ if (sz * 4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+-
+- if (reg+sz*4 >= 0x10000){
+- DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, sz);
++
++ if (reg + sz * 4 >= 0x10000) {
++ DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
++ sz);
+ return DRM_ERR(EINVAL);
+- }
++ }
+
+- if(r300_check_range(reg, sz)){
++ if (r300_check_range(reg, sz)) {
+ /* go and check everything */
+- return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf, header);
+- }
++ return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
++ header);
++ }
+ /* the rest of the data is safe to emit, whatever the values the user passed */
+
+- BEGIN_RING(1+sz);
+- OUT_RING( CP_PACKET0( reg, sz-1 ) );
+- OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz );
++ BEGIN_RING(1 + sz);
++ OUT_RING(CP_PACKET0(reg, sz - 1));
++ OUT_RING_TABLE((int *)cmdbuf->buf, sz);
+ ADVANCE_RING();
+
+- cmdbuf->buf += sz*4;
+- cmdbuf->bufsz -= sz*4;
++ cmdbuf->buf += sz * 4;
++ cmdbuf->bufsz -= sz * 4;
+
+ return 0;
+ }
+
+-
+ /**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+-static __inline__ int r300_emit_vpu(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf,
++static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf,
+ drm_r300_cmd_header_t header)
+ {
+ int sz;
+@@ -357,114 +376,121 @@ static __inline__ int r300_emit_vpu(drm_
+
+ if (!sz)
+ return 0;
+- if (sz*16 > cmdbuf->bufsz)
++ if (sz * 16 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+- BEGIN_RING(5+sz*4);
++ BEGIN_RING(5 + sz * 4);
+ /* Wait for VAP to come to senses.. */
+ /* there is no need to emit it multiple times, (only once before VAP is programmed,
+ but this optimization is for later */
+- OUT_RING_REG( R300_VAP_PVS_WAITIDLE, 0 );
+- OUT_RING_REG( R300_VAP_PVS_UPLOAD_ADDRESS, addr );
+- OUT_RING( CP_PACKET0_TABLE( R300_VAP_PVS_UPLOAD_DATA, sz*4 - 1 ) );
+- OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz*4 );
++ OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
++ OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
++ OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
++ OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
+
+ ADVANCE_RING();
+
+- cmdbuf->buf += sz*16;
+- cmdbuf->bufsz -= sz*16;
++ cmdbuf->buf += sz * 16;
++ cmdbuf->bufsz -= sz * 16;
+
+ return 0;
+ }
+
+-
+ /**
+ * Emit a clear packet from userspace.
+ * Called by r300_emit_packet3.
+ */
+-static __inline__ int r300_emit_clear(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf)
++static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf)
+ {
+ RING_LOCALS;
+
+- if (8*4 > cmdbuf->bufsz)
++ if (8 * 4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+ BEGIN_RING(10);
+- OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 8 ) );
+- OUT_RING( R300_PRIM_TYPE_POINT|R300_PRIM_WALK_RING|
+- (1<<R300_PRIM_NUM_VERTICES_SHIFT) );
+- OUT_RING_TABLE( (int __user*)cmdbuf->buf, 8 );
++ OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
++ OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
++ (1 << R300_PRIM_NUM_VERTICES_SHIFT));
++ OUT_RING_TABLE((int *)cmdbuf->buf, 8);
+ ADVANCE_RING();
+
+- cmdbuf->buf += 8*4;
+- cmdbuf->bufsz -= 8*4;
++ cmdbuf->buf += 8 * 4;
++ cmdbuf->bufsz -= 8 * 4;
+
+ return 0;
+ }
+
+-static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf,
+- u32 header)
++static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf,
++ u32 header)
+ {
+- int count, i,k;
+- #define MAX_ARRAY_PACKET 64
++ int count, i, k;
++#define MAX_ARRAY_PACKET 64
+ u32 payload[MAX_ARRAY_PACKET];
+ u32 narrays;
+ RING_LOCALS;
+
+- count=(header>>16) & 0x3fff;
+-
+- if((count+1)>MAX_ARRAY_PACKET){
+- DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", count);
++ count = (header >> 16) & 0x3fff;
++
++ if ((count + 1) > MAX_ARRAY_PACKET) {
++ DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
++ count);
+ return DRM_ERR(EINVAL);
+- }
+- memset(payload, 0, MAX_ARRAY_PACKET*4);
+- memcpy(payload, cmdbuf->buf+4, (count+1)*4);
+-
++ }
++ memset(payload, 0, MAX_ARRAY_PACKET * 4);
++ memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
++
+ /* carefully check packet contents */
+-
+- narrays=payload[0];
+- k=0;
+- i=1;
+- while((k<narrays) && (i<(count+1))){
+- i++; /* skip attribute field */
+- if(r300_check_offset(dev_priv, payload[i])){
+- DRM_ERROR("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", k, i);
++
++ narrays = payload[0];
++ k = 0;
++ i = 1;
++ while ((k < narrays) && (i < (count + 1))) {
++ i++; /* skip attribute field */
++ if (r300_check_offset(dev_priv, payload[i])) {
++ DRM_ERROR
++ ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
++ k, i);
+ return DRM_ERR(EINVAL);
+- }
++ }
+ k++;
+ i++;
+- if(k==narrays)break;
++ if (k == narrays)
++ break;
+ /* have one more to process, they come in pairs */
+- if(r300_check_offset(dev_priv, payload[i])){
+- DRM_ERROR("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", k, i);
++ if (r300_check_offset(dev_priv, payload[i])) {
++ DRM_ERROR
++ ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
++ k, i);
+ return DRM_ERR(EINVAL);
+- }
+- k++;
+- i++;
+ }
++ k++;
++ i++;
++ }
+ /* do the counts match what we expect ? */
+- if((k!=narrays) || (i!=(count+1))){
+- DRM_ERROR("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", k, i, narrays, count+1);
++ if ((k != narrays) || (i != (count + 1))) {
++ DRM_ERROR
++ ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
++ k, i, narrays, count + 1);
+ return DRM_ERR(EINVAL);
+- }
++ }
+
+ /* all clear, output packet */
+
+- BEGIN_RING(count+2);
++ BEGIN_RING(count + 2);
+ OUT_RING(header);
+- OUT_RING_TABLE(payload, count+1);
++ OUT_RING_TABLE(payload, count + 1);
+ ADVANCE_RING();
+
+- cmdbuf->buf += (count+2)*4;
+- cmdbuf->bufsz -= (count+2)*4;
++ cmdbuf->buf += (count + 2) * 4;
++ cmdbuf->bufsz -= (count + 2) * 4;
+
+ return 0;
+ }
+
+-static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf)
++static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf)
+ {
+ u32 header;
+ int count;
+@@ -473,36 +499,37 @@ static __inline__ int r300_emit_raw_pack
+ if (4 > cmdbuf->bufsz)
+ return DRM_ERR(EINVAL);
+
+- /* Fixme !! This simply emits a packet without much checking.
++ /* Fixme !! This simply emits a packet without much checking.
+ We need to be smarter. */
+
+ /* obtain first word - actual packet3 header */
+- header = *(u32 __user*)cmdbuf->buf;
++ header = *(u32 *) cmdbuf->buf;
+
+ /* Is it packet 3 ? */
+- if( (header>>30)!=0x3 ) {
++ if ((header >> 30) != 0x3) {
+ DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
+ return DRM_ERR(EINVAL);
+- }
++ }
+
+- count=(header>>16) & 0x3fff;
++ count = (header >> 16) & 0x3fff;
+
+ /* Check again now that we know how much data to expect */
+- if ((count+2)*4 > cmdbuf->bufsz){
+- DRM_ERROR("Expected packet3 of length %d but have only %d bytes left\n",
+- (count+2)*4, cmdbuf->bufsz);
++ if ((count + 2) * 4 > cmdbuf->bufsz) {
++ DRM_ERROR
++ ("Expected packet3 of length %d but have only %d bytes left\n",
++ (count + 2) * 4, cmdbuf->bufsz);
+ return DRM_ERR(EINVAL);
+- }
++ }
+
+ /* Is it a packet type we know about ? */
+- switch(header & 0xff00){
+- case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
++ switch (header & 0xff00) {
++ case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
+ return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
+
+- case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
+- case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
+- case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
+- case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
++ case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
++ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
++ case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
++ case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
+ case RADEON_WAIT_FOR_IDLE:
+ case RADEON_CP_NOP:
+ /* these packets are safe */
+@@ -510,32 +537,30 @@ static __inline__ int r300_emit_raw_pack
+ default:
+ DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
+ return DRM_ERR(EINVAL);
+- }
+-
++ }
+
+- BEGIN_RING(count+2);
++ BEGIN_RING(count + 2);
+ OUT_RING(header);
+- OUT_RING_TABLE( (int __user*)(cmdbuf->buf+4), count+1);
++ OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+ ADVANCE_RING();
+
+- cmdbuf->buf += (count+2)*4;
+- cmdbuf->bufsz -= (count+2)*4;
++ cmdbuf->buf += (count + 2) * 4;
++ cmdbuf->bufsz -= (count + 2) * 4;
+
+ return 0;
+ }
+
+-
+ /**
+ * Emit a rendering packet3 from userspace.
+ * Called by r300_do_cp_cmdbuf.
+ */
+-static __inline__ int r300_emit_packet3(drm_radeon_private_t* dev_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf,
++static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf,
+ drm_r300_cmd_header_t header)
+ {
+ int n;
+ int ret;
+- char __user* orig_buf = cmdbuf->buf;
++ char *orig_buf = cmdbuf->buf;
+ int orig_bufsz = cmdbuf->bufsz;
+
+ /* This is a do-while-loop so that we run the interior at least once,
+@@ -550,16 +575,16 @@ static __inline__ int r300_emit_packet3(
+
+ cmdbuf->buf = orig_buf;
+ cmdbuf->bufsz = orig_bufsz;
+- }
++ }
+
+- switch(header.packet3.packet) {
++ switch (header.packet3.packet) {
+ case R300_CMD_PACKET3_CLEAR:
+ DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
+ ret = r300_emit_clear(dev_priv, cmdbuf);
+ if (ret) {
+ DRM_ERROR("r300_emit_clear failed\n");
+ return ret;
+- }
++ }
+ break;
+
+ case R300_CMD_PACKET3_RAW:
+@@ -568,18 +593,18 @@ static __inline__ int r300_emit_packet3(
+ if (ret) {
+ DRM_ERROR("r300_emit_raw_packet3 failed\n");
+ return ret;
+- }
++ }
+ break;
+
+ default:
+ DRM_ERROR("bad packet3 type %i at %p\n",
+- header.packet3.packet,
+- cmdbuf->buf - sizeof(header));
++ header.packet3.packet,
++ cmdbuf->buf - sizeof(header));
+ return DRM_ERR(EINVAL);
+- }
++ }
+
+ n += R300_SIMULTANEOUS_CLIPRECTS;
+- } while(n < cmdbuf->nbox);
++ } while (n < cmdbuf->nbox);
+
+ return 0;
+ }
+@@ -598,21 +623,20 @@ static __inline__ int r300_emit_packet3(
+ /**
+ * Emit the sequence to pacify R300.
+ */
+-static __inline__ void r300_pacify(drm_radeon_private_t* dev_priv)
++static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv)
+ {
+ RING_LOCALS;
+
+ BEGIN_RING(6);
+- OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) );
+- OUT_RING( 0xa );
+- OUT_RING( CP_PACKET0( 0x4f18, 0 ) );
+- OUT_RING( 0x3 );
+- OUT_RING( CP_PACKET3( RADEON_CP_NOP, 0 ) );
+- OUT_RING( 0x0 );
++ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
++ OUT_RING(0xa);
++ OUT_RING(CP_PACKET0(0x4f18, 0));
++ OUT_RING(0x3);
++ OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
++ OUT_RING(0x0);
+ ADVANCE_RING();
+ }
+
+-
+ /**
+ * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
+ * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
+@@ -628,20 +652,18 @@ static void r300_discard_buffer(drm_devi
+ buf->used = 0;
+ }
+
+-
+ /**
+ * Parses and validates a user-supplied command buffer and emits appropriate
+ * commands on the DMA ring buffer.
+ * Called by the ioctl handler function radeon_cp_cmdbuf.
+ */
+-int r300_do_cp_cmdbuf(drm_device_t* dev,
+- DRMFILE filp,
+- drm_file_t* filp_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf)
++int r300_do_cp_cmdbuf(drm_device_t * dev,
++ DRMFILE filp,
++ drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- drm_device_dma_t *dma = dev->dma;
+- drm_buf_t *buf = NULL;
++ drm_device_dma_t *dma = dev->dma;
++ drm_buf_t *buf = NULL;
+ int emit_dispatch_age = 0;
+ int ret = 0;
+
+@@ -655,9 +677,9 @@ int r300_do_cp_cmdbuf(drm_device_t* dev,
+ ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
+ if (ret)
+ goto cleanup;
+- }
++ }
+
+- while(cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
++ while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
+ int idx;
+ drm_r300_cmd_header_t header;
+
+@@ -666,14 +688,14 @@ int r300_do_cp_cmdbuf(drm_device_t* dev,
+ cmdbuf->buf += sizeof(header);
+ cmdbuf->bufsz -= sizeof(header);
+
+- switch(header.header.cmd_type) {
+- case R300_CMD_PACKET0:
++ switch (header.header.cmd_type) {
++ case R300_CMD_PACKET0:
+ DRM_DEBUG("R300_CMD_PACKET0\n");
+ ret = r300_emit_packet0(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_emit_packet0 failed\n");
+ goto cleanup;
+- }
++ }
+ break;
+
+ case R300_CMD_VPU:
+@@ -682,7 +704,7 @@ int r300_do_cp_cmdbuf(drm_device_t* dev,
+ if (ret) {
+ DRM_ERROR("r300_emit_vpu failed\n");
+ goto cleanup;
+- }
++ }
+ break;
+
+ case R300_CMD_PACKET3:
+@@ -691,26 +713,26 @@ int r300_do_cp_cmdbuf(drm_device_t* dev,
+ if (ret) {
+ DRM_ERROR("r300_emit_packet3 failed\n");
+ goto cleanup;
+- }
++ }
+ break;
+
+ case R300_CMD_END3D:
+ DRM_DEBUG("R300_CMD_END3D\n");
+- /* TODO:
+- Ideally userspace driver should not need to issue this call,
+- i.e. the drm driver should issue it automatically and prevent
+- lockups.
+-
+- In practice, we do not understand why this call is needed and what
+- it does (except for some vague guesses that it has to do with cache
+- coherence) and so the user space driver does it.
+-
+- Once we are sure which uses prevent lockups the code could be moved
+- into the kernel and the userspace driver will not
+- need to use this command.
++ /* TODO:
++ Ideally userspace driver should not need to issue this call,
++ i.e. the drm driver should issue it automatically and prevent
++ lockups.
++
++ In practice, we do not understand why this call is needed and what
++ it does (except for some vague guesses that it has to do with cache
++ coherence) and so the user space driver does it.
++
++ Once we are sure which uses prevent lockups the code could be moved
++ into the kernel and the userspace driver will not
++ need to use this command.
+
+- Note that issuing this command does not hurt anything
+- except, possibly, performance */
++ Note that issuing this command does not hurt anything
++ except, possibly, performance */
+ r300_pacify(dev_priv);
+ break;
+
+@@ -722,7 +744,7 @@ int r300_do_cp_cmdbuf(drm_device_t* dev,
+ RING_LOCALS;
+
+ BEGIN_RING(header.delay.count);
+- for(i=0;i<header.delay.count;i++)
++ for (i = 0; i < header.delay.count; i++)
+ OUT_RING(RADEON_CP_PACKET2);
+ ADVANCE_RING();
+ }
+@@ -730,53 +752,54 @@ int r300_do_cp_cmdbuf(drm_device_t* dev,
+
+ case R300_CMD_DMA_DISCARD:
+ DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+- idx = header.dma.buf_idx;
+- if (idx < 0 || idx >= dma->buf_count) {
+- DRM_ERROR("buffer index %d (of %d max)\n",
+- idx, dma->buf_count - 1);
++ idx = header.dma.buf_idx;
++ if (idx < 0 || idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ idx, dma->buf_count - 1);
+ ret = DRM_ERR(EINVAL);
+- goto cleanup;
+- }
++ goto cleanup;
++ }
+
+- buf = dma->buflist[idx];
+- if (buf->filp != filp || buf->pending) {
+- DRM_ERROR("bad buffer %p %p %d\n",
+- buf->filp, filp, buf->pending);
+- ret = DRM_ERR(EINVAL);
++ buf = dma->buflist[idx];
++ if (buf->filp != filp || buf->pending) {
++ DRM_ERROR("bad buffer %p %p %d\n",
++ buf->filp, filp, buf->pending);
++ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+- }
++ }
+
+ emit_dispatch_age = 1;
+ r300_discard_buffer(dev, buf);
+- break;
++ break;
+
+ case R300_CMD_WAIT:
+ /* simple enough, we can do it here */
+ DRM_DEBUG("R300_CMD_WAIT\n");
+- if(header.wait.flags==0)break; /* nothing to do */
++ if (header.wait.flags == 0)
++ break; /* nothing to do */
+
+ {
+ RING_LOCALS;
+
+ BEGIN_RING(2);
+- OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );
+- OUT_RING( (header.wait.flags & 0xf)<<14 );
++ OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
++ OUT_RING((header.wait.flags & 0xf) << 14);
+ ADVANCE_RING();
+ }
+ break;
+
+ default:
+ DRM_ERROR("bad cmd_type %i at %p\n",
+- header.header.cmd_type,
++ header.header.cmd_type,
+ cmdbuf->buf - sizeof(header));
+ ret = DRM_ERR(EINVAL);
+ goto cleanup;
+- }
++ }
+ }
+
+ DRM_DEBUG("END\n");
+
+-cleanup:
++ cleanup:
+ r300_pacify(dev_priv);
+
+ /* We emit the vertex buffer age here, outside the pacifier "brackets"
+@@ -792,10 +815,9 @@ cleanup:
+ BEGIN_RING(2);
+ RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
+ ADVANCE_RING();
+- }
++ }
+
+ COMMIT_RING();
+
+ return ret;
+ }
+-
+diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
+--- a/drivers/char/drm/r300_reg.h
++++ b/drivers/char/drm/r300_reg.h
+@@ -36,7 +36,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
+ # define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24
+ # define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28
+
+-
+ #define R300_MC_INIT_GFX_LAT_TIMER 0x154
+ # define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0
+ # define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4
+@@ -62,7 +61,6 @@ I am fairly certain that they are correc
+ #define R300_SE_VPORT_ZSCALE 0x1DA8
+ #define R300_SE_VPORT_ZOFFSET 0x1DAC
+
+-
+ /* This register is written directly and also starts data section in many 3d CP_PACKET3's */
+ #define R300_VAP_VF_CNTL 0x2084
+
+@@ -93,17 +91,17 @@ I am fairly certain that they are correc
+
+ /* index size - when not set the indices are assumed to be 16 bit */
+ # define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11)
+- /* number of vertices */
++ /* number of vertices */
+ # define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16
+
+ /* BEGIN: Wild guesses */
+ #define R300_VAP_OUTPUT_VTX_FMT_0 0x2090
+ # define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0)
+ # define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT (1<<1)
+-# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */
+-# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */
+-# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */
+-# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
++# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2) /* GUESS */
++# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3) /* GUESS */
++# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4) /* GUESS */
++# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
+
+ #define R300_VAP_OUTPUT_VTX_FMT_1 0x2094
+ # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+@@ -159,14 +157,14 @@ I am fairly certain that they are correc
+ # define R300_INPUT_ROUTE_COMPONENTS_2 (1 << 0)
+ # define R300_INPUT_ROUTE_COMPONENTS_3 (2 << 0)
+ # define R300_INPUT_ROUTE_COMPONENTS_4 (3 << 0)
+-# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */
++# define R300_INPUT_ROUTE_COMPONENTS_RGBA (4 << 0) /* GUESS */
+ # define R300_VAP_INPUT_ROUTE_IDX_SHIFT 8
+-# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */
++# define R300_VAP_INPUT_ROUTE_IDX_MASK (31 << 8) /* GUESS */
+ # define R300_VAP_INPUT_ROUTE_END (1 << 13)
+-# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */
+-# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */
+-# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */
+-# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */
++# define R300_INPUT_ROUTE_IMMEDIATE_MODE (0 << 14) /* GUESS */
++# define R300_INPUT_ROUTE_FLOAT (1 << 14) /* GUESS */
++# define R300_INPUT_ROUTE_UNSIGNED_BYTE (2 << 14) /* GUESS */
++# define R300_INPUT_ROUTE_FLOAT_COLOR (3 << 14) /* GUESS */
+ #define R300_VAP_INPUT_ROUTE_0_1 0x2154
+ #define R300_VAP_INPUT_ROUTE_0_2 0x2158
+ #define R300_VAP_INPUT_ROUTE_0_3 0x215C
+@@ -188,12 +186,12 @@ I am fairly certain that they are correc
+ # define R300_INPUT_CNTL_COLOR 0x00000004
+ # define R300_INPUT_CNTL_TC0 0x00000400
+ # define R300_INPUT_CNTL_TC1 0x00000800
+-# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */
+-# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */
+-# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */
+-# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */
+-# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */
+-# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */
++# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */
++# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */
++# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */
++# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */
++# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */
++# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */
+
+ /* gap */
+ /* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
+@@ -270,12 +268,12 @@ I am fairly certain that they are correc
+ // rendering commands and overwriting vertex program parameters.
+ // Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
+ // avoids bugs caused by still running shaders reading bad data from memory. */
+-#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
++#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */
+
+ /* Absolutely no clue what this register is about. */
+ #define R300_VAP_UNKNOWN_2288 0x2288
+-# define R300_2288_R300 0x00750000 /* -- nh */
+-# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
++# define R300_2288_R300 0x00750000 /* -- nh */
++# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
+
+ /* gap */
+ /* Addresses are relative to the vertex program instruction area of the
+@@ -286,10 +284,10 @@ I am fairly certain that they are correc
+ // experiments so far have shown that both *must* point to an instruction
+ // inside the vertex program, otherwise the GPU locks up.
+ // fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
+-// CNTL_1_UNKNOWN points to instruction where last write to position takes place.
++// CNTL_1_UNKNOWN points to instruction where last write to position takes place.
+ // Most likely this is used to ignore rest of the program in cases where group of verts arent visible.
+ // For some reason this "section" is sometimes accepted other instruction that have
+-// no relationship with position calculations.
++// no relationship with position calculations.
+ */
+ #define R300_VAP_PVS_CNTL_1 0x22D0
+ # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
+@@ -308,13 +306,13 @@ I am fairly certain that they are correc
+ #define R300_VAP_VTX_COLOR_R 0x2464
+ #define R300_VAP_VTX_COLOR_G 0x2468
+ #define R300_VAP_VTX_COLOR_B 0x246C
+-#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */
++#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */
+ #define R300_VAP_VTX_POS_0_Y_1 0x2494
+-#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */
+-#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */
++#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */
++#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */
+ #define R300_VAP_VTX_POS_0_Y_2 0x24A4
+ #define R300_VAP_VTX_POS_0_Z_2 0x24A8
+-#define R300_VAP_VTX_END_OF_PKT 0x24AC /* write 0 to indicate end of packet? */
++#define R300_VAP_VTX_END_OF_PKT 0x24AC /* write 0 to indicate end of packet? */
+
+ /* gap */
+
+@@ -385,7 +383,6 @@ I am fairly certain that they are correc
+ # define R300_GB_MSPOS1__MS_Y5_SHIFT 20
+ # define R300_GB_MSPOS1__MSBD1 24
+
+-
+ #define R300_GB_TILE_CONFIG 0x4018
+ # define R300_GB_TILE_ENABLE (1<<0)
+ # define R300_GB_TILE_PIPE_COUNT_RV300 0
+@@ -478,9 +475,9 @@ I am fairly certain that they are correc
+ // framebuffer. */
+ #define R300_RE_POINTSIZE 0x421C
+ # define R300_POINTSIZE_Y_SHIFT 0
+-# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */
++# define R300_POINTSIZE_Y_MASK (0xFFFF << 0) /* GUESS */
+ # define R300_POINTSIZE_X_SHIFT 16
+-# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */
++# define R300_POINTSIZE_X_MASK (0xFFFF << 16) /* GUESS */
+ # define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6)
+
+ /* The line width is given in multiples of 6.
+@@ -491,7 +488,7 @@ I am fairly certain that they are correc
+ */
+ #define R300_RE_LINE_CNT 0x4234
+ # define R300_LINESIZE_SHIFT 0
+-# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */
++# define R300_LINESIZE_MASK (0xFFFF << 0) /* GUESS */
+ # define R300_LINESIZE_MAX (R300_LINESIZE_MASK / 6)
+ # define R300_LINE_CNT_HO (1 << 16)
+ # define R300_LINE_CNT_VE (1 << 17)
+@@ -513,8 +510,8 @@ I am fairly certain that they are correc
+ # define R300_PM_BACK_LINE (1 << 7)
+ # define R300_PM_BACK_FILL (1 << 8)
+
+-/* Not sure why there are duplicate of factor and constant values.
+- My best guess so far is that there are seperate zbiases for test and write.
++/* Not sure why there are duplicate of factor and constant values.
++ My best guess so far is that there are seperate zbiases for test and write.
+ Ordering might be wrong.
+ Some of the tests indicate that fgl has a fallback implementation of zbias
+ via pixel shaders. */
+@@ -540,7 +537,6 @@ I am fairly certain that they are correc
+ # define R300_FRONT_FACE_CCW (0 << 2)
+ # define R300_FRONT_FACE_CW (1 << 2)
+
+-
+ /* BEGIN: Rasterization / Interpolators - many guesses
+ // 0_UNKNOWN_18 has always been set except for clear operations.
+ // TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
+@@ -548,7 +544,7 @@ I am fairly certain that they are correc
+ #define R300_RS_CNTL_0 0x4300
+ # define R300_RS_CNTL_TC_CNT_SHIFT 2
+ # define R300_RS_CNTL_TC_CNT_MASK (7 << 2)
+-# define R300_RS_CNTL_CI_CNT_SHIFT 7 /* number of color interpolators used */
++# define R300_RS_CNTL_CI_CNT_SHIFT 7 /* number of color interpolators used */
+ # define R300_RS_CNTL_0_UNKNOWN_18 (1 << 18)
+ /* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n register. */
+ #define R300_RS_CNTL_1 0x4304
+@@ -585,29 +581,29 @@ I am fairly certain that they are correc
+ #define R300_RS_ROUTE_0 0x4330
+ #define R300_RS_ROUTE_1 0x4334
+ #define R300_RS_ROUTE_2 0x4338
+-#define R300_RS_ROUTE_3 0x433C /* GUESS */
+-#define R300_RS_ROUTE_4 0x4340 /* GUESS */
+-#define R300_RS_ROUTE_5 0x4344 /* GUESS */
+-#define R300_RS_ROUTE_6 0x4348 /* GUESS */
+-#define R300_RS_ROUTE_7 0x434C /* GUESS */
++#define R300_RS_ROUTE_3 0x433C /* GUESS */
++#define R300_RS_ROUTE_4 0x4340 /* GUESS */
++#define R300_RS_ROUTE_5 0x4344 /* GUESS */
++#define R300_RS_ROUTE_6 0x4348 /* GUESS */
++#define R300_RS_ROUTE_7 0x434C /* GUESS */
+ # define R300_RS_ROUTE_SOURCE_INTERP_0 0
+ # define R300_RS_ROUTE_SOURCE_INTERP_1 1
+ # define R300_RS_ROUTE_SOURCE_INTERP_2 2
+ # define R300_RS_ROUTE_SOURCE_INTERP_3 3
+ # define R300_RS_ROUTE_SOURCE_INTERP_4 4
+-# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */
+-# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */
+-# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */
+-# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */
++# define R300_RS_ROUTE_SOURCE_INTERP_5 5 /* GUESS */
++# define R300_RS_ROUTE_SOURCE_INTERP_6 6 /* GUESS */
++# define R300_RS_ROUTE_SOURCE_INTERP_7 7 /* GUESS */
++# define R300_RS_ROUTE_ENABLE (1 << 3) /* GUESS */
+ # define R300_RS_ROUTE_DEST_SHIFT 6
+-# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */
++# define R300_RS_ROUTE_DEST_MASK (31 << 6) /* GUESS */
+
+ /* Special handling for color: When the fragment program uses color,
+ // the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
+ // color register index. */
+ # define R300_RS_ROUTE_0_COLOR (1 << 14)
+ # define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17
+-# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */
++# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */
+ /* As above, but for secondary color */
+ # define R300_RS_ROUTE_1_COLOR1 (1 << 14)
+ # define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17
+@@ -721,7 +717,7 @@ I am fairly certain that they are correc
+ # define R300_TX_HEIGHTMASK_SHIFT 11
+ # define R300_TX_HEIGHTMASK_MASK (2047 << 11)
+ # define R300_TX_UNK23 (1 << 23)
+-# define R300_TX_SIZE_SHIFT 26 /* largest of width, height */
++# define R300_TX_SIZE_SHIFT 26 /* largest of width, height */
+ # define R300_TX_SIZE_MASK (15 << 26)
+ #define R300_TX_FORMAT_0 0x44C0
+ /* The interpretation of the format word by Wladimir van der Laan */
+@@ -746,12 +742,12 @@ I am fairly certain that they are correc
+ # define R300_TX_FORMAT_DXT1 0xF
+ # define R300_TX_FORMAT_DXT3 0x10
+ # define R300_TX_FORMAT_DXT5 0x11
+-# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */
+-# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */
+-# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */
+-# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */
++# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */
++# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */
++# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */
++# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */
+ /* 0x16 - some 16 bit green format.. ?? */
+-# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */
++# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */
+
+ /* gap */
+ /* Floating point formats */
+@@ -777,8 +773,8 @@ I am fairly certain that they are correc
+ # define R300_TX_FORMAT_W 3
+ # define R300_TX_FORMAT_ZERO 4
+ # define R300_TX_FORMAT_ONE 5
+-# define R300_TX_FORMAT_CUT_Z 6 /* 2.0*Z, everything above 1.0 is set to 0.0 */
+-# define R300_TX_FORMAT_CUT_W 7 /* 2.0*W, everything above 1.0 is set to 0.0 */
++# define R300_TX_FORMAT_CUT_Z 6 /* 2.0*Z, everything above 1.0 is set to 0.0 */
++# define R300_TX_FORMAT_CUT_W 7 /* 2.0*W, everything above 1.0 is set to 0.0 */
+
+ # define R300_TX_FORMAT_B_SHIFT 18
+ # define R300_TX_FORMAT_G_SHIFT 15
+@@ -811,7 +807,7 @@ I am fairly certain that they are correc
+ # define R300_TXO_OFFSET_SHIFT 5
+ /* END */
+ #define R300_TX_UNK4_0 0x4580
+-#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
++#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
+
+ /* END */
+
+@@ -844,9 +840,9 @@ I am fairly certain that they are correc
+ # define R300_PFS_CNTL_ALU_END_SHIFT 6
+ # define R300_PFS_CNTL_ALU_END_MASK (63 << 0)
+ # define R300_PFS_CNTL_TEX_OFFSET_SHIFT 12
+-# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */
++# define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 12) /* GUESS */
+ # define R300_PFS_CNTL_TEX_END_SHIFT 18
+-# define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */
++# define R300_PFS_CNTL_TEX_END_MASK (31 << 18) /* GUESS */
+
+ /* gap */
+ /* Nodes are stored backwards. The last active node is always stored in
+@@ -877,11 +873,11 @@ I am fairly certain that they are correc
+ #define R300_PFS_TEXI_0 0x4620
+ # define R300_FPITX_SRC_SHIFT 0
+ # define R300_FPITX_SRC_MASK (31 << 0)
+-# define R300_FPITX_SRC_CONST (1 << 5) /* GUESS */
++# define R300_FPITX_SRC_CONST (1 << 5) /* GUESS */
+ # define R300_FPITX_DST_SHIFT 6
+ # define R300_FPITX_DST_MASK (31 << 6)
+ # define R300_FPITX_IMAGE_SHIFT 11
+-# define R300_FPITX_IMAGE_MASK (15 << 11) /* GUESS based on layout and native limits */
++# define R300_FPITX_IMAGE_MASK (15 << 11) /* GUESS based on layout and native limits */
+ /* Unsure if these are opcodes, or some kind of bitfield, but this is how
+ * they were set when I checked
+ */
+@@ -1003,7 +999,7 @@ I am fairly certain that they are correc
+ # define R300_FPI0_ARGC_SRC1C_LRP 15
+ # define R300_FPI0_ARGC_ZERO 20
+ # define R300_FPI0_ARGC_ONE 21
+-# define R300_FPI0_ARGC_HALF 22 /* GUESS */
++# define R300_FPI0_ARGC_HALF 22 /* GUESS */
+ # define R300_FPI0_ARGC_SRC0C_YZX 23
+ # define R300_FPI0_ARGC_SRC1C_YZX 24
+ # define R300_FPI0_ARGC_SRC2C_YZX 25
+@@ -1054,20 +1050,20 @@ I am fairly certain that they are correc
+ # define R300_FPI2_ARGA_SRC1A_LRP 15
+ # define R300_FPI2_ARGA_ZERO 16
+ # define R300_FPI2_ARGA_ONE 17
+-# define R300_FPI2_ARGA_HALF 18 /* GUESS */
++# define R300_FPI2_ARGA_HALF 18 /* GUESS */
+
+ # define R300_FPI2_ARG0A_SHIFT 0
+ # define R300_FPI2_ARG0A_MASK (31 << 0)
+ # define R300_FPI2_ARG0A_NEG (1 << 5)
+-# define R300_FPI2_ARG0A_ABS (1 << 6) /* GUESS */
++# define R300_FPI2_ARG0A_ABS (1 << 6) /* GUESS */
+ # define R300_FPI2_ARG1A_SHIFT 7
+ # define R300_FPI2_ARG1A_MASK (31 << 7)
+ # define R300_FPI2_ARG1A_NEG (1 << 12)
+-# define R300_FPI2_ARG1A_ABS (1 << 13) /* GUESS */
++# define R300_FPI2_ARG1A_ABS (1 << 13) /* GUESS */
+ # define R300_FPI2_ARG2A_SHIFT 14
+ # define R300_FPI2_ARG2A_MASK (31 << 14)
+ # define R300_FPI2_ARG2A_NEG (1 << 19)
+-# define R300_FPI2_ARG2A_ABS (1 << 20) /* GUESS */
++# define R300_FPI2_ARG2A_ABS (1 << 20) /* GUESS */
+ # define R300_FPI2_SPECIAL_LRP (1 << 21)
+ # define R300_FPI2_OUTA_MAD (0 << 23)
+ # define R300_FPI2_OUTA_DP4 (1 << 23)
+@@ -1157,26 +1153,26 @@ I am fairly certain that they are correc
+
+ /* gap */
+ #define R300_RB3D_COLOROFFSET0 0x4E28
+-# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */
+-#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */
+-#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */
+-#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */
++# define R300_COLOROFFSET_MASK 0xFFFFFFF0 /* GUESS */
++#define R300_RB3D_COLOROFFSET1 0x4E2C /* GUESS */
++#define R300_RB3D_COLOROFFSET2 0x4E30 /* GUESS */
++#define R300_RB3D_COLOROFFSET3 0x4E34 /* GUESS */
+ /* gap */
+ /* Bit 16: Larger tiles
+ // Bit 17: 4x2 tiles
+ // Bit 18: Extremely weird tile like, but some pixels duplicated? */
+ #define R300_RB3D_COLORPITCH0 0x4E38
+-# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */
+-# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */
+-# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */
+-# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+-# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+-# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
++# define R300_COLORPITCH_MASK 0x00001FF8 /* GUESS */
++# define R300_COLOR_TILE_ENABLE (1 << 16) /* GUESS */
++# define R300_COLOR_MICROTILE_ENABLE (1 << 17) /* GUESS */
++# define R300_COLOR_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
++# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
++# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+ # define R300_COLOR_FORMAT_RGB565 (2 << 22)
+ # define R300_COLOR_FORMAT_ARGB8888 (3 << 22)
+-#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */
+-#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
+-#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
++#define R300_RB3D_COLORPITCH1 0x4E3C /* GUESS */
++#define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */
++#define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */
+
+ /* gap */
+ /* Guess by Vladimir.
+@@ -1189,8 +1185,8 @@ I am fairly certain that they are correc
+ /* There seems to be no "write only" setting, so use Z-test = ALWAYS for this. */
+ /* Bit (1<<8) is the "test" bit. so plain write is 6 - vd */
+ #define R300_RB3D_ZSTENCIL_CNTL_0 0x4F00
+-# define R300_RB3D_Z_DISABLED_1 0x00000010 /* GUESS */
+-# define R300_RB3D_Z_DISABLED_2 0x00000014 /* GUESS */
++# define R300_RB3D_Z_DISABLED_1 0x00000010 /* GUESS */
++# define R300_RB3D_Z_DISABLED_2 0x00000014 /* GUESS */
+ # define R300_RB3D_Z_TEST 0x00000012
+ # define R300_RB3D_Z_TEST_AND_WRITE 0x00000016
+ # define R300_RB3D_Z_WRITE_ONLY 0x00000006
+@@ -1233,8 +1229,6 @@ I am fairly certain that they are correc
+ # define R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT 21
+ # define R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT 24
+
+-
+-
+ #define R300_RB3D_ZSTENCIL_CNTL_2 0x4F08
+ # define R300_RB3D_ZS2_STENCIL_REF_SHIFT 0
+ # define R300_RB3D_ZS2_STENCIL_MASK 0xFF
+@@ -1250,12 +1244,12 @@ I am fairly certain that they are correc
+ /* gap */
+ #define R300_RB3D_DEPTHOFFSET 0x4F20
+ #define R300_RB3D_DEPTHPITCH 0x4F24
+-# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */
+-# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */
+-# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */
+-# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
+-# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
+-# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
++# define R300_DEPTHPITCH_MASK 0x00001FF8 /* GUESS */
++# define R300_DEPTH_TILE_ENABLE (1 << 16) /* GUESS */
++# define R300_DEPTH_MICROTILE_ENABLE (1 << 17) /* GUESS */
++# define R300_DEPTH_ENDIAN_NO_SWAP (0 << 18) /* GUESS */
++# define R300_DEPTH_ENDIAN_WORD_SWAP (1 << 18) /* GUESS */
++# define R300_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) /* GUESS */
+
+ /* BEGIN: Vertex program instruction set
+ // Every instruction is four dwords long:
+@@ -1295,26 +1289,26 @@ I am fairly certain that they are correc
+ #define R300_VPI_OUT_OP_MIN (8 << 0)
+ #define R300_VPI_OUT_OP_SGE (9 << 0)
+ #define R300_VPI_OUT_OP_SLT (10 << 0)
+-#define R300_VPI_OUT_OP_UNK12 (12 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
++#define R300_VPI_OUT_OP_UNK12 (12 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+ #define R300_VPI_OUT_OP_EXP (65 << 0)
+ #define R300_VPI_OUT_OP_LOG (66 << 0)
+-#define R300_VPI_OUT_OP_UNK67 (67 << 0) /* Used in fog computations, scalar(scalar) */
++#define R300_VPI_OUT_OP_UNK67 (67 << 0) /* Used in fog computations, scalar(scalar) */
+ #define R300_VPI_OUT_OP_LIT (68 << 0)
+ #define R300_VPI_OUT_OP_POW (69 << 0)
+ #define R300_VPI_OUT_OP_RCP (70 << 0)
+ #define R300_VPI_OUT_OP_RSQ (72 << 0)
+-#define R300_VPI_OUT_OP_UNK73 (73 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
++#define R300_VPI_OUT_OP_UNK73 (73 << 0) /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+ #define R300_VPI_OUT_OP_EX2 (75 << 0)
+ #define R300_VPI_OUT_OP_LG2 (76 << 0)
+ #define R300_VPI_OUT_OP_MAD_2 (128 << 0)
+-#define R300_VPI_OUT_OP_UNK129 (129 << 0) /* all temps, vector(scalar, vector, vector) */
++#define R300_VPI_OUT_OP_UNK129 (129 << 0) /* all temps, vector(scalar, vector, vector) */
+
+ #define R300_VPI_OUT_REG_CLASS_TEMPORARY (0 << 8)
+ #define R300_VPI_OUT_REG_CLASS_RESULT (2 << 8)
+ #define R300_VPI_OUT_REG_CLASS_MASK (31 << 8)
+
+ #define R300_VPI_OUT_REG_INDEX_SHIFT 13
+-#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) /* GUESS based on fglrx native limits */
++#define R300_VPI_OUT_REG_INDEX_MASK (31 << 13) /* GUESS based on fglrx native limits */
+
+ #define R300_VPI_OUT_WRITE_X (1 << 20)
+ #define R300_VPI_OUT_WRITE_Y (1 << 21)
+@@ -1325,10 +1319,10 @@ I am fairly certain that they are correc
+ #define R300_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0)
+ #define R300_VPI_IN_REG_CLASS_PARAMETER (2 << 0)
+ #define R300_VPI_IN_REG_CLASS_NONE (9 << 0)
+-#define R300_VPI_IN_REG_CLASS_MASK (31 << 0) /* GUESS */
++#define R300_VPI_IN_REG_CLASS_MASK (31 << 0) /* GUESS */
+
+ #define R300_VPI_IN_REG_INDEX_SHIFT 5
+-#define R300_VPI_IN_REG_INDEX_MASK (255 << 5) /* GUESS based on fglrx native limits */
++#define R300_VPI_IN_REG_INDEX_MASK (255 << 5) /* GUESS based on fglrx native limits */
+
+ /* The R300 can select components from the input register arbitrarily.
+ // Use the following constants, shifted by the component shift you
+@@ -1366,7 +1360,7 @@ I am fairly certain that they are correc
+ #define R300_PRIM_TYPE_RECT_LIST (8 << 0)
+ #define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
+ #define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
+-#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) // GUESS (based on r200)
++#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0) // GUESS (based on r200)
+ #define R300_PRIM_TYPE_LINE_LOOP (12 << 0)
+ #define R300_PRIM_TYPE_QUADS (13 << 0)
+ #define R300_PRIM_TYPE_QUAD_STRIP (14 << 0)
+@@ -1376,8 +1370,8 @@ I am fairly certain that they are correc
+ #define R300_PRIM_WALK_LIST (2 << 4)
+ #define R300_PRIM_WALK_RING (3 << 4)
+ #define R300_PRIM_WALK_MASK (3 << 4)
+-#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) // GUESS (based on r200)
+-#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) // GUESS
++#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6) // GUESS (based on r200)
++#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6) // GUESS
+ #define R300_PRIM_NUM_VERTICES_SHIFT 16
+
+ // Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+@@ -1409,4 +1403,4 @@ I am fairly certain that they are correc
+
+ //END
+
+-#endif /* _R300_REG_H */
++#endif /* _R300_REG_H */
+diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
+--- a/drivers/char/drm/radeon_cp.c
++++ b/drivers/char/drm/radeon_cp.c
+@@ -36,788 +36,787 @@
+
+ #define RADEON_FIFO_DEBUG 0
+
+-static int radeon_do_cleanup_cp( drm_device_t *dev );
++static int radeon_do_cleanup_cp(drm_device_t * dev);
+
+ /* CP microcode (from ATI) */
+ static u32 R200_cp_microcode[][2] = {
+- { 0x21007000, 0000000000 },
+- { 0x20007000, 0000000000 },
+- { 0x000000ab, 0x00000004 },
+- { 0x000000af, 0x00000004 },
+- { 0x66544a49, 0000000000 },
+- { 0x49494174, 0000000000 },
+- { 0x54517d83, 0000000000 },
+- { 0x498d8b64, 0000000000 },
+- { 0x49494949, 0000000000 },
+- { 0x49da493c, 0000000000 },
+- { 0x49989898, 0000000000 },
+- { 0xd34949d5, 0000000000 },
+- { 0x9dc90e11, 0000000000 },
+- { 0xce9b9b9b, 0000000000 },
+- { 0x000f0000, 0x00000016 },
+- { 0x352e232c, 0000000000 },
+- { 0x00000013, 0x00000004 },
+- { 0x000f0000, 0x00000016 },
+- { 0x352e272c, 0000000000 },
+- { 0x000f0001, 0x00000016 },
+- { 0x3239362f, 0000000000 },
+- { 0x000077ef, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x00000020, 0x0000001a },
+- { 0x00004000, 0x0000001e },
+- { 0x00061000, 0x00000002 },
+- { 0x00000020, 0x0000001a },
+- { 0x00004000, 0x0000001e },
+- { 0x00061000, 0x00000002 },
+- { 0x00000020, 0x0000001a },
+- { 0x00004000, 0x0000001e },
+- { 0x00000016, 0x00000004 },
+- { 0x0003802a, 0x00000002 },
+- { 0x040067e0, 0x00000002 },
+- { 0x00000016, 0x00000004 },
+- { 0x000077e0, 0x00000002 },
+- { 0x00065000, 0x00000002 },
+- { 0x000037e1, 0x00000002 },
+- { 0x040067e1, 0x00000006 },
+- { 0x000077e0, 0x00000002 },
+- { 0x000077e1, 0x00000002 },
+- { 0x000077e1, 0x00000006 },
+- { 0xffffffff, 0000000000 },
+- { 0x10000000, 0000000000 },
+- { 0x0003802a, 0x00000002 },
+- { 0x040067e0, 0x00000006 },
+- { 0x00007675, 0x00000002 },
+- { 0x00007676, 0x00000002 },
+- { 0x00007677, 0x00000002 },
+- { 0x00007678, 0x00000006 },
+- { 0x0003802b, 0x00000002 },
+- { 0x04002676, 0x00000002 },
+- { 0x00007677, 0x00000002 },
+- { 0x00007678, 0x00000006 },
+- { 0x0000002e, 0x00000018 },
+- { 0x0000002e, 0x00000018 },
+- { 0000000000, 0x00000006 },
+- { 0x0000002f, 0x00000018 },
+- { 0x0000002f, 0x00000018 },
+- { 0000000000, 0x00000006 },
+- { 0x01605000, 0x00000002 },
+- { 0x00065000, 0x00000002 },
+- { 0x00098000, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x64c0603d, 0x00000004 },
+- { 0x00080000, 0x00000016 },
+- { 0000000000, 0000000000 },
+- { 0x0400251d, 0x00000002 },
+- { 0x00007580, 0x00000002 },
+- { 0x00067581, 0x00000002 },
+- { 0x04002580, 0x00000002 },
+- { 0x00067581, 0x00000002 },
+- { 0x00000046, 0x00000004 },
+- { 0x00005000, 0000000000 },
+- { 0x00061000, 0x00000002 },
+- { 0x0000750e, 0x00000002 },
+- { 0x00019000, 0x00000002 },
+- { 0x00011055, 0x00000014 },
+- { 0x00000055, 0x00000012 },
+- { 0x0400250f, 0x00000002 },
+- { 0x0000504a, 0x00000004 },
+- { 0x00007565, 0x00000002 },
+- { 0x00007566, 0x00000002 },
+- { 0x00000051, 0x00000004 },
+- { 0x01e655b4, 0x00000002 },
+- { 0x4401b0dc, 0x00000002 },
+- { 0x01c110dc, 0x00000002 },
+- { 0x2666705d, 0x00000018 },
+- { 0x040c2565, 0x00000002 },
+- { 0x0000005d, 0x00000018 },
+- { 0x04002564, 0x00000002 },
+- { 0x00007566, 0x00000002 },
+- { 0x00000054, 0x00000004 },
+- { 0x00401060, 0x00000008 },
+- { 0x00101000, 0x00000002 },
+- { 0x000d80ff, 0x00000002 },
+- { 0x00800063, 0x00000008 },
+- { 0x000f9000, 0x00000002 },
+- { 0x000e00ff, 0x00000002 },
+- { 0000000000, 0x00000006 },
+- { 0x00000080, 0x00000018 },
+- { 0x00000054, 0x00000004 },
+- { 0x00007576, 0x00000002 },
+- { 0x00065000, 0x00000002 },
+- { 0x00009000, 0x00000002 },
+- { 0x00041000, 0x00000002 },
+- { 0x0c00350e, 0x00000002 },
+- { 0x00049000, 0x00000002 },
+- { 0x00051000, 0x00000002 },
+- { 0x01e785f8, 0x00000002 },
+- { 0x00200000, 0x00000002 },
+- { 0x00600073, 0x0000000c },
+- { 0x00007563, 0x00000002 },
+- { 0x006075f0, 0x00000021 },
+- { 0x20007068, 0x00000004 },
+- { 0x00005068, 0x00000004 },
+- { 0x00007576, 0x00000002 },
+- { 0x00007577, 0x00000002 },
+- { 0x0000750e, 0x00000002 },
+- { 0x0000750f, 0x00000002 },
+- { 0x00a05000, 0x00000002 },
+- { 0x00600076, 0x0000000c },
+- { 0x006075f0, 0x00000021 },
+- { 0x000075f8, 0x00000002 },
+- { 0x00000076, 0x00000004 },
+- { 0x000a750e, 0x00000002 },
+- { 0x0020750f, 0x00000002 },
+- { 0x00600079, 0x00000004 },
+- { 0x00007570, 0x00000002 },
+- { 0x00007571, 0x00000002 },
+- { 0x00007572, 0x00000006 },
+- { 0x00005000, 0x00000002 },
+- { 0x00a05000, 0x00000002 },
+- { 0x00007568, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x00000084, 0x0000000c },
+- { 0x00058000, 0x00000002 },
+- { 0x0c607562, 0x00000002 },
+- { 0x00000086, 0x00000004 },
+- { 0x00600085, 0x00000004 },
+- { 0x400070dd, 0000000000 },
+- { 0x000380dd, 0x00000002 },
+- { 0x00000093, 0x0000001c },
+- { 0x00065095, 0x00000018 },
+- { 0x040025bb, 0x00000002 },
+- { 0x00061096, 0x00000018 },
+- { 0x040075bc, 0000000000 },
+- { 0x000075bb, 0x00000002 },
+- { 0x000075bc, 0000000000 },
+- { 0x00090000, 0x00000006 },
+- { 0x00090000, 0x00000002 },
+- { 0x000d8002, 0x00000006 },
+- { 0x00005000, 0x00000002 },
+- { 0x00007821, 0x00000002 },
+- { 0x00007800, 0000000000 },
+- { 0x00007821, 0x00000002 },
+- { 0x00007800, 0000000000 },
+- { 0x01665000, 0x00000002 },
+- { 0x000a0000, 0x00000002 },
+- { 0x000671cc, 0x00000002 },
+- { 0x0286f1cd, 0x00000002 },
+- { 0x000000a3, 0x00000010 },
+- { 0x21007000, 0000000000 },
+- { 0x000000aa, 0x0000001c },
+- { 0x00065000, 0x00000002 },
+- { 0x000a0000, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x000b0000, 0x00000002 },
+- { 0x38067000, 0x00000002 },
+- { 0x000a00a6, 0x00000004 },
+- { 0x20007000, 0000000000 },
+- { 0x01200000, 0x00000002 },
+- { 0x20077000, 0x00000002 },
+- { 0x01200000, 0x00000002 },
+- { 0x20007000, 0000000000 },
+- { 0x00061000, 0x00000002 },
+- { 0x0120751b, 0x00000002 },
+- { 0x8040750a, 0x00000002 },
+- { 0x8040750b, 0x00000002 },
+- { 0x00110000, 0x00000002 },
+- { 0x000380dd, 0x00000002 },
+- { 0x000000bd, 0x0000001c },
+- { 0x00061096, 0x00000018 },
+- { 0x844075bd, 0x00000002 },
+- { 0x00061095, 0x00000018 },
+- { 0x840075bb, 0x00000002 },
+- { 0x00061096, 0x00000018 },
+- { 0x844075bc, 0x00000002 },
+- { 0x000000c0, 0x00000004 },
+- { 0x804075bd, 0x00000002 },
+- { 0x800075bb, 0x00000002 },
+- { 0x804075bc, 0x00000002 },
+- { 0x00108000, 0x00000002 },
+- { 0x01400000, 0x00000002 },
+- { 0x006000c4, 0x0000000c },
+- { 0x20c07000, 0x00000020 },
+- { 0x000000c6, 0x00000012 },
+- { 0x00800000, 0x00000006 },
+- { 0x0080751d, 0x00000006 },
+- { 0x000025bb, 0x00000002 },
+- { 0x000040c0, 0x00000004 },
+- { 0x0000775c, 0x00000002 },
+- { 0x00a05000, 0x00000002 },
+- { 0x00661000, 0x00000002 },
+- { 0x0460275d, 0x00000020 },
+- { 0x00004000, 0000000000 },
+- { 0x00007999, 0x00000002 },
+- { 0x00a05000, 0x00000002 },
+- { 0x00661000, 0x00000002 },
+- { 0x0460299b, 0x00000020 },
+- { 0x00004000, 0000000000 },
+- { 0x01e00830, 0x00000002 },
+- { 0x21007000, 0000000000 },
+- { 0x00005000, 0x00000002 },
+- { 0x00038042, 0x00000002 },
+- { 0x040025e0, 0x00000002 },
+- { 0x000075e1, 0000000000 },
+- { 0x00000001, 0000000000 },
+- { 0x000380d9, 0x00000002 },
+- { 0x04007394, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
++ {0x21007000, 0000000000},
++ {0x20007000, 0000000000},
++ {0x000000ab, 0x00000004},
++ {0x000000af, 0x00000004},
++ {0x66544a49, 0000000000},
++ {0x49494174, 0000000000},
++ {0x54517d83, 0000000000},
++ {0x498d8b64, 0000000000},
++ {0x49494949, 0000000000},
++ {0x49da493c, 0000000000},
++ {0x49989898, 0000000000},
++ {0xd34949d5, 0000000000},
++ {0x9dc90e11, 0000000000},
++ {0xce9b9b9b, 0000000000},
++ {0x000f0000, 0x00000016},
++ {0x352e232c, 0000000000},
++ {0x00000013, 0x00000004},
++ {0x000f0000, 0x00000016},
++ {0x352e272c, 0000000000},
++ {0x000f0001, 0x00000016},
++ {0x3239362f, 0000000000},
++ {0x000077ef, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x00000020, 0x0000001a},
++ {0x00004000, 0x0000001e},
++ {0x00061000, 0x00000002},
++ {0x00000020, 0x0000001a},
++ {0x00004000, 0x0000001e},
++ {0x00061000, 0x00000002},
++ {0x00000020, 0x0000001a},
++ {0x00004000, 0x0000001e},
++ {0x00000016, 0x00000004},
++ {0x0003802a, 0x00000002},
++ {0x040067e0, 0x00000002},
++ {0x00000016, 0x00000004},
++ {0x000077e0, 0x00000002},
++ {0x00065000, 0x00000002},
++ {0x000037e1, 0x00000002},
++ {0x040067e1, 0x00000006},
++ {0x000077e0, 0x00000002},
++ {0x000077e1, 0x00000002},
++ {0x000077e1, 0x00000006},
++ {0xffffffff, 0000000000},
++ {0x10000000, 0000000000},
++ {0x0003802a, 0x00000002},
++ {0x040067e0, 0x00000006},
++ {0x00007675, 0x00000002},
++ {0x00007676, 0x00000002},
++ {0x00007677, 0x00000002},
++ {0x00007678, 0x00000006},
++ {0x0003802b, 0x00000002},
++ {0x04002676, 0x00000002},
++ {0x00007677, 0x00000002},
++ {0x00007678, 0x00000006},
++ {0x0000002e, 0x00000018},
++ {0x0000002e, 0x00000018},
++ {0000000000, 0x00000006},
++ {0x0000002f, 0x00000018},
++ {0x0000002f, 0x00000018},
++ {0000000000, 0x00000006},
++ {0x01605000, 0x00000002},
++ {0x00065000, 0x00000002},
++ {0x00098000, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x64c0603d, 0x00000004},
++ {0x00080000, 0x00000016},
++ {0000000000, 0000000000},
++ {0x0400251d, 0x00000002},
++ {0x00007580, 0x00000002},
++ {0x00067581, 0x00000002},
++ {0x04002580, 0x00000002},
++ {0x00067581, 0x00000002},
++ {0x00000046, 0x00000004},
++ {0x00005000, 0000000000},
++ {0x00061000, 0x00000002},
++ {0x0000750e, 0x00000002},
++ {0x00019000, 0x00000002},
++ {0x00011055, 0x00000014},
++ {0x00000055, 0x00000012},
++ {0x0400250f, 0x00000002},
++ {0x0000504a, 0x00000004},
++ {0x00007565, 0x00000002},
++ {0x00007566, 0x00000002},
++ {0x00000051, 0x00000004},
++ {0x01e655b4, 0x00000002},
++ {0x4401b0dc, 0x00000002},
++ {0x01c110dc, 0x00000002},
++ {0x2666705d, 0x00000018},
++ {0x040c2565, 0x00000002},
++ {0x0000005d, 0x00000018},
++ {0x04002564, 0x00000002},
++ {0x00007566, 0x00000002},
++ {0x00000054, 0x00000004},
++ {0x00401060, 0x00000008},
++ {0x00101000, 0x00000002},
++ {0x000d80ff, 0x00000002},
++ {0x00800063, 0x00000008},
++ {0x000f9000, 0x00000002},
++ {0x000e00ff, 0x00000002},
++ {0000000000, 0x00000006},
++ {0x00000080, 0x00000018},
++ {0x00000054, 0x00000004},
++ {0x00007576, 0x00000002},
++ {0x00065000, 0x00000002},
++ {0x00009000, 0x00000002},
++ {0x00041000, 0x00000002},
++ {0x0c00350e, 0x00000002},
++ {0x00049000, 0x00000002},
++ {0x00051000, 0x00000002},
++ {0x01e785f8, 0x00000002},
++ {0x00200000, 0x00000002},
++ {0x00600073, 0x0000000c},
++ {0x00007563, 0x00000002},
++ {0x006075f0, 0x00000021},
++ {0x20007068, 0x00000004},
++ {0x00005068, 0x00000004},
++ {0x00007576, 0x00000002},
++ {0x00007577, 0x00000002},
++ {0x0000750e, 0x00000002},
++ {0x0000750f, 0x00000002},
++ {0x00a05000, 0x00000002},
++ {0x00600076, 0x0000000c},
++ {0x006075f0, 0x00000021},
++ {0x000075f8, 0x00000002},
++ {0x00000076, 0x00000004},
++ {0x000a750e, 0x00000002},
++ {0x0020750f, 0x00000002},
++ {0x00600079, 0x00000004},
++ {0x00007570, 0x00000002},
++ {0x00007571, 0x00000002},
++ {0x00007572, 0x00000006},
++ {0x00005000, 0x00000002},
++ {0x00a05000, 0x00000002},
++ {0x00007568, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x00000084, 0x0000000c},
++ {0x00058000, 0x00000002},
++ {0x0c607562, 0x00000002},
++ {0x00000086, 0x00000004},
++ {0x00600085, 0x00000004},
++ {0x400070dd, 0000000000},
++ {0x000380dd, 0x00000002},
++ {0x00000093, 0x0000001c},
++ {0x00065095, 0x00000018},
++ {0x040025bb, 0x00000002},
++ {0x00061096, 0x00000018},
++ {0x040075bc, 0000000000},
++ {0x000075bb, 0x00000002},
++ {0x000075bc, 0000000000},
++ {0x00090000, 0x00000006},
++ {0x00090000, 0x00000002},
++ {0x000d8002, 0x00000006},
++ {0x00005000, 0x00000002},
++ {0x00007821, 0x00000002},
++ {0x00007800, 0000000000},
++ {0x00007821, 0x00000002},
++ {0x00007800, 0000000000},
++ {0x01665000, 0x00000002},
++ {0x000a0000, 0x00000002},
++ {0x000671cc, 0x00000002},
++ {0x0286f1cd, 0x00000002},
++ {0x000000a3, 0x00000010},
++ {0x21007000, 0000000000},
++ {0x000000aa, 0x0000001c},
++ {0x00065000, 0x00000002},
++ {0x000a0000, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x000b0000, 0x00000002},
++ {0x38067000, 0x00000002},
++ {0x000a00a6, 0x00000004},
++ {0x20007000, 0000000000},
++ {0x01200000, 0x00000002},
++ {0x20077000, 0x00000002},
++ {0x01200000, 0x00000002},
++ {0x20007000, 0000000000},
++ {0x00061000, 0x00000002},
++ {0x0120751b, 0x00000002},
++ {0x8040750a, 0x00000002},
++ {0x8040750b, 0x00000002},
++ {0x00110000, 0x00000002},
++ {0x000380dd, 0x00000002},
++ {0x000000bd, 0x0000001c},
++ {0x00061096, 0x00000018},
++ {0x844075bd, 0x00000002},
++ {0x00061095, 0x00000018},
++ {0x840075bb, 0x00000002},
++ {0x00061096, 0x00000018},
++ {0x844075bc, 0x00000002},
++ {0x000000c0, 0x00000004},
++ {0x804075bd, 0x00000002},
++ {0x800075bb, 0x00000002},
++ {0x804075bc, 0x00000002},
++ {0x00108000, 0x00000002},
++ {0x01400000, 0x00000002},
++ {0x006000c4, 0x0000000c},
++ {0x20c07000, 0x00000020},
++ {0x000000c6, 0x00000012},
++ {0x00800000, 0x00000006},
++ {0x0080751d, 0x00000006},
++ {0x000025bb, 0x00000002},
++ {0x000040c0, 0x00000004},
++ {0x0000775c, 0x00000002},
++ {0x00a05000, 0x00000002},
++ {0x00661000, 0x00000002},
++ {0x0460275d, 0x00000020},
++ {0x00004000, 0000000000},
++ {0x00007999, 0x00000002},
++ {0x00a05000, 0x00000002},
++ {0x00661000, 0x00000002},
++ {0x0460299b, 0x00000020},
++ {0x00004000, 0000000000},
++ {0x01e00830, 0x00000002},
++ {0x21007000, 0000000000},
++ {0x00005000, 0x00000002},
++ {0x00038042, 0x00000002},
++ {0x040025e0, 0x00000002},
++ {0x000075e1, 0000000000},
++ {0x00000001, 0000000000},
++ {0x000380d9, 0x00000002},
++ {0x04007394, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
+ };
+
+-
+ static u32 radeon_cp_microcode[][2] = {
+- { 0x21007000, 0000000000 },
+- { 0x20007000, 0000000000 },
+- { 0x000000b4, 0x00000004 },
+- { 0x000000b8, 0x00000004 },
+- { 0x6f5b4d4c, 0000000000 },
+- { 0x4c4c427f, 0000000000 },
+- { 0x5b568a92, 0000000000 },
+- { 0x4ca09c6d, 0000000000 },
+- { 0xad4c4c4c, 0000000000 },
+- { 0x4ce1af3d, 0000000000 },
+- { 0xd8afafaf, 0000000000 },
+- { 0xd64c4cdc, 0000000000 },
+- { 0x4cd10d10, 0000000000 },
+- { 0x000f0000, 0x00000016 },
+- { 0x362f242d, 0000000000 },
+- { 0x00000012, 0x00000004 },
+- { 0x000f0000, 0x00000016 },
+- { 0x362f282d, 0000000000 },
+- { 0x000380e7, 0x00000002 },
+- { 0x04002c97, 0x00000002 },
+- { 0x000f0001, 0x00000016 },
+- { 0x333a3730, 0000000000 },
+- { 0x000077ef, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x00000021, 0x0000001a },
+- { 0x00004000, 0x0000001e },
+- { 0x00061000, 0x00000002 },
+- { 0x00000021, 0x0000001a },
+- { 0x00004000, 0x0000001e },
+- { 0x00061000, 0x00000002 },
+- { 0x00000021, 0x0000001a },
+- { 0x00004000, 0x0000001e },
+- { 0x00000017, 0x00000004 },
+- { 0x0003802b, 0x00000002 },
+- { 0x040067e0, 0x00000002 },
+- { 0x00000017, 0x00000004 },
+- { 0x000077e0, 0x00000002 },
+- { 0x00065000, 0x00000002 },
+- { 0x000037e1, 0x00000002 },
+- { 0x040067e1, 0x00000006 },
+- { 0x000077e0, 0x00000002 },
+- { 0x000077e1, 0x00000002 },
+- { 0x000077e1, 0x00000006 },
+- { 0xffffffff, 0000000000 },
+- { 0x10000000, 0000000000 },
+- { 0x0003802b, 0x00000002 },
+- { 0x040067e0, 0x00000006 },
+- { 0x00007675, 0x00000002 },
+- { 0x00007676, 0x00000002 },
+- { 0x00007677, 0x00000002 },
+- { 0x00007678, 0x00000006 },
+- { 0x0003802c, 0x00000002 },
+- { 0x04002676, 0x00000002 },
+- { 0x00007677, 0x00000002 },
+- { 0x00007678, 0x00000006 },
+- { 0x0000002f, 0x00000018 },
+- { 0x0000002f, 0x00000018 },
+- { 0000000000, 0x00000006 },
+- { 0x00000030, 0x00000018 },
+- { 0x00000030, 0x00000018 },
+- { 0000000000, 0x00000006 },
+- { 0x01605000, 0x00000002 },
+- { 0x00065000, 0x00000002 },
+- { 0x00098000, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x64c0603e, 0x00000004 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x00080000, 0x00000016 },
+- { 0000000000, 0000000000 },
+- { 0x0400251d, 0x00000002 },
+- { 0x00007580, 0x00000002 },
+- { 0x00067581, 0x00000002 },
+- { 0x04002580, 0x00000002 },
+- { 0x00067581, 0x00000002 },
+- { 0x00000049, 0x00000004 },
+- { 0x00005000, 0000000000 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x0000750e, 0x00000002 },
+- { 0x00019000, 0x00000002 },
+- { 0x00011055, 0x00000014 },
+- { 0x00000055, 0x00000012 },
+- { 0x0400250f, 0x00000002 },
+- { 0x0000504f, 0x00000004 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x00007565, 0x00000002 },
+- { 0x00007566, 0x00000002 },
+- { 0x00000058, 0x00000004 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x01e655b4, 0x00000002 },
+- { 0x4401b0e4, 0x00000002 },
+- { 0x01c110e4, 0x00000002 },
+- { 0x26667066, 0x00000018 },
+- { 0x040c2565, 0x00000002 },
+- { 0x00000066, 0x00000018 },
+- { 0x04002564, 0x00000002 },
+- { 0x00007566, 0x00000002 },
+- { 0x0000005d, 0x00000004 },
+- { 0x00401069, 0x00000008 },
+- { 0x00101000, 0x00000002 },
+- { 0x000d80ff, 0x00000002 },
+- { 0x0080006c, 0x00000008 },
+- { 0x000f9000, 0x00000002 },
+- { 0x000e00ff, 0x00000002 },
+- { 0000000000, 0x00000006 },
+- { 0x0000008f, 0x00000018 },
+- { 0x0000005b, 0x00000004 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x00007576, 0x00000002 },
+- { 0x00065000, 0x00000002 },
+- { 0x00009000, 0x00000002 },
+- { 0x00041000, 0x00000002 },
+- { 0x0c00350e, 0x00000002 },
+- { 0x00049000, 0x00000002 },
+- { 0x00051000, 0x00000002 },
+- { 0x01e785f8, 0x00000002 },
+- { 0x00200000, 0x00000002 },
+- { 0x0060007e, 0x0000000c },
+- { 0x00007563, 0x00000002 },
+- { 0x006075f0, 0x00000021 },
+- { 0x20007073, 0x00000004 },
+- { 0x00005073, 0x00000004 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x00007576, 0x00000002 },
+- { 0x00007577, 0x00000002 },
+- { 0x0000750e, 0x00000002 },
+- { 0x0000750f, 0x00000002 },
+- { 0x00a05000, 0x00000002 },
+- { 0x00600083, 0x0000000c },
+- { 0x006075f0, 0x00000021 },
+- { 0x000075f8, 0x00000002 },
+- { 0x00000083, 0x00000004 },
+- { 0x000a750e, 0x00000002 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x0020750f, 0x00000002 },
+- { 0x00600086, 0x00000004 },
+- { 0x00007570, 0x00000002 },
+- { 0x00007571, 0x00000002 },
+- { 0x00007572, 0x00000006 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x00005000, 0x00000002 },
+- { 0x00a05000, 0x00000002 },
+- { 0x00007568, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x00000095, 0x0000000c },
+- { 0x00058000, 0x00000002 },
+- { 0x0c607562, 0x00000002 },
+- { 0x00000097, 0x00000004 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x00600096, 0x00000004 },
+- { 0x400070e5, 0000000000 },
+- { 0x000380e6, 0x00000002 },
+- { 0x040025c5, 0x00000002 },
+- { 0x000380e5, 0x00000002 },
+- { 0x000000a8, 0x0000001c },
+- { 0x000650aa, 0x00000018 },
+- { 0x040025bb, 0x00000002 },
+- { 0x000610ab, 0x00000018 },
+- { 0x040075bc, 0000000000 },
+- { 0x000075bb, 0x00000002 },
+- { 0x000075bc, 0000000000 },
+- { 0x00090000, 0x00000006 },
+- { 0x00090000, 0x00000002 },
+- { 0x000d8002, 0x00000006 },
+- { 0x00007832, 0x00000002 },
+- { 0x00005000, 0x00000002 },
+- { 0x000380e7, 0x00000002 },
+- { 0x04002c97, 0x00000002 },
+- { 0x00007820, 0x00000002 },
+- { 0x00007821, 0x00000002 },
+- { 0x00007800, 0000000000 },
+- { 0x01200000, 0x00000002 },
+- { 0x20077000, 0x00000002 },
+- { 0x01200000, 0x00000002 },
+- { 0x20007000, 0x00000002 },
+- { 0x00061000, 0x00000002 },
+- { 0x0120751b, 0x00000002 },
+- { 0x8040750a, 0x00000002 },
+- { 0x8040750b, 0x00000002 },
+- { 0x00110000, 0x00000002 },
+- { 0x000380e5, 0x00000002 },
+- { 0x000000c6, 0x0000001c },
+- { 0x000610ab, 0x00000018 },
+- { 0x844075bd, 0x00000002 },
+- { 0x000610aa, 0x00000018 },
+- { 0x840075bb, 0x00000002 },
+- { 0x000610ab, 0x00000018 },
+- { 0x844075bc, 0x00000002 },
+- { 0x000000c9, 0x00000004 },
+- { 0x804075bd, 0x00000002 },
+- { 0x800075bb, 0x00000002 },
+- { 0x804075bc, 0x00000002 },
+- { 0x00108000, 0x00000002 },
+- { 0x01400000, 0x00000002 },
+- { 0x006000cd, 0x0000000c },
+- { 0x20c07000, 0x00000020 },
+- { 0x000000cf, 0x00000012 },
+- { 0x00800000, 0x00000006 },
+- { 0x0080751d, 0x00000006 },
+- { 0000000000, 0000000000 },
+- { 0x0000775c, 0x00000002 },
+- { 0x00a05000, 0x00000002 },
+- { 0x00661000, 0x00000002 },
+- { 0x0460275d, 0x00000020 },
+- { 0x00004000, 0000000000 },
+- { 0x01e00830, 0x00000002 },
+- { 0x21007000, 0000000000 },
+- { 0x6464614d, 0000000000 },
+- { 0x69687420, 0000000000 },
+- { 0x00000073, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0x00005000, 0x00000002 },
+- { 0x000380d0, 0x00000002 },
+- { 0x040025e0, 0x00000002 },
+- { 0x000075e1, 0000000000 },
+- { 0x00000001, 0000000000 },
+- { 0x000380e0, 0x00000002 },
+- { 0x04002394, 0x00000002 },
+- { 0x00005000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0x00000008, 0000000000 },
+- { 0x00000004, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
++ {0x21007000, 0000000000},
++ {0x20007000, 0000000000},
++ {0x000000b4, 0x00000004},
++ {0x000000b8, 0x00000004},
++ {0x6f5b4d4c, 0000000000},
++ {0x4c4c427f, 0000000000},
++ {0x5b568a92, 0000000000},
++ {0x4ca09c6d, 0000000000},
++ {0xad4c4c4c, 0000000000},
++ {0x4ce1af3d, 0000000000},
++ {0xd8afafaf, 0000000000},
++ {0xd64c4cdc, 0000000000},
++ {0x4cd10d10, 0000000000},
++ {0x000f0000, 0x00000016},
++ {0x362f242d, 0000000000},
++ {0x00000012, 0x00000004},
++ {0x000f0000, 0x00000016},
++ {0x362f282d, 0000000000},
++ {0x000380e7, 0x00000002},
++ {0x04002c97, 0x00000002},
++ {0x000f0001, 0x00000016},
++ {0x333a3730, 0000000000},
++ {0x000077ef, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x00000021, 0x0000001a},
++ {0x00004000, 0x0000001e},
++ {0x00061000, 0x00000002},
++ {0x00000021, 0x0000001a},
++ {0x00004000, 0x0000001e},
++ {0x00061000, 0x00000002},
++ {0x00000021, 0x0000001a},
++ {0x00004000, 0x0000001e},
++ {0x00000017, 0x00000004},
++ {0x0003802b, 0x00000002},
++ {0x040067e0, 0x00000002},
++ {0x00000017, 0x00000004},
++ {0x000077e0, 0x00000002},
++ {0x00065000, 0x00000002},
++ {0x000037e1, 0x00000002},
++ {0x040067e1, 0x00000006},
++ {0x000077e0, 0x00000002},
++ {0x000077e1, 0x00000002},
++ {0x000077e1, 0x00000006},
++ {0xffffffff, 0000000000},
++ {0x10000000, 0000000000},
++ {0x0003802b, 0x00000002},
++ {0x040067e0, 0x00000006},
++ {0x00007675, 0x00000002},
++ {0x00007676, 0x00000002},
++ {0x00007677, 0x00000002},
++ {0x00007678, 0x00000006},
++ {0x0003802c, 0x00000002},
++ {0x04002676, 0x00000002},
++ {0x00007677, 0x00000002},
++ {0x00007678, 0x00000006},
++ {0x0000002f, 0x00000018},
++ {0x0000002f, 0x00000018},
++ {0000000000, 0x00000006},
++ {0x00000030, 0x00000018},
++ {0x00000030, 0x00000018},
++ {0000000000, 0x00000006},
++ {0x01605000, 0x00000002},
++ {0x00065000, 0x00000002},
++ {0x00098000, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x64c0603e, 0x00000004},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x00080000, 0x00000016},
++ {0000000000, 0000000000},
++ {0x0400251d, 0x00000002},
++ {0x00007580, 0x00000002},
++ {0x00067581, 0x00000002},
++ {0x04002580, 0x00000002},
++ {0x00067581, 0x00000002},
++ {0x00000049, 0x00000004},
++ {0x00005000, 0000000000},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x0000750e, 0x00000002},
++ {0x00019000, 0x00000002},
++ {0x00011055, 0x00000014},
++ {0x00000055, 0x00000012},
++ {0x0400250f, 0x00000002},
++ {0x0000504f, 0x00000004},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x00007565, 0x00000002},
++ {0x00007566, 0x00000002},
++ {0x00000058, 0x00000004},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x01e655b4, 0x00000002},
++ {0x4401b0e4, 0x00000002},
++ {0x01c110e4, 0x00000002},
++ {0x26667066, 0x00000018},
++ {0x040c2565, 0x00000002},
++ {0x00000066, 0x00000018},
++ {0x04002564, 0x00000002},
++ {0x00007566, 0x00000002},
++ {0x0000005d, 0x00000004},
++ {0x00401069, 0x00000008},
++ {0x00101000, 0x00000002},
++ {0x000d80ff, 0x00000002},
++ {0x0080006c, 0x00000008},
++ {0x000f9000, 0x00000002},
++ {0x000e00ff, 0x00000002},
++ {0000000000, 0x00000006},
++ {0x0000008f, 0x00000018},
++ {0x0000005b, 0x00000004},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x00007576, 0x00000002},
++ {0x00065000, 0x00000002},
++ {0x00009000, 0x00000002},
++ {0x00041000, 0x00000002},
++ {0x0c00350e, 0x00000002},
++ {0x00049000, 0x00000002},
++ {0x00051000, 0x00000002},
++ {0x01e785f8, 0x00000002},
++ {0x00200000, 0x00000002},
++ {0x0060007e, 0x0000000c},
++ {0x00007563, 0x00000002},
++ {0x006075f0, 0x00000021},
++ {0x20007073, 0x00000004},
++ {0x00005073, 0x00000004},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x00007576, 0x00000002},
++ {0x00007577, 0x00000002},
++ {0x0000750e, 0x00000002},
++ {0x0000750f, 0x00000002},
++ {0x00a05000, 0x00000002},
++ {0x00600083, 0x0000000c},
++ {0x006075f0, 0x00000021},
++ {0x000075f8, 0x00000002},
++ {0x00000083, 0x00000004},
++ {0x000a750e, 0x00000002},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x0020750f, 0x00000002},
++ {0x00600086, 0x00000004},
++ {0x00007570, 0x00000002},
++ {0x00007571, 0x00000002},
++ {0x00007572, 0x00000006},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x00005000, 0x00000002},
++ {0x00a05000, 0x00000002},
++ {0x00007568, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x00000095, 0x0000000c},
++ {0x00058000, 0x00000002},
++ {0x0c607562, 0x00000002},
++ {0x00000097, 0x00000004},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x00600096, 0x00000004},
++ {0x400070e5, 0000000000},
++ {0x000380e6, 0x00000002},
++ {0x040025c5, 0x00000002},
++ {0x000380e5, 0x00000002},
++ {0x000000a8, 0x0000001c},
++ {0x000650aa, 0x00000018},
++ {0x040025bb, 0x00000002},
++ {0x000610ab, 0x00000018},
++ {0x040075bc, 0000000000},
++ {0x000075bb, 0x00000002},
++ {0x000075bc, 0000000000},
++ {0x00090000, 0x00000006},
++ {0x00090000, 0x00000002},
++ {0x000d8002, 0x00000006},
++ {0x00007832, 0x00000002},
++ {0x00005000, 0x00000002},
++ {0x000380e7, 0x00000002},
++ {0x04002c97, 0x00000002},
++ {0x00007820, 0x00000002},
++ {0x00007821, 0x00000002},
++ {0x00007800, 0000000000},
++ {0x01200000, 0x00000002},
++ {0x20077000, 0x00000002},
++ {0x01200000, 0x00000002},
++ {0x20007000, 0x00000002},
++ {0x00061000, 0x00000002},
++ {0x0120751b, 0x00000002},
++ {0x8040750a, 0x00000002},
++ {0x8040750b, 0x00000002},
++ {0x00110000, 0x00000002},
++ {0x000380e5, 0x00000002},
++ {0x000000c6, 0x0000001c},
++ {0x000610ab, 0x00000018},
++ {0x844075bd, 0x00000002},
++ {0x000610aa, 0x00000018},
++ {0x840075bb, 0x00000002},
++ {0x000610ab, 0x00000018},
++ {0x844075bc, 0x00000002},
++ {0x000000c9, 0x00000004},
++ {0x804075bd, 0x00000002},
++ {0x800075bb, 0x00000002},
++ {0x804075bc, 0x00000002},
++ {0x00108000, 0x00000002},
++ {0x01400000, 0x00000002},
++ {0x006000cd, 0x0000000c},
++ {0x20c07000, 0x00000020},
++ {0x000000cf, 0x00000012},
++ {0x00800000, 0x00000006},
++ {0x0080751d, 0x00000006},
++ {0000000000, 0000000000},
++ {0x0000775c, 0x00000002},
++ {0x00a05000, 0x00000002},
++ {0x00661000, 0x00000002},
++ {0x0460275d, 0x00000020},
++ {0x00004000, 0000000000},
++ {0x01e00830, 0x00000002},
++ {0x21007000, 0000000000},
++ {0x6464614d, 0000000000},
++ {0x69687420, 0000000000},
++ {0x00000073, 0000000000},
++ {0000000000, 0000000000},
++ {0x00005000, 0x00000002},
++ {0x000380d0, 0x00000002},
++ {0x040025e0, 0x00000002},
++ {0x000075e1, 0000000000},
++ {0x00000001, 0000000000},
++ {0x000380e0, 0x00000002},
++ {0x04002394, 0x00000002},
++ {0x00005000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0x00000008, 0000000000},
++ {0x00000004, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
+ };
+
+ static u32 R300_cp_microcode[][2] = {
+- { 0x4200e000, 0000000000 },
+- { 0x4000e000, 0000000000 },
+- { 0x000000af, 0x00000008 },
+- { 0x000000b3, 0x00000008 },
+- { 0x6c5a504f, 0000000000 },
+- { 0x4f4f497a, 0000000000 },
+- { 0x5a578288, 0000000000 },
+- { 0x4f91906a, 0000000000 },
+- { 0x4f4f4f4f, 0000000000 },
+- { 0x4fe24f44, 0000000000 },
+- { 0x4f9c9c9c, 0000000000 },
+- { 0xdc4f4fde, 0000000000 },
+- { 0xa1cd4f4f, 0000000000 },
+- { 0xd29d9d9d, 0000000000 },
+- { 0x4f0f9fd7, 0000000000 },
+- { 0x000ca000, 0x00000004 },
+- { 0x000d0012, 0x00000038 },
+- { 0x0000e8b4, 0x00000004 },
+- { 0x000d0014, 0x00000038 },
+- { 0x0000e8b6, 0x00000004 },
+- { 0x000d0016, 0x00000038 },
+- { 0x0000e854, 0x00000004 },
+- { 0x000d0018, 0x00000038 },
+- { 0x0000e855, 0x00000004 },
+- { 0x000d001a, 0x00000038 },
+- { 0x0000e856, 0x00000004 },
+- { 0x000d001c, 0x00000038 },
+- { 0x0000e857, 0x00000004 },
+- { 0x000d001e, 0x00000038 },
+- { 0x0000e824, 0x00000004 },
+- { 0x000d0020, 0x00000038 },
+- { 0x0000e825, 0x00000004 },
+- { 0x000d0022, 0x00000038 },
+- { 0x0000e830, 0x00000004 },
+- { 0x000d0024, 0x00000038 },
+- { 0x0000f0c0, 0x00000004 },
+- { 0x000d0026, 0x00000038 },
+- { 0x0000f0c1, 0x00000004 },
+- { 0x000d0028, 0x00000038 },
+- { 0x0000f041, 0x00000004 },
+- { 0x000d002a, 0x00000038 },
+- { 0x0000f184, 0x00000004 },
+- { 0x000d002c, 0x00000038 },
+- { 0x0000f185, 0x00000004 },
+- { 0x000d002e, 0x00000038 },
+- { 0x0000f186, 0x00000004 },
+- { 0x000d0030, 0x00000038 },
+- { 0x0000f187, 0x00000004 },
+- { 0x000d0032, 0x00000038 },
+- { 0x0000f180, 0x00000004 },
+- { 0x000d0034, 0x00000038 },
+- { 0x0000f393, 0x00000004 },
+- { 0x000d0036, 0x00000038 },
+- { 0x0000f38a, 0x00000004 },
+- { 0x000d0038, 0x00000038 },
+- { 0x0000f38e, 0x00000004 },
+- { 0x0000e821, 0x00000004 },
+- { 0x0140a000, 0x00000004 },
+- { 0x00000043, 0x00000018 },
+- { 0x00cce800, 0x00000004 },
+- { 0x001b0001, 0x00000004 },
+- { 0x08004800, 0x00000004 },
+- { 0x001b0001, 0x00000004 },
+- { 0x08004800, 0x00000004 },
+- { 0x001b0001, 0x00000004 },
+- { 0x08004800, 0x00000004 },
+- { 0x0000003a, 0x00000008 },
+- { 0x0000a000, 0000000000 },
+- { 0x02c0a000, 0x00000004 },
+- { 0x000ca000, 0x00000004 },
+- { 0x00130000, 0x00000004 },
+- { 0x000c2000, 0x00000004 },
+- { 0xc980c045, 0x00000008 },
+- { 0x2000451d, 0x00000004 },
+- { 0x0000e580, 0x00000004 },
+- { 0x000ce581, 0x00000004 },
+- { 0x08004580, 0x00000004 },
+- { 0x000ce581, 0x00000004 },
+- { 0x0000004c, 0x00000008 },
+- { 0x0000a000, 0000000000 },
+- { 0x000c2000, 0x00000004 },
+- { 0x0000e50e, 0x00000004 },
+- { 0x00032000, 0x00000004 },
+- { 0x00022056, 0x00000028 },
+- { 0x00000056, 0x00000024 },
+- { 0x0800450f, 0x00000004 },
+- { 0x0000a050, 0x00000008 },
+- { 0x0000e565, 0x00000004 },
+- { 0x0000e566, 0x00000004 },
+- { 0x00000057, 0x00000008 },
+- { 0x03cca5b4, 0x00000004 },
+- { 0x05432000, 0x00000004 },
+- { 0x00022000, 0x00000004 },
+- { 0x4ccce063, 0x00000030 },
+- { 0x08274565, 0x00000004 },
+- { 0x00000063, 0x00000030 },
+- { 0x08004564, 0x00000004 },
+- { 0x0000e566, 0x00000004 },
+- { 0x0000005a, 0x00000008 },
+- { 0x00802066, 0x00000010 },
+- { 0x00202000, 0x00000004 },
+- { 0x001b00ff, 0x00000004 },
+- { 0x01000069, 0x00000010 },
+- { 0x001f2000, 0x00000004 },
+- { 0x001c00ff, 0x00000004 },
+- { 0000000000, 0x0000000c },
+- { 0x00000085, 0x00000030 },
+- { 0x0000005a, 0x00000008 },
+- { 0x0000e576, 0x00000004 },
+- { 0x000ca000, 0x00000004 },
+- { 0x00012000, 0x00000004 },
+- { 0x00082000, 0x00000004 },
+- { 0x1800650e, 0x00000004 },
+- { 0x00092000, 0x00000004 },
+- { 0x000a2000, 0x00000004 },
+- { 0x000f0000, 0x00000004 },
+- { 0x00400000, 0x00000004 },
+- { 0x00000079, 0x00000018 },
+- { 0x0000e563, 0x00000004 },
+- { 0x00c0e5f9, 0x000000c2 },
+- { 0x0000006e, 0x00000008 },
+- { 0x0000a06e, 0x00000008 },
+- { 0x0000e576, 0x00000004 },
+- { 0x0000e577, 0x00000004 },
+- { 0x0000e50e, 0x00000004 },
+- { 0x0000e50f, 0x00000004 },
+- { 0x0140a000, 0x00000004 },
+- { 0x0000007c, 0x00000018 },
+- { 0x00c0e5f9, 0x000000c2 },
+- { 0x0000007c, 0x00000008 },
+- { 0x0014e50e, 0x00000004 },
+- { 0x0040e50f, 0x00000004 },
+- { 0x00c0007f, 0x00000008 },
+- { 0x0000e570, 0x00000004 },
+- { 0x0000e571, 0x00000004 },
+- { 0x0000e572, 0x0000000c },
+- { 0x0000a000, 0x00000004 },
+- { 0x0140a000, 0x00000004 },
+- { 0x0000e568, 0x00000004 },
+- { 0x000c2000, 0x00000004 },
+- { 0x00000089, 0x00000018 },
+- { 0x000b0000, 0x00000004 },
+- { 0x18c0e562, 0x00000004 },
+- { 0x0000008b, 0x00000008 },
+- { 0x00c0008a, 0x00000008 },
+- { 0x000700e4, 0x00000004 },
+- { 0x00000097, 0x00000038 },
+- { 0x000ca099, 0x00000030 },
+- { 0x080045bb, 0x00000004 },
+- { 0x000c209a, 0x00000030 },
+- { 0x0800e5bc, 0000000000 },
+- { 0x0000e5bb, 0x00000004 },
+- { 0x0000e5bc, 0000000000 },
+- { 0x00120000, 0x0000000c },
+- { 0x00120000, 0x00000004 },
+- { 0x001b0002, 0x0000000c },
+- { 0x0000a000, 0x00000004 },
+- { 0x0000e821, 0x00000004 },
+- { 0x0000e800, 0000000000 },
+- { 0x0000e821, 0x00000004 },
+- { 0x0000e82e, 0000000000 },
+- { 0x02cca000, 0x00000004 },
+- { 0x00140000, 0x00000004 },
+- { 0x000ce1cc, 0x00000004 },
+- { 0x050de1cd, 0x00000004 },
+- { 0x000000a7, 0x00000020 },
+- { 0x4200e000, 0000000000 },
+- { 0x000000ae, 0x00000038 },
+- { 0x000ca000, 0x00000004 },
+- { 0x00140000, 0x00000004 },
+- { 0x000c2000, 0x00000004 },
+- { 0x00160000, 0x00000004 },
+- { 0x700ce000, 0x00000004 },
+- { 0x001400aa, 0x00000008 },
+- { 0x4000e000, 0000000000 },
+- { 0x02400000, 0x00000004 },
+- { 0x400ee000, 0x00000004 },
+- { 0x02400000, 0x00000004 },
+- { 0x4000e000, 0000000000 },
+- { 0x000c2000, 0x00000004 },
+- { 0x0240e51b, 0x00000004 },
+- { 0x0080e50a, 0x00000005 },
+- { 0x0080e50b, 0x00000005 },
+- { 0x00220000, 0x00000004 },
+- { 0x000700e4, 0x00000004 },
+- { 0x000000c1, 0x00000038 },
+- { 0x000c209a, 0x00000030 },
+- { 0x0880e5bd, 0x00000005 },
+- { 0x000c2099, 0x00000030 },
+- { 0x0800e5bb, 0x00000005 },
+- { 0x000c209a, 0x00000030 },
+- { 0x0880e5bc, 0x00000005 },
+- { 0x000000c4, 0x00000008 },
+- { 0x0080e5bd, 0x00000005 },
+- { 0x0000e5bb, 0x00000005 },
+- { 0x0080e5bc, 0x00000005 },
+- { 0x00210000, 0x00000004 },
+- { 0x02800000, 0x00000004 },
+- { 0x00c000c8, 0x00000018 },
+- { 0x4180e000, 0x00000040 },
+- { 0x000000ca, 0x00000024 },
+- { 0x01000000, 0x0000000c },
+- { 0x0100e51d, 0x0000000c },
+- { 0x000045bb, 0x00000004 },
+- { 0x000080c4, 0x00000008 },
+- { 0x0000f3ce, 0x00000004 },
+- { 0x0140a000, 0x00000004 },
+- { 0x00cc2000, 0x00000004 },
+- { 0x08c053cf, 0x00000040 },
+- { 0x00008000, 0000000000 },
+- { 0x0000f3d2, 0x00000004 },
+- { 0x0140a000, 0x00000004 },
+- { 0x00cc2000, 0x00000004 },
+- { 0x08c053d3, 0x00000040 },
+- { 0x00008000, 0000000000 },
+- { 0x0000f39d, 0x00000004 },
+- { 0x0140a000, 0x00000004 },
+- { 0x00cc2000, 0x00000004 },
+- { 0x08c0539e, 0x00000040 },
+- { 0x00008000, 0000000000 },
+- { 0x03c00830, 0x00000004 },
+- { 0x4200e000, 0000000000 },
+- { 0x0000a000, 0x00000004 },
+- { 0x200045e0, 0x00000004 },
+- { 0x0000e5e1, 0000000000 },
+- { 0x00000001, 0000000000 },
+- { 0x000700e1, 0x00000004 },
+- { 0x0800e394, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
+- { 0000000000, 0000000000 },
++ {0x4200e000, 0000000000},
++ {0x4000e000, 0000000000},
++ {0x000000af, 0x00000008},
++ {0x000000b3, 0x00000008},
++ {0x6c5a504f, 0000000000},
++ {0x4f4f497a, 0000000000},
++ {0x5a578288, 0000000000},
++ {0x4f91906a, 0000000000},
++ {0x4f4f4f4f, 0000000000},
++ {0x4fe24f44, 0000000000},
++ {0x4f9c9c9c, 0000000000},
++ {0xdc4f4fde, 0000000000},
++ {0xa1cd4f4f, 0000000000},
++ {0xd29d9d9d, 0000000000},
++ {0x4f0f9fd7, 0000000000},
++ {0x000ca000, 0x00000004},
++ {0x000d0012, 0x00000038},
++ {0x0000e8b4, 0x00000004},
++ {0x000d0014, 0x00000038},
++ {0x0000e8b6, 0x00000004},
++ {0x000d0016, 0x00000038},
++ {0x0000e854, 0x00000004},
++ {0x000d0018, 0x00000038},
++ {0x0000e855, 0x00000004},
++ {0x000d001a, 0x00000038},
++ {0x0000e856, 0x00000004},
++ {0x000d001c, 0x00000038},
++ {0x0000e857, 0x00000004},
++ {0x000d001e, 0x00000038},
++ {0x0000e824, 0x00000004},
++ {0x000d0020, 0x00000038},
++ {0x0000e825, 0x00000004},
++ {0x000d0022, 0x00000038},
++ {0x0000e830, 0x00000004},
++ {0x000d0024, 0x00000038},
++ {0x0000f0c0, 0x00000004},
++ {0x000d0026, 0x00000038},
++ {0x0000f0c1, 0x00000004},
++ {0x000d0028, 0x00000038},
++ {0x0000f041, 0x00000004},
++ {0x000d002a, 0x00000038},
++ {0x0000f184, 0x00000004},
++ {0x000d002c, 0x00000038},
++ {0x0000f185, 0x00000004},
++ {0x000d002e, 0x00000038},
++ {0x0000f186, 0x00000004},
++ {0x000d0030, 0x00000038},
++ {0x0000f187, 0x00000004},
++ {0x000d0032, 0x00000038},
++ {0x0000f180, 0x00000004},
++ {0x000d0034, 0x00000038},
++ {0x0000f393, 0x00000004},
++ {0x000d0036, 0x00000038},
++ {0x0000f38a, 0x00000004},
++ {0x000d0038, 0x00000038},
++ {0x0000f38e, 0x00000004},
++ {0x0000e821, 0x00000004},
++ {0x0140a000, 0x00000004},
++ {0x00000043, 0x00000018},
++ {0x00cce800, 0x00000004},
++ {0x001b0001, 0x00000004},
++ {0x08004800, 0x00000004},
++ {0x001b0001, 0x00000004},
++ {0x08004800, 0x00000004},
++ {0x001b0001, 0x00000004},
++ {0x08004800, 0x00000004},
++ {0x0000003a, 0x00000008},
++ {0x0000a000, 0000000000},
++ {0x02c0a000, 0x00000004},
++ {0x000ca000, 0x00000004},
++ {0x00130000, 0x00000004},
++ {0x000c2000, 0x00000004},
++ {0xc980c045, 0x00000008},
++ {0x2000451d, 0x00000004},
++ {0x0000e580, 0x00000004},
++ {0x000ce581, 0x00000004},
++ {0x08004580, 0x00000004},
++ {0x000ce581, 0x00000004},
++ {0x0000004c, 0x00000008},
++ {0x0000a000, 0000000000},
++ {0x000c2000, 0x00000004},
++ {0x0000e50e, 0x00000004},
++ {0x00032000, 0x00000004},
++ {0x00022056, 0x00000028},
++ {0x00000056, 0x00000024},
++ {0x0800450f, 0x00000004},
++ {0x0000a050, 0x00000008},
++ {0x0000e565, 0x00000004},
++ {0x0000e566, 0x00000004},
++ {0x00000057, 0x00000008},
++ {0x03cca5b4, 0x00000004},
++ {0x05432000, 0x00000004},
++ {0x00022000, 0x00000004},
++ {0x4ccce063, 0x00000030},
++ {0x08274565, 0x00000004},
++ {0x00000063, 0x00000030},
++ {0x08004564, 0x00000004},
++ {0x0000e566, 0x00000004},
++ {0x0000005a, 0x00000008},
++ {0x00802066, 0x00000010},
++ {0x00202000, 0x00000004},
++ {0x001b00ff, 0x00000004},
++ {0x01000069, 0x00000010},
++ {0x001f2000, 0x00000004},
++ {0x001c00ff, 0x00000004},
++ {0000000000, 0x0000000c},
++ {0x00000085, 0x00000030},
++ {0x0000005a, 0x00000008},
++ {0x0000e576, 0x00000004},
++ {0x000ca000, 0x00000004},
++ {0x00012000, 0x00000004},
++ {0x00082000, 0x00000004},
++ {0x1800650e, 0x00000004},
++ {0x00092000, 0x00000004},
++ {0x000a2000, 0x00000004},
++ {0x000f0000, 0x00000004},
++ {0x00400000, 0x00000004},
++ {0x00000079, 0x00000018},
++ {0x0000e563, 0x00000004},
++ {0x00c0e5f9, 0x000000c2},
++ {0x0000006e, 0x00000008},
++ {0x0000a06e, 0x00000008},
++ {0x0000e576, 0x00000004},
++ {0x0000e577, 0x00000004},
++ {0x0000e50e, 0x00000004},
++ {0x0000e50f, 0x00000004},
++ {0x0140a000, 0x00000004},
++ {0x0000007c, 0x00000018},
++ {0x00c0e5f9, 0x000000c2},
++ {0x0000007c, 0x00000008},
++ {0x0014e50e, 0x00000004},
++ {0x0040e50f, 0x00000004},
++ {0x00c0007f, 0x00000008},
++ {0x0000e570, 0x00000004},
++ {0x0000e571, 0x00000004},
++ {0x0000e572, 0x0000000c},
++ {0x0000a000, 0x00000004},
++ {0x0140a000, 0x00000004},
++ {0x0000e568, 0x00000004},
++ {0x000c2000, 0x00000004},
++ {0x00000089, 0x00000018},
++ {0x000b0000, 0x00000004},
++ {0x18c0e562, 0x00000004},
++ {0x0000008b, 0x00000008},
++ {0x00c0008a, 0x00000008},
++ {0x000700e4, 0x00000004},
++ {0x00000097, 0x00000038},
++ {0x000ca099, 0x00000030},
++ {0x080045bb, 0x00000004},
++ {0x000c209a, 0x00000030},
++ {0x0800e5bc, 0000000000},
++ {0x0000e5bb, 0x00000004},
++ {0x0000e5bc, 0000000000},
++ {0x00120000, 0x0000000c},
++ {0x00120000, 0x00000004},
++ {0x001b0002, 0x0000000c},
++ {0x0000a000, 0x00000004},
++ {0x0000e821, 0x00000004},
++ {0x0000e800, 0000000000},
++ {0x0000e821, 0x00000004},
++ {0x0000e82e, 0000000000},
++ {0x02cca000, 0x00000004},
++ {0x00140000, 0x00000004},
++ {0x000ce1cc, 0x00000004},
++ {0x050de1cd, 0x00000004},
++ {0x000000a7, 0x00000020},
++ {0x4200e000, 0000000000},
++ {0x000000ae, 0x00000038},
++ {0x000ca000, 0x00000004},
++ {0x00140000, 0x00000004},
++ {0x000c2000, 0x00000004},
++ {0x00160000, 0x00000004},
++ {0x700ce000, 0x00000004},
++ {0x001400aa, 0x00000008},
++ {0x4000e000, 0000000000},
++ {0x02400000, 0x00000004},
++ {0x400ee000, 0x00000004},
++ {0x02400000, 0x00000004},
++ {0x4000e000, 0000000000},
++ {0x000c2000, 0x00000004},
++ {0x0240e51b, 0x00000004},
++ {0x0080e50a, 0x00000005},
++ {0x0080e50b, 0x00000005},
++ {0x00220000, 0x00000004},
++ {0x000700e4, 0x00000004},
++ {0x000000c1, 0x00000038},
++ {0x000c209a, 0x00000030},
++ {0x0880e5bd, 0x00000005},
++ {0x000c2099, 0x00000030},
++ {0x0800e5bb, 0x00000005},
++ {0x000c209a, 0x00000030},
++ {0x0880e5bc, 0x00000005},
++ {0x000000c4, 0x00000008},
++ {0x0080e5bd, 0x00000005},
++ {0x0000e5bb, 0x00000005},
++ {0x0080e5bc, 0x00000005},
++ {0x00210000, 0x00000004},
++ {0x02800000, 0x00000004},
++ {0x00c000c8, 0x00000018},
++ {0x4180e000, 0x00000040},
++ {0x000000ca, 0x00000024},
++ {0x01000000, 0x0000000c},
++ {0x0100e51d, 0x0000000c},
++ {0x000045bb, 0x00000004},
++ {0x000080c4, 0x00000008},
++ {0x0000f3ce, 0x00000004},
++ {0x0140a000, 0x00000004},
++ {0x00cc2000, 0x00000004},
++ {0x08c053cf, 0x00000040},
++ {0x00008000, 0000000000},
++ {0x0000f3d2, 0x00000004},
++ {0x0140a000, 0x00000004},
++ {0x00cc2000, 0x00000004},
++ {0x08c053d3, 0x00000040},
++ {0x00008000, 0000000000},
++ {0x0000f39d, 0x00000004},
++ {0x0140a000, 0x00000004},
++ {0x00cc2000, 0x00000004},
++ {0x08c0539e, 0x00000040},
++ {0x00008000, 0000000000},
++ {0x03c00830, 0x00000004},
++ {0x4200e000, 0000000000},
++ {0x0000a000, 0x00000004},
++ {0x200045e0, 0x00000004},
++ {0x0000e5e1, 0000000000},
++ {0x00000001, 0000000000},
++ {0x000700e1, 0x00000004},
++ {0x0800e394, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
++ {0000000000, 0000000000},
+ };
+
+-static int RADEON_READ_PLL(drm_device_t *dev, int addr)
++static int RADEON_READ_PLL(drm_device_t * dev, int addr)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+@@ -825,145 +824,148 @@ static int RADEON_READ_PLL(drm_device_t
+ return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+ }
+
++static int RADEON_READ_PCIE(drm_radeon_private_t * dev_priv, int addr)
++{
++ RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
++ return RADEON_READ(RADEON_PCIE_DATA);
++}
++
+ #if RADEON_FIFO_DEBUG
+-static void radeon_status( drm_radeon_private_t *dev_priv )
++static void radeon_status(drm_radeon_private_t * dev_priv)
+ {
+- printk( "%s:\n", __FUNCTION__ );
+- printk( "RBBM_STATUS = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
+- printk( "CP_RB_RTPR = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
+- printk( "CP_RB_WTPR = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
+- printk( "AIC_CNTL = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
+- printk( "AIC_STAT = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
+- printk( "AIC_PT_BASE = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
+- printk( "TLB_ADDR = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
+- printk( "TLB_DATA = 0x%08x\n",
+- (unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
++ printk("%s:\n", __FUNCTION__);
++ printk("RBBM_STATUS = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
++ printk("CP_RB_RTPR = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
++ printk("CP_RB_WTPR = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
++ printk("AIC_CNTL = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
++ printk("AIC_STAT = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_AIC_STAT));
++ printk("AIC_PT_BASE = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
++ printk("TLB_ADDR = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
++ printk("TLB_DATA = 0x%08x\n",
++ (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
+ }
+ #endif
+
+-
+ /* ================================================================
+ * Engine, FIFO control
+ */
+
+-static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
++static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
+ {
+ u32 tmp;
+ int i;
+
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+- tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
++ tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT);
+ tmp |= RADEON_RB2D_DC_FLUSH_ALL;
+- RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
++ RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp);
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
+- & RADEON_RB2D_DC_BUSY) ) {
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT)
++ & RADEON_RB2D_DC_BUSY)) {
+ return 0;
+ }
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ #if RADEON_FIFO_DEBUG
+- DRM_ERROR( "failed!\n" );
+- radeon_status( dev_priv );
++ DRM_ERROR("failed!\n");
++ radeon_status(dev_priv);
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
+- int entries )
++static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
+ {
+ int i;
+
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
+- & RADEON_RBBM_FIFOCNT_MASK );
+- if ( slots >= entries ) return 0;
+- DRM_UDELAY( 1 );
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ int slots = (RADEON_READ(RADEON_RBBM_STATUS)
++ & RADEON_RBBM_FIFOCNT_MASK);
++ if (slots >= entries)
++ return 0;
++ DRM_UDELAY(1);
+ }
+
+ #if RADEON_FIFO_DEBUG
+- DRM_ERROR( "failed!\n" );
+- radeon_status( dev_priv );
++ DRM_ERROR("failed!\n");
++ radeon_status(dev_priv);
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
++static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
+ {
+ int i, ret;
+
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+- ret = radeon_do_wait_for_fifo( dev_priv, 64 );
+- if ( ret ) return ret;
++ ret = radeon_do_wait_for_fifo(dev_priv, 64);
++ if (ret)
++ return ret;
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- if ( !(RADEON_READ( RADEON_RBBM_STATUS )
+- & RADEON_RBBM_ACTIVE) ) {
+- radeon_do_pixcache_flush( dev_priv );
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ if (!(RADEON_READ(RADEON_RBBM_STATUS)
++ & RADEON_RBBM_ACTIVE)) {
++ radeon_do_pixcache_flush(dev_priv);
+ return 0;
+ }
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ #if RADEON_FIFO_DEBUG
+- DRM_ERROR( "failed!\n" );
+- radeon_status( dev_priv );
++ DRM_ERROR("failed!\n");
++ radeon_status(dev_priv);
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-
+ /* ================================================================
+ * CP control, initialization
+ */
+
+ /* Load the microcode for the CP */
+-static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
++static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+ {
+ int i;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- radeon_do_wait_for_idle( dev_priv );
++ radeon_do_wait_for_idle(dev_priv);
+
+- RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
++ RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+
+- if (dev_priv->microcode_version==UCODE_R200) {
++ if (dev_priv->microcode_version == UCODE_R200) {
+ DRM_INFO("Loading R200 Microcode\n");
+- for ( i = 0 ; i < 256 ; i++ )
+- {
+- RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+- R200_cp_microcode[i][1] );
+- RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+- R200_cp_microcode[i][0] );
++ for (i = 0; i < 256; i++) {
++ RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
++ R200_cp_microcode[i][1]);
++ RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
++ R200_cp_microcode[i][0]);
+ }
+- } else if (dev_priv->microcode_version==UCODE_R300) {
++ } else if (dev_priv->microcode_version == UCODE_R300) {
+ DRM_INFO("Loading R300 Microcode\n");
+- for ( i = 0 ; i < 256 ; i++ )
+- {
+- RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+- R300_cp_microcode[i][1] );
+- RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+- R300_cp_microcode[i][0] );
++ for (i = 0; i < 256; i++) {
++ RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
++ R300_cp_microcode[i][1]);
++ RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
++ R300_cp_microcode[i][0]);
+ }
+ } else {
+- for ( i = 0 ; i < 256 ; i++ ) {
+- RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+- radeon_cp_microcode[i][1] );
+- RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+- radeon_cp_microcode[i][0] );
++ for (i = 0; i < 256; i++) {
++ RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
++ radeon_cp_microcode[i][1]);
++ RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
++ radeon_cp_microcode[i][0]);
+ }
+ }
+ }
+@@ -972,25 +974,25 @@ static void radeon_cp_load_microcode( dr
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+-static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
++static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
+ {
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+ #if 0
+ u32 tmp;
+
+- tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
+- RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
++ tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
++ RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
+ #endif
+ }
+
+ /* Wait for the CP to go idle.
+ */
+-int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
++int radeon_do_cp_idle(drm_radeon_private_t * dev_priv)
+ {
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- BEGIN_RING( 6 );
++ BEGIN_RING(6);
+
+ RADEON_PURGE_CACHE();
+ RADEON_PURGE_ZCACHE();
+@@ -999,23 +1001,23 @@ int radeon_do_cp_idle( drm_radeon_privat
+ ADVANCE_RING();
+ COMMIT_RING();
+
+- return radeon_do_wait_for_idle( dev_priv );
++ return radeon_do_wait_for_idle(dev_priv);
+ }
+
+ /* Start the Command Processor.
+ */
+-static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
++static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
+ {
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- radeon_do_wait_for_idle( dev_priv );
++ radeon_do_wait_for_idle(dev_priv);
+
+- RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
++ RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
+
+ dev_priv->cp_running = 1;
+
+- BEGIN_RING( 6 );
++ BEGIN_RING(6);
+
+ RADEON_PURGE_CACHE();
+ RADEON_PURGE_ZCACHE();
+@@ -1029,14 +1031,14 @@ static void radeon_do_cp_start( drm_rade
+ * commands, so you must wait for the CP command stream to complete
+ * before calling this routine.
+ */
+-static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
++static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
+ {
+ u32 cur_read_ptr;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+- RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+- SET_RING_HEAD( dev_priv, cur_read_ptr );
++ cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
++ RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
++ SET_RING_HEAD(dev_priv, cur_read_ptr);
+ dev_priv->ring.tail = cur_read_ptr;
+ }
+
+@@ -1044,91 +1046,90 @@ static void radeon_do_cp_reset( drm_rade
+ * commands, so you must flush the command stream and wait for the CP
+ * to go idle before calling this routine.
+ */
+-static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
++static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
+ {
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
++ RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
+
+ dev_priv->cp_running = 0;
+ }
+
+ /* Reset the engine. This will stop the CP if it is running.
+ */
+-static int radeon_do_engine_reset( drm_device_t *dev )
++static int radeon_do_engine_reset(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+- DRM_DEBUG( "\n" );
+-
+- radeon_do_pixcache_flush( dev_priv );
+-
+- clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
+- mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
++ DRM_DEBUG("\n");
+
+- RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl |
+- RADEON_FORCEON_MCLKA |
+- RADEON_FORCEON_MCLKB |
+- RADEON_FORCEON_YCLKA |
+- RADEON_FORCEON_YCLKB |
+- RADEON_FORCEON_MC |
+- RADEON_FORCEON_AIC ) );
++ radeon_do_pixcache_flush(dev_priv);
+
+- rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
++ clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
++ mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
+
+- RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
+- RADEON_SOFT_RESET_CP |
++ RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
++ RADEON_FORCEON_MCLKA |
++ RADEON_FORCEON_MCLKB |
++ RADEON_FORCEON_YCLKA |
++ RADEON_FORCEON_YCLKB |
++ RADEON_FORCEON_MC |
++ RADEON_FORCEON_AIC));
++
++ rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
++
++ RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
++ RADEON_SOFT_RESET_CP |
++ RADEON_SOFT_RESET_HI |
++ RADEON_SOFT_RESET_SE |
++ RADEON_SOFT_RESET_RE |
++ RADEON_SOFT_RESET_PP |
++ RADEON_SOFT_RESET_E2 |
++ RADEON_SOFT_RESET_RB));
++ RADEON_READ(RADEON_RBBM_SOFT_RESET);
++ RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
++ ~(RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+- RADEON_SOFT_RESET_RB ) );
+- RADEON_READ( RADEON_RBBM_SOFT_RESET );
+- RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
+- ~( RADEON_SOFT_RESET_CP |
+- RADEON_SOFT_RESET_HI |
+- RADEON_SOFT_RESET_SE |
+- RADEON_SOFT_RESET_RE |
+- RADEON_SOFT_RESET_PP |
+- RADEON_SOFT_RESET_E2 |
+- RADEON_SOFT_RESET_RB ) ) );
+- RADEON_READ( RADEON_RBBM_SOFT_RESET );
+-
+-
+- RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
+- RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
+- RADEON_WRITE( RADEON_RBBM_SOFT_RESET, rbbm_soft_reset );
++ RADEON_SOFT_RESET_RB)));
++ RADEON_READ(RADEON_RBBM_SOFT_RESET);
++
++ RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
++ RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
++ RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
+
+ /* Reset the CP ring */
+- radeon_do_cp_reset( dev_priv );
++ radeon_do_cp_reset(dev_priv);
+
+ /* The CP is no longer running after an engine reset */
+ dev_priv->cp_running = 0;
+
+ /* Reset any pending vertex, indirect buffers */
+- radeon_freelist_reset( dev );
++ radeon_freelist_reset(dev);
+
+ return 0;
+ }
+
+-static void radeon_cp_init_ring_buffer( drm_device_t *dev,
+- drm_radeon_private_t *dev_priv )
++static void radeon_cp_init_ring_buffer(drm_device_t * dev,
++ drm_radeon_private_t * dev_priv)
+ {
+ u32 ring_start, cur_read_ptr;
+ u32 tmp;
+
+ /* Initialize the memory controller */
+- RADEON_WRITE( RADEON_MC_FB_LOCATION,
+- ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
+- | ( dev_priv->fb_location >> 16 ) );
++ RADEON_WRITE(RADEON_MC_FB_LOCATION,
++ ((dev_priv->gart_vm_start - 1) & 0xffff0000)
++ | (dev_priv->fb_location >> 16));
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
+- RADEON_WRITE( RADEON_MC_AGP_LOCATION,
+- (((dev_priv->gart_vm_start - 1 +
+- dev_priv->gart_size) & 0xffff0000) |
+- (dev_priv->gart_vm_start >> 16)) );
++ if (!dev_priv->is_pci) {
++ RADEON_WRITE(RADEON_MC_AGP_LOCATION,
++ (((dev_priv->gart_vm_start - 1 +
++ dev_priv->gart_size) & 0xffff0000) |
++ (dev_priv->gart_vm_start >> 16)));
+
+ ring_start = (dev_priv->cp_ring->offset
+ - dev->agp->base
+@@ -1139,25 +1140,24 @@ static void radeon_cp_init_ring_buffer(
+ - (unsigned long)dev->sg->virtual
+ + dev_priv->gart_vm_start);
+
+- RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
++ RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
+
+ /* Set the write pointer delay */
+- RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
++ RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
+
+ /* Initialize the ring buffer's read and write pointers */
+- cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+- RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+- SET_RING_HEAD( dev_priv, cur_read_ptr );
++ cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
++ RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
++ SET_RING_HEAD(dev_priv, cur_read_ptr);
+ dev_priv->ring.tail = cur_read_ptr;
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
++ if (!dev_priv->is_pci) {
+ /* set RADEON_AGP_BASE here instead of relying on X from user space */
+ RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
+- RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+- dev_priv->ring_rptr->offset
+- - dev->agp->base
+- + dev_priv->gart_vm_start);
++ RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
++ dev_priv->ring_rptr->offset
++ - dev->agp->base + dev_priv->gart_vm_start);
+ } else
+ #endif
+ {
+@@ -1168,11 +1168,10 @@ static void radeon_cp_init_ring_buffer(
+ (unsigned long)dev->sg->virtual;
+ page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+- RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+- entry->busaddr[page_ofs]);
+- DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+- (unsigned long) entry->busaddr[page_ofs],
+- entry->handle + tmp_ofs );
++ RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);
++ DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
++ (unsigned long)entry->busaddr[page_ofs],
++ entry->handle + tmp_ofs);
+ }
+
+ /* Initialize the scratch register pointer. This will cause
+@@ -1182,127 +1181,168 @@ static void radeon_cp_init_ring_buffer(
+ * We simply put this behind the ring read pointer, this works
+ * with PCI GART as well as (whatever kind of) AGP GART
+ */
+- RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
+- + RADEON_SCRATCH_REG_OFFSET );
++ RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
++ + RADEON_SCRATCH_REG_OFFSET);
+
+ dev_priv->scratch = ((__volatile__ u32 *)
+ dev_priv->ring_rptr->handle +
+ (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+- RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
++ RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
+
+ /* Writeback doesn't seem to work everywhere, test it first */
+- DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 );
+- RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
++ DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
++ RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
+
+- for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
+- if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef )
++ for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
++ if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
++ 0xdeadbeef)
+ break;
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+- if ( tmp < dev_priv->usec_timeout ) {
++ if (tmp < dev_priv->usec_timeout) {
+ dev_priv->writeback_works = 1;
+- DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
++ DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp);
+ } else {
+ dev_priv->writeback_works = 0;
+- DRM_DEBUG( "writeback test failed\n" );
++ DRM_DEBUG("writeback test failed\n");
++ }
++ if (radeon_no_wb == 1) {
++ dev_priv->writeback_works = 0;
++ DRM_DEBUG("writeback forced off\n");
+ }
+
+ dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
+- RADEON_WRITE( RADEON_LAST_FRAME_REG,
+- dev_priv->sarea_priv->last_frame );
++ RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+
+ dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
+- RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
+- dev_priv->sarea_priv->last_dispatch );
++ RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
++ dev_priv->sarea_priv->last_dispatch);
+
+ dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
+- RADEON_WRITE( RADEON_LAST_CLEAR_REG,
+- dev_priv->sarea_priv->last_clear );
++ RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
+
+ /* Set ring buffer size */
+ #ifdef __BIG_ENDIAN
+- RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT );
++ RADEON_WRITE(RADEON_CP_RB_CNTL,
++ dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
+ #else
+- RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
++ RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
+ #endif
+
+- radeon_do_wait_for_idle( dev_priv );
++ radeon_do_wait_for_idle(dev_priv);
+
+ /* Turn on bus mastering */
+- tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
+- RADEON_WRITE( RADEON_BUS_CNTL, tmp );
++ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
++ RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+
+ /* Sync everything up */
+- RADEON_WRITE( RADEON_ISYNC_CNTL,
+- (RADEON_ISYNC_ANY2D_IDLE3D |
+- RADEON_ISYNC_ANY3D_IDLE2D |
+- RADEON_ISYNC_WAIT_IDLEGUI |
+- RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
++ RADEON_WRITE(RADEON_ISYNC_CNTL,
++ (RADEON_ISYNC_ANY2D_IDLE3D |
++ RADEON_ISYNC_ANY3D_IDLE2D |
++ RADEON_ISYNC_WAIT_IDLEGUI |
++ RADEON_ISYNC_CPSCRATCH_IDLEGUI));
++}
++
++/* Enable or disable PCI-E GART on the chip */
++static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
++{
++ u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
++ if (on) {
++
++ DRM_DEBUG("programming pcie %08X %08lX %08X\n",
++ dev_priv->gart_vm_start,
++ (long)dev_priv->gart_info.bus_addr,
++ dev_priv->gart_size);
++ RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
++ dev_priv->gart_vm_start);
++ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
++ dev_priv->gart_info.bus_addr);
++ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
++ dev_priv->gart_vm_start);
++ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
++ dev_priv->gart_vm_start +
++ dev_priv->gart_size - 1);
++
++ RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0); /* ?? */
++
++ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
++ RADEON_PCIE_TX_GART_EN);
++ } else {
++ RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
++ tmp & ~RADEON_PCIE_TX_GART_EN);
++ }
+ }
+
+ /* Enable or disable PCI GART on the chip */
+-static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on )
++static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
+ {
+- u32 tmp = RADEON_READ( RADEON_AIC_CNTL );
++ u32 tmp = RADEON_READ(RADEON_AIC_CNTL);
+
+- if ( on ) {
+- RADEON_WRITE( RADEON_AIC_CNTL, tmp | RADEON_PCIGART_TRANSLATE_EN );
++ if (dev_priv->flags & CHIP_IS_PCIE) {
++ radeon_set_pciegart(dev_priv, on);
++ return;
++ }
++
++ if (on) {
++ RADEON_WRITE(RADEON_AIC_CNTL,
++ tmp | RADEON_PCIGART_TRANSLATE_EN);
+
+ /* set PCI GART page-table base address
+ */
+- RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
++ RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
+
+ /* set address range for PCI address translate
+ */
+- RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start );
+- RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
+- + dev_priv->gart_size - 1);
++ RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
++ RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
++ + dev_priv->gart_size - 1);
+
+ /* Turn off AGP aperture -- is this required for PCI GART?
+ */
+- RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
+- RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
++ RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0); /* ?? */
++ RADEON_WRITE(RADEON_AGP_COMMAND, 0); /* clear AGP_COMMAND */
+ } else {
+- RADEON_WRITE( RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN );
++ RADEON_WRITE(RADEON_AIC_CNTL,
++ tmp & ~RADEON_PCIGART_TRANSLATE_EN);
+ }
+ }
+
+-static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
++static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ dev_priv->is_pci = init->is_pci;
+
+- if ( dev_priv->is_pci && !dev->sg ) {
+- DRM_ERROR( "PCI GART memory not allocated!\n" );
++ if (dev_priv->is_pci && !dev->sg) {
++ DRM_ERROR("PCI GART memory not allocated!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+ dev_priv->usec_timeout = init->usec_timeout;
+- if ( dev_priv->usec_timeout < 1 ||
+- dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
+- DRM_DEBUG( "TIMEOUT problem!\n" );
++ if (dev_priv->usec_timeout < 1 ||
++ dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
++ DRM_DEBUG("TIMEOUT problem!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+- switch(init->func) {
++ switch (init->func) {
+ case RADEON_INIT_R200_CP:
+- dev_priv->microcode_version=UCODE_R200;
++ dev_priv->microcode_version = UCODE_R200;
+ break;
+ case RADEON_INIT_R300_CP:
+- dev_priv->microcode_version=UCODE_R300;
++ dev_priv->microcode_version = UCODE_R300;
+ break;
+ default:
+- dev_priv->microcode_version=UCODE_R100;
++ dev_priv->microcode_version = UCODE_R100;
+ }
+-
++
+ dev_priv->do_boxes = 0;
+ dev_priv->cp_mode = init->cp_mode;
+
+@@ -1310,15 +1350,15 @@ static int radeon_do_init_cp( drm_device
+ * but the ring can be in either AGP or PCI space for the ring
+ * read pointer.
+ */
+- if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
+- ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
+- DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
++ if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
++ (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
++ DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+- switch ( init->fb_bpp ) {
++ switch (init->fb_bpp) {
+ case 16:
+ dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
+ break;
+@@ -1327,12 +1367,12 @@ static int radeon_do_init_cp( drm_device
+ dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
+ break;
+ }
+- dev_priv->front_offset = init->front_offset;
+- dev_priv->front_pitch = init->front_pitch;
+- dev_priv->back_offset = init->back_offset;
+- dev_priv->back_pitch = init->back_pitch;
++ dev_priv->front_offset = init->front_offset;
++ dev_priv->front_pitch = init->front_pitch;
++ dev_priv->back_offset = init->back_offset;
++ dev_priv->back_pitch = init->back_pitch;
+
+- switch ( init->depth_bpp ) {
++ switch (init->depth_bpp) {
+ case 16:
+ dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ break;
+@@ -1341,8 +1381,8 @@ static int radeon_do_init_cp( drm_device
+ dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ break;
+ }
+- dev_priv->depth_offset = init->depth_offset;
+- dev_priv->depth_pitch = init->depth_pitch;
++ dev_priv->depth_offset = init->depth_offset;
++ dev_priv->depth_pitch = init->depth_pitch;
+
+ /* Hardware state for depth clears. Remove this if/when we no
+ * longer clear the depth buffer with a 3D rectangle. Hard-code
+@@ -1351,16 +1391,16 @@ static int radeon_do_init_cp( drm_device
+ */
+ dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
+ (dev_priv->color_fmt << 10) |
+- (dev_priv->microcode_version == UCODE_R100 ? RADEON_ZBLOCK16 : 0));
++ (dev_priv->microcode_version ==
++ UCODE_R100 ? RADEON_ZBLOCK16 : 0));
+
+- dev_priv->depth_clear.rb3d_zstencilcntl =
+- (dev_priv->depth_fmt |
+- RADEON_Z_TEST_ALWAYS |
+- RADEON_STENCIL_TEST_ALWAYS |
+- RADEON_STENCIL_S_FAIL_REPLACE |
+- RADEON_STENCIL_ZPASS_REPLACE |
+- RADEON_STENCIL_ZFAIL_REPLACE |
+- RADEON_Z_WRITE_ENABLE);
++ dev_priv->depth_clear.rb3d_zstencilcntl =
++ (dev_priv->depth_fmt |
++ RADEON_Z_TEST_ALWAYS |
++ RADEON_STENCIL_TEST_ALWAYS |
++ RADEON_STENCIL_S_FAIL_REPLACE |
++ RADEON_STENCIL_ZPASS_REPLACE |
++ RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
+
+ dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
+ RADEON_BFACE_SOLID |
+@@ -1382,8 +1422,8 @@ static int radeon_do_init_cp( drm_device
+ dev_priv->ring_rptr_offset = init->ring_rptr_offset;
+ dev_priv->buffers_offset = init->buffers_offset;
+ dev_priv->gart_textures_offset = init->gart_textures_offset;
+-
+- if(!dev_priv->sarea) {
++
++ if (!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+@@ -1391,21 +1431,21 @@ static int radeon_do_init_cp( drm_device
+ }
+
+ dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+- if(!dev_priv->mmio) {
++ if (!dev_priv->mmio) {
+ DRM_ERROR("could not find mmio region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
+- if(!dev_priv->cp_ring) {
++ if (!dev_priv->cp_ring) {
+ DRM_ERROR("could not find cp ring region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
+- if(!dev_priv->ring_rptr) {
++ if (!dev_priv->ring_rptr) {
+ DRM_ERROR("could not find ring read pointer!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+@@ -1413,16 +1453,17 @@ static int radeon_do_init_cp( drm_device
+ }
+ dev->agp_buffer_token = init->buffers_offset;
+ dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+- if(!dev->agp_buffer_map) {
++ if (!dev->agp_buffer_map) {
+ DRM_ERROR("could not find dma buffer region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( init->gart_textures_offset ) {
+- dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset);
+- if ( !dev_priv->gart_textures ) {
++ if (init->gart_textures_offset) {
++ dev_priv->gart_textures =
++ drm_core_findmap(dev, init->gart_textures_offset);
++ if (!dev_priv->gart_textures) {
+ DRM_ERROR("could not find GART texture region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+@@ -1431,17 +1472,17 @@ static int radeon_do_init_cp( drm_device
+ }
+
+ dev_priv->sarea_priv =
+- (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
+- init->sarea_priv_offset);
++ (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
++ init->sarea_priv_offset);
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
+- drm_core_ioremap( dev_priv->cp_ring, dev );
+- drm_core_ioremap( dev_priv->ring_rptr, dev );
+- drm_core_ioremap( dev->agp_buffer_map, dev );
+- if(!dev_priv->cp_ring->handle ||
+- !dev_priv->ring_rptr->handle ||
+- !dev->agp_buffer_map->handle) {
++ if (!dev_priv->is_pci) {
++ drm_core_ioremap(dev_priv->cp_ring, dev);
++ drm_core_ioremap(dev_priv->ring_rptr, dev);
++ drm_core_ioremap(dev->agp_buffer_map, dev);
++ if (!dev_priv->cp_ring->handle ||
++ !dev_priv->ring_rptr->handle ||
++ !dev->agp_buffer_map->handle) {
+ DRM_ERROR("could not find ioremap agp regions!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+@@ -1450,220 +1491,251 @@ static int radeon_do_init_cp( drm_device
+ } else
+ #endif
+ {
+- dev_priv->cp_ring->handle =
+- (void *)dev_priv->cp_ring->offset;
++ dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;
+ dev_priv->ring_rptr->handle =
+- (void *)dev_priv->ring_rptr->offset;
+- dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
+-
+- DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
+- dev_priv->cp_ring->handle );
+- DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
+- dev_priv->ring_rptr->handle );
+- DRM_DEBUG( "dev->agp_buffer_map->handle %p\n",
+- dev->agp_buffer_map->handle );
+- }
+-
+- dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
+- & 0xffff ) << 16;
+-
+- dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+- ( ( dev_priv->front_offset
+- + dev_priv->fb_location ) >> 10 ) );
+-
+- dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+- ( ( dev_priv->back_offset
+- + dev_priv->fb_location ) >> 10 ) );
+-
+- dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+- ( ( dev_priv->depth_offset
+- + dev_priv->fb_location ) >> 10 ) );
+-
++ (void *)dev_priv->ring_rptr->offset;
++ dev->agp_buffer_map->handle =
++ (void *)dev->agp_buffer_map->offset;
++
++ DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
++ dev_priv->cp_ring->handle);
++ DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
++ dev_priv->ring_rptr->handle);
++ DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
++ dev->agp_buffer_map->handle);
++ }
++
++ dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)
++ & 0xffff) << 16;
++
++ dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
++ ((dev_priv->front_offset
++ + dev_priv->fb_location) >> 10));
++
++ dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
++ ((dev_priv->back_offset
++ + dev_priv->fb_location) >> 10));
++
++ dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
++ ((dev_priv->depth_offset
++ + dev_priv->fb_location) >> 10));
+
+ dev_priv->gart_size = init->gart_size;
+ dev_priv->gart_vm_start = dev_priv->fb_location
+- + RADEON_READ( RADEON_CONFIG_APER_SIZE );
++ + RADEON_READ(RADEON_CONFIG_APER_SIZE);
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci )
++ if (!dev_priv->is_pci)
+ dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
+- - dev->agp->base
+- + dev_priv->gart_vm_start);
++ - dev->agp->base
++ + dev_priv->gart_vm_start);
+ else
+ #endif
+ dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
+ - (unsigned long)dev->sg->virtual
+ + dev_priv->gart_vm_start);
+
+- DRM_DEBUG( "dev_priv->gart_size %d\n",
+- dev_priv->gart_size );
+- DRM_DEBUG( "dev_priv->gart_vm_start 0x%x\n",
+- dev_priv->gart_vm_start );
+- DRM_DEBUG( "dev_priv->gart_buffers_offset 0x%lx\n",
+- dev_priv->gart_buffers_offset );
++ DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
++ DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
++ DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
++ dev_priv->gart_buffers_offset);
+
+- dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
+- dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
++ dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
++ dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
+ + init->ring_size / sizeof(u32));
+ dev_priv->ring.size = init->ring_size;
+- dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
++ dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+
+- dev_priv->ring.tail_mask =
+- (dev_priv->ring.size / sizeof(u32)) - 1;
++ dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+
+ dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
++ if (!dev_priv->is_pci) {
+ /* Turn off PCI GART */
+- radeon_set_pcigart( dev_priv, 0 );
++ radeon_set_pcigart(dev_priv, 0);
+ } else
+ #endif
+ {
+- if (!drm_ati_pcigart_init( dev, &dev_priv->phys_pci_gart,
+- &dev_priv->bus_pci_gart)) {
+- DRM_ERROR( "failed to init PCI GART!\n" );
++ /* if we have an offset set from userspace */
++ if (dev_priv->pcigart_offset) {
++ dev_priv->gart_info.bus_addr =
++ dev_priv->pcigart_offset + dev_priv->fb_location;
++ dev_priv->gart_info.addr =
++ (unsigned long)drm_ioremap(dev_priv->gart_info.
++ bus_addr,
++ RADEON_PCIGART_TABLE_SIZE,
++ dev);
++
++ dev_priv->gart_info.is_pcie =
++ !!(dev_priv->flags & CHIP_IS_PCIE);
++ dev_priv->gart_info.gart_table_location =
++ DRM_ATI_GART_FB;
++
++ DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n",
++ dev_priv->gart_info.addr,
++ dev_priv->pcigart_offset);
++ } else {
++ dev_priv->gart_info.gart_table_location =
++ DRM_ATI_GART_MAIN;
++ dev_priv->gart_info.addr =
++ dev_priv->gart_info.bus_addr = 0;
++ if (dev_priv->flags & CHIP_IS_PCIE) {
++ DRM_ERROR
++ ("Cannot use PCI Express without GART in FB memory\n");
++ radeon_do_cleanup_cp(dev);
++ return DRM_ERR(EINVAL);
++ }
++ }
++
++ if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
++ DRM_ERROR("failed to init PCI GART!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(ENOMEM);
+ }
+
+ /* Turn on PCI GART */
+- radeon_set_pcigart( dev_priv, 1 );
++ radeon_set_pcigart(dev_priv, 1);
+ }
+
+- radeon_cp_load_microcode( dev_priv );
+- radeon_cp_init_ring_buffer( dev, dev_priv );
++ radeon_cp_load_microcode(dev_priv);
++ radeon_cp_init_ring_buffer(dev, dev_priv);
+
+ dev_priv->last_buf = 0;
+
+ dev->dev_private = (void *)dev_priv;
+
+- radeon_do_engine_reset( dev );
++ radeon_do_engine_reset(dev);
+
+ return 0;
+ }
+
+-static int radeon_do_cleanup_cp( drm_device_t *dev )
++static int radeon_do_cleanup_cp(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ /* Make sure interrupts are disabled here because the uninstall ioctl
+ * may not have been called from userspace and after dev_private
+ * is freed, it's too late.
+ */
+- if ( dev->irq_enabled ) drm_irq_uninstall(dev);
++ if (dev->irq_enabled)
++ drm_irq_uninstall(dev);
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
+- if ( dev_priv->cp_ring != NULL )
+- drm_core_ioremapfree( dev_priv->cp_ring, dev );
+- if ( dev_priv->ring_rptr != NULL )
+- drm_core_ioremapfree( dev_priv->ring_rptr, dev );
+- if ( dev->agp_buffer_map != NULL )
+- {
+- drm_core_ioremapfree( dev->agp_buffer_map, dev );
++ if (!dev_priv->is_pci) {
++ if (dev_priv->cp_ring != NULL)
++ drm_core_ioremapfree(dev_priv->cp_ring, dev);
++ if (dev_priv->ring_rptr != NULL)
++ drm_core_ioremapfree(dev_priv->ring_rptr, dev);
++ if (dev->agp_buffer_map != NULL) {
++ drm_core_ioremapfree(dev->agp_buffer_map, dev);
+ dev->agp_buffer_map = NULL;
+ }
+ } else
+ #endif
+ {
+- if (!drm_ati_pcigart_cleanup( dev,
+- dev_priv->phys_pci_gart,
+- dev_priv->bus_pci_gart ))
+- DRM_ERROR( "failed to cleanup PCI GART!\n" );
++ if (dev_priv->gart_info.bus_addr)
++ if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
++ DRM_ERROR("failed to cleanup PCI GART!\n");
++
++ if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {
++ drm_ioremapfree((void *)dev_priv->gart_info.addr,
++ RADEON_PCIGART_TABLE_SIZE, dev);
++ dev_priv->gart_info.addr = 0;
++ }
+ }
+-
++
+ /* only clear to the start of flags */
+ memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
+
+ return 0;
+ }
+
+-/* This code will reinit the Radeon CP hardware after a resume from disc.
+- * AFAIK, it would be very difficult to pickle the state at suspend time, so
++/* This code will reinit the Radeon CP hardware after a resume from disc.
++ * AFAIK, it would be very difficult to pickle the state at suspend time, so
+ * here we make sure that all Radeon hardware initialisation is re-done without
+ * affecting running applications.
+ *
+ * Charl P. Botha <http://cpbotha.net>
+ */
+-static int radeon_do_resume_cp( drm_device_t *dev )
++static int radeon_do_resume_cp(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "Called with no initialization\n" );
+- return DRM_ERR( EINVAL );
++ if (!dev_priv) {
++ DRM_ERROR("Called with no initialization\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ DRM_DEBUG("Starting radeon_do_resume_cp()\n");
+
+ #if __OS_HAS_AGP
+- if ( !dev_priv->is_pci ) {
++ if (!dev_priv->is_pci) {
+ /* Turn off PCI GART */
+- radeon_set_pcigart( dev_priv, 0 );
++ radeon_set_pcigart(dev_priv, 0);
+ } else
+ #endif
+ {
+ /* Turn on PCI GART */
+- radeon_set_pcigart( dev_priv, 1 );
++ radeon_set_pcigart(dev_priv, 1);
+ }
+
+- radeon_cp_load_microcode( dev_priv );
+- radeon_cp_init_ring_buffer( dev, dev_priv );
++ radeon_cp_load_microcode(dev_priv);
++ radeon_cp_init_ring_buffer(dev, dev_priv);
+
+- radeon_do_engine_reset( dev );
++ radeon_do_engine_reset(dev);
+
+ DRM_DEBUG("radeon_do_resume_cp() complete\n");
+
+ return 0;
+ }
+
+-
+-int radeon_cp_init( DRM_IOCTL_ARGS )
++int radeon_cp_init(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_init_t init;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t __user *)data, sizeof(init) );
++ DRM_COPY_FROM_USER_IOCTL(init, (drm_radeon_init_t __user *) data,
++ sizeof(init));
+
+- if(init.func == RADEON_INIT_R300_CP)
++ if (init.func == RADEON_INIT_R300_CP)
+ r300_init_reg_flags();
+
+- switch ( init.func ) {
++ switch (init.func) {
+ case RADEON_INIT_CP:
+ case RADEON_INIT_R200_CP:
+ case RADEON_INIT_R300_CP:
+- return radeon_do_init_cp( dev, &init );
++ return radeon_do_init_cp(dev, &init);
+ case RADEON_CLEANUP_CP:
+- return radeon_do_cleanup_cp( dev );
++ return radeon_do_cleanup_cp(dev);
+ }
+
+ return DRM_ERR(EINVAL);
+ }
+
+-int radeon_cp_start( DRM_IOCTL_ARGS )
++int radeon_cp_start(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( dev_priv->cp_running ) {
+- DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
++ if (dev_priv->cp_running) {
++ DRM_DEBUG("%s while CP running\n", __FUNCTION__);
+ return 0;
+ }
+- if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
+- DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
+- __FUNCTION__, dev_priv->cp_mode );
++ if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
++ DRM_DEBUG("%s called with bogus CP mode (%d)\n",
++ __FUNCTION__, dev_priv->cp_mode);
+ return 0;
+ }
+
+- radeon_do_cp_start( dev_priv );
++ radeon_do_cp_start(dev_priv);
+
+ return 0;
+ }
+@@ -1671,17 +1743,18 @@ int radeon_cp_start( DRM_IOCTL_ARGS )
+ /* Stop the CP. The engine must have been idled before calling this
+ * routine.
+ */
+-int radeon_cp_stop( DRM_IOCTL_ARGS )
++int radeon_cp_stop(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_cp_stop_t stop;
+ int ret;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t __user *)data, sizeof(stop) );
++ DRM_COPY_FROM_USER_IOCTL(stop, (drm_radeon_cp_stop_t __user *) data,
++ sizeof(stop));
+
+ if (!dev_priv->cp_running)
+ return 0;
+@@ -1689,32 +1762,32 @@ int radeon_cp_stop( DRM_IOCTL_ARGS )
+ /* Flush any pending CP commands. This ensures any outstanding
+ * commands are exectuted by the engine before we turn it off.
+ */
+- if ( stop.flush ) {
+- radeon_do_cp_flush( dev_priv );
++ if (stop.flush) {
++ radeon_do_cp_flush(dev_priv);
+ }
+
+ /* If we fail to make the engine go idle, we return an error
+ * code so that the DRM ioctl wrapper can try again.
+ */
+- if ( stop.idle ) {
+- ret = radeon_do_cp_idle( dev_priv );
+- if ( ret ) return ret;
++ if (stop.idle) {
++ ret = radeon_do_cp_idle(dev_priv);
++ if (ret)
++ return ret;
+ }
+
+ /* Finally, we can turn off the CP. If the engine isn't idle,
+ * we will get some dropped triangles as they won't be fully
+ * rendered before the CP is shut down.
+ */
+- radeon_do_cp_stop( dev_priv );
++ radeon_do_cp_stop(dev_priv);
+
+ /* Reset the engine */
+- radeon_do_engine_reset( dev );
++ radeon_do_engine_reset(dev);
+
+ return 0;
+ }
+
+-
+-void radeon_do_release( drm_device_t *dev )
++void radeon_do_release(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int i, ret;
+@@ -1722,7 +1795,7 @@ void radeon_do_release( drm_device_t *de
+ if (dev_priv) {
+ if (dev_priv->cp_running) {
+ /* Stop the cp */
+- while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {
++ while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
+ DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
+ #ifdef __linux__
+ schedule();
+@@ -1730,47 +1803,49 @@ void radeon_do_release( drm_device_t *de
+ tsleep(&ret, PZERO, "rdnrel", 1);
+ #endif
+ }
+- radeon_do_cp_stop( dev_priv );
+- radeon_do_engine_reset( dev );
++ radeon_do_cp_stop(dev_priv);
++ radeon_do_engine_reset(dev);
+ }
+
+ /* Disable *all* interrupts */
+ if (dev_priv->mmio) /* remove this after permanent addmaps */
+- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
++ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+- if (dev_priv->mmio) {/* remove all surfaces */
++ if (dev_priv->mmio) { /* remove all surfaces */
+ for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+- RADEON_WRITE(RADEON_SURFACE0_INFO + 16*i, 0);
+- RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*i, 0);
+- RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*i, 0);
++ RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
++ RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
++ 16 * i, 0);
++ RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
++ 16 * i, 0);
+ }
+ }
+
+ /* Free memory heap structures */
+- radeon_mem_takedown( &(dev_priv->gart_heap) );
+- radeon_mem_takedown( &(dev_priv->fb_heap) );
++ radeon_mem_takedown(&(dev_priv->gart_heap));
++ radeon_mem_takedown(&(dev_priv->fb_heap));
+
+ /* deallocate kernel resources */
+- radeon_do_cleanup_cp( dev );
++ radeon_do_cleanup_cp(dev);
+ }
+ }
+
+ /* Just reset the CP ring. Called as part of an X Server engine reset.
+ */
+-int radeon_cp_reset( DRM_IOCTL_ARGS )
++int radeon_cp_reset(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_DEBUG("%s called before init done\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- radeon_do_cp_reset( dev_priv );
++ radeon_do_cp_reset(dev_priv);
+
+ /* The CP is no longer running after an engine reset */
+ dev_priv->cp_running = 0;
+@@ -1778,50 +1853,47 @@ int radeon_cp_reset( DRM_IOCTL_ARGS )
+ return 0;
+ }
+
+-int radeon_cp_idle( DRM_IOCTL_ARGS )
++int radeon_cp_idle(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- return radeon_do_cp_idle( dev_priv );
++ return radeon_do_cp_idle(dev_priv);
+ }
+
+ /* Added by Charl P. Botha to call radeon_do_resume_cp().
+ */
+-int radeon_cp_resume( DRM_IOCTL_ARGS )
++int radeon_cp_resume(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+
+ return radeon_do_resume_cp(dev);
+ }
+
+-
+-int radeon_engine_reset( DRM_IOCTL_ARGS )
++int radeon_engine_reset(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- return radeon_do_engine_reset( dev );
++ return radeon_do_engine_reset(dev);
+ }
+
+-
+ /* ================================================================
+ * Fullscreen mode
+ */
+
+ /* KW: Deprecated to say the least:
+ */
+-int radeon_fullscreen( DRM_IOCTL_ARGS )
++int radeon_fullscreen(DRM_IOCTL_ARGS)
+ {
+ return 0;
+ }
+
+-
+ /* ================================================================
+ * Freelist management
+ */
+@@ -1830,20 +1902,20 @@ int radeon_fullscreen( DRM_IOCTL_ARGS )
+ * bufs until freelist code is used. Note this hides a problem with
+ * the scratch register * (used to keep track of last buffer
+ * completed) being written to before * the last buffer has actually
+- * completed rendering.
++ * completed rendering.
+ *
+ * KW: It's also a good way to find free buffers quickly.
+ *
+ * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
+ * sleep. However, bugs in older versions of radeon_accel.c mean that
+ * we essentially have to do this, else old clients will break.
+- *
++ *
+ * However, it does leave open a potential deadlock where all the
+ * buffers are held by other clients, which can't release them because
+- * they can't get the lock.
++ * they can't get the lock.
+ */
+
+-drm_buf_t *radeon_freelist_get( drm_device_t *dev )
++drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -1852,19 +1924,19 @@ drm_buf_t *radeon_freelist_get( drm_devi
+ int i, t;
+ int start;
+
+- if ( ++dev_priv->last_buf >= dma->buf_count )
++ if (++dev_priv->last_buf >= dma->buf_count)
+ dev_priv->last_buf = 0;
+
+ start = dev_priv->last_buf;
+
+- for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
+- u32 done_age = GET_SCRATCH( 1 );
+- DRM_DEBUG("done_age = %d\n",done_age);
+- for ( i = start ; i < dma->buf_count ; i++ ) {
++ for (t = 0; t < dev_priv->usec_timeout; t++) {
++ u32 done_age = GET_SCRATCH(1);
++ DRM_DEBUG("done_age = %d\n", done_age);
++ for (i = start; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+- if ( buf->filp == 0 || (buf->pending &&
+- buf_priv->age <= done_age) ) {
++ if (buf->filp == 0 || (buf->pending &&
++ buf_priv->age <= done_age)) {
+ dev_priv->stats.requested_bufs++;
+ buf->pending = 0;
+ return buf;
+@@ -1873,16 +1945,17 @@ drm_buf_t *radeon_freelist_get( drm_devi
+ }
+
+ if (t) {
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ dev_priv->stats.freelist_loops++;
+ }
+ }
+
+- DRM_DEBUG( "returning NULL!\n" );
++ DRM_DEBUG("returning NULL!\n");
+ return NULL;
+ }
++
+ #if 0
+-drm_buf_t *radeon_freelist_get( drm_device_t *dev )
++drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -1892,18 +1965,18 @@ drm_buf_t *radeon_freelist_get( drm_devi
+ int start;
+ u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
+
+- if ( ++dev_priv->last_buf >= dma->buf_count )
++ if (++dev_priv->last_buf >= dma->buf_count)
+ dev_priv->last_buf = 0;
+
+ start = dev_priv->last_buf;
+ dev_priv->stats.freelist_loops++;
+-
+- for ( t = 0 ; t < 2 ; t++ ) {
+- for ( i = start ; i < dma->buf_count ; i++ ) {
++
++ for (t = 0; t < 2; t++) {
++ for (i = start; i < dma->buf_count; i++) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+- if ( buf->filp == 0 || (buf->pending &&
+- buf_priv->age <= done_age) ) {
++ if (buf->filp == 0 || (buf->pending &&
++ buf_priv->age <= done_age)) {
+ dev_priv->stats.requested_bufs++;
+ buf->pending = 0;
+ return buf;
+@@ -1916,73 +1989,74 @@ drm_buf_t *radeon_freelist_get( drm_devi
+ }
+ #endif
+
+-void radeon_freelist_reset( drm_device_t *dev )
++void radeon_freelist_reset(drm_device_t * dev)
+ {
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ dev_priv->last_buf = 0;
+- for ( i = 0 ; i < dma->buf_count ; i++ ) {
++ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ buf_priv->age = 0;
+ }
+ }
+
+-
+ /* ================================================================
+ * CP command submission
+ */
+
+-int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
++int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
+ {
+ drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+ int i;
+- u32 last_head = GET_RING_HEAD( dev_priv );
++ u32 last_head = GET_RING_HEAD(dev_priv);
+
+- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+- u32 head = GET_RING_HEAD( dev_priv );
++ for (i = 0; i < dev_priv->usec_timeout; i++) {
++ u32 head = GET_RING_HEAD(dev_priv);
+
+ ring->space = (head - ring->tail) * sizeof(u32);
+- if ( ring->space <= 0 )
++ if (ring->space <= 0)
+ ring->space += ring->size;
+- if ( ring->space > n )
++ if (ring->space > n)
+ return 0;
+-
++
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+ if (head != last_head)
+ i = 0;
+ last_head = head;
+
+- DRM_UDELAY( 1 );
++ DRM_UDELAY(1);
+ }
+
+ /* FIXME: This return value is ignored in the BEGIN_RING macro! */
+ #if RADEON_FIFO_DEBUG
+- radeon_status( dev_priv );
+- DRM_ERROR( "failed!\n" );
++ radeon_status(dev_priv);
++ DRM_ERROR("failed!\n");
+ #endif
+ return DRM_ERR(EBUSY);
+ }
+
+-static int radeon_cp_get_buffers( DRMFILE filp, drm_device_t *dev, drm_dma_t *d )
++static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev,
++ drm_dma_t * d)
+ {
+ int i;
+ drm_buf_t *buf;
+
+- for ( i = d->granted_count ; i < d->request_count ; i++ ) {
+- buf = radeon_freelist_get( dev );
+- if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
++ for (i = d->granted_count; i < d->request_count; i++) {
++ buf = radeon_freelist_get(dev);
++ if (!buf)
++ return DRM_ERR(EBUSY); /* NOTE: broken client */
+
+ buf->filp = filp;
+
+- if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
+- sizeof(buf->idx) ) )
++ if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
++ sizeof(buf->idx)))
+ return DRM_ERR(EFAULT);
+- if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
+- sizeof(buf->total) ) )
++ if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
++ sizeof(buf->total)))
+ return DRM_ERR(EFAULT);
+
+ d->granted_count++;
+@@ -1990,7 +2064,7 @@ static int radeon_cp_get_buffers( DRMFIL
+ return 0;
+ }
+
+-int radeon_cp_buffers( DRM_IOCTL_ARGS )
++int radeon_cp_buffers(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+@@ -1998,33 +2072,33 @@ int radeon_cp_buffers( DRM_IOCTL_ARGS )
+ drm_dma_t __user *argp = (void __user *)data;
+ drm_dma_t d;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( d, argp, sizeof(d) );
++ DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+
+ /* Please don't send us buffers.
+ */
+- if ( d.send_count != 0 ) {
+- DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
+- DRM_CURRENTPID, d.send_count );
++ if (d.send_count != 0) {
++ DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
++ DRM_CURRENTPID, d.send_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* We'll send you buffers.
+ */
+- if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
+- DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
+- DRM_CURRENTPID, d.request_count, dma->buf_count );
++ if (d.request_count < 0 || d.request_count > dma->buf_count) {
++ DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
++ DRM_CURRENTPID, d.request_count, dma->buf_count);
+ return DRM_ERR(EINVAL);
+ }
+
+ d.granted_count = 0;
+
+- if ( d.request_count ) {
+- ret = radeon_cp_get_buffers( filp, dev, &d );
++ if (d.request_count) {
++ ret = radeon_cp_get_buffers(filp, dev, &d);
+ }
+
+- DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );
++ DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
+
+ return ret;
+ }
+@@ -2051,13 +2125,16 @@ int radeon_driver_preinit(struct drm_dev
+ dev_priv->flags |= CHIP_HAS_HIERZ;
+ break;
+ default:
+- /* all other chips have no hierarchical z buffer */
++ /* all other chips have no hierarchical z buffer */
+ break;
+ }
+
+ if (drm_device_is_agp(dev))
+ dev_priv->flags |= CHIP_IS_AGP;
+-
++
++ if (drm_device_is_pcie(dev))
++ dev_priv->flags |= CHIP_IS_PCIE;
++
+ DRM_DEBUG("%s card detected\n",
+ ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));
+ return ret;
+diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
+--- a/drivers/char/drm/radeon_drm.h
++++ b/drivers/char/drm/radeon_drm.h
+@@ -57,78 +57,77 @@
+ #define RADEON_UPLOAD_TEX0IMAGES 0x00001000
+ #define RADEON_UPLOAD_TEX1IMAGES 0x00002000
+ #define RADEON_UPLOAD_TEX2IMAGES 0x00004000
+-#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
++#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
+ #define RADEON_REQUIRE_QUIESCENCE 0x00010000
+-#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */
++#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */
+ #define RADEON_UPLOAD_ALL 0x003effff
+ #define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff
+
+-
+ /* New style per-packet identifiers for use in cmd_buffer ioctl with
+ * the RADEON_EMIT_PACKET command. Comments relate new packets to old
+ * state bits and the packet size:
+ */
+-#define RADEON_EMIT_PP_MISC 0 /* context/7 */
+-#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
+-#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
+-#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
+-#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
+-#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
+-#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
+-#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
+-#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
+-#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
+-#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
+-#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
+-#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
+-#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
+-#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
+-#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
+-#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
+-#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
+-#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
+-#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
+-#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
+-#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
+-#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
+-#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
+-#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
+-#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
+-#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
+-#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
+-#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
+-#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */
+-#define R200_EMIT_TFACTOR_0 30 /* tf/7 */
+-#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */
+-#define R200_EMIT_VAP_CTL 32 /* vap/1 */
+-#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
+-#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
+-#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
+-#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
+-#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
+-#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
+-#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
+-#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
+-#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
+-#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
+-#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
+-#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
+-#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
+-#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
+-#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
+-#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
+-#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
+-#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
+-#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
+-#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
+-#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
+-#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
+-#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
+-#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
+-#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
+-#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
+-#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
+-#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
++#define RADEON_EMIT_PP_MISC 0 /* context/7 */
++#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
++#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
++#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
++#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
++#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
++#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
++#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
++#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
++#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
++#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
++#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
++#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
++#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
++#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
++#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
++#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
++#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
++#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
++#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
++#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
++#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
++#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
++#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
++#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
++#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
++#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
++#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
++#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
++#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */
++#define R200_EMIT_TFACTOR_0 30 /* tf/7 */
++#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */
++#define R200_EMIT_VAP_CTL 32 /* vap/1 */
++#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
++#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
++#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
++#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
++#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
++#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
++#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
++#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
++#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
++#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
++#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
++#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
++#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
++#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
++#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
++#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
++#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
++#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
++#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
++#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
++#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
++#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
++#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
++#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
++#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
++#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
++#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
++#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
+ #define R200_EMIT_PP_CUBIC_FACES_0 61
+ #define R200_EMIT_PP_CUBIC_OFFSETS_0 62
+ #define R200_EMIT_PP_CUBIC_FACES_1 63
+@@ -153,42 +152,50 @@
+ #define RADEON_EMIT_PP_CUBIC_FACES_2 82
+ #define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83
+ #define R200_EMIT_PP_TRI_PERF_CNTL 84
+-#define RADEON_MAX_STATE_PACKETS 85
++#define R200_EMIT_PP_AFS_0 85
++#define R200_EMIT_PP_AFS_1 86
++#define R200_EMIT_ATF_TFACTOR 87
++#define R200_EMIT_PP_TXCTLALL_0 88
++#define R200_EMIT_PP_TXCTLALL_1 89
++#define R200_EMIT_PP_TXCTLALL_2 90
++#define R200_EMIT_PP_TXCTLALL_3 91
++#define R200_EMIT_PP_TXCTLALL_4 92
++#define R200_EMIT_PP_TXCTLALL_5 93
++#define RADEON_MAX_STATE_PACKETS 94
+
+ /* Commands understood by cmd_buffer ioctl. More can be added but
+ * obviously these can't be removed or changed:
+ */
+-#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
+-#define RADEON_CMD_SCALARS 2 /* emit scalar data */
+-#define RADEON_CMD_VECTORS 3 /* emit vector data */
+-#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
+-#define RADEON_CMD_PACKET3 5 /* emit hw packet */
+-#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
+-#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */
+-#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note:
+- * doesn't make the cpu wait, just
+- * the graphics hardware */
+-
++#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
++#define RADEON_CMD_SCALARS 2 /* emit scalar data */
++#define RADEON_CMD_VECTORS 3 /* emit vector data */
++#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
++#define RADEON_CMD_PACKET3 5 /* emit hw packet */
++#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
++#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */
++#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note:
++ * doesn't make the cpu wait, just
++ * the graphics hardware */
+
+ typedef union {
+ int i;
+- struct {
++ struct {
+ unsigned char cmd_type, pad0, pad1, pad2;
+ } header;
+- struct {
++ struct {
+ unsigned char cmd_type, packet_id, pad0, pad1;
+ } packet;
+- struct {
+- unsigned char cmd_type, offset, stride, count;
++ struct {
++ unsigned char cmd_type, offset, stride, count;
+ } scalars;
+- struct {
+- unsigned char cmd_type, offset, stride, count;
++ struct {
++ unsigned char cmd_type, offset, stride, count;
+ } vectors;
+- struct {
+- unsigned char cmd_type, buf_idx, pad0, pad1;
++ struct {
++ unsigned char cmd_type, buf_idx, pad0, pad1;
+ } dma;
+- struct {
+- unsigned char cmd_type, flags, pad0, pad1;
++ struct {
++ unsigned char cmd_type, flags, pad0, pad1;
+ } wait;
+ } drm_radeon_cmd_header_t;
+
+@@ -204,10 +211,10 @@ typedef union {
+ * The interface has not been stabilized, so some of these may be removed
+ * and eventually reordered before stabilization.
+ */
+-#define R300_CMD_PACKET0 1
+-#define R300_CMD_VPU 2 /* emit vertex program upload */
+-#define R300_CMD_PACKET3 3 /* emit a packet3 */
+-#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */
++#define R300_CMD_PACKET0 1
++#define R300_CMD_VPU 2 /* emit vertex program upload */
++#define R300_CMD_PACKET3 3 /* emit a packet3 */
++#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */
+ #define R300_CMD_CP_DELAY 5
+ #define R300_CMD_DMA_DISCARD 6
+ #define R300_CMD_WAIT 7
+@@ -232,13 +239,13 @@ typedef union {
+ } packet3;
+ struct {
+ unsigned char cmd_type, packet;
+- unsigned short count; /* amount of packet2 to emit */
++ unsigned short count; /* amount of packet2 to emit */
+ } delay;
+ struct {
+ unsigned char cmd_type, buf_idx, pad0, pad1;
+ } dma;
+ struct {
+- unsigned char cmd_type, flags, pad0, pad1;
++ unsigned char cmd_type, flags, pad0, pad1;
+ } wait;
+ } drm_r300_cmd_header_t;
+
+@@ -292,7 +299,7 @@ typedef union {
+ #define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT)
+ #define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1)
+
+-#endif /* __RADEON_SAREA_DEFINES__ */
++#endif /* __RADEON_SAREA_DEFINES__ */
+
+ typedef struct {
+ unsigned int red;
+@@ -303,7 +310,7 @@ typedef struct {
+
+ typedef struct {
+ /* Context state */
+- unsigned int pp_misc; /* 0x1c14 */
++ unsigned int pp_misc; /* 0x1c14 */
+ unsigned int pp_fog_color;
+ unsigned int re_solid_color;
+ unsigned int rb3d_blendcntl;
+@@ -311,7 +318,7 @@ typedef struct {
+ unsigned int rb3d_depthpitch;
+ unsigned int rb3d_zstencilcntl;
+
+- unsigned int pp_cntl; /* 0x1c38 */
++ unsigned int pp_cntl; /* 0x1c38 */
+ unsigned int rb3d_cntl;
+ unsigned int rb3d_coloroffset;
+ unsigned int re_width_height;
+@@ -319,27 +326,27 @@ typedef struct {
+ unsigned int se_cntl;
+
+ /* Vertex format state */
+- unsigned int se_coord_fmt; /* 0x1c50 */
++ unsigned int se_coord_fmt; /* 0x1c50 */
+
+ /* Line state */
+- unsigned int re_line_pattern; /* 0x1cd0 */
++ unsigned int re_line_pattern; /* 0x1cd0 */
+ unsigned int re_line_state;
+
+- unsigned int se_line_width; /* 0x1db8 */
++ unsigned int se_line_width; /* 0x1db8 */
+
+ /* Bumpmap state */
+- unsigned int pp_lum_matrix; /* 0x1d00 */
++ unsigned int pp_lum_matrix; /* 0x1d00 */
+
+- unsigned int pp_rot_matrix_0; /* 0x1d58 */
++ unsigned int pp_rot_matrix_0; /* 0x1d58 */
+ unsigned int pp_rot_matrix_1;
+
+ /* Mask state */
+- unsigned int rb3d_stencilrefmask; /* 0x1d7c */
++ unsigned int rb3d_stencilrefmask; /* 0x1d7c */
+ unsigned int rb3d_ropcntl;
+ unsigned int rb3d_planemask;
+
+ /* Viewport state */
+- unsigned int se_vport_xscale; /* 0x1d98 */
++ unsigned int se_vport_xscale; /* 0x1d98 */
+ unsigned int se_vport_xoffset;
+ unsigned int se_vport_yscale;
+ unsigned int se_vport_yoffset;
+@@ -347,20 +354,19 @@ typedef struct {
+ unsigned int se_vport_zoffset;
+
+ /* Setup state */
+- unsigned int se_cntl_status; /* 0x2140 */
++ unsigned int se_cntl_status; /* 0x2140 */
+
+ /* Misc state */
+- unsigned int re_top_left; /* 0x26c0 */
++ unsigned int re_top_left; /* 0x26c0 */
+ unsigned int re_misc;
+ } drm_radeon_context_regs_t;
+
+ typedef struct {
+ /* Zbias state */
+- unsigned int se_zbias_factor; /* 0x1dac */
++ unsigned int se_zbias_factor; /* 0x1dac */
+ unsigned int se_zbias_constant;
+ } drm_radeon_context2_regs_t;
+
+-
+ /* Setup registers for each texture unit
+ */
+ typedef struct {
+@@ -378,11 +384,10 @@ typedef struct {
+ unsigned int finish;
+ unsigned int prim:8;
+ unsigned int stateidx:8;
+- unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
+- unsigned int vc_format; /* vertex format */
++ unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
++ unsigned int vc_format; /* vertex format */
+ } drm_radeon_prim_t;
+
+-
+ typedef struct {
+ drm_radeon_context_regs_t context;
+ drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
+@@ -390,7 +395,6 @@ typedef struct {
+ unsigned int dirty;
+ } drm_radeon_state_t;
+
+-
+ typedef struct {
+ /* The channel for communication of state information to the
+ * kernel on firing a vertex buffer with either of the
+@@ -413,16 +417,16 @@ typedef struct {
+ unsigned int last_dispatch;
+ unsigned int last_clear;
+
+- drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
++ drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
++ 1];
+ unsigned int tex_age[RADEON_NR_TEX_HEAPS];
+ int ctx_owner;
+- int pfState; /* number of 3d windows (0,1,2ormore) */
+- int pfCurrentPage; /* which buffer is being displayed? */
+- int crtc2_base; /* CRTC2 frame offset */
++ int pfState; /* number of 3d windows (0,1,2ormore) */
++ int pfCurrentPage; /* which buffer is being displayed? */
++ int crtc2_base; /* CRTC2 frame offset */
+ int tiling_enabled; /* set by drm, read by 2d + 3d clients */
+ } drm_radeon_sarea_t;
+
+-
+ /* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmRadeon.h)
+ *
+@@ -432,15 +436,15 @@ typedef struct {
+ /* Radeon specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+-#define DRM_RADEON_CP_INIT 0x00
+-#define DRM_RADEON_CP_START 0x01
++#define DRM_RADEON_CP_INIT 0x00
++#define DRM_RADEON_CP_START 0x01
+ #define DRM_RADEON_CP_STOP 0x02
+ #define DRM_RADEON_CP_RESET 0x03
+ #define DRM_RADEON_CP_IDLE 0x04
+-#define DRM_RADEON_RESET 0x05
++#define DRM_RADEON_RESET 0x05
+ #define DRM_RADEON_FULLSCREEN 0x06
+-#define DRM_RADEON_SWAP 0x07
+-#define DRM_RADEON_CLEAR 0x08
++#define DRM_RADEON_SWAP 0x07
++#define DRM_RADEON_CLEAR 0x08
+ #define DRM_RADEON_VERTEX 0x09
+ #define DRM_RADEON_INDICES 0x0A
+ #define DRM_RADEON_NOT_USED
+@@ -491,7 +495,7 @@ typedef struct {
+
+ typedef struct drm_radeon_init {
+ enum {
+- RADEON_INIT_CP = 0x01,
++ RADEON_INIT_CP = 0x01,
+ RADEON_CLEANUP_CP = 0x02,
+ RADEON_INIT_R200_CP = 0x03,
+ RADEON_INIT_R300_CP = 0x04
+@@ -524,7 +528,7 @@ typedef struct drm_radeon_cp_stop {
+
+ typedef struct drm_radeon_fullscreen {
+ enum {
+- RADEON_INIT_FULLSCREEN = 0x01,
++ RADEON_INIT_FULLSCREEN = 0x01,
+ RADEON_CLEANUP_FULLSCREEN = 0x02
+ } func;
+ } drm_radeon_fullscreen_t;
+@@ -545,15 +549,15 @@ typedef struct drm_radeon_clear {
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int color_mask;
+- unsigned int depth_mask; /* misnamed field: should be stencil */
++ unsigned int depth_mask; /* misnamed field: should be stencil */
+ drm_radeon_clear_rect_t __user *depth_boxes;
+ } drm_radeon_clear_t;
+
+ typedef struct drm_radeon_vertex {
+ int prim;
+- int idx; /* Index of vertex buffer */
+- int count; /* Number of vertices in buffer */
+- int discard; /* Client finished with buffer? */
++ int idx; /* Index of vertex buffer */
++ int count; /* Number of vertices in buffer */
++ int discard; /* Client finished with buffer? */
+ } drm_radeon_vertex_t;
+
+ typedef struct drm_radeon_indices {
+@@ -561,7 +565,7 @@ typedef struct drm_radeon_indices {
+ int idx;
+ int start;
+ int end;
+- int discard; /* Client finished with buffer? */
++ int discard; /* Client finished with buffer? */
+ } drm_radeon_indices_t;
+
+ /* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
+@@ -569,8 +573,8 @@ typedef struct drm_radeon_indices {
+ * - supports driver change to emit native primitives
+ */
+ typedef struct drm_radeon_vertex2 {
+- int idx; /* Index of vertex buffer */
+- int discard; /* Client finished with buffer? */
++ int idx; /* Index of vertex buffer */
++ int discard; /* Client finished with buffer? */
+ int nr_states;
+ drm_radeon_state_t __user *state;
+ int nr_prims;
+@@ -578,10 +582,10 @@ typedef struct drm_radeon_vertex2 {
+ } drm_radeon_vertex2_t;
+
+ /* v1.3 - obsoletes drm_radeon_vertex2
+- * - allows arbitarily large cliprect list
++ * - allows arbitarily large cliprect list
+ * - allows updating of tcl packet, vector and scalar state
+ * - allows memory-efficient description of state updates
+- * - allows state to be emitted without a primitive
++ * - allows state to be emitted without a primitive
+ * (for clears, ctx switches)
+ * - allows more than one dma buffer to be referenced per ioctl
+ * - supports tcl driver
+@@ -595,7 +599,7 @@ typedef struct drm_radeon_cmd_buffer {
+ } drm_radeon_cmd_buffer_t;
+
+ typedef struct drm_radeon_tex_image {
+- unsigned int x, y; /* Blit coordinates */
++ unsigned int x, y; /* Blit coordinates */
+ unsigned int width, height;
+ const void __user *data;
+ } drm_radeon_tex_image_t;
+@@ -604,7 +608,7 @@ typedef struct drm_radeon_texture {
+ unsigned int offset;
+ int pitch;
+ int format;
+- int width; /* Texture image coordinates */
++ int width; /* Texture image coordinates */
+ int height;
+ drm_radeon_tex_image_t __user *image;
+ } drm_radeon_texture_t;
+@@ -620,19 +624,18 @@ typedef struct drm_radeon_indirect {
+ int discard;
+ } drm_radeon_indirect_t;
+
+-
+ /* 1.3: An ioctl to get parameters that aren't available to the 3d
+- * client any other way.
++ * client any other way.
+ */
+-#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */
++#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */
+ #define RADEON_PARAM_LAST_FRAME 2
+ #define RADEON_PARAM_LAST_DISPATCH 3
+ #define RADEON_PARAM_LAST_CLEAR 4
+ /* Added with DRM version 1.6. */
+ #define RADEON_PARAM_IRQ_NR 5
+-#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */
++#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */
+ /* Added with DRM version 1.8. */
+-#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */
++#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */
+ #define RADEON_PARAM_STATUS_HANDLE 8
+ #define RADEON_PARAM_SAREA_HANDLE 9
+ #define RADEON_PARAM_GART_TEX_HANDLE 10
+@@ -663,10 +666,9 @@ typedef struct drm_radeon_mem_free {
+ typedef struct drm_radeon_mem_init_heap {
+ int region;
+ int size;
+- int start;
++ int start;
+ } drm_radeon_mem_init_heap_t;
+
+-
+ /* 1.6: Userspace can request & wait on irq's:
+ */
+ typedef struct drm_radeon_irq_emit {
+@@ -677,18 +679,18 @@ typedef struct drm_radeon_irq_wait {
+ int irq_seq;
+ } drm_radeon_irq_wait_t;
+
+-
+ /* 1.10: Clients tell the DRM where they think the framebuffer is located in
+ * the card's address space, via a new generic ioctl to set parameters
+ */
+
+ typedef struct drm_radeon_setparam {
+ unsigned int param;
+- int64_t value;
++ int64_t value;
+ } drm_radeon_setparam_t;
+
+ #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
+ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
++#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
+
+ /* 1.14: Clients can allocate/free a surface
+ */
+diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
+--- a/drivers/char/drm/radeon_drv.c
++++ b/drivers/char/drm/radeon_drv.c
+@@ -29,7 +29,6 @@
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+-
+ #include <linux/config.h>
+ #include "drmP.h"
+ #include "drm.h"
+@@ -38,30 +37,33 @@
+
+ #include "drm_pciids.h"
+
+-static int postinit( struct drm_device *dev, unsigned long flags )
++int radeon_no_wb;
++
++MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n");
++module_param_named(no_wb, radeon_no_wb, int, 0444);
++
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -69,11 +71,11 @@ static struct pci_device_id pciidlist[]
+ radeon_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t radeon_ioctls[];
+-extern int radeon_max_ioctl;
+-
+ static struct drm_driver driver = {
+- .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
++ .driver_features =
++ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
++ DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
++ DRIVER_IRQ_VBL,
+ .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
+ .preinit = radeon_driver_preinit,
+ .presetup = radeon_presetup,
+@@ -95,21 +97,22 @@ static struct drm_driver driver = {
+ .ioctls = radeon_ioctls,
+ .dma_ioctl = radeon_cp_buffers,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
+ #ifdef CONFIG_COMPAT
+- .compat_ioctl = radeon_compat_ioctl,
++ .compat_ioctl = radeon_compat_ioctl,
+ #endif
+- },
++ }
++ ,
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init radeon_init(void)
+@@ -126,6 +129,6 @@ static void __exit radeon_exit(void)
+ module_init(radeon_init);
+ module_exit(radeon_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
+--- a/drivers/char/drm/radeon_drv.h
++++ b/drivers/char/drm/radeon_drv.h
+@@ -38,7 +38,7 @@
+
+ #define DRIVER_NAME "radeon"
+ #define DRIVER_DESC "ATI Radeon"
+-#define DRIVER_DATE "20050311"
++#define DRIVER_DATE "20050911"
+
+ /* Interface history:
+ *
+@@ -68,7 +68,7 @@
+ * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
+ * Add texture rectangle support for r100.
+ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
+- * clients use to tell the DRM where they think the framebuffer is
++ * clients use to tell the DRM where they think the framebuffer is
+ * located in the card's address space
+ * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
+ * and GL_EXT_blend_[func|equation]_separate on r200
+@@ -83,9 +83,14 @@
+ * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
+ * texture filtering on r200
+ * 1.17- Add initial support for R300 (3D).
++ * 1.18- Add support for GL_ATI_fragment_shader, new packets
++ * R200_EMIT_PP_AFS_0/1, R200_EMIT_PP_TXCTLALL_0-5 (replaces
++ * R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR
++ * (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
++ * 1.19- Add support for gart table in FB memory and PCIE r300
+ */
+ #define DRIVER_MAJOR 1
+-#define DRIVER_MINOR 17
++#define DRIVER_MINOR 19
+ #define DRIVER_PATCHLEVEL 0
+
+ #define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
+@@ -129,14 +134,15 @@ enum radeon_chip_flags {
+ CHIP_IS_IGP = 0x00020000UL,
+ CHIP_SINGLE_CRTC = 0x00040000UL,
+ CHIP_IS_AGP = 0x00080000UL,
+- CHIP_HAS_HIERZ = 0x00100000UL,
++ CHIP_HAS_HIERZ = 0x00100000UL,
++ CHIP_IS_PCIE = 0x00200000UL,
+ };
+
+ typedef struct drm_radeon_freelist {
+- unsigned int age;
+- drm_buf_t *buf;
+- struct drm_radeon_freelist *next;
+- struct drm_radeon_freelist *prev;
++ unsigned int age;
++ drm_buf_t *buf;
++ struct drm_radeon_freelist *next;
++ struct drm_radeon_freelist *prev;
+ } drm_radeon_freelist_t;
+
+ typedef struct drm_radeon_ring_buffer {
+@@ -198,8 +204,8 @@ typedef struct drm_radeon_private {
+ int cp_mode;
+ int cp_running;
+
+- drm_radeon_freelist_t *head;
+- drm_radeon_freelist_t *tail;
++ drm_radeon_freelist_t *head;
++ drm_radeon_freelist_t *tail;
+ int last_buf;
+ volatile u32 *scratch;
+ int writeback_works;
+@@ -209,8 +215,6 @@ typedef struct drm_radeon_private {
+ int microcode_version;
+
+ int is_pci;
+- unsigned long phys_pci_gart;
+- dma_addr_t bus_pci_gart;
+
+ struct {
+ u32 boxes;
+@@ -242,7 +246,7 @@ typedef struct drm_radeon_private {
+ u32 depth_pitch_offset;
+
+ drm_radeon_depth_clear_t depth_clear;
+-
++
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+ unsigned long ring_offset;
+@@ -260,11 +264,14 @@ typedef struct drm_radeon_private {
+ struct mem_block *fb_heap;
+
+ /* SW interrupt */
+- wait_queue_head_t swi_queue;
+- atomic_t swi_emitted;
++ wait_queue_head_t swi_queue;
++ atomic_t swi_emitted;
+
+ struct radeon_surface surfaces[RADEON_MAX_SURFACES];
+- struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES];
++ struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
++
++ unsigned long pcigart_offset;
++ drm_ati_pcigart_info gart_info;
+
+ /* starting from here on, data is preserved accross an open */
+ uint32_t flags; /* see radeon_chip_flags */
+@@ -274,63 +281,76 @@ typedef struct drm_radeon_buf_priv {
+ u32 age;
+ } drm_radeon_buf_priv_t;
+
++typedef struct drm_radeon_kcmd_buffer {
++ int bufsz;
++ char *buf;
++ int nbox;
++ drm_clip_rect_t __user *boxes;
++} drm_radeon_kcmd_buffer_t;
++
++extern int radeon_no_wb;
++extern drm_ioctl_desc_t radeon_ioctls[];
++extern int radeon_max_ioctl;
++
+ /* radeon_cp.c */
+-extern int radeon_cp_init( DRM_IOCTL_ARGS );
+-extern int radeon_cp_start( DRM_IOCTL_ARGS );
+-extern int radeon_cp_stop( DRM_IOCTL_ARGS );
+-extern int radeon_cp_reset( DRM_IOCTL_ARGS );
+-extern int radeon_cp_idle( DRM_IOCTL_ARGS );
+-extern int radeon_cp_resume( DRM_IOCTL_ARGS );
+-extern int radeon_engine_reset( DRM_IOCTL_ARGS );
+-extern int radeon_fullscreen( DRM_IOCTL_ARGS );
+-extern int radeon_cp_buffers( DRM_IOCTL_ARGS );
++extern int radeon_cp_init(DRM_IOCTL_ARGS);
++extern int radeon_cp_start(DRM_IOCTL_ARGS);
++extern int radeon_cp_stop(DRM_IOCTL_ARGS);
++extern int radeon_cp_reset(DRM_IOCTL_ARGS);
++extern int radeon_cp_idle(DRM_IOCTL_ARGS);
++extern int radeon_cp_resume(DRM_IOCTL_ARGS);
++extern int radeon_engine_reset(DRM_IOCTL_ARGS);
++extern int radeon_fullscreen(DRM_IOCTL_ARGS);
++extern int radeon_cp_buffers(DRM_IOCTL_ARGS);
+
+-extern void radeon_freelist_reset( drm_device_t *dev );
+-extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
++extern void radeon_freelist_reset(drm_device_t * dev);
++extern drm_buf_t *radeon_freelist_get(drm_device_t * dev);
+
+-extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
++extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
+
+-extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
++extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv);
+
+ extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
+ extern int radeon_presetup(struct drm_device *dev);
+ extern int radeon_driver_postcleanup(struct drm_device *dev);
+
+-extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
+-extern int radeon_mem_free( DRM_IOCTL_ARGS );
+-extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
+-extern void radeon_mem_takedown( struct mem_block **heap );
+-extern void radeon_mem_release( DRMFILE filp, struct mem_block *heap );
++extern int radeon_mem_alloc(DRM_IOCTL_ARGS);
++extern int radeon_mem_free(DRM_IOCTL_ARGS);
++extern int radeon_mem_init_heap(DRM_IOCTL_ARGS);
++extern void radeon_mem_takedown(struct mem_block **heap);
++extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap);
+
+ /* radeon_irq.c */
+-extern int radeon_irq_emit( DRM_IOCTL_ARGS );
+-extern int radeon_irq_wait( DRM_IOCTL_ARGS );
++extern int radeon_irq_emit(DRM_IOCTL_ARGS);
++extern int radeon_irq_wait(DRM_IOCTL_ARGS);
+
+-extern void radeon_do_release(drm_device_t *dev);
+-extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+-extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS );
+-extern void radeon_driver_irq_preinstall( drm_device_t *dev );
+-extern void radeon_driver_irq_postinstall( drm_device_t *dev );
+-extern void radeon_driver_irq_uninstall( drm_device_t *dev );
+-extern void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+-extern void radeon_driver_pretakedown(drm_device_t *dev);
+-extern int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv);
+-extern void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv);
+-
+-extern int radeon_preinit( struct drm_device *dev, unsigned long flags );
+-extern int radeon_postinit( struct drm_device *dev, unsigned long flags );
+-extern int radeon_postcleanup( struct drm_device *dev );
++extern void radeon_do_release(drm_device_t * dev);
++extern int radeon_driver_vblank_wait(drm_device_t * dev,
++ unsigned int *sequence);
++extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
++extern void radeon_driver_irq_preinstall(drm_device_t * dev);
++extern void radeon_driver_irq_postinstall(drm_device_t * dev);
++extern void radeon_driver_irq_uninstall(drm_device_t * dev);
++extern void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp);
++extern void radeon_driver_pretakedown(drm_device_t * dev);
++extern int radeon_driver_open_helper(drm_device_t * dev,
++ drm_file_t * filp_priv);
++extern void radeon_driver_free_filp_priv(drm_device_t * dev,
++ drm_file_t * filp_priv);
++
++extern int radeon_preinit(struct drm_device *dev, unsigned long flags);
++extern int radeon_postinit(struct drm_device *dev, unsigned long flags);
++extern int radeon_postcleanup(struct drm_device *dev);
+
+ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+-
+ /* r300_cmdbuf.c */
+ extern void r300_init_reg_flags(void);
+
+-extern int r300_do_cp_cmdbuf(drm_device_t* dev, DRMFILE filp,
+- drm_file_t* filp_priv,
+- drm_radeon_cmd_buffer_t* cmdbuf);
++extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
++ drm_file_t * filp_priv,
++ drm_radeon_kcmd_buffer_t * cmdbuf);
+
+ /* Flags for stats.boxes
+ */
+@@ -340,8 +360,6 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ #define RADEON_BOX_WAIT_IDLE 0x8
+ #define RADEON_BOX_TEXTURE_LOAD 0x10
+
+-
+-
+ /* Register definitions, register access macros and drmAddMap constants
+ * for Radeon kernel driver.
+ */
+@@ -369,6 +387,25 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ #define RADEON_CRTC2_OFFSET 0x0324
+ #define RADEON_CRTC2_OFFSET_CNTL 0x0328
+
++#define RADEON_PCIE_INDEX 0x0030
++#define RADEON_PCIE_DATA 0x0034
++#define RADEON_PCIE_TX_GART_CNTL 0x10
++# define RADEON_PCIE_TX_GART_EN (1 << 0)
++# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0<<1)
++# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1<<1)
++# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3<<1)
++# define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0<<3)
++# define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1<<3)
++# define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1<<5)
++# define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1<<8)
++#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
++#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
++#define RADEON_PCIE_TX_GART_BASE 0x13
++#define RADEON_PCIE_TX_GART_START_LO 0x14
++#define RADEON_PCIE_TX_GART_START_HI 0x15
++#define RADEON_PCIE_TX_GART_END_LO 0x16
++#define RADEON_PCIE_TX_GART_END_HI 0x17
++
+ #define RADEON_MPP_TB_CONFIG 0x01c0
+ #define RADEON_MEM_CNTL 0x0140
+ #define RADEON_MEM_SDRAM_MODE_REG 0x0158
+@@ -416,7 +453,6 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
+ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
+-
+ #define RADEON_GEN_INT_CNTL 0x0040
+ # define RADEON_CRTC_VBLANK_MASK (1 << 0)
+ # define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
+@@ -624,7 +660,6 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ # define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
+ # define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
+
+-
+ /* CP registers */
+ #define RADEON_CP_ME_RAM_ADDR 0x07d4
+ #define RADEON_CP_ME_RAM_RADDR 0x07d8
+@@ -672,7 +707,7 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ # define RADEON_CP_NEXT_CHAR 0x00001900
+ # define RADEON_CP_PLY_NEXTSCAN 0x00001D00
+ # define RADEON_CP_SET_SCISSORS 0x00001E00
+- /* GEN_INDX_PRIM is unsupported starting with R300 */
++ /* GEN_INDX_PRIM is unsupported starting with R300 */
+ # define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300
+ # define RADEON_WAIT_FOR_IDLE 0x00002600
+ # define RADEON_3D_DRAW_VBUF 0x00002800
+@@ -756,19 +791,19 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ #define R200_PP_TXCBLEND_5 0x2f50
+ #define R200_PP_TXCBLEND_6 0x2f60
+ #define R200_PP_TXCBLEND_7 0x2f70
+-#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268
++#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268
+ #define R200_PP_TFACTOR_0 0x2ee0
+ #define R200_SE_VTX_FMT_0 0x2088
+ #define R200_SE_VAP_CNTL 0x2080
+ #define R200_SE_TCL_MATRIX_SEL_0 0x2230
+-#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8
+-#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0
+-#define R200_PP_TXFILTER_5 0x2ca0
+-#define R200_PP_TXFILTER_4 0x2c80
+-#define R200_PP_TXFILTER_3 0x2c60
+-#define R200_PP_TXFILTER_2 0x2c40
+-#define R200_PP_TXFILTER_1 0x2c20
+-#define R200_PP_TXFILTER_0 0x2c00
++#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8
++#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0
++#define R200_PP_TXFILTER_5 0x2ca0
++#define R200_PP_TXFILTER_4 0x2c80
++#define R200_PP_TXFILTER_3 0x2c60
++#define R200_PP_TXFILTER_2 0x2c40
++#define R200_PP_TXFILTER_1 0x2c20
++#define R200_PP_TXFILTER_0 0x2c00
+ #define R200_PP_TXOFFSET_5 0x2d78
+ #define R200_PP_TXOFFSET_4 0x2d60
+ #define R200_PP_TXOFFSET_3 0x2d48
+@@ -822,13 +857,13 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ #define R200_RE_SCISSOR_TL_0 0x1cd8
+ #define R200_RE_SCISSOR_TL_1 0x1ce0
+ #define R200_RE_SCISSOR_TL_2 0x1ce8
+-#define R200_RB3D_DEPTHXY_OFFSET 0x1d60
++#define R200_RB3D_DEPTHXY_OFFSET 0x1d60
+ #define R200_RE_AUX_SCISSOR_CNTL 0x26f0
+ #define R200_SE_VTX_STATE_CNTL 0x2180
+ #define R200_RE_POINTSIZE 0x2648
+ #define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
+
+-#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
++#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */
+ #define RADEON_PP_TEX_SIZE_1 0x1d0c
+ #define RADEON_PP_TEX_SIZE_2 0x1d14
+
+@@ -849,7 +884,7 @@ extern int r300_do_cp_cmdbuf(drm_device_
+ #define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b
+ #define R200_3D_DRAW_IMMD_2 0xC0003500
+ #define R200_SE_VTX_FMT_1 0x208c
+-#define R200_RE_CNTL 0x1c50
++#define R200_RE_CNTL 0x1c50
+
+ #define R200_RB3D_BLENDCOLOR 0x3218
+
+@@ -857,6 +892,9 @@ extern int r300_do_cp_cmdbuf(drm_device_
+
+ #define R200_PP_TRI_PERF 0x2cf8
+
++#define R200_PP_AFS_0 0x2f80
++#define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */
++
+ /* Constants */
+ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
+
+@@ -871,6 +909,8 @@ extern int r300_do_cp_cmdbuf(drm_device_
+
+ #define RADEON_RING_HIGH_MARK 128
+
++#define RADEON_PCIGART_TABLE_SIZE (32*1024)
++
+ #define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
+ #define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
+ #define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
+@@ -883,6 +923,13 @@ do { \
+ RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
+ } while (0)
+
++#define RADEON_WRITE_PCIE( addr, val ) \
++do { \
++ RADEON_WRITE8( RADEON_PCIE_INDEX, \
++ ((addr) & 0xff)); \
++ RADEON_WRITE( RADEON_PCIE_DATA, (val) ); \
++} while (0)
++
+ #define CP_PACKET0( reg, n ) \
+ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+ #define CP_PACKET0_TABLE( reg, n ) \
+@@ -894,7 +941,6 @@ do { \
+ #define CP_PACKET3( pkt, n ) \
+ (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+-
+ /* ================================================================
+ * Engine control helper macros
+ */
+@@ -943,12 +989,11 @@ do { \
+ OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
+ } while (0)
+
+-
+ /* ================================================================
+ * Misc helper macros
+ */
+
+-/* Perfbox functionality only.
++/* Perfbox functionality only.
+ */
+ #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
+ do { \
+@@ -985,7 +1030,6 @@ do { \
+ OUT_RING( age ); \
+ } while (0)
+
+-
+ /* ================================================================
+ * Ring control
+ */
+@@ -1046,7 +1090,6 @@ do { \
+ OUT_RING( val ); \
+ } while (0)
+
+-
+ #define OUT_RING_TABLE( tab, sz ) do { \
+ int _size = (sz); \
+ int *_tab = (int *)(tab); \
+@@ -1071,5 +1114,4 @@ do { \
+ write &= mask; \
+ } while (0)
+
+-
+-#endif /* __RADEON_DRV_H__ */
++#endif /* __RADEON_DRV_H__ */
+diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
+--- a/drivers/char/drm/radeon_ioc32.c
++++ b/drivers/char/drm/radeon_ioc32.c
+@@ -94,7 +94,7 @@ static int compat_radeon_cp_init(struct
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);
++ DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
+ }
+
+ typedef struct drm_radeon_clear32 {
+@@ -102,8 +102,8 @@ typedef struct drm_radeon_clear32 {
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int color_mask;
+- unsigned int depth_mask; /* misnamed field: should be stencil */
+- u32 depth_boxes;
++ unsigned int depth_mask; /* misnamed field: should be stencil */
++ u32 depth_boxes;
+ } drm_radeon_clear32_t;
+
+ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
+@@ -127,7 +127,7 @@ static int compat_radeon_cp_clear(struct
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);
++ DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
+ }
+
+ typedef struct drm_radeon_stipple32 {
+@@ -137,7 +137,7 @@ typedef struct drm_radeon_stipple32 {
+ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
+ unsigned long arg)
+ {
+- drm_radeon_stipple32_t __user *argp = (void __user *) arg;
++ drm_radeon_stipple32_t __user *argp = (void __user *)arg;
+ drm_radeon_stipple_t __user *request;
+ u32 mask;
+
+@@ -146,16 +146,16 @@ static int compat_radeon_cp_stipple(stru
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+- || __put_user((unsigned int __user *)(unsigned long) mask,
++ || __put_user((unsigned int __user *)(unsigned long)mask,
+ &request->mask))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);
++ DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
+ }
+
+ typedef struct drm_radeon_tex_image32 {
+- unsigned int x, y; /* Blit coordinates */
++ unsigned int x, y; /* Blit coordinates */
+ unsigned int width, height;
+ u32 data;
+ } drm_radeon_tex_image32_t;
+@@ -164,7 +164,7 @@ typedef struct drm_radeon_texture32 {
+ unsigned int offset;
+ int pitch;
+ int format;
+- int width; /* Texture image coordinates */
++ int width; /* Texture image coordinates */
+ int height;
+ u32 image;
+ } drm_radeon_texture32_t;
+@@ -177,7 +177,7 @@ static int compat_radeon_cp_texture(stru
+ drm_radeon_tex_image32_t img32;
+ drm_radeon_tex_image_t __user *image;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+ if (req32.image == 0)
+ return -EINVAL;
+@@ -206,12 +206,12 @@ static int compat_radeon_cp_texture(stru
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);
++ DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
+ }
+
+ typedef struct drm_radeon_vertex2_32 {
+- int idx; /* Index of vertex buffer */
+- int discard; /* Client finished with buffer? */
++ int idx; /* Index of vertex buffer */
++ int discard; /* Client finished with buffer? */
+ int nr_states;
+ u32 state;
+ int nr_prims;
+@@ -224,7 +224,7 @@ static int compat_radeon_cp_vertex2(stru
+ drm_radeon_vertex2_32_t req32;
+ drm_radeon_vertex2_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -240,7 +240,7 @@ static int compat_radeon_cp_vertex2(stru
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);
++ DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
+ }
+
+ typedef struct drm_radeon_cmd_buffer32 {
+@@ -256,7 +256,7 @@ static int compat_radeon_cp_cmdbuf(struc
+ drm_radeon_cmd_buffer32_t req32;
+ drm_radeon_cmd_buffer_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -270,7 +270,7 @@ static int compat_radeon_cp_cmdbuf(struc
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);
++ DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
+ }
+
+ typedef struct drm_radeon_getparam32 {
+@@ -284,7 +284,7 @@ static int compat_radeon_cp_getparam(str
+ drm_radeon_getparam32_t req32;
+ drm_radeon_getparam_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -295,7 +295,7 @@ static int compat_radeon_cp_getparam(str
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);
++ DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
+ }
+
+ typedef struct drm_radeon_mem_alloc32 {
+@@ -311,7 +311,7 @@ static int compat_radeon_mem_alloc(struc
+ drm_radeon_mem_alloc32_t req32;
+ drm_radeon_mem_alloc_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -324,7 +324,7 @@ static int compat_radeon_mem_alloc(struc
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);
++ DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
+ }
+
+ typedef struct drm_radeon_irq_emit32 {
+@@ -337,7 +337,7 @@ static int compat_radeon_irq_emit(struct
+ drm_radeon_irq_emit32_t req32;
+ drm_radeon_irq_emit_t __user *request;
+
+- if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
++ if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+@@ -347,7 +347,7 @@ static int compat_radeon_irq_emit(struct
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+- DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
++ DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
+ }
+
+ drm_ioctl_compat_t *radeon_compat_ioctls[] = {
+@@ -371,8 +371,7 @@ drm_ioctl_compat_t *radeon_compat_ioctls
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+-long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+@@ -386,7 +385,7 @@ long radeon_compat_ioctl(struct file *fi
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+- ret = (*fn)(filp, cmd, arg);
++ ret = (*fn) (filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
+--- a/drivers/char/drm/radeon_irq.c
++++ b/drivers/char/drm/radeon_irq.c
+@@ -1,7 +1,7 @@
+ /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+- *
++ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+@@ -35,7 +35,8 @@
+ #include "radeon_drm.h"
+ #include "radeon_drv.h"
+
+-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 mask)
++static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
++ u32 mask)
+ {
+ u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+ if (irqs)
+@@ -61,37 +62,37 @@ static __inline__ u32 radeon_acknowledge
+ * tied to dma at all, this is just a hangover from dri prehistory.
+ */
+
+-irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
++irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ drm_device_t *dev = (drm_device_t *) arg;
+- drm_radeon_private_t *dev_priv =
+- (drm_radeon_private_t *)dev->dev_private;
+- u32 stat;
++ drm_radeon_private_t *dev_priv =
++ (drm_radeon_private_t *) dev->dev_private;
++ u32 stat;
+
+ /* Only consider the bits we're interested in - others could be used
+ * outside the DRM
+ */
+- stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
++ stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+ RADEON_CRTC_VBLANK_STAT));
+ if (!stat)
+ return IRQ_NONE;
+
+ /* SW interrupt */
+ if (stat & RADEON_SW_INT_TEST) {
+- DRM_WAKEUP( &dev_priv->swi_queue );
++ DRM_WAKEUP(&dev_priv->swi_queue);
+ }
+
+ /* VBLANK interrupt */
+ if (stat & RADEON_CRTC_VBLANK_STAT) {
+ atomic_inc(&dev->vbl_received);
+ DRM_WAKEUP(&dev->vbl_queue);
+- drm_vbl_send_signals( dev );
++ drm_vbl_send_signals(dev);
+ }
+
+ return IRQ_HANDLED;
+ }
+
+-static int radeon_emit_irq(drm_device_t *dev)
++static int radeon_emit_irq(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ unsigned int ret;
+@@ -100,42 +101,41 @@ static int radeon_emit_irq(drm_device_t
+ atomic_inc(&dev_priv->swi_emitted);
+ ret = atomic_read(&dev_priv->swi_emitted);
+
+- BEGIN_RING( 4 );
+- OUT_RING_REG( RADEON_LAST_SWI_REG, ret );
+- OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE );
+- ADVANCE_RING();
+- COMMIT_RING();
++ BEGIN_RING(4);
++ OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
++ OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
++ ADVANCE_RING();
++ COMMIT_RING();
+
+ return ret;
+ }
+
+-
+-static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
++static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
+ {
+- drm_radeon_private_t *dev_priv =
+- (drm_radeon_private_t *)dev->dev_private;
++ drm_radeon_private_t *dev_priv =
++ (drm_radeon_private_t *) dev->dev_private;
+ int ret = 0;
+
+- if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr)
+- return 0;
++ if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
++ return 0;
+
+ dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+- DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ,
+- RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
++ DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
++ RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
+
+ return ret;
+ }
+
+-int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
++int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+ {
+- drm_radeon_private_t *dev_priv =
+- (drm_radeon_private_t *)dev->dev_private;
++ drm_radeon_private_t *dev_priv =
++ (drm_radeon_private_t *) dev->dev_private;
+ unsigned int cur_vblank;
+ int ret = 0;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -145,101 +145,100 @@ int radeon_driver_vblank_wait(drm_device
+
+ /* Assume that the user has missed the current sequence number
+ * by about a day rather than she wants to wait for years
+- * using vertical blanks...
++ * using vertical blanks...
+ */
+- DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ,
+- ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+- - *sequence ) <= (1<<23) ) );
++ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
++ (((cur_vblank = atomic_read(&dev->vbl_received))
++ - *sequence) <= (1 << 23)));
+
+ *sequence = cur_vblank;
+
+ return ret;
+ }
+
+-
+ /* Needs the lock as it touches the ring.
+ */
+-int radeon_irq_emit( DRM_IOCTL_ARGS )
++int radeon_irq_emit(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_irq_emit_t emit;
+ int result;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t __user *)data,
+- sizeof(emit) );
++ DRM_COPY_FROM_USER_IOCTL(emit, (drm_radeon_irq_emit_t __user *) data,
++ sizeof(emit));
+
+- result = radeon_emit_irq( dev );
++ result = radeon_emit_irq(dev);
+
+- if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) {
+- DRM_ERROR( "copy_to_user\n" );
++ if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
++ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+
+ return 0;
+ }
+
+-
+ /* Doesn't need the hardware lock.
+ */
+-int radeon_irq_wait( DRM_IOCTL_ARGS )
++int radeon_irq_wait(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_irq_wait_t irqwait;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t __user*)data,
+- sizeof(irqwait) );
++ DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_radeon_irq_wait_t __user *) data,
++ sizeof(irqwait));
+
+- return radeon_wait_irq( dev, irqwait.irq_seq );
++ return radeon_wait_irq(dev, irqwait.irq_seq);
+ }
+
+-
+ /* drm_dma.h hooks
+ */
+-void radeon_driver_irq_preinstall( drm_device_t *dev ) {
++void radeon_driver_irq_preinstall(drm_device_t * dev)
++{
+ drm_radeon_private_t *dev_priv =
+- (drm_radeon_private_t *)dev->dev_private;
++ (drm_radeon_private_t *) dev->dev_private;
+
+- /* Disable *all* interrupts */
+- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
++ /* Disable *all* interrupts */
++ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+ /* Clear bits if they're already high */
+ radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+ RADEON_CRTC_VBLANK_STAT));
+ }
+
+-void radeon_driver_irq_postinstall( drm_device_t *dev ) {
++void radeon_driver_irq_postinstall(drm_device_t * dev)
++{
+ drm_radeon_private_t *dev_priv =
+- (drm_radeon_private_t *)dev->dev_private;
++ (drm_radeon_private_t *) dev->dev_private;
+
+- atomic_set(&dev_priv->swi_emitted, 0);
+- DRM_INIT_WAITQUEUE( &dev_priv->swi_queue );
++ atomic_set(&dev_priv->swi_emitted, 0);
++ DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+
+ /* Turn on SW and VBL ints */
+- RADEON_WRITE( RADEON_GEN_INT_CNTL,
+- RADEON_CRTC_VBLANK_MASK |
+- RADEON_SW_INT_ENABLE );
++ RADEON_WRITE(RADEON_GEN_INT_CNTL,
++ RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
+ }
+
+-void radeon_driver_irq_uninstall( drm_device_t *dev ) {
++void radeon_driver_irq_uninstall(drm_device_t * dev)
++{
+ drm_radeon_private_t *dev_priv =
+- (drm_radeon_private_t *)dev->dev_private;
++ (drm_radeon_private_t *) dev->dev_private;
+ if (!dev_priv)
+ return;
+
+ /* Disable *all* interrupts */
+- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
++ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+ }
+diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c
+--- a/drivers/char/drm/radeon_mem.c
++++ b/drivers/char/drm/radeon_mem.c
+@@ -1,7 +1,7 @@
+ /* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+- *
++ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+@@ -35,16 +35,17 @@
+ #include "radeon_drv.h"
+
+ /* Very simple allocator for GART memory, working on a static range
+- * already mapped into each client's address space.
++ * already mapped into each client's address space.
+ */
+
+ static struct mem_block *split_block(struct mem_block *p, int start, int size,
+- DRMFILE filp )
++ DRMFILE filp)
+ {
+ /* Maybe cut off the start of an existing block */
+ if (start > p->start) {
+- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS );
+- if (!newblock)
++ struct mem_block *newblock =
++ drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
++ if (!newblock)
+ goto out;
+ newblock->start = start;
+ newblock->size = p->size - (start - p->start);
+@@ -56,10 +57,11 @@ static struct mem_block *split_block(str
+ p->size -= newblock->size;
+ p = newblock;
+ }
+-
++
+ /* Maybe cut off the end of an existing block */
+ if (size < p->size) {
+- struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFS );
++ struct mem_block *newblock =
++ drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+ if (!newblock)
+ goto out;
+ newblock->start = start + size;
+@@ -72,40 +74,39 @@ static struct mem_block *split_block(str
+ p->size = size;
+ }
+
+- out:
++ out:
+ /* Our block is in the middle */
+ p->filp = filp;
+ return p;
+ }
+
+-static struct mem_block *alloc_block( struct mem_block *heap, int size,
+- int align2, DRMFILE filp )
++static struct mem_block *alloc_block(struct mem_block *heap, int size,
++ int align2, DRMFILE filp)
+ {
+ struct mem_block *p;
+- int mask = (1 << align2)-1;
++ int mask = (1 << align2) - 1;
+
+ list_for_each(p, heap) {
+ int start = (p->start + mask) & ~mask;
+ if (p->filp == 0 && start + size <= p->start + p->size)
+- return split_block( p, start, size, filp );
++ return split_block(p, start, size, filp);
+ }
+
+ return NULL;
+ }
+
+-static struct mem_block *find_block( struct mem_block *heap, int start )
++static struct mem_block *find_block(struct mem_block *heap, int start)
+ {
+ struct mem_block *p;
+
+ list_for_each(p, heap)
+- if (p->start == start)
+- return p;
++ if (p->start == start)
++ return p;
+
+ return NULL;
+ }
+
+-
+-static void free_block( struct mem_block *p )
++static void free_block(struct mem_block *p)
+ {
+ p->filp = NULL;
+
+@@ -117,7 +118,7 @@ static void free_block( struct mem_block
+ p->size += q->size;
+ p->next = q->next;
+ p->next->prev = p;
+- drm_free(q, sizeof(*q), DRM_MEM_BUFS );
++ drm_free(q, sizeof(*q), DRM_MEM_BUFS);
+ }
+
+ if (p->prev->filp == 0) {
+@@ -125,7 +126,7 @@ static void free_block( struct mem_block
+ q->size += p->size;
+ q->next = p->next;
+ q->next->prev = q;
+- drm_free(p, sizeof(*q), DRM_MEM_BUFS );
++ drm_free(p, sizeof(*q), DRM_MEM_BUFS);
+ }
+ }
+
+@@ -133,14 +134,14 @@ static void free_block( struct mem_block
+ */
+ static int init_heap(struct mem_block **heap, int start, int size)
+ {
+- struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS );
++ struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
+
+- if (!blocks)
++ if (!blocks)
+ return DRM_ERR(ENOMEM);
+-
+- *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS );
++
++ *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
+ if (!*heap) {
+- drm_free( blocks, sizeof(*blocks), DRM_MEM_BUFS );
++ drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
+ return DRM_ERR(ENOMEM);
+ }
+
+@@ -149,16 +150,15 @@ static int init_heap(struct mem_block **
+ blocks->filp = NULL;
+ blocks->next = blocks->prev = *heap;
+
+- memset( *heap, 0, sizeof(**heap) );
+- (*heap)->filp = (DRMFILE) -1;
++ memset(*heap, 0, sizeof(**heap));
++ (*heap)->filp = (DRMFILE) - 1;
+ (*heap)->next = (*heap)->prev = blocks;
+ return 0;
+ }
+
+-
+ /* Free all blocks associated with the releasing file.
+ */
+-void radeon_mem_release( DRMFILE filp, struct mem_block *heap )
++void radeon_mem_release(DRMFILE filp, struct mem_block *heap)
+ {
+ struct mem_block *p;
+
+@@ -166,7 +166,7 @@ void radeon_mem_release( DRMFILE filp, s
+ return;
+
+ list_for_each(p, heap) {
+- if (p->filp == filp)
++ if (p->filp == filp)
+ p->filp = NULL;
+ }
+
+@@ -179,40 +179,37 @@ void radeon_mem_release( DRMFILE filp, s
+ p->size += q->size;
+ p->next = q->next;
+ p->next->prev = p;
+- drm_free(q, sizeof(*q),DRM_MEM_DRIVER);
++ drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+ }
+ }
+ }
+
+ /* Shutdown.
+ */
+-void radeon_mem_takedown( struct mem_block **heap )
++void radeon_mem_takedown(struct mem_block **heap)
+ {
+ struct mem_block *p;
+-
++
+ if (!*heap)
+ return;
+
+- for (p = (*heap)->next ; p != *heap ; ) {
++ for (p = (*heap)->next; p != *heap;) {
+ struct mem_block *q = p;
+ p = p->next;
+- drm_free(q, sizeof(*q),DRM_MEM_DRIVER);
++ drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+ }
+
+- drm_free( *heap, sizeof(**heap),DRM_MEM_DRIVER );
++ drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
+ *heap = NULL;
+ }
+
+-
+-
+ /* IOCTL HANDLERS */
+
+-static struct mem_block **get_heap( drm_radeon_private_t *dev_priv,
+- int region )
++static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
+ {
+- switch( region ) {
++ switch (region) {
+ case RADEON_MEM_REGION_GART:
+- return &dev_priv->gart_heap;
++ return &dev_priv->gart_heap;
+ case RADEON_MEM_REGION_FB:
+ return &dev_priv->fb_heap;
+ default:
+@@ -220,103 +217,98 @@ static struct mem_block **get_heap( drm_
+ }
+ }
+
+-int radeon_mem_alloc( DRM_IOCTL_ARGS )
++int radeon_mem_alloc(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_mem_alloc_t alloc;
+ struct mem_block *block, **heap;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t __user *)data,
+- sizeof(alloc) );
++ DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_mem_alloc_t __user *) data,
++ sizeof(alloc));
+
+- heap = get_heap( dev_priv, alloc.region );
++ heap = get_heap(dev_priv, alloc.region);
+ if (!heap || !*heap)
+ return DRM_ERR(EFAULT);
+-
++
+ /* Make things easier on ourselves: all allocations at least
+ * 4k aligned.
+ */
+ if (alloc.alignment < 12)
+ alloc.alignment = 12;
+
+- block = alloc_block( *heap, alloc.size, alloc.alignment,
+- filp );
++ block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
+
+- if (!block)
++ if (!block)
+ return DRM_ERR(ENOMEM);
+
+- if ( DRM_COPY_TO_USER( alloc.region_offset, &block->start,
+- sizeof(int) ) ) {
+- DRM_ERROR( "copy_to_user\n" );
++ if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
++ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+-
++
+ return 0;
+ }
+
+-
+-
+-int radeon_mem_free( DRM_IOCTL_ARGS )
++int radeon_mem_free(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_mem_free_t memfree;
+ struct mem_block *block, **heap;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t __user *)data,
+- sizeof(memfree) );
++ DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
++ sizeof(memfree));
+
+- heap = get_heap( dev_priv, memfree.region );
++ heap = get_heap(dev_priv, memfree.region);
+ if (!heap || !*heap)
+ return DRM_ERR(EFAULT);
+-
+- block = find_block( *heap, memfree.region_offset );
++
++ block = find_block(*heap, memfree.region_offset);
+ if (!block)
+ return DRM_ERR(EFAULT);
+
+ if (block->filp != filp)
+ return DRM_ERR(EPERM);
+
+- free_block( block );
++ free_block(block);
+ return 0;
+ }
+
+-int radeon_mem_init_heap( DRM_IOCTL_ARGS )
++int radeon_mem_init_heap(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_mem_init_heap_t initheap;
+ struct mem_block **heap;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( initheap, (drm_radeon_mem_init_heap_t __user *)data,
+- sizeof(initheap) );
++ DRM_COPY_FROM_USER_IOCTL(initheap,
++ (drm_radeon_mem_init_heap_t __user *) data,
++ sizeof(initheap));
+
+- heap = get_heap( dev_priv, initheap.region );
+- if (!heap)
++ heap = get_heap(dev_priv, initheap.region);
++ if (!heap)
+ return DRM_ERR(EFAULT);
+-
++
+ if (*heap) {
+ DRM_ERROR("heap already initialized?");
+ return DRM_ERR(EFAULT);
+ }
+-
+- return init_heap( heap, initheap.start, initheap.size );
+-}
+-
+
++ return init_heap(heap, initheap.start, initheap.size);
++}
+diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
+--- a/drivers/char/drm/radeon_state.c
++++ b/drivers/char/drm/radeon_state.c
+@@ -37,51 +37,58 @@
+ * Helper functions for client state checking and fixup
+ */
+
+-static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
+- drm_file_t *filp_priv,
+- u32 *offset ) {
++static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
++ dev_priv,
++ drm_file_t * filp_priv,
++ u32 *offset)
++{
+ u32 off = *offset;
+ struct drm_radeon_driver_file_fields *radeon_priv;
+
+- if ( off >= dev_priv->fb_location &&
+- off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
++ if (off >= dev_priv->fb_location &&
++ off < (dev_priv->gart_vm_start + dev_priv->gart_size))
+ return 0;
+
+ radeon_priv = filp_priv->driver_priv;
+ off += radeon_priv->radeon_fb_delta;
+
+- DRM_DEBUG( "offset fixed up to 0x%x\n", off );
++ DRM_DEBUG("offset fixed up to 0x%x\n", off);
+
+- if ( off < dev_priv->fb_location ||
+- off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+- return DRM_ERR( EINVAL );
++ if (off < dev_priv->fb_location ||
++ off >= (dev_priv->gart_vm_start + dev_priv->gart_size))
++ return DRM_ERR(EINVAL);
+
+ *offset = off;
+
+ return 0;
+ }
+
+-static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
+- drm_file_t *filp_priv,
+- int id,
+- u32 __user *data ) {
+- switch ( id ) {
++static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
++ dev_priv,
++ drm_file_t * filp_priv,
++ int id, u32 *data)
++{
++ switch (id) {
+
+ case RADEON_EMIT_PP_MISC:
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &data[( RADEON_RB3D_DEPTHOFFSET
+- - RADEON_PP_MISC ) / 4] ) ) {
+- DRM_ERROR( "Invalid depth buffer offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &data[(RADEON_RB3D_DEPTHOFFSET
++ -
++ RADEON_PP_MISC) /
++ 4])) {
++ DRM_ERROR("Invalid depth buffer offset\n");
++ return DRM_ERR(EINVAL);
+ }
+ break;
+
+ case RADEON_EMIT_PP_CNTL:
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &data[( RADEON_RB3D_COLOROFFSET
+- - RADEON_PP_CNTL ) / 4] ) ) {
+- DRM_ERROR( "Invalid colour buffer offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &data[(RADEON_RB3D_COLOROFFSET
++ -
++ RADEON_PP_CNTL) /
++ 4])) {
++ DRM_ERROR("Invalid colour buffer offset\n");
++ return DRM_ERR(EINVAL);
+ }
+ break;
+
+@@ -91,21 +98,23 @@ static __inline__ int radeon_check_and_f
+ case R200_EMIT_PP_TXOFFSET_3:
+ case R200_EMIT_PP_TXOFFSET_4:
+ case R200_EMIT_PP_TXOFFSET_5:
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &data[0] ) ) {
+- DRM_ERROR( "Invalid R200 texture offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &data[0])) {
++ DRM_ERROR("Invalid R200 texture offset\n");
++ return DRM_ERR(EINVAL);
+ }
+ break;
+
+ case RADEON_EMIT_PP_TXFILTER_0:
+ case RADEON_EMIT_PP_TXFILTER_1:
+ case RADEON_EMIT_PP_TXFILTER_2:
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &data[( RADEON_PP_TXOFFSET_0
+- - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
+- DRM_ERROR( "Invalid R100 texture offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &data[(RADEON_PP_TXOFFSET_0
++ -
++ RADEON_PP_TXFILTER_0) /
++ 4])) {
++ DRM_ERROR("Invalid R100 texture offset\n");
++ return DRM_ERR(EINVAL);
+ }
+ break;
+
+@@ -114,17 +123,18 @@ static __inline__ int radeon_check_and_f
+ case R200_EMIT_PP_CUBIC_OFFSETS_2:
+ case R200_EMIT_PP_CUBIC_OFFSETS_3:
+ case R200_EMIT_PP_CUBIC_OFFSETS_4:
+- case R200_EMIT_PP_CUBIC_OFFSETS_5: {
+- int i;
+- for ( i = 0; i < 5; i++ ) {
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &data[i] ) ) {
+- DRM_ERROR( "Invalid R200 cubic texture offset\n" );
+- return DRM_ERR( EINVAL );
++ case R200_EMIT_PP_CUBIC_OFFSETS_5:{
++ int i;
++ for (i = 0; i < 5; i++) {
++ if (radeon_check_and_fixup_offset
++ (dev_priv, filp_priv, &data[i])) {
++ DRM_ERROR
++ ("Invalid R200 cubic texture offset\n");
++ return DRM_ERR(EINVAL);
++ }
+ }
++ break;
+ }
+- break;
+- }
+
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
+@@ -207,247 +217,259 @@ static __inline__ int radeon_check_and_f
+ case RADEON_EMIT_PP_CUBIC_FACES_1:
+ case RADEON_EMIT_PP_CUBIC_FACES_2:
+ case R200_EMIT_PP_TRI_PERF_CNTL:
++ case R200_EMIT_PP_AFS_0:
++ case R200_EMIT_PP_AFS_1:
++ case R200_EMIT_ATF_TFACTOR:
++ case R200_EMIT_PP_TXCTLALL_0:
++ case R200_EMIT_PP_TXCTLALL_1:
++ case R200_EMIT_PP_TXCTLALL_2:
++ case R200_EMIT_PP_TXCTLALL_3:
++ case R200_EMIT_PP_TXCTLALL_4:
++ case R200_EMIT_PP_TXCTLALL_5:
+ /* These packets don't contain memory offsets */
+ break;
+
+ default:
+- DRM_ERROR( "Unknown state packet ID %d\n", id );
+- return DRM_ERR( EINVAL );
++ DRM_ERROR("Unknown state packet ID %d\n", id);
++ return DRM_ERR(EINVAL);
+ }
+
+ return 0;
+ }
+
+-static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
+- drm_file_t *filp_priv,
+- drm_radeon_cmd_buffer_t *cmdbuf,
+- unsigned int *cmdsz ) {
++static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
++ dev_priv,
++ drm_file_t * filp_priv,
++ drm_radeon_kcmd_buffer_t *cmdbuf,
++ unsigned int *cmdsz)
++{
+ u32 *cmd = (u32 *) cmdbuf->buf;
+
+- *cmdsz = 2 + ( ( cmd[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
++ *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+- if ( ( cmd[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
+- DRM_ERROR( "Not a type 3 packet\n" );
+- return DRM_ERR( EINVAL );
++ if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
++ DRM_ERROR("Not a type 3 packet\n");
++ return DRM_ERR(EINVAL);
+ }
+
+- if ( 4 * *cmdsz > cmdbuf->bufsz ) {
+- DRM_ERROR( "Packet size larger than size of data provided\n" );
+- return DRM_ERR( EINVAL );
++ if (4 * *cmdsz > cmdbuf->bufsz) {
++ DRM_ERROR("Packet size larger than size of data provided\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ /* Check client state and fix it up if necessary */
+- if ( cmd[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
++ if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */
+ u32 offset;
+
+- if ( cmd[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+- | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
++ if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
++ | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+ offset = cmd[2] << 10;
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+- DRM_ERROR( "Invalid first packet offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset
++ (dev_priv, filp_priv, &offset)) {
++ DRM_ERROR("Invalid first packet offset\n");
++ return DRM_ERR(EINVAL);
+ }
+- cmd[2] = ( cmd[2] & 0xffc00000 ) | offset >> 10;
++ cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
+ }
+
+- if ( ( cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
+- ( cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
++ if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
++ (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+ offset = cmd[3] << 10;
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+- DRM_ERROR( "Invalid second packet offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset
++ (dev_priv, filp_priv, &offset)) {
++ DRM_ERROR("Invalid second packet offset\n");
++ return DRM_ERR(EINVAL);
+ }
+- cmd[3] = ( cmd[3] & 0xffc00000 ) | offset >> 10;
++ cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
+ }
+ }
+
+ return 0;
+ }
+
+-
+ /* ================================================================
+ * CP hardware state programming functions
+ */
+
+-static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
+- drm_clip_rect_t *box )
++static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
++ drm_clip_rect_t * box)
+ {
+ RING_LOCALS;
+
+- DRM_DEBUG( " box: x1=%d y1=%d x2=%d y2=%d\n",
+- box->x1, box->y1, box->x2, box->y2 );
++ DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n",
++ box->x1, box->y1, box->x2, box->y2);
+
+- BEGIN_RING( 4 );
+- OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
+- OUT_RING( (box->y1 << 16) | box->x1 );
+- OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
+- OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
++ BEGIN_RING(4);
++ OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
++ OUT_RING((box->y1 << 16) | box->x1);
++ OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
++ OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
+ ADVANCE_RING();
+ }
+
+ /* Emit 1.1 state
+ */
+-static int radeon_emit_state( drm_radeon_private_t *dev_priv,
+- drm_file_t *filp_priv,
+- drm_radeon_context_regs_t *ctx,
+- drm_radeon_texture_regs_t *tex,
+- unsigned int dirty )
++static int radeon_emit_state(drm_radeon_private_t * dev_priv,
++ drm_file_t * filp_priv,
++ drm_radeon_context_regs_t * ctx,
++ drm_radeon_texture_regs_t * tex,
++ unsigned int dirty)
+ {
+ RING_LOCALS;
+- DRM_DEBUG( "dirty=0x%08x\n", dirty );
++ DRM_DEBUG("dirty=0x%08x\n", dirty);
+
+- if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &ctx->rb3d_depthoffset ) ) {
+- DRM_ERROR( "Invalid depth buffer offset\n" );
+- return DRM_ERR( EINVAL );
++ if (dirty & RADEON_UPLOAD_CONTEXT) {
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &ctx->rb3d_depthoffset)) {
++ DRM_ERROR("Invalid depth buffer offset\n");
++ return DRM_ERR(EINVAL);
+ }
+
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &ctx->rb3d_coloroffset ) ) {
+- DRM_ERROR( "Invalid depth buffer offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &ctx->rb3d_coloroffset)) {
++ DRM_ERROR("Invalid depth buffer offset\n");
++ return DRM_ERR(EINVAL);
+ }
+
+- BEGIN_RING( 14 );
+- OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
+- OUT_RING( ctx->pp_misc );
+- OUT_RING( ctx->pp_fog_color );
+- OUT_RING( ctx->re_solid_color );
+- OUT_RING( ctx->rb3d_blendcntl );
+- OUT_RING( ctx->rb3d_depthoffset );
+- OUT_RING( ctx->rb3d_depthpitch );
+- OUT_RING( ctx->rb3d_zstencilcntl );
+- OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
+- OUT_RING( ctx->pp_cntl );
+- OUT_RING( ctx->rb3d_cntl );
+- OUT_RING( ctx->rb3d_coloroffset );
+- OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
+- OUT_RING( ctx->rb3d_colorpitch );
++ BEGIN_RING(14);
++ OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
++ OUT_RING(ctx->pp_misc);
++ OUT_RING(ctx->pp_fog_color);
++ OUT_RING(ctx->re_solid_color);
++ OUT_RING(ctx->rb3d_blendcntl);
++ OUT_RING(ctx->rb3d_depthoffset);
++ OUT_RING(ctx->rb3d_depthpitch);
++ OUT_RING(ctx->rb3d_zstencilcntl);
++ OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
++ OUT_RING(ctx->pp_cntl);
++ OUT_RING(ctx->rb3d_cntl);
++ OUT_RING(ctx->rb3d_coloroffset);
++ OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
++ OUT_RING(ctx->rb3d_colorpitch);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_VERTFMT ) {
+- BEGIN_RING( 2 );
+- OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
+- OUT_RING( ctx->se_coord_fmt );
++ if (dirty & RADEON_UPLOAD_VERTFMT) {
++ BEGIN_RING(2);
++ OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
++ OUT_RING(ctx->se_coord_fmt);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_LINE ) {
+- BEGIN_RING( 5 );
+- OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
+- OUT_RING( ctx->re_line_pattern );
+- OUT_RING( ctx->re_line_state );
+- OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
+- OUT_RING( ctx->se_line_width );
++ if (dirty & RADEON_UPLOAD_LINE) {
++ BEGIN_RING(5);
++ OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
++ OUT_RING(ctx->re_line_pattern);
++ OUT_RING(ctx->re_line_state);
++ OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
++ OUT_RING(ctx->se_line_width);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
+- BEGIN_RING( 5 );
+- OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
+- OUT_RING( ctx->pp_lum_matrix );
+- OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
+- OUT_RING( ctx->pp_rot_matrix_0 );
+- OUT_RING( ctx->pp_rot_matrix_1 );
++ if (dirty & RADEON_UPLOAD_BUMPMAP) {
++ BEGIN_RING(5);
++ OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
++ OUT_RING(ctx->pp_lum_matrix);
++ OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
++ OUT_RING(ctx->pp_rot_matrix_0);
++ OUT_RING(ctx->pp_rot_matrix_1);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_MASKS ) {
+- BEGIN_RING( 4 );
+- OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
+- OUT_RING( ctx->rb3d_stencilrefmask );
+- OUT_RING( ctx->rb3d_ropcntl );
+- OUT_RING( ctx->rb3d_planemask );
++ if (dirty & RADEON_UPLOAD_MASKS) {
++ BEGIN_RING(4);
++ OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
++ OUT_RING(ctx->rb3d_stencilrefmask);
++ OUT_RING(ctx->rb3d_ropcntl);
++ OUT_RING(ctx->rb3d_planemask);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
+- BEGIN_RING( 7 );
+- OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
+- OUT_RING( ctx->se_vport_xscale );
+- OUT_RING( ctx->se_vport_xoffset );
+- OUT_RING( ctx->se_vport_yscale );
+- OUT_RING( ctx->se_vport_yoffset );
+- OUT_RING( ctx->se_vport_zscale );
+- OUT_RING( ctx->se_vport_zoffset );
++ if (dirty & RADEON_UPLOAD_VIEWPORT) {
++ BEGIN_RING(7);
++ OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
++ OUT_RING(ctx->se_vport_xscale);
++ OUT_RING(ctx->se_vport_xoffset);
++ OUT_RING(ctx->se_vport_yscale);
++ OUT_RING(ctx->se_vport_yoffset);
++ OUT_RING(ctx->se_vport_zscale);
++ OUT_RING(ctx->se_vport_zoffset);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_SETUP ) {
+- BEGIN_RING( 4 );
+- OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+- OUT_RING( ctx->se_cntl );
+- OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
+- OUT_RING( ctx->se_cntl_status );
++ if (dirty & RADEON_UPLOAD_SETUP) {
++ BEGIN_RING(4);
++ OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
++ OUT_RING(ctx->se_cntl);
++ OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
++ OUT_RING(ctx->se_cntl_status);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_MISC ) {
+- BEGIN_RING( 2 );
+- OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
+- OUT_RING( ctx->re_misc );
++ if (dirty & RADEON_UPLOAD_MISC) {
++ BEGIN_RING(2);
++ OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
++ OUT_RING(ctx->re_misc);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_TEX0 ) {
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &tex[0].pp_txoffset ) ) {
+- DRM_ERROR( "Invalid texture offset for unit 0\n" );
+- return DRM_ERR( EINVAL );
++ if (dirty & RADEON_UPLOAD_TEX0) {
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &tex[0].pp_txoffset)) {
++ DRM_ERROR("Invalid texture offset for unit 0\n");
++ return DRM_ERR(EINVAL);
+ }
+
+- BEGIN_RING( 9 );
+- OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
+- OUT_RING( tex[0].pp_txfilter );
+- OUT_RING( tex[0].pp_txformat );
+- OUT_RING( tex[0].pp_txoffset );
+- OUT_RING( tex[0].pp_txcblend );
+- OUT_RING( tex[0].pp_txablend );
+- OUT_RING( tex[0].pp_tfactor );
+- OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
+- OUT_RING( tex[0].pp_border_color );
++ BEGIN_RING(9);
++ OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
++ OUT_RING(tex[0].pp_txfilter);
++ OUT_RING(tex[0].pp_txformat);
++ OUT_RING(tex[0].pp_txoffset);
++ OUT_RING(tex[0].pp_txcblend);
++ OUT_RING(tex[0].pp_txablend);
++ OUT_RING(tex[0].pp_tfactor);
++ OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
++ OUT_RING(tex[0].pp_border_color);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_TEX1 ) {
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &tex[1].pp_txoffset ) ) {
+- DRM_ERROR( "Invalid texture offset for unit 1\n" );
+- return DRM_ERR( EINVAL );
++ if (dirty & RADEON_UPLOAD_TEX1) {
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &tex[1].pp_txoffset)) {
++ DRM_ERROR("Invalid texture offset for unit 1\n");
++ return DRM_ERR(EINVAL);
+ }
+
+- BEGIN_RING( 9 );
+- OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
+- OUT_RING( tex[1].pp_txfilter );
+- OUT_RING( tex[1].pp_txformat );
+- OUT_RING( tex[1].pp_txoffset );
+- OUT_RING( tex[1].pp_txcblend );
+- OUT_RING( tex[1].pp_txablend );
+- OUT_RING( tex[1].pp_tfactor );
+- OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
+- OUT_RING( tex[1].pp_border_color );
++ BEGIN_RING(9);
++ OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
++ OUT_RING(tex[1].pp_txfilter);
++ OUT_RING(tex[1].pp_txformat);
++ OUT_RING(tex[1].pp_txoffset);
++ OUT_RING(tex[1].pp_txcblend);
++ OUT_RING(tex[1].pp_txablend);
++ OUT_RING(tex[1].pp_tfactor);
++ OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
++ OUT_RING(tex[1].pp_border_color);
+ ADVANCE_RING();
+ }
+
+- if ( dirty & RADEON_UPLOAD_TEX2 ) {
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+- &tex[2].pp_txoffset ) ) {
+- DRM_ERROR( "Invalid texture offset for unit 2\n" );
+- return DRM_ERR( EINVAL );
++ if (dirty & RADEON_UPLOAD_TEX2) {
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
++ &tex[2].pp_txoffset)) {
++ DRM_ERROR("Invalid texture offset for unit 2\n");
++ return DRM_ERR(EINVAL);
+ }
+
+- BEGIN_RING( 9 );
+- OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
+- OUT_RING( tex[2].pp_txfilter );
+- OUT_RING( tex[2].pp_txformat );
+- OUT_RING( tex[2].pp_txoffset );
+- OUT_RING( tex[2].pp_txcblend );
+- OUT_RING( tex[2].pp_txablend );
+- OUT_RING( tex[2].pp_tfactor );
+- OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
+- OUT_RING( tex[2].pp_border_color );
++ BEGIN_RING(9);
++ OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
++ OUT_RING(tex[2].pp_txfilter);
++ OUT_RING(tex[2].pp_txformat);
++ OUT_RING(tex[2].pp_txoffset);
++ OUT_RING(tex[2].pp_txcblend);
++ OUT_RING(tex[2].pp_txablend);
++ OUT_RING(tex[2].pp_tfactor);
++ OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
++ OUT_RING(tex[2].pp_border_color);
+ ADVANCE_RING();
+ }
+
+@@ -456,129 +478,137 @@ static int radeon_emit_state( drm_radeon
+
+ /* Emit 1.2 state
+ */
+-static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
+- drm_file_t *filp_priv,
+- drm_radeon_state_t *state )
++static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
++ drm_file_t * filp_priv,
++ drm_radeon_state_t * state)
+ {
+ RING_LOCALS;
+
+ if (state->dirty & RADEON_UPLOAD_ZBIAS) {
+- BEGIN_RING( 3 );
+- OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) );
+- OUT_RING( state->context2.se_zbias_factor );
+- OUT_RING( state->context2.se_zbias_constant );
++ BEGIN_RING(3);
++ OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
++ OUT_RING(state->context2.se_zbias_factor);
++ OUT_RING(state->context2.se_zbias_constant);
+ ADVANCE_RING();
+ }
+
+- return radeon_emit_state( dev_priv, filp_priv, &state->context,
+- state->tex, state->dirty );
++ return radeon_emit_state(dev_priv, filp_priv, &state->context,
++ state->tex, state->dirty);
+ }
+
+ /* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+- * the tcl scalar and vector areas.
++ * the tcl scalar and vector areas.
+ */
+-static struct {
+- int start;
+- int len;
++static struct {
++ int start;
++ int len;
+ const char *name;
+ } packet[RADEON_MAX_STATE_PACKETS] = {
+- { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
+- { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
+- { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
+- { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
+- { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
+- { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
+- { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
+- { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
+- { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
+- { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
+- { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
+- { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
+- { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
+- { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
+- { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
+- { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
+- { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
+- { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
+- { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
+- { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
+- { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
+- { R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" },
+- { R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" },
+- { R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" },
+- { R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" },
+- { R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" },
+- { R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" },
+- { R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" },
+- { R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" },
+- { R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
+- { R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" },
+- { R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" },
+- { R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" },
+- { R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
+- { R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
+- { R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
+- { R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" },
+- { R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" },
+- { R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" },
+- { R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" },
+- { R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" },
+- { R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" },
+- { R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" },
+- { R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" },
+- { R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" },
+- { R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" },
+- { R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" },
+- { R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" },
+- { R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" },
+- { R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
+- { R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" },
+- { R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" },
+- { R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" },
+- { R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" },
+- { R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" },
+- { R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" },
+- { R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" },
+- { R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" },
+- { R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" },
+- { R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" },
+- { R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
+- { R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
+- { R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
+- { R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" },
+- { R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
+- { R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" },
+- { R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
+- { R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" },
+- { R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
+- { R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" },
+- { R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
+- { R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
+- { R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
+- { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
+- { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
+- { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
+- { R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" },
+- { R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" },
+- { RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+- { RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+- { RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+- { RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+- { RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
+- { RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
+- { R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
++ {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
++ {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
++ {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
++ {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
++ {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
++ {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
++ {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
++ {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
++ {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
++ {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
++ {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
++ {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
++ {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
++ {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
++ {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
++ {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
++ {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
++ {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
++ {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
++ {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
++ {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
++ "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
++ {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
++ {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
++ {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
++ {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
++ {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
++ {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
++ {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
++ {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
++ {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
++ {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
++ {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
++ {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
++ {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
++ {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
++ {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
++ {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
++ {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
++ {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
++ {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
++ {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
++ {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
++ {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
++ {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
++ {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
++ {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
++ {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
++ {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
++ {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
++ {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
++ {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
++ {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
++ {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
++ {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
++ {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
++ {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
++ {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
++ {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
++ {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
++ {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
++ {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
++ "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
++ {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */
++ {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
++ {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
++ {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
++ {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
++ {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
++ {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
++ {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
++ {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
++ {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
++ {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
++ {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
++ {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
++ {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
++ {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
++ {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
++ {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
++ {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
++ {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
++ {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
++ {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
++ {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
++ {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
++ {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
++ {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */
++ {R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
++ {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
++ {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
++ {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
++ {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
++ {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
++ {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
++ {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+ };
+
+-
+-
+ /* ================================================================
+ * Performance monitoring functions
+ */
+
+-static void radeon_clear_box( drm_radeon_private_t *dev_priv,
+- int x, int y, int w, int h,
+- int r, int g, int b )
++static void radeon_clear_box(drm_radeon_private_t * dev_priv,
++ int x, int y, int w, int h, int r, int g, int b)
+ {
+ u32 color;
+ RING_LOCALS;
+@@ -586,49 +616,47 @@ static void radeon_clear_box( drm_radeon
+ x += dev_priv->sarea_priv->boxes[0].x1;
+ y += dev_priv->sarea_priv->boxes[0].y1;
+
+- switch ( dev_priv->color_fmt ) {
++ switch (dev_priv->color_fmt) {
+ case RADEON_COLOR_FORMAT_RGB565:
+ color = (((r & 0xf8) << 8) |
+- ((g & 0xfc) << 3) |
+- ((b & 0xf8) >> 3));
++ ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+ break;
+ case RADEON_COLOR_FORMAT_ARGB8888:
+ default:
+- color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
++ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ break;
+ }
+
+- BEGIN_RING( 4 );
+- RADEON_WAIT_UNTIL_3D_IDLE();
+- OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
+- OUT_RING( 0xffffffff );
++ BEGIN_RING(4);
++ RADEON_WAIT_UNTIL_3D_IDLE();
++ OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
++ OUT_RING(0xffffffff);
+ ADVANCE_RING();
+
+- BEGIN_RING( 6 );
++ BEGIN_RING(6);
+
+- OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+- RADEON_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->color_fmt << 8) |
+- RADEON_GMC_SRC_DATATYPE_COLOR |
+- RADEON_ROP3_P |
+- RADEON_GMC_CLR_CMP_CNTL_DIS );
+-
+- if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+- OUT_RING( dev_priv->front_pitch_offset );
+- } else {
+- OUT_RING( dev_priv->back_pitch_offset );
+- }
++ OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
++ OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
++ RADEON_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->color_fmt << 8) |
++ RADEON_GMC_SRC_DATATYPE_COLOR |
++ RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+- OUT_RING( color );
++ if (dev_priv->page_flipping && dev_priv->current_page == 1) {
++ OUT_RING(dev_priv->front_pitch_offset);
++ } else {
++ OUT_RING(dev_priv->back_pitch_offset);
++ }
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ OUT_RING(color);
++
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+
+-static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
++static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
+ {
+ /* Collapse various things into a wait flag -- trying to
+ * guess if userspase slept -- better just to have them tell us.
+@@ -644,50 +672,50 @@ static void radeon_cp_performance_boxes(
+
+ /* Purple box for page flipping
+ */
+- if ( dev_priv->stats.boxes & RADEON_BOX_FLIP )
+- radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 );
++ if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
++ radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
+
+ /* Red box if we have to wait for idle at any point
+ */
+- if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE )
+- radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 );
++ if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
++ radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
+
+ /* Blue box: lost context?
+ */
+
+ /* Yellow box for texture swaps
+ */
+- if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD )
+- radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 );
++ if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
++ radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
+
+ /* Green box if hardware never idles (as far as we can tell)
+ */
+- if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) )
+- radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
+-
++ if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
++ radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
+
+- /* Draw bars indicating number of buffers allocated
++ /* Draw bars indicating number of buffers allocated
+ * (not a great measure, easily confused)
+ */
+ if (dev_priv->stats.requested_bufs) {
+ if (dev_priv->stats.requested_bufs > 100)
+ dev_priv->stats.requested_bufs = 100;
+
+- radeon_clear_box( dev_priv, 4, 16,
+- dev_priv->stats.requested_bufs, 4,
+- 196, 128, 128 );
++ radeon_clear_box(dev_priv, 4, 16,
++ dev_priv->stats.requested_bufs, 4,
++ 196, 128, 128);
+ }
+
+- memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) );
++ memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
+
+ }
++
+ /* ================================================================
+ * CP command dispatch functions
+ */
+
+-static void radeon_cp_dispatch_clear( drm_device_t *dev,
+- drm_radeon_clear_t *clear,
+- drm_radeon_clear_rect_t *depth_boxes )
++static void radeon_cp_dispatch_clear(drm_device_t * dev,
++ drm_radeon_clear_t * clear,
++ drm_radeon_clear_rect_t * depth_boxes)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -695,32 +723,34 @@ static void radeon_cp_dispatch_clear( dr
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ unsigned int flags = clear->flags;
+- u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0;
++ u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( "flags = 0x%x\n", flags );
++ DRM_DEBUG("flags = 0x%x\n", flags);
+
+ dev_priv->stats.clears++;
+
+- if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
++ if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+ unsigned int tmp = flags;
+
+ flags &= ~(RADEON_FRONT | RADEON_BACK);
+- if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
+- if ( tmp & RADEON_BACK ) flags |= RADEON_FRONT;
++ if (tmp & RADEON_FRONT)
++ flags |= RADEON_BACK;
++ if (tmp & RADEON_BACK)
++ flags |= RADEON_FRONT;
+ }
+
+- if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
++ if (flags & (RADEON_FRONT | RADEON_BACK)) {
+
+- BEGIN_RING( 4 );
++ BEGIN_RING(4);
+
+ /* Ensure the 3D stream is idle before doing a
+ * 2D fill to clear the front or back buffer.
+ */
+ RADEON_WAIT_UNTIL_3D_IDLE();
+-
+- OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
+- OUT_RING( clear->color_mask );
++
++ OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
++ OUT_RING(clear->color_mask);
+
+ ADVANCE_RING();
+
+@@ -728,121 +758,130 @@ static void radeon_cp_dispatch_clear( dr
+ */
+ dev_priv->sarea_priv->ctx_owner = 0;
+
+- for ( i = 0 ; i < nbox ; i++ ) {
++ for (i = 0; i < nbox; i++) {
+ int x = pbox[i].x1;
+ int y = pbox[i].y1;
+ int w = pbox[i].x2 - x;
+ int h = pbox[i].y2 - y;
+
+- DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
+- x, y, w, h, flags );
++ DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
++ x, y, w, h, flags);
++
++ if (flags & RADEON_FRONT) {
++ BEGIN_RING(6);
++
++ OUT_RING(CP_PACKET3
++ (RADEON_CNTL_PAINT_MULTI, 4));
++ OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
++ RADEON_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->
++ color_fmt << 8) |
++ RADEON_GMC_SRC_DATATYPE_COLOR |
++ RADEON_ROP3_P |
++ RADEON_GMC_CLR_CMP_CNTL_DIS);
++
++ OUT_RING(dev_priv->front_pitch_offset);
++ OUT_RING(clear->clear_color);
++
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+- if ( flags & RADEON_FRONT ) {
+- BEGIN_RING( 6 );
+-
+- OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+- RADEON_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->color_fmt << 8) |
+- RADEON_GMC_SRC_DATATYPE_COLOR |
+- RADEON_ROP3_P |
+- RADEON_GMC_CLR_CMP_CNTL_DIS );
+-
+- OUT_RING( dev_priv->front_pitch_offset );
+- OUT_RING( clear->clear_color );
+-
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
+-
+ ADVANCE_RING();
+ }
+-
+- if ( flags & RADEON_BACK ) {
+- BEGIN_RING( 6 );
+-
+- OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+- OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+- RADEON_GMC_BRUSH_SOLID_COLOR |
+- (dev_priv->color_fmt << 8) |
+- RADEON_GMC_SRC_DATATYPE_COLOR |
+- RADEON_ROP3_P |
+- RADEON_GMC_CLR_CMP_CNTL_DIS );
+-
+- OUT_RING( dev_priv->back_pitch_offset );
+- OUT_RING( clear->clear_color );
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ if (flags & RADEON_BACK) {
++ BEGIN_RING(6);
++
++ OUT_RING(CP_PACKET3
++ (RADEON_CNTL_PAINT_MULTI, 4));
++ OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
++ RADEON_GMC_BRUSH_SOLID_COLOR |
++ (dev_priv->
++ color_fmt << 8) |
++ RADEON_GMC_SRC_DATATYPE_COLOR |
++ RADEON_ROP3_P |
++ RADEON_GMC_CLR_CMP_CNTL_DIS);
++
++ OUT_RING(dev_priv->back_pitch_offset);
++ OUT_RING(clear->clear_color);
++
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+ }
+ }
+-
++
+ /* hyper z clear */
+ /* no docs available, based on reverse engeneering by Stephane Marchesin */
+- if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) && (flags & RADEON_CLEAR_FASTZ)) {
++ if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
++ && (flags & RADEON_CLEAR_FASTZ)) {
+
+ int i;
+- int depthpixperline = dev_priv->depth_fmt==RADEON_DEPTH_FORMAT_16BIT_INT_Z?
+- (dev_priv->depth_pitch / 2): (dev_priv->depth_pitch / 4);
+-
++ int depthpixperline =
++ dev_priv->depth_fmt ==
++ RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
++ 2) : (dev_priv->
++ depth_pitch / 4);
++
+ u32 clearmask;
+
+ u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
+- ((clear->depth_mask & 0xff) << 24);
+-
+-
++ ((clear->depth_mask & 0xff) << 24);
++
+ /* Make sure we restore the 3D state next time.
+ * we haven't touched any "normal" state - still need this?
+ */
+ dev_priv->sarea_priv->ctx_owner = 0;
+
+- if ((dev_priv->flags & CHIP_HAS_HIERZ) && (flags & RADEON_USE_HIERZ)) {
+- /* FIXME : reverse engineer that for Rx00 cards */
+- /* FIXME : the mask supposedly contains low-res z values. So can't set
+- just to the max (0xff? or actually 0x3fff?), need to take z clear
+- value into account? */
+- /* pattern seems to work for r100, though get slight
+- rendering errors with glxgears. If hierz is not enabled for r100,
+- only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
+- other ones are ignored, and the same clear mask can be used. That's
+- very different behaviour than R200 which needs different clear mask
+- and different number of tiles to clear if hierz is enabled or not !?!
+- */
+- clearmask = (0xff<<22)|(0xff<<6)| 0x003f003f;
+- }
+- else {
+- /* clear mask : chooses the clearing pattern.
+- rv250: could be used to clear only parts of macrotiles
+- (but that would get really complicated...)?
+- bit 0 and 1 (either or both of them ?!?!) are used to
+- not clear tile (or maybe one of the bits indicates if the tile is
+- compressed or not), bit 2 and 3 to not clear tile 1,...,.
+- Pattern is as follows:
+- | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
+- bits -------------------------------------------------
+- | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
+- rv100: clearmask covers 2x8 4x1 tiles, but one clear still
+- covers 256 pixels ?!?
+- */
++ if ((dev_priv->flags & CHIP_HAS_HIERZ)
++ && (flags & RADEON_USE_HIERZ)) {
++ /* FIXME : reverse engineer that for Rx00 cards */
++ /* FIXME : the mask supposedly contains low-res z values. So can't set
++ just to the max (0xff? or actually 0x3fff?), need to take z clear
++ value into account? */
++ /* pattern seems to work for r100, though get slight
++ rendering errors with glxgears. If hierz is not enabled for r100,
++ only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
++ other ones are ignored, and the same clear mask can be used. That's
++ very different behaviour than R200 which needs different clear mask
++ and different number of tiles to clear if hierz is enabled or not !?!
++ */
++ clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
++ } else {
++ /* clear mask : chooses the clearing pattern.
++ rv250: could be used to clear only parts of macrotiles
++ (but that would get really complicated...)?
++ bit 0 and 1 (either or both of them ?!?!) are used to
++ not clear tile (or maybe one of the bits indicates if the tile is
++ compressed or not), bit 2 and 3 to not clear tile 1,...,.
++ Pattern is as follows:
++ | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
++ bits -------------------------------------------------
++ | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
++ rv100: clearmask covers 2x8 4x1 tiles, but one clear still
++ covers 256 pixels ?!?
++ */
+ clearmask = 0x0;
+ }
+
+- BEGIN_RING( 8 );
++ BEGIN_RING(8);
+ RADEON_WAIT_UNTIL_2D_IDLE();
+- OUT_RING_REG( RADEON_RB3D_DEPTHCLEARVALUE,
+- tempRB3D_DEPTHCLEARVALUE);
++ OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
++ tempRB3D_DEPTHCLEARVALUE);
+ /* what offset is this exactly ? */
+- OUT_RING_REG( RADEON_RB3D_ZMASKOFFSET, 0 );
++ OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
+ /* need ctlstat, otherwise get some strange black flickering */
+- OUT_RING_REG( RADEON_RB3D_ZCACHE_CTLSTAT, RADEON_RB3D_ZC_FLUSH_ALL );
++ OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
++ RADEON_RB3D_ZC_FLUSH_ALL);
+ ADVANCE_RING();
+
+ for (i = 0; i < nbox; i++) {
+ int tileoffset, nrtilesx, nrtilesy, j;
+ /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
+- if ((dev_priv->flags&CHIP_HAS_HIERZ) && !(dev_priv->microcode_version==UCODE_R200)) {
++ if ((dev_priv->flags & CHIP_HAS_HIERZ)
++ && !(dev_priv->microcode_version == UCODE_R200)) {
+ /* FIXME : figure this out for r200 (when hierz is enabled). Or
+ maybe r200 actually doesn't need to put the low-res z value into
+ the tile cache like r100, but just needs to clear the hi-level z-buffer?
+@@ -850,59 +889,74 @@ static void radeon_cp_dispatch_clear( dr
+ R100 seems to operate on 2x1 8x8 tiles, but...
+ odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
+ problematic with resolutions which are not 64 pix aligned? */
+- tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 6;
+- nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4;
+- nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
++ tileoffset =
++ ((pbox[i].y1 >> 3) * depthpixperline +
++ pbox[i].x1) >> 6;
++ nrtilesx =
++ ((pbox[i].x2 & ~63) -
++ (pbox[i].x1 & ~63)) >> 4;
++ nrtilesy =
++ (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+ for (j = 0; j <= nrtilesy; j++) {
+- BEGIN_RING( 4 );
+- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
++ BEGIN_RING(4);
++ OUT_RING(CP_PACKET3
++ (RADEON_3D_CLEAR_ZMASK, 2));
+ /* first tile */
+- OUT_RING( tileoffset * 8 );
++ OUT_RING(tileoffset * 8);
+ /* the number of tiles to clear */
+- OUT_RING( nrtilesx + 4 );
++ OUT_RING(nrtilesx + 4);
+ /* clear mask : chooses the clearing pattern. */
+- OUT_RING( clearmask );
++ OUT_RING(clearmask);
+ ADVANCE_RING();
+ tileoffset += depthpixperline >> 6;
+ }
+- }
+- else if (dev_priv->microcode_version==UCODE_R200) {
++ } else if (dev_priv->microcode_version == UCODE_R200) {
+ /* works for rv250. */
+ /* find first macro tile (8x2 4x4 z-pixels on rv250) */
+- tileoffset = ((pbox[i].y1 >> 3) * depthpixperline + pbox[i].x1) >> 5;
+- nrtilesx = (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
+- nrtilesy = (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
++ tileoffset =
++ ((pbox[i].y1 >> 3) * depthpixperline +
++ pbox[i].x1) >> 5;
++ nrtilesx =
++ (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
++ nrtilesy =
++ (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+ for (j = 0; j <= nrtilesy; j++) {
+- BEGIN_RING( 4 );
+- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
++ BEGIN_RING(4);
++ OUT_RING(CP_PACKET3
++ (RADEON_3D_CLEAR_ZMASK, 2));
+ /* first tile */
+ /* judging by the first tile offset needed, could possibly
+ directly address/clear 4x4 tiles instead of 8x2 * 4x4
+ macro tiles, though would still need clear mask for
+ right/bottom if truely 4x4 granularity is desired ? */
+- OUT_RING( tileoffset * 16 );
++ OUT_RING(tileoffset * 16);
+ /* the number of tiles to clear */
+- OUT_RING( nrtilesx + 1 );
++ OUT_RING(nrtilesx + 1);
+ /* clear mask : chooses the clearing pattern. */
+- OUT_RING( clearmask );
++ OUT_RING(clearmask);
+ ADVANCE_RING();
+ tileoffset += depthpixperline >> 5;
+ }
+- }
+- else { /* rv 100 */
++ } else { /* rv 100 */
+ /* rv100 might not need 64 pix alignment, who knows */
+ /* offsets are, hmm, weird */
+- tileoffset = ((pbox[i].y1 >> 4) * depthpixperline + pbox[i].x1) >> 6;
+- nrtilesx = ((pbox[i].x2 & ~63) - (pbox[i].x1 & ~63)) >> 4;
+- nrtilesy = (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
++ tileoffset =
++ ((pbox[i].y1 >> 4) * depthpixperline +
++ pbox[i].x1) >> 6;
++ nrtilesx =
++ ((pbox[i].x2 & ~63) -
++ (pbox[i].x1 & ~63)) >> 4;
++ nrtilesy =
++ (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
+ for (j = 0; j <= nrtilesy; j++) {
+- BEGIN_RING( 4 );
+- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_ZMASK, 2 ) );
+- OUT_RING( tileoffset * 128 );
++ BEGIN_RING(4);
++ OUT_RING(CP_PACKET3
++ (RADEON_3D_CLEAR_ZMASK, 2));
++ OUT_RING(tileoffset * 128);
+ /* the number of tiles to clear */
+- OUT_RING( nrtilesx + 4 );
++ OUT_RING(nrtilesx + 4);
+ /* clear mask : chooses the clearing pattern. */
+- OUT_RING( clearmask );
++ OUT_RING(clearmask);
+ ADVANCE_RING();
+ tileoffset += depthpixperline >> 6;
+ }
+@@ -910,18 +964,19 @@ static void radeon_cp_dispatch_clear( dr
+ }
+
+ /* TODO don't always clear all hi-level z tiles */
+- if ((dev_priv->flags & CHIP_HAS_HIERZ) && (dev_priv->microcode_version==UCODE_R200)
+- && (flags & RADEON_USE_HIERZ))
+- /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
+- /* FIXME : the mask supposedly contains low-res z values. So can't set
+- just to the max (0xff? or actually 0x3fff?), need to take z clear
+- value into account? */
++ if ((dev_priv->flags & CHIP_HAS_HIERZ)
++ && (dev_priv->microcode_version == UCODE_R200)
++ && (flags & RADEON_USE_HIERZ))
++ /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
++ /* FIXME : the mask supposedly contains low-res z values. So can't set
++ just to the max (0xff? or actually 0x3fff?), need to take z clear
++ value into account? */
+ {
+- BEGIN_RING( 4 );
+- OUT_RING( CP_PACKET3( RADEON_3D_CLEAR_HIZ, 2 ) );
+- OUT_RING( 0x0 ); /* First tile */
+- OUT_RING( 0x3cc0 );
+- OUT_RING( (0xff<<22)|(0xff<<6)| 0x003f003f);
++ BEGIN_RING(4);
++ OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
++ OUT_RING(0x0); /* First tile */
++ OUT_RING(0x3cc0);
++ OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
+ ADVANCE_RING();
+ }
+ }
+@@ -956,30 +1011,27 @@ static void radeon_cp_dispatch_clear( dr
+
+ tempSE_CNTL = depth_clear->se_cntl;
+
+-
+-
+ /* Disable TCL */
+
+- tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */
+- (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
++ tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */
++ (0x9 <<
++ SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
+
+ tempRB3D_PLANEMASK = 0x0;
+
+ tempRE_AUX_SCISSOR_CNTL = 0x0;
+
+ tempSE_VTE_CNTL =
+- SE_VTE_CNTL__VTX_XY_FMT_MASK |
+- SE_VTE_CNTL__VTX_Z_FMT_MASK;
++ SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
+
+- /* Vertex format (X, Y, Z, W)*/
++ /* Vertex format (X, Y, Z, W) */
+ tempSE_VTX_FMT_0 =
+- SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
+- SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
++ SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
++ SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
+ tempSE_VTX_FMT_1 = 0x0;
+
+-
+- /*
+- * Depth buffer specific enables
++ /*
++ * Depth buffer specific enables
+ */
+ if (flags & RADEON_DEPTH) {
+ /* Enable depth buffer */
+@@ -989,12 +1041,12 @@ static void radeon_cp_dispatch_clear( dr
+ tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
+ }
+
+- /*
++ /*
+ * Stencil buffer specific enables
+ */
+- if ( flags & RADEON_STENCIL ) {
+- tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
+- tempRB3D_STENCILREFMASK = clear->depth_mask;
++ if (flags & RADEON_STENCIL) {
++ tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
++ tempRB3D_STENCILREFMASK = clear->depth_mask;
+ } else {
+ tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
+ tempRB3D_STENCILREFMASK = 0x00000000;
+@@ -1002,79 +1054,75 @@ static void radeon_cp_dispatch_clear( dr
+
+ if (flags & RADEON_USE_COMP_ZBUF) {
+ tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
+- RADEON_Z_DECOMPRESSION_ENABLE;
++ RADEON_Z_DECOMPRESSION_ENABLE;
+ }
+ if (flags & RADEON_USE_HIERZ) {
+ tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
+ }
+
+- BEGIN_RING( 26 );
++ BEGIN_RING(26);
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+- OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL );
+- OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL );
+- OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL );
+- OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
+- tempRB3D_ZSTENCILCNTL );
+- OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
+- tempRB3D_STENCILREFMASK );
+- OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK );
+- OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL );
+- OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL );
+- OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 );
+- OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 );
+- OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL );
+- OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL,
+- tempRE_AUX_SCISSOR_CNTL );
++ OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
++ OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
++ OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
++ OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
++ OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
++ tempRB3D_STENCILREFMASK);
++ OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
++ OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
++ OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
++ OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
++ OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
++ OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
++ OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
+ ADVANCE_RING();
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->ctx_owner = 0;
+
+- for ( i = 0 ; i < nbox ; i++ ) {
+-
+- /* Funny that this should be required --
++ for (i = 0; i < nbox; i++) {
++
++ /* Funny that this should be required --
+ * sets top-left?
+ */
+- radeon_emit_clip_rect( dev_priv,
+- &sarea_priv->boxes[i] );
++ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+- BEGIN_RING( 14 );
+- OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) );
+- OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
+- RADEON_PRIM_WALK_RING |
+- (3 << RADEON_NUM_VERTICES_SHIFT)) );
+- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+- OUT_RING( 0x3f800000 );
+- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+- OUT_RING( 0x3f800000 );
+- OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+- OUT_RING( 0x3f800000 );
++ BEGIN_RING(14);
++ OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
++ OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
++ RADEON_PRIM_WALK_RING |
++ (3 << RADEON_NUM_VERTICES_SHIFT)));
++ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
++ OUT_RING(0x3f800000);
++ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
++ OUT_RING(0x3f800000);
++ OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
++ OUT_RING(0x3f800000);
+ ADVANCE_RING();
+ }
+- }
+- else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
++ } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+
+ int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
+
+ rb3d_cntl = depth_clear->rb3d_cntl;
+
+- if ( flags & RADEON_DEPTH ) {
+- rb3d_cntl |= RADEON_Z_ENABLE;
++ if (flags & RADEON_DEPTH) {
++ rb3d_cntl |= RADEON_Z_ENABLE;
+ } else {
+ rb3d_cntl &= ~RADEON_Z_ENABLE;
+ }
+
+- if ( flags & RADEON_STENCIL ) {
+- rb3d_cntl |= RADEON_STENCIL_ENABLE;
+- rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
++ if (flags & RADEON_STENCIL) {
++ rb3d_cntl |= RADEON_STENCIL_ENABLE;
++ rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
+ } else {
+ rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
+ rb3d_stencilrefmask = 0x00000000;
+@@ -1082,66 +1130,61 @@ static void radeon_cp_dispatch_clear( dr
+
+ if (flags & RADEON_USE_COMP_ZBUF) {
+ tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
+- RADEON_Z_DECOMPRESSION_ENABLE;
++ RADEON_Z_DECOMPRESSION_ENABLE;
+ }
+ if (flags & RADEON_USE_HIERZ) {
+ tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
+ }
+
+- BEGIN_RING( 13 );
++ BEGIN_RING(13);
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+- OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
+- OUT_RING( 0x00000000 );
+- OUT_RING( rb3d_cntl );
+-
+- OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL );
+- OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
+- rb3d_stencilrefmask );
+- OUT_RING_REG( RADEON_RB3D_PLANEMASK,
+- 0x00000000 );
+- OUT_RING_REG( RADEON_SE_CNTL,
+- depth_clear->se_cntl );
++ OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
++ OUT_RING(0x00000000);
++ OUT_RING(rb3d_cntl);
++
++ OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
++ OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
++ OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
++ OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
+ ADVANCE_RING();
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->ctx_owner = 0;
+
+- for ( i = 0 ; i < nbox ; i++ ) {
+-
+- /* Funny that this should be required --
++ for (i = 0; i < nbox; i++) {
++
++ /* Funny that this should be required --
+ * sets top-left?
+ */
+- radeon_emit_clip_rect( dev_priv,
+- &sarea_priv->boxes[i] );
++ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+- BEGIN_RING( 15 );
++ BEGIN_RING(15);
+
+- OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) );
+- OUT_RING( RADEON_VTX_Z_PRESENT |
+- RADEON_VTX_PKCOLOR_PRESENT);
+- OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
+- RADEON_PRIM_WALK_RING |
+- RADEON_MAOS_ENABLE |
+- RADEON_VTX_FMT_RADEON_MODE |
+- (3 << RADEON_NUM_VERTICES_SHIFT)) );
+-
+-
+- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+- OUT_RING( 0x0 );
+-
+- OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+- OUT_RING( 0x0 );
+-
+- OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+- OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+- OUT_RING( 0x0 );
++ OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
++ OUT_RING(RADEON_VTX_Z_PRESENT |
++ RADEON_VTX_PKCOLOR_PRESENT);
++ OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
++ RADEON_PRIM_WALK_RING |
++ RADEON_MAOS_ENABLE |
++ RADEON_VTX_FMT_RADEON_MODE |
++ (3 << RADEON_NUM_VERTICES_SHIFT)));
++
++ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
++ OUT_RING(0x0);
++
++ OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
++ OUT_RING(0x0);
++
++ OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
++ OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
++ OUT_RING(0x0);
+
+ ADVANCE_RING();
+ }
+@@ -1153,15 +1196,15 @@ static void radeon_cp_dispatch_clear( dr
+ */
+ dev_priv->sarea_priv->last_clear++;
+
+- BEGIN_RING( 4 );
++ BEGIN_RING(4);
+
+- RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
++ RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+ }
+
+-static void radeon_cp_dispatch_swap( drm_device_t *dev )
++static void radeon_cp_dispatch_swap(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -1169,59 +1212,55 @@ static void radeon_cp_dispatch_swap( drm
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ /* Do some trivial performance monitoring...
+ */
+ if (dev_priv->do_boxes)
+- radeon_cp_performance_boxes( dev_priv );
+-
++ radeon_cp_performance_boxes(dev_priv);
+
+ /* Wait for the 3D stream to idle before dispatching the bitblt.
+ * This will prevent data corruption between the two streams.
+ */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+ ADVANCE_RING();
+
+- for ( i = 0 ; i < nbox ; i++ ) {
++ for (i = 0; i < nbox; i++) {
+ int x = pbox[i].x1;
+ int y = pbox[i].y1;
+ int w = pbox[i].x2 - x;
+ int h = pbox[i].y2 - y;
+
+- DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n",
+- x, y, w, h );
++ DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
+
+- BEGIN_RING( 7 );
++ BEGIN_RING(7);
++
++ OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
++ OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
++ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
++ RADEON_GMC_BRUSH_NONE |
++ (dev_priv->color_fmt << 8) |
++ RADEON_GMC_SRC_DATATYPE_COLOR |
++ RADEON_ROP3_S |
++ RADEON_DP_SRC_SOURCE_MEMORY |
++ RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+
+- OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
+- OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+- RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+- RADEON_GMC_BRUSH_NONE |
+- (dev_priv->color_fmt << 8) |
+- RADEON_GMC_SRC_DATATYPE_COLOR |
+- RADEON_ROP3_S |
+- RADEON_DP_SRC_SOURCE_MEMORY |
+- RADEON_GMC_CLR_CMP_CNTL_DIS |
+- RADEON_GMC_WR_MSK_DIS );
+-
+ /* Make this work even if front & back are flipped:
+ */
+ if (dev_priv->current_page == 0) {
+- OUT_RING( dev_priv->back_pitch_offset );
+- OUT_RING( dev_priv->front_pitch_offset );
+- }
+- else {
+- OUT_RING( dev_priv->front_pitch_offset );
+- OUT_RING( dev_priv->back_pitch_offset );
++ OUT_RING(dev_priv->back_pitch_offset);
++ OUT_RING(dev_priv->front_pitch_offset);
++ } else {
++ OUT_RING(dev_priv->front_pitch_offset);
++ OUT_RING(dev_priv->back_pitch_offset);
+ }
+
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (x << 16) | y );
+- OUT_RING( (w << 16) | h );
++ OUT_RING((x << 16) | y);
++ OUT_RING((x << 16) | y);
++ OUT_RING((w << 16) | h);
+
+ ADVANCE_RING();
+ }
+@@ -1232,44 +1271,43 @@ static void radeon_cp_dispatch_swap( drm
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+- BEGIN_RING( 4 );
++ BEGIN_RING(4);
+
+- RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
++ RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+ ADVANCE_RING();
+ }
+
+-static void radeon_cp_dispatch_flip( drm_device_t *dev )
++static void radeon_cp_dispatch_flip(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
++ drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
+ int offset = (dev_priv->current_page == 1)
+- ? dev_priv->front_offset : dev_priv->back_offset;
++ ? dev_priv->front_offset : dev_priv->back_offset;
+ RING_LOCALS;
+- DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n",
+- __FUNCTION__,
+- dev_priv->current_page,
+- dev_priv->sarea_priv->pfCurrentPage);
++ DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
++ __FUNCTION__,
++ dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+
+ /* Do some trivial performance monitoring...
+ */
+ if (dev_priv->do_boxes) {
+ dev_priv->stats.boxes |= RADEON_BOX_FLIP;
+- radeon_cp_performance_boxes( dev_priv );
++ radeon_cp_performance_boxes(dev_priv);
+ }
+
+ /* Update the frame offsets for both CRTCs
+ */
+- BEGIN_RING( 6 );
++ BEGIN_RING(6);
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+- OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch
+- + sarea->frame.x
+- * ( dev_priv->color_fmt - 2 ) ) & ~7 )
+- + offset );
+- OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
+- + offset );
++ OUT_RING_REG(RADEON_CRTC_OFFSET,
++ ((sarea->frame.y * dev_priv->front_pitch +
++ sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
++ + offset);
++ OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
++ + offset);
+
+ ADVANCE_RING();
+
+@@ -1279,16 +1317,16 @@ static void radeon_cp_dispatch_flip( drm
+ */
+ dev_priv->sarea_priv->last_frame++;
+ dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
+- 1 - dev_priv->current_page;
++ 1 - dev_priv->current_page;
+
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+- RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
++ RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
+
+ ADVANCE_RING();
+ }
+
+-static int bad_prim_vertex_nr( int primitive, int nr )
++static int bad_prim_vertex_nr(int primitive, int nr)
+ {
+ switch (primitive & RADEON_PRIM_TYPE_MASK) {
+ case RADEON_PRIM_TYPE_NONE:
+@@ -1308,24 +1346,21 @@ static int bad_prim_vertex_nr( int primi
+ return nr < 3;
+ default:
+ return 1;
+- }
++ }
+ }
+
+-
+-
+ typedef struct {
+ unsigned int start;
+ unsigned int finish;
+ unsigned int prim;
+ unsigned int numverts;
+- unsigned int offset;
+- unsigned int vc_format;
++ unsigned int offset;
++ unsigned int vc_format;
+ } drm_radeon_tcl_prim_t;
+
+-static void radeon_cp_dispatch_vertex( drm_device_t *dev,
+- drm_buf_t *buf,
+- drm_radeon_tcl_prim_t *prim )
+-
++static void radeon_cp_dispatch_vertex(drm_device_t * dev,
++ drm_buf_t * buf,
++ drm_radeon_tcl_prim_t * prim)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -1337,45 +1372,39 @@ static void radeon_cp_dispatch_vertex( d
+
+ DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
+ prim->prim,
+- prim->vc_format,
+- prim->start,
+- prim->finish,
+- prim->numverts);
+-
+- if (bad_prim_vertex_nr( prim->prim, prim->numverts )) {
+- DRM_ERROR( "bad prim %x numverts %d\n",
+- prim->prim, prim->numverts );
++ prim->vc_format, prim->start, prim->finish, prim->numverts);
++
++ if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
++ DRM_ERROR("bad prim %x numverts %d\n",
++ prim->prim, prim->numverts);
+ return;
+ }
+
+ do {
+ /* Emit the next cliprect */
+- if ( i < nbox ) {
+- radeon_emit_clip_rect( dev_priv,
+- &sarea_priv->boxes[i] );
++ if (i < nbox) {
++ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+ }
+
+ /* Emit the vertex buffer rendering commands */
+- BEGIN_RING( 5 );
++ BEGIN_RING(5);
+
+- OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+- OUT_RING( offset );
+- OUT_RING( numverts );
+- OUT_RING( prim->vc_format );
+- OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST |
+- RADEON_COLOR_ORDER_RGBA |
+- RADEON_VTX_FMT_RADEON_MODE |
+- (numverts << RADEON_NUM_VERTICES_SHIFT) );
++ OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
++ OUT_RING(offset);
++ OUT_RING(numverts);
++ OUT_RING(prim->vc_format);
++ OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
++ RADEON_COLOR_ORDER_RGBA |
++ RADEON_VTX_FMT_RADEON_MODE |
++ (numverts << RADEON_NUM_VERTICES_SHIFT));
+
+ ADVANCE_RING();
+
+ i++;
+- } while ( i < nbox );
++ } while (i < nbox);
+ }
+
+-
+-
+-static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
++static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+@@ -1384,24 +1413,22 @@ static void radeon_cp_discard_buffer( dr
+ buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+- BEGIN_RING( 2 );
+- RADEON_DISPATCH_AGE( buf_priv->age );
++ BEGIN_RING(2);
++ RADEON_DISPATCH_AGE(buf_priv->age);
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ buf->used = 0;
+ }
+
+-static void radeon_cp_dispatch_indirect( drm_device_t *dev,
+- drm_buf_t *buf,
+- int start, int end )
++static void radeon_cp_dispatch_indirect(drm_device_t * dev,
++ drm_buf_t * buf, int start, int end)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+- DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
+- buf->idx, start, end );
++ DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
+
+- if ( start != end ) {
++ if (start != end) {
+ int offset = (dev_priv->gart_buffers_offset
+ + buf->offset + start);
+ int dwords = (end - start + 3) / sizeof(u32);
+@@ -1410,28 +1437,27 @@ static void radeon_cp_dispatch_indirect(
+ * dwords, so if we've been given an odd number we must
+ * pad the data with a Type-2 CP packet.
+ */
+- if ( dwords & 1 ) {
++ if (dwords & 1) {
+ u32 *data = (u32 *)
+- ((char *)dev->agp_buffer_map->handle
+- + buf->offset + start);
++ ((char *)dev->agp_buffer_map->handle
++ + buf->offset + start);
+ data[dwords++] = RADEON_CP_PACKET2;
+ }
+
+ /* Fire off the indirect buffer */
+- BEGIN_RING( 3 );
++ BEGIN_RING(3);
+
+- OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
+- OUT_RING( offset );
+- OUT_RING( dwords );
++ OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
++ OUT_RING(offset);
++ OUT_RING(dwords);
+
+ ADVANCE_RING();
+ }
+ }
+
+-
+-static void radeon_cp_dispatch_indices( drm_device_t *dev,
+- drm_buf_t *elt_buf,
+- drm_radeon_tcl_prim_t *prim )
++static void radeon_cp_dispatch_indices(drm_device_t * dev,
++ drm_buf_t * elt_buf,
++ drm_radeon_tcl_prim_t * prim)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+@@ -1446,30 +1472,24 @@ static void radeon_cp_dispatch_indices(
+ DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
+ prim->prim,
+ prim->vc_format,
+- prim->start,
+- prim->finish,
+- prim->offset,
+- prim->numverts);
+-
+- if (bad_prim_vertex_nr( prim->prim, count )) {
+- DRM_ERROR( "bad prim %x count %d\n",
+- prim->prim, count );
++ prim->start, prim->finish, prim->offset, prim->numverts);
++
++ if (bad_prim_vertex_nr(prim->prim, count)) {
++ DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
+ return;
+ }
+
+-
+- if ( start >= prim->finish ||
+- (prim->start & 0x7) ) {
+- DRM_ERROR( "buffer prim %d\n", prim->prim );
++ if (start >= prim->finish || (prim->start & 0x7)) {
++ DRM_ERROR("buffer prim %d\n", prim->prim);
+ return;
+ }
+
+ dwords = (prim->finish - prim->start + 3) / sizeof(u32);
+
+- data = (u32 *)((char *)dev->agp_buffer_map->handle +
+- elt_buf->offset + prim->start);
++ data = (u32 *) ((char *)dev->agp_buffer_map->handle +
++ elt_buf->offset + prim->start);
+
+- data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
++ data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
+ data[1] = offset;
+ data[2] = prim->numverts;
+ data[3] = prim->vc_format;
+@@ -1477,28 +1497,26 @@ static void radeon_cp_dispatch_indices(
+ RADEON_PRIM_WALK_IND |
+ RADEON_COLOR_ORDER_RGBA |
+ RADEON_VTX_FMT_RADEON_MODE |
+- (count << RADEON_NUM_VERTICES_SHIFT) );
++ (count << RADEON_NUM_VERTICES_SHIFT));
+
+ do {
+- if ( i < nbox )
+- radeon_emit_clip_rect( dev_priv,
+- &sarea_priv->boxes[i] );
+-
+- radeon_cp_dispatch_indirect( dev, elt_buf,
+- prim->start,
+- prim->finish );
++ if (i < nbox)
++ radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
++
++ radeon_cp_dispatch_indirect(dev, elt_buf,
++ prim->start, prim->finish);
+
+ i++;
+- } while ( i < nbox );
++ } while (i < nbox);
+
+ }
+
+ #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
+
+-static int radeon_cp_dispatch_texture( DRMFILE filp,
+- drm_device_t *dev,
+- drm_radeon_texture_t *tex,
+- drm_radeon_tex_image_t *image )
++static int radeon_cp_dispatch_texture(DRMFILE filp,
++ drm_device_t * dev,
++ drm_radeon_texture_t * tex,
++ drm_radeon_tex_image_t * image)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
+@@ -1513,11 +1531,11 @@ static int radeon_cp_dispatch_texture( D
+ u32 offset;
+ RING_LOCALS;
+
+- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
++ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
+- DRM_ERROR( "Invalid destination offset\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) {
++ DRM_ERROR("Invalid destination offset\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
+@@ -1526,7 +1544,7 @@ static int radeon_cp_dispatch_texture( D
+ * up with the texture data from the host data blit, otherwise
+ * part of the texture image may be corrupted.
+ */
+- BEGIN_RING( 4 );
++ BEGIN_RING(4);
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+ ADVANCE_RING();
+@@ -1535,7 +1553,7 @@ static int radeon_cp_dispatch_texture( D
+ * even if the only legal values are powers of two. Thus, we'll
+ * use a shift instead.
+ */
+- switch ( tex->format ) {
++ switch (tex->format) {
+ case RADEON_TXFORMAT_ARGB8888:
+ case RADEON_TXFORMAT_RGBA8888:
+ format = RADEON_COLOR_FORMAT_ARGB8888;
+@@ -1559,7 +1577,7 @@ static int radeon_cp_dispatch_texture( D
+ blit_width = image->width * 1;
+ break;
+ default:
+- DRM_ERROR( "invalid texture format %d\n", tex->format );
++ DRM_ERROR("invalid texture format %d\n", tex->format);
+ return DRM_ERR(EINVAL);
+ }
+ spitch = blit_width >> 6;
+@@ -1574,49 +1592,49 @@ static int radeon_cp_dispatch_texture( D
+ /* we got tiled coordinates, untile them */
+ image->x *= 2;
+ }
+- }
+- else microtile = 0;
++ } else
++ microtile = 0;
+
+- DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
++ DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
+
+ do {
+- DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+- tex->offset >> 10, tex->pitch, tex->format,
+- image->x, image->y, image->width, image->height );
++ DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
++ tex->offset >> 10, tex->pitch, tex->format,
++ image->x, image->y, image->width, image->height);
+
+ /* Make a copy of some parameters in case we have to
+ * update them for a multi-pass texture blit.
+ */
+ height = image->height;
+ data = (const u8 __user *)image->data;
+-
++
+ size = height * blit_width;
+
+- if ( size > RADEON_MAX_TEXTURE_SIZE ) {
++ if (size > RADEON_MAX_TEXTURE_SIZE) {
+ height = RADEON_MAX_TEXTURE_SIZE / blit_width;
+ size = height * blit_width;
+- } else if ( size < 4 && size > 0 ) {
++ } else if (size < 4 && size > 0) {
+ size = 4;
+- } else if ( size == 0 ) {
++ } else if (size == 0) {
+ return 0;
+ }
+
+- buf = radeon_freelist_get( dev );
+- if ( 0 && !buf ) {
+- radeon_do_cp_idle( dev_priv );
+- buf = radeon_freelist_get( dev );
++ buf = radeon_freelist_get(dev);
++ if (0 && !buf) {
++ radeon_do_cp_idle(dev_priv);
++ buf = radeon_freelist_get(dev);
+ }
+- if ( !buf ) {
++ if (!buf) {
+ DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
+- if (DRM_COPY_TO_USER( tex->image, image, sizeof(*image) ))
++ if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+ return DRM_ERR(EFAULT);
+ return DRM_ERR(EAGAIN);
+ }
+
+-
+ /* Dispatch the indirect buffer.
+ */
+- buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset);
++ buffer =
++ (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+ dwords = size / 4;
+
+ if (microtile) {
+@@ -1631,20 +1649,26 @@ static int radeon_cp_dispatch_texture( D
+ if (tex->height == 1) {
+ if (tex_width >= 64 || tex_width <= 16) {
+ if (DRM_COPY_FROM_USER(buffer, data,
+- tex_width * sizeof(u32))) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ tex_width *
++ sizeof(u32))) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ } else if (tex_width == 32) {
+- if (DRM_COPY_FROM_USER(buffer, data, 16)) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ if (DRM_COPY_FROM_USER
++ (buffer, data, 16)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+- if (DRM_COPY_FROM_USER(buffer + 8, data + 16, 16)) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ if (DRM_COPY_FROM_USER
++ (buffer + 8, data + 16, 16)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ }
+@@ -1657,9 +1681,11 @@ static int radeon_cp_dispatch_texture( D
+ }
+ } else if (tex_width < 16) {
+ for (i = 0; i < tex->height; i++) {
+- if (DRM_COPY_FROM_USER(buffer, data, tex_width)) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ if (DRM_COPY_FROM_USER
++ (buffer, data, tex_width)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ buffer += 4;
+@@ -1669,35 +1695,42 @@ static int radeon_cp_dispatch_texture( D
+ /* TODO: make sure this works when not fitting in one buffer
+ (i.e. 32bytes x 2048...) */
+ for (i = 0; i < tex->height; i += 2) {
+- if (DRM_COPY_FROM_USER(buffer, data, 16)) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ if (DRM_COPY_FROM_USER
++ (buffer, data, 16)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+- if (DRM_COPY_FROM_USER(buffer + 8, data, 16)) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ if (DRM_COPY_FROM_USER
++ (buffer + 8, data, 16)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+- if (DRM_COPY_FROM_USER(buffer + 4, data, 16)) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ if (DRM_COPY_FROM_USER
++ (buffer + 4, data, 16)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+- if (DRM_COPY_FROM_USER(buffer + 12, data, 16)) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n",
+- tex_width);
++ if (DRM_COPY_FROM_USER
++ (buffer + 12, data, 16)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+ buffer += 16;
+ }
+ }
+- }
+- else {
++ } else {
+ if (tex_width >= 32) {
+ /* Texture image width is larger than the minimum, so we
+ * can upload it directly.
+@@ -1713,9 +1746,12 @@ static int radeon_cp_dispatch_texture( D
+ * need to pad out each image scanline to the minimum
+ * width.
+ */
+- for (i = 0 ; i < tex->height ; i++) {
+- if (DRM_COPY_FROM_USER(buffer, data, tex_width )) {
+- DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width);
++ for (i = 0; i < tex->height; i++) {
++ if (DRM_COPY_FROM_USER
++ (buffer, data, tex_width)) {
++ DRM_ERROR
++ ("EFAULT on pad, %d bytes\n",
++ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ buffer += 8;
+@@ -1736,8 +1772,7 @@ static int radeon_cp_dispatch_texture( D
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+- RADEON_GMC_CLR_CMP_CNTL_DIS |
+- RADEON_GMC_WR_MSK_DIS );
++ RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+ OUT_RING((spitch << 22) | (offset >> 10));
+ OUT_RING((texpitch << 22) | (tex->offset >> 10));
+ OUT_RING(0);
+@@ -1758,62 +1793,62 @@ static int radeon_cp_dispatch_texture( D
+ * the texture data is written out to memory before rendering
+ * continues.
+ */
+- BEGIN_RING( 4 );
++ BEGIN_RING(4);
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_2D_IDLE();
+ ADVANCE_RING();
+ return 0;
+ }
+
+-
+-static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
++static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int i;
+ RING_LOCALS;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- BEGIN_RING( 35 );
++ BEGIN_RING(35);
+
+- OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
+- OUT_RING( 0x00000000 );
++ OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
++ OUT_RING(0x00000000);
+
+- OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
+- for ( i = 0 ; i < 32 ; i++ ) {
+- OUT_RING( stipple[i] );
++ OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
++ for (i = 0; i < 32; i++) {
++ OUT_RING(stipple[i]);
+ }
+
+ ADVANCE_RING();
+ }
+
+-static void radeon_apply_surface_regs(int surf_index, drm_radeon_private_t *dev_priv)
++static void radeon_apply_surface_regs(int surf_index,
++ drm_radeon_private_t * dev_priv)
+ {
+ if (!dev_priv->mmio)
+ return;
+
+ radeon_do_cp_idle(dev_priv);
+
+- RADEON_WRITE(RADEON_SURFACE0_INFO + 16*surf_index,
+- dev_priv->surfaces[surf_index].flags);
+- RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16*surf_index,
+- dev_priv->surfaces[surf_index].lower);
+- RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16*surf_index,
+- dev_priv->surfaces[surf_index].upper);
++ RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
++ dev_priv->surfaces[surf_index].flags);
++ RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
++ dev_priv->surfaces[surf_index].lower);
++ RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
++ dev_priv->surfaces[surf_index].upper);
+ }
+
+-
+ /* Allocates a virtual surface
+- * doesn't always allocate a real surface, will stretch an existing
++ * doesn't always allocate a real surface, will stretch an existing
+ * surface when possible.
+ *
+ * Note that refcount can be at most 2, since during a free refcount=3
+ * might mean we have to allocate a new surface which might not always
+ * be available.
+- * For example : we allocate three contigous surfaces ABC. If B is
++ * For example : we allocate three contigous surfaces ABC. If B is
+ * freed, we suddenly need two surfaces to store A and C, which might
+ * not always be available.
+ */
+-static int alloc_surface(drm_radeon_surface_alloc_t* new, drm_radeon_private_t *dev_priv, DRMFILE filp)
++static int alloc_surface(drm_radeon_surface_alloc_t * new,
++ drm_radeon_private_t * dev_priv, DRMFILE filp)
+ {
+ struct radeon_virt_surface *s;
+ int i;
+@@ -1825,34 +1860,37 @@ static int alloc_surface(drm_radeon_surf
+
+ /* sanity check */
+ if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
+- ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) != RADEON_SURF_ADDRESS_FIXED_MASK) ||
+- ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
++ ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
++ RADEON_SURF_ADDRESS_FIXED_MASK)
++ || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
+ return -1;
+
+ /* make sure there is no overlap with existing surfaces */
+ for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+ if ((dev_priv->surfaces[i].refcount != 0) &&
+- (( (new_lower >= dev_priv->surfaces[i].lower) &&
+- (new_lower < dev_priv->surfaces[i].upper) ) ||
+- ( (new_lower < dev_priv->surfaces[i].lower) &&
+- (new_upper > dev_priv->surfaces[i].lower) )) ){
+- return -1;}
++ (((new_lower >= dev_priv->surfaces[i].lower) &&
++ (new_lower < dev_priv->surfaces[i].upper)) ||
++ ((new_lower < dev_priv->surfaces[i].lower) &&
++ (new_upper > dev_priv->surfaces[i].lower)))) {
++ return -1;
++ }
+ }
+
+ /* find a virtual surface */
+- for (i = 0; i < 2*RADEON_MAX_SURFACES; i++)
++ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
+ if (dev_priv->virt_surfaces[i].filp == 0)
+ break;
+- if (i == 2*RADEON_MAX_SURFACES) {
+- return -1;}
++ if (i == 2 * RADEON_MAX_SURFACES) {
++ return -1;
++ }
+ virt_surface_index = i;
+
+ /* try to reuse an existing surface */
+ for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+ /* extend before */
+ if ((dev_priv->surfaces[i].refcount == 1) &&
+- (new->flags == dev_priv->surfaces[i].flags) &&
+- (new_upper + 1 == dev_priv->surfaces[i].lower)) {
++ (new->flags == dev_priv->surfaces[i].flags) &&
++ (new_upper + 1 == dev_priv->surfaces[i].lower)) {
+ s = &(dev_priv->virt_surfaces[virt_surface_index]);
+ s->surface_index = i;
+ s->lower = new_lower;
+@@ -1867,8 +1905,8 @@ static int alloc_surface(drm_radeon_surf
+
+ /* extend after */
+ if ((dev_priv->surfaces[i].refcount == 1) &&
+- (new->flags == dev_priv->surfaces[i].flags) &&
+- (new_lower == dev_priv->surfaces[i].upper + 1)) {
++ (new->flags == dev_priv->surfaces[i].flags) &&
++ (new_lower == dev_priv->surfaces[i].upper + 1)) {
+ s = &(dev_priv->virt_surfaces[virt_surface_index]);
+ s->surface_index = i;
+ s->lower = new_lower;
+@@ -1904,26 +1942,34 @@ static int alloc_surface(drm_radeon_surf
+ return -1;
+ }
+
+-static int free_surface(DRMFILE filp, drm_radeon_private_t *dev_priv, int lower)
++static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
++ int lower)
+ {
+ struct radeon_virt_surface *s;
+ int i;
+ /* find the virtual surface */
+- for(i = 0; i < 2*RADEON_MAX_SURFACES; i++) {
++ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
+ s = &(dev_priv->virt_surfaces[i]);
+ if (s->filp) {
+ if ((lower == s->lower) && (filp == s->filp)) {
+- if (dev_priv->surfaces[s->surface_index].lower == s->lower)
+- dev_priv->surfaces[s->surface_index].lower = s->upper;
+-
+- if (dev_priv->surfaces[s->surface_index].upper == s->upper)
+- dev_priv->surfaces[s->surface_index].upper = s->lower;
++ if (dev_priv->surfaces[s->surface_index].
++ lower == s->lower)
++ dev_priv->surfaces[s->surface_index].
++ lower = s->upper;
++
++ if (dev_priv->surfaces[s->surface_index].
++ upper == s->upper)
++ dev_priv->surfaces[s->surface_index].
++ upper = s->lower;
+
+ dev_priv->surfaces[s->surface_index].refcount--;
+- if (dev_priv->surfaces[s->surface_index].refcount == 0)
+- dev_priv->surfaces[s->surface_index].flags = 0;
++ if (dev_priv->surfaces[s->surface_index].
++ refcount == 0)
++ dev_priv->surfaces[s->surface_index].
++ flags = 0;
+ s->filp = NULL;
+- radeon_apply_surface_regs(s->surface_index, dev_priv);
++ radeon_apply_surface_regs(s->surface_index,
++ dev_priv);
+ return 0;
+ }
+ }
+@@ -1931,13 +1977,14 @@ static int free_surface(DRMFILE filp, dr
+ return 1;
+ }
+
+-static void radeon_surfaces_release(DRMFILE filp, drm_radeon_private_t *dev_priv)
++static void radeon_surfaces_release(DRMFILE filp,
++ drm_radeon_private_t * dev_priv)
+ {
+ int i;
+- for( i = 0; i < 2*RADEON_MAX_SURFACES; i++)
+- {
++ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
+ if (dev_priv->virt_surfaces[i].filp == filp)
+- free_surface(filp, dev_priv, dev_priv->virt_surfaces[i].lower);
++ free_surface(filp, dev_priv,
++ dev_priv->virt_surfaces[i].lower);
+ }
+ }
+
+@@ -1951,12 +1998,13 @@ static int radeon_surface_alloc(DRM_IOCT
+ drm_radeon_surface_alloc_t alloc;
+
+ if (!dev_priv) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_surface_alloc_t __user *)data,
+- sizeof(alloc));
++ DRM_COPY_FROM_USER_IOCTL(alloc,
++ (drm_radeon_surface_alloc_t __user *) data,
++ sizeof(alloc));
+
+ if (alloc_surface(&alloc, dev_priv, filp) == -1)
+ return DRM_ERR(EINVAL);
+@@ -1971,12 +2019,12 @@ static int radeon_surface_free(DRM_IOCTL
+ drm_radeon_surface_free_t memfree;
+
+ if (!dev_priv) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *)data,
+- sizeof(memfree) );
++ DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
++ sizeof(memfree));
+
+ if (free_surface(filp, dev_priv, memfree.address))
+ return DRM_ERR(EINVAL);
+@@ -1984,51 +2032,52 @@ static int radeon_surface_free(DRM_IOCTL
+ return 0;
+ }
+
+-static int radeon_cp_clear( DRM_IOCTL_ARGS )
++static int radeon_cp_clear(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_clear_t clear;
+ drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( clear, (drm_radeon_clear_t __user *)data,
+- sizeof(clear) );
++ DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data,
++ sizeof(clear));
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+- if ( DRM_COPY_FROM_USER( &depth_boxes, clear.depth_boxes,
+- sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
++ if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes,
++ sarea_priv->nbox * sizeof(depth_boxes[0])))
+ return DRM_ERR(EFAULT);
+
+- radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
++ radeon_cp_dispatch_clear(dev, &clear, depth_boxes);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-
+ /* Not sure why this isn't set all the time:
+- */
+-static int radeon_do_init_pageflip( drm_device_t *dev )
++ */
++static int radeon_do_init_pageflip(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- BEGIN_RING( 6 );
++ BEGIN_RING(6);
+ RADEON_WAIT_UNTIL_3D_IDLE();
+- OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) );
+- OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
+- OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) );
+- OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
++ OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
++ OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
++ RADEON_CRTC_OFFSET_FLIP_CNTL);
++ OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
++ OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
++ RADEON_CRTC_OFFSET_FLIP_CNTL);
+ ADVANCE_RING();
+
+ dev_priv->page_flipping = 1;
+@@ -2041,62 +2090,62 @@ static int radeon_do_init_pageflip( drm_
+ /* Called whenever a client dies, from drm_release.
+ * NOTE: Lock isn't necessarily held when this is called!
+ */
+-static int radeon_do_cleanup_pageflip( drm_device_t *dev )
++static int radeon_do_cleanup_pageflip(drm_device_t * dev)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+ if (dev_priv->current_page != 0)
+- radeon_cp_dispatch_flip( dev );
++ radeon_cp_dispatch_flip(dev);
+
+ dev_priv->page_flipping = 0;
+ return 0;
+ }
+
+ /* Swapping and flipping are different operations, need different ioctls.
+- * They can & should be intermixed to support multiple 3d windows.
++ * They can & should be intermixed to support multiple 3d windows.
+ */
+-static int radeon_cp_flip( DRM_IOCTL_ARGS )
++static int radeon_cp_flip(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- if (!dev_priv->page_flipping)
+- radeon_do_init_pageflip( dev );
+-
+- radeon_cp_dispatch_flip( dev );
++ if (!dev_priv->page_flipping)
++ radeon_do_init_pageflip(dev);
++
++ radeon_cp_dispatch_flip(dev);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int radeon_cp_swap( DRM_IOCTL_ARGS )
++static int radeon_cp_swap(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+- DRM_DEBUG( "\n" );
++ DRM_DEBUG("\n");
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
++ if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+- radeon_cp_dispatch_swap( dev );
++ radeon_cp_dispatch_swap(dev);
+ dev_priv->sarea_priv->ctx_owner = 0;
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int radeon_cp_vertex( DRM_IOCTL_ARGS )
++static int radeon_cp_vertex(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -2107,55 +2156,53 @@ static int radeon_cp_vertex( DRM_IOCTL_A
+ drm_radeon_vertex_t vertex;
+ drm_radeon_tcl_prim_t prim;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
++ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t __user *)data,
+- sizeof(vertex) );
++ DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
++ sizeof(vertex));
+
+- DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
+- DRM_CURRENTPID,
+- vertex.idx, vertex.count, vertex.discard );
++ DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
++ DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
+
+- if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- vertex.idx, dma->buf_count - 1 );
++ if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ vertex.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+- if ( vertex.prim < 0 ||
+- vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+- DRM_ERROR( "buffer prim %d\n", vertex.prim );
++ if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
++ DRM_ERROR("buffer prim %d\n", vertex.prim);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+ buf = dma->buflist[vertex.idx];
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", vertex.idx);
+ return DRM_ERR(EINVAL);
+ }
+
+ /* Build up a prim_t record:
+ */
+ if (vertex.count) {
+- buf->used = vertex.count; /* not used? */
++ buf->used = vertex.count; /* not used? */
+
+- if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+- if ( radeon_emit_state( dev_priv, filp_priv,
+- &sarea_priv->context_state,
+- sarea_priv->tex_state,
+- sarea_priv->dirty ) ) {
+- DRM_ERROR( "radeon_emit_state failed\n" );
+- return DRM_ERR( EINVAL );
++ if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
++ if (radeon_emit_state(dev_priv, filp_priv,
++ &sarea_priv->context_state,
++ sarea_priv->tex_state,
++ sarea_priv->dirty)) {
++ DRM_ERROR("radeon_emit_state failed\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+@@ -2165,23 +2212,23 @@ static int radeon_cp_vertex( DRM_IOCTL_A
+ }
+
+ prim.start = 0;
+- prim.finish = vertex.count; /* unused */
++ prim.finish = vertex.count; /* unused */
+ prim.prim = vertex.prim;
+ prim.numverts = vertex.count;
+ prim.vc_format = dev_priv->sarea_priv->vc_format;
+-
+- radeon_cp_dispatch_vertex( dev, buf, &prim );
++
++ radeon_cp_dispatch_vertex(dev, buf, &prim);
+ }
+
+ if (vertex.discard) {
+- radeon_cp_discard_buffer( dev, buf );
++ radeon_cp_discard_buffer(dev, buf);
+ }
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int radeon_cp_indices( DRM_IOCTL_ARGS )
++static int radeon_cp_indices(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -2193,69 +2240,67 @@ static int radeon_cp_indices( DRM_IOCTL_
+ drm_radeon_tcl_prim_t prim;
+ int count;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
++ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t __user *)data,
+- sizeof(elts) );
++ DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
++ sizeof(elts));
+
+- DRM_DEBUG( "pid=%d index=%d start=%d end=%d discard=%d\n",
+- DRM_CURRENTPID,
+- elts.idx, elts.start, elts.end, elts.discard );
++ DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
++ DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard);
+
+- if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- elts.idx, dma->buf_count - 1 );
++ if (elts.idx < 0 || elts.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ elts.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+- if ( elts.prim < 0 ||
+- elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+- DRM_ERROR( "buffer prim %d\n", elts.prim );
++ if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
++ DRM_ERROR("buffer prim %d\n", elts.prim);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+ buf = dma->buflist[elts.idx];
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", elts.idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", elts.idx);
+ return DRM_ERR(EINVAL);
+ }
+
+ count = (elts.end - elts.start) / sizeof(u16);
+ elts.start -= RADEON_INDEX_PRIM_OFFSET;
+
+- if ( elts.start & 0x7 ) {
+- DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
++ if (elts.start & 0x7) {
++ DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
+ return DRM_ERR(EINVAL);
+ }
+- if ( elts.start < buf->used ) {
+- DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
++ if (elts.start < buf->used) {
++ DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
+ return DRM_ERR(EINVAL);
+ }
+
+ buf->used = elts.end;
+
+- if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+- if ( radeon_emit_state( dev_priv, filp_priv,
+- &sarea_priv->context_state,
+- sarea_priv->tex_state,
+- sarea_priv->dirty ) ) {
+- DRM_ERROR( "radeon_emit_state failed\n" );
+- return DRM_ERR( EINVAL );
++ if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
++ if (radeon_emit_state(dev_priv, filp_priv,
++ &sarea_priv->context_state,
++ sarea_priv->tex_state,
++ sarea_priv->dirty)) {
++ DRM_ERROR("radeon_emit_state failed\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+@@ -2264,26 +2309,25 @@ static int radeon_cp_indices( DRM_IOCTL_
+ RADEON_REQUIRE_QUIESCENCE);
+ }
+
+-
+ /* Build up a prim_t record:
+ */
+ prim.start = elts.start;
+- prim.finish = elts.end;
++ prim.finish = elts.end;
+ prim.prim = elts.prim;
+ prim.offset = 0; /* offset from start of dma buffers */
+- prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
++ prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+ prim.vc_format = dev_priv->sarea_priv->vc_format;
+-
+- radeon_cp_dispatch_indices( dev, buf, &prim );
++
++ radeon_cp_dispatch_indices(dev, buf, &prim);
+ if (elts.discard) {
+- radeon_cp_discard_buffer( dev, buf );
++ radeon_cp_discard_buffer(dev, buf);
+ }
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int radeon_cp_texture( DRM_IOCTL_ARGS )
++static int radeon_cp_texture(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -2291,53 +2335,54 @@ static int radeon_cp_texture( DRM_IOCTL_
+ drm_radeon_tex_image_t image;
+ int ret;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( tex, (drm_radeon_texture_t __user *)data, sizeof(tex) );
++ DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data,
++ sizeof(tex));
+
+- if ( tex.image == NULL ) {
+- DRM_ERROR( "null texture image!\n" );
++ if (tex.image == NULL) {
++ DRM_ERROR("null texture image!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( DRM_COPY_FROM_USER( &image,
+- (drm_radeon_tex_image_t __user *)tex.image,
+- sizeof(image) ) )
++ if (DRM_COPY_FROM_USER(&image,
++ (drm_radeon_tex_image_t __user *) tex.image,
++ sizeof(image)))
+ return DRM_ERR(EFAULT);
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+- ret = radeon_cp_dispatch_texture( filp, dev, &tex, &image );
++ ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image);
+
+ COMMIT_RING();
+ return ret;
+ }
+
+-static int radeon_cp_stipple( DRM_IOCTL_ARGS )
++static int radeon_cp_stipple(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_stipple_t stipple;
+ u32 mask[32];
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( stipple, (drm_radeon_stipple_t __user *)data,
+- sizeof(stipple) );
++ DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data,
++ sizeof(stipple));
+
+- if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) )
++ if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
+ return DRM_ERR(EFAULT);
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+- radeon_cp_dispatch_stipple( dev, mask );
++ radeon_cp_dispatch_stipple(dev, mask);
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int radeon_cp_indirect( DRM_IOCTL_ARGS )
++static int radeon_cp_indirect(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -2346,53 +2391,53 @@ static int radeon_cp_indirect( DRM_IOCTL
+ drm_radeon_indirect_t indirect;
+ RING_LOCALS;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( indirect, (drm_radeon_indirect_t __user *)data,
+- sizeof(indirect) );
++ DRM_COPY_FROM_USER_IOCTL(indirect,
++ (drm_radeon_indirect_t __user *) data,
++ sizeof(indirect));
+
+- DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+- indirect.idx, indirect.start,
+- indirect.end, indirect.discard );
++ DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
++ indirect.idx, indirect.start, indirect.end, indirect.discard);
+
+- if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- indirect.idx, dma->buf_count - 1 );
++ if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ indirect.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+ buf = dma->buflist[indirect.idx];
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", indirect.idx);
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( indirect.start < buf->used ) {
+- DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+- indirect.start, buf->used );
++ if (indirect.start < buf->used) {
++ DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
++ indirect.start, buf->used);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+ buf->used = indirect.end;
+
+ /* Wait for the 3D stream to idle before the indirect buffer
+ * containing 2D acceleration commands is processed.
+ */
+- BEGIN_RING( 2 );
++ BEGIN_RING(2);
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+@@ -2402,17 +2447,16 @@ static int radeon_cp_indirect( DRM_IOCTL
+ * X server. This is insecure and is thus only available to
+ * privileged clients.
+ */
+- radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
++ radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end);
+ if (indirect.discard) {
+- radeon_cp_discard_buffer( dev, buf );
++ radeon_cp_discard_buffer(dev, buf);
+ }
+
+-
+ COMMIT_RING();
+ return 0;
+ }
+
+-static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
++static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -2424,65 +2468,64 @@ static int radeon_cp_vertex2( DRM_IOCTL_
+ int i;
+ unsigned char laststate;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
++ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t __user *)data,
+- sizeof(vertex) );
++ DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
++ sizeof(vertex));
+
+- DRM_DEBUG( "pid=%d index=%d discard=%d\n",
+- DRM_CURRENTPID,
+- vertex.idx, vertex.discard );
++ DRM_DEBUG("pid=%d index=%d discard=%d\n",
++ DRM_CURRENTPID, vertex.idx, vertex.discard);
+
+- if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- vertex.idx, dma->buf_count - 1 );
++ if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ vertex.idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+ buf = dma->buflist[vertex.idx];
+
+- if ( buf->filp != filp ) {
+- DRM_ERROR( "process %d using buffer owned by %p\n",
+- DRM_CURRENTPID, buf->filp );
++ if (buf->filp != filp) {
++ DRM_ERROR("process %d using buffer owned by %p\n",
++ DRM_CURRENTPID, buf->filp);
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( buf->pending ) {
+- DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
++ if (buf->pending) {
++ DRM_ERROR("sending pending buffer %d\n", vertex.idx);
+ return DRM_ERR(EINVAL);
+ }
+-
++
+ if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+ return DRM_ERR(EINVAL);
+
+- for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
++ for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) {
+ drm_radeon_prim_t prim;
+ drm_radeon_tcl_prim_t tclprim;
+-
+- if ( DRM_COPY_FROM_USER( &prim, &vertex.prim[i], sizeof(prim) ) )
++
++ if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim)))
+ return DRM_ERR(EFAULT);
+-
+- if ( prim.stateidx != laststate ) {
+- drm_radeon_state_t state;
+-
+- if ( DRM_COPY_FROM_USER( &state,
+- &vertex.state[prim.stateidx],
+- sizeof(state) ) )
++
++ if (prim.stateidx != laststate) {
++ drm_radeon_state_t state;
++
++ if (DRM_COPY_FROM_USER(&state,
++ &vertex.state[prim.stateidx],
++ sizeof(state)))
+ return DRM_ERR(EFAULT);
+
+- if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
+- DRM_ERROR( "radeon_emit_state2 failed\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_emit_state2(dev_priv, filp_priv, &state)) {
++ DRM_ERROR("radeon_emit_state2 failed\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ laststate = prim.stateidx;
+@@ -2493,42 +2536,40 @@ static int radeon_cp_vertex2( DRM_IOCTL_
+ tclprim.prim = prim.prim;
+ tclprim.vc_format = prim.vc_format;
+
+- if ( prim.prim & RADEON_PRIM_WALK_IND ) {
++ if (prim.prim & RADEON_PRIM_WALK_IND) {
+ tclprim.offset = prim.numverts * 64;
+- tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
++ tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+
+- radeon_cp_dispatch_indices( dev, buf, &tclprim );
++ radeon_cp_dispatch_indices(dev, buf, &tclprim);
+ } else {
+ tclprim.numverts = prim.numverts;
+- tclprim.offset = 0; /* not used */
++ tclprim.offset = 0; /* not used */
+
+- radeon_cp_dispatch_vertex( dev, buf, &tclprim );
++ radeon_cp_dispatch_vertex(dev, buf, &tclprim);
+ }
+-
++
+ if (sarea_priv->nbox == 1)
+ sarea_priv->nbox = 0;
+ }
+
+- if ( vertex.discard ) {
+- radeon_cp_discard_buffer( dev, buf );
++ if (vertex.discard) {
++ radeon_cp_discard_buffer(dev, buf);
+ }
+
+ COMMIT_RING();
+ return 0;
+ }
+
+-
+-static int radeon_emit_packets(
+- drm_radeon_private_t *dev_priv,
+- drm_file_t *filp_priv,
+- drm_radeon_cmd_header_t header,
+- drm_radeon_cmd_buffer_t *cmdbuf )
++static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
++ drm_file_t * filp_priv,
++ drm_radeon_cmd_header_t header,
++ drm_radeon_kcmd_buffer_t *cmdbuf)
+ {
+ int id = (int)header.packet.packet_id;
+ int sz, reg;
+ int *data = (int *)cmdbuf->buf;
+ RING_LOCALS;
+-
++
+ if (id >= RADEON_MAX_STATE_PACKETS)
+ return DRM_ERR(EINVAL);
+
+@@ -2536,18 +2577,18 @@ static int radeon_emit_packets(
+ reg = packet[id].start;
+
+ if (sz * sizeof(int) > cmdbuf->bufsz) {
+- DRM_ERROR( "Packet size provided larger than data provided\n" );
++ DRM_ERROR("Packet size provided larger than data provided\n");
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
+- DRM_ERROR( "Packet verification failed\n" );
+- return DRM_ERR( EINVAL );
++ if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) {
++ DRM_ERROR("Packet verification failed\n");
++ return DRM_ERR(EINVAL);
+ }
+
+- BEGIN_RING(sz+1);
+- OUT_RING( CP_PACKET0( reg, (sz-1) ) );
+- OUT_RING_TABLE( data, sz );
++ BEGIN_RING(sz + 1);
++ OUT_RING(CP_PACKET0(reg, (sz - 1)));
++ OUT_RING_TABLE(data, sz);
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz * sizeof(int);
+@@ -2555,21 +2596,20 @@ static int radeon_emit_packets(
+ return 0;
+ }
+
+-static __inline__ int radeon_emit_scalars(
+- drm_radeon_private_t *dev_priv,
+- drm_radeon_cmd_header_t header,
+- drm_radeon_cmd_buffer_t *cmdbuf )
++static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
++ drm_radeon_cmd_header_t header,
++ drm_radeon_kcmd_buffer_t * cmdbuf)
+ {
+ int sz = header.scalars.count;
+ int start = header.scalars.offset;
+ int stride = header.scalars.stride;
+ RING_LOCALS;
+
+- BEGIN_RING( 3+sz );
+- OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
+- OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+- OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
+- OUT_RING_TABLE( cmdbuf->buf, sz );
++ BEGIN_RING(3 + sz);
++ OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
++ OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
++ OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
++ OUT_RING_TABLE(cmdbuf->buf, sz);
+ ADVANCE_RING();
+ cmdbuf->buf += sz * sizeof(int);
+ cmdbuf->bufsz -= sz * sizeof(int);
+@@ -2578,42 +2618,40 @@ static __inline__ int radeon_emit_scalar
+
+ /* God this is ugly
+ */
+-static __inline__ int radeon_emit_scalars2(
+- drm_radeon_private_t *dev_priv,
+- drm_radeon_cmd_header_t header,
+- drm_radeon_cmd_buffer_t *cmdbuf )
++static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
++ drm_radeon_cmd_header_t header,
++ drm_radeon_kcmd_buffer_t * cmdbuf)
+ {
+ int sz = header.scalars.count;
+ int start = ((unsigned int)header.scalars.offset) + 0x100;
+ int stride = header.scalars.stride;
+ RING_LOCALS;
+
+- BEGIN_RING( 3+sz );
+- OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
+- OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+- OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
+- OUT_RING_TABLE( cmdbuf->buf, sz );
++ BEGIN_RING(3 + sz);
++ OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
++ OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
++ OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
++ OUT_RING_TABLE(cmdbuf->buf, sz);
+ ADVANCE_RING();
+ cmdbuf->buf += sz * sizeof(int);
+ cmdbuf->bufsz -= sz * sizeof(int);
+ return 0;
+ }
+
+-static __inline__ int radeon_emit_vectors(
+- drm_radeon_private_t *dev_priv,
+- drm_radeon_cmd_header_t header,
+- drm_radeon_cmd_buffer_t *cmdbuf )
++static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
++ drm_radeon_cmd_header_t header,
++ drm_radeon_kcmd_buffer_t * cmdbuf)
+ {
+ int sz = header.vectors.count;
+ int start = header.vectors.offset;
+ int stride = header.vectors.stride;
+ RING_LOCALS;
+
+- BEGIN_RING( 3+sz );
+- OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
+- OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+- OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
+- OUT_RING_TABLE( cmdbuf->buf, sz );
++ BEGIN_RING(3 + sz);
++ OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
++ OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
++ OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
++ OUT_RING_TABLE(cmdbuf->buf, sz);
+ ADVANCE_RING();
+
+ cmdbuf->buf += sz * sizeof(int);
+@@ -2621,10 +2659,9 @@ static __inline__ int radeon_emit_vector
+ return 0;
+ }
+
+-
+-static int radeon_emit_packet3( drm_device_t *dev,
+- drm_file_t *filp_priv,
+- drm_radeon_cmd_buffer_t *cmdbuf )
++static int radeon_emit_packet3(drm_device_t * dev,
++ drm_file_t * filp_priv,
++ drm_radeon_kcmd_buffer_t *cmdbuf)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ unsigned int cmdsz;
+@@ -2633,14 +2670,14 @@ static int radeon_emit_packet3( drm_devi
+
+ DRM_DEBUG("\n");
+
+- if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+- cmdbuf, &cmdsz ) ) ) {
+- DRM_ERROR( "Packet verification failed\n" );
++ if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
++ cmdbuf, &cmdsz))) {
++ DRM_ERROR("Packet verification failed\n");
+ return ret;
+ }
+
+- BEGIN_RING( cmdsz );
+- OUT_RING_TABLE( cmdbuf->buf, cmdsz );
++ BEGIN_RING(cmdsz);
++ OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+ ADVANCE_RING();
+
+ cmdbuf->buf += cmdsz * 4;
+@@ -2648,11 +2685,10 @@ static int radeon_emit_packet3( drm_devi
+ return 0;
+ }
+
+-
+-static int radeon_emit_packet3_cliprect( drm_device_t *dev,
+- drm_file_t *filp_priv,
+- drm_radeon_cmd_buffer_t *cmdbuf,
+- int orig_nbox )
++static int radeon_emit_packet3_cliprect(drm_device_t * dev,
++ drm_file_t * filp_priv,
++ drm_radeon_kcmd_buffer_t *cmdbuf,
++ int orig_nbox)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_clip_rect_t box;
+@@ -2664,9 +2700,9 @@ static int radeon_emit_packet3_cliprect(
+
+ DRM_DEBUG("\n");
+
+- if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+- cmdbuf, &cmdsz ) ) ) {
+- DRM_ERROR( "Packet verification failed\n" );
++ if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
++ cmdbuf, &cmdsz))) {
++ DRM_ERROR("Packet verification failed\n");
+ return ret;
+ }
+
+@@ -2674,8 +2710,8 @@ static int radeon_emit_packet3_cliprect(
+ goto out;
+
+ do {
+- if ( i < cmdbuf->nbox ) {
+- if (DRM_COPY_FROM_USER( &box, &boxes[i], sizeof(box) ))
++ if (i < cmdbuf->nbox) {
++ if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
+ return DRM_ERR(EFAULT);
+ /* FIXME The second and subsequent times round
+ * this loop, send a WAIT_UNTIL_3D_IDLE before
+@@ -2689,30 +2725,29 @@ static int radeon_emit_packet3_cliprect(
+ * the correct place to fix it but this works
+ * around it until I can figure that out - Tim
+ * Smith */
+- if ( i ) {
+- BEGIN_RING( 2 );
++ if (i) {
++ BEGIN_RING(2);
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ }
+- radeon_emit_clip_rect( dev_priv, &box );
++ radeon_emit_clip_rect(dev_priv, &box);
+ }
+-
+- BEGIN_RING( cmdsz );
+- OUT_RING_TABLE( cmdbuf->buf, cmdsz );
++
++ BEGIN_RING(cmdsz);
++ OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+ ADVANCE_RING();
+
+- } while ( ++i < cmdbuf->nbox );
+- if (cmdbuf->nbox == 1)
++ } while (++i < cmdbuf->nbox);
++ if (cmdbuf->nbox == 1)
+ cmdbuf->nbox = 0;
+
+- out:
++ out:
+ cmdbuf->buf += cmdsz * 4;
+ cmdbuf->bufsz -= cmdsz * 4;
+ return 0;
+ }
+
+-
+-static int radeon_emit_wait( drm_device_t *dev, int flags )
++static int radeon_emit_wait(drm_device_t * dev, int flags)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+@@ -2720,18 +2755,18 @@ static int radeon_emit_wait( drm_device_
+ DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
+ switch (flags) {
+ case RADEON_WAIT_2D:
+- BEGIN_RING( 2 );
+- RADEON_WAIT_UNTIL_2D_IDLE();
++ BEGIN_RING(2);
++ RADEON_WAIT_UNTIL_2D_IDLE();
+ ADVANCE_RING();
+ break;
+ case RADEON_WAIT_3D:
+- BEGIN_RING( 2 );
+- RADEON_WAIT_UNTIL_3D_IDLE();
++ BEGIN_RING(2);
++ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+ break;
+- case RADEON_WAIT_2D|RADEON_WAIT_3D:
+- BEGIN_RING( 2 );
+- RADEON_WAIT_UNTIL_IDLE();
++ case RADEON_WAIT_2D | RADEON_WAIT_3D:
++ BEGIN_RING(2);
++ RADEON_WAIT_UNTIL_IDLE();
+ ADVANCE_RING();
+ break;
+ default:
+@@ -2741,7 +2776,7 @@ static int radeon_emit_wait( drm_device_
+ return 0;
+ }
+
+-static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
++static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+@@ -2749,27 +2784,28 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf = NULL;
+ int idx;
+- drm_radeon_cmd_buffer_t cmdbuf;
++ drm_radeon_kcmd_buffer_t cmdbuf;
+ drm_radeon_cmd_header_t header;
+ int orig_nbox, orig_bufsz;
+- char *kbuf=NULL;
++ char *kbuf = NULL;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
++ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t __user *)data,
+- sizeof(cmdbuf) );
++ DRM_COPY_FROM_USER_IOCTL(cmdbuf,
++ (drm_radeon_cmd_buffer_t __user *) data,
++ sizeof(cmdbuf));
+
+- RING_SPACE_TEST_WITH_RETURN( dev_priv );
+- VB_AGE_TEST_WITH_RETURN( dev_priv );
++ RING_SPACE_TEST_WITH_RETURN(dev_priv);
++ VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+- if (cmdbuf.bufsz > 64*1024 || cmdbuf.bufsz<0) {
++ if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) {
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -2782,7 +2818,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+ kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
+ if (kbuf == NULL)
+ return DRM_ERR(ENOMEM);
+- if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) {
++ if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, cmdbuf.bufsz)) {
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+ return DRM_ERR(EFAULT);
+ }
+@@ -2791,27 +2827,28 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+
+ orig_nbox = cmdbuf.nbox;
+
+- if(dev_priv->microcode_version == UCODE_R300) {
++ if (dev_priv->microcode_version == UCODE_R300) {
+ int temp;
+- temp=r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
+-
++ temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
++
+ if (orig_bufsz != 0)
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+-
++
+ return temp;
+ }
+
+ /* microcode_version != r300 */
+- while ( cmdbuf.bufsz >= sizeof(header) ) {
++ while (cmdbuf.bufsz >= sizeof(header)) {
+
+ header.i = *(int *)cmdbuf.buf;
+ cmdbuf.buf += sizeof(header);
+ cmdbuf.bufsz -= sizeof(header);
+
+ switch (header.header.cmd_type) {
+- case RADEON_CMD_PACKET:
++ case RADEON_CMD_PACKET:
+ DRM_DEBUG("RADEON_CMD_PACKET\n");
+- if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
++ if (radeon_emit_packets
++ (dev_priv, filp_priv, header, &cmdbuf)) {
+ DRM_ERROR("radeon_emit_packets failed\n");
+ goto err;
+ }
+@@ -2819,7 +2856,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+
+ case RADEON_CMD_SCALARS:
+ DRM_DEBUG("RADEON_CMD_SCALARS\n");
+- if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
++ if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) {
+ DRM_ERROR("radeon_emit_scalars failed\n");
+ goto err;
+ }
+@@ -2827,7 +2864,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+
+ case RADEON_CMD_VECTORS:
+ DRM_DEBUG("RADEON_CMD_VECTORS\n");
+- if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
++ if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) {
+ DRM_ERROR("radeon_emit_vectors failed\n");
+ goto err;
+ }
+@@ -2836,25 +2873,25 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+ case RADEON_CMD_DMA_DISCARD:
+ DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+ idx = header.dma.buf_idx;
+- if ( idx < 0 || idx >= dma->buf_count ) {
+- DRM_ERROR( "buffer index %d (of %d max)\n",
+- idx, dma->buf_count - 1 );
++ if (idx < 0 || idx >= dma->buf_count) {
++ DRM_ERROR("buffer index %d (of %d max)\n",
++ idx, dma->buf_count - 1);
+ goto err;
+ }
+
+ buf = dma->buflist[idx];
+- if ( buf->filp != filp || buf->pending ) {
+- DRM_ERROR( "bad buffer %p %p %d\n",
+- buf->filp, filp, buf->pending);
++ if (buf->filp != filp || buf->pending) {
++ DRM_ERROR("bad buffer %p %p %d\n",
++ buf->filp, filp, buf->pending);
+ goto err;
+ }
+
+- radeon_cp_discard_buffer( dev, buf );
++ radeon_cp_discard_buffer(dev, buf);
+ break;
+
+ case RADEON_CMD_PACKET3:
+ DRM_DEBUG("RADEON_CMD_PACKET3\n");
+- if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
++ if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) {
+ DRM_ERROR("radeon_emit_packet3 failed\n");
+ goto err;
+ }
+@@ -2862,7 +2899,8 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+
+ case RADEON_CMD_PACKET3_CLIP:
+ DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
+- if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
++ if (radeon_emit_packet3_cliprect
++ (dev, filp_priv, &cmdbuf, orig_nbox)) {
+ DRM_ERROR("radeon_emit_packet3_clip failed\n");
+ goto err;
+ }
+@@ -2870,7 +2908,7 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+
+ case RADEON_CMD_SCALARS2:
+ DRM_DEBUG("RADEON_CMD_SCALARS2\n");
+- if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) {
++ if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) {
+ DRM_ERROR("radeon_emit_scalars2 failed\n");
+ goto err;
+ }
+@@ -2878,13 +2916,13 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+
+ case RADEON_CMD_WAIT:
+ DRM_DEBUG("RADEON_CMD_WAIT\n");
+- if (radeon_emit_wait( dev, header.wait.flags )) {
++ if (radeon_emit_wait(dev, header.wait.flags)) {
+ DRM_ERROR("radeon_emit_wait failed\n");
+ goto err;
+ }
+ break;
+ default:
+- DRM_ERROR("bad cmd_type %d at %p\n",
++ DRM_ERROR("bad cmd_type %d at %p\n",
+ header.header.cmd_type,
+ cmdbuf.buf - sizeof(header));
+ goto err;
+@@ -2898,45 +2936,43 @@ static int radeon_cp_cmdbuf( DRM_IOCTL_A
+ COMMIT_RING();
+ return 0;
+
+-err:
++ err:
+ if (orig_bufsz != 0)
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+ return DRM_ERR(EINVAL);
+ }
+
+-
+-
+-static int radeon_cp_getparam( DRM_IOCTL_ARGS )
++static int radeon_cp_getparam(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_getparam_t param;
+ int value;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+- DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t __user *)data,
+- sizeof(param) );
++ DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
++ sizeof(param));
+
+- DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
++ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+- switch( param.param ) {
++ switch (param.param) {
+ case RADEON_PARAM_GART_BUFFER_OFFSET:
+ value = dev_priv->gart_buffers_offset;
+ break;
+ case RADEON_PARAM_LAST_FRAME:
+ dev_priv->stats.last_frame_reads++;
+- value = GET_SCRATCH( 0 );
++ value = GET_SCRATCH(0);
+ break;
+ case RADEON_PARAM_LAST_DISPATCH:
+- value = GET_SCRATCH( 1 );
++ value = GET_SCRATCH(1);
+ break;
+ case RADEON_PARAM_LAST_CLEAR:
+ dev_priv->stats.last_clear_reads++;
+- value = GET_SCRATCH( 2 );
++ value = GET_SCRATCH(2);
+ break;
+ case RADEON_PARAM_IRQ_NR:
+ value = dev->irq;
+@@ -2951,15 +2987,15 @@ static int radeon_cp_getparam( DRM_IOCTL
+ value = dev_priv->ring_rptr_offset;
+ break;
+ #if BITS_PER_LONG == 32
+- /*
+- * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
+- * pointer which can't fit into an int-sized variable. According to
+- * Michel Dänzer, the ioctl() is only used on embedded platforms, so
+- * not supporting it shouldn't be a problem. If the same functionality
+- * is needed on 64-bit platforms, a new ioctl() would have to be added,
+- * so backwards-compatibility for the embedded platforms can be
+- * maintained. --davidm 4-Feb-2004.
+- */
++ /*
++ * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
++ * pointer which can't fit into an int-sized variable. According to
++ * Michel Dänzer, the ioctl() is only used on embedded platforms, so
++ * not supporting it shouldn't be a problem. If the same functionality
++ * is needed on 64-bit platforms, a new ioctl() would have to be added,
++ * so backwards-compatibility for the embedded platforms can be
++ * maintained. --davidm 4-Feb-2004.
++ */
+ case RADEON_PARAM_SAREA_HANDLE:
+ /* The lock is the first dword in the sarea. */
+ value = (long)dev->lock.hw_lock;
+@@ -2972,53 +3008,56 @@ static int radeon_cp_getparam( DRM_IOCTL
+ return DRM_ERR(EINVAL);
+ }
+
+- if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+- DRM_ERROR( "copy_to_user\n" );
++ if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
++ DRM_ERROR("copy_to_user\n");
+ return DRM_ERR(EFAULT);
+ }
+-
++
+ return 0;
+ }
+
+-static int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
++static int radeon_cp_setparam(DRM_IOCTL_ARGS)
++{
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
+ drm_radeon_setparam_t sp;
+ struct drm_radeon_driver_file_fields *radeon_priv;
+
+- if ( !dev_priv ) {
+- DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+- return DRM_ERR( EINVAL );
++ if (!dev_priv) {
++ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
++ return DRM_ERR(EINVAL);
+ }
+
+- DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
++ DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+- DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t __user * )data,
+- sizeof( sp ) );
++ DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
++ sizeof(sp));
+
+- switch( sp.param ) {
++ switch (sp.param) {
+ case RADEON_SETPARAM_FB_LOCATION:
+ radeon_priv = filp_priv->driver_priv;
+ radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+ break;
+ case RADEON_SETPARAM_SWITCH_TILING:
+ if (sp.value == 0) {
+- DRM_DEBUG( "color tiling disabled\n" );
++ DRM_DEBUG("color tiling disabled\n");
+ dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
+ dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
+ dev_priv->sarea_priv->tiling_enabled = 0;
+- }
+- else if (sp.value == 1) {
+- DRM_DEBUG( "color tiling enabled\n" );
++ } else if (sp.value == 1) {
++ DRM_DEBUG("color tiling enabled\n");
+ dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
+ dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
+ dev_priv->sarea_priv->tiling_enabled = 1;
+ }
+- break;
++ break;
++ case RADEON_SETPARAM_PCIGART_LOCATION:
++ dev_priv->pcigart_offset = sp.value;
++ break;
+ default:
+- DRM_DEBUG( "Invalid parameter %d\n", sp.param );
+- return DRM_ERR( EINVAL );
++ DRM_DEBUG("Invalid parameter %d\n", sp.param);
++ return DRM_ERR(EINVAL);
+ }
+
+ return 0;
+@@ -3030,78 +3069,80 @@ static int radeon_cp_setparam( DRM_IOCTL
+ *
+ * DRM infrastructure takes care of reclaiming dma buffers.
+ */
+-void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp)
++void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+ {
+- if ( dev->dev_private ) {
+- drm_radeon_private_t *dev_priv = dev->dev_private;
+- if ( dev_priv->page_flipping ) {
+- radeon_do_cleanup_pageflip( dev );
+- }
+- radeon_mem_release( filp, dev_priv->gart_heap );
+- radeon_mem_release( filp, dev_priv->fb_heap );
++ if (dev->dev_private) {
++ drm_radeon_private_t *dev_priv = dev->dev_private;
++ if (dev_priv->page_flipping) {
++ radeon_do_cleanup_pageflip(dev);
++ }
++ radeon_mem_release(filp, dev_priv->gart_heap);
++ radeon_mem_release(filp, dev_priv->fb_heap);
+ radeon_surfaces_release(filp, dev_priv);
+- }
++ }
+ }
+
+-void radeon_driver_pretakedown(drm_device_t *dev)
++void radeon_driver_pretakedown(drm_device_t * dev)
+ {
+ radeon_do_release(dev);
+ }
+
+-int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv)
++int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ struct drm_radeon_driver_file_fields *radeon_priv;
+-
+- radeon_priv = (struct drm_radeon_driver_file_fields *)drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
+-
++
++ radeon_priv =
++ (struct drm_radeon_driver_file_fields *)
++ drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
++
+ if (!radeon_priv)
+ return -ENOMEM;
+
+ filp_priv->driver_priv = radeon_priv;
+- if ( dev_priv )
++ if (dev_priv)
+ radeon_priv->radeon_fb_delta = dev_priv->fb_location;
+ else
+ radeon_priv->radeon_fb_delta = 0;
+ return 0;
+ }
+
+-
+-void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv)
++void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
+ {
+- struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv;
+-
+- drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
++ struct drm_radeon_driver_file_fields *radeon_priv =
++ filp_priv->driver_priv;
++
++ drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+ }
+
+ drm_ioctl_desc_t radeon_ioctls[] = {
+- [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 },
+- [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = { radeon_cp_start, 1, 1 },
+- [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 },
+- [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 },
+- [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 },
+- [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_FREE)] = { radeon_mem_free, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = { radeon_mem_init_heap,1, 1 },
+- [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },
+- [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = { radeon_surface_free, 1, 0 }
++ [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1},
++ [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1},
++ [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1},
++ [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1},
++ [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1},
++ [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1},
++ [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0},
++ [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0}
+ };
+
+ int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
+diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
+--- a/drivers/char/drm/savage_bci.c
++++ b/drivers/char/drm/savage_bci.c
+@@ -28,12 +28,12 @@
+
+ /* Need a long timeout for shadow status updates can take a while
+ * and so can waiting for events when the queue is full. */
+-#define SAVAGE_DEFAULT_USEC_TIMEOUT 1000000 /* 1s */
+-#define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */
++#define SAVAGE_DEFAULT_USEC_TIMEOUT 1000000 /* 1s */
++#define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */
+ #define SAVAGE_FREELIST_DEBUG 0
+
+ static int
+-savage_bci_wait_fifo_shadow(drm_savage_private_t *dev_priv, unsigned int n)
++savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
+ {
+ uint32_t mask = dev_priv->status_used_mask;
+ uint32_t threshold = dev_priv->bci_threshold_hi;
+@@ -62,7 +62,7 @@ savage_bci_wait_fifo_shadow(drm_savage_p
+ }
+
+ static int
+-savage_bci_wait_fifo_s3d(drm_savage_private_t *dev_priv, unsigned int n)
++savage_bci_wait_fifo_s3d(drm_savage_private_t * dev_priv, unsigned int n)
+ {
+ uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+ uint32_t status;
+@@ -83,7 +83,7 @@ savage_bci_wait_fifo_s3d(drm_savage_priv
+ }
+
+ static int
+-savage_bci_wait_fifo_s4(drm_savage_private_t *dev_priv, unsigned int n)
++savage_bci_wait_fifo_s4(drm_savage_private_t * dev_priv, unsigned int n)
+ {
+ uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+ uint32_t status;
+@@ -115,7 +115,7 @@ savage_bci_wait_fifo_s4(drm_savage_priva
+ * rule. Otherwise there may be glitches every 2^16 events.
+ */
+ static int
+-savage_bci_wait_event_shadow(drm_savage_private_t *dev_priv, uint16_t e)
++savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e)
+ {
+ uint32_t status;
+ int i;
+@@ -138,7 +138,7 @@ savage_bci_wait_event_shadow(drm_savage_
+ }
+
+ static int
+-savage_bci_wait_event_reg(drm_savage_private_t *dev_priv, uint16_t e)
++savage_bci_wait_event_reg(drm_savage_private_t * dev_priv, uint16_t e)
+ {
+ uint32_t status;
+ int i;
+@@ -159,7 +159,7 @@ savage_bci_wait_event_reg(drm_savage_pri
+ return DRM_ERR(EBUSY);
+ }
+
+-uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
++uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
+ unsigned int flags)
+ {
+ uint16_t count;
+@@ -175,12 +175,12 @@ uint16_t savage_bci_emit_event(drm_savag
+ }
+ count = (count + 1) & 0xffff;
+ if (count == 0) {
+- count++; /* See the comment above savage_wait_event_*. */
++ count++; /* See the comment above savage_wait_event_*. */
+ dev_priv->event_wrap++;
+ }
+ dev_priv->event_counter = count;
+ if (dev_priv->status_ptr)
+- dev_priv->status_ptr[1023] = (uint32_t)count;
++ dev_priv->status_ptr[1023] = (uint32_t) count;
+
+ if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) {
+ unsigned int wait_cmd = BCI_CMD_WAIT;
+@@ -193,7 +193,7 @@ uint16_t savage_bci_emit_event(drm_savag
+ } else {
+ BEGIN_BCI(1);
+ }
+- BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t)count);
++ BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t) count);
+
+ return count;
+ }
+@@ -201,7 +201,7 @@ uint16_t savage_bci_emit_event(drm_savag
+ /*
+ * Freelist management
+ */
+-static int savage_freelist_init(drm_device_t *dev)
++static int savage_freelist_init(drm_device_t * dev)
+ {
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+@@ -234,7 +234,7 @@ static int savage_freelist_init(drm_devi
+ return 0;
+ }
+
+-static drm_buf_t *savage_freelist_get(drm_device_t *dev)
++static drm_buf_t *savage_freelist_get(drm_device_t * dev)
+ {
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
+@@ -249,7 +249,7 @@ static drm_buf_t *savage_freelist_get(dr
+ event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ wrap = dev_priv->event_wrap;
+ if (event > dev_priv->event_counter)
+- wrap--; /* hardware hasn't passed the last wrap yet */
++ wrap--; /* hardware hasn't passed the last wrap yet */
+
+ DRM_DEBUG(" tail=0x%04x %d\n", tail->age.event, tail->age.wrap);
+ DRM_DEBUG(" head=0x%04x %d\n", event, wrap);
+@@ -267,7 +267,7 @@ static drm_buf_t *savage_freelist_get(dr
+ return NULL;
+ }
+
+-void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf)
++void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+ {
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
+@@ -290,15 +290,14 @@ void savage_freelist_put(drm_device_t *d
+ /*
+ * Command DMA
+ */
+-static int savage_dma_init(drm_savage_private_t *dev_priv)
++static int savage_dma_init(drm_savage_private_t * dev_priv)
+ {
+ unsigned int i;
+
+ dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
+- (SAVAGE_DMA_PAGE_SIZE*4);
++ (SAVAGE_DMA_PAGE_SIZE * 4);
+ dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
+- dev_priv->nr_dma_pages,
+- DRM_MEM_DRIVER);
++ dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
+ if (dev_priv->dma_pages == NULL)
+ return DRM_ERR(ENOMEM);
+
+@@ -315,7 +314,7 @@ static int savage_dma_init(drm_savage_pr
+ return 0;
+ }
+
+-void savage_dma_reset(drm_savage_private_t *dev_priv)
++void savage_dma_reset(drm_savage_private_t * dev_priv)
+ {
+ uint16_t event;
+ unsigned int wrap, i;
+@@ -330,7 +329,7 @@ void savage_dma_reset(drm_savage_private
+ dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+ }
+
+-void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page)
++void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page)
+ {
+ uint16_t event;
+ unsigned int wrap;
+@@ -346,7 +345,7 @@ void savage_dma_wait(drm_savage_private_
+ event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ wrap = dev_priv->event_wrap;
+ if (event > dev_priv->event_counter)
+- wrap--; /* hardware hasn't passed the last wrap yet */
++ wrap--; /* hardware hasn't passed the last wrap yet */
+
+ if (dev_priv->dma_pages[page].age.wrap > wrap ||
+ (dev_priv->dma_pages[page].age.wrap == wrap &&
+@@ -358,13 +357,13 @@ void savage_dma_wait(drm_savage_private_
+ }
+ }
+
+-uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv, unsigned int n)
++uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, unsigned int n)
+ {
+ unsigned int cur = dev_priv->current_dma_page;
+ unsigned int rest = SAVAGE_DMA_PAGE_SIZE -
+- dev_priv->dma_pages[cur].used;
+- unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE-1) /
+- SAVAGE_DMA_PAGE_SIZE;
++ dev_priv->dma_pages[cur].used;
++ unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE - 1) /
++ SAVAGE_DMA_PAGE_SIZE;
+ uint32_t *dma_ptr;
+ unsigned int i;
+
+@@ -372,9 +371,8 @@ uint32_t *savage_dma_alloc(drm_savage_pr
+ cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages);
+
+ if (cur + nr_pages < dev_priv->nr_dma_pages) {
+- dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+- cur*SAVAGE_DMA_PAGE_SIZE +
+- dev_priv->dma_pages[cur].used;
++ dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
++ cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+ if (n < rest)
+ rest = n;
+ dev_priv->dma_pages[cur].used += rest;
+@@ -382,13 +380,14 @@ uint32_t *savage_dma_alloc(drm_savage_pr
+ cur++;
+ } else {
+ dev_priv->dma_flush(dev_priv);
+- nr_pages = (n + SAVAGE_DMA_PAGE_SIZE-1) / SAVAGE_DMA_PAGE_SIZE;
++ nr_pages =
++ (n + SAVAGE_DMA_PAGE_SIZE - 1) / SAVAGE_DMA_PAGE_SIZE;
+ for (i = cur; i < dev_priv->nr_dma_pages; ++i) {
+ dev_priv->dma_pages[i].age = dev_priv->last_dma_age;
+ dev_priv->dma_pages[i].used = 0;
+ dev_priv->dma_pages[i].flushed = 0;
+ }
+- dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle;
++ dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle;
+ dev_priv->first_dma_page = cur = 0;
+ }
+ for (i = cur; nr_pages > 0; ++i, --nr_pages) {
+@@ -414,7 +413,7 @@ uint32_t *savage_dma_alloc(drm_savage_pr
+ return dma_ptr;
+ }
+
+-static void savage_dma_flush(drm_savage_private_t *dev_priv)
++static void savage_dma_flush(drm_savage_private_t * dev_priv)
+ {
+ unsigned int first = dev_priv->first_dma_page;
+ unsigned int cur = dev_priv->current_dma_page;
+@@ -439,11 +438,10 @@ static void savage_dma_flush(drm_savage_
+
+ /* pad with noops */
+ if (pad) {
+- uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+- cur * SAVAGE_DMA_PAGE_SIZE +
+- dev_priv->dma_pages[cur].used;
++ uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
++ cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+ dev_priv->dma_pages[cur].used += pad;
+- while(pad != 0) {
++ while (pad != 0) {
+ *dma_ptr++ = BCI_CMD_WAIT;
+ pad--;
+ }
+@@ -453,11 +451,10 @@ static void savage_dma_flush(drm_savage_
+
+ /* do flush ... */
+ phys_addr = dev_priv->cmd_dma->offset +
+- (first * SAVAGE_DMA_PAGE_SIZE +
+- dev_priv->dma_pages[first].flushed) * 4;
++ (first * SAVAGE_DMA_PAGE_SIZE +
++ dev_priv->dma_pages[first].flushed) * 4;
+ len = (cur - first) * SAVAGE_DMA_PAGE_SIZE +
+- dev_priv->dma_pages[cur].used -
+- dev_priv->dma_pages[first].flushed;
++ dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed;
+
+ DRM_DEBUG("phys_addr=%lx, len=%u\n",
+ phys_addr | dev_priv->dma_type, len);
+@@ -499,7 +496,7 @@ static void savage_dma_flush(drm_savage_
+ dev_priv->dma_pages[cur].flushed);
+ }
+
+-static void savage_fake_dma_flush(drm_savage_private_t *dev_priv)
++static void savage_fake_dma_flush(drm_savage_private_t * dev_priv)
+ {
+ unsigned int i, j;
+ BCI_LOCALS;
+@@ -515,8 +512,8 @@ static void savage_fake_dma_flush(drm_sa
+ for (i = dev_priv->first_dma_page;
+ i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used;
+ ++i) {
+- uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+- i * SAVAGE_DMA_PAGE_SIZE;
++ uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
++ i * SAVAGE_DMA_PAGE_SIZE;
+ #if SAVAGE_DMA_DEBUG
+ /* Sanity check: all pages except the last one must be full. */
+ if (i < dev_priv->current_dma_page &&
+@@ -543,7 +540,7 @@ static void savage_fake_dma_flush(drm_sa
+ * initialized. We also need to take care of deleting the MTRRs in
+ * postcleanup.
+ */
+-int savage_preinit(drm_device_t *dev, unsigned long chipset)
++int savage_preinit(drm_device_t * dev, unsigned long chipset)
+ {
+ drm_savage_private_t *dev_priv;
+ unsigned long mmio_base, fb_base, fb_size, aperture_base;
+@@ -578,19 +575,22 @@ int savage_preinit(drm_device_t *dev, un
+ * MTRRs. */
+ dev_priv->mtrr[0].base = fb_base;
+ dev_priv->mtrr[0].size = 0x01000000;
+- dev_priv->mtrr[0].handle = mtrr_add(
+- dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
+- MTRR_TYPE_WRCOMB, 1);
+- dev_priv->mtrr[1].base = fb_base+0x02000000;
++ dev_priv->mtrr[0].handle =
++ mtrr_add(dev_priv->mtrr[0].base,
++ dev_priv->mtrr[0].size, MTRR_TYPE_WRCOMB,
++ 1);
++ dev_priv->mtrr[1].base = fb_base + 0x02000000;
+ dev_priv->mtrr[1].size = 0x02000000;
+- dev_priv->mtrr[1].handle = mtrr_add(
+- dev_priv->mtrr[1].base, dev_priv->mtrr[1].size,
+- MTRR_TYPE_WRCOMB, 1);
+- dev_priv->mtrr[2].base = fb_base+0x04000000;
++ dev_priv->mtrr[1].handle =
++ mtrr_add(dev_priv->mtrr[1].base,
++ dev_priv->mtrr[1].size, MTRR_TYPE_WRCOMB,
++ 1);
++ dev_priv->mtrr[2].base = fb_base + 0x04000000;
+ dev_priv->mtrr[2].size = 0x04000000;
+- dev_priv->mtrr[2].handle = mtrr_add(
+- dev_priv->mtrr[2].base, dev_priv->mtrr[2].size,
+- MTRR_TYPE_WRCOMB, 1);
++ dev_priv->mtrr[2].handle =
++ mtrr_add(dev_priv->mtrr[2].base,
++ dev_priv->mtrr[2].size, MTRR_TYPE_WRCOMB,
++ 1);
+ } else {
+ DRM_ERROR("strange pci_resource_len %08lx\n",
+ drm_get_resource_len(dev, 0));
+@@ -608,9 +608,10 @@ int savage_preinit(drm_device_t *dev, un
+ * aperture. */
+ dev_priv->mtrr[0].base = fb_base;
+ dev_priv->mtrr[0].size = 0x08000000;
+- dev_priv->mtrr[0].handle = mtrr_add(
+- dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
+- MTRR_TYPE_WRCOMB, 1);
++ dev_priv->mtrr[0].handle =
++ mtrr_add(dev_priv->mtrr[0].base,
++ dev_priv->mtrr[0].size, MTRR_TYPE_WRCOMB,
++ 1);
+ } else {
+ DRM_ERROR("strange pci_resource_len %08lx\n",
+ drm_get_resource_len(dev, 1));
+@@ -647,7 +648,7 @@ int savage_preinit(drm_device_t *dev, un
+ /*
+ * Delete MTRRs and free device-private data.
+ */
+-int savage_postcleanup(drm_device_t *dev)
++int savage_postcleanup(drm_device_t * dev)
+ {
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ int i;
+@@ -663,7 +664,7 @@ int savage_postcleanup(drm_device_t *dev
+ return 0;
+ }
+
+-static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
++static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init)
+ {
+ drm_savage_private_t *dev_priv = dev->dev_private;
+
+@@ -731,7 +732,7 @@ static int savage_do_init_bci(drm_device
+ }
+ if (init->agp_textures_offset) {
+ dev_priv->agp_textures =
+- drm_core_findmap(dev, init->agp_textures_offset);
++ drm_core_findmap(dev, init->agp_textures_offset);
+ if (!dev_priv->agp_textures) {
+ DRM_ERROR("could not find agp texture region!\n");
+ savage_do_cleanup_bci(dev);
+@@ -802,8 +803,8 @@ static int savage_do_init_bci(drm_device
+ }
+
+ dev_priv->sarea_priv =
+- (drm_savage_sarea_t *)((uint8_t *)dev_priv->sarea->handle +
+- init->sarea_priv_offset);
++ (drm_savage_sarea_t *) ((uint8_t *) dev_priv->sarea->handle +
++ init->sarea_priv_offset);
+
+ /* setup bitmap descriptors */
+ {
+@@ -812,35 +813,36 @@ static int savage_do_init_bci(drm_device
+ unsigned int front_stride, back_stride, depth_stride;
+ if (dev_priv->chipset <= S3_SAVAGE4) {
+ color_tile_format = dev_priv->fb_bpp == 16 ?
+- SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
++ SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+ depth_tile_format = dev_priv->depth_bpp == 16 ?
+- SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
++ SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+ } else {
+ color_tile_format = SAVAGE_BD_TILE_DEST;
+ depth_tile_format = SAVAGE_BD_TILE_DEST;
+ }
+- front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp/8);
+- back_stride = dev_priv-> back_pitch / (dev_priv->fb_bpp/8);
+- depth_stride = dev_priv->depth_pitch / (dev_priv->depth_bpp/8);
++ front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp / 8);
++ back_stride = dev_priv->back_pitch / (dev_priv->fb_bpp / 8);
++ depth_stride =
++ dev_priv->depth_pitch / (dev_priv->depth_bpp / 8);
+
+ dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE |
+- (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+- (color_tile_format << SAVAGE_BD_TILE_SHIFT);
++ (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
++ (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+- dev_priv-> back_bd = back_stride | SAVAGE_BD_BW_DISABLE |
+- (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+- (color_tile_format << SAVAGE_BD_TILE_SHIFT);
++ dev_priv->back_bd = back_stride | SAVAGE_BD_BW_DISABLE |
++ (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
++ (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+ dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE |
+- (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) |
+- (depth_tile_format << SAVAGE_BD_TILE_SHIFT);
++ (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) |
++ (depth_tile_format << SAVAGE_BD_TILE_SHIFT);
+ }
+
+ /* setup status and bci ptr */
+ dev_priv->event_counter = 0;
+ dev_priv->event_wrap = 0;
+ dev_priv->bci_ptr = (volatile uint32_t *)
+- ((uint8_t *)dev_priv->mmio->handle + SAVAGE_BCI_OFFSET);
++ ((uint8_t *) dev_priv->mmio->handle + SAVAGE_BCI_OFFSET);
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D;
+ } else {
+@@ -848,7 +850,7 @@ static int savage_do_init_bci(drm_device
+ }
+ if (dev_priv->status != NULL) {
+ dev_priv->status_ptr =
+- (volatile uint32_t *)dev_priv->status->handle;
++ (volatile uint32_t *)dev_priv->status->handle;
+ dev_priv->wait_fifo = savage_bci_wait_fifo_shadow;
+ dev_priv->wait_evnt = savage_bci_wait_event_shadow;
+ dev_priv->status_ptr[1023] = dev_priv->event_counter;
+@@ -874,7 +876,7 @@ static int savage_do_init_bci(drm_device
+ return DRM_ERR(ENOMEM);
+ }
+
+- if (savage_dma_init(dev_priv) < 0) {
++ if (savage_dma_init(dev_priv) < 0) {
+ DRM_ERROR("could not initialize command DMA\n");
+ savage_do_cleanup_bci(dev);
+ return DRM_ERR(ENOMEM);
+@@ -883,7 +885,7 @@ static int savage_do_init_bci(drm_device
+ return 0;
+ }
+
+-int savage_do_cleanup_bci(drm_device_t *dev)
++int savage_do_cleanup_bci(drm_device_t * dev)
+ {
+ drm_savage_private_t *dev_priv = dev->dev_private;
+
+@@ -907,7 +909,7 @@ int savage_do_cleanup_bci(drm_device_t *
+
+ if (dev_priv->dma_pages)
+ drm_free(dev_priv->dma_pages,
+- sizeof(drm_savage_dma_page_t)*dev_priv->nr_dma_pages,
++ sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages,
+ DRM_MEM_DRIVER);
+
+ return 0;
+@@ -920,7 +922,7 @@ static int savage_bci_init(DRM_IOCTL_ARG
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *)data,
++ DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *) data,
+ sizeof(init));
+
+ switch (init.func) {
+@@ -943,13 +945,13 @@ static int savage_bci_event_emit(DRM_IOC
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *)data,
++ DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *) data,
+ sizeof(event));
+
+ event.count = savage_bci_emit_event(dev_priv, event.flags);
+ event.count |= dev_priv->event_wrap << 16;
+- DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *)data)->count,
+- event.count, sizeof(event.count));
++ DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *) data)->
++ count, event.count, sizeof(event.count));
+ return 0;
+ }
+
+@@ -963,7 +965,7 @@ static int savage_bci_event_wait(DRM_IOC
+
+ DRM_DEBUG("\n");
+
+- DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *)data,
++ DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *) data,
+ sizeof(event));
+
+ UPDATE_EVENT_COUNTER();
+@@ -973,7 +975,7 @@ static int savage_bci_event_wait(DRM_IOC
+ hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+ hw_w = dev_priv->event_wrap;
+ if (hw_e > dev_priv->event_counter)
+- hw_w--; /* hardware hasn't passed the last wrap yet */
++ hw_w--; /* hardware hasn't passed the last wrap yet */
+
+ event_e = event.count & 0xffff;
+ event_w = event.count >> 16;
+@@ -982,7 +984,7 @@ static int savage_bci_event_wait(DRM_IOC
+ * - event counter wrapped since the event was emitted or
+ * - the hardware has advanced up to or over the event to wait for.
+ */
+- if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e) )
++ if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e))
+ return 0;
+ else
+ return dev_priv->wait_evnt(dev_priv, event_e);
+@@ -992,7 +994,8 @@ static int savage_bci_event_wait(DRM_IOC
+ * DMA buffer management
+ */
+
+-static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
++static int savage_bci_get_buffers(DRMFILE filp, drm_device_t * dev,
++ drm_dma_t * d)
+ {
+ drm_buf_t *buf;
+ int i;
+@@ -1025,7 +1028,7 @@ int savage_bci_buffers(DRM_IOCTL_ARGS)
+
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *)data, sizeof(d));
++ DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *) data, sizeof(d));
+
+ /* Please don't send us buffers.
+ */
+@@ -1049,12 +1052,13 @@ int savage_bci_buffers(DRM_IOCTL_ARGS)
+ ret = savage_bci_get_buffers(filp, dev, &d);
+ }
+
+- DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *)data, d, sizeof(d));
++ DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *) data, d, sizeof(d));
+
+ return ret;
+ }
+
+-void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp) {
++void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp)
++{
+ drm_device_dma_t *dma = dev->dma;
+ drm_savage_private_t *dev_priv = dev->dev_private;
+ int i;
+@@ -1066,7 +1070,7 @@ void savage_reclaim_buffers(drm_device_t
+ if (!dma->buflist)
+ return;
+
+- /*i830_flush_queue(dev);*/
++ /*i830_flush_queue(dev); */
+
+ for (i = 0; i < dma->buf_count; i++) {
+ drm_buf_t *buf = dma->buflist[i];
+@@ -1085,7 +1089,6 @@ void savage_reclaim_buffers(drm_device_t
+ drm_core_reclaim_buffers(dev, filp);
+ }
+
+-
+ drm_ioctl_desc_t savage_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, 1, 1},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, 1, 0},
+diff --git a/drivers/char/drm/savage_drm.h b/drivers/char/drm/savage_drm.h
+--- a/drivers/char/drm/savage_drm.h
++++ b/drivers/char/drm/savage_drm.h
+@@ -42,12 +42,13 @@
+ #define SAVAGE_NR_TEX_REGIONS 16
+ #define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16
+
+-#endif /* __SAVAGE_SAREA_DEFINES__ */
++#endif /* __SAVAGE_SAREA_DEFINES__ */
+
+ typedef struct _drm_savage_sarea {
+ /* LRU lists for texture memory in agp space and on the card.
+ */
+- drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS+1];
++ drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
++ 1];
+ unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
+
+ /* Mechanism to validate card state.
+@@ -101,24 +102,24 @@ typedef struct drm_savage_init {
+
+ typedef union drm_savage_cmd_header drm_savage_cmd_header_t;
+ typedef struct drm_savage_cmdbuf {
+- /* command buffer in client's address space */
++ /* command buffer in client's address space */
+ drm_savage_cmd_header_t __user *cmd_addr;
+ unsigned int size; /* size of the command buffer in 64bit units */
+
+ unsigned int dma_idx; /* DMA buffer index to use */
+ int discard; /* discard DMA buffer when done */
+- /* vertex buffer in client's address space */
++ /* vertex buffer in client's address space */
+ unsigned int __user *vb_addr;
+ unsigned int vb_size; /* size of client vertex buffer in bytes */
+ unsigned int vb_stride; /* stride of vertices in 32bit words */
+- /* boxes in client's address space */
++ /* boxes in client's address space */
+ drm_clip_rect_t __user *box_addr;
+ unsigned int nbox; /* number of clipping boxes */
+ } drm_savage_cmdbuf_t;
+
+-#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */
+-#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */
+-#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */
++#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */
++#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */
++#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */
+ typedef struct drm_savage_event {
+ unsigned int count;
+ unsigned int flags;
+@@ -126,21 +127,21 @@ typedef struct drm_savage_event {
+
+ /* Commands for the cmdbuf ioctl
+ */
+-#define SAVAGE_CMD_STATE 0 /* a range of state registers */
+-#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */
+-#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */
+-#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */
+-#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */
+-#define SAVAGE_CMD_CLEAR 5 /* clear buffers */
+-#define SAVAGE_CMD_SWAP 6 /* swap buffers */
++#define SAVAGE_CMD_STATE 0 /* a range of state registers */
++#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */
++#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */
++#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */
++#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */
++#define SAVAGE_CMD_CLEAR 5 /* clear buffers */
++#define SAVAGE_CMD_SWAP 6 /* swap buffers */
+
+ /* Primitive types
+ */
+-#define SAVAGE_PRIM_TRILIST 0 /* triangle list */
+-#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */
+-#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */
+-#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat
+- * shading on s3d */
++#define SAVAGE_PRIM_TRILIST 0 /* triangle list */
++#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */
++#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */
++#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat
++ * shading on s3d */
+
+ /* Skip flags (vertex format)
+ */
+@@ -172,38 +173,38 @@ union drm_savage_cmd_header {
+ unsigned short pad1;
+ unsigned short pad2;
+ unsigned short pad3;
+- } cmd; /* generic */
++ } cmd; /* generic */
+ struct {
+ unsigned char cmd;
+ unsigned char global; /* need idle engine? */
+ unsigned short count; /* number of consecutive registers */
+ unsigned short start; /* first register */
+ unsigned short pad3;
+- } state; /* SAVAGE_CMD_STATE */
++ } state; /* SAVAGE_CMD_STATE */
+ struct {
+ unsigned char cmd;
+ unsigned char prim; /* primitive type */
+ unsigned short skip; /* vertex format (skip flags) */
+ unsigned short count; /* number of vertices */
+ unsigned short start; /* first vertex in DMA/vertex buffer */
+- } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */
++ } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */
+ struct {
+ unsigned char cmd;
+ unsigned char prim;
+ unsigned short skip;
+ unsigned short count; /* number of indices that follow */
+ unsigned short pad3;
+- } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */
++ } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */
+ struct {
+ unsigned char cmd;
+ unsigned char pad0;
+ unsigned short pad1;
+ unsigned int flags;
+- } clear0; /* SAVAGE_CMD_CLEAR */
++ } clear0; /* SAVAGE_CMD_CLEAR */
+ struct {
+ unsigned int mask;
+ unsigned int value;
+- } clear1; /* SAVAGE_CMD_CLEAR data */
++ } clear1; /* SAVAGE_CMD_CLEAR data */
+ };
+
+ #endif
+diff --git a/drivers/char/drm/savage_drv.c b/drivers/char/drm/savage_drv.c
+--- a/drivers/char/drm/savage_drv.c
++++ b/drivers/char/drm/savage_drv.c
+@@ -30,30 +30,28 @@
+
+ #include "drm_pciids.h"
+
+-static int postinit( struct drm_device *dev, unsigned long flags )
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -61,13 +59,9 @@ static struct pci_device_id pciidlist[]
+ savage_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t savage_ioctls[];
+-extern int savage_max_ioctl;
+-
+ static struct drm_driver driver = {
+ .driver_features =
+- DRIVER_USE_AGP | DRIVER_USE_MTRR |
+- DRIVER_HAVE_DMA | DRIVER_PCI_DMA,
++ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_PCI_DMA,
+ .dev_priv_size = sizeof(drm_savage_buf_priv_t),
+ .preinit = savage_preinit,
+ .postinit = postinit,
+@@ -79,18 +73,19 @@ static struct drm_driver driver = {
+ .ioctls = savage_ioctls,
+ .dma_ioctl = savage_bci_buffers,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
+- },
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
++ }
++ ,
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init savage_init(void)
+@@ -107,6 +102,6 @@ static void __exit savage_exit(void)
+ module_init(savage_init);
+ module_exit(savage_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
+--- a/drivers/char/drm/savage_drv.h
++++ b/drivers/char/drm/savage_drv.h
+@@ -65,7 +65,7 @@ typedef struct drm_savage_dma_page {
+ drm_savage_age_t age;
+ unsigned int used, flushed;
+ } drm_savage_dma_page_t;
+-#define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */
++#define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */
+ /* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command
+ * size of 16kbytes or 4k entries. Minimum requirement would be
+ * 10kbytes for 255 40-byte vertices in one drawing command. */
+@@ -104,6 +104,9 @@ enum savage_family {
+ S3_LAST
+ };
+
++extern drm_ioctl_desc_t savage_ioctls[];
++extern int savage_max_ioctl;
++
+ #define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+ #define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \
+@@ -184,13 +187,13 @@ typedef struct drm_savage_private {
+ unsigned int waiting;
+
+ /* config/hardware-dependent function pointers */
+- int (*wait_fifo)(struct drm_savage_private *dev_priv, unsigned int n);
+- int (*wait_evnt)(struct drm_savage_private *dev_priv, uint16_t e);
++ int (*wait_fifo) (struct drm_savage_private * dev_priv, unsigned int n);
++ int (*wait_evnt) (struct drm_savage_private * dev_priv, uint16_t e);
+ /* Err, there is a macro wait_event in include/linux/wait.h.
+ * Avoid unwanted macro expansion. */
+- void (*emit_clip_rect)(struct drm_savage_private *dev_priv,
+- drm_clip_rect_t *pbox);
+- void (*dma_flush)(struct drm_savage_private *dev_priv);
++ void (*emit_clip_rect) (struct drm_savage_private * dev_priv,
++ drm_clip_rect_t * pbox);
++ void (*dma_flush) (struct drm_savage_private * dev_priv);
+ } drm_savage_private_t;
+
+ /* ioctls */
+@@ -198,23 +201,23 @@ extern int savage_bci_cmdbuf(DRM_IOCTL_A
+ extern int savage_bci_buffers(DRM_IOCTL_ARGS);
+
+ /* BCI functions */
+-extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
++extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
+ unsigned int flags);
+-extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
+-extern void savage_dma_reset(drm_savage_private_t *dev_priv);
+-extern void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page);
+-extern uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv,
++extern void savage_freelist_put(drm_device_t * dev, drm_buf_t * buf);
++extern void savage_dma_reset(drm_savage_private_t * dev_priv);
++extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page);
++extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv,
+ unsigned int n);
+-extern int savage_preinit(drm_device_t *dev, unsigned long chipset);
+-extern int savage_postcleanup(drm_device_t *dev);
+-extern int savage_do_cleanup_bci(drm_device_t *dev);
+-extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
++extern int savage_preinit(drm_device_t * dev, unsigned long chipset);
++extern int savage_postcleanup(drm_device_t * dev);
++extern int savage_do_cleanup_bci(drm_device_t * dev);
++extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);
+
+ /* state functions */
+-extern void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
+- drm_clip_rect_t *pbox);
+-extern void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
+- drm_clip_rect_t *pbox);
++extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
++ drm_clip_rect_t * pbox);
++extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
++ drm_clip_rect_t * pbox);
+
+ #define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */
+ #define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */
+@@ -222,10 +225,10 @@ extern void savage_emit_clip_rect_s4(drm
+ #define SAVAGE_APERTURE_OFFSET 0x02000000 /* 32MB */
+ #define SAVAGE_APERTURE_SIZE 0x05000000 /* 5 tiled surfaces, 16MB each */
+
+-#define SAVAGE_BCI_OFFSET 0x00010000 /* offset of the BCI region
++#define SAVAGE_BCI_OFFSET 0x00010000 /* offset of the BCI region
+ * inside the MMIO region */
+-#define SAVAGE_BCI_FIFO_SIZE 32 /* number of entries in on-chip
+- * BCI FIFO */
++#define SAVAGE_BCI_FIFO_SIZE 32 /* number of entries in on-chip
++ * BCI FIFO */
+
+ /*
+ * MMIO registers
+@@ -278,7 +281,7 @@ extern void savage_emit_clip_rect_s4(drm
+ #define SAVAGE_TEXADDR1_S4 0x23
+ #define SAVAGE_TEXBLEND0_S4 0x24
+ #define SAVAGE_TEXBLEND1_S4 0x25
+-#define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */
++#define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */
+ #define SAVAGE_TEXDESCR_S4 0x27
+ #define SAVAGE_FOGTABLE_S4 0x28
+ #define SAVAGE_FOGCTRL_S4 0x30
+@@ -293,7 +296,7 @@ extern void savage_emit_clip_rect_s4(drm
+ #define SAVAGE_TEXBLENDCOLOR_S4 0x39
+ /* Savage3D/MX/IX 3D registers */
+ #define SAVAGE_TEXPALADDR_S3D 0x18
+-#define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */
++#define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */
+ #define SAVAGE_TEXADDR_S3D 0x1A
+ #define SAVAGE_TEXDESCR_S3D 0x1B
+ #define SAVAGE_TEXCTRL_S3D 0x1C
+@@ -305,7 +308,7 @@ extern void savage_emit_clip_rect_s4(drm
+ #define SAVAGE_DESTCTRL_S3D 0x34
+ #define SAVAGE_SCSTART_S3D 0x35
+ #define SAVAGE_SCEND_S3D 0x36
+-#define SAVAGE_ZWATERMARK_S3D 0x37
++#define SAVAGE_ZWATERMARK_S3D 0x37
+ #define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38
+ /* common stuff */
+ #define SAVAGE_VERTBUFADDR 0x3e
+@@ -313,9 +316,9 @@ extern void savage_emit_clip_rect_s4(drm
+ #define SAVAGE_DMABUFADDR 0x51
+
+ /* texture enable bits (needed for tex addr checking) */
+-#define SAVAGE_TEXCTRL_TEXEN_MASK 0x00010000 /* S3D */
+-#define SAVAGE_TEXDESCR_TEX0EN_MASK 0x02000000 /* S4 */
+-#define SAVAGE_TEXDESCR_TEX1EN_MASK 0x04000000 /* S4 */
++#define SAVAGE_TEXCTRL_TEXEN_MASK 0x00010000 /* S3D */
++#define SAVAGE_TEXDESCR_TEX0EN_MASK 0x02000000 /* S4 */
++#define SAVAGE_TEXDESCR_TEX1EN_MASK 0x04000000 /* S4 */
+
+ /* Global fields in Savage4/Twister/ProSavage 3D registers:
+ *
+@@ -576,4 +579,4 @@ extern void savage_emit_clip_rect_s4(drm
+ #define TEST_AGE( age, e, w ) \
+ ( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) )
+
+-#endif /* __SAVAGE_DRV_H__ */
++#endif /* __SAVAGE_DRV_H__ */
+diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
+--- a/drivers/char/drm/savage_state.c
++++ b/drivers/char/drm/savage_state.c
+@@ -26,48 +26,48 @@
+ #include "savage_drm.h"
+ #include "savage_drv.h"
+
+-void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
+- drm_clip_rect_t *pbox)
++void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
++ drm_clip_rect_t * pbox)
+ {
+ uint32_t scstart = dev_priv->state.s3d.new_scstart;
+- uint32_t scend = dev_priv->state.s3d.new_scend;
++ uint32_t scend = dev_priv->state.s3d.new_scend;
+ scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) |
+- ((uint32_t)pbox->x1 & 0x000007ff) |
+- (((uint32_t)pbox->y1 << 16) & 0x07ff0000);
+- scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) |
+- (((uint32_t)pbox->x2-1) & 0x000007ff) |
+- ((((uint32_t)pbox->y2-1) << 16) & 0x07ff0000);
++ ((uint32_t) pbox->x1 & 0x000007ff) |
++ (((uint32_t) pbox->y1 << 16) & 0x07ff0000);
++ scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) |
++ (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
++ ((((uint32_t) pbox->y2 - 1) << 16) & 0x07ff0000);
+ if (scstart != dev_priv->state.s3d.scstart ||
+- scend != dev_priv->state.s3d.scend) {
++ scend != dev_priv->state.s3d.scend) {
+ DMA_LOCALS;
+ BEGIN_DMA(4);
+- DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D);
++ DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+ DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2);
+ DMA_WRITE(scstart);
+ DMA_WRITE(scend);
+ dev_priv->state.s3d.scstart = scstart;
+- dev_priv->state.s3d.scend = scend;
++ dev_priv->state.s3d.scend = scend;
+ dev_priv->waiting = 1;
+ DMA_COMMIT();
+ }
+ }
+
+-void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
+- drm_clip_rect_t *pbox)
++void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
++ drm_clip_rect_t * pbox)
+ {
+ uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
+ uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
+ drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) |
+- ((uint32_t)pbox->x1 & 0x000007ff) |
+- (((uint32_t)pbox->y1 << 12) & 0x00fff000);
++ ((uint32_t) pbox->x1 & 0x000007ff) |
++ (((uint32_t) pbox->y1 << 12) & 0x00fff000);
+ drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) |
+- (((uint32_t)pbox->x2-1) & 0x000007ff) |
+- ((((uint32_t)pbox->y2-1) << 12) & 0x00fff000);
++ (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
++ ((((uint32_t) pbox->y2 - 1) << 12) & 0x00fff000);
+ if (drawctrl0 != dev_priv->state.s4.drawctrl0 ||
+ drawctrl1 != dev_priv->state.s4.drawctrl1) {
+ DMA_LOCALS;
+ BEGIN_DMA(4);
+- DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D);
++ DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+ DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2);
+ DMA_WRITE(drawctrl0);
+ DMA_WRITE(drawctrl1);
+@@ -78,22 +78,23 @@ void savage_emit_clip_rect_s4(drm_savage
+ }
+ }
+
+-static int savage_verify_texaddr(drm_savage_private_t *dev_priv, int unit,
++static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit,
+ uint32_t addr)
+ {
+- if ((addr & 6) != 2) { /* reserved bits */
++ if ((addr & 6) != 2) { /* reserved bits */
+ DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+- if (!(addr & 1)) { /* local */
++ if (!(addr & 1)) { /* local */
+ addr &= ~7;
+- if (addr < dev_priv->texture_offset ||
+- addr >= dev_priv->texture_offset+dev_priv->texture_size) {
+- DRM_ERROR("bad texAddr%d %08x (local addr out of range)\n",
+- unit, addr);
++ if (addr < dev_priv->texture_offset ||
++ addr >= dev_priv->texture_offset + dev_priv->texture_size) {
++ DRM_ERROR
++ ("bad texAddr%d %08x (local addr out of range)\n",
++ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+- } else { /* AGP */
++ } else { /* AGP */
+ if (!dev_priv->agp_textures) {
+ DRM_ERROR("bad texAddr%d %08x (AGP not available)\n",
+ unit, addr);
+@@ -103,8 +104,9 @@ static int savage_verify_texaddr(drm_sav
+ if (addr < dev_priv->agp_textures->offset ||
+ addr >= (dev_priv->agp_textures->offset +
+ dev_priv->agp_textures->size)) {
+- DRM_ERROR("bad texAddr%d %08x (AGP addr out of range)\n",
+- unit, addr);
++ DRM_ERROR
++ ("bad texAddr%d %08x (AGP addr out of range)\n",
++ unit, addr);
+ return DRM_ERR(EINVAL);
+ }
+ }
+@@ -122,14 +124,14 @@ static int savage_verify_texaddr(drm_sav
+ (dev_priv->state.where & ~(mask)); \
+ } \
+ } while (0)
+-static int savage_verify_state_s3d(drm_savage_private_t *dev_priv,
++static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
+ unsigned int start, unsigned int count,
+- const uint32_t __user *regs)
++ const uint32_t __user * regs)
+ {
+ if (start < SAVAGE_TEXPALADDR_S3D ||
+- start+count-1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
++ start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
+ DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+- start, start+count-1);
++ start, start + count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -140,28 +142,29 @@ static int savage_verify_state_s3d(drm_s
+
+ /* if any texture regs were changed ... */
+ if (start <= SAVAGE_TEXCTRL_S3D &&
+- start+count > SAVAGE_TEXPALADDR_S3D) {
++ start + count > SAVAGE_TEXPALADDR_S3D) {
+ /* ... check texture state */
+ SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl);
+ SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr);
+ if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK)
+- return savage_verify_texaddr(
+- dev_priv, 0, dev_priv->state.s3d.texaddr);
++ return savage_verify_texaddr(dev_priv, 0,
++ dev_priv->state.s3d.
++ texaddr);
+ }
+
+ return 0;
+ }
+
+-static int savage_verify_state_s4(drm_savage_private_t *dev_priv,
++static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
+ unsigned int start, unsigned int count,
+- const uint32_t __user *regs)
++ const uint32_t __user * regs)
+ {
+ int ret = 0;
+
+ if (start < SAVAGE_DRAWLOCALCTRL_S4 ||
+- start+count-1 > SAVAGE_TEXBLENDCOLOR_S4) {
++ start + count - 1 > SAVAGE_TEXBLENDCOLOR_S4) {
+ DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+- start, start+count-1);
++ start, start + count - 1);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -171,28 +174,30 @@ static int savage_verify_state_s4(drm_sa
+ ~SAVAGE_SCISSOR_MASK_S4);
+
+ /* if any texture regs were changed ... */
+- if (start <= SAVAGE_TEXDESCR_S4 &&
+- start+count > SAVAGE_TEXPALADDR_S4) {
++ if (start <= SAVAGE_TEXDESCR_S4 && start + count > SAVAGE_TEXPALADDR_S4) {
+ /* ... check texture state */
+ SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr);
+ SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0);
+ SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1);
+ if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK)
+- ret |= savage_verify_texaddr(
+- dev_priv, 0, dev_priv->state.s4.texaddr0);
++ ret |=
++ savage_verify_texaddr(dev_priv, 0,
++ dev_priv->state.s4.texaddr0);
+ if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK)
+- ret |= savage_verify_texaddr(
+- dev_priv, 1, dev_priv->state.s4.texaddr1);
++ ret |=
++ savage_verify_texaddr(dev_priv, 1,
++ dev_priv->state.s4.texaddr1);
+ }
+
+ return ret;
+ }
++
+ #undef SAVE_STATE
+ #undef SAVE_STATE_MASK
+
+-static int savage_dispatch_state(drm_savage_private_t *dev_priv,
+- const drm_savage_cmd_header_t *cmd_header,
+- const uint32_t __user *regs)
++static int savage_dispatch_state(drm_savage_private_t * dev_priv,
++ const drm_savage_cmd_header_t * cmd_header,
++ const uint32_t __user * regs)
+ {
+ unsigned int count = cmd_header->state.count;
+ unsigned int start = cmd_header->state.start;
+@@ -204,7 +209,7 @@ static int savage_dispatch_state(drm_sav
+ if (!count)
+ return 0;
+
+- if (DRM_VERIFYAREA_READ(regs, count*4))
++ if (DRM_VERIFYAREA_READ(regs, count * 4))
+ return DRM_ERR(EFAULT);
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+@@ -213,14 +218,14 @@ static int savage_dispatch_state(drm_sav
+ return ret;
+ /* scissor regs are emitted in savage_dispatch_draw */
+ if (start < SAVAGE_SCSTART_S3D) {
+- if (start+count > SAVAGE_SCEND_S3D+1)
+- count2 = count - (SAVAGE_SCEND_S3D+1 - start);
+- if (start+count > SAVAGE_SCSTART_S3D)
++ if (start + count > SAVAGE_SCEND_S3D + 1)
++ count2 = count - (SAVAGE_SCEND_S3D + 1 - start);
++ if (start + count > SAVAGE_SCSTART_S3D)
+ count = SAVAGE_SCSTART_S3D - start;
+ } else if (start <= SAVAGE_SCEND_S3D) {
+- if (start+count > SAVAGE_SCEND_S3D+1) {
+- count -= SAVAGE_SCEND_S3D+1 - start;
+- start = SAVAGE_SCEND_S3D+1;
++ if (start + count > SAVAGE_SCEND_S3D + 1) {
++ count -= SAVAGE_SCEND_S3D + 1 - start;
++ start = SAVAGE_SCEND_S3D + 1;
+ } else
+ return 0;
+ }
+@@ -230,23 +235,24 @@ static int savage_dispatch_state(drm_sav
+ return ret;
+ /* scissor regs are emitted in savage_dispatch_draw */
+ if (start < SAVAGE_DRAWCTRL0_S4) {
+- if (start+count > SAVAGE_DRAWCTRL1_S4+1)
+- count2 = count - (SAVAGE_DRAWCTRL1_S4+1 - start);
+- if (start+count > SAVAGE_DRAWCTRL0_S4)
++ if (start + count > SAVAGE_DRAWCTRL1_S4 + 1)
++ count2 =
++ count - (SAVAGE_DRAWCTRL1_S4 + 1 - start);
++ if (start + count > SAVAGE_DRAWCTRL0_S4)
+ count = SAVAGE_DRAWCTRL0_S4 - start;
+ } else if (start <= SAVAGE_DRAWCTRL1_S4) {
+- if (start+count > SAVAGE_DRAWCTRL1_S4+1) {
+- count -= SAVAGE_DRAWCTRL1_S4+1 - start;
+- start = SAVAGE_DRAWCTRL1_S4+1;
++ if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) {
++ count -= SAVAGE_DRAWCTRL1_S4 + 1 - start;
++ start = SAVAGE_DRAWCTRL1_S4 + 1;
+ } else
+ return 0;
+ }
+ }
+
+- bci_size = count + (count+254)/255 + count2 + (count2+254)/255;
++ bci_size = count + (count + 254) / 255 + count2 + (count2 + 254) / 255;
+
+ if (cmd_header->state.global) {
+- BEGIN_DMA(bci_size+1);
++ BEGIN_DMA(bci_size + 1);
+ DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+ dev_priv->waiting = 1;
+ } else {
+@@ -273,9 +279,9 @@ static int savage_dispatch_state(drm_sav
+ return 0;
+ }
+
+-static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
+- const drm_savage_cmd_header_t *cmd_header,
+- const drm_buf_t *dmabuf)
++static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
++ const drm_savage_cmd_header_t * cmd_header,
++ const drm_buf_t * dmabuf)
+ {
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->prim.prim;
+@@ -286,8 +292,8 @@ static int savage_dispatch_dma_prim(drm_
+ BCI_LOCALS;
+
+ if (!dmabuf) {
+- DRM_ERROR("called without dma buffers!\n");
+- return DRM_ERR(EINVAL);
++ DRM_ERROR("called without dma buffers!\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ if (!n)
+@@ -307,8 +313,9 @@ static int savage_dispatch_dma_prim(drm_
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+- DRM_ERROR("wrong number of vertices %u in TRIFAN/STRIP\n",
+- n);
++ DRM_ERROR
++ ("wrong number of vertices %u in TRIFAN/STRIP\n",
++ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+@@ -319,17 +326,15 @@ static int savage_dispatch_dma_prim(drm_
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip != 0) {
+- DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+- skip);
++ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+- (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+- (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
++ (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
++ (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+ if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+- DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+- skip);
++ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ if (reorder) {
+@@ -338,9 +343,9 @@ static int savage_dispatch_dma_prim(drm_
+ }
+ }
+
+- if (start + n > dmabuf->total/32) {
++ if (start + n > dmabuf->total / 32) {
+ DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+- start, start + n - 1, dmabuf->total/32);
++ start, start + n - 1, dmabuf->total / 32);
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -375,32 +380,33 @@ static int savage_dispatch_dma_prim(drm_
+ /* Need to reorder indices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+- int reorder[3] = {-1, -1, -1};
+- reorder[start%3] = 2;
++ int reorder[3] = { -1, -1, -1 };
++ reorder[start % 3] = 2;
+
+- BEGIN_BCI((count+1+1)/2);
+- BCI_DRAW_INDICES_S3D(count, prim, start+2);
++ BEGIN_BCI((count + 1 + 1) / 2);
++ BCI_DRAW_INDICES_S3D(count, prim, start + 2);
+
+- for (i = start+1; i+1 < start+count; i += 2)
++ for (i = start + 1; i + 1 < start + count; i += 2)
+ BCI_WRITE((i + reorder[i % 3]) |
+- ((i+1 + reorder[(i+1) % 3]) << 16));
+- if (i < start+count)
+- BCI_WRITE(i + reorder[i%3]);
++ ((i + 1 +
++ reorder[(i + 1) % 3]) << 16));
++ if (i < start + count)
++ BCI_WRITE(i + reorder[i % 3]);
+ } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+- BEGIN_BCI((count+1+1)/2);
++ BEGIN_BCI((count + 1 + 1) / 2);
+ BCI_DRAW_INDICES_S3D(count, prim, start);
+
+- for (i = start+1; i+1 < start+count; i += 2)
+- BCI_WRITE(i | ((i+1) << 16));
+- if (i < start+count)
++ for (i = start + 1; i + 1 < start + count; i += 2)
++ BCI_WRITE(i | ((i + 1) << 16));
++ if (i < start + count)
+ BCI_WRITE(i);
+ } else {
+- BEGIN_BCI((count+2+1)/2);
++ BEGIN_BCI((count + 2 + 1) / 2);
+ BCI_DRAW_INDICES_S4(count, prim, skip);
+
+- for (i = start; i+1 < start+count; i += 2)
+- BCI_WRITE(i | ((i+1) << 16));
+- if (i < start+count)
++ for (i = start; i + 1 < start + count; i += 2)
++ BCI_WRITE(i | ((i + 1) << 16));
++ if (i < start + count)
+ BCI_WRITE(i);
+ }
+
+@@ -413,11 +419,10 @@ static int savage_dispatch_dma_prim(drm_
+ return 0;
+ }
+
+-static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv,
+- const drm_savage_cmd_header_t *cmd_header,
+- const uint32_t __user *vtxbuf,
+- unsigned int vb_size,
+- unsigned int vb_stride)
++static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
++ const drm_savage_cmd_header_t * cmd_header,
++ const uint32_t __user * vtxbuf,
++ unsigned int vb_size, unsigned int vb_stride)
+ {
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->prim.prim;
+@@ -445,8 +450,9 @@ static int savage_dispatch_vb_prim(drm_s
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+- DRM_ERROR("wrong number of vertices %u in TRIFAN/STRIP\n",
+- n);
++ DRM_ERROR
++ ("wrong number of vertices %u in TRIFAN/STRIP\n",
++ n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+@@ -460,18 +466,18 @@ static int savage_dispatch_vb_prim(drm_s
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+- vtx_size = 8; /* full vertex */
++ vtx_size = 8; /* full vertex */
+ } else {
+ if (skip > SAVAGE_SKIP_ALL_S4) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+- vtx_size = 10; /* full vertex */
++ vtx_size = 10; /* full vertex */
+ }
+
+ vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+- (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+- (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
++ (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
++ (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+ if (vtx_size > vb_stride) {
+ DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+@@ -479,9 +485,9 @@ static int savage_dispatch_vb_prim(drm_s
+ return DRM_ERR(EINVAL);
+ }
+
+- if (start + n > vb_size / (vb_stride*4)) {
++ if (start + n > vb_size / (vb_stride * 4)) {
+ DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+- start, start + n - 1, vb_size / (vb_stride*4));
++ start, start + n - 1, vb_size / (vb_stride * 4));
+ return DRM_ERR(EINVAL);
+ }
+
+@@ -493,31 +499,31 @@ static int savage_dispatch_vb_prim(drm_s
+ /* Need to reorder vertices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+- int reorder[3] = {-1, -1, -1};
+- reorder[start%3] = 2;
++ int reorder[3] = { -1, -1, -1 };
++ reorder[start % 3] = 2;
+
+- BEGIN_DMA(count*vtx_size+1);
++ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+- for (i = start; i < start+count; ++i) {
++ for (i = start; i < start + count; ++i) {
+ unsigned int j = i + reorder[i % 3];
+- DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],
++ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ } else {
+- BEGIN_DMA(count*vtx_size+1);
++ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ if (vb_stride == vtx_size) {
+- DMA_COPY_FROM_USER(&vtxbuf[vb_stride*start],
+- vtx_size*count);
++ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * start],
++ vtx_size * count);
+ } else {
+- for (i = start; i < start+count; ++i) {
+- DMA_COPY_FROM_USER(
+- &vtxbuf[vb_stride*i],
+- vtx_size);
++ for (i = start; i < start + count; ++i) {
++ DMA_COPY_FROM_USER(&vtxbuf
++ [vb_stride * i],
++ vtx_size);
+ }
+ }
+
+@@ -533,10 +539,10 @@ static int savage_dispatch_vb_prim(drm_s
+ return 0;
+ }
+
+-static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
+- const drm_savage_cmd_header_t *cmd_header,
+- const uint16_t __user *usr_idx,
+- const drm_buf_t *dmabuf)
++static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
++ const drm_savage_cmd_header_t * cmd_header,
++ const uint16_t __user * usr_idx,
++ const drm_buf_t * dmabuf)
+ {
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->idx.prim;
+@@ -546,8 +552,8 @@ static int savage_dispatch_dma_idx(drm_s
+ BCI_LOCALS;
+
+ if (!dmabuf) {
+- DRM_ERROR("called without dma buffers!\n");
+- return DRM_ERR(EINVAL);
++ DRM_ERROR("called without dma buffers!\n");
++ return DRM_ERR(EINVAL);
+ }
+
+ if (!n)
+@@ -559,16 +565,15 @@ static int savage_dispatch_dma_idx(drm_s
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+- DRM_ERROR("wrong number of indices %u in TRILIST\n",
+- n);
++ DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+- DRM_ERROR("wrong number of indices %u in TRIFAN/STRIP\n",
+- n);
++ DRM_ERROR
++ ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+@@ -579,17 +584,15 @@ static int savage_dispatch_dma_idx(drm_s
+
+ if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+ if (skip != 0) {
+- DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+- skip);
++ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ } else {
+ unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+- (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+- (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
++ (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
++ (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+ if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+- DRM_ERROR("invalid skip flags 0x%04x for DMA\n",
+- skip);
++ DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+ if (reorder) {
+@@ -629,11 +632,11 @@ static int savage_dispatch_dma_idx(drm_s
+ uint16_t idx[255];
+
+ /* Copy and check indices */
+- DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count*2);
++ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2);
+ for (i = 0; i < count; ++i) {
+- if (idx[i] > dmabuf->total/32) {
++ if (idx[i] > dmabuf->total / 32) {
+ DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+- i, idx[i], dmabuf->total/32);
++ i, idx[i], dmabuf->total / 32);
+ return DRM_ERR(EINVAL);
+ }
+ }
+@@ -642,30 +645,31 @@ static int savage_dispatch_dma_idx(drm_s
+ /* Need to reorder indices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+- int reorder[3] = {2, -1, -1};
++ int reorder[3] = { 2, -1, -1 };
+
+- BEGIN_BCI((count+1+1)/2);
++ BEGIN_BCI((count + 1 + 1) / 2);
+ BCI_DRAW_INDICES_S3D(count, prim, idx[2]);
+
+- for (i = 1; i+1 < count; i += 2)
++ for (i = 1; i + 1 < count; i += 2)
+ BCI_WRITE(idx[i + reorder[i % 3]] |
+- (idx[i+1 + reorder[(i+1) % 3]] << 16));
++ (idx[i + 1 + reorder[(i + 1) % 3]] <<
++ 16));
+ if (i < count)
+- BCI_WRITE(idx[i + reorder[i%3]]);
++ BCI_WRITE(idx[i + reorder[i % 3]]);
+ } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+- BEGIN_BCI((count+1+1)/2);
++ BEGIN_BCI((count + 1 + 1) / 2);
+ BCI_DRAW_INDICES_S3D(count, prim, idx[0]);
+
+- for (i = 1; i+1 < count; i += 2)
+- BCI_WRITE(idx[i] | (idx[i+1] << 16));
++ for (i = 1; i + 1 < count; i += 2)
++ BCI_WRITE(idx[i] | (idx[i + 1] << 16));
+ if (i < count)
+ BCI_WRITE(idx[i]);
+ } else {
+- BEGIN_BCI((count+2+1)/2);
++ BEGIN_BCI((count + 2 + 1) / 2);
+ BCI_DRAW_INDICES_S4(count, prim, skip);
+
+- for (i = 0; i+1 < count; i += 2)
+- BCI_WRITE(idx[i] | (idx[i+1] << 16));
++ for (i = 0; i + 1 < count; i += 2)
++ BCI_WRITE(idx[i] | (idx[i + 1] << 16));
+ if (i < count)
+ BCI_WRITE(idx[i]);
+ }
+@@ -679,12 +683,11 @@ static int savage_dispatch_dma_idx(drm_s
+ return 0;
+ }
+
+-static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv,
+- const drm_savage_cmd_header_t *cmd_header,
+- const uint16_t __user *usr_idx,
+- const uint32_t __user *vtxbuf,
+- unsigned int vb_size,
+- unsigned int vb_stride)
++static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
++ const drm_savage_cmd_header_t * cmd_header,
++ const uint16_t __user * usr_idx,
++ const uint32_t __user * vtxbuf,
++ unsigned int vb_size, unsigned int vb_stride)
+ {
+ unsigned char reorder = 0;
+ unsigned int prim = cmd_header->idx.prim;
+@@ -703,16 +706,15 @@ static int savage_dispatch_vb_idx(drm_sa
+ prim = SAVAGE_PRIM_TRILIST;
+ case SAVAGE_PRIM_TRILIST:
+ if (n % 3 != 0) {
+- DRM_ERROR("wrong number of indices %u in TRILIST\n",
+- n);
++ DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+ case SAVAGE_PRIM_TRISTRIP:
+ case SAVAGE_PRIM_TRIFAN:
+ if (n < 3) {
+- DRM_ERROR("wrong number of indices %u in TRIFAN/STRIP\n",
+- n);
++ DRM_ERROR
++ ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+ return DRM_ERR(EINVAL);
+ }
+ break;
+@@ -726,18 +728,18 @@ static int savage_dispatch_vb_idx(drm_sa
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+- vtx_size = 8; /* full vertex */
++ vtx_size = 8; /* full vertex */
+ } else {
+ if (skip > SAVAGE_SKIP_ALL_S4) {
+ DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+ return DRM_ERR(EINVAL);
+ }
+- vtx_size = 10; /* full vertex */
++ vtx_size = 10; /* full vertex */
+ }
+
+ vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+- (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+- (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
++ (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
++ (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+ if (vtx_size > vb_stride) {
+ DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+@@ -753,11 +755,11 @@ static int savage_dispatch_vb_idx(drm_sa
+ uint16_t idx[255];
+
+ /* Copy and check indices */
+- DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count*2);
++ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2);
+ for (i = 0; i < count; ++i) {
+- if (idx[i] > vb_size / (vb_stride*4)) {
++ if (idx[i] > vb_size / (vb_stride * 4)) {
+ DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+- i, idx[i], vb_size / (vb_stride*4));
++ i, idx[i], vb_size / (vb_stride * 4));
+ return DRM_ERR(EINVAL);
+ }
+ }
+@@ -766,25 +768,25 @@ static int savage_dispatch_vb_idx(drm_sa
+ /* Need to reorder vertices for correct flat
+ * shading while preserving the clock sense
+ * for correct culling. Only on Savage3D. */
+- int reorder[3] = {2, -1, -1};
++ int reorder[3] = { 2, -1, -1 };
+
+- BEGIN_DMA(count*vtx_size+1);
++ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = 0; i < count; ++i) {
+ unsigned int j = idx[i + reorder[i % 3]];
+- DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],
++ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
+ vtx_size);
+ }
+
+ DMA_COMMIT();
+ } else {
+- BEGIN_DMA(count*vtx_size+1);
++ BEGIN_DMA(count * vtx_size + 1);
+ DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+ for (i = 0; i < count; ++i) {
+ unsigned int j = idx[i];
+- DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],
++ DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
+ vtx_size);
+ }
+
+@@ -800,11 +802,11 @@ static int savage_dispatch_vb_idx(drm_sa
+ return 0;
+ }
+
+-static int savage_dispatch_clear(drm_savage_private_t *dev_priv,
+- const drm_savage_cmd_header_t *cmd_header,
+- const drm_savage_cmd_header_t __user *data,
++static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
++ const drm_savage_cmd_header_t * cmd_header,
++ const drm_savage_cmd_header_t __user * data,
+ unsigned int nbox,
+- const drm_clip_rect_t __user *usr_boxes)
++ const drm_clip_rect_t __user * usr_boxes)
+ {
+ unsigned int flags = cmd_header->clear0.flags, mask, value;
+ unsigned int clear_cmd;
+@@ -814,18 +816,15 @@ static int savage_dispatch_clear(drm_sav
+ if (nbox == 0)
+ return 0;
+
+- DRM_GET_USER_UNCHECKED(mask, &((const drm_savage_cmd_header_t*)data)
+- ->clear1.mask);
+- DRM_GET_USER_UNCHECKED(value, &((const drm_savage_cmd_header_t*)data)
+- ->clear1.value);
++ DRM_GET_USER_UNCHECKED(mask, &data->clear1.mask);
++ DRM_GET_USER_UNCHECKED(value, &data->clear1.value);
+
+ clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+- BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;
+- BCI_CMD_SET_ROP(clear_cmd,0xCC);
++ BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;
++ BCI_CMD_SET_ROP(clear_cmd, 0xCC);
+
+ nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) +
+- ((flags & SAVAGE_BACK) ? 1 : 0) +
+- ((flags & SAVAGE_DEPTH) ? 1 : 0);
++ ((flags & SAVAGE_BACK) ? 1 : 0) + ((flags & SAVAGE_DEPTH) ? 1 : 0);
+ if (nbufs == 0)
+ return 0;
+
+@@ -844,12 +843,12 @@ static int savage_dispatch_clear(drm_sav
+ x = box.x1, y = box.y1;
+ w = box.x2 - box.x1;
+ h = box.y2 - box.y1;
+- BEGIN_DMA(nbufs*6);
++ BEGIN_DMA(nbufs * 6);
+ for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
+ if (!(flags & buf))
+ continue;
+ DMA_WRITE(clear_cmd);
+- switch(buf) {
++ switch (buf) {
+ case SAVAGE_FRONT:
+ DMA_WRITE(dev_priv->front_offset);
+ DMA_WRITE(dev_priv->front_bd);
+@@ -880,9 +879,9 @@ static int savage_dispatch_clear(drm_sav
+ return 0;
+ }
+
+-static int savage_dispatch_swap(drm_savage_private_t *dev_priv,
++static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
+ unsigned int nbox,
+- const drm_clip_rect_t __user *usr_boxes)
++ const drm_clip_rect_t __user * usr_boxes)
+ {
+ unsigned int swap_cmd;
+ unsigned int i;
+@@ -892,8 +891,8 @@ static int savage_dispatch_swap(drm_sava
+ return 0;
+
+ swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+- BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;
+- BCI_CMD_SET_ROP(swap_cmd,0xCC);
++ BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;
++ BCI_CMD_SET_ROP(swap_cmd, 0xCC);
+
+ for (i = 0; i < nbox; ++i) {
+ drm_clip_rect_t box;
+@@ -905,21 +904,21 @@ static int savage_dispatch_swap(drm_sava
+ DMA_WRITE(dev_priv->back_bd);
+ DMA_WRITE(BCI_X_Y(box.x1, box.y1));
+ DMA_WRITE(BCI_X_Y(box.x1, box.y1));
+- DMA_WRITE(BCI_W_H(box.x2-box.x1, box.y2-box.y1));
++ DMA_WRITE(BCI_W_H(box.x2 - box.x1, box.y2 - box.y1));
+ DMA_COMMIT();
+ }
+
+ return 0;
+ }
+
+-static int savage_dispatch_draw(drm_savage_private_t *dev_priv,
+- const drm_savage_cmd_header_t __user *start,
+- const drm_savage_cmd_header_t __user *end,
+- const drm_buf_t *dmabuf,
+- const unsigned int __user *usr_vtxbuf,
++static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
++ const drm_savage_cmd_header_t __user * start,
++ const drm_savage_cmd_header_t __user * end,
++ const drm_buf_t * dmabuf,
++ const unsigned int __user * usr_vtxbuf,
+ unsigned int vb_size, unsigned int vb_stride,
+ unsigned int nbox,
+- const drm_clip_rect_t __user *usr_boxes)
++ const drm_clip_rect_t __user * usr_boxes)
+ {
+ unsigned int i, j;
+ int ret;
+@@ -938,32 +937,42 @@ static int savage_dispatch_draw(drm_sava
+ usr_cmdbuf++;
+ switch (cmd_header.cmd.cmd) {
+ case SAVAGE_CMD_DMA_PRIM:
+- ret = savage_dispatch_dma_prim(
+- dev_priv, &cmd_header, dmabuf);
++ ret =
++ savage_dispatch_dma_prim(dev_priv,
++ &cmd_header,
++ dmabuf);
+ break;
+ case SAVAGE_CMD_VB_PRIM:
+- ret = savage_dispatch_vb_prim(
+- dev_priv, &cmd_header,
+- (const uint32_t __user *)usr_vtxbuf,
+- vb_size, vb_stride);
++ ret =
++ savage_dispatch_vb_prim(dev_priv,
++ &cmd_header,
++ (const uint32_t
++ __user *)
++ usr_vtxbuf, vb_size,
++ vb_stride);
+ break;
+ case SAVAGE_CMD_DMA_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ /* j was check in savage_bci_cmdbuf */
+- ret = savage_dispatch_dma_idx(
+- dev_priv, &cmd_header,
+- (const uint16_t __user *)usr_cmdbuf,
+- dmabuf);
++ ret =
++ savage_dispatch_dma_idx(dev_priv,
++ &cmd_header,
++ (const uint16_t
++ __user *)
++ usr_cmdbuf, dmabuf);
+ usr_cmdbuf += j;
+ break;
+ case SAVAGE_CMD_VB_IDX:
+ j = (cmd_header.idx.count + 3) / 4;
+ /* j was check in savage_bci_cmdbuf */
+- ret = savage_dispatch_vb_idx(
+- dev_priv, &cmd_header,
+- (const uint16_t __user *)usr_cmdbuf,
+- (const uint32_t __user *)usr_vtxbuf,
+- vb_size, vb_stride);
++ ret =
++ savage_dispatch_vb_idx(dev_priv,
++ &cmd_header,
++ (const uint16_t
++ __user *)usr_cmdbuf,
++ (const uint32_t
++ __user *)usr_vtxbuf,
++ vb_size, vb_stride);
+ usr_cmdbuf += j;
+ break;
+ default:
+@@ -997,16 +1006,17 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+ int ret = 0;
+
+ DRM_DEBUG("\n");
+-
++
+ LOCK_TEST_WITH_RETURN(dev, filp);
+
+- DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *)data,
++ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *) data,
+ sizeof(cmdbuf));
+
+ if (dma && dma->buflist) {
+ if (cmdbuf.dma_idx > dma->buf_count) {
+- DRM_ERROR("vertex buffer index %u out of range (0-%u)\n",
+- cmdbuf.dma_idx, dma->buf_count-1);
++ DRM_ERROR
++ ("vertex buffer index %u out of range (0-%u)\n",
++ cmdbuf.dma_idx, dma->buf_count - 1);
+ return DRM_ERR(EINVAL);
+ }
+ dmabuf = dma->buflist[cmdbuf.dma_idx];
+@@ -1014,14 +1024,14 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+ dmabuf = NULL;
+ }
+
+- usr_cmdbuf = (drm_savage_cmd_header_t __user *)cmdbuf.cmd_addr;
++ usr_cmdbuf = (drm_savage_cmd_header_t __user *) cmdbuf.cmd_addr;
+ usr_vtxbuf = (unsigned int __user *)cmdbuf.vb_addr;
+- usr_boxes = (drm_clip_rect_t __user *)cmdbuf.box_addr;
+- if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size*8)) ||
+- (cmdbuf.vb_size && DRM_VERIFYAREA_READ(
+- usr_vtxbuf, cmdbuf.vb_size)) ||
+- (cmdbuf.nbox && DRM_VERIFYAREA_READ(
+- usr_boxes, cmdbuf.nbox*sizeof(drm_clip_rect_t))))
++ usr_boxes = (drm_clip_rect_t __user *) cmdbuf.box_addr;
++ if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size * 8)) ||
++ (cmdbuf.vb_size && DRM_VERIFYAREA_READ(usr_vtxbuf, cmdbuf.vb_size))
++ || (cmdbuf.nbox
++ && DRM_VERIFYAREA_READ(usr_boxes,
++ cmdbuf.nbox * sizeof(drm_clip_rect_t))))
+ return DRM_ERR(EFAULT);
+
+ /* Make sure writes to DMA buffers are finished before sending
+@@ -1058,17 +1068,21 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+ case SAVAGE_CMD_DMA_PRIM:
+ case SAVAGE_CMD_VB_PRIM:
+ if (!first_draw_cmd)
+- first_draw_cmd = usr_cmdbuf-1;
++ first_draw_cmd = usr_cmdbuf - 1;
+ usr_cmdbuf += j;
+ i += j;
+ break;
+ default:
+ if (first_draw_cmd) {
+- ret = savage_dispatch_draw (
+- dev_priv, first_draw_cmd, usr_cmdbuf-1,
+- dmabuf, usr_vtxbuf, cmdbuf.vb_size,
+- cmdbuf.vb_stride,
+- cmdbuf.nbox, usr_boxes);
++ ret =
++ savage_dispatch_draw(dev_priv,
++ first_draw_cmd,
++ usr_cmdbuf - 1, dmabuf,
++ usr_vtxbuf,
++ cmdbuf.vb_size,
++ cmdbuf.vb_stride,
++ cmdbuf.nbox,
++ usr_boxes);
+ if (ret != 0)
+ return ret;
+ first_draw_cmd = NULL;
+@@ -1086,9 +1100,9 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+ DMA_FLUSH();
+ return DRM_ERR(EINVAL);
+ }
+- ret = savage_dispatch_state(
+- dev_priv, &cmd_header,
+- (uint32_t __user *)usr_cmdbuf);
++ ret = savage_dispatch_state(dev_priv, &cmd_header,
++ (uint32_t __user *)
++ usr_cmdbuf);
+ usr_cmdbuf += j;
+ i += j;
+ break;
+@@ -1122,10 +1136,11 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+ }
+
+ if (first_draw_cmd) {
+- ret = savage_dispatch_draw (
+- dev_priv, first_draw_cmd, usr_cmdbuf, dmabuf,
+- usr_vtxbuf, cmdbuf.vb_size, cmdbuf.vb_stride,
+- cmdbuf.nbox, usr_boxes);
++ ret =
++ savage_dispatch_draw(dev_priv, first_draw_cmd, usr_cmdbuf,
++ dmabuf, usr_vtxbuf, cmdbuf.vb_size,
++ cmdbuf.vb_stride, cmdbuf.nbox,
++ usr_boxes);
+ if (ret != 0) {
+ DMA_FLUSH();
+ return ret;
+diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
+--- a/drivers/char/drm/sis_drm.h
++++ b/drivers/char/drm/sis_drm.h
+@@ -39,4 +39,4 @@ typedef struct {
+ unsigned int offset, size;
+ } drm_sis_fb_t;
+
+-#endif /* __SIS_DRM_H__ */
++#endif /* __SIS_DRM_H__ */
+diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
+--- a/drivers/char/drm/sis_drv.c
++++ b/drivers/char/drm/sis_drv.c
+@@ -10,11 +10,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -31,31 +31,29 @@
+ #include "sis_drv.h"
+
+ #include "drm_pciids.h"
+-
+-static int postinit( struct drm_device *dev, unsigned long flags )
++
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -63,9 +61,6 @@ static struct pci_device_id pciidlist[]
+ sisdrv_PCI_IDS
+ };
+
+-extern drm_ioctl_desc_t sis_ioctls[];
+-extern int sis_max_ioctl;
+-
+ static struct drm_driver driver = {
+ .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
+ .context_ctor = sis_init_context,
+@@ -77,18 +72,18 @@ static struct drm_driver driver = {
+ .version = version,
+ .ioctls = sis_ioctls,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
+- },
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
++ },
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init sis_init(void)
+@@ -105,6 +100,6 @@ static void __exit sis_exit(void)
+ module_init(sis_init);
+ module_exit(sis_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
+--- a/drivers/char/drm/sis_drv.h
++++ b/drivers/char/drm/sis_drv.h
+@@ -10,11 +10,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -22,7 +22,7 @@
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+- *
++ *
+ */
+
+ #ifndef _SIS_DRV_H_
+@@ -46,7 +46,10 @@ typedef struct drm_sis_private {
+ memHeap_t *FBHeap;
+ } drm_sis_private_t;
+
+-extern int sis_init_context(drm_device_t *dev, int context);
+-extern int sis_final_context(drm_device_t *dev, int context);
++extern int sis_init_context(drm_device_t * dev, int context);
++extern int sis_final_context(drm_device_t * dev, int context);
++
++extern drm_ioctl_desc_t sis_ioctls[];
++extern int sis_max_ioctl;
+
+ #endif
+diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
+--- a/drivers/char/drm/sis_ds.c
++++ b/drivers/char/drm/sis_ds.c
+@@ -10,11 +10,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -22,10 +22,10 @@
+ * 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.
+- *
++ *
+ * Authors:
+ * Sung-Ching Lin <sclin at sis.com.tw>
+- *
++ *
+ */
+
+ #include "drmP.h"
+@@ -41,13 +41,13 @@ set_t *setInit(void)
+ int i;
+ set_t *set;
+
+- set = (set_t *)drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
++ set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
+ if (set != NULL) {
+ for (i = 0; i < SET_SIZE; i++) {
+- set->list[i].free_next = i + 1;
++ set->list[i].free_next = i + 1;
+ set->list[i].alloc_next = -1;
+ }
+- set->list[SET_SIZE-1].free_next = -1;
++ set->list[SET_SIZE - 1].free_next = -1;
+ set->free = 0;
+ set->alloc = -1;
+ set->trace = -1;
+@@ -55,10 +55,10 @@ set_t *setInit(void)
+ return set;
+ }
+
+-int setAdd(set_t *set, ITEM_TYPE item)
++int setAdd(set_t * set, ITEM_TYPE item)
+ {
+ int free = set->free;
+-
++
+ if (free != -1) {
+ set->list[free].val = item;
+ set->free = set->list[free].free_next;
+@@ -67,16 +67,16 @@ int setAdd(set_t *set, ITEM_TYPE item)
+ }
+
+ set->list[free].alloc_next = set->alloc;
+- set->alloc = free;
+- set->list[free].free_next = -1;
++ set->alloc = free;
++ set->list[free].free_next = -1;
+
+ return 1;
+ }
+
+-int setDel(set_t *set, ITEM_TYPE item)
++int setDel(set_t * set, ITEM_TYPE item)
+ {
+ int alloc = set->alloc;
+- int prev = -1;
++ int prev = -1;
+
+ while (alloc != -1) {
+ if (set->list[alloc].val == item) {
+@@ -103,7 +103,7 @@ int setDel(set_t *set, ITEM_TYPE item)
+
+ /* setFirst -> setAdd -> setNext is wrong */
+
+-int setFirst(set_t *set, ITEM_TYPE *item)
++int setFirst(set_t * set, ITEM_TYPE * item)
+ {
+ if (set->alloc == -1)
+ return 0;
+@@ -114,7 +114,7 @@ int setFirst(set_t *set, ITEM_TYPE *item
+ return 1;
+ }
+
+-int setNext(set_t *set, ITEM_TYPE *item)
++int setNext(set_t * set, ITEM_TYPE * item)
+ {
+ if (set->trace == -1)
+ return 0;
+@@ -125,7 +125,7 @@ int setNext(set_t *set, ITEM_TYPE *item)
+ return 1;
+ }
+
+-int setDestroy(set_t *set)
++int setDestroy(set_t * set)
+ {
+ drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
+
+@@ -149,35 +149,34 @@ int setDestroy(set_t *set)
+ * 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
+- * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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
++ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
++ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
++ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+ #define ISFREE(bptr) ((bptr)->free)
+
+-memHeap_t *mmInit(int ofs,
+- int size)
++memHeap_t *mmInit(int ofs, int size)
+ {
+ PMemBlock blocks;
+
+ if (size <= 0)
+ return NULL;
+
+- blocks = (TMemBlock *)drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
++ blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
+ if (blocks != NULL) {
+ blocks->ofs = ofs;
+ blocks->size = size;
+ blocks->free = 1;
+- return (memHeap_t *)blocks;
++ return (memHeap_t *) blocks;
+ } else
+ return NULL;
+ }
+
+ /* Checks if a pointer 'b' is part of the heap 'heap' */
+-int mmBlockInHeap(memHeap_t *heap, PMemBlock b)
++int mmBlockInHeap(memHeap_t * heap, PMemBlock b)
+ {
+ TMemBlock *p;
+
+@@ -194,16 +193,16 @@ int mmBlockInHeap(memHeap_t *heap, PMemB
+ return 0;
+ }
+
+-static TMemBlock* SliceBlock(TMemBlock *p,
+- int startofs, int size,
++static TMemBlock *SliceBlock(TMemBlock * p,
++ int startofs, int size,
+ int reserved, int alignment)
+ {
+ TMemBlock *newblock;
+
+ /* break left */
+ if (startofs > p->ofs) {
+- newblock = (TMemBlock*) drm_calloc(1, sizeof(TMemBlock),
+- DRM_MEM_DRIVER);
++ newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
++ DRM_MEM_DRIVER);
+ newblock->ofs = startofs;
+ newblock->size = p->size - (startofs - p->ofs);
+ newblock->free = 1;
+@@ -215,8 +214,8 @@ static TMemBlock* SliceBlock(TMemBlock *
+
+ /* break right */
+ if (size < p->size) {
+- newblock = (TMemBlock*) drm_calloc(1, sizeof(TMemBlock),
+- DRM_MEM_DRIVER);
++ newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
++ DRM_MEM_DRIVER);
+ newblock->ofs = startofs + size;
+ newblock->size = p->size - size;
+ newblock->free = 1;
+@@ -232,37 +231,37 @@ static TMemBlock* SliceBlock(TMemBlock *
+ return p;
+ }
+
+-PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
++PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
+ {
+- int mask,startofs, endofs;
++ int mask, startofs, endofs;
+ TMemBlock *p;
+-
++
+ if (heap == NULL || align2 < 0 || size <= 0)
+ return NULL;
+
+- mask = (1 << align2)-1;
++ mask = (1 << align2) - 1;
+ startofs = 0;
+- p = (TMemBlock *)heap;
++ p = (TMemBlock *) heap;
+ while (p != NULL) {
+ if (ISFREE(p)) {
+ startofs = (p->ofs + mask) & ~mask;
+- if ( startofs < startSearch ) {
++ if (startofs < startSearch) {
+ startofs = startSearch;
+ }
+- endofs = startofs+size;
+- if (endofs <= (p->ofs+p->size))
++ endofs = startofs + size;
++ if (endofs <= (p->ofs + p->size))
+ break;
+ }
+ p = p->next;
+ }
+ if (p == NULL)
+ return NULL;
+- p = SliceBlock(p,startofs,size,0,mask+1);
++ p = SliceBlock(p, startofs, size, 0, mask + 1);
+ p->heap = heap;
+ return p;
+ }
+
+-static __inline__ int Join2Blocks(TMemBlock *p)
++static __inline__ int Join2Blocks(TMemBlock * p)
+ {
+ if (p->free && p->next && p->next->free) {
+ TMemBlock *q = p->next;
+@@ -295,7 +294,6 @@ int mmFreeMem(PMemBlock b)
+ p->free = 1;
+ Join2Blocks(p);
+ if (prev)
+- Join2Blocks(prev);
++ Join2Blocks(prev);
+ return 0;
+ }
+-
+diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
+--- a/drivers/char/drm/sis_ds.h
++++ b/drivers/char/drm/sis_ds.h
+@@ -10,11 +10,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -22,10 +22,10 @@
+ * 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.
+- *
++ *
+ * Authors:
+ * Sung-Ching Lin <sclin at sis.com.tw>
+- *
++ *
+ */
+
+ #ifndef __SIS_DS_H__
+@@ -50,11 +50,11 @@ typedef struct {
+ } set_t;
+
+ set_t *setInit(void);
+-int setAdd(set_t *set, ITEM_TYPE item);
+-int setDel(set_t *set, ITEM_TYPE item);
+-int setFirst(set_t *set, ITEM_TYPE *item);
+-int setNext(set_t *set, ITEM_TYPE *item);
+-int setDestroy(set_t *set);
++int setAdd(set_t * set, ITEM_TYPE item);
++int setDel(set_t * set, ITEM_TYPE item);
++int setFirst(set_t * set, ITEM_TYPE * item);
++int setNext(set_t * set, ITEM_TYPE * item);
++int setDestroy(set_t * set);
+
+ /*
+ * GLX Hardware Device Driver common code
+@@ -73,9 +73,9 @@ int setDestroy(set_t *set);
+ * 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
+- * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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
++ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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.
+ *
+ */
+@@ -83,7 +83,7 @@ int setDestroy(set_t *set);
+ struct mem_block_t {
+ struct mem_block_t *next;
+ struct mem_block_t *heap;
+- int ofs,size;
++ int ofs, size;
+ int align;
+ unsigned int free:1;
+ unsigned int reserved:1;
+@@ -109,11 +109,11 @@ static __inline__ void mmMarkReserved(PM
+ b->reserved = 1;
+ }
+
+-/*
++/*
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+-memHeap_t *mmInit( int ofs, int size );
++memHeap_t *mmInit(int ofs, int size);
+
+ /*
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+@@ -125,21 +125,21 @@ memHeap_t *mmInit( int ofs, int size );
+ * startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+-PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch );
++PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch);
+
+ /*
+ * Returns 1 if the block 'b' is part of the heap 'heap'
+ */
+-int mmBlockInHeap( PMemBlock heap, PMemBlock b );
++int mmBlockInHeap(PMemBlock heap, PMemBlock b);
+
+ /*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+-int mmFreeMem( PMemBlock b );
++int mmFreeMem(PMemBlock b);
+
+ /* For debuging purpose. */
+-void mmDumpMemInfo( memHeap_t *mmInit );
++void mmDumpMemInfo(memHeap_t * mmInit);
+
+-#endif /* __SIS_DS_H__ */
++#endif /* __SIS_DS_H__ */
+diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
+--- a/drivers/char/drm/sis_mm.c
++++ b/drivers/char/drm/sis_mm.c
+@@ -10,11 +10,11 @@
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+- *
++ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+- *
++ *
+ * 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
+@@ -22,10 +22,10 @@
+ * 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.
+- *
++ *
+ * Authors:
+ * Sung-Ching Lin <sclin at sis.com.tw>
+- *
++ *
+ */
+
+ #include "drmP.h"
+@@ -37,25 +37,23 @@
+ #endif
+
+ #define MAX_CONTEXT 100
+-#define VIDEO_TYPE 0
++#define VIDEO_TYPE 0
+ #define AGP_TYPE 1
+
+ typedef struct {
+ int used;
+ int context;
+- set_t *sets[2]; /* 0 for video, 1 for AGP */
++ set_t *sets[2]; /* 0 for video, 1 for AGP */
+ } sis_context_t;
+
+ static sis_context_t global_ppriv[MAX_CONTEXT];
+
+-
+ static int add_alloc_set(int context, int type, unsigned int val)
+ {
+ int i, retval = 0;
+-
++
+ for (i = 0; i < MAX_CONTEXT; i++) {
+- if (global_ppriv[i].used && global_ppriv[i].context == context)
+- {
++ if (global_ppriv[i].used && global_ppriv[i].context == context) {
+ retval = setAdd(global_ppriv[i].sets[type], val);
+ break;
+ }
+@@ -64,12 +62,11 @@ static int add_alloc_set(int context, in
+ }
+
+ static int del_alloc_set(int context, int type, unsigned int val)
+-{
++{
+ int i, retval = 0;
+
+ for (i = 0; i < MAX_CONTEXT; i++) {
+- if (global_ppriv[i].used && global_ppriv[i].context == context)
+- {
++ if (global_ppriv[i].used && global_ppriv[i].context == context) {
+ retval = setDel(global_ppriv[i].sets[type], val);
+ break;
+ }
+@@ -77,15 +74,15 @@ static int del_alloc_set(int context, in
+ return retval;
+ }
+
+-/* fb management via fb device */
++/* fb management via fb device */
+ #if defined(__linux__) && defined(CONFIG_FB_SIS)
+
+-static int sis_fb_init( DRM_IOCTL_ARGS )
++static int sis_fb_init(DRM_IOCTL_ARGS)
+ {
+ return 0;
+ }
+
+-static int sis_fb_alloc( DRM_IOCTL_ARGS )
++static int sis_fb_alloc(DRM_IOCTL_ARGS)
+ {
+ drm_sis_mem_t fb;
+ struct sis_memreq req;
+@@ -105,7 +102,7 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS
+ sis_free(req.offset);
+ retval = DRM_ERR(EINVAL);
+ }
+- } else {
++ } else {
+ fb.offset = 0;
+ fb.size = 0;
+ fb.free = 0;
+@@ -118,19 +115,19 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS
+ return retval;
+ }
+
+-static int sis_fb_free( DRM_IOCTL_ARGS )
++static int sis_fb_free(DRM_IOCTL_ARGS)
+ {
+ drm_sis_mem_t fb;
+ int retval = 0;
+
+- DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
++ DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
+
+ if (!fb.free)
+ return DRM_ERR(EINVAL);
+
+ if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
+ retval = DRM_ERR(EINVAL);
+- sis_free((u32)fb.free);
++ sis_free((u32) fb.free);
+
+ DRM_DEBUG("free fb, offset = %lu\n", fb.free);
+
+@@ -149,17 +146,17 @@ static int sis_fb_free( DRM_IOCTL_ARGS )
+ * X driver/sisfb HW- Command-
+ * framebuffer memory DRI heap Cursor queue
+ */
+-static int sis_fb_init( DRM_IOCTL_ARGS )
++static int sis_fb_init(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_sis_private_t *dev_priv = dev->dev_private;
+ drm_sis_fb_t fb;
+
+- DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *)data, sizeof(fb));
++ DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
+
+ if (dev_priv == NULL) {
+ dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
+- DRM_MEM_DRIVER);
++ DRM_MEM_DRIVER);
+ dev_priv = dev->dev_private;
+ if (dev_priv == NULL)
+ return ENOMEM;
+@@ -175,7 +172,7 @@ static int sis_fb_init( DRM_IOCTL_ARGS )
+ return 0;
+ }
+
+-static int sis_fb_alloc( DRM_IOCTL_ARGS )
++static int sis_fb_alloc(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_sis_private_t *dev_priv = dev->dev_private;
+@@ -186,9 +183,9 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS
+
+ if (dev_priv == NULL || dev_priv->FBHeap == NULL)
+ return DRM_ERR(EINVAL);
+-
++
+ DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
+-
++
+ block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
+ if (block) {
+ /* TODO */
+@@ -196,7 +193,7 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS
+ fb.free = (unsigned long)block;
+ if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
+ DRM_DEBUG("adding to allocation set fails\n");
+- mmFreeMem((PMemBlock)fb.free);
++ mmFreeMem((PMemBlock) fb.free);
+ retval = DRM_ERR(EINVAL);
+ }
+ } else {
+@@ -212,7 +209,7 @@ static int sis_fb_alloc( DRM_IOCTL_ARGS
+ return retval;
+ }
+
+-static int sis_fb_free( DRM_IOCTL_ARGS )
++static int sis_fb_free(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_sis_private_t *dev_priv = dev->dev_private;
+@@ -221,14 +218,14 @@ static int sis_fb_free( DRM_IOCTL_ARGS )
+ if (dev_priv == NULL || dev_priv->FBHeap == NULL)
+ return DRM_ERR(EINVAL);
+
+- DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
++ DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
+
+- if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free))
++ if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
+ return DRM_ERR(EINVAL);
+
+ if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
+ return DRM_ERR(EINVAL);
+- mmFreeMem((PMemBlock)fb.free);
++ mmFreeMem((PMemBlock) fb.free);
+
+ DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
+
+@@ -237,9 +234,9 @@ static int sis_fb_free( DRM_IOCTL_ARGS )
+
+ #endif
+
+-/* agp memory management */
++/* agp memory management */
+
+-static int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
++static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_sis_private_t *dev_priv = dev->dev_private;
+@@ -247,7 +244,7 @@ static int sis_ioctl_agp_init( DRM_IOCTL
+
+ if (dev_priv == NULL) {
+ dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
+- DRM_MEM_DRIVER);
++ DRM_MEM_DRIVER);
+ dev_priv = dev->dev_private;
+ if (dev_priv == NULL)
+ return ENOMEM;
+@@ -256,16 +253,17 @@ static int sis_ioctl_agp_init( DRM_IOCTL
+ if (dev_priv->AGPHeap != NULL)
+ return DRM_ERR(EINVAL);
+
+- DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *)data, sizeof(agp));
++ DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
++ sizeof(agp));
+
+ dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
+
+ DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+-
++
+ return 0;
+ }
+
+-static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
++static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_sis_private_t *dev_priv = dev->dev_private;
+@@ -273,12 +271,12 @@ static int sis_ioctl_agp_alloc( DRM_IOCT
+ drm_sis_mem_t agp;
+ PMemBlock block;
+ int retval = 0;
+-
++
+ if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
+ return DRM_ERR(EINVAL);
+-
++
+ DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
+-
++
+ block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
+ if (block) {
+ /* TODO */
+@@ -286,10 +284,10 @@ static int sis_ioctl_agp_alloc( DRM_IOCT
+ agp.free = (unsigned long)block;
+ if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
+ DRM_DEBUG("adding to allocation set fails\n");
+- mmFreeMem((PMemBlock)agp.free);
++ mmFreeMem((PMemBlock) agp.free);
+ retval = -1;
+ }
+- } else {
++ } else {
+ agp.offset = 0;
+ agp.size = 0;
+ agp.free = 0;
+@@ -302,7 +300,7 @@ static int sis_ioctl_agp_alloc( DRM_IOCT
+ return retval;
+ }
+
+-static int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
++static int sis_ioctl_agp_free(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_sis_private_t *dev_priv = dev->dev_private;
+@@ -311,12 +309,13 @@ static int sis_ioctl_agp_free( DRM_IOCTL
+ if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
+ return DRM_ERR(EINVAL);
+
+- DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *)data, sizeof(agp));
++ DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data,
++ sizeof(agp));
+
+- if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free))
++ if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free))
+ return DRM_ERR(EINVAL);
+
+- mmFreeMem((PMemBlock)agp.free);
++ mmFreeMem((PMemBlock) agp.free);
+ if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
+ return DRM_ERR(EINVAL);
+
+@@ -329,31 +328,30 @@ int sis_init_context(struct drm_device *
+ {
+ int i;
+
+- for (i = 0; i < MAX_CONTEXT ; i++) {
++ for (i = 0; i < MAX_CONTEXT; i++) {
+ if (global_ppriv[i].used &&
+ (global_ppriv[i].context == context))
+ break;
+ }
+
+ if (i >= MAX_CONTEXT) {
+- for (i = 0; i < MAX_CONTEXT ; i++) {
++ for (i = 0; i < MAX_CONTEXT; i++) {
+ if (!global_ppriv[i].used) {
+ global_ppriv[i].context = context;
+ global_ppriv[i].used = 1;
+ global_ppriv[i].sets[0] = setInit();
+ global_ppriv[i].sets[1] = setInit();
+ DRM_DEBUG("init allocation set, socket=%d, "
+- "context = %d\n", i, context);
++ "context = %d\n", i, context);
+ break;
+ }
+ }
+ if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+- (global_ppriv[i].sets[1] == NULL))
+- {
++ (global_ppriv[i].sets[1] == NULL)) {
+ return 0;
+ }
+ }
+-
++
+ return 1;
+ }
+
+@@ -361,7 +359,7 @@ int sis_final_context(struct drm_device
+ {
+ int i;
+
+- for (i=0; i<MAX_CONTEXT; i++) {
++ for (i = 0; i < MAX_CONTEXT; i++) {
+ if (global_ppriv[i].used &&
+ (global_ppriv[i].context == context))
+ break;
+@@ -382,7 +380,7 @@ int sis_final_context(struct drm_device
+ #if defined(__linux__) && defined(CONFIG_FB_SIS)
+ sis_free(item);
+ #else
+- mmFreeMem((PMemBlock)item);
++ mmFreeMem((PMemBlock) item);
+ #endif
+ retval = setNext(set, &item);
+ }
+@@ -393,25 +391,24 @@ int sis_final_context(struct drm_device
+ retval = setFirst(set, &item);
+ while (retval) {
+ DRM_DEBUG("free agp memory 0x%x\n", item);
+- mmFreeMem((PMemBlock)item);
++ mmFreeMem((PMemBlock) item);
+ retval = setNext(set, &item);
+ }
+ setDestroy(set);
+
+- global_ppriv[i].used = 0;
+- }
+-
++ global_ppriv[i].used = 0;
++ }
++
+ return 1;
+ }
+
+ drm_ioctl_desc_t sis_ioctls[] = {
+- [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = { sis_fb_alloc, 1, 0 },
+- [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = { sis_fb_free, 1, 0 },
+- [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = { sis_ioctl_agp_init, 1, 1 },
+- [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = { sis_ioctl_agp_alloc, 1, 0 },
+- [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = { sis_ioctl_agp_free, 1, 0 },
+- [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = { sis_fb_init, 1, 1 }
++ [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, 1, 0},
++ [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, 1, 0},
++ [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, 1, 1},
++ [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, 1, 0},
++ [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, 1, 0},
++ [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, 1, 1}
+ };
+
+ int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
+-
+diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
+--- a/drivers/char/drm/tdfx_drv.c
++++ b/drivers/char/drm/tdfx_drv.c
+@@ -36,30 +36,28 @@
+
+ #include "drm_pciids.h"
+
+-static int postinit( struct drm_device *dev, unsigned long flags )
++static int postinit(struct drm_device *dev, unsigned long flags)
+ {
+- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
+- DRIVER_NAME,
+- DRIVER_MAJOR,
+- DRIVER_MINOR,
+- DRIVER_PATCHLEVEL,
+- DRIVER_DATE,
+- dev->primary.minor,
+- pci_pretty_name(dev->pdev)
+- );
++ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
++ DRIVER_NAME,
++ DRIVER_MAJOR,
++ DRIVER_MINOR,
++ DRIVER_PATCHLEVEL,
++ DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
++ );
+ return 0;
+ }
+
+-static int version( drm_version_t *version )
++static int version(drm_version_t * version)
+ {
+ int len;
+
+ version->version_major = DRIVER_MAJOR;
+ version->version_minor = DRIVER_MINOR;
+ version->version_patchlevel = DRIVER_PATCHLEVEL;
+- DRM_COPY( version->name, DRIVER_NAME );
+- DRM_COPY( version->date, DRIVER_DATE );
+- DRM_COPY( version->desc, DRIVER_DESC );
++ DRM_COPY(version->name, DRIVER_NAME);
++ DRM_COPY(version->date, DRIVER_DATE);
++ DRM_COPY(version->desc, DRIVER_DESC);
+ return 0;
+ }
+
+@@ -75,18 +73,18 @@ static struct drm_driver driver = {
+ .postinit = postinit,
+ .version = version,
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
+- },
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
++ },
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init tdfx_init(void)
+@@ -102,6 +100,6 @@ static void __exit tdfx_exit(void)
+ module_init(tdfx_init);
+ module_exit(tdfx_exit);
+
+-MODULE_AUTHOR( DRIVER_AUTHOR );
+-MODULE_DESCRIPTION( DRIVER_DESC );
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/char/drm/via_3d_reg.h b/drivers/char/drm/via_3d_reg.h
+--- a/drivers/char/drm/via_3d_reg.h
++++ b/drivers/char/drm/via_3d_reg.h
+@@ -1643,7 +1643,6 @@
+ #define HC_HAGPBpID_STOP 0x00000002
+ #define HC_HAGPBpH_MASK 0x00ffffff
+
+-
+ #define VIA_VIDEO_HEADER5 0xFE040000
+ #define VIA_VIDEO_HEADER6 0xFE050000
+ #define VIA_VIDEO_HEADER7 0xFE060000
+diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
+--- a/drivers/char/drm/via_dma.c
++++ b/drivers/char/drm/via_dma.c
+@@ -1,11 +1,11 @@
+ /* via_dma.c -- DMA support for the VIA Unichrome/Pro
+- *
++ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
+ * All Rights Reserved.
+- *
++ *
+ * Copyright 2004 The Unichrome project.
+ * All Rights Reserved.
+ *
+@@ -23,14 +23,14 @@
+ * 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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
++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+- * Authors:
+- * Tungsten Graphics,
+- * Erdi Chen,
++ * Authors:
++ * Tungsten Graphics,
++ * Erdi Chen,
+ * Thomas Hellstrom.
+ */
+
+@@ -61,34 +61,31 @@
+ dev_priv->dma_low +=8; \
+ }
+
+-#define via_flush_write_combine() DRM_MEMORYBARRIER()
++#define via_flush_write_combine() DRM_MEMORYBARRIER()
+
+ #define VIA_OUT_RING_QW(w1,w2) \
+ *vb++ = (w1); \
+ *vb++ = (w2); \
+- dev_priv->dma_low += 8;
++ dev_priv->dma_low += 8;
+
+ static void via_cmdbuf_start(drm_via_private_t * dev_priv);
+ static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
+ static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
+ static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
+ static int via_wait_idle(drm_via_private_t * dev_priv);
+-static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
+-
++static void via_pad_cache(drm_via_private_t * dev_priv, int qwords);
+
+ /*
+ * Free space in command buffer.
+ */
+
+-static uint32_t
+-via_cmdbuf_space(drm_via_private_t *dev_priv)
++static uint32_t via_cmdbuf_space(drm_via_private_t * dev_priv)
+ {
+- uint32_t agp_base = dev_priv->dma_offset +
+- (uint32_t) dev_priv->agpAddr;
++ uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+-
+- return ((hw_addr <= dev_priv->dma_low) ?
+- (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
++
++ return ((hw_addr <= dev_priv->dma_low) ?
++ (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
+ (hw_addr - dev_priv->dma_low));
+ }
+
+@@ -96,15 +93,13 @@ via_cmdbuf_space(drm_via_private_t *dev_
+ * How much does the command regulator lag behind?
+ */
+
+-static uint32_t
+-via_cmdbuf_lag(drm_via_private_t *dev_priv)
++static uint32_t via_cmdbuf_lag(drm_via_private_t * dev_priv)
+ {
+- uint32_t agp_base = dev_priv->dma_offset +
+- (uint32_t) dev_priv->agpAddr;
++ uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+-
+- return ((hw_addr <= dev_priv->dma_low) ?
+- (dev_priv->dma_low - hw_addr) :
++
++ return ((hw_addr <= dev_priv->dma_low) ?
++ (dev_priv->dma_low - hw_addr) :
+ (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
+ }
+
+@@ -121,20 +116,20 @@ via_cmdbuf_wait(drm_via_private_t * dev_
+ uint32_t count;
+ hw_addr_ptr = dev_priv->hw_addr_ptr;
+ cur_addr = dev_priv->dma_low;
+- next_addr = cur_addr + size + 512*1024;
++ next_addr = cur_addr + size + 512 * 1024;
+ count = 1000000;
+ do {
+- hw_addr = *hw_addr_ptr - agp_base;
++ hw_addr = *hw_addr_ptr - agp_base;
+ if (count-- == 0) {
+- DRM_ERROR("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
+- hw_addr, cur_addr, next_addr);
++ DRM_ERROR
++ ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
++ hw_addr, cur_addr, next_addr);
+ return -1;
+ }
+ } while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
+ return 0;
+ }
+
+-
+ /*
+ * Checks whether buffer head has reach the end. Rewind the ring buffer
+ * when necessary.
+@@ -145,7 +140,8 @@ via_cmdbuf_wait(drm_via_private_t * dev_
+ static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
+ unsigned int size)
+ {
+- if ((dev_priv->dma_low + size + 4*CMDBUF_ALIGNMENT_SIZE) > dev_priv->dma_high) {
++ if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) >
++ dev_priv->dma_high) {
+ via_cmdbuf_rewind(dev_priv);
+ }
+ if (via_cmdbuf_wait(dev_priv, size) != 0) {
+@@ -159,7 +155,7 @@ int via_dma_cleanup(drm_device_t * dev)
+ {
+ if (dev->dev_private) {
+ drm_via_private_t *dev_priv =
+- (drm_via_private_t *) dev->dev_private;
++ (drm_via_private_t *) dev->dev_private;
+
+ if (dev_priv->ring.virtual_start) {
+ via_cmdbuf_reset(dev_priv);
+@@ -189,7 +185,7 @@ static int via_initialize(drm_device_t *
+ }
+
+ if (!dev->agp || !dev->agp->base) {
+- DRM_ERROR("%s called with no agp memory available\n",
++ DRM_ERROR("%s called with no agp memory available\n",
+ __FUNCTION__);
+ return DRM_ERR(EFAULT);
+ }
+@@ -247,10 +243,10 @@ int via_dma_init(DRM_IOCTL_ARGS)
+ else
+ retcode = via_dma_cleanup(dev);
+ break;
+- case VIA_DMA_INITIALIZED:
+- retcode = (dev_priv->ring.virtual_start != NULL) ?
+- 0: DRM_ERR( EFAULT );
+- break;
++ case VIA_DMA_INITIALIZED:
++ retcode = (dev_priv->ring.virtual_start != NULL) ?
++ 0 : DRM_ERR(EFAULT);
++ break;
+ default:
+ retcode = DRM_ERR(EINVAL);
+ break;
+@@ -259,8 +255,6 @@ int via_dma_init(DRM_IOCTL_ARGS)
+ return retcode;
+ }
+
+-
+-
+ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
+ {
+ drm_via_private_t *dev_priv;
+@@ -277,8 +271,7 @@ static int via_dispatch_cmdbuffer(drm_de
+
+ if (cmd->size > VIA_PCI_BUF_SIZE) {
+ return DRM_ERR(ENOMEM);
+- }
+-
++ }
+
+ if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+ return DRM_ERR(EFAULT);
+@@ -289,19 +282,19 @@ static int via_dispatch_cmdbuffer(drm_de
+ * copy it to AGP memory when ready.
+ */
+
+-
+- if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 1))) {
++ if ((ret =
++ via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
++ cmd->size, dev, 1))) {
+ return ret;
+ }
+-
+-
++
+ vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
+ if (vb == NULL) {
+ return DRM_ERR(EAGAIN);
+ }
+
+ memcpy(vb, dev_priv->pci_buf, cmd->size);
+-
++
+ dev_priv->dma_low += cmd->size;
+
+ /*
+@@ -310,7 +303,7 @@ static int via_dispatch_cmdbuffer(drm_de
+ */
+
+ if (cmd->size < 0x100)
+- via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
++ via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3);
+ via_cmdbuf_pause(dev_priv);
+
+ return 0;
+@@ -330,7 +323,7 @@ int via_flush_ioctl(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ return via_driver_dma_quiescent(dev);
+ }
+@@ -341,7 +334,7 @@ int via_cmdbuffer(DRM_IOCTL_ARGS)
+ drm_via_cmdbuffer_t cmdbuf;
+ int ret;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
+ sizeof(cmdbuf));
+@@ -356,8 +349,9 @@ int via_cmdbuffer(DRM_IOCTL_ARGS)
+ return 0;
+ }
+
+-extern int
+-via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size);
++extern int
++via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
++ unsigned int size);
+ static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
+ drm_via_cmdbuffer_t * cmd)
+ {
+@@ -366,15 +360,19 @@ static int via_dispatch_pci_cmdbuffer(dr
+
+ if (cmd->size > VIA_PCI_BUF_SIZE) {
+ return DRM_ERR(ENOMEM);
+- }
++ }
+ if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+ return DRM_ERR(EFAULT);
+-
+- if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 0))) {
++
++ if ((ret =
++ via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
++ cmd->size, dev, 0))) {
+ return ret;
+ }
+-
+- ret = via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, cmd->size);
++
++ ret =
++ via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
++ cmd->size);
+ return ret;
+ }
+
+@@ -384,7 +382,7 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+ drm_via_cmdbuffer_t cmdbuf;
+ int ret;
+
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
+ sizeof(cmdbuf));
+@@ -400,17 +398,15 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+ return 0;
+ }
+
+-
+ static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
+ uint32_t * vb, int qw_count)
+ {
+- for (; qw_count > 0; --qw_count) {
++ for (; qw_count > 0; --qw_count) {
+ VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
+ }
+ return vb;
+ }
+
+-
+ /*
+ * This function is used internally by ring buffer mangement code.
+ *
+@@ -426,7 +422,7 @@ static inline uint32_t *via_get_dma(drm_
+ * modifying the pause address stored in the buffer itself. If
+ * the regulator has already paused, restart it.
+ */
+-static int via_hook_segment(drm_via_private_t *dev_priv,
++static int via_hook_segment(drm_via_private_t * dev_priv,
+ uint32_t pause_addr_hi, uint32_t pause_addr_lo,
+ int no_pci_fire)
+ {
+@@ -434,7 +430,7 @@ static int via_hook_segment(drm_via_priv
+ volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+
+ via_flush_write_combine();
+- while(! *(via_get_dma(dev_priv)-1));
++ while (!*(via_get_dma(dev_priv) - 1)) ;
+ *dev_priv->last_pause_ptr = pause_addr_lo;
+ via_flush_write_combine();
+
+@@ -443,55 +439,53 @@ static int via_hook_segment(drm_via_priv
+ * Not sure it is needed.
+ */
+
+- while(! *dev_priv->last_pause_ptr);
++ while (!*dev_priv->last_pause_ptr) ;
+ dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
+- while(! *dev_priv->last_pause_ptr);
+-
++ while (!*dev_priv->last_pause_ptr) ;
+
+ paused = 0;
+- count = 20;
++ count = 20;
+
+- while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
++ while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ;
+ if ((count <= 8) && (count >= 0)) {
+ uint32_t rgtr, ptr;
+ rgtr = *(dev_priv->hw_addr_ptr);
+- ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+- dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 -
+- CMDBUF_ALIGNMENT_SIZE;
++ ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
++ dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 -
++ CMDBUF_ALIGNMENT_SIZE;
+ if (rgtr <= ptr) {
+- DRM_ERROR("Command regulator\npaused at count %d, address %x, "
+- "while current pause address is %x.\n"
+- "Please mail this message to "
+- "<unichrome-devel at lists.sourceforge.net>\n",
+- count, rgtr, ptr);
++ DRM_ERROR
++ ("Command regulator\npaused at count %d, address %x, "
++ "while current pause address is %x.\n"
++ "Please mail this message to "
++ "<unichrome-devel at lists.sourceforge.net>\n", count,
++ rgtr, ptr);
+ }
+ }
+-
++
+ if (paused && !no_pci_fire) {
+- uint32_t rgtr,ptr;
++ uint32_t rgtr, ptr;
+ uint32_t ptr_low;
+
+ count = 1000000;
+- while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) && count--);
+-
++ while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
++ && count--) ;
++
+ rgtr = *(dev_priv->hw_addr_ptr);
+- ptr = ((char *)paused_at - dev_priv->dma_ptr) +
+- dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+-
++ ptr = ((char *)paused_at - dev_priv->dma_ptr) +
++ dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+- ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ?
+- ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
++ ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
++ ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0;
+ if (rgtr <= ptr && rgtr >= ptr_low) {
+ VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+ VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
+ VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+- }
++ }
+ }
+ return paused;
+ }
+
+-
+-
+ static int via_wait_idle(drm_via_private_t * dev_priv)
+ {
+ int count = 10000000;
+@@ -502,9 +496,8 @@ static int via_wait_idle(drm_via_private
+ }
+
+ static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
+- uint32_t addr, uint32_t *cmd_addr_hi,
+- uint32_t *cmd_addr_lo,
+- int skip_wait)
++ uint32_t addr, uint32_t * cmd_addr_hi,
++ uint32_t * cmd_addr_lo, int skip_wait)
+ {
+ uint32_t agp_base;
+ uint32_t cmd_addr, addr_lo, addr_hi;
+@@ -512,31 +505,26 @@ static uint32_t *via_align_cmd(drm_via_p
+ uint32_t qw_pad_count;
+
+ if (!skip_wait)
+- via_cmdbuf_wait(dev_priv, 2*CMDBUF_ALIGNMENT_SIZE);
++ via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
+
+ vb = via_get_dma(dev_priv);
+- VIA_OUT_RING_QW( HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
+- (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
++ VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
++ (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
+ agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
+- ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
++ ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
+
+-
+- cmd_addr = (addr) ? addr :
+- agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
++ cmd_addr = (addr) ? addr :
++ agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
+ addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
+ (cmd_addr & HC_HAGPBpL_MASK));
+ addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
+
+ vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
+- VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi,
+- *cmd_addr_lo = addr_lo);
++ VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo);
+ return vb;
+ }
+
+-
+-
+-
+ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
+ {
+ uint32_t pause_addr_lo, pause_addr_hi;
+@@ -545,7 +533,6 @@ static void via_cmdbuf_start(drm_via_pri
+ uint32_t command;
+ uint32_t agp_base;
+
+-
+ dev_priv->dma_low = 0;
+
+ agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+@@ -557,12 +544,12 @@ static void via_cmdbuf_start(drm_via_pri
+ command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
+ ((end_addr & 0xff000000) >> 16));
+
+- dev_priv->last_pause_ptr =
+- via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
+- &pause_addr_hi, & pause_addr_lo, 1) - 1;
++ dev_priv->last_pause_ptr =
++ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
++ &pause_addr_hi, &pause_addr_lo, 1) - 1;
+
+ via_flush_write_combine();
+- while(! *dev_priv->last_pause_ptr);
++ while (!*dev_priv->last_pause_ptr) ;
+
+ VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+ VIA_WRITE(VIA_REG_TRANSPACE, command);
+@@ -575,14 +562,14 @@ static void via_cmdbuf_start(drm_via_pri
+ VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
+ }
+
+-static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
++static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
+ {
+ uint32_t *vb;
+
+ via_cmdbuf_wait(dev_priv, qwords + 2);
+ vb = via_get_dma(dev_priv);
+- VIA_OUT_RING_QW( HC_HEADER2, HC_ParaType_NotTex << 16);
+- via_align_buffer(dev_priv,vb,qwords);
++ VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16);
++ via_align_buffer(dev_priv, vb, qwords);
+ }
+
+ static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
+@@ -590,10 +577,9 @@ static inline void via_dummy_bitblt(drm_
+ uint32_t *vb = via_get_dma(dev_priv);
+ SetReg2DAGP(0x0C, (0 | (0 << 16)));
+ SetReg2DAGP(0x10, 0 | (0 << 16));
+- SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
++ SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
+ }
+
+-
+ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
+ {
+ uint32_t agp_base;
+@@ -603,11 +589,10 @@ static void via_cmdbuf_jump(drm_via_priv
+ uint32_t dma_low_save1, dma_low_save2;
+
+ agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+- via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
++ via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
+ &jump_addr_lo, 0);
+-
+- dev_priv->dma_wrap = dev_priv->dma_low;
+
++ dev_priv->dma_wrap = dev_priv->dma_low;
+
+ /*
+ * Wrap command buffer to the beginning.
+@@ -619,11 +604,12 @@ static void via_cmdbuf_jump(drm_via_priv
+ }
+
+ via_dummy_bitblt(dev_priv);
+- via_dummy_bitblt(dev_priv);
++ via_dummy_bitblt(dev_priv);
+
+- last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+- &pause_addr_lo, 0) -1;
+- via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
++ last_pause_ptr =
++ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
++ &pause_addr_lo, 0) - 1;
++ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0);
+
+ *last_pause_ptr = pause_addr_lo;
+@@ -638,23 +624,23 @@ static void via_cmdbuf_jump(drm_via_priv
+ * does not seem to get updated immediately when a jump occurs.
+ */
+
+- last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+- &pause_addr_lo, 0) -1;
+- via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
++ last_pause_ptr =
++ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
++ &pause_addr_lo, 0) - 1;
++ via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+ &pause_addr_lo, 0);
+ *last_pause_ptr = pause_addr_lo;
+
+ dma_low_save2 = dev_priv->dma_low;
+- dev_priv->dma_low = dma_low_save1;
+- via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
++ dev_priv->dma_low = dma_low_save1;
++ via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
+ dev_priv->dma_low = dma_low_save2;
+- via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
++ via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+ }
+
+-
+ static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
+ {
+- via_cmdbuf_jump(dev_priv);
++ via_cmdbuf_jump(dev_priv);
+ }
+
+ static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
+@@ -662,10 +648,9 @@ static void via_cmdbuf_flush(drm_via_pri
+ uint32_t pause_addr_lo, pause_addr_hi;
+
+ via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
+- via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
++ via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+ }
+
+-
+ static void via_cmdbuf_pause(drm_via_private_t * dev_priv)
+ {
+ via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
+@@ -681,8 +666,7 @@ static void via_cmdbuf_reset(drm_via_pri
+ * User interface to the space and lag functions.
+ */
+
+-int
+-via_cmdbuf_size(DRM_IOCTL_ARGS)
++int via_cmdbuf_size(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_via_cmdbuf_size_t d_siz;
+@@ -691,7 +675,7 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
+ drm_via_private_t *dev_priv;
+
+ DRM_DEBUG("via cmdbuf_size\n");
+- LOCK_TEST_WITH_RETURN( dev, filp );
++ LOCK_TEST_WITH_RETURN(dev, filp);
+
+ dev_priv = (drm_via_private_t *) dev->dev_private;
+
+@@ -704,12 +688,12 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
+ DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t __user *) data,
+ sizeof(d_siz));
+
+-
+ count = 1000000;
+ tmp_size = d_siz.size;
+- switch(d_siz.func) {
++ switch (d_siz.func) {
+ case VIA_CMDBUF_SPACE:
+- while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size) && count--) {
++ while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size)
++ && count--) {
+ if (!d_siz.wait) {
+ break;
+ }
+@@ -720,7 +704,8 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
+ }
+ break;
+ case VIA_CMDBUF_LAG:
+- while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size) && count--) {
++ while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size)
++ && count--) {
+ if (!d_siz.wait) {
+ break;
+ }
+diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
+--- a/drivers/char/drm/via_drm.h
++++ b/drivers/char/drm/via_drm.h
+@@ -149,7 +149,7 @@ typedef struct _drm_via_dma_init {
+ enum {
+ VIA_INIT_DMA = 0x01,
+ VIA_CLEANUP_DMA = 0x02,
+- VIA_DMA_INITIALIZED = 0x03
++ VIA_DMA_INITIALIZED = 0x03
+ } func;
+
+ unsigned long offset;
+@@ -212,7 +212,7 @@ typedef enum {
+
+ #define VIA_IRQ_FLAGS_MASK 0xF0000000
+
+-struct drm_via_wait_irq_request{
++struct drm_via_wait_irq_request {
+ unsigned irq;
+ via_irq_seq_type_t type;
+ uint32_t sequence;
+diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
+--- a/drivers/char/drm/via_drv.c
++++ b/drivers/char/drm/via_drv.c
+@@ -93,18 +93,18 @@ static struct drm_driver driver = {
+ .ioctls = ioctls,
+ .num_ioctls = DRM_ARRAY_SIZE(ioctls),
+ .fops = {
+- .owner = THIS_MODULE,
+- .open = drm_open,
+- .release = drm_release,
+- .ioctl = drm_ioctl,
+- .mmap = drm_mmap,
+- .poll = drm_poll,
+- .fasync = drm_fasync,
+- },
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .ioctl = drm_ioctl,
++ .mmap = drm_mmap,
++ .poll = drm_poll,
++ .fasync = drm_fasync,
++ },
+ .pci_driver = {
+- .name = DRIVER_NAME,
+- .id_table = pciidlist,
+- }
++ .name = DRIVER_NAME,
++ .id_table = pciidlist,
++ }
+ };
+
+ static int __init via_init(void)
+diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
+--- a/drivers/char/drm/via_drv.h
++++ b/drivers/char/drm/via_drv.h
+@@ -40,8 +40,6 @@
+ #define VIA_FIRE_BUF_SIZE 1024
+ #define VIA_NUM_IRQS 2
+
+-
+-
+ typedef struct drm_via_ring_buffer {
+ drm_map_t map;
+ char *virtual_start;
+@@ -55,7 +53,7 @@ typedef struct drm_via_irq {
+ uint32_t enable_mask;
+ wait_queue_head_t irq_queue;
+ } drm_via_irq_t;
+-
++
+ typedef struct drm_via_private {
+ drm_via_sarea_t *sarea_priv;
+ drm_map_t *sarea;
+@@ -71,9 +69,9 @@ typedef struct drm_via_private {
+ volatile uint32_t *last_pause_ptr;
+ volatile uint32_t *hw_addr_ptr;
+ drm_via_ring_buffer_t ring;
+- struct timeval last_vblank;
+- int last_vblank_valid;
+- unsigned usec_per_vblank;
++ struct timeval last_vblank;
++ int last_vblank_valid;
++ unsigned usec_per_vblank;
+ drm_via_state_t hc_state;
+ char pci_buf[VIA_PCI_BUF_SIZE];
+ const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
+@@ -82,8 +80,8 @@ typedef struct drm_via_private {
+ drm_via_irq_t via_irqs[VIA_NUM_IRQS];
+ unsigned num_irqs;
+ maskarray_t *irq_masks;
+- uint32_t irq_enable_mask;
+- uint32_t irq_pending_mask;
++ uint32_t irq_enable_mask;
++ uint32_t irq_pending_mask;
+ } drm_via_private_t;
+
+ /* VIA MMIO register access */
+@@ -110,9 +108,11 @@ extern void via_driver_irq_uninstall(drm
+ extern int via_dma_cleanup(drm_device_t * dev);
+ extern void via_init_command_verifier(void);
+ extern int via_driver_dma_quiescent(drm_device_t * dev);
+-extern void via_init_futex(drm_via_private_t *dev_priv);
+-extern void via_cleanup_futex(drm_via_private_t *dev_priv);
+-extern void via_release_futex(drm_via_private_t *dev_priv, int context);
++extern void via_init_futex(drm_via_private_t * dev_priv);
++extern void via_cleanup_futex(drm_via_private_t * dev_priv);
++extern void via_release_futex(drm_via_private_t * dev_priv, int context);
+
++extern int via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
++ unsigned int size);
+
+ #endif
+diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
+--- a/drivers/char/drm/via_irq.c
++++ b/drivers/char/drm/via_irq.c
+@@ -54,23 +54,26 @@
+ /*
+ * Device-specific IRQs go here. This type might need to be extended with
+ * the register if there are multiple IRQ control registers.
+- * Currently we activate the HQV interrupts of Unichrome Pro group A.
++ * Currently we activate the HQV interrupts of Unichrome Pro group A.
+ */
+
+ static maskarray_t via_pro_group_a_irqs[] = {
+- {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 0x00000000 },
+- {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 0x00000000 }};
+-static int via_num_pro_group_a = sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t);
++ {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
++ 0x00000000},
++ {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
++ 0x00000000}
++};
++static int via_num_pro_group_a =
++ sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
+
+-static maskarray_t via_unichrome_irqs[] = {};
+-static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t);
++static maskarray_t via_unichrome_irqs[] = { };
++static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+
+-
+-static unsigned time_diff(struct timeval *now,struct timeval *then)
++static unsigned time_diff(struct timeval *now, struct timeval *then)
+ {
+- return (now->tv_usec >= then->tv_usec) ?
+- now->tv_usec - then->tv_usec :
+- 1000000 - (then->tv_usec - now->tv_usec);
++ return (now->tv_usec >= then->tv_usec) ?
++ now->tv_usec - then->tv_usec :
++ 1000000 - (then->tv_usec - now->tv_usec);
+ }
+
+ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+@@ -86,38 +89,37 @@ irqreturn_t via_driver_irq_handler(DRM_I
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ if (status & VIA_IRQ_VBLANK_PENDING) {
+ atomic_inc(&dev->vbl_received);
+- if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
++ if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+ do_gettimeofday(&cur_vblank);
+- if (dev_priv->last_vblank_valid) {
+- dev_priv->usec_per_vblank =
+- time_diff( &cur_vblank,&dev_priv->last_vblank) >> 4;
++ if (dev_priv->last_vblank_valid) {
++ dev_priv->usec_per_vblank =
++ time_diff(&cur_vblank,
++ &dev_priv->last_vblank) >> 4;
+ }
+ dev_priv->last_vblank = cur_vblank;
+ dev_priv->last_vblank_valid = 1;
+- }
+- if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
++ }
++ if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+ DRM_DEBUG("US per vblank is: %u\n",
+- dev_priv->usec_per_vblank);
++ dev_priv->usec_per_vblank);
+ }
+ DRM_WAKEUP(&dev->vbl_queue);
+ drm_vbl_send_signals(dev);
+ handled = 1;
+ }
+-
+
+- for (i=0; i<dev_priv->num_irqs; ++i) {
++ for (i = 0; i < dev_priv->num_irqs; ++i) {
+ if (status & cur_irq->pending_mask) {
+- atomic_inc( &cur_irq->irq_received );
+- DRM_WAKEUP( &cur_irq->irq_queue );
++ atomic_inc(&cur_irq->irq_received);
++ DRM_WAKEUP(&cur_irq->irq_queue);
+ handled = 1;
+ }
+ cur_irq++;
+ }
+-
++
+ /* Acknowlege interrupts */
+ VIA_WRITE(VIA_REG_INTERRUPT, status);
+
+-
+ if (handled)
+ return IRQ_HANDLED;
+ else
+@@ -131,7 +133,7 @@ static __inline__ void viadrv_acknowledg
+ if (dev_priv) {
+ /* Acknowlege interrupts */
+ status = VIA_READ(VIA_REG_INTERRUPT);
+- VIA_WRITE(VIA_REG_INTERRUPT, status |
++ VIA_WRITE(VIA_REG_INTERRUPT, status |
+ dev_priv->irq_pending_mask);
+ }
+ }
+@@ -158,12 +160,12 @@ int via_driver_vblank_wait(drm_device_t
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(&dev->vbl_received)) -
+ *sequence) <= (1 << 23)));
+-
++
+ *sequence = cur_vblank;
+ return ret;
+ }
+
+-static int
++static int
+ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+ unsigned int *sequence)
+ {
+@@ -180,27 +182,29 @@ via_driver_irq_wait(drm_device_t * dev,
+ return DRM_ERR(EINVAL);
+ }
+
+- if (irq >= dev_priv->num_irqs ) {
+- DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq);
++ if (irq >= dev_priv->num_irqs) {
++ DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
++ irq);
+ return DRM_ERR(EINVAL);
+ }
+-
++
+ cur_irq += irq;
+
+ if (masks[irq][2] && !force_sequence) {
+ DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+- ((VIA_READ(masks[irq][2]) & masks[irq][3]) == masks[irq][4]));
++ ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
++ masks[irq][4]));
+ cur_irq_sequence = atomic_read(&cur_irq->irq_received);
+ } else {
+ DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+- (((cur_irq_sequence = atomic_read(&cur_irq->irq_received)) -
+- *sequence) <= (1 << 23)));
++ (((cur_irq_sequence =
++ atomic_read(&cur_irq->irq_received)) -
++ *sequence) <= (1 << 23)));
+ }
+ *sequence = cur_irq_sequence;
+ return ret;
+ }
+
+-
+ /*
+ * drm_dma.h hooks
+ */
+@@ -219,29 +223,29 @@ void via_driver_irq_preinstall(drm_devic
+ dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
+
+ dev_priv->irq_masks = (dev_priv->pro_group_a) ?
+- via_pro_group_a_irqs : via_unichrome_irqs;
++ via_pro_group_a_irqs : via_unichrome_irqs;
+ dev_priv->num_irqs = (dev_priv->pro_group_a) ?
+- via_num_pro_group_a : via_num_unichrome;
+-
+- for(i=0; i < dev_priv->num_irqs; ++i) {
++ via_num_pro_group_a : via_num_unichrome;
++
++ for (i = 0; i < dev_priv->num_irqs; ++i) {
+ atomic_set(&cur_irq->irq_received, 0);
+- cur_irq->enable_mask = dev_priv->irq_masks[i][0];
++ cur_irq->enable_mask = dev_priv->irq_masks[i][0];
+ cur_irq->pending_mask = dev_priv->irq_masks[i][1];
+- DRM_INIT_WAITQUEUE( &cur_irq->irq_queue );
++ DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
+ dev_priv->irq_enable_mask |= cur_irq->enable_mask;
+ dev_priv->irq_pending_mask |= cur_irq->pending_mask;
+ cur_irq++;
+-
++
+ DRM_DEBUG("Initializing IRQ %d\n", i);
+ }
+-
+- dev_priv->last_vblank_valid = 0;
++
++ dev_priv->last_vblank_valid = 0;
+
+ // Clear VSync interrupt regs
+ status = VIA_READ(VIA_REG_INTERRUPT);
+- VIA_WRITE(VIA_REG_INTERRUPT, status &
++ VIA_WRITE(VIA_REG_INTERRUPT, status &
+ ~(dev_priv->irq_enable_mask));
+-
++
+ /* Clear bits if they're already high */
+ viadrv_acknowledge_irqs(dev_priv);
+ }
+@@ -262,7 +266,7 @@ void via_driver_irq_postinstall(drm_devi
+
+ VIA_WRITE8(0x83d4, 0x11);
+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+-
++
+ }
+ }
+
+@@ -280,7 +284,7 @@ void via_driver_irq_uninstall(drm_device
+ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+ status = VIA_READ(VIA_REG_INTERRUPT);
+- VIA_WRITE(VIA_REG_INTERRUPT, status &
++ VIA_WRITE(VIA_REG_INTERRUPT, status &
+ ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
+ }
+ }
+@@ -302,7 +306,7 @@ int via_wait_irq(DRM_IOCTL_ARGS)
+
+ DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait));
+ if (irqwait.request.irq >= dev_priv->num_irqs) {
+- DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
++ DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
+ irqwait.request.irq);
+ return DRM_ERR(EINVAL);
+ }
+@@ -320,7 +324,7 @@ int via_wait_irq(DRM_IOCTL_ARGS)
+ }
+
+ if (irqwait.request.type & VIA_IRQ_SIGNAL) {
+- DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n",
++ DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n",
+ __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
+--- a/drivers/char/drm/via_map.c
++++ b/drivers/char/drm/via_map.c
+@@ -66,7 +66,7 @@ static int via_do_init_map(drm_device_t
+
+ dev_priv->agpAddr = init->agpAddr;
+
+- via_init_futex( dev_priv );
++ via_init_futex(dev_priv);
+ dev_priv->pro_group_a = (dev->pdev->device == 0x3118);
+
+ dev->dev_private = (void *)dev_priv;
+@@ -107,5 +107,3 @@ int via_map_init(DRM_IOCTL_ARGS)
+
+ return -EINVAL;
+ }
+-
+-
+diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
+--- a/drivers/char/drm/via_mm.c
++++ b/drivers/char/drm/via_mm.c
+@@ -81,7 +81,8 @@ int via_agp_init(DRM_IOCTL_ARGS)
+
+ AgpHeap = via_mmInit(agp.offset, agp.size);
+
+- DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, (unsigned long)agp.size);
++ DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset,
++ (unsigned long)agp.size);
+
+ return 0;
+ }
+@@ -97,7 +98,8 @@ int via_fb_init(DRM_IOCTL_ARGS)
+
+ FBHeap = via_mmInit(fb.offset, fb.size);
+
+- DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, (unsigned long)fb.size);
++ DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset,
++ (unsigned long)fb.size);
+
+ return 0;
+ }
+@@ -134,8 +136,8 @@ int via_init_context(struct drm_device *
+ }
+
+ int via_final_context(struct drm_device *dev, int context)
+-{
+- int i;
++{
++ int i;
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+ for (i = 0; i < MAX_CONTEXT; i++)
+@@ -171,14 +173,13 @@ int via_final_context(struct drm_device
+ via_setDestroy(set);
+ global_ppriv[i].used = 0;
+ }
+- via_release_futex(dev_priv, context);
+-
+-
++ via_release_futex(dev_priv, context);
++
+ #if defined(__linux__)
+ /* Linux specific until context tracking code gets ported to BSD */
+ /* Last context, perform cleanup */
+ if (dev->ctx_count == 1 && dev->dev_private) {
+- DRM_DEBUG("Last Context\n");
++ DRM_DEBUG("Last Context\n");
+ if (dev->irq)
+ drm_irq_uninstall(dev);
+
+diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
+--- a/drivers/char/drm/via_verifier.c
++++ b/drivers/char/drm/via_verifier.c
+@@ -28,7 +28,6 @@
+ * be very slow.
+ */
+
+-
+ #include "via_3d_reg.h"
+ #include "drmP.h"
+ #include "drm.h"
+@@ -36,7 +35,7 @@
+ #include "via_verifier.h"
+ #include "via_drv.h"
+
+-typedef enum{
++typedef enum {
+ state_command,
+ state_header2,
+ state_header1,
+@@ -45,8 +44,7 @@ typedef enum{
+ state_error
+ } verifier_state_t;
+
+-
+-typedef enum{
++typedef enum {
+ no_check = 0,
+ check_for_header2,
+ check_for_header1,
+@@ -74,16 +72,16 @@ typedef enum{
+ check_for_vertex_count,
+ check_number_texunits,
+ forbidden_command
+-}hazard_t;
++} hazard_t;
+
+ /*
+ * Associates each hazard above with a possible multi-command
+ * sequence. For example an address that is split over multiple
+- * commands and that needs to be checked at the first command
++ * commands and that needs to be checked at the first command
+ * that does not include any part of the address.
+ */
+
+-static drm_via_sequence_t seqs[] = {
++static drm_via_sequence_t seqs[] = {
+ no_sequence,
+ no_sequence,
+ no_sequence,
+@@ -110,14 +108,12 @@ static drm_via_sequence_t seqs[] = {
+ tex_address,
+ no_sequence
+ };
+-
+-typedef struct{
++
++typedef struct {
+ unsigned int code;
+ hazard_t hz;
+ } hz_init_t;
+
+-
+-
+ static hz_init_t init_table1[] = {
+ {0xf2, check_for_header2_err},
+ {0xf0, check_for_header1_err},
+@@ -169,8 +165,6 @@ static hz_init_t init_table1[] = {
+ {0x7D, check_for_vertex_count}
+ };
+
+-
+-
+ static hz_init_t init_table2[] = {
+ {0xf2, check_for_header2_err},
+ {0xf0, check_for_header1_err},
+@@ -235,49 +229,49 @@ static hz_init_t init_table3[] = {
+ {0xcc, check_for_dummy},
+ {0x00, check_number_texunits}
+ };
+-
+-
+-static hazard_t table1[256];
+-static hazard_t table2[256];
+-static hazard_t table3[256];
+-
+
++static hazard_t table1[256];
++static hazard_t table2[256];
++static hazard_t table3[256];
+
+ static __inline__ int
+-eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
++eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
+ {
+ if ((*buf - buf_end) >= num_words) {
+ *buf += num_words;
+ return 0;
+- }
++ }
+ DRM_ERROR("Illegal termination of DMA command buffer\n");
+ return 1;
+ }
+
+-
+ /*
+ * Partially stolen from drm_memory.h
+ */
+
+-static __inline__ drm_map_t *
+-via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned long size,
+- drm_device_t *dev)
++static __inline__ drm_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
++ unsigned long offset,
++ unsigned long size,
++ drm_device_t * dev)
+ {
+ struct list_head *list;
+ drm_map_list_t *r_list;
+ drm_map_t *map = seq->map_cache;
+
+- if (map && map->offset <= offset && (offset + size) <= (map->offset + map->size)) {
++ if (map && map->offset <= offset
++ && (offset + size) <= (map->offset + map->size)) {
+ return map;
+ }
+-
++
+ list_for_each(list, &dev->maplist->head) {
+ r_list = (drm_map_list_t *) list;
+ map = r_list->map;
+ if (!map)
+ continue;
+- if (map->offset <= offset && (offset + size) <= (map->offset + map->size) &&
+- !(map->flags & _DRM_RESTRICTED) && (map->type == _DRM_AGP)) {
++ if (map->offset <= offset
++ && (offset + size) <= (map->offset + map->size)
++ && !(map->flags & _DRM_RESTRICTED)
++ && (map->type == _DRM_AGP)) {
+ seq->map_cache = map;
+ return map;
+ }
+@@ -285,54 +279,60 @@ via_drm_lookup_agp_map (drm_via_state_t
+ return NULL;
+ }
+
+-
+ /*
+- * Require that all AGP texture levels reside in the same AGP map which should
++ * Require that all AGP texture levels reside in the same AGP map which should
+ * be mappable by the client. This is not a big restriction.
+- * FIXME: To actually enforce this security policy strictly, drm_rmmap
+- * would have to wait for dma quiescent before removing an AGP map.
++ * FIXME: To actually enforce this security policy strictly, drm_rmmap
++ * would have to wait for dma quiescent before removing an AGP map.
+ * The via_drm_lookup_agp_map call in reality seems to take
+ * very little CPU time.
+ */
+
+-
+-static __inline__ int
+-finish_current_sequence(drm_via_state_t *cur_seq)
++static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
+ {
+- switch(cur_seq->unfinished) {
++ switch (cur_seq->unfinished) {
+ case z_address:
+ DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
+ break;
+ case dest_address:
+- DRM_DEBUG("Destination start address is 0x%x\n", cur_seq->d_addr);
++ DRM_DEBUG("Destination start address is 0x%x\n",
++ cur_seq->d_addr);
+ break;
+ case tex_address:
+- if (cur_seq->agp_texture) {
+- unsigned start = cur_seq->tex_level_lo[cur_seq->texture];
++ if (cur_seq->agp_texture) {
++ unsigned start =
++ cur_seq->tex_level_lo[cur_seq->texture];
+ unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
+- unsigned long lo=~0, hi=0, tmp;
++ unsigned long lo = ~0, hi = 0, tmp;
+ uint32_t *addr, *pitch, *height, tex;
+ unsigned i;
+
+- if (end > 9) end = 9;
+- if (start > 9) start = 9;
++ if (end > 9)
++ end = 9;
++ if (start > 9)
++ start = 9;
+
+- addr =&(cur_seq->t_addr[tex = cur_seq->texture][start]);
++ addr =
++ &(cur_seq->t_addr[tex = cur_seq->texture][start]);
+ pitch = &(cur_seq->pitch[tex][start]);
+ height = &(cur_seq->height[tex][start]);
+
+- for (i=start; i<= end; ++i) {
++ for (i = start; i <= end; ++i) {
+ tmp = *addr++;
+- if (tmp < lo) lo = tmp;
++ if (tmp < lo)
++ lo = tmp;
+ tmp += (*height++ << *pitch++);
+- if (tmp > hi) hi = tmp;
++ if (tmp > hi)
++ hi = tmp;
+ }
+
+- if (! via_drm_lookup_agp_map (cur_seq, lo, hi - lo, cur_seq->dev)) {
+- DRM_ERROR("AGP texture is not in allowed map\n");
++ if (!via_drm_lookup_agp_map
++ (cur_seq, lo, hi - lo, cur_seq->dev)) {
++ DRM_ERROR
++ ("AGP texture is not in allowed map\n");
+ return 2;
+ }
+- }
++ }
+ break;
+ default:
+ break;
+@@ -341,73 +341,84 @@ finish_current_sequence(drm_via_state_t
+ return 0;
+ }
+
+-static __inline__ int
+-investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
++static __inline__ int
++investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
+ {
+ register uint32_t tmp, *tmp_addr;
+
+ if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
+ int ret;
+- if ((ret = finish_current_sequence(cur_seq))) return ret;
++ if ((ret = finish_current_sequence(cur_seq)))
++ return ret;
+ }
+
+- switch(hz) {
++ switch (hz) {
+ case check_for_header2:
+- if (cmd == HALCYON_HEADER2) return 1;
++ if (cmd == HALCYON_HEADER2)
++ return 1;
+ return 0;
+ case check_for_header1:
+- if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
++ if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
++ return 1;
+ return 0;
+ case check_for_header2_err:
+- if (cmd == HALCYON_HEADER2) return 1;
++ if (cmd == HALCYON_HEADER2)
++ return 1;
+ DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
+ break;
+ case check_for_header1_err:
+- if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
++ if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
++ return 1;
+ DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
+ break;
+ case check_for_fire:
+- if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD) return 1;
++ if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
++ return 1;
+ DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
+ break;
+ case check_for_dummy:
+- if (HC_DUMMY == cmd) return 0;
++ if (HC_DUMMY == cmd)
++ return 0;
+ DRM_ERROR("Illegal DMA HC_DUMMY command\n");
+ break;
+ case check_for_dd:
+- if (0xdddddddd == cmd) return 0;
++ if (0xdddddddd == cmd)
++ return 0;
+ DRM_ERROR("Illegal DMA 0xdddddddd command\n");
+ break;
+ case check_z_buffer_addr0:
+ cur_seq->unfinished = z_address;
+ cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
+- (cmd & 0x00FFFFFF);
++ (cmd & 0x00FFFFFF);
+ return 0;
+ case check_z_buffer_addr1:
+ cur_seq->unfinished = z_address;
+ cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
+- ((cmd & 0xFF) << 24);
++ ((cmd & 0xFF) << 24);
+ return 0;
+ case check_z_buffer_addr_mode:
+ cur_seq->unfinished = z_address;
+- if ((cmd & 0x0000C000) == 0) return 0;
++ if ((cmd & 0x0000C000) == 0)
++ return 0;
+ DRM_ERROR("Attempt to place Z buffer in system memory\n");
+ return 2;
+ case check_destination_addr0:
+ cur_seq->unfinished = dest_address;
+ cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
+- (cmd & 0x00FFFFFF);
++ (cmd & 0x00FFFFFF);
+ return 0;
+ case check_destination_addr1:
+ cur_seq->unfinished = dest_address;
+ cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
+- ((cmd & 0xFF) << 24);
++ ((cmd & 0xFF) << 24);
+ return 0;
+ case check_destination_addr_mode:
+ cur_seq->unfinished = dest_address;
+- if ((cmd & 0x0000C000) == 0) return 0;
+- DRM_ERROR("Attempt to place 3D drawing buffer in system memory\n");
+- return 2;
++ if ((cmd & 0x0000C000) == 0)
++ return 0;
++ DRM_ERROR
++ ("Attempt to place 3D drawing buffer in system memory\n");
++ return 2;
+ case check_texture_addr0:
+ cur_seq->unfinished = tex_address;
+ tmp = (cmd >> 24);
+@@ -433,9 +444,11 @@ investigate_hazard( uint32_t cmd, hazard
+ case check_texture_addr3:
+ cur_seq->unfinished = tex_address;
+ tmp = ((cmd >> 24) - 0x2B);
+- cur_seq->pitch[cur_seq->texture][tmp] = (cmd & 0x00F00000) >> 20;
++ cur_seq->pitch[cur_seq->texture][tmp] =
++ (cmd & 0x00F00000) >> 20;
+ if (!tmp && (cmd & 0x000FFFFF)) {
+- DRM_ERROR("Unimplemented texture level 0 pitch mode.\n");
++ DRM_ERROR
++ ("Unimplemented texture level 0 pitch mode.\n");
+ return 2;
+ }
+ return 0;
+@@ -449,7 +462,7 @@ investigate_hazard( uint32_t cmd, hazard
+ cur_seq->unfinished = tex_address;
+ /*
+ * Texture width. We don't care since we have the pitch.
+- */
++ */
+ return 0;
+ case check_texture_addr7:
+ cur_seq->unfinished = tex_address;
+@@ -465,25 +478,26 @@ investigate_hazard( uint32_t cmd, hazard
+ cur_seq->unfinished = tex_address;
+ tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+ tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
+- tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
++ tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
+ tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
+ tmp_addr[6] = 1 << (cmd & 0x0000000F);
+ return 0;
+ case check_texture_addr_mode:
+ cur_seq->unfinished = tex_address;
+- if ( 2 == (tmp = cmd & 0x00000003)) {
+- DRM_ERROR("Attempt to fetch texture from system memory.\n");
++ if (2 == (tmp = cmd & 0x00000003)) {
++ DRM_ERROR
++ ("Attempt to fetch texture from system memory.\n");
+ return 2;
+ }
+ cur_seq->agp_texture = (tmp == 3);
+- cur_seq->tex_palette_size[cur_seq->texture] =
+- (cmd >> 16) & 0x000000007;
++ cur_seq->tex_palette_size[cur_seq->texture] =
++ (cmd >> 16) & 0x000000007;
+ return 0;
+ case check_for_vertex_count:
+ cur_seq->vertex_count = cmd & 0x0000FFFF;
+ return 0;
+ case check_number_texunits:
+- cur_seq->multitex = (cmd >> 3) & 1;
++ cur_seq->multitex = (cmd >> 3) & 1;
+ return 0;
+ default:
+ DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
+@@ -492,25 +506,27 @@ investigate_hazard( uint32_t cmd, hazard
+ return 2;
+ }
+
+-
+ static __inline__ int
+-via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
+- drm_via_state_t *cur_seq)
++via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
++ drm_via_state_t * cur_seq)
+ {
+- drm_via_private_t *dev_priv = (drm_via_private_t *) cur_seq->dev->dev_private;
+- uint32_t a_fire, bcmd , dw_count;
++ drm_via_private_t *dev_priv =
++ (drm_via_private_t *) cur_seq->dev->dev_private;
++ uint32_t a_fire, bcmd, dw_count;
+ int ret = 0;
+ int have_fire;
+ const uint32_t *buf = *buffer;
+
+- while(buf < buf_end) {
+- have_fire = 0;
++ while (buf < buf_end) {
++ have_fire = 0;
+ if ((buf_end - buf) < 2) {
+- DRM_ERROR("Unexpected termination of primitive list.\n");
++ DRM_ERROR
++ ("Unexpected termination of primitive list.\n");
+ ret = 1;
+ break;
+ }
+- if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB) break;
++ if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
++ break;
+ bcmd = *buf++;
+ if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
+ DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
+@@ -518,43 +534,56 @@ via_check_prim_list(uint32_t const **buf
+ ret = 1;
+ break;
+ }
+- a_fire = *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK;
+-
++ a_fire =
++ *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
++ HC_HE3Fire_MASK;
++
+ /*
+ * How many dwords per vertex ?
+- */
+-
++ */
++
+ if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
+ DRM_ERROR("Illegal B command vertex data for AGP.\n");
+ ret = 1;
+ break;
+- }
++ }
+
+ dw_count = 0;
+- if (bcmd & (1 << 7)) dw_count += (cur_seq->multitex) ? 2:1;
+- if (bcmd & (1 << 8)) dw_count += (cur_seq->multitex) ? 2:1;
+- if (bcmd & (1 << 9)) dw_count++;
+- if (bcmd & (1 << 10)) dw_count++;
+- if (bcmd & (1 << 11)) dw_count++;
+- if (bcmd & (1 << 12)) dw_count++;
+- if (bcmd & (1 << 13)) dw_count++;
+- if (bcmd & (1 << 14)) dw_count++;
++ if (bcmd & (1 << 7))
++ dw_count += (cur_seq->multitex) ? 2 : 1;
++ if (bcmd & (1 << 8))
++ dw_count += (cur_seq->multitex) ? 2 : 1;
++ if (bcmd & (1 << 9))
++ dw_count++;
++ if (bcmd & (1 << 10))
++ dw_count++;
++ if (bcmd & (1 << 11))
++ dw_count++;
++ if (bcmd & (1 << 12))
++ dw_count++;
++ if (bcmd & (1 << 13))
++ dw_count++;
++ if (bcmd & (1 << 14))
++ dw_count++;
+
+- while(buf < buf_end) {
++ while (buf < buf_end) {
+ if (*buf == a_fire) {
+- if (dev_priv->num_fire_offsets >= VIA_FIRE_BUF_SIZE) {
++ if (dev_priv->num_fire_offsets >=
++ VIA_FIRE_BUF_SIZE) {
+ DRM_ERROR("Fire offset buffer full.\n");
+ ret = 1;
+ break;
+ }
+- dev_priv->fire_offsets[dev_priv->num_fire_offsets++] = buf;
+- have_fire = 1;
++ dev_priv->fire_offsets[dev_priv->
++ num_fire_offsets++] =
++ buf;
++ have_fire = 1;
+ buf++;
+- if (buf < buf_end && *buf == a_fire)
++ if (buf < buf_end && *buf == a_fire)
+ buf++;
+ break;
+ }
+- if ((*buf == HALCYON_HEADER2) ||
++ if ((*buf == HALCYON_HEADER2) ||
+ ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
+ DRM_ERROR("Missing Vertex Fire command, "
+ "Stray Vertex Fire command or verifier "
+@@ -576,18 +605,14 @@ via_check_prim_list(uint32_t const **buf
+ ret = 1;
+ break;
+ }
+- }
++ }
+ *buffer = buf;
+ return ret;
+ }
+
+-
+-
+-
+-
+ static __inline__ verifier_state_t
+-via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
+- drm_via_state_t *hc_state)
++via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
++ drm_via_state_t * hc_state)
+ {
+ uint32_t cmd;
+ int hz_mode;
+@@ -595,17 +620,17 @@ via_check_header2( uint32_t const **buff
+ const uint32_t *buf = *buffer;
+ const hazard_t *hz_table;
+
+-
+ if ((buf_end - buf) < 2) {
+- DRM_ERROR("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
++ DRM_ERROR
++ ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
+ return state_error;
+ }
+ buf++;
+ cmd = (*buf++ & 0xFFFF0000) >> 16;
+
+- switch(cmd) {
++ switch (cmd) {
+ case HC_ParaType_CmdVdata:
+- if (via_check_prim_list(&buf, buf_end, hc_state ))
++ if (via_check_prim_list(&buf, buf_end, hc_state))
+ return state_error;
+ *buffer = buf;
+ return state_command;
+@@ -650,13 +675,13 @@ via_check_header2( uint32_t const **buff
+ */
+
+ DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
+- "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
+- cmd, *(buf -2));
++ "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
++ cmd, *(buf - 2));
+ *buffer = buf;
+ return state_error;
+ }
+
+- while(buf < buf_end) {
++ while (buf < buf_end) {
+ cmd = *buf++;
+ if ((hz = hz_table[cmd >> 24])) {
+ if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
+@@ -666,7 +691,7 @@ via_check_header2( uint32_t const **buff
+ }
+ return state_error;
+ }
+- } else if (hc_state->unfinished &&
++ } else if (hc_state->unfinished &&
+ finish_current_sequence(hc_state)) {
+ return state_error;
+ }
+@@ -679,64 +704,65 @@ via_check_header2( uint32_t const **buff
+ }
+
+ static __inline__ verifier_state_t
+-via_parse_header2( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end,
+- int *fire_count)
++via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
++ const uint32_t * buf_end, int *fire_count)
+ {
+ uint32_t cmd;
+ const uint32_t *buf = *buffer;
+- const uint32_t *next_fire;
++ const uint32_t *next_fire;
+ int burst = 0;
+
+ next_fire = dev_priv->fire_offsets[*fire_count];
+ buf++;
+ cmd = (*buf & 0xFFFF0000) >> 16;
+ VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
+- switch(cmd) {
++ switch (cmd) {
+ case HC_ParaType_CmdVdata:
+ while ((buf < buf_end) &&
+- (*fire_count < dev_priv->num_fire_offsets) &&
+- (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB ) {
+- while(buf <= next_fire) {
+- VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
++ (*fire_count < dev_priv->num_fire_offsets) &&
++ (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
++ while (buf <= next_fire) {
++ VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
++ (burst & 63), *buf++);
+ burst += 4;
+ }
+- if ( ( buf < buf_end ) && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
++ if ((buf < buf_end)
++ && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+ buf++;
+
+- if (++(*fire_count) < dev_priv->num_fire_offsets)
++ if (++(*fire_count) < dev_priv->num_fire_offsets)
+ next_fire = dev_priv->fire_offsets[*fire_count];
+ }
+ break;
+ default:
+- while(buf < buf_end) {
+-
+- if ( *buf == HC_HEADER2 ||
+- (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
+- (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
+- (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6 ) break;
+-
+- VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
+- burst +=4;
++ while (buf < buf_end) {
++
++ if (*buf == HC_HEADER2 ||
++ (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
++ (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
++ (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
++ break;
++
++ VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
++ (burst & 63), *buf++);
++ burst += 4;
+ }
+ }
+ *buffer = buf;
+ return state_command;
+ }
+
+-
+-
+-static __inline__ int
+-verify_mmio_address( uint32_t address)
++static __inline__ int verify_mmio_address(uint32_t address)
+ {
+- if ((address > 0x3FF) && (address < 0xC00 )) {
++ if ((address > 0x3FF) && (address < 0xC00)) {
+ DRM_ERROR("Invalid VIDEO DMA command. "
+ "Attempt to access 3D- or command burst area.\n");
+ return 1;
+ } else if ((address > 0xCFF) && (address < 0x1300)) {
+ DRM_ERROR("Invalid VIDEO DMA command. "
+ "Attempt to access PCI DMA area.\n");
+- return 1;
+- } else if (address > 0x13FF ) {
++ return 1;
++ } else if (address > 0x13FF) {
+ DRM_ERROR("Invalid VIDEO DMA command. "
+ "Attempt to access VGA registers.\n");
+ return 1;
+@@ -745,7 +771,8 @@ verify_mmio_address( uint32_t address)
+ }
+
+ static __inline__ int
+-verify_video_tail( uint32_t const **buffer, const uint32_t *buf_end, uint32_t dwords)
++verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
++ uint32_t dwords)
+ {
+ const uint32_t *buf = *buffer;
+
+@@ -762,10 +789,9 @@ verify_video_tail( uint32_t const **buff
+ *buffer = buf;
+ return 0;
+ }
+-
+
+ static __inline__ verifier_state_t
+-via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
++via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
+ {
+ uint32_t cmd;
+ const uint32_t *buf = *buffer;
+@@ -774,21 +800,21 @@ via_check_header1( uint32_t const **buff
+ while (buf < buf_end) {
+ cmd = *buf;
+ if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
+- (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
+- if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
++ (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
++ if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+ break;
+ DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+ "Attempt to access 3D- or command burst area.\n");
+ ret = state_error;
+ break;
+ } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
+- if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
++ if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+ break;
+ DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+ "Attempt to access VGA registers.\n");
+ ret = state_error;
+- break;
+- } else {
++ break;
++ } else {
+ buf += 2;
+ }
+ }
+@@ -797,15 +823,17 @@ via_check_header1( uint32_t const **buff
+ }
+
+ static __inline__ verifier_state_t
+-via_parse_header1( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
++via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
++ const uint32_t * buf_end)
+ {
+ register uint32_t cmd;
+ const uint32_t *buf = *buffer;
+
+ while (buf < buf_end) {
+ cmd = *buf;
+- if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) break;
+- VIA_WRITE( (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
++ if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
++ break;
++ VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
+ buf++;
+ }
+ *buffer = buf;
+@@ -813,7 +841,7 @@ via_parse_header1( drm_via_private_t *de
+ }
+
+ static __inline__ verifier_state_t
+-via_check_vheader5( uint32_t const **buffer, const uint32_t *buf_end )
++via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
+ {
+ uint32_t data;
+ const uint32_t *buf = *buffer;
+@@ -836,41 +864,41 @@ via_check_vheader5( uint32_t const **buf
+ DRM_ERROR("Illegal header5 header data\n");
+ return state_error;
+ }
+- if (eat_words(&buf, buf_end, data))
++ if (eat_words(&buf, buf_end, data))
+ return state_error;
+- if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
++ if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+ return state_error;
+ *buffer = buf;
+ return state_command;
+-
+-}
++
++}
+
+ static __inline__ verifier_state_t
+-via_parse_vheader5( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
++via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
++ const uint32_t * buf_end)
+ {
+- uint32_t addr, count, i;
++ uint32_t addr, count, i;
+ const uint32_t *buf = *buffer;
+-
++
+ addr = *buf++ & ~VIA_VIDEOMASK;
+ i = count = *buf;
+ buf += 3;
+- while(i--) {
++ while (i--) {
+ VIA_WRITE(addr, *buf++);
+ }
+- if (count & 3) buf += 4 - (count & 3);
++ if (count & 3)
++ buf += 4 - (count & 3);
+ *buffer = buf;
+- return state_command;
+-}
+-
++ return state_command;
++}
+
+ static __inline__ verifier_state_t
+-via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
++via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
+ {
+ uint32_t data;
+ const uint32_t *buf = *buffer;
+ uint32_t i;
+
+-
+ if (buf_end - buf < 4) {
+ DRM_ERROR("Illegal termination of video header6 command\n");
+ return state_error;
+@@ -889,7 +917,7 @@ via_check_vheader6( uint32_t const **buf
+ DRM_ERROR("Illegal termination of video header6 command\n");
+ return state_error;
+ }
+- for (i=0; i<data; ++i) {
++ for (i = 0; i < data; ++i) {
+ if (verify_mmio_address(*buf++))
+ return state_error;
+ buf++;
+@@ -899,42 +927,42 @@ via_check_vheader6( uint32_t const **buf
+ return state_error;
+ *buffer = buf;
+ return state_command;
+-}
++}
+
+ static __inline__ verifier_state_t
+-via_parse_vheader6( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
++via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
++ const uint32_t * buf_end)
+ {
+
+- uint32_t addr, count, i;
++ uint32_t addr, count, i;
+ const uint32_t *buf = *buffer;
+
+ i = count = *++buf;
+ buf += 3;
+- while(i--) {
++ while (i--) {
+ addr = *buf++;
+ VIA_WRITE(addr, *buf++);
+ }
+ count <<= 1;
+- if (count & 3) buf += 4 - (count & 3);
++ if (count & 3)
++ buf += 4 - (count & 3);
+ *buffer = buf;
+ return state_command;
+-}
+-
+-
++}
+
+-int
+-via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t *dev,
+- int agp)
++int
++via_verify_command_stream(const uint32_t * buf, unsigned int size,
++ drm_device_t * dev, int agp)
+ {
+
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ drm_via_state_t *hc_state = &dev_priv->hc_state;
+ drm_via_state_t saved_state = *hc_state;
+ uint32_t cmd;
+- const uint32_t *buf_end = buf + ( size >> 2 );
++ const uint32_t *buf_end = buf + (size >> 2);
+ verifier_state_t state = state_command;
+ int pro_group_a = dev_priv->pro_group_a;
+-
++
+ hc_state->dev = dev;
+ hc_state->unfinished = no_sequence;
+ hc_state->map_cache = NULL;
+@@ -946,38 +974,41 @@ via_verify_command_stream(const uint32_t
+
+ switch (state) {
+ case state_header2:
+- state = via_check_header2( &buf, buf_end, hc_state );
++ state = via_check_header2(&buf, buf_end, hc_state);
+ break;
+ case state_header1:
+- state = via_check_header1( &buf, buf_end );
++ state = via_check_header1(&buf, buf_end);
+ break;
+ case state_vheader5:
+- state = via_check_vheader5( &buf, buf_end );
++ state = via_check_vheader5(&buf, buf_end);
+ break;
+ case state_vheader6:
+- state = via_check_vheader6( &buf, buf_end );
++ state = via_check_vheader6(&buf, buf_end);
+ break;
+ case state_command:
+- if (HALCYON_HEADER2 == (cmd = *buf))
++ if (HALCYON_HEADER2 == (cmd = *buf))
+ state = state_header2;
+- else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
++ else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+ state = state_header1;
+- else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
++ else if (pro_group_a
++ && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+ state = state_vheader5;
+- else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
++ else if (pro_group_a
++ && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+ state = state_vheader6;
+ else {
+- DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+- cmd);
++ DRM_ERROR
++ ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
++ cmd);
+ state = state_error;
+ }
+ break;
+ case state_error:
+ default:
+ *hc_state = saved_state;
+- return DRM_ERR(EINVAL);
++ return DRM_ERR(EINVAL);
+ }
+- }
++ }
+ if (state == state_error) {
+ *hc_state = saved_state;
+ return DRM_ERR(EINVAL);
+@@ -985,77 +1016,81 @@ via_verify_command_stream(const uint32_t
+ return 0;
+ }
+
+-int
+-via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size)
++int
++via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
++ unsigned int size)
+ {
+
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ uint32_t cmd;
+- const uint32_t *buf_end = buf + ( size >> 2 );
++ const uint32_t *buf_end = buf + (size >> 2);
+ verifier_state_t state = state_command;
+ int fire_count = 0;
+-
++
+ while (buf < buf_end) {
+
+ switch (state) {
+ case state_header2:
+- state = via_parse_header2( dev_priv, &buf, buf_end, &fire_count );
++ state =
++ via_parse_header2(dev_priv, &buf, buf_end,
++ &fire_count);
+ break;
+ case state_header1:
+- state = via_parse_header1( dev_priv, &buf, buf_end );
++ state = via_parse_header1(dev_priv, &buf, buf_end);
+ break;
+ case state_vheader5:
+- state = via_parse_vheader5( dev_priv, &buf, buf_end );
++ state = via_parse_vheader5(dev_priv, &buf, buf_end);
+ break;
+ case state_vheader6:
+- state = via_parse_vheader6( dev_priv, &buf, buf_end );
++ state = via_parse_vheader6(dev_priv, &buf, buf_end);
+ break;
+ case state_command:
+- if (HALCYON_HEADER2 == (cmd = *buf))
++ if (HALCYON_HEADER2 == (cmd = *buf))
+ state = state_header2;
+- else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
++ else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+ state = state_header1;
+ else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+ state = state_vheader5;
+ else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+ state = state_vheader6;
+ else {
+- DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+- cmd);
++ DRM_ERROR
++ ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
++ cmd);
+ state = state_error;
+ }
+ break;
+ case state_error:
+ default:
+- return DRM_ERR(EINVAL);
++ return DRM_ERR(EINVAL);
+ }
+- }
++ }
+ if (state == state_error) {
+ return DRM_ERR(EINVAL);
+ }
+ return 0;
+ }
+
+-
+-
+-static void
++static void
+ setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
+ {
+ int i;
+
+- for(i=0; i<256; ++i) {
++ for (i = 0; i < 256; ++i) {
+ table[i] = forbidden_command;
+ }
+
+- for(i=0; i<size; ++i) {
++ for (i = 0; i < size; ++i) {
+ table[init_table[i].code] = init_table[i].hz;
+ }
+ }
+
+-void
+-via_init_command_verifier( void )
++void via_init_command_verifier(void)
+ {
+- setup_hazard_table(init_table1, table1, sizeof(init_table1) / sizeof(hz_init_t));
+- setup_hazard_table(init_table2, table2, sizeof(init_table2) / sizeof(hz_init_t));
+- setup_hazard_table(init_table3, table3, sizeof(init_table3) / sizeof(hz_init_t));
++ setup_hazard_table(init_table1, table1,
++ sizeof(init_table1) / sizeof(hz_init_t));
++ setup_hazard_table(init_table2, table2,
++ sizeof(init_table2) / sizeof(hz_init_t));
++ setup_hazard_table(init_table3, table3,
++ sizeof(init_table3) / sizeof(hz_init_t));
+ }
+diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
+--- a/drivers/char/drm/via_verifier.h
++++ b/drivers/char/drm/via_verifier.h
+@@ -26,23 +26,21 @@
+ #ifndef _VIA_VERIFIER_H_
+ #define _VIA_VERIFIER_H_
+
+-typedef enum{
+- no_sequence = 0,
++typedef enum {
++ no_sequence = 0,
+ z_address,
+ dest_address,
+ tex_address
+-}drm_via_sequence_t;
++} drm_via_sequence_t;
+
+-
+-
+-typedef struct{
++typedef struct {
+ unsigned texture;
+- uint32_t z_addr;
+- uint32_t d_addr;
+- uint32_t t_addr[2][10];
++ uint32_t z_addr;
++ uint32_t d_addr;
++ uint32_t t_addr[2][10];
+ uint32_t pitch[2][10];
+ uint32_t height[2][10];
+- uint32_t tex_level_lo[2];
++ uint32_t tex_level_lo[2];
+ uint32_t tex_level_hi[2];
+ uint32_t tex_palette_size[2];
+ drm_via_sequence_t unfinished;
+@@ -55,7 +53,7 @@ typedef struct{
+ const uint32_t *buf_start;
+ } drm_via_state_t;
+
+-extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
+- drm_device_t *dev, int agp);
++extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
++ drm_device_t * dev, int agp);
+
+ #endif
+diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
+--- a/drivers/char/drm/via_video.c
++++ b/drivers/char/drm/via_video.c
+@@ -29,8 +29,7 @@
+ #include "via_drm.h"
+ #include "via_drv.h"
+
+-void
+-via_init_futex(drm_via_private_t *dev_priv)
++void via_init_futex(drm_via_private_t * dev_priv)
+ {
+ unsigned int i;
+
+@@ -42,30 +41,28 @@ via_init_futex(drm_via_private_t *dev_pr
+ }
+ }
+
+-void
+-via_cleanup_futex(drm_via_private_t *dev_priv)
++void via_cleanup_futex(drm_via_private_t * dev_priv)
+ {
+-}
++}
+
+-void
+-via_release_futex(drm_via_private_t *dev_priv, int context)
++void via_release_futex(drm_via_private_t * dev_priv, int context)
+ {
+ unsigned int i;
+ volatile int *lock;
+
+- for (i=0; i < VIA_NR_XVMC_LOCKS; ++i) {
+- lock = (int *) XVMCLOCKPTR(dev_priv->sarea_priv, i);
+- if ( (_DRM_LOCKING_CONTEXT( *lock ) == context)) {
+- if (_DRM_LOCK_IS_HELD( *lock ) && (*lock & _DRM_LOCK_CONT)) {
+- DRM_WAKEUP( &(dev_priv->decoder_queue[i]));
++ for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
++ lock = (int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
++ if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
++ if (_DRM_LOCK_IS_HELD(*lock)
++ && (*lock & _DRM_LOCK_CONT)) {
++ DRM_WAKEUP(&(dev_priv->decoder_queue[i]));
+ }
+ *lock = 0;
+ }
+- }
+-}
++ }
++}
+
+-int
+-via_decoder_futex(DRM_IOCTL_ARGS)
++int via_decoder_futex(DRM_IOCTL_ARGS)
+ {
+ DRM_DEVICE;
+ drm_via_futex_t fx;
+@@ -95,4 +92,3 @@ via_decoder_futex(DRM_IOCTL_ARGS)
+ }
+ return 0;
+ }
+-
+diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
+--- a/drivers/char/dsp56k.c
++++ b/drivers/char/dsp56k.c
+@@ -515,7 +515,7 @@ static int __init dsp56k_init_driver(voi
+ 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
+--- a/drivers/char/epca.c
++++ b/drivers/char/epca.c
+@@ -3113,6 +3113,7 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
+ 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
+--- a/drivers/char/ftape/zftape/zftape-init.c
++++ b/drivers/char/ftape/zftape/zftape-init.c
+@@ -331,27 +331,27 @@ KERN_INFO
+
+ 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
+--- a/drivers/char/hangcheck-timer.c
++++ b/drivers/char/hangcheck-timer.c
+@@ -117,7 +117,7 @@ __setup("hcheck_reboot", hangcheck_parse
+ __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
+--- 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 hpets {
+ 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 @@ static struct hpets *hpets;
+ #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 @@ static irqreturn_t hpet_interrupt(int ir
+ 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 @@ static irqreturn_t hpet_interrupt(int ir
+ &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 @@ static int hpet_mmap(struct file *file,
+
+ 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 @@ static int hpet_ioctl_ieon(struct hpet_d
+ 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 @@ static int hpet_ioctl_ieon(struct hpet_d
+ }
+
+ 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 @@ static int hpet_ioctl_ieon(struct hpet_d
+ 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 @@ hpet_ioctl_common(struct hpet_dev *devp,
+ {
+ 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 @@ hpet_ioctl_common(struct hpet_dev *devp,
+ 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 @@ static struct file_operations hpet_fops
+ .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 @@ int hpet_register(struct hpet_task *tp,
+ return -EINVAL;
+ }
+
++ tp->ht_opaque = NULL;
++
+ spin_lock_irq(&hpet_task_lock);
+ spin_lock(&hpet_lock);
+
+@@ -702,15 +742,14 @@ static void hpet_register_interpolator(s
+ #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 @@ static unsigned long hpet_calibrate(stru
+ 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 @@ int hpet_alloc(struct hpet_data *hdp)
+ 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 @@ int hpet_alloc(struct hpet_data *hdp)
+
+ 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 @@ int hpet_alloc(struct hpet_data *hdp)
+ 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 @@ static acpi_status hpet_resources(struct
+ struct hpet_data *hdp;
+ acpi_status status;
+ struct acpi_resource_address64 addr;
+- struct hpets *hpetp;
+
+ hdp = data;
+
+@@ -893,9 +931,29 @@ static acpi_status hpet_resources(struct
+ 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/hvc_vio.c b/drivers/char/hvc_vio.c
+--- a/drivers/char/hvc_vio.c
++++ b/drivers/char/hvc_vio.c
+@@ -95,11 +95,11 @@ static int __devexit hvc_vio_remove(stru
+ }
+
+ static struct vio_driver hvc_vio_driver = {
+- .name = hvc_driver_name,
+ .id_table = hvc_driver_table,
+ .probe = hvc_vio_probe,
+ .remove = hvc_vio_remove,
+ .driver = {
++ .name = hvc_driver_name,
+ .owner = THIS_MODULE,
+ }
+ };
+diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
+--- a/drivers/char/hvcs.c
++++ b/drivers/char/hvcs.c
+@@ -720,10 +720,13 @@ static int __devexit hvcs_remove(struct
+ };
+
+ static struct vio_driver hvcs_vio_driver = {
+- .name = hvcs_driver_name,
+ .id_table = hvcs_driver_table,
+ .probe = hvcs_probe,
+ .remove = hvcs_remove,
++ .driver = {
++ .name = hvcs_driver_name,
++ .owner = THIS_MODULE,
++ }
+ };
+
+ /* Only called from hvcs_get_pi please */
+diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
+--- a/drivers/char/ip2main.c
++++ b/drivers/char/ip2main.c
+@@ -721,8 +721,9 @@ ip2_loadmain(int *iop, int *irqp, unsign
+ }
+
+ 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 @@ ip2_loadmain(int *iop, int *irqp, unsign
+ 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
+--- a/drivers/char/ipmi/ipmi_devintf.c
++++ b/drivers/char/ipmi/ipmi_devintf.c
+@@ -798,7 +798,7 @@ static void ipmi_new_smi(int if_num)
+ 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
+--- a/drivers/char/istallion.c
++++ b/drivers/char/istallion.c
+@@ -5246,7 +5246,8 @@ int __init stli_init(void)
+ 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
+--- a/drivers/char/lcd.c
++++ b/drivers/char/lcd.c
+@@ -575,8 +575,8 @@ static inline int button_pressed(void)
+
+ 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
+--- a/drivers/char/lcd.h
++++ b/drivers/char/lcd.h
+@@ -22,7 +22,7 @@ static int timeout(volatile unsigned lon
+ #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
+--- a/drivers/char/lp.c
++++ b/drivers/char/lp.c
+@@ -805,7 +805,7 @@ static int lp_register(int nr, struct pa
+ 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
+--- a/drivers/char/mem.c
++++ b/drivers/char/mem.c
+@@ -231,9 +231,7 @@ static ssize_t write_mem(struct file * f
+ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+ {
+ #if defined(__HAVE_PHYS_MEM_ACCESS_PROT)
+- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+-
+- vma->vm_page_prot = phys_mem_access_prot(file, offset,
++ vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ #elif defined(pgprot_noncached)
+@@ -920,7 +918,8 @@ static int __init chr_dev_init(void)
+
+ 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
+--- a/drivers/char/misc.c
++++ b/drivers/char/misc.c
+@@ -234,7 +234,7 @@ int misc_register(struct miscdevice * mi
+ }
+ 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
+--- a/drivers/char/mmtimer.c
++++ b/drivers/char/mmtimer.c
+@@ -441,7 +441,7 @@ static irqreturn_t
+ 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 @@ static int sgi_timer_set(struct k_itimer
+ */
+ 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
+--- 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
+--- 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
+--- 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 @@ atari_proc_infos(unsigned char *nvram, c
+
+ #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
+--- a/drivers/char/ppdev.c
++++ b/drivers/char/ppdev.c
+@@ -752,7 +752,7 @@ static struct file_operations pp_fops =
+
+ 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
+--- a/drivers/char/qtronix.c
++++ b/drivers/char/qtronix.c
+@@ -591,6 +591,11 @@ static int __init psaux_init(void)
+ 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
+--- a/drivers/char/raw.c
++++ b/drivers/char/raw.c
+@@ -128,7 +128,7 @@ raw_ioctl(struct inode *inode, struct fi
+ 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 @@ static int __init raw_init(void)
+ 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
+--- a/drivers/char/rocket.c
++++ b/drivers/char/rocket.c
+@@ -256,7 +256,6 @@ static int sInitController(CONTROLLER_T
+ 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_PARM_DESC(pc104_3, "set interface
+ 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 @@ static struct tty_operations rocket_ops
+ /*
+ * 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 @@ int __init rp_init(void)
+ return 0;
+ }
+
+-#ifdef MODULE
+
+ static void rp_cleanup_module(void)
+ {
+@@ -2530,7 +2525,6 @@ static void rp_cleanup_module(void)
+ if (controller)
+ release_region(controller, 4);
+ }
+-#endif
+
+ /***************************************************************************
+ Function: sInitController
+diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
+--- a/drivers/char/s3c2410-rtc.c
++++ b/drivers/char/s3c2410-rtc.c
+@@ -20,7 +20,7 @@
+ #include <linux/fs.h>
+ #include <linux/string.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/rtc.h>
+ #include <linux/bcd.h>
+@@ -519,30 +519,28 @@ static struct timespec s3c2410_rtc_delta
+
+ 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
+--- a/drivers/char/ser_a2232.c
++++ b/drivers/char/ser_a2232.c
+@@ -790,7 +790,7 @@ static int __init a2232board_init(void)
+
+ }
+
+- 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
+--- a/drivers/char/snsc.c
++++ b/drivers/char/snsc.c
+@@ -377,7 +377,7 @@ scdrv_init(void)
+ 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 @@ scdrv_init(void)
+ }
+ 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 @@ scdrv_init(void)
+ 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
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -48,6 +48,7 @@
+ #include <linux/dmi.h>
+ #include <linux/err.h>
+ #include <linux/kfifo.h>
++#include <linux/platform_device.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -424,10 +425,6 @@ static struct sonypi_eventtypes {
+
+ #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 +487,8 @@ static struct sonypi_device {
+ 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 +776,8 @@ static void input_keyrelease(void *data)
+
+ 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 +1168,17 @@ static int sonypi_disable(void)
+ #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 +1198,47 @@ static struct device_driver sonypi_drive
+ .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 +1334,10 @@ static int __devinit sonypi_probe(void)
+ }
+
+ 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 +1387,9 @@ static int __devinit sonypi_probe(void)
+ 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 +1415,8 @@ static void __devexit sonypi_remove(void
+ 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
+--- 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 at email.enst.fr)
+- *
++ *
+ */
+
+ #define VERSION "1.11"
+@@ -154,7 +154,7 @@ static int sx_poll = HZ;
+
+
+
+-/*
++/*
+ * 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 DECLARE_MUTEX(tmp_buf_sem);
+
+ 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 @@ static inline int sx_paranoia_check(stru
+ 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 @@ static inline int sx_paranoia_check(stru
+
+
+ /*
+- *
++ *
+ * Service functions for specialix IO8+ driver.
+- *
++ *
+ */
+
+ /* Get board number from pointer */
+@@ -246,7 +246,7 @@ static inline int board_No (struct speci
+ /* 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 @@ static inline void sx_wait_CCR(struct sp
+ return;
+ udelay (1);
+ }
+-
++
+ printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
+ }
+
+@@ -329,7 +329,7 @@ static inline void sx_wait_CCR_off(struc
+ return;
+ udelay (1);
+ }
+-
++
+ printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
+ }
+
+@@ -338,34 +338,28 @@ static inline void sx_wait_CCR_off(struc
+ * 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 @@ static int sx_set_irq ( struct specialix
+ 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 @@ static int sx_init_CD186x(struct special
+ 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 @@ static int read_cross_byte (struct speci
+ 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 @@ void missed_irq (unsigned long data)
+ 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 @@ static int sx_probe(struct specialix_boa
+
+ func_enter();
+
+- if (sx_check_io_range(bp)) {
++ if (sx_request_io_range(bp)) {
+ func_exit();
+ return 1;
+ }
+@@ -509,15 +503,16 @@ static int sx_probe(struct specialix_boa
+ 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 @@ static int sx_probe(struct specialix_boa
+ 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 @@ static int sx_probe(struct specialix_boa
+ 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 @@ static int sx_probe(struct specialix_boa
+ }
+
+ 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 @@ static int sx_probe(struct specialix_boa
+ #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 @@ static int sx_probe(struct specialix_boa
+ return 0;
+ }
+
+-/*
+- *
++/*
++ *
+ * Interrupt processing routines.
+ * */
+
+@@ -657,7 +655,7 @@ static inline struct specialix_port * sx
+ 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 @@ static inline void sx_receive_exc(struct
+ 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 @@ static inline void sx_receive_exc(struct
+ 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 @@ static inline void sx_receive(struct spe
+ 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 @@ static inline void sx_transmit(struct sp
+ }
+ 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 @@ static inline void sx_transmit(struct sp
+ 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 @@ static inline void sx_transmit(struct sp
+ func_exit();
+ return;
+ }
+-
++
+ if (port->break_length) {
+ if (port->break_length > 0) {
+ if (port->COR2 & COR2_ETC) {
+@@ -831,7 +829,7 @@ static inline void sx_transmit(struct sp
+ func_exit();
+ return;
+ }
+-
++
+ count = CD186x_NFIFO;
+ do {
+ sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
+@@ -839,7 +837,7 @@ static inline void sx_transmit(struct sp
+ 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 @@ static inline void sx_check_modem(struct
+ 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 @@ static inline void sx_check_modem(struct
+ 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 @@ static inline void sx_check_modem(struct
+ 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 @@ static irqreturn_t sx_interrupt(int irq,
+ 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 @@ static irqreturn_t sx_interrupt(int irq,
+ 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 @@ static irqreturn_t sx_interrupt(int irq,
+ } 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 @@ static inline int sx_setup_board(struct
+ {
+ 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 @@ static inline int sx_setup_board(struct
+ 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 @@ static inline void sx_shutdown_board(str
+ }
+
+ 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 @@ static inline void sx_shutdown_board(str
+
+
+ /*
+- * 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static void sx_change_speed(struct speci
+ 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 @@ static int sx_setup_port(struct speciali
+ 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 @@ static int sx_setup_port(struct speciali
+ }
+ 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 @@ static int sx_setup_port(struct speciali
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+-
++
+ func_exit();
+ return 0;
+ }
+@@ -1352,14 +1350,14 @@ static void sx_shutdown_port(struct spec
+ 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 @@ static void sx_shutdown_port(struct spec
+ 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 @@ static int block_til_ready(struct tty_st
+ 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 @@ static int block_til_ready(struct tty_st
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+- retval = -ERESTARTSYS;
++ retval = -ERESTARTSYS;
+ break;
+ }
+ if (!(port->flags & ASYNC_CLOSING) &&
+@@ -1506,7 +1504,7 @@ static int block_til_ready(struct tty_st
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ func_exit();
+ return 0;
+-}
++}
+
+
+ static int sx_open(struct tty_struct * tty, struct file * filp)
+@@ -1526,7 +1524,7 @@ static int sx_open(struct tty_struct * t
+ 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 @@ static int sx_open(struct tty_struct * t
+ func_enter();
+ return error;
+ }
+-
++
+ if ((error = block_til_ready(tty, filp, port))) {
+ func_enter();
+ return error;
+@@ -1574,7 +1572,7 @@ static void sx_close(struct tty_struct *
+ 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 @@ static void sx_close(struct tty_struct *
+ 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 @@ static void sx_close(struct tty_struct *
+ }
+ 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 void sx_close(struct tty_struct *
+ }
+
+
+-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 @@ static int sx_write(struct tty_struct *
+ func_exit();
+ return 0;
+ }
+-
++
+ bp = port_Board(port);
+
+ if (!tty || !port->xmit_buf || !tmp_buf) {
+@@ -1824,7 +1822,7 @@ static int sx_chars_in_buffer(struct tty
+ 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 @@ static int sx_tiocmget(struct tty_struct
+ 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 @@ static inline void sx_send_break(struct
+ {
+ struct specialix_board *bp = port_Board(port);
+ unsigned long flags;
+-
++
+ func_enter();
+
+ spin_lock_irqsave (&port->lock, flags);
+@@ -1996,8 +1994,8 @@ static inline int sx_set_serial_info(str
+ 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 @@ static inline int sx_set_serial_info(str
+ 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 @@ static inline int sx_get_serial_info(str
+ {
+ struct serial_struct tmp;
+ struct specialix_board *bp = port_Board(port);
+-
++
+ func_enter();
+
+ /*
+@@ -2074,7 +2072,7 @@ static inline int sx_get_serial_info(str
+ }
+
+
+-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 @@ static int sx_ioctl(struct tty_struct *
+ func_exit();
+ return -ENODEV;
+ }
+-
++
+ switch (cmd) {
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ retval = tty_check_change(tty);
+@@ -2129,7 +2127,7 @@ static int sx_ioctl(struct tty_struct *
+ 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 @@ static void sx_throttle(struct tty_struc
+ 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 @@ static void sx_unthrottle(struct tty_str
+ 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 @@ static void sx_stop(struct tty_struct *
+ 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 @@ static void sx_start(struct tty_struct *
+ 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 @@ static void sx_start(struct tty_struct *
+ *
+ * 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 @@ static void sx_hangup(struct tty_struct
+ 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 @@ static void sx_set_termios(struct tty_st
+ 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 @@ static int sx_init_drivers(void)
+ 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 @@ static int sx_init_drivers(void)
+ init_waitqueue_head(&sx_port[i].close_wait);
+ spin_lock_init(&sx_port[i].lock);
+ }
+-
++
+ func_exit();
+ return 0;
+ }
+@@ -2472,8 +2470,8 @@ static void sx_release_drivers(void)
+ 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 @@ static int __init specialix_init(void)
+ #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 @@ static int __init specialix_init(void)
+ 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 @@ static int __init specialix_init(void)
+ 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 @@ module_param(sx_poll, int, 0);
+ /*
+ * 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 @@ static int __init specialix_init_module(
+
+ 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
+--- a/drivers/char/stallion.c
++++ b/drivers/char/stallion.c
+@@ -3095,7 +3095,9 @@ static int __init stl_init(void)
+ 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
+--- a/drivers/char/synclink.c
++++ b/drivers/char/synclink.c
+@@ -912,6 +912,7 @@ MODULE_DEVICE_TABLE(pci, synclink_pci_tb
+ 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
+--- a/drivers/char/synclinkmp.c
++++ b/drivers/char/synclinkmp.c
+@@ -500,6 +500,7 @@ MODULE_DEVICE_TABLE(pci, synclinkmp_pci_
+ 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/tb0219.c b/drivers/char/tb0219.c
+--- a/drivers/char/tb0219.c
++++ b/drivers/char/tb0219.c
+@@ -17,7 +17,7 @@
+ * 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/device.h>
++#include <linux/platform_device.h>
+ #include <linux/fs.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
+--- a/drivers/char/tipar.c
++++ b/drivers/char/tipar.c
+@@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *p
+ 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
+--- /dev/null
++++ b/drivers/char/tlclk.c
+@@ -0,0 +1,897 @@
++/*
++ * 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 at ca.kontron.com> and the current
++ * Maintainer <mark.gross at 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 <linux/platform_device.h>
++#include <asm/io.h> /* inb/outb */
++#include <asm/uaccess.h>
++
++MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard at 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
+--- a/drivers/char/tpm/tpm.c
++++ b/drivers/char/tpm/tpm.c
+@@ -64,7 +64,7 @@ static ssize_t tpm_transmit(struct tpm_c
+ 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 @@ static ssize_t tpm_transmit(struct tpm_c
+ 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 @@ static ssize_t tpm_transmit(struct tpm_c
+
+
+ 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 @@ ssize_t tpm_show_pcrs(struct device *dev
+ __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 @@ ssize_t tpm_show_pcrs(struct device *dev
+ 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 @@ ssize_t tpm_show_pubek(struct device *de
+ 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 @@ out:
+ kfree(data);
+ return rc;
+ }
+-
+ EXPORT_SYMBOL_GPL(tpm_show_pubek);
+
+ #define CAP_VER_RESULT_SIZE 18
+@@ -274,8 +271,7 @@ ssize_t tpm_show_caps(struct device *dev
+ 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 @@ ssize_t tpm_store_cancel(struct device *
+ }
+ EXPORT_SYMBOL_GPL(tpm_store_cancel);
+
+-
+ /*
+ * Device file system interface to the TPM
+ */
+@@ -339,21 +334,20 @@ int tpm_open(struct inode *inode, struct
+ }
+
+ 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 @@ err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+ }
+-
+ EXPORT_SYMBOL_GPL(tpm_open);
+
+ int tpm_release(struct inode *inode, struct file *file)
+@@ -378,15 +371,14 @@ int tpm_release(struct inode *inode, str
+ 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 @@ ssize_t tpm_write(struct file * file, co
+
+ 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 @@ ssize_t tpm_read(struct file * file, cha
+
+ 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 @@ void __devexit tpm_remove(struct pci_dev
+
+ 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 @@ static u8 savestate[] = {
+ * 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 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
+ * 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 tpm_register_hardware(struct pci_dev
+ 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 @@ int tpm_register_hardware(struct pci_dev
+
+ 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 @@ dev_num_search_complete:
+ 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 @@ dev_num_search_complete:
+
+ 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 at watson.ibm.com)");
+diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
+--- a/drivers/char/tpm/tpm.h
++++ b/drivers/char/tpm/tpm.h
+@@ -24,6 +24,7 @@
+ #include <linux/delay.h>
+ #include <linux/fs.h>
+ #include <linux/miscdevice.h>
++#include <linux/platform_device.h>
+
+ enum tpm_timeout {
+ TPM_TIMEOUT = 5, /* msecs */
+@@ -55,12 +56,13 @@ struct tpm_vendor_specific {
+ 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 +93,13 @@ static inline void tpm_write_index(int b
+ 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
+--- a/drivers/char/tpm/tpm_atmel.c
++++ b/drivers/char/tpm/tpm_atmel.c
+@@ -19,6 +19,7 @@
+ *
+ */
+
++#include <linux/platform_device.h>
+ #include "tpm.h"
+
+ /* Atmel definitions */
+@@ -40,7 +41,7 @@ enum tpm_atmel_read_status {
+ 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 +55,7 @@ static int tpm_atml_recv(struct tpm_chip
+ 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 +67,12 @@ static int tpm_atml_recv(struct tpm_chip
+ 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 +84,7 @@ static int tpm_atml_recv(struct tpm_chip
+ 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 +94,20 @@ static int tpm_atml_recv(struct tpm_chip
+ /* 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 +119,11 @@ static void tpm_atml_cancel(struct tpm_c
+ 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 +143,7 @@ static struct attribute* atmel_attrs[] =
+ &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 +152,7 @@ static struct tpm_vendor_specific tpm_at
+ .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 +160,94 @@ static struct tpm_vendor_specific tpm_at
+ .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)
++{
++ 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 atml_drv = {
++ .name = "tpm_atmel",
++ .bus = &platform_bus_type,
++ .owner = THIS_MODULE,
++ .suspend = tpm_pm_suspend,
++ .resume = tpm_pm_resume,
++};
++
++static int __init init_atmel(void)
+ {
+- u8 version[4];
+ int rc = 0;
+ int lo, hi;
+
+- if (pci_enable_device(pci_dev))
+- return -EIO;
++ 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;
+- 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;
++ return -ENODEV;
+ }
+
+- /* 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]);
++ /* verify chip version number is 1.1 */
++ if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) ||
++ (tpm_read_index(TPM_ADDR, 0x01) != 0x01 ))
++ return -ENODEV;
+
+- 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,}
+-};
++ pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
++ if ( !pdev )
++ return -ENOMEM;
+
+-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
++ pdev->name = "tpm_atmel0";
++ pdev->id = -1;
++ pdev->num_resources = 0;
++ pdev->dev.release = tpm_atml_remove;
++ pdev->dev.driver = &atml_drv;
+
+-static struct pci_driver atmel_pci_driver = {
+- .name = "tpm_atmel",
+- .id_table = tpm_pci_tbl,
+- .probe = tpm_atml_init,
+- .remove = __devexit_p(tpm_remove),
+- .suspend = tpm_pm_suspend,
+- .resume = tpm_pm_resume,
+-};
++ if ((rc = platform_device_register(pdev)) < 0) {
++ kfree(pdev);
++ pdev = NULL;
++ return rc;
++ }
+
+-static int __init init_atmel(void)
+-{
+- return pci_register_driver(&atmel_pci_driver);
++ 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
+--- 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 at 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 @@ static int wait(struct tpm_chip *chip, i
+ }
+ 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 wait_and_send(struct tpm_chi
+ 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(struct tpm_chip *chi
+
+ 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 @@ recv_begin:
+ }
+
+ 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 @@ recv_begin:
+ }
+
+ 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 @@ recv_begin:
+ }
+
+ 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 @@ recv_begin:
+ }
+
+ 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 @@ static int tpm_inf_send(struct tpm_chip
+
+ 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 void tpm_inf_cancel(struct tpm_ch
+ */
+ }
+
++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 @@ static struct tpm_vendor_specific tpm_in
+ .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 @@ static const struct pnp_device_id tpm_pn
+ {"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 @@ static int __devinit tpm_inf_probe(struc
+ 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 @@ static int __devinit tpm_inf_probe(struc
+
+ 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 @@ static int __devinit tpm_inf_probe(struc
+ 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 @@ static int __devinit tpm_inf_probe(struc
+ 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 @@ static int __devinit tpm_inf_probe(struc
+ "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,}
+-};
+-
+-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+-
+-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 __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
++{
++ struct tpm_chip *chip = pnp_get_drvdata(dev);
++
++ if (chip) {
++ release_region(chip->vendor->base, TPM_INF_PORT_LEN);
++ tpm_remove_hardware(chip->dev);
++ }
++}
++
++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_exit(cleanup_inf);
+
+ MODULE_AUTHOR("Marcel Selhorst <selhorst at 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
+--- a/drivers/char/tpm/tpm_nsc.c
++++ b/drivers/char/tpm/tpm_nsc.c
+@@ -19,6 +19,7 @@
+ *
+ */
+
++#include <linux/platform_device.h>
+ #include "tpm.h"
+
+ /* National definitions */
+@@ -111,7 +112,7 @@ static int nsc_wait_for_ready(struct tpm
+ }
+ 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 +128,12 @@ static int tpm_nsc_recv(struct tpm_chip
+ 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 +142,7 @@ static int tpm_nsc_recv(struct tpm_chip
+ 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 +153,11 @@ static int tpm_nsc_recv(struct tpm_chip
+
+ 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 +188,19 @@ static int tpm_nsc_send(struct tpm_chip
+ 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 +208,7 @@ static int tpm_nsc_send(struct tpm_chip
+ }
+
+ 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 +221,11 @@ static void tpm_nsc_cancel(struct tpm_ch
+ 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 +245,7 @@ static struct attribute * nsc_attrs[] =
+ &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 +254,7 @@ static struct tpm_vendor_specific tpm_ns
+ .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 +262,32 @@ static struct tpm_vendor_specific tpm_ns
+ .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 +296,71 @@ static int __devinit tpm_nsc_init(struct
+ 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 +369,23 @@ static int __devinit tpm_nsc_init(struct
+ 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
+--- a/drivers/char/tty_io.c
++++ b/drivers/char/tty_io.c
+@@ -809,7 +809,7 @@ static void do_tty_hangup(void *data)
+ 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 @@ void tty_register_device(struct tty_driv
+ 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 @@ static int __init tty_init(void)
+ 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 @@ static int __init tty_init(void)
+ 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 @@ static int __init tty_init(void)
+ 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
+--- a/drivers/char/vc_screen.c
++++ b/drivers/char/vc_screen.c
+@@ -484,8 +484,10 @@ void vcs_make_devfs(struct tty_struct *t
+ 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 @@ int __init vcs_init(void)
+
+ 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
+--- a/drivers/char/viotape.c
++++ b/drivers/char/viotape.c
+@@ -956,9 +956,9 @@ static int viotape_probe(struct vio_dev
+ 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);
+@@ -993,13 +993,16 @@ static struct vio_device_id viotape_devi
+ { "viotape", "" },
+ { "", "" }
+ };
+-
+ MODULE_DEVICE_TABLE(vio, viotape_device_table);
++
+ static struct vio_driver viotape_driver = {
+- .name = "viotape",
+ .id_table = viotape_device_table,
+ .probe = viotape_probe,
+- .remove = viotape_remove
++ .remove = viotape_remove,
++ .driver = {
++ .name = "viotape",
++ .owner = THIS_MODULE,
++ }
+ };
+
+
+diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
+--- a/drivers/char/vr41xx_giu.c
++++ b/drivers/char/vr41xx_giu.c
+@@ -19,7 +19,7 @@
+ * 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/device.h>
++#include <linux/platform_device.h>
+ #include <linux/errno.h>
+ #include <linux/fs.h>
+ #include <linux/init.h>
+diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c
+--- a/drivers/char/vr41xx_rtc.c
++++ b/drivers/char/vr41xx_rtc.c
+@@ -17,7 +17,7 @@
+ * 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/device.h>
++#include <linux/platform_device.h>
+ #include <linux/fs.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
+--- a/drivers/char/vt_ioctl.c
++++ b/drivers/char/vt_ioctl.c
+@@ -192,6 +192,9 @@ do_kdgkb_ioctl(int cmd, struct kbsentry
+ 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
+--- 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
+--- 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/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
+--- a/drivers/char/watchdog/mpcore_wdt.c
++++ b/drivers/char/watchdog/mpcore_wdt.c
+@@ -29,7 +29,7 @@
+ #include <linux/reboot.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/hardware/arm_twd.h>
+ #include <asm/uaccess.h>
+@@ -396,6 +396,7 @@ static int __devexit mpcore_wdt_remove(s
+ }
+
+ static struct device_driver mpcore_wdt_driver = {
++ .owner = THIS_MODULE,
+ .name = "mpcore_wdt",
+ .bus = &platform_bus_type,
+ .probe = mpcore_wdt_probe,
+diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
+--- a/drivers/char/watchdog/mv64x60_wdt.c
++++ b/drivers/char/watchdog/mv64x60_wdt.c
+@@ -22,6 +22,8 @@
+ #include <linux/miscdevice.h>
+ #include <linux/module.h>
+ #include <linux/watchdog.h>
++#include <linux/platform_device.h>
++
+ #include <asm/mv64x60.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -211,6 +213,7 @@ static int __devexit mv64x60_wdt_remove(
+ }
+
+ static struct device_driver mv64x60_wdt_driver = {
++ .owner = THIS_MODULE,
+ .name = MV64x60_WDT_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv64x60_wdt_probe,
+diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
+--- 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
+--- a/drivers/char/watchdog/pcwd_pci.c
++++ b/drivers/char/watchdog/pcwd_pci.c
+@@ -1,7 +1,7 @@
+ /*
+ * Berkshire PCI-PC Watchdog Card Driver
+ *
+- * (c) Copyright 2003 Wim Van Sebroeck <wim at iguana.be>.
++ * (c) Copyright 2003-2005 Wim Van Sebroeck <wim at iguana.be>.
+ *
+ * Based on source code of the following authors:
+ * Ken Hollis <kenji at bitgate.com>,
+@@ -21,7 +21,9 @@
+ */
+
+ /*
+- * A bells and whistles driver is available from http://www.pcwd.de/
++ * A bells and whistles driver is available from:
++ * http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/
++ *
+ * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
+ */
+
+@@ -753,6 +755,7 @@ static struct pci_device_id pcipcwd_pci_
+ 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
+--- a/drivers/char/watchdog/s3c2410_wdt.c
++++ b/drivers/char/watchdog/s3c2410_wdt.c
+@@ -44,7 +44,7 @@
+ #include <linux/watchdog.h>
+ #include <linux/fs.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+
+ #include <asm/uaccess.h>
+@@ -464,32 +464,28 @@ static void s3c2410wdt_shutdown(struct d
+ 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;
+ }
+@@ -501,6 +497,7 @@ static int s3c2410wdt_resume(struct devi
+
+
+ static struct device_driver s3c2410wdt_driver = {
++ .owner = THIS_MODULE,
+ .name = "s3c2410-wdt",
+ .bus = &platform_bus_type,
+ .probe = s3c2410wdt_probe,
+diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
+--- 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
+--- 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/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
+--- a/drivers/char/watchdog/w83627hf_wdt.c
++++ b/drivers/char/watchdog/w83627hf_wdt.c
+@@ -359,5 +359,5 @@ module_exit(wdt_exit);
+
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Pádraig Brady <P at draigBrady.com>");
+-MODULE_DESCRIPTION("w38627hf WDT driver");
++MODULE_DESCRIPTION("w83627hf WDT driver");
+ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
+--- a/drivers/char/watchdog/wdt_pci.c
++++ b/drivers/char/watchdog/wdt_pci.c
+@@ -711,6 +711,7 @@ MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl)
+
+
+ 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
+--- 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 at brodo.de>
+ *
++ * Oct 2005 - Ashok Raj <ashok.raj at 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 struct cpufreq_policy *cpufreq_cp
+ 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 @@ static int cpufreq_add_dev (struct sys_d
+ 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 @@ static int cpufreq_add_dev (struct sys_d
+ * 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 @@ static int cpufreq_add_dev (struct sys_d
+ }
+
+ module_put(cpufreq_driver->owner);
+- cpu_sys_devices[cpu] = sys_dev;
+ dprintk("initialization complete\n");
+ cpufreq_debug_enable_ratelimit();
+
+@@ -682,7 +679,7 @@ err_out:
+
+ nomem_out:
+ module_put(cpufreq_driver->owner);
+- module_out:
++module_out:
+ cpufreq_debug_enable_ratelimit();
+ return ret;
+ }
+@@ -698,6 +695,7 @@ static int cpufreq_remove_dev (struct sy
+ 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 @@ static int cpufreq_remove_dev (struct sy
+
+ if (!data) {
+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+- cpu_sys_devices[cpu] = NULL;
+ cpufreq_debug_enable_ratelimit();
+ return -EINVAL;
+ }
+@@ -725,14 +722,12 @@ static int cpufreq_remove_dev (struct sy
+ 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 @@ static int cpufreq_remove_dev (struct sy
+ 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 @@ static int cpufreq_remove_dev (struct sy
+ 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 @@ int __cpufreq_driver_target(struct cpufr
+ 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 at 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 @@ int cpufreq_update_policy(unsigned int c
+ }
+ 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 @@ int cpufreq_register_driver(struct cpufr
+ }
+
+ 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 @@ int cpufreq_unregister_driver(struct cpu
+ 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
+--- 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 @@ cpufreq_stat_notifier_trans (struct noti
+ 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 @@ __init cpufreq_stats_init(void)
+ {
+ int ret;
+ unsigned int cpu;
++
+ spin_lock_init(&cpufreq_stats_lock);
+ if ((ret = cpufreq_register_notifier(¬ifier_policy_block,
+ CPUFREQ_POLICY_NOTIFIER)))
+@@ -323,20 +346,31 @@ __init cpufreq_stats_init(void)
+ 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(¬ifier_policy_block,
+ CPUFREQ_POLICY_NOTIFIER);
+ cpufreq_unregister_notifier(¬ifier_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 at intel.com>");
+diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -2,7 +2,7 @@ menu "Hardware crypto devices"
+
+ 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/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
+--- a/drivers/eisa/virtual_root.c
++++ b/drivers/eisa/virtual_root.c
+@@ -9,7 +9,7 @@
+
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/eisa.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -70,8 +70,7 @@ config DELL_RBU
+
+ 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/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
+--- a/drivers/firmware/dcdbas.c
++++ b/drivers/firmware/dcdbas.c
+@@ -20,7 +20,7 @@
+ * GNU General Public License for more details.
+ */
+
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
+--- a/drivers/firmware/dell_rbu.c
++++ b/drivers/firmware/dell_rbu.c
+@@ -41,7 +41,7 @@
+ #include <linux/string.h>
+ #include <linux/errno.h>
+ #include <linux/blkdev.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/spinlock.h>
+ #include <linux/moduleparam.h>
+ #include <linux/firmware.h>
+diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
+--- a/drivers/hwmon/adm1021.c
++++ b/drivers/hwmon/adm1021.c
+@@ -121,7 +121,7 @@ static int adm1021_write_value(struct i2
+ 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 @@ static int adm1021_detect(struct i2c_ada
+ 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
+--- a/drivers/hwmon/adm1025.c
++++ b/drivers/hwmon/adm1025.c
+@@ -331,11 +331,10 @@ static int adm1025_detect(struct i2c_ada
+ 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
+--- a/drivers/hwmon/adm1026.c
++++ b/drivers/hwmon/adm1026.c
+@@ -315,7 +315,7 @@ static struct i2c_driver adm1026_driver
+ .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 @@ int adm1026_attach_adapter(struct i2c_ad
+ 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 @@ int adm1026_detach_client(struct i2c_cli
+ 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 @@ int adm1026_read_value(struct i2c_client
+ 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 @@ int adm1026_write_value(struct i2c_clien
+ 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_init_client(struct i2c_clie
+ }
+ }
+
+-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_print_gpio(struct i2c_clien
+ }
+ }
+
+-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(temp1_auto_point2_pwm
+ 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 @@ int adm1026_detect(struct i2c_adapter *a
+ 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
+--- a/drivers/hwmon/adm1031.c
++++ b/drivers/hwmon/adm1031.c
+@@ -740,11 +740,10 @@ static int adm1031_detect(struct i2c_ada
+ 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
+--- 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 @@ I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm8
+ #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 @@ struct adm9240_data {
+ 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)
++/*** sysfs accessors ***/
++
++/* temperature */
++static ssize_t show_temp(struct device *dev, struct device_attribute *dummy,
++ char *buf)
+ {
+- return i2c_smbus_read_byte_data(client, reg);
++ struct adm9240_data *data = adm9240_update_device(dev);
++ return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */
+ }
+
+-static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
++static ssize_t show_max(struct device *dev, struct device_attribute *devattr,
++ char *buf)
+ {
+- return i2c_smbus_write_byte_data(client, reg, value);
++ 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);
+ }
+
+-/*** sysfs accessors ***/
++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;
++}
+
+-/* 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; \
+-}
+-
+-set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
+-set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
+-
+-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 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);
+-
+-show_in_offset(0);
+-show_in_offset(1);
+-show_in_offset(2);
+-show_in_offset(3);
+-show_in_offset(4);
+-show_in_offset(5);
++#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);
++
++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 @@ static void adm9240_write_fan_div(struct
+ {
+ 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 @@ static void adm9240_write_fan_div(struct
+ * - 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 @@ static ssize_t set_fan_min(struct device
+ 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 ssize_t show_alarms(struct device
+ 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 ssize_t show_vid(struct device *d
+ 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 @@ static ssize_t set_aout(struct device *d
+
+ 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 @@ static int adm9240_detect(struct i2c_ada
+ 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 @@ static int adm9240_detect(struct i2c_ada
+ 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 @@ static int adm9240_detect(struct i2c_ada
+ }
+
+ /* 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 @@ static int adm9240_detect(struct i2c_ada
+ }
+
+ /* 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 @@ static int adm9240_detect(struct i2c_ada
+ 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 int adm9240_detach_client(struct
+ 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 @@ static void adm9240_init_client(struct i
+
+ 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 @@ static struct adm9240_data *adm9240_upda
+
+ 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 @@ static struct adm9240_data *adm9240_upda
+
+ 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
+--- a/drivers/hwmon/asb100.c
++++ b/drivers/hwmon/asb100.c
+@@ -629,19 +629,17 @@ static int asb100_detect_subclients(stru
+ 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 @@ static int asb100_detect(struct i2c_adap
+ 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
+--- a/drivers/hwmon/atxp1.c
++++ b/drivers/hwmon/atxp1.c
+@@ -253,6 +253,8 @@ static DEVICE_ATTR(gpio2, S_IRUGO | S_IW
+
+ 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 @@ static int atxp1_detect(struct i2c_adapt
+ 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
+--- a/drivers/hwmon/ds1621.c
++++ b/drivers/hwmon/ds1621.c
+@@ -180,12 +180,14 @@ static DEVICE_ATTR(temp1_max, S_IWUSR |
+
+ 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 @@ int ds1621_detect(struct i2c_adapter *ad
+ /* 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
+--- a/drivers/hwmon/fscher.c
++++ b/drivers/hwmon/fscher.c
+@@ -303,11 +303,10 @@ static int fscher_detect(struct i2c_adap
+ /* 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
+--- a/drivers/hwmon/fscpos.c
++++ b/drivers/hwmon/fscpos.c
+@@ -438,7 +438,7 @@ static int fscpos_attach_adapter(struct
+ 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 @@ int fscpos_detect(struct i2c_adapter *ad
+ * 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
+--- a/drivers/hwmon/gl518sm.c
++++ b/drivers/hwmon/gl518sm.c
+@@ -365,11 +365,10 @@ static int gl518_detect(struct i2c_adapt
+ 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
+--- a/drivers/hwmon/gl520sm.c
++++ b/drivers/hwmon/gl520sm.c
+@@ -536,11 +536,10 @@ static int gl520_detect(struct i2c_adapt
+ 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
+--- a/drivers/hwmon/hdaps.c
++++ b/drivers/hwmon/hdaps.c
+@@ -27,7 +27,7 @@
+ */
+
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/input.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -296,11 +296,9 @@ static int hdaps_probe(struct device *de
+ 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
+--- a/drivers/hwmon/hwmon.c
++++ b/drivers/hwmon/hwmon.c
+@@ -45,7 +45,7 @@ struct class_device *hwmon_device_regist
+ 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
+--- 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 @@ static int it87_isa_attach_adapter(struc
+ }
+
+ /* 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 @@ exit:
+ }
+
+ /* 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 @@ int it87_detect(struct i2c_adapter *adap
+ 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 struct it87_data *it87_update_dev
+
+ 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
+--- a/drivers/hwmon/lm63.c
++++ b/drivers/hwmon/lm63.c
+@@ -375,11 +375,10 @@ static int lm63_detect(struct i2c_adapte
+ 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
+--- a/drivers/hwmon/lm75.c
++++ b/drivers/hwmon/lm75.c
+@@ -127,11 +127,10 @@ static int lm75_detect(struct i2c_adapte
+ /* 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
+--- a/drivers/hwmon/lm77.c
++++ b/drivers/hwmon/lm77.c
+@@ -226,11 +226,10 @@ static int lm77_detect(struct i2c_adapte
+ /* 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
+--- a/drivers/hwmon/lm78.c
++++ b/drivers/hwmon/lm78.c
+@@ -480,7 +480,7 @@ static int lm78_isa_attach_adapter(struc
+ }
+
+ /* 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 @@ int lm78_detect(struct i2c_adapter *adap
+ 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 @@ static int lm78_write_value(struct i2c_c
+ 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
+--- a/drivers/hwmon/lm80.c
++++ b/drivers/hwmon/lm80.c
+@@ -393,7 +393,7 @@ static int lm80_attach_adapter(struct i2
+ 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 @@ int lm80_detect(struct i2c_adapter *adap
+ /* 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
+--- a/drivers/hwmon/lm83.c
++++ b/drivers/hwmon/lm83.c
+@@ -230,11 +230,10 @@ static int lm83_detect(struct i2c_adapte
+ 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
+--- a/drivers/hwmon/lm85.c
++++ b/drivers/hwmon/lm85.c
+@@ -1007,14 +1007,14 @@ temp_auto(1);
+ 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 @@ int lm85_detect(struct i2c_adapter *adap
+ 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 @@ int lm85_detect(struct i2c_adapter *adap
+ 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_detach_client(struct i2c_client
+ }
+
+
+-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 @@ int lm85_read_value(struct i2c_client *c
+ 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 @@ int lm85_write_value(struct i2c_client *
+ 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
+--- a/drivers/hwmon/lm87.c
++++ b/drivers/hwmon/lm87.c
+@@ -554,11 +554,10 @@ static int lm87_detect(struct i2c_adapte
+ 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
+--- 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(temp1_crit_hys
+ 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 @@ static int lm90_detect(struct i2c_adapte
+ 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 @@ static int lm90_detect(struct i2c_adapte
+ 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,
++ ®_config1) < 0
++ || lm90_read_reg(new_client, LM90_REG_R_CONVRATE,
++ ®_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,
++ ®_config2) < 0)
++ goto exit_free;
+
+ if ((reg_config1 & 0x2A) == 0x00
+ && (reg_config2 & 0xF8) == 0x00
+@@ -435,14 +500,12 @@ static int lm90_detect(struct i2c_adapte
+ }
+ } 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 @@ static int lm90_detect(struct i2c_adapte
+ 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 @@ static int lm90_detect(struct i2c_adapte
+ &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 @@ static void lm90_init_client(struct i2c_
+ */
+ 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 @@ static struct lm90_data *lm90_update_dev
+ 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 @@ static struct lm90_data *lm90_update_dev
+ * 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);
+-
+- 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_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;
++
++ 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
+--- a/drivers/hwmon/lm92.c
++++ b/drivers/hwmon/lm92.c
+@@ -300,11 +300,10 @@ static int lm92_detect(struct i2c_adapte
+ | 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
+--- a/drivers/hwmon/max1619.c
++++ b/drivers/hwmon/max1619.c
+@@ -197,11 +197,10 @@ static int max1619_detect(struct i2c_ada
+ 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
+--- a/drivers/hwmon/pc87360.c
++++ b/drivers/hwmon/pc87360.c
+@@ -754,9 +754,8 @@ static int pc87360_detect(struct i2c_ada
+ 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
+--- a/drivers/hwmon/sis5595.c
++++ b/drivers/hwmon/sis5595.c
+@@ -518,11 +518,10 @@ static int sis5595_detect(struct i2c_ada
+ 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
+--- a/drivers/hwmon/smsc47b397.c
++++ b/drivers/hwmon/smsc47b397.c
+@@ -244,11 +244,10 @@ static int smsc47b397_detect(struct i2c_
+ 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 @@ static int __init smsc47b397_find(unsign
+ superio_enter();
+ id = superio_inb(SUPERIO_REG_DEVID);
+
+- if (id != 0x6f) {
++ if ((id != 0x6f) && (id != 0x81)) {
+ superio_exit();
+ return -ENODEV;
+ }
+@@ -310,8 +309,9 @@ static int __init smsc47b397_find(unsign
+ *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
+--- 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 at yahoo.com>
+ Copyright (C) 2004 Jean Delvare <khali at linux-fr.org>
+@@ -356,6 +356,8 @@ static int __init smsc47m1_find(unsigned
+ * 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 @@ static int __init smsc47m1_find(unsigned
+ 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 @@ static int smsc47m1_detect(struct i2c_ad
+ 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
+--- 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 @@ static inline u8 FAN_TO_REG(long rpm, in
+ 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 @@ static inline u8 TEMP_TO_REG(long val)
+ }
+
+ /* 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 @@ static int via686a_detect(struct i2c_ada
+ 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 @@ static int via686a_detect(struct i2c_ada
+ 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 @@ static int via686a_detect(struct i2c_ada
+ 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 @@ static int via686a_detach_client(struct
+ 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
+--- a/drivers/hwmon/w83627ehf.c
++++ b/drivers/hwmon/w83627ehf.c
+@@ -105,7 +105,9 @@ superio_exit(void)
+ * 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 @@ static int w83627ehf_detect(struct i2c_a
+ 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_detach:
+ 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 @@ static int w83627ehf_detach_client(struc
+
+ 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 @@ static int __init w83627ehf_find(int sio
+ 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
+--- a/drivers/hwmon/w83627hf.c
++++ b/drivers/hwmon/w83627hf.c
+@@ -142,10 +142,14 @@ superio_exit(void)
+ #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 @@ superio_exit(void)
+
+ #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 @@ static int __init w83627hf_find(int sioa
+ 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 @@ static int w83627hf_detect(struct i2c_ad
+ 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 @@ static int w83627hf_detect(struct i2c_ad
+ 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 @@ static int w83627hf_detect(struct i2c_ad
+ 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 @@ static int w83627hf_detach_client(struct
+ 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 @@ static int w83627hf_write_value(struct i
+ 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 @@ static void w83627hf_init_client(struct
+ }
+ }
+
+- 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
+--- a/drivers/hwmon/w83781d.c
++++ b/drivers/hwmon/w83781d.c
+@@ -889,12 +889,11 @@ w83781d_detect_subclients(struct i2c_ada
+ 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 @@ w83781d_detect_subclients(struct i2c_ada
+ }
+
+ 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 @@ w83781d_detect(struct i2c_adapter *adapt
+ 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 @@ w83781d_write_value(struct i2c_client *c
+ 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
+--- a/drivers/hwmon/w83792d.c
++++ b/drivers/hwmon/w83792d.c
+@@ -1086,11 +1086,10 @@ w83792d_create_subclient(struct i2c_adap
+ 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 @@ w83792d_detect(struct i2c_adapter *adapt
+ 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 @@ w83792d_write_value(struct i2c_client *c
+ 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
+--- 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 @@ I2C_CLIENT_INSMOD_1(w83l785ts);
+ * 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 @@ struct w83l785ts_data {
+ 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 @@ static int w83l785ts_detect(struct i2c_a
+ 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 @@ static int w83l785ts_detect(struct i2c_a
+ 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 @@ static int w83l785ts_detect(struct i2c_a
+ 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 @@ static struct w83l785ts_data *w83l785ts_
+
+ 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
+--- 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
+--- 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
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -135,11 +135,12 @@ config I2C_I810
+ 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
+--- 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 @@ static int ali1535_setup(struct pci_dev
+ 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 @@ static struct i2c_adapter ali1535_adapte
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+ .algo = &smbus_algorithm,
+- .name = "unset",
+ };
+
+ static struct pci_device_id ali1535_ids[] = {
+@@ -513,6 +513,7 @@ static void __devexit ali1535_remove(str
+ }
+
+ 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
+--- 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 @@ static int __devinit ali1563_setup(struc
+ 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 @@ static struct pci_device_id __devinitdat
+ 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
+--- 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 @@ static int ali15x3_setup(struct pci_dev
+ 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 @@ static struct i2c_adapter ali15x3_adapte
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+ .algo = &smbus_algorithm,
+- .name = "unset",
+ };
+
+ static struct pci_device_id ali15x3_ids[] = {
+@@ -503,6 +504,7 @@ static void __devexit ali15x3_remove(str
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-amd756-s4882.c
++++ b/drivers/i2c/busses/i2c-amd756-s4882.c
+@@ -169,12 +169,12 @@ static int __init amd756_s4882_init(void
+ 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
+--- 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 @@ struct i2c_adapter amd756_smbus = {
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+ .algo = &smbus_algorithm,
+- .name = "unset",
+ };
+
+ enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
+@@ -365,7 +364,7 @@ static int __devinit amd756_probe(struct
+ 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 void __devexit amd756_remove(stru
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-amd8111.c
++++ b/drivers/i2c/busses/i2c-amd8111.c
+@@ -30,6 +30,8 @@ struct amd_smbus {
+ int size;
+ };
+
++static struct pci_driver amd8111_driver;
++
+ /*
+ * AMD PCI control registers definitions.
+ */
+@@ -242,7 +244,6 @@ static s32 amd8111_access(struct i2c_ada
+ 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 @@ static s32 amd8111_access(struct i2c_ada
+ 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 @@ static int __devinit amd8111_probe(struc
+ 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 void __devexit amd8111_remove(str
+ }
+
+ 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
+--- 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 at cc.hut.fi> and even
+ Frodo Looijaard <frodol at 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 wait_queue_head_t pcf_wait;
+ 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);
+-
+- pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val);
++ u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
++ int val = ioread8(address);
+
++ pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val);
+ return (val);
+ }
+
+@@ -149,16 +144,40 @@ static int pcf_isa_init(void)
+ {
+ 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 @@ static struct i2c_adapter pcf_isa_ops =
+ .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 @@ static int __init i2c_pcfisa_init(void)
+
+ /* 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 @@ static int __init i2c_pcfisa_init(void)
+ 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 @@ static int __init i2c_pcfisa_init(void)
+ 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 @@ static void i2c_pcfisa_exit(void)
+ 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 at spacetec.no>");
+diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
+--- a/drivers/i2c/busses/i2c-hydra.c
++++ b/drivers/i2c/busses/i2c-hydra.c
+@@ -155,6 +155,7 @@ static void __devexit hydra_remove(struc
+
+
+ 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
+--- 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 @@ MODULE_PARM_DESC(force_addr,
+ "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 @@ static int i801_setup(struct pci_dev *de
+ }
+ }
+
+- 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 @@ static int i801_transaction(void)
+
+ /* 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 @@ static int i801_block_transaction(union
+ 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 @@ static int i801_block_transaction(union
+ }
+ outb_p(temp, SMBHSTSTS);
+ }
+-#endif
+ result = 0;
+ END:
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+@@ -421,14 +416,13 @@ static s32 i801_access(struct i2c_adapte
+ 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 @@ static s32 i801_access(struct i2c_adapte
+ 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 @@ static s32 i801_access(struct i2c_adapte
+ 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 @@ static u32 i801_func(struct i2c_adapter
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
+-#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 @@ static struct i2c_adapter i801_adapter =
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+ .algo = &smbus_algorithm,
+- .name = "unset",
+ };
+
+ static struct pci_device_id i801_ids[] = {
+@@ -586,6 +560,7 @@ static void __devexit i801_remove(struct
+ }
+
+ 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
+--- 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 void __devexit i810_remove(struct
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-ibm_iic.c
++++ b/drivers/i2c/busses/i2c-ibm_iic.c
+@@ -672,13 +672,12 @@ static int __devinit iic_probe(struct oc
+ 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
+--- a/drivers/i2c/busses/i2c-iop3xx.c
++++ b/drivers/i2c/busses/i2c-iop3xx.c
+@@ -11,7 +11,7 @@
+ *
+ * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
+ *
+- * And which acknowledged Kyösti Mälkki <kmalkki at cc.hut.fi>,
++ * And which acknowledged Kyösti Mälkki <kmalkki at cc.hut.fi>,
+ * Frodo Looijaard <frodol at dds.nl>, Martin Bailey<mbailey at littlefeet-inc.com>
+ *
+ * Major cleanup by Deepak Saxena <dsaxena at plexity.net>, 01/2005:
+@@ -35,7 +35,7 @@
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/i2c.h>
+
+ #include <asm/io.h>
+@@ -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)
+@@ -184,7 +184,7 @@ iop3xx_i2c_wait_event(struct i2c_algo_io
+ do {
+ interrupted = wait_event_interruptible_timeout (
+ iop3xx_adap->waitq,
+- (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
++ (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
+ 1 * HZ;
+ );
+ if ((rc = iop3xx_i2c_error(sr)) < 0) {
+@@ -440,19 +440,17 @@ iop3xx_i2c_probe(struct device *dev)
+ 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) {
+@@ -474,9 +472,10 @@ iop3xx_i2c_probe(struct device *dev)
+ goto release_region;
+ }
+
+- res = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
++ ret = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
+ pdev->name, adapter_data);
+- if (res) {
++
++ if (ret) {
+ ret = -EIO;
+ goto unmap;
+ }
+@@ -525,6 +524,7 @@ out:
+
+
+ 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
+--- a/drivers/i2c/busses/i2c-isa.c
++++ b/drivers/i2c/busses/i2c-isa.c
+@@ -38,6 +38,7 @@
+ #include <linux/errno.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-isa.h>
++#include <linux/platform_device.h>
+
+ static u32 isa_func(struct i2c_adapter *adapter);
+
+@@ -92,6 +93,7 @@ int i2c_isa_add_driver(struct i2c_driver
+
+ /* 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
+--- a/drivers/i2c/busses/i2c-ixp2000.c
++++ b/drivers/i2c/busses/i2c-ixp2000.c
+@@ -28,7 +28,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-bit.h>
+@@ -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 @@ static int ixp2000_i2c_probe(struct devi
+ 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 @@ static int ixp2000_i2c_probe(struct devi
+ 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 int ixp2000_i2c_probe(struct devi
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-ixp4xx.c
++++ b/drivers/i2c/busses/i2c-ixp4xx.c
+@@ -28,13 +28,15 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-bit.h>
+
+ #include <asm/hardware.h> /* Pick up IXP4xx-specific bits */
+
++static 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 @@ static int ixp4xx_i2c_probe(struct devic
+ 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 @@ static int ixp4xx_i2c_probe(struct devic
+ 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 int ixp4xx_i2c_probe(struct devic
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-keywest.c
++++ b/drivers/i2c/busses/i2c-keywest.c
+@@ -535,13 +535,12 @@ create_iface(struct device_node *np, str
+
+ 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 of_device_id i2c_keywest_m
+
+ 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 macio_driver i2c_keywest_m
+
+ 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
+--- a/drivers/i2c/busses/i2c-mpc.c
++++ b/drivers/i2c/busses/i2c-mpc.c
+@@ -19,6 +19,8 @@
+ #include <linux/sched.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
++#include <linux/platform_device.h>
++
+ #include <asm/io.h>
+ #include <linux/fsl_devices.h>
+ #include <linux/i2c.h>
+@@ -296,10 +298,9 @@ static int fsl_i2c_probe(struct device *
+
+ 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 +362,7 @@ static int fsl_i2c_remove(struct device
+
+ /* 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
+--- a/drivers/i2c/busses/i2c-mv64xxx.c
++++ b/drivers/i2c/busses/i2c-mv64xxx.c
+@@ -17,6 +17,8 @@
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
+ #include <linux/mv643xx.h>
++#include <linux/platform_device.h>
++
+ #include <asm/io.h>
+
+ /* Register defines */
+@@ -500,13 +502,10 @@ mv64xxx_i2c_probe(struct device *dev)
+ 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 +569,7 @@ mv64xxx_i2c_remove(struct device *dev)
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-nforce2.c
++++ b/drivers/i2c/busses/i2c-nforce2.c
+@@ -97,6 +97,7 @@ struct nforce2_smbus {
+ #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 @@ static struct i2c_adapter nforce2_adapte
+ .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 @@ static s32 nforce2_access(struct i2c_ada
+ 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 @@ static int __devinit nforce2_probe_smb (
+ 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 @@ static int __devinit nforce2_probe(struc
+ 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 void __devexit nforce2_remove(str
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-parport.c
++++ b/drivers/i2c/busses/i2c-parport.c
+@@ -155,12 +155,11 @@ static void i2c_parport_attach (struct p
+ {
+ 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 void i2c_parport_detach (struct p
+ }
+ }
+
+-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 @@ static int __init i2c_parport_init(void)
+ 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 at linux-fr.org>");
+diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -90,13 +90,13 @@ struct sd {
+
+ /* 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 @@ MODULE_PARM_DESC(force_addr,
+
+ /* 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 @@ static int __devinit piix4_setup(struct
+ }
+ }
+
+- 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 @@ static struct i2c_adapter piix4_adapter
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+ .algo = &smbus_algorithm,
+- .name = "unset",
+ };
+
+ static struct pci_device_id piix4_ids[] = {
+@@ -462,6 +462,7 @@ static void __devexit piix4_remove(struc
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-pmac-smu.c
++++ b/drivers/i2c/busses/i2c-pmac-smu.c
+@@ -211,12 +211,11 @@ static int create_iface(struct device_no
+ }
+ 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
+--- a/drivers/i2c/busses/i2c-prosavage.c
++++ b/drivers/i2c/busses/i2c-prosavage.c
+@@ -83,11 +83,6 @@ struct s_i2c_chip {
+ /*
+ * 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 @@ static int __devinit prosavage_probe(str
+ 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 @@ static struct pci_device_id prosavage_pc
+ 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-pxa.c b/drivers/i2c/busses/i2c-pxa.c
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -30,6 +30,7 @@
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+ #include <linux/i2c-pxa.h>
++#include <linux/platform_device.h>
+
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
+--- a/drivers/i2c/busses/i2c-s3c2410.c
++++ b/drivers/i2c/busses/i2c-s3c2410.c
+@@ -33,7 +33,7 @@
+ #include <linux/delay.h>
+ #include <linux/errno.h>
+ #include <linux/err.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+@@ -879,14 +879,12 @@ static int s3c24xx_i2c_remove(struct dev
+ }
+
+ #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 @@ static int s3c24xx_i2c_resume(struct dev
+ /* 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 s3c2410_i2c_
+ };
+
+ static struct device_driver s3c2440_i2c_driver = {
++ .owner = THIS_MODULE,
+ .name = "s3c2440-i2c",
+ .bus = &platform_bus_type,
+ .probe = s3c24xx_i2c_probe,
+@@ -918,8 +918,11 @@ static int __init i2c_adap_s3c_init(void
+ int ret;
+
+ ret = driver_register(&s3c2410_i2c_driver);
+- if (ret == 0)
+- ret = driver_register(&s3c2440_i2c_driver);
++ if (ret == 0) {
++ ret = driver_register(&s3c2440_i2c_driver);
++ if (ret)
++ driver_unregister(&s3c2410_i2c_driver);
++ }
+
+ return ret;
+ }
+diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
+--- a/drivers/i2c/busses/i2c-savage4.c
++++ b/drivers/i2c/busses/i2c-savage4.c
+@@ -179,6 +179,7 @@ static void __devexit savage4_remove(str
+ }
+
+ 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
+--- a/drivers/i2c/busses/i2c-sis5595.c
++++ b/drivers/i2c/busses/i2c-sis5595.c
+@@ -123,11 +123,12 @@ static int blacklist[] = {
+
+ /* 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 @@ static int sis5595_setup(struct pci_dev
+
+ /* 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_algorithm smbus_algori
+ static struct i2c_adapter sis5595_adapter = {
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+- .name = "unset",
+ .algo = &smbus_algorithm,
+ };
+
+@@ -397,6 +398,7 @@ static void __devexit sis5595_remove(str
+ }
+
+ 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
+--- 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_param(force, bool, 0);
+ 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 @@ static int sis630_setup(struct pci_dev *
+ 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_algorithm smbus_algori
+ static struct i2c_adapter sis630_adapter = {
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+- .name = "unset",
+ .algo = &smbus_algorithm,
+ };
+
+@@ -494,6 +496,7 @@ static void __devexit sis630_remove(stru
+
+
+ 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
+--- 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 @@ static struct i2c_adapter sis96x_adapter
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+ .algo = &smbus_algorithm,
+- .name = "unset",
+ };
+
+ static struct pci_device_id sis96x_ids[] = {
+@@ -294,7 +294,8 @@ static int __devinit sis96x_probe(struct
+ 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 void __devexit sis96x_remove(stru
+ }
+
+ 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
+--- 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 @@ static int __devinit vt586b_probe(struct
+ 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 void __devexit vt586b_remove(stru
+
+
+ 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
+--- 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 at dds.nl>,
++ Copyright (c) 1998 - 2002 Frodo Looijaard <frodol at dds.nl>,
+ Philip Edelbrock <phil at netroedge.com>, Kyösti Mälkki <kmalkki at cc.hut.fi>,
+ Mark D. Studebaker <mdsxyz123 at yahoo.com>
++ Copyright (C) 2005 Jean Delvare <khali at linux-fr.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+@@ -21,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 @@ MODULE_PARM_DESC(force_addr,
+ "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 @@ static int vt596_transaction(void)
+ /* 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 @@ static s32 vt596_access(struct i2c_adapt
+ }
+ 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 @@ static s32 vt596_access(struct i2c_adapt
+
+ 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 @@ static struct i2c_adapter vt596_adapter
+ .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 @@ static int __devinit vt596_probe(struct
+ {
+ 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 @@ static int __devinit vt596_probe(struct
+ }
+
+ 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 @@ static int __devinit vt596_probe(struct
+ 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 @@ static int __devinit vt596_probe(struct
+ 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 @@ static int __devinit vt596_probe(struct
+ }
+ }
+
+- 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 @@ static int __devinit vt596_probe(struct
+ */
+ return -ENODEV;
+
+- release_region:
++release_region:
+ release_region(vt596_smba, 8);
+ return error;
+ }
+@@ -420,9 +436,10 @@ static struct pci_device_id vt596_ids[]
+ { 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
+--- a/drivers/i2c/busses/i2c-voodoo3.c
++++ b/drivers/i2c/busses/i2c-voodoo3.c
+@@ -225,6 +225,7 @@ static void __devexit voodoo3_remove(str
+ }
+
+ 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
+--- a/drivers/i2c/busses/scx200_acb.c
++++ b/drivers/i2c/busses/scx200_acb.c
+@@ -442,14 +442,13 @@ static int __init scx200_acb_create(int
+ 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
+--- a/drivers/i2c/chips/Kconfig
++++ b/drivers/i2c/chips/Kconfig
+@@ -126,4 +126,13 @@ config SENSORS_MAX6875
+ 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
+--- a/drivers/i2c/chips/Makefile
++++ b/drivers/i2c/chips/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591
+ 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
+--- a/drivers/i2c/chips/ds1337.c
++++ b/drivers/i2c/chips/ds1337.c
+@@ -243,11 +243,10 @@ static int ds1337_detect(struct i2c_adap
+ 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
+--- a/drivers/i2c/chips/ds1374.c
++++ b/drivers/i2c/chips/ds1374.c
+@@ -167,7 +167,8 @@ static void ds1374_set_tlet(ulong arg)
+
+ 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 @@ static int ds1374_probe(struct i2c_adapt
+ 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
+--- a/drivers/i2c/chips/eeprom.c
++++ b/drivers/i2c/chips/eeprom.c
+@@ -88,8 +88,8 @@ static void eeprom_update_client(struct
+ 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 @@ static int eeprom_attach_adapter(struct
+ }
+
+ /* 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 @@ int eeprom_detect(struct i2c_adapter *ad
+ | 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
+--- a/drivers/i2c/chips/isp1301_omap.c
++++ b/drivers/i2c/chips/isp1301_omap.c
+@@ -27,7 +27,7 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/usb_ch9.h>
+ #include <linux/usb_gadget.h>
+ #include <linux/usb.h>
+@@ -888,6 +888,7 @@ static int otg_remove(struct device *dev
+ }
+
+ 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
+--- a/drivers/i2c/chips/m41t00.c
++++ b/drivers/i2c/chips/m41t00.c
+@@ -174,13 +174,11 @@ m41t00_probe(struct i2c_adapter *adap, i
+ 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
+--- a/drivers/i2c/chips/max6875.c
++++ b/drivers/i2c/chips/max6875.c
+@@ -179,16 +179,14 @@ static int max6875_detect(struct i2c_ada
+ 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
+--- a/drivers/i2c/chips/pca9539.c
++++ b/drivers/i2c/chips/pca9539.c
+@@ -122,11 +122,10 @@ static int pca9539_detect(struct i2c_ada
+
+ /* 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
+--- a/drivers/i2c/chips/pcf8574.c
++++ b/drivers/i2c/chips/pcf8574.c
+@@ -115,7 +115,7 @@ static int pcf8574_attach_adapter(struct
+ }
+
+ /* 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 @@ int pcf8574_detect(struct i2c_adapter *a
+
+ /* 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
+--- a/drivers/i2c/chips/pcf8591.c
++++ b/drivers/i2c/chips/pcf8591.c
+@@ -166,7 +166,7 @@ static int pcf8591_attach_adapter(struct
+ }
+
+ /* 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 @@ int pcf8591_detect(struct i2c_adapter *a
+
+ /* 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
+--- a/drivers/i2c/chips/rtc8564.c
++++ b/drivers/i2c/chips/rtc8564.c
+@@ -148,17 +148,16 @@ static int rtc8564_attach(struct i2c_ada
+ {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
+--- a/drivers/i2c/chips/tps65010.c
++++ b/drivers/i2c/chips/tps65010.c
+@@ -500,11 +500,10 @@ tps65010_probe(struct i2c_adapter *bus,
+ 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
+--- /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, ® },
++ };
++
++ 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 at tampabay.rr.com>, "
++ "Alessandro Zummo <a.zummo at 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
+--- 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 at cc.hut.fi>.
+ All SMBus-related things are written by Frodo Looijaard <frodol at dds.nl>
+- SMBus 2.0 support by Mark Studebaker <mdsxyz123 at yahoo.com> */
++ SMBus 2.0 support by Mark Studebaker <mdsxyz123 at yahoo.com> and
++ Jean Delvare <khali at linux-fr.org> */
+
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -29,6 +30,7 @@
+ #include <linux/init.h>
+ #include <linux/idr.h>
+ #include <linux/seq_file.h>
++#include <linux/platform_device.h>
+ #include <asm/uaccess.h>
+
+
+@@ -48,7 +50,7 @@ static int i2c_bus_suspend(struct device
+ 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 +59,7 @@ static int i2c_bus_resume(struct device
+ int rc = 0;
+
+ if (dev->driver && dev->driver->resume)
+- rc = dev->driver->resume(dev,0);
++ rc = dev->driver->resume(dev);
+ return rc;
+ }
+
+@@ -85,6 +87,7 @@ void i2c_adapter_dev_release(struct devi
+ }
+
+ struct device_driver i2c_adapter_driver = {
++ .owner = THIS_MODULE,
+ .name = "i2c_adapter",
+ .bus = &i2c_bus_type,
+ .probe = i2c_device_probe,
+@@ -98,6 +101,7 @@ static void i2c_adapter_class_dev_releas
+ }
+
+ struct class i2c_adapter_class = {
++ .owner = THIS_MODULE,
+ .name = "i2c-adapter",
+ .release = &i2c_adapter_class_dev_release,
+ };
+@@ -291,6 +295,7 @@ int i2c_add_driver(struct i2c_driver *dr
+ 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 +711,6 @@ int i2c_probe(struct i2c_adapter *adapte
+ 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 +737,17 @@ int i2c_probe(struct i2c_adapter *adapte
+ }
+ }
+
++ /* 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 +832,44 @@ crc8(u16 data)
+ 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 +896,8 @@ s32 i2c_smbus_read_byte(struct i2c_clien
+
+ 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 +980,14 @@ static s32 i2c_smbus_xfer_emulated(struc
+ 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 +1030,6 @@ static s32 i2c_smbus_xfer_emulated(struc
+ 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 +1042,20 @@ static s32 i2c_smbus_xfer_emulated(struc
+ 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 +1071,30 @@ static s32 i2c_smbus_xfer_emulated(struc
+ 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 +1109,8 @@ static s32 i2c_smbus_xfer_emulated(struc
+ 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 +1123,8 @@ s32 i2c_smbus_xfer(struct i2c_adapter *
+ 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 +1135,6 @@ s32 i2c_smbus_xfer(struct i2c_adapter *
+ 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
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -26,18 +26,15 @@
+
+ /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk at telos.de> */
+
+-/* The devfs code is contributed by Philipp Matthias Hahn
+- <pmhahn at 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>
++#include <linux/platform_device.h>
+ #include <asm/uaccess.h>
+
+ static struct i2c_client i2cdev_client_template;
+@@ -80,10 +77,9 @@ static struct i2c_dev *get_free_i2c_dev(
+ {
+ 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 +173,8 @@ static int i2cdev_ioctl(struct inode *in
+ 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 +428,6 @@ static int i2cdev_attach_adapter(struct
+ 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 +460,6 @@ static int i2cdev_detach_adapter(struct
+ 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 +515,6 @@ static int __init i2c_dev_init(void)
+ if (res)
+ goto out_unreg_class;
+
+- devfs_mk_dir("i2c");
+-
+ return 0;
+
+ out_unreg_class:
+@@ -539,7 +530,6 @@ static void __exit i2c_dev_exit(void)
+ {
+ 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
+--- a/drivers/ide/Kconfig
++++ b/drivers/ide/Kconfig
+@@ -778,6 +778,35 @@ config BLK_DEV_IDE_PMAC_BLINK
+ 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 @@ config BLK_DEV_UMC8672
+ 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
+--- a/drivers/ide/ide-cd.c
++++ b/drivers/ide/ide-cd.c
+@@ -2211,13 +2211,12 @@ static int cdrom_read_toc(ide_drive_t *d
+
+ 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 @@ static int cdrom_read_toc(ide_drive_t *d
+ /* 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 @@ static int cdrom_read_toc(ide_drive_t *d
+ /* 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 @@ static int ide_cdrom_packet(struct cdrom
+ 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 @@ int ide_cdrom_audio_ioctl (struct cdrom_
+ 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 @@ int ide_cdrom_audio_ioctl (struct cdrom_
+ */
+ 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 @@ int ide_cdrom_audio_ioctl (struct cdrom_
+ }
+
+ 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 @@ int ide_cdrom_audio_ioctl (struct cdrom_
+ }
+
+ 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 @@ int ide_cdrom_audio_ioctl (struct cdrom_
+ 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 @@ int ide_cdrom_reset (struct cdrom_device
+ 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 @@ int ide_cdrom_tray_move (struct cdrom_de
+ 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 @@ void ide_cdrom_update_speed (ide_drive_t
+ 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 @@ int ide_cdrom_select_speed (struct cdrom
+ 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 @@ int ide_cdrom_get_last_session (struct c
+ 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 ide_cdrom_get_mcn (struct cdrom_devi
+ {
+ 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 @@ static
+ 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 @@ static int ide_cdrom_register (ide_drive
+ 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 @@ int ide_cdrom_probe_capabilities (ide_dr
+ * 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 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ return 0;
+ }
+
++#ifdef CONFIG_PROC_FS
+ static
+ sector_t ide_cdrom_capacity (ide_drive_t *drive)
+ {
+@@ -3264,6 +3269,7 @@ sector_t ide_cdrom_capacity (ide_drive_t
+
+ return capacity * sectors_per_frame;
+ }
++#endif
+
+ static int ide_cd_remove(struct device *dev)
+ {
+@@ -3309,7 +3315,7 @@ static int ide_cd_probe(struct device *)
+ 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 @@ static int ide_cd_probe(struct device *d
+ 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
+--- a/drivers/ide/ide-proc.c
++++ b/drivers/ide/ide-proc.c
+@@ -64,6 +64,7 @@ static int proc_ide_read_imodel
+ 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
+--- a/drivers/ide/ide-tape.c
++++ b/drivers/ide/ide-tape.c
+@@ -1013,6 +1013,8 @@ typedef struct ide_tape_obj {
+
+ 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 @@ static void ide_tape_release(struct kref
+
+ 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 @@ static int ide_tape_probe(struct device
+
+ 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 @@ MODULE_LICENSE("GPL");
+ 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 void __exit idetape_exit (void)
+ */
+ 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
+--- /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 at 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/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
+--- a/drivers/ide/ppc/pmac.c
++++ b/drivers/ide/ppc/pmac.c
+@@ -81,7 +81,7 @@ typedef struct pmac_ide_hwif {
+
+ } pmac_ide_hwif_t;
+
+-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS] __pmacdata;
++static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
+ static int pmac_ide_count;
+
+ enum {
+@@ -242,7 +242,7 @@ struct mdma_timings_t {
+ int cycleTime;
+ };
+
+-struct mdma_timings_t mdma_timings_33[] __pmacdata =
++struct mdma_timings_t mdma_timings_33[] =
+ {
+ { 240, 240, 480 },
+ { 180, 180, 360 },
+@@ -255,7 +255,7 @@ struct mdma_timings_t mdma_timings_33[]
+ { 0, 0, 0 }
+ };
+
+-struct mdma_timings_t mdma_timings_33k[] __pmacdata =
++struct mdma_timings_t mdma_timings_33k[] =
+ {
+ { 240, 240, 480 },
+ { 180, 180, 360 },
+@@ -268,7 +268,7 @@ struct mdma_timings_t mdma_timings_33k[]
+ { 0, 0, 0 }
+ };
+
+-struct mdma_timings_t mdma_timings_66[] __pmacdata =
++struct mdma_timings_t mdma_timings_66[] =
+ {
+ { 240, 240, 480 },
+ { 180, 180, 360 },
+@@ -286,7 +286,7 @@ struct {
+ int addrSetup; /* ??? */
+ int rdy2pause;
+ int wrDataSetup;
+-} kl66_udma_timings[] __pmacdata =
++} kl66_udma_timings[] =
+ {
+ { 0, 180, 120 }, /* Mode 0 */
+ { 0, 150, 90 }, /* 1 */
+@@ -301,7 +301,7 @@ struct kauai_timing {
+ u32 timing_reg;
+ };
+
+-static struct kauai_timing kauai_pio_timings[] __pmacdata =
++static struct kauai_timing kauai_pio_timings[] =
+ {
+ { 930 , 0x08000fff },
+ { 600 , 0x08000a92 },
+@@ -316,7 +316,7 @@ static struct kauai_timing kauai_pio_tim
+ { 120 , 0x04000148 }
+ };
+
+-static struct kauai_timing kauai_mdma_timings[] __pmacdata =
++static struct kauai_timing kauai_mdma_timings[] =
+ {
+ { 1260 , 0x00fff000 },
+ { 480 , 0x00618000 },
+@@ -330,7 +330,7 @@ static struct kauai_timing kauai_mdma_ti
+ { 0 , 0 },
+ };
+
+-static struct kauai_timing kauai_udma_timings[] __pmacdata =
++static struct kauai_timing kauai_udma_timings[] =
+ {
+ { 120 , 0x000070c0 },
+ { 90 , 0x00005d80 },
+@@ -341,7 +341,7 @@ static struct kauai_timing kauai_udma_ti
+ { 0 , 0 },
+ };
+
+-static struct kauai_timing shasta_pio_timings[] __pmacdata =
++static struct kauai_timing shasta_pio_timings[] =
+ {
+ { 930 , 0x08000fff },
+ { 600 , 0x0A000c97 },
+@@ -356,7 +356,7 @@ static struct kauai_timing shasta_pio_ti
+ { 120 , 0x0400010a }
+ };
+
+-static struct kauai_timing shasta_mdma_timings[] __pmacdata =
++static struct kauai_timing shasta_mdma_timings[] =
+ {
+ { 1260 , 0x00fff000 },
+ { 480 , 0x00820800 },
+@@ -370,7 +370,7 @@ static struct kauai_timing shasta_mdma_t
+ { 0 , 0 },
+ };
+
+-static struct kauai_timing shasta_udma133_timings[] __pmacdata =
++static struct kauai_timing shasta_udma133_timings[] =
+ {
+ { 120 , 0x00035901, },
+ { 90 , 0x000348b1, },
+@@ -522,7 +522,7 @@ pmu_hd_blink_init(void)
+ * N.B. this can't be an initfunc, because the media-bay task can
+ * call ide_[un]register at any time.
+ */
+-void __pmac
++void
+ pmac_ide_init_hwif_ports(hw_regs_t *hw,
+ unsigned long data_port, unsigned long ctrl_port,
+ int *irq)
+@@ -559,7 +559,7 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
+ * timing register when selecting that unit. This version is for
+ * ASICs with a single timing register
+ */
+-static void __pmac
++static void
+ pmac_ide_selectproc(ide_drive_t *drive)
+ {
+ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+@@ -579,7 +579,7 @@ pmac_ide_selectproc(ide_drive_t *drive)
+ * timing register when selecting that unit. This version is for
+ * ASICs with a dual timing register (Kauai)
+ */
+-static void __pmac
++static void
+ pmac_ide_kauai_selectproc(ide_drive_t *drive)
+ {
+ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+@@ -600,7 +600,7 @@ pmac_ide_kauai_selectproc(ide_drive_t *d
+ /*
+ * Force an update of controller timing values for a given drive
+ */
+-static void __pmac
++static void
+ pmac_ide_do_update_timings(ide_drive_t *drive)
+ {
+ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+@@ -633,7 +633,7 @@ pmac_outbsync(ide_drive_t *drive, u8 val
+ * to sort that out sooner or later and see if I can finally get the
+ * common version to work properly in all cases
+ */
+-static int __pmac
++static int
+ pmac_ide_do_setfeature(ide_drive_t *drive, u8 command)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+@@ -710,7 +710,7 @@ out:
+ /*
+ * Old tuning functions (called on hdparm -p), sets up drive PIO timings
+ */
+-static void __pmac
++static void
+ pmac_ide_tuneproc(ide_drive_t *drive, u8 pio)
+ {
+ ide_pio_data_t d;
+@@ -801,7 +801,7 @@ pmac_ide_tuneproc(ide_drive_t *drive, u8
+ /*
+ * Calculate KeyLargo ATA/66 UDMA timings
+ */
+-static int __pmac
++static int
+ set_timings_udma_ata4(u32 *timings, u8 speed)
+ {
+ unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
+@@ -829,7 +829,7 @@ set_timings_udma_ata4(u32 *timings, u8 s
+ /*
+ * Calculate Kauai ATA/100 UDMA timings
+ */
+-static int __pmac
++static int
+ set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
+ {
+ struct ide_timing *t = ide_timing_find_mode(speed);
+@@ -849,7 +849,7 @@ set_timings_udma_ata6(u32 *pio_timings,
+ /*
+ * Calculate Shasta ATA/133 UDMA timings
+ */
+-static int __pmac
++static int
+ set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed)
+ {
+ struct ide_timing *t = ide_timing_find_mode(speed);
+@@ -869,7 +869,7 @@ set_timings_udma_shasta(u32 *pio_timings
+ /*
+ * Calculate MDMA timings for all cells
+ */
+-static int __pmac
++static int
+ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
+ u8 speed, int drive_cycle_time)
+ {
+@@ -1014,7 +1014,7 @@ set_timings_mdma(ide_drive_t *drive, int
+ * our dedicated function is more precise as it uses the drive provided
+ * cycle time value. We should probably fix this one to deal with that too...
+ */
+-static int __pmac
++static int
+ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
+ {
+ int unit = (drive->select.b.unit & 0x01);
+@@ -1092,7 +1092,7 @@ pmac_ide_tune_chipset (ide_drive_t *driv
+ * Blast some well known "safe" values to the timing registers at init or
+ * wakeup from sleep time, before we do real calculation
+ */
+-static void __pmac
++static void
+ sanitize_timings(pmac_ide_hwif_t *pmif)
+ {
+ unsigned int value, value2 = 0;
+@@ -1123,13 +1123,13 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
+ pmif->timings[2] = pmif->timings[3] = value2;
+ }
+
+-unsigned long __pmac
++unsigned long
+ pmac_ide_get_base(int index)
+ {
+ return pmac_ide[index].regbase;
+ }
+
+-int __pmac
++int
+ pmac_ide_check_base(unsigned long base)
+ {
+ int ix;
+@@ -1140,7 +1140,7 @@ pmac_ide_check_base(unsigned long base)
+ return -1;
+ }
+
+-int __pmac
++int
+ pmac_ide_get_irq(unsigned long base)
+ {
+ int ix;
+@@ -1151,7 +1151,7 @@ pmac_ide_get_irq(unsigned long base)
+ return 0;
+ }
+
+-static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 };
++static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+
+ dev_t __init
+ pmac_find_ide_boot(char *bootdevice, int n)
+@@ -1701,7 +1701,7 @@ pmac_ide_probe(void)
+ * pmac_ide_build_dmatable builds the DBDMA command list
+ * for a transfer and sets the DBDMA channel to point to it.
+ */
+-static int __pmac
++static int
+ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+ {
+ struct dbdma_cmd *table;
+@@ -1785,7 +1785,7 @@ pmac_ide_build_dmatable(ide_drive_t *dri
+ }
+
+ /* Teardown mappings after DMA has completed. */
+-static void __pmac
++static void
+ pmac_ide_destroy_dmatable (ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+@@ -1802,7 +1802,7 @@ pmac_ide_destroy_dmatable (ide_drive_t *
+ /*
+ * Pick up best MDMA timing for the drive and apply it
+ */
+-static int __pmac
++static int
+ pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+@@ -1859,7 +1859,7 @@ pmac_ide_mdma_enable(ide_drive_t *drive,
+ /*
+ * Pick up best UDMA timing for the drive and apply it
+ */
+-static int __pmac
++static int
+ pmac_ide_udma_enable(ide_drive_t *drive, u16 mode)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+@@ -1915,7 +1915,7 @@ pmac_ide_udma_enable(ide_drive_t *drive,
+ * Check what is the best DMA timing setting for the drive and
+ * call appropriate functions to apply it.
+ */
+-static int __pmac
++static int
+ pmac_ide_dma_check(ide_drive_t *drive)
+ {
+ struct hd_driveid *id = drive->id;
+@@ -1967,7 +1967,7 @@ pmac_ide_dma_check(ide_drive_t *drive)
+ * Prepare a DMA transfer. We build the DMA table, adjust the timings for
+ * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
+ */
+-static int __pmac
++static int
+ pmac_ide_dma_setup(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+@@ -1997,7 +1997,7 @@ pmac_ide_dma_setup(ide_drive_t *drive)
+ return 0;
+ }
+
+-static void __pmac
++static void
+ pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+ {
+ /* issue cmd to drive */
+@@ -2008,7 +2008,7 @@ pmac_ide_dma_exec_cmd(ide_drive_t *drive
+ * Kick the DMA controller into life after the DMA command has been issued
+ * to the drive.
+ */
+-static void __pmac
++static void
+ pmac_ide_dma_start(ide_drive_t *drive)
+ {
+ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+@@ -2024,7 +2024,7 @@ pmac_ide_dma_start(ide_drive_t *drive)
+ /*
+ * After a DMA transfer, make sure the controller is stopped
+ */
+-static int __pmac
++static int
+ pmac_ide_dma_end (ide_drive_t *drive)
+ {
+ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+@@ -2052,7 +2052,7 @@ pmac_ide_dma_end (ide_drive_t *drive)
+ * that's not implemented yet), on the other hand, we don't have shared interrupts
+ * so it's not really a problem
+ */
+-static int __pmac
++static int
+ pmac_ide_dma_test_irq (ide_drive_t *drive)
+ {
+ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+@@ -2108,19 +2108,19 @@ pmac_ide_dma_test_irq (ide_drive_t *driv
+ return 1;
+ }
+
+-static int __pmac
++static int
+ pmac_ide_dma_host_off (ide_drive_t *drive)
+ {
+ return 0;
+ }
+
+-static int __pmac
++static int
+ pmac_ide_dma_host_on (ide_drive_t *drive)
+ {
+ return 0;
+ }
+
+-static int __pmac
++static int
+ pmac_ide_dma_lostirq (ide_drive_t *drive)
+ {
+ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
+--- a/drivers/ieee1394/dv1394.c
++++ b/drivers/ieee1394/dv1394.c
+@@ -2361,7 +2361,7 @@ static void dv1394_add_host (struct hpsb
+
+ 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
+--- a/drivers/ieee1394/eth1394.c
++++ b/drivers/ieee1394/eth1394.c
+@@ -1630,7 +1630,7 @@ static void ether1394_complete_cb(void *
+ /* 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
+--- a/drivers/ieee1394/nodemgr.c
++++ b/drivers/ieee1394/nodemgr.c
+@@ -1292,7 +1292,7 @@ static void nodemgr_suspend_ne(struct no
+
+ 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 @@ static void nodemgr_resume_ne(struct nod
+ 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
+--- a/drivers/ieee1394/raw1394.c
++++ b/drivers/ieee1394/raw1394.c
+@@ -2912,7 +2912,7 @@ static int __init init_raw1394(void)
+
+ 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
+--- a/drivers/ieee1394/video1394.c
++++ b/drivers/ieee1394/video1394.c
+@@ -1370,7 +1370,7 @@ static void video1394_add_host (struct h
+ 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
+--- 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 "agent.h"
++#include "smi.h"
+
+-#include <rdma/ib_smi.h>
++#define SPFX "ib_agent: "
+
+-#include "smi.h"
+-#include "agent_priv.h"
+-#include "mad_priv.h"
+-#include "agent.h"
++struct ib_agent_port_private {
++ struct list_head port_list;
++ struct ib_mad_agent *agent[2];
++};
+
+-spinlock_t ib_agent_port_list_lock;
++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 @@ int smi_check_local_dr_smp(struct ib_smp
+
+ 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;
++ }
++
++ 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 agent_mad_send(mad_agent, port_priv, mad, grh, wc);
++ 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 @@ int ib_agent_port_open(struct ib_device
+ 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,
+- &agent_send_handler,
+- NULL, NULL);
+
+- if (IS_ERR(port_priv->smp_agent)) {
+- ret = PTR_ERR(port_priv->smp_agent);
++ /* 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->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 @@ int ib_agent_port_open(struct ib_device
+ 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 @@ int ib_agent_port_close(struct ib_device
+ 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 @@ int ib_agent_port_close(struct ib_device
+ 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
+--- 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
+--- 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
+--- 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
+--- a/drivers/infiniband/core/cm.c
++++ b/drivers/infiniband/core/cm.c
+@@ -135,6 +135,7 @@ struct cm_id_private {
+ __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 @@ static int cm_alloc_msg(struct cm_id_pri
+
+ 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 @@ static int cm_alloc_msg(struct cm_id_pri
+ }
+
+ /* 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 @@ static int cm_alloc_response_msg(struct
+ 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 @@ static struct cm_id_private * cm_insert_
+ 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 @@ static struct cm_id_private * cm_insert_
+ 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 @@ static struct cm_id_private * cm_find_li
+ 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 @@ static void cm_reject_sidr_req(struct cm
+ ib_send_cm_sidr_rep(&cm_id_priv->id, ¶m);
+ }
+
+-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 @@ struct ib_cm_id *ib_create_cm_id(ib_cm_h
+
+ 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 @@ retest:
+ 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 @@ retest:
+ 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 @@ retest:
+ 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 @@ int ib_send_cm_req(struct ib_cm_id *cm_i
+ 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 @@ int ib_send_cm_req(struct ib_cm_id *cm_i
+ 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 @@ int ib_send_cm_req(struct ib_cm_id *cm_i
+ 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 @@ int ib_send_cm_req(struct ib_cm_id *cm_i
+ 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 @@ static int cm_issue_rej(struct cm_port *
+ 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 @@ static int cm_issue_rej(struct cm_port *
+ 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 @@ static void cm_format_req_event(struct c
+ 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 @@ static void cm_dup_req_handler(struct cm
+ 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 @@ static void cm_dup_req_handler(struct cm
+ }
+ 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 @@ static struct cm_id_private * cm_match_r
+ }
+
+ /* 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 @@ static int cm_req_handler(struct cm_work
+
+ 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 @@ static int cm_req_handler(struct cm_work
+ 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 @@ int ib_send_cm_rep(struct ib_cm_id *cm_i
+ 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 @@ int ib_send_cm_rep(struct ib_cm_id *cm_i
+
+ 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 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_i
+ {
+ 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 @@ int ib_send_cm_rtu(struct ib_cm_id *cm_i
+ 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 @@ static void cm_dup_rep_handler(struct cm
+ 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 @@ static void cm_dup_rep_handler(struct cm
+ 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 @@ static int cm_rep_handler(struct cm_work
+
+ /* 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 @@ static int cm_establish_handler(struct c
+ 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 @@ static int cm_rtu_handler(struct cm_work
+ }
+ 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 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_
+ {
+ 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 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_
+
+ 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 @@ int ib_send_cm_drep(struct ib_cm_id *cm_
+ {
+ 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 @@ int ib_send_cm_drep(struct ib_cm_id *cm_
+ 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 @@ static int cm_dreq_handler(struct cm_wor
+ 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 @@ static int cm_dreq_handler(struct cm_wor
+ 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 @@ static int cm_dreq_handler(struct cm_wor
+ 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 @@ static int cm_drep_handler(struct cm_wor
+ }
+ 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 @@ int ib_send_cm_rej(struct ib_cm_id *cm_i
+ {
+ 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 @@ int ib_send_cm_rej(struct ib_cm_id *cm_i
+ 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 @@ static int cm_rej_handler(struct cm_work
+ 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 @@ static int cm_rej_handler(struct cm_work
+ 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 @@ int ib_send_cm_mra(struct ib_cm_id *cm_i
+ {
+ 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 @@ int ib_send_cm_mra(struct ib_cm_id *cm_i
+ 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 @@ int ib_send_cm_mra(struct ib_cm_id *cm_i
+ 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 @@ int ib_send_cm_mra(struct ib_cm_id *cm_i
+ 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 @@ static int cm_mra_handler(struct cm_work
+ 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 @@ static int cm_mra_handler(struct cm_work
+ if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
+ cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
+ ib_modify_mad(cm_id_priv->av.port->mad_agent,
+- (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 @@ int ib_send_cm_lap(struct ib_cm_id *cm_i
+ {
+ 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 @@ int ib_send_cm_lap(struct ib_cm_id *cm_i
+
+ 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 @@ static int cm_lap_handler(struct cm_work
+ 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 @@ static int cm_lap_handler(struct cm_work
+ 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 @@ int ib_send_cm_apr(struct ib_cm_id *cm_i
+ {
+ 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 @@ int ib_send_cm_apr(struct ib_cm_id *cm_i
+
+ 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 @@ static int cm_apr_handler(struct cm_work
+ 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 @@ int ib_send_cm_sidr_req(struct ib_cm_id
+ {
+ 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 @@ int ib_send_cm_sidr_req(struct ib_cm_id
+
+ 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 @@ static void cm_format_sidr_req_event(str
+ 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 @@ static int cm_sidr_req_handler(struct cm
+ 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 @@ static int cm_sidr_req_handler(struct cm
+ 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 @@ int ib_send_cm_sidr_rep(struct ib_cm_id
+ {
+ 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 @@ int ib_send_cm_sidr_rep(struct ib_cm_id
+
+ 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 @@ static int cm_sidr_rep_handler(struct cm
+ 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 @@ discard:
+ 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 @@ static int cm_init_qp_init_attr(struct c
+ 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 @@ static int cm_init_qp_rtr_attr(struct cm
+ 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 @@ static int cm_init_qp_rts_attr(struct cm
+ 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 @@ static void __exit ib_cm_cleanup(void)
+ 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
+--- a/drivers/infiniband/core/cm_msgs.h
++++ b/drivers/infiniband/core/cm_msgs.h
+@@ -186,6 +186,7 @@ static inline void cm_req_set_qp_type(st
+ 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
+--- a/drivers/infiniband/core/device.c
++++ b/drivers/infiniband/core/device.c
+@@ -514,6 +514,12 @@ int ib_query_port(struct ib_device *devi
+ 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 @@ int ib_modify_port(struct ib_device *dev
+ 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
+--- a/drivers/infiniband/core/mad.c
++++ b/drivers/infiniband/core/mad.c
+@@ -579,7 +579,7 @@ static void dequeue_mad(struct ib_mad_li
+ }
+
+ 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 @@ static void snoop_send(struct ib_mad_qp_
+ 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 @@ static void build_smp_wc(u64 wr_id, u16
+ * 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 @@ static int handle_outgoing_dr_smp(struct
+ 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 @@ static int handle_outgoing_dr_smp(struct
+ 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 @@ static int get_buf_length(int hdr_len, i
+
+ 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 @@ struct ib_mad_send_buf * ib_create_send_
+ (!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;
+-
+- 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->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;
++
++ 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 @@ void ib_free_send_mad(struct ib_mad_send
+
+ 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 @@ EXPORT_SYMBOL(ib_free_send_mad);
+ 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 @@ int ib_send_mad(struct ib_mad_send_wr_pr
+ 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 @@ int ib_send_mad(struct ib_mad_send_wr_pr
+ 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 @@ int ib_send_mad(struct ib_mad_send_wr_pr
+ * 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;
+-
+- if (send_wr->wr.ud.timeout_ms && !mad_agent->recv_handler)
+- 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.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 @@ int ib_post_send_mad(struct ib_mad_agent
+ * 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;
+- }
+-
+- /* 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;
++ continue;
+ }
+- 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 @@ int ib_post_send_mad(struct ib_mad_agent
+ 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 @@ find_mad_agent(struct ib_mad_port_privat
+ * 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 @@ ib_find_send_mad(struct ib_mad_agent_pri
+ */
+ 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 @@ static void ib_mad_complete_recv(struct
+ 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 @@ local:
+ 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 @@ void ib_mad_complete_send_wr(struct ib_m
+
+ 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 @@ static void ib_mad_send_done_handler(str
+ 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 @@ static void ib_mad_send_done_handler(str
+ 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 @@ retry:
+ }
+ 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 @@ static void cancel_mads(struct ib_mad_ag
+
+ 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 @@ int ib_modify_mad(struct ib_mad_agent *m
+ 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 @@ int ib_modify_mad(struct ib_mad_agent *m
+ 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 @@ int ib_modify_mad(struct ib_mad_agent *m
+ }
+ 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 @@ static void local_completions(void *data
+ * 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 @@ local_send_completion:
+ /* 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 @@ static int retry_send(struct ib_mad_send
+ 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 @@ static void timeout_sends(void *data)
+ 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 int ib_mad_port_close(struct ib_d
+
+ 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 @@ static int __init ib_mad_init_module(voi
+ 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
+--- a/drivers/infiniband/core/mad_priv.h
++++ b/drivers/infiniband/core/mad_priv.h
+@@ -118,9 +118,10 @@ struct ib_mad_send_wr_private {
+ 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 ib_mad_local_private {
+ 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
+--- a/drivers/infiniband/core/mad_rmpp.c
++++ b/drivers/infiniband/core/mad_rmpp.c
+@@ -103,12 +103,12 @@ void ib_cancel_rmpp_recvs(struct ib_mad_
+ 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 @@ static void ack_recv(struct mad_rmpp_rec
+ 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 @@ static void nack_recv(struct ib_mad_agen
+ {
+ 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 @@ static void nack_recv(struct ib_mad_agen
+ 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 @@ static int send_next_seg(struct ib_mad_s
+ 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 @@ static int send_next_seg(struct ib_mad_s
+ }
+
+ /* 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 @@ static void abort_send(struct ib_mad_age
+
+ 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 @@ static void process_rmpp_ack(struct ib_m
+
+ 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 @@ static void process_rmpp_ack(struct ib_m
+
+ 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 @@ int ib_send_rmpp_mad(struct ib_mad_send_
+ 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 @@ int ib_send_rmpp_mad(struct ib_mad_send_
+
+ 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 @@ int ib_process_rmpp_send_wc(struct ib_ma
+ 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 @@ int ib_process_rmpp_send_wc(struct ib_ma
+
+ 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 @@ int ib_retry_rmpp(struct ib_mad_send_wr_
+ 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
+--- a/drivers/infiniband/core/mad_rmpp.h
++++ b/drivers/infiniband/core/mad_rmpp.h
+@@ -51,6 +51,8 @@ ib_process_rmpp_recv_wc(struct ib_mad_ag
+ 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
+--- 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_device {
+ 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 @@ void ib_sa_cancel_query(int id, struct i
+ {
+ 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 @@ void ib_sa_cancel_query(int id, struct i
+ 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 void init_mad(struct ib_sa_mad *m
+
+ 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(&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);
+
+- 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);
+-
+- 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_callback(stru
+
+ 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,43 +559,58 @@ int ib_sa_path_rec_get(struct ib_device
+ {
+ 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_callback(s
+
+ 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 @@ int ib_sa_service_rec_query(struct ib_de
+ {
+ 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,37 +694,45 @@ int ib_sa_service_rec_query(struct ib_de
+ 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_callback(
+
+ 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 @@ int ib_sa_mcmember_rec_query(struct ib_d
+ {
+ 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 @@ static void send_handler(struct ib_mad_a
+ 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 int __init ib_sa_init(void)
+ 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
+--- 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
+--- a/drivers/infiniband/core/sysfs.c
++++ b/drivers/infiniband/core/sysfs.c
+@@ -65,6 +65,11 @@ struct port_table_attribute {
+ 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 @@ static ssize_t port_attr_show(struct kob
+
+ 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 @@ static ssize_t show_node_type(struct cla
+ {
+ 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 @@ static ssize_t show_sys_image_guid(struc
+ 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 @@ static ssize_t show_node_guid(struct cla
+ 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
+--- 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;
++};
++
++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;
++};
+
+-module_param_named(debug_level, ucm_debug_level, int, 0644);
+-MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
++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 @@ static struct ib_ucm_context *ib_ucm_ctx
+ 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 @@ static void ib_ucm_event_req_get(struct
+ 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 @@ static int ib_ucm_event_process(struct i
+ 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 @@ static ssize_t ib_ucm_event(struct ib_uc
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+- /*
+- * wait
+- */
++
+ down(&file->mutex);
+ while (list_empty(&file->events)) {
+
+@@ -471,7 +512,6 @@ done:
+ 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 @@ static ssize_t ib_ucm_create_id(struct i
+ 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 @@ static ssize_t ib_ucm_write(struct file
+ 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 @@ static int ib_ucm_open(struct inode *ino
+
+ 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 @@ static int ib_ucm_close(struct inode *in
+ 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 @@ static struct file_operations ib_ucm_fop
+ .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 int __init ib_ucm_init(void)
++static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
+ {
+- int result;
++ 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);
+
+- result = register_chrdev_region(IB_UCM_DEV, 1, "infiniband_cm");
+- if (result) {
+- ucm_dbg("Error <%d> registering dev\n", result);
+- goto err_chr;
+- }
++static void ib_ucm_add_one(struct ib_device *device)
++{
++ struct ib_ucm_device *ucm_dev;
++
++ if (!device->alloc_ucontext)
++ return;
+
+- cdev_init(&ib_ucm_cdev, &ib_ucm_fops);
++ ucm_dev = kmalloc(sizeof *ucm_dev, GFP_KERNEL);
++ if (!ucm_dev)
++ return;
++
++ memset(ucm_dev, 0, sizeof *ucm_dev);
++ ucm_dev->ib_dev = device;
+
+- result = cdev_add(&ib_ucm_cdev, IB_UCM_DEV, 1);
+- if (result) {
+- ucm_dbg("Error <%d> adding cdev\n", result);
++ 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;
+- }
+
+- 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);
++ 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 ret;
++
++ 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;
+ }
+
+- class_device_create(ib_ucm_class, IB_UCM_DEV, NULL, "ucm");
++ ret = class_register(&ucm_class);
++ if (ret) {
++ printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n");
++ goto err_chrdev;
++ }
+
+- idr_init(&ctx_id_table);
+- init_MUTEX(&ctx_id_mutex);
++ 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;
++ }
+
++ 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
+--- 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
+--- a/drivers/infiniband/core/user_mad.c
++++ b/drivers/infiniband/core/user_mad.c
+@@ -64,18 +64,39 @@ enum {
+ IB_UMAD_MINOR_BASE = 0
+ };
+
++/*
++ * 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.
++ */
++
+ struct ib_umad_port {
+- int devnum;
+- struct cdev dev;
+- struct class_device class_dev;
+-
+- int sm_devnum;
+- struct cdev sm_dev;
+- struct class_device sm_class_dev;
++ 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_file {
+ };
+
+ 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 @@ static void send_handler(struct ib_mad_a
+ 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 @@ static void recv_handler(struct ib_mad_a
+ 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 @@ static ssize_t ib_umad_read(struct file
+ 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 @@ static ssize_t ib_umad_write(struct file
+ 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 @@ static ssize_t ib_umad_write(struct file
+ goto err;
+ }
+
+- packet->length = length;
+-
+ down_read(&file->agent_mutex);
+
+ agent = file->agent[packet->mad.hdr.id];
+@@ -321,9 +343,9 @@ static ssize_t ib_umad_write(struct file
+ 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 @@ static ssize_t ib_umad_write(struct file
+
+ /* 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;
+-
+- /* 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;
+- }
++ 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;
++
++ /* 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 @@ static ssize_t ib_umad_write(struct file
+ * 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 long ib_umad_ioctl(struct file *f
+
+ 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)
++ 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);
++
++ if (!port)
++ return -ENXIO;
++
++ file = kzalloc(sizeof *file, GFP_KERNEL);
++ if (!file) {
++ kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+ return -ENOMEM;
+-
+- memset(file, 0, sizeof *file);
++ }
+
+ spin_lock_init(&file->recv_lock);
+ init_rwsem(&file->agent_mutex);
+@@ -589,6 +599,7 @@ static int ib_umad_open(struct inode *in
+ 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 @@ static int ib_umad_close(struct inode *i
+
+ kfree(file);
+
++ kref_put(&dev->ref, ib_umad_release_dev);
++
+ return 0;
+ }
+
+@@ -619,30 +632,46 @@ static struct file_operations umad_fops
+
+ 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 @@ static int ib_umad_sm_close(struct inode
+ 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 @@ static struct ib_client umad_client = {
+ .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 @@ static ssize_t show_port(struct class_de
+ {
+ 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 CLASS_ATTR(abi_version, S_IRUGO,
+ 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);
+- 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);
++ 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;
+ }
+- 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))
+- goto err_class;
+- if (class_device_create_file(&port->class_dev, &class_device_attr_ibdev))
++ 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);
++ 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;
+
+- if (class_device_register(&port->sm_class_dev))
++ 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;
+
+- class_set_devdata(&port->sm_class_dev, port);
+- kref_get(&port->umad_dev->ref);
++ 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_dev))
+- 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_ibdev))
+ goto err_sm_class;
+- if (class_device_create_file(&port->sm_class_dev, &class_device_attr_port))
++ 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 @@ static void ib_umad_add_one(struct ib_de
+ 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 @@ static void ib_umad_add_one(struct ib_de
+ 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 @@ static void ib_umad_remove_one(struct ib
+ 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 @@ static int __init ib_umad_init(void)
+ {
+ 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 @@ static int __init ib_umad_init(void)
+ 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 @@ static int __init ib_umad_init(void)
+ 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 @@ out:
+ 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
+--- 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_file {
+ 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_cq_idr;
+ 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 @@ void ib_umem_release_on_close(struct ib_
+ 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
+--- 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 @@ ssize_t ib_uverbs_get_context(struct ib_
+ 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 @@ ssize_t ib_uverbs_get_context(struct ib_
+ 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 @@ ssize_t ib_uverbs_query_port(struct ib_u
+ 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 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uve
+ 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 @@ retry:
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+- goto err_list;
++ goto err_idr;
+ }
+
+- return in_len;
+-
+-err_list:
+- down(&file->mutex);
+- list_del(&uobj->list);
++ down(&file->mutex);
++ list_add_tail(&uobj->list, &file->ucontext->pd_list);
+ up(&file->mutex);
+
+- down(&ib_uverbs_idr_mutex);
+- idr_remove(&ib_uverbs_pd_idr, uobj->id);
+ up(&ib_uverbs_idr_mutex);
+
+-err_pd:
++ return in_len;
++
++err_idr:
++ idr_remove(&ib_uverbs_pd_idr, uobj->id);
++
++err_up:
++ up(&ib_uverbs_idr_mutex);
+ ib_dealloc_pd(pd);
+
+ err:
+@@ -459,6 +397,14 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverb
+ 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 @@ retry:
+
+ 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 @@ out:
+ 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 @@ ssize_t ib_uverbs_create_cq(struct ib_uv
+ 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 @@ ssize_t ib_uverbs_create_cq(struct ib_uv
+ (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 @@ ssize_t ib_uverbs_create_cq(struct ib_uv
+ 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 @@ retry:
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+- goto err_list;
++ goto err_idr;
+ }
+
+- return in_len;
+-
+-err_list:
+- down(&file->mutex);
+- list_del(&uobj->uobject.list);
++ down(&file->mutex);
++ list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
+ up(&file->mutex);
+
+- down(&ib_uverbs_idr_mutex);
+- idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
+ up(&ib_uverbs_idr_mutex);
+
+-err_cq:
++ return in_len;
++
++err_idr:
++ idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
++
++err_up:
++ up(&ib_uverbs_idr_mutex);
+ ib_destroy_cq(cq);
+
+ err:
+@@ -692,6 +666,93 @@ err:
+ 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 @@ ssize_t ib_uverbs_destroy_cq(struct ib_u
+ 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 @@ ssize_t ib_uverbs_destroy_cq(struct ib_u
+ 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 @@ ssize_t ib_uverbs_destroy_cq(struct ib_u
+ 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 @@ retry:
+
+ 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 @@ ssize_t ib_uverbs_destroy_qp(struct ib_u
+ 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 @@ ssize_t ib_uverbs_destroy_qp(struct ib_u
+ 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 @@ out:
+ 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 @@ retry:
+
+ 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 @@ ssize_t ib_uverbs_destroy_srq(struct ib_
+ 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 @@ ssize_t ib_uverbs_destroy_srq(struct ib_
+ 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
+--- 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 @@ enum {
+
+ #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_qp_idr);
+ 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 struct vfsmount *uverbs_event_mnt
+ 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 @@ static int ib_dealloc_ucontext(struct ib
+
+ 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 @@ static void ib_uverbs_release_file(struc
+ 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 @@ static ssize_t ib_uverbs_event_read(stru
+
+ 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 @@ static unsigned int ib_uverbs_event_poll
+ 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_fasync(int fd
+ 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;
++
++ 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_release(file);
+ 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 @@ static struct file_operations uverbs_eve
+
+ 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 @@ static void ib_uverbs_async_handler(stru
+ struct ib_uverbs_event *entry;
+ unsigned long flags;
+
++ 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)
++ 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 @@ void ib_uverbs_srq_event_handler(struct
+ &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 @@ static void ib_uverbs_event_handler(stru
+ 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;
+-
+- file->fd = get_unused_fd();
+- if (file->fd < 0)
+- return file->fd;
++ ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
++ if (!ev_file)
++ return ERR_PTR(-ENOMEM);
++
++ 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 @@ static ssize_t ib_uverbs_write(struct fi
+
+ 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_mmap(struct file *f
+
+ 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);
++
++ if (!dev)
++ return -ENXIO;
+
+- file = kmalloc(sizeof *file +
+- (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
+- GFP_KERNEL);
++ if (!try_module_get(dev->ib_dev->owner)) {
++ ret = -ENODEV;
++ goto err;
++ }
++
++ file = kmalloc(sizeof *file, GFP_KERNEL);
+ if (!file) {
+ ret = -ENOMEM;
+- goto err;
++ goto err_module;
+ }
+
+- file->device = dev;
++ 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 struct ib_client uverbs_client =
+
+ 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;
+
+-static struct class uverbs_class = {
+- .name = "infiniband_verbs",
+- .release = ib_uverbs_release_class_dev
+-};
++ return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
++}
++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 @@ static void ib_uverbs_add_one(struct ib_
+
+ 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 @@ static void ib_uverbs_add_one(struct ib_
+ 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->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;
+
+- 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->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;
+
+- if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev))
++ 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 @@ static void ib_uverbs_remove_one(struct
+ 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 @@ static int __init ib_uverbs_init(void)
+ 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 @@ out_fs:
+ 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 @@ static void __exit ib_uverbs_cleanup(voi
+ 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
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -523,16 +523,22 @@ EXPORT_SYMBOL(ib_dealloc_fmr);
+
+ 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
+--- a/drivers/infiniband/hw/mthca/Makefile
++++ b/drivers/infiniband/hw/mthca/Makefile
+@@ -7,4 +7,5 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mth
+ 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
+--- 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
+--- /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
+--- 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 @@ void mthca_cmd_use_polling(struct mthca_
+ }
+
+ 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 @@ int mthca_QUERY_FW(struct mthca_dev *dev
+
+ 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 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev
+ 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 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev
+ 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
+--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
++++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
+@@ -248,7 +248,7 @@ void mthca_cmd_event(struct mthca_dev *d
+ 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
+--- a/drivers/infiniband/hw/mthca/mthca_dev.h
++++ b/drivers/infiniband/hw/mthca/mthca_dev.h
+@@ -83,6 +83,8 @@ enum {
+ /* 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 @@ struct mthca_limits {
+ 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 @@ struct mthca_limits {
+ int reserved_mcgs;
+ int num_pds;
+ int reserved_pds;
++ u32 flags;
+ u8 port_width_cap;
+ };
+
+@@ -251,6 +258,14 @@ struct mthca_mcg_table {
+ 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_dev {
+ 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 @@ void mthca_cleanup_mcg_table(struct mthc
+ 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 @@ void mthca_cq_clean(struct mthca_dev *de
+ 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
+--- a/drivers/infiniband/hw/mthca/mthca_eq.c
++++ b/drivers/infiniband/hw/mthca/mthca_eq.c
+@@ -83,7 +83,8 @@ enum {
+ 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 @@ enum {
+ (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 @@ struct mthca_eqe {
+ __be32 qpn;
+ } __attribute__((packed)) qp;
+ struct {
++ __be32 srqn;
++ } __attribute__((packed)) srq;
++ struct {
+ __be32 cqn;
+ u32 reserved1;
+ u8 reserved2[3];
+@@ -305,6 +310,16 @@ static int mthca_eq_int(struct mthca_dev
+ 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
+--- 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 @@ enum {
+ 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 @@ static void forward_trap(struct mthca_de
+ 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 @@ static void forward_trap(struct mthca_de
+ * 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 @@ int mthca_process_mad(struct ib_device *
+ 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
+--- a/drivers/infiniband/hw/mthca/mthca_main.c
++++ b/drivers/infiniband/hw/mthca/mthca_main.c
+@@ -162,9 +162,18 @@ static int __devinit mthca_dev_lim(struc
+ 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 @@ static int __devinit mthca_dev_lim(struc
+ 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 @@ MODULE_DEVICE_TABLE(pci, mthca_pci_table
+
+ 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
+--- 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 @@ int mthca_multicast_attach(struct ib_qp
+ }
+
+ 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
+--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
++++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
+@@ -82,7 +82,7 @@ void mthca_free_icm(struct mthca_dev *de
+ }
+
+ 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 @@ void mthca_cleanup_user_db_tab(struct mt
+ }
+ }
+
+-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
+--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
++++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
+@@ -77,7 +77,7 @@ struct mthca_icm_iter {
+ 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 @@ void mthca_cleanup_user_db_tab(struct mt
+
+ 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
+--- 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
+--- 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 @@ static int mthca_query_device(struct ib_
+
+ 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 @@ static int mthca_query_port(struct ib_de
+ 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 @@ static struct ib_cq *mthca_create_cq(str
+ 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 @@ int mthca_register_device(struct mthca_d
+ 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 @@ int mthca_register_device(struct mthca_d
+
+ 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 @@ int mthca_register_device(struct mthca_d
+ }
+ }
+
++ 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
+--- 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 @@ static const struct {
+ [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 @@ static const struct {
+ .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 @@ static const struct {
+ [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 @@ static const struct {
+ .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 @@ static int mthca_set_qp_size(struct mthc
+ 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
+--- 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
+--- a/drivers/infiniband/hw/mthca/mthca_srq.c
++++ b/drivers/infiniband/hw/mthca/mthca_srq.c
+@@ -186,7 +186,8 @@ int mthca_alloc_srq(struct mthca_dev *de
+ 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 @@ void mthca_free_srq(struct mthca_dev *de
+ 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 @@ void mthca_srq_event(struct mthca_dev *d
+
+ 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 @@ int mthca_tavor_post_srq_recv(struct ib_
+
+ 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 @@ int mthca_arbel_post_srq_recv(struct ib_
+ 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
+--- 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
+--- 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
+--- a/drivers/infiniband/ulp/ipoib/ipoib.h
++++ b/drivers/infiniband/ulp/ipoib/ipoib.h
+@@ -100,7 +100,12 @@ struct ipoib_pseudoheader {
+
+ 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 @@ struct ipoib_dev_priv {
+ 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_attach(struct net_device
+ 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
+--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+@@ -95,57 +95,65 @@ void ipoib_free_ah(struct kref *kref)
+ }
+ }
+
+-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,
+- };
++static int ipoib_ib_post_receive(struct net_device *dev, int id)
++{
++ struct ipoib_dev_priv *priv = netdev_priv(dev);
++ struct ib_sge list;
++ struct ib_recv_wr param;
+ struct ib_recv_wr *bad_wr;
++ int ret;
++
++ list.addr = priv->rx_ring[id].mapping;
++ list.length = IPOIB_BUF_SIZE;
++ list.lkey = priv->mr->lkey;
++
++ param.next = NULL;
++ param.wr_id = id | IPOIB_OP_RECV;
++ param.sg_list = &list;
++ param.num_sge = 1;
++
++ ret = ib_post_recv(priv->qp, ¶m, &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(priv->rx_ring[id].skb);
++ priv->rx_ring[id].skb = NULL;
++ }
+
+- return ib_post_recv(priv->qp, ¶m, &bad_wr);
++ return ret;
+ }
+
+-static int ipoib_ib_post_receive(struct net_device *dev, int id)
++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;
+- int ret;
+
+ skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
+- if (!skb) {
+- ipoib_warn(priv, "failed to allocate receive buffer\n");
+-
+- priv->rx_ring[id].skb = NULL;
++ if (!skb)
+ return -ENOMEM;
+- }
+- skb_reserve(skb, 4); /* 16 byte align IP header */
+- priv->rx_ring[id].skb = skb;
++
++ /*
++ * 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);
+- pci_unmap_addr_set(&priv->rx_ring[id], mapping, addr);
+-
+- 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,
+- IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
++ if (unlikely(dma_mapping_error(addr))) {
+ dev_kfree_skb_any(skb);
+- priv->rx_ring[id].skb = NULL;
++ return -EIO;
+ }
+
+- return ret;
++ priv->rx_ring[id].skb = skb;
++ priv->rx_ring[id].mapping = addr;
++
++ return 0;
+ }
+
+ static int ipoib_ib_post_receives(struct net_device *dev)
+@@ -154,6 +162,10 @@ static int ipoib_ib_post_receives(struct
+ 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 @@ static void ipoib_ib_handle_wc(struct ne
+ wr_id &= ~IPOIB_OP_RECV;
+
+ if (wr_id < IPOIB_RX_RING_SIZE) {
+- struct sk_buff *skb = priv->rx_ring[wr_id].skb;
+-
+- priv->rx_ring[wr_id].skb = NULL;
++ struct sk_buff *skb = priv->rx_ring[wr_id].skb;
++ dma_addr_t addr = priv->rx_ring[wr_id].mapping;
+
+- 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 @@ static void ipoib_ib_handle_wc(struct ne
+ 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 @@ static void ipoib_ib_handle_wc(struct ne
+ 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 @@ void ipoib_send(struct net_device *dev,
+ 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 @@ int ipoib_ib_dev_open(struct net_device
+ 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 @@ int ipoib_ib_dev_stop(struct net_device
+ 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
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -637,8 +637,11 @@ static void ipoib_timeout(struct net_dev
+ {
+ 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 @@ int ipoib_dev_init(struct net_device *de
+
+ /* 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 @@ int ipoib_dev_init(struct net_device *de
+ 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 @@ int ipoib_dev_init(struct net_device *de
+ 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
+--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+@@ -92,7 +92,7 @@ int ipoib_mcast_detach(struct net_device
+ 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 @@ int ipoib_qp_create(struct net_device *d
+ 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
+--- 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 {
+@@ -566,6 +565,7 @@ static long evdev_ioctl_compat(struct fi
+ case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
+ case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
+ case EV_FF: bits = dev->ffbit; max = FF_MAX; break;
++ case EV_SW: bits = dev->swbit; max = SW_MAX; break;
+ default: return -EINVAL;
+ }
+ bit_to_user(bits, max);
+@@ -580,6 +580,9 @@ static long evdev_ioctl_compat(struct fi
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
+ bit_to_user(dev->snd, SND_MAX);
+
++ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
++ bit_to_user(dev->sw, SW_MAX);
++
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
+ int len;
+ if (!dev->name) return -ENOENT;
+@@ -662,6 +665,7 @@ static struct file_operations evdev_fops
+ 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 +691,13 @@ static struct input_handle *evdev_connec
+
+ 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 +707,9 @@ static void evdev_disconnect(struct inpu
+ 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
+--- 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
+--- 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 at 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_close_device);
+ 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 @@ static struct input_device_id *input_mat
+ 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;
+-
+- 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;
+- }
+-
+- 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);
++ int i;
++ int len = 0;
+
+- kfree(buf);
+- kfree(envp);
++ for (i = NBITS(max) - 1; i > 0; i--)
++ if (bitmap[i])
++ break;
+
+-#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 @@ static unsigned int input_devices_poll(s
+ 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 @@ static int input_devices_read(char *buf,
+
+ 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 @@ static int input_devices_read(char *buf,
+ if (cnt >= count)
+ break;
+ }
++
++ kfree(path);
+ }
+
+ if (&dev->node == &input_dev_list)
+@@ -606,6 +507,240 @@ static inline int input_proc_init(void)
+ 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 as %s/%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 @@ void input_register_device(struct input_
+ 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 @@ void input_unregister_device(struct inpu
+ 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 @@ static struct file_operations input_fops
+ .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 @@ static int __init input_init(void)
+ 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
+--- 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 at ucw.cz>");
+ MODULE_DESCRIPTION("Joystick device interfaces");
+@@ -449,6 +448,7 @@ static struct file_operations joydev_fop
+ 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 @@ static struct input_handle *joydev_conne
+
+ 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 @@ static void joydev_disconnect(struct inp
+ 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
+--- 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
+--- 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 @@ MODULE_LICENSE("GPL");
+ #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 @@ static struct {
+ */
+
+ struct adi {
+- struct input_dev dev;
++ struct input_dev *dev;
+ int length;
+ int ret;
+ int idx;
+@@ -215,7 +216,7 @@ static inline int adi_get_bits(struct ad
+
+ 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 @@ static void adi_init_digital(struct game
+
+ 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_id_decode(struct adi *ad
+ }
+ }
+
+-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 @@ static void adi_init_center(struct adi *
+ 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 @@ static int adi_connect(struct gameport *
+ 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 @@ static int adi_connect(struct gameport *
+ 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 @@ static int adi_connect(struct gameport *
+
+ 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 @@ static int adi_connect(struct gameport *
+ 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 @@ static void adi_disconnect(struct gamepo
+
+ 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
+--- a/drivers/input/joystick/amijoy.c
++++ b/drivers/input/joystick/amijoy.c
+@@ -53,11 +53,9 @@ __obsolete_setup("amijoy=");
+
+ 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 @@ static irqreturn_t amijoy_interrupt(int
+ 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 void amijoy_close(struct input_de
+ 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;
+- }
+-
+- 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;
+- }
++ for (i = 0; i < 2; i++) {
++ if (!amijoy[i])
++ continue;
++
++ amijoy_dev[i] = input_allocate_device();
++ if (!amijoy_dev[i]) {
++ err = -ENOMEM;
++ goto fail;
++ }
+
+- 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;
++ if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
++ input_free_device(amijoy_dev[i]);
++ err = -EBUSY;
++ goto fail;
++ }
+
+- input_register_device(amijoy_dev + i);
+- printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
++ 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 @@ static void __exit amijoy_exit(void)
+
+ 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
+--- 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 short analog_joy_btn[] = { BTN_TR
+ 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 unsigned long analog_faketime = 0
+
+ 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 @@ static void analog_name(struct analog *a
+ * 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.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;
+-
+- analog->dev.open = analog_open;
+- analog->dev.close = analog_close;
+- analog->dev.private = port;
+- analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ analog->dev = input_dev = input_allocate_device();
++ if (!input_dev)
++ return -ENOMEM;
++
++ 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;
++
++ 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 @@ static void analog_init_device(struct an
+ 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 @@ static void analog_init_device(struct an
+ 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 @@ static void analog_init_device(struct an
+ 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);
+-
+- printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys);
++ input_register_device(analog->dev);
+
+- 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 @@ static int analog_connect(struct gamepor
+ 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
+--- 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 @@ MODULE_LICENSE("GPL");
+ #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 @@ static void cobra_poll(struct gameport *
+ 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 void cobra_close(struct input_dev
+ 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 @@ static int cobra_connect(struct gameport
+ gameport_set_poll_handler(gameport, cobra_poll);
+ gameport_set_poll_interval(gameport, 20);
+
+- for (i = 0; i < 2; i++)
+- if ((cobra->exists >> i) & 1) {
+-
+- 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;
++ for (i = 0; i < 2; i++) {
++ if (~(cobra->exists >> i) & 1)
++ continue;
+
+- cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ cobra->dev[i] = input_dev = input_allocate_device();
++ if (!input_dev) {
++ err = -ENOMEM;
++ goto fail3;
++ }
+
+- 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);
++ sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
+
+- for (j = 0; cobra_btn[j]; j++)
+- set_bit(cobra_btn[j], cobra->dev[i].keybit);
++ 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]);
+- printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
+- }
++ 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 @@ static void cobra_disconnect(struct game
+
+ 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
+--- a/drivers/input/joystick/db9.c
++++ b/drivers/input/joystick/db9.c
+@@ -43,25 +43,28 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech at u
+ 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);
+-MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
++struct db9_config {
++ int args[2];
++ int nargs;
++};
+
+-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_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
++#define DB9_MAX_PORTS 3
++static struct db9_config db9[DB9_MAX_PORTS] __initdata;
+
+-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(dev, db9[0].args, int, &db9[0].nargs, 0);
++MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
++module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0);
++MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
++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 @@ __obsolete_setup("db9_3=");
+ #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 @@ static int db9_saturn(int mode, struct p
+ 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 @@ static void db9_timer(unsigned long priv
+ {
+ 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 @@ static void db9_timer(unsigned long priv
+ 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 @@ static void db9_timer(unsigned long priv
+ 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 @@ static void db9_timer(unsigned long priv
+ 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 @@ static void db9_timer(unsigned long priv
+
+ 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 @@ static void db9_timer(unsigned long priv
+
+ 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 @@ static void db9_timer(unsigned long priv
+
+ 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 @@ static void db9_timer(unsigned long priv
+ 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 @@ static int db9_open(struct input_dev *de
+ 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 @@ static void db9_close(struct input_dev *
+ 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;
++ }
++
++ 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;
+ }
+
+- if (!(db9 = kzalloc(sizeof(struct db9), GFP_KERNEL))) {
+- parport_put_port(pp);
+- return NULL;
++ 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;
+-
+- 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;
+-
+- 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->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;
++
++ input_dev->open = db9_open;
++ input_dev->close = db9_close;
++
++ 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;
++
++ for (i = 0; i < DB9_MAX_PORTS; i++) {
++ if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0)
++ continue;
++
++ if (db9[i].nargs < 2) {
++ printk(KERN_ERR "db9.c: Device type must be specified.\n");
++ err = -EINVAL;
++ break;
++ }
+
+- if (db9_base[0] || db9_base[1] || db9_base[2])
+- return 0;
++ 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;
++ }
+
+- return -ENODEV;
++ 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
+--- a/drivers/input/joystick/gamecon.c
++++ b/drivers/input/joystick/gamecon.c
+@@ -41,20 +41,22 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech at u
+ 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>)");
+-
+-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");
+-
+-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");
++#define GC_MAX_PORTS 3
++#define GC_MAX_DEVICES 5
++
++struct gc_config {
++ int args[GC_MAX_DEVICES + 1];
++ int nargs;
++};
++
++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 @@ __obsolete_setup("gc_3=");
+
+ 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_psx_read_packet(struct gc
+ 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 @@ static void gc_timer(unsigned long priva
+ 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 @@ static void gc_timer(unsigned long priva
+ 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 @@ static void gc_timer(unsigned long priva
+ 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 @@ static void gc_timer(unsigned long priva
+
+ 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 @@ static void gc_timer(unsigned long priva
+ }
+
+ 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 @@ static void gc_close(struct input_dev *d
+ 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 gc *gc;
+- struct parport *pp;
+- int i, j;
+-
+- if (config[0] < 0)
+- return NULL;
+-
+- if (nargs < 2) {
+- printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
+- return NULL;
+- }
++ struct input_dev *input_dev;
++ int i;
+
+- pp = parport_find_number(config[0]);
++ if (!pad_type)
++ return 0;
+
+- if (!pp) {
+- printk(KERN_ERR "gamecon.c: no such parport\n");
+- return NULL;
++ if (pad_type < 1 || pad_type > GC_MAX) {
++ printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);
++ return -EINVAL;
+ }
+
+- if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) {
+- parport_put_port(pp);
+- return NULL;
++ 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;
+ }
+
+- init_MUTEX(&gc->sem);
++ 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;
+
+- gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
++ input_dev->open = gc_open;
++ input_dev->close = gc_close;
+
+- parport_put_port(pp);
++ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+- if (!gc->pd) {
+- printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
+- kfree(gc);
+- return NULL;
+- }
++ for (i = 0; i < 2; i++)
++ input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+
+- parport_claim(gc->pd);
++ gc->pads[0] |= gc_status_bit[idx];
++ gc->pads[pad_type] |= gc_status_bit[idx];
+
+- init_timer(&gc->timer);
+- gc->timer.data = (long) gc;
+- gc->timer.function = gc_timer;
++ switch (pad_type) {
+
+- for (i = 0; i < nargs - 1; i++) {
++ case GC_N64:
++ for (i = 0; i < 10; i++)
++ set_bit(gc_n64_btn[i], input_dev->keybit);
+
+- if (!config[i + 1])
+- 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;
+- }
++ 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);
++ }
+
+- 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;
+- }
++ break;
+
+- gc->pads[0] |= gc_status_bit[i];
+- gc->pads[config[i + 1]] |= gc_status_bit[i];
++ 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);
+
+- switch(config[i + 1]) {
++ break;
++ }
+
+- case GC_N64:
+- for (j = 0; j < 10; j++)
+- set_bit(gc_n64_btn[j], gc->dev[i].keybit);
++ return 0;
++}
+
+- 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;
+- }
++static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
++{
++ struct gc *gc;
++ struct parport *pp;
++ struct pardevice *pd;
++ int i;
++ int err;
+
+- break;
++ pp = parport_find_number(parport);
++ if (!pp) {
++ printk(KERN_ERR "gamecon.c: no such parport\n");
++ err = -EINVAL;
++ goto err_out;
++ }
+
+- 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;
++ 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;
++ }
+
+- 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;
+- }
+- }
++ gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
++ if (!gc) {
++ printk(KERN_ERR "gamecon.c: Not enough memory\n");
++ err = -ENOMEM;
++ goto err_unreg_pardev;
++ }
+
+- for (j = 0; j < 12; j++)
+- set_bit(gc_psx_btn[j], gc->dev[i].keybit);
++ init_MUTEX(&gc->sem);
++ gc->pd = pd;
++ init_timer(&gc->timer);
++ gc->timer.data = (long) gc;
++ gc->timer.function = gc_timer;
+
+- break;
+- }
++ for (i = 0; i < n_pads; i++) {
++ if (!pads[i])
++ continue;
+
+ 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;
++
++ if (gc[i].nargs < 2) {
++ printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
++ err = -EINVAL;
++ break;
++ }
+
+- return -ENODEV;
++ 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
+--- 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 @@ static short gf2k_seq_digital[] = { 590,
+
+ 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 int gf2k_get_bits(unsigned char *
+
+ 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 void gf2k_close(struct input_dev
+ 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 @@ static int gf2k_connect(struct gameport
+
+ gf2k->length = gf2k_lens[gf2k->id];
+
+- init_input_dev(&gf2k->dev);
+-
+- 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->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;
++
++ 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 @@ static void gf2k_disconnect(struct gamep
+ {
+ 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
+--- 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 @@ MODULE_LICENSE("GPL");
+
+ 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 @@ static void grip_poll(struct gameport *g
+
+ 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 void grip_close(struct input_dev
+ 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 @@ static int grip_connect(struct gameport
+ gameport_set_poll_handler(gameport, grip_poll);
+ gameport_set_poll_interval(gameport, 20);
+
+- for (i = 0; i < 2; i++)
+- if (grip->mode[i]) {
+-
+- 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;
++ for (i = 0; i < 2; i++) {
++ if (!grip->mode[i])
++ continue;
+
+- 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] = input_dev = input_allocate_device();
++ if (!input_dev) {
++ err = -ENOMEM;
++ goto fail3;
++ }
+
+- grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
+
+- for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
++ 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);
++ }
+
+- 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, input_dev->keybit);
+
+- 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);
+- }
++ 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 @@ static void grip_disconnect(struct gamep
+ 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
+--- 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 @@ MODULE_LICENSE("GPL");
+ #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 @@ struct grip_mp {
+ #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 @@ static const int init_seq[] = {
+
+ /* 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 dig_mode_start(struct gamepor
+
+ 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 @@ static int get_and_decode_packet(struct
+ 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 @@ static int get_and_decode_packet(struct
+ 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 @@ static int get_and_decode_packet(struct
+ 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 @@ static int slots_valid(struct grip_mp *g
+ 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 @@ static int multiport_init(struct grip_mp
+
+ /* 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 int multiport_init(struct grip_mp
+
+ 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 @@ static void grip_poll(struct gameport *g
+ }
+
+ for (i = 0; i < 4; i++)
+- if (grip->dirty[i])
++ if (grip->port[i]->dirty)
+ report_slot(grip, i);
+ }
+
+@@ -571,35 +589,43 @@ static void grip_close(struct input_dev
+ * 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;
++
++ 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;
++
++ input_dev->open = grip_open;
++ input_dev->close = grip_close;
+
+- 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->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+- for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
++ 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 @@ static int grip_connect(struct gameport
+ 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 @@ static void grip_disconnect(struct gamep
+ 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
+--- 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_type {
+
+ 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 int guillemot_read_packet(struct
+ 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 void guillemot_close(struct input
+ 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 @@ static int guillemot_connect(struct game
+ 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;
+-
+- 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->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;
++
++ 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 @@ static void guillemot_disconnect(struct
+ 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
+--- a/drivers/input/joystick/iforce/iforce-main.c
++++ b/drivers/input/joystick/iforce/iforce-main.c
+@@ -144,7 +144,7 @@ static int iforce_upload_effect(struct i
+ 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 @@ static int iforce_upload_effect(struct i
+ */
+ 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 @@ void iforce_delete_device(struct iforce
+
+ 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 @@ int iforce_init_device(struct iforce *if
+ 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 @@ int iforce_init_device(struct iforce *if
+
+ 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 @@ int iforce_init_device(struct iforce *if
+ */
+
+ 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 @@ int iforce_init_device(struct iforce *if
+ 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 @@ int iforce_init_device(struct iforce *if
+ */
+
+ 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 @@ int iforce_init_device(struct iforce *if
+ 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);
+-
+- printk(KERN_DEBUG "iforce->dev.open = %p\n", iforce->dev.open);
++ input_register_device(iforce->dev);
+
+- 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
+--- a/drivers/input/joystick/iforce/iforce-packets.c
++++ b/drivers/input/joystick/iforce/iforce-packets.c
+@@ -139,7 +139,8 @@ printk(KERN_DEBUG "iforce-packets.c: con
+ 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 @@ static int mark_core_as_ready(struct ifo
+
+ 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
+--- a/drivers/input/joystick/iforce/iforce-serio.c
++++ b/drivers/input/joystick/iforce/iforce-serio.c
+@@ -131,11 +131,10 @@ static int iforce_serio_connect(struct s
+ 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 @@ static int iforce_serio_connect(struct s
+ 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 @@ static void iforce_serio_disconnect(stru
+ {
+ 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
+--- a/drivers/input/joystick/iforce/iforce-usb.c
++++ b/drivers/input/joystick/iforce/iforce-usb.c
+@@ -135,28 +135,24 @@ static int iforce_usb_probe(struct usb_i
+ 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 @@ static int iforce_usb_probe(struct usb_i
+ 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 @@ fail:
+ kfree(iforce);
+ }
+
+- return -ENODEV;
++ return err;
+ }
+
+ /* Called by iforce_delete() */
+@@ -211,7 +209,7 @@ static void iforce_usb_disconnect(struct
+ 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
+--- a/drivers/input/joystick/iforce/iforce.h
++++ b/drivers/input/joystick/iforce/iforce.h
+@@ -117,7 +117,7 @@ struct iforce_device {
+ };
+
+ 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
+--- 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 @@ MODULE_LICENSE("GPL");
+
+ 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 int interact_read_packet(struct g
+ 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 void interact_close(struct input_
+ 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 @@ static int interact_connect(struct gamep
+ interact->type = i;
+ interact->length = interact_type[i].length;
+
+- interact->dev.private = interact;
+- interact->dev.open = interact_open;
+- interact->dev.close = interact_close;
+-
+- 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->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;
++
++ 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 @@ static void interact_disconnect(struct g
+ {
+ 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
+--- 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
+--- a/drivers/input/joystick/magellan.c
++++ b/drivers/input/joystick/magellan.c
+@@ -49,14 +49,13 @@ MODULE_LICENSE("GPL");
+
+ 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 int magellan_crunch_nibbles(unsig
+
+ 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 @@ static void magellan_disconnect(struct s
+ {
+ 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 void magellan_disconnect(struct s
+ 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;
++
++ magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!magellan || !input_dev)
++ goto fail;
+
+- if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
+- return -ENOMEM;
++ magellan->dev = input_dev;
++ sprintf(magellan->phys, "%s/input0", serio->phys);
+
+- memset(magellan, 0, sizeof(struct magellan));
++ 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;
+
+- magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ input_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;
+- }
+-
+- sprintf(magellan->phys, "%s/input0", serio->phys);
++ set_bit(magellan_buttons[i], input_dev->keybit);
+
+- 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;
++ 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;
+- }
+-
+- input_register_device(&magellan->dev);
+-
+- printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
++ if (err)
++ goto fail;
+
++ 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
+--- 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 @@ static struct {
+
+ 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_check(__u64 t)
+ 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 @@ static int sw_parse(unsigned char *buf,
+ 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 @@ static int sw_parse(unsigned char *buf,
+ 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 @@ static int sw_parse(unsigned char *buf,
+ 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 @@ static int sw_parse(unsigned char *buf,
+ 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 @@ static int sw_parse(unsigned char *buf,
+ 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_guess_mode(unsigned char *
+ 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 @@ static int sw_connect(struct gameport *g
+ 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;
+-
+- sw->dev[i].open = sw_open;
+- sw->dev[i].close = sw_close;
++ input_dev = input_allocate_device();
++ if (!input_dev) {
++ err = -ENOMEM;
++ goto fail3;
++ }
++
++ 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);
++
++ dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
+
+- 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);
++ 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 @@ static void sw_disconnect(struct gamepor
+ 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
+--- a/drivers/input/joystick/spaceball.c
++++ b/drivers/input/joystick/spaceball.c
+@@ -70,8 +70,7 @@ static char *spaceball_names[] = {
+ */
+
+ 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 @@ struct spaceball {
+
+ 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 @@ static void spaceball_disconnect(struct
+ {
+ 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 void spaceball_disconnect(struct
+ 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);
++
++ 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;
+
+- spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ 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;
+- }
+-
+- input_register_device(&spaceball->dev);
+-
+- printk(KERN_INFO "input: %s on serio%s\n",
+- spaceball_names[id], serio->phys);
++ if (err)
++ goto fail;
+
++ 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
+--- a/drivers/input/joystick/spaceorb.c
++++ b/drivers/input/joystick/spaceorb.c
+@@ -52,15 +52,13 @@ MODULE_LICENSE("GPL");
+
+ 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 unsigned char *spaceorb_errors[]
+
+ 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 @@ static void spaceorb_process_packet(stru
+ 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 @@ static void spaceorb_process_packet(stru
+
+ 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 @@ static void spaceorb_disconnect(struct s
+ {
+ 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 void spaceorb_disconnect(struct s
+ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
+ {
+ struct spaceorb *spaceorb;
+- int i, t;
+- int err;
+-
+- if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
+- return -ENOMEM;
+-
+- memset(spaceorb, 0, sizeof(struct spaceorb));
++ struct input_dev *input_dev;
++ int err = -ENOMEM;
++ int i;
+
+- spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!spaceorb || !input_dev)
++ goto fail;
+
+- for (i = 0; i < 6; i++)
+- set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
++ spaceorb->dev = input_dev;
++ sprintf(spaceorb->phys, "%s/input0", serio->phys);
+
+- 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;
+- }
++ 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;
+
+- spaceorb->serio = serio;
+- spaceorb->dev.private = spaceorb;
++ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+- sprintf(spaceorb->phys, "%s/input0", serio->phys);
++ for (i = 0; i < 6; i++)
++ set_bit(spaceorb_buttons[i], input_dev->keybit);
+
+- 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;
++ 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;
+- }
+-
+- input_register_device(&spaceorb->dev);
++ if (err)
++ goto fail;
+
++ 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
+--- a/drivers/input/joystick/stinger.c
++++ b/drivers/input/joystick/stinger.c
+@@ -48,14 +48,12 @@ MODULE_LICENSE("GPL");
+
+ #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 @@ struct stinger {
+
+ 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 @@ static void stinger_disconnect(struct se
+ {
+ 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 void stinger_disconnect(struct se
+ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
+ {
+ struct stinger *stinger;
+- int i;
+- int err;
+-
+- if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
+- return -ENOMEM;
+-
+- memset(stinger, 0, sizeof(struct stinger));
++ struct input_dev *input_dev;
++ int err = -ENOMEM;
+
+- 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 = kmalloc(sizeof(struct stinger), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!stinger || !input_dev)
++ goto fail;
+
++ 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;
+-
+- 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->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;
++
++ 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;
+- }
+-
+- input_register_device(&stinger->dev);
+-
+- printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
++ if (err)
++ goto fail;
+
++ 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
+--- 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 @@ MODULE_LICENSE("GPL");
+ #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 @@ struct tmdc {
+ 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 @@ static int tmdc_read_packet(struct gamep
+ 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 @@ static void tmdc_poll(struct gameport *g
+ {
+ 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
+-
+- for (j = 0; j < 2; j++)
+- if (r & (1 << j) & tmdc->exists) {
+-
+- if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
+- bad = 1;
+- continue;
+- }
+-
+- dev = tmdc->dev + j;
++ else {
++ for (i = 0; i < 2; i++) {
++ if (r & (1 << i) & tmdc->exists) {
+
+- 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]]);
++ if (tmdc_parse_packet(tmdc->port[i], data[i]))
++ bad = 1;
+ }
+-
+- 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 @@ static void tmdc_close(struct input_dev
+ 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 @@ static int tmdc_connect(struct gameport
+ gameport_set_poll_handler(gameport, tmdc_poll);
+ gameport_set_poll_interval(gameport, 20);
+
+- for (j = 0; j < 2; j++)
+- if (tmdc->exists & (1 << j)) {
+-
+- tmdc->mode[j] = data[j][TMDC_BYTE_ID];
+-
+- for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
++ for (i = 0; i < 2; i++) {
++ if (tmdc->exists & (1 << i)) {
+
+- 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 @@ static void tmdc_disconnect(struct gamep
+ 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
+--- a/drivers/input/joystick/turbografx.c
++++ b/drivers/input/joystick/turbografx.c
+@@ -42,19 +42,21 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech at u
+ 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);
+-MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
++#define TGFX_MAX_PORTS 3
++#define TGFX_MAX_DEVICES 7
+
+-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_PARM_DESC(map2, "Describes second set of devices");
++struct tgfx_config {
++ int args[TGFX_MAX_DEVICES + 1];
++ int nargs;
++};
++
++static struct tgfx_config tgfx[TGFX_MAX_PORTS] __initdata;
+
+-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(map, tgfx[0].args, int, &tgfx[0].nargs, 0);
++MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
++module_param_array_named(map2, tgfx[1].args, int, &tgfx[1].nargs, 0);
++MODULE_PARM_DESC(map2, "Describes second set of devices");
++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 @@ __obsolete_setup("tgfx_3=");
+ #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 @@ static void tgfx_timer(unsigned long pri
+ 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 @@ static void tgfx_close(struct input_dev
+ 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;
+ }
+
+- 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 = 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 = pd;
+ init_timer(&tgfx->timer);
+ tgfx->timer.data = (long) tgfx;
+ tgfx->timer.function = tgfx_timer;
+
+- tgfx->sticks = 0;
+-
+- 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;
++ for (i = 0; i < n_devs; i++) {
++ if (n_buttons[i] < 1)
++ continue;
++
++ 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].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+- tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
++ 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;
++ }
+
+- for (j = 0; j < config[i+1]; j++)
+- set_bit(tgfx_buttons[j], tgfx->dev[i].keybit);
++ 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);
+
+- 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;
++ for (j = 0; j < n_buttons[i]; j++)
++ set_bit(tgfx_buttons[j], input_dev->keybit);
+
+- input_register_device(tgfx->dev + i);
+- printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
+- config[i+1], tgfx->pd->port->name);
+- }
++ 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;
++
++ for (i = 0; i < TGFX_MAX_PORTS; i++) {
++ if (tgfx[i].nargs == 0 || tgfx[i].args[0] < 0)
++ continue;
++
++ if (tgfx[i].nargs < 2) {
++ printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
++ err = -EINVAL;
++ break;
++ }
+
+- if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
+- return 0;
++ 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;
++ }
+
+- return -ENODEV;
++ 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
+--- a/drivers/input/joystick/twidjoy.c
++++ b/drivers/input/joystick/twidjoy.c
+@@ -69,8 +69,6 @@ MODULE_LICENSE("GPL");
+
+ #define TWIDJOY_MAX_LENGTH 5
+
+-static char *twidjoy_name = "Handykey Twiddler";
+-
+ static struct twidjoy_button_spec {
+ int bitshift;
+ int bitmask;
+@@ -95,7 +93,7 @@ twidjoy_buttons[] = {
+ */
+
+ 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 @@ struct twidjoy {
+
+ 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;
+-
+- button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
++ struct input_dev *dev = twidjoy->dev;
++ unsigned char *data = twidjoy->data;
++ struct twidjoy_button_spec *bp;
++ int button_bits, abs_x, abs_y;
+
+- input_regs(dev, regs);
++ button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
+
+- for (bp = twidjoy_buttons; bp->bitmask; bp++) {
+- int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
+- int i;
++ input_regs(dev, regs);
+
+- for (i = 0; i < bp->bitmask; i++)
+- input_report_key(dev, bp->buttons[i], i+1 == value);
+- }
++ for (bp = twidjoy_buttons; bp->bitmask; bp++) {
++ int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
++ int i;
+
+- abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
+- if (data[4] & 0x08) abs_x -= 256;
++ for (i = 0; i < bp->bitmask; i++)
++ input_report_key(dev, bp->buttons[i], i+1 == value);
++ }
+
+- abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
+- if (data[3] & 0x02) abs_y -= 256;
++ abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
++ if (data[4] & 0x08) abs_x -= 256;
+
+- input_report_abs(dev, ABS_X, -abs_x);
+- input_report_abs(dev, ABS_Y, +abs_y);
++ abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
++ if (data[3] & 0x02) abs_y -= 256;
+
+- input_sync(dev);
+- }
++ input_report_abs(dev, ABS_X, -abs_x);
++ input_report_abs(dev, ABS_Y, +abs_y);
+
+- return;
++ input_sync(dev);
+ }
+
+ /*
+@@ -179,9 +173,9 @@ static void twidjoy_disconnect(struct se
+ {
+ 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 @@ static int twidjoy_connect(struct serio
+ {
+ 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;
+
+- memset(twidjoy, 0, sizeof(struct twidjoy));
++ twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!twidjoy || !input_dev)
++ goto fail;
+
++ 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;
++
++ 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);
+
+- twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+-
+- 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;
+- }
+-
+- input_register_device(&twidjoy->dev);
+-
+- printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
++ if (err)
++ goto fail;
+
++ 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
+--- a/drivers/input/joystick/warrior.c
++++ b/drivers/input/joystick/warrior.c
+@@ -47,14 +47,13 @@ MODULE_LICENSE("GPL");
+
+ #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 @@ struct warrior {
+
+ 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 @@ static void warrior_disconnect(struct se
+ {
+ 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 void warrior_disconnect(struct se
+ 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;
+-
+- 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 = kzalloc(sizeof(struct warrior), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!warrior || !input_dev)
++ goto fail;
+
++ 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;
+-
+- 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->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;
++
++ 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;
+- }
+-
+- input_register_device(&warrior->dev);
+-
+- printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
++ if (err)
++ goto fail;
+
++ 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/Kconfig b/drivers/input/keyboard/Kconfig
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -13,11 +13,11 @@ menuconfig INPUT_KEYBOARD
+ if INPUT_KEYBOARD
+
+ config KEYBOARD_ATKBD
+- tristate "AT keyboard" if !PC
++ tristate "AT keyboard" if !X86_PC
+ default y
+ select SERIO
+ select SERIO_LIBPS2
+- select SERIO_I8042 if PC
++ select SERIO_I8042 if X86_PC
+ select SERIO_GSCPS2 if GSC
+ help
+ Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
+diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
+--- a/drivers/input/keyboard/amikbd.c
++++ b/drivers/input/keyboard/amikbd.c
+@@ -155,10 +155,7 @@ static const char *amikbd_messages[8] =
+ [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 @@ static irqreturn_t amikbd_interrupt(int
+
+ 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 @@ static int __init amikbd_init(void)
+ if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
+ return -EBUSY;
+
+- init_input_dev(&amikbd_dev);
+-
+- 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 = 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->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
+--- a/drivers/input/keyboard/atkbd.c
++++ b/drivers/input/keyboard/atkbd.c
+@@ -185,12 +185,12 @@ static struct {
+
+ 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 @@ static irqreturn_t atkbd_interrupt(struc
+ 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 @@ static irqreturn_t atkbd_interrupt(struc
+ 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 @@ static irqreturn_t atkbd_interrupt(struc
+ }
+
+ 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 @@ static irqreturn_t atkbd_interrupt(struc
+ "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 @@ static irqreturn_t atkbd_interrupt(struc
+ 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 @@ static irqreturn_t atkbd_interrupt(struc
+ 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 @@ static irqreturn_t atkbd_interrupt(struc
+ 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 @@ static int atkbd_event(struct input_dev
+
+ return 0;
+
+-
+ case EV_REP:
+
+ if (atkbd->softrepeat) return 0;
+@@ -693,7 +692,7 @@ static void atkbd_disconnect(struct seri
+ 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 @@ static void atkbd_disconnect(struct seri
+
+
+ /*
+- * 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_keycode_table(stru
+
+ 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 void atkbd_set_device_attrs(struc
+ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
+ {
+ struct atkbd *atkbd;
+- int err;
+-
+- if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
+- return - ENOMEM;
++ struct input_dev *dev;
++ int err = -ENOMEM;
+
+- memset(atkbd, 0, sizeof(struct atkbd));
++ atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
++ dev = input_allocate_device();
++ if (!atkbd || !dev)
++ goto fail;
+
++ atkbd->dev = dev;
+ ps2_init(&atkbd->ps2dev, serio);
+
+ switch (serio->id.type) {
+@@ -828,19 +834,15 @@ static int atkbd_connect(struct serio *s
+ 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 @@ static int atkbd_connect(struct serio *s
+ 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 @@ static int atkbd_connect(struct serio *s
+
+ 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 @@ static int atkbd_reconnect(struct serio
+ 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_show_extra(struct a
+
+ 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 @@ static ssize_t atkbd_set_extra(struct at
+ 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_show_scroll(struct
+
+ 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 @@ static ssize_t atkbd_set_scroll(struct a
+ 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_show_set(struct atk
+
+ 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 @@ static ssize_t atkbd_set_set(struct atkb
+ 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_show_softrepeat(str
+
+ 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 @@ static ssize_t atkbd_set_softrepeat(stru
+ 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_show_softraw(struct
+
+ 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 @@ static ssize_t atkbd_set_softraw(struct
+ 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
+--- a/drivers/input/keyboard/corgikbd.c
++++ b/drivers/input/keyboard/corgikbd.c
+@@ -12,7 +12,7 @@
+ */
+
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/init.h>
+ #include <linux/input.h>
+ #include <linux/interrupt.h>
+@@ -70,8 +70,7 @@ static unsigned char corgikbd_keycode[NR
+
+ 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 @@ static void corgikbd_scankeyboard(struct
+ 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 @@ static void corgikbd_scankeyboard(struct
+ 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 @@ static void corgikbd_scankeyboard(struct
+
+ 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 @@ static void corgikbd_hinge_timer(unsigne
+ 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 @@ static void corgikbd_hinge_timer(unsigne
+ }
+
+ #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 corgikbd_resume(struct device
+
+ 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 @@ static int __init corgikbd_probe(struct
+
+ 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));
++
++ 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], corgikbd->input.keybit);
+- clear_bit(0, corgikbd->input.keybit);
+- set_bit(SW_0, corgikbd->input.swbit);
+- set_bit(SW_1, corgikbd->input.swbit);
++ 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);
+
+- 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 @@ static int __init corgikbd_probe(struct
+ 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 @@ static int corgikbd_remove(struct device
+ 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
+--- a/drivers/input/keyboard/hil_kbd.c
++++ b/drivers/input/keyboard/hil_kbd.c
+@@ -204,7 +204,7 @@ static irqreturn_t hil_kbd_interrupt(str
+ 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 @@ static void hil_kbd_disconnect(struct se
+ {
+ struct hil_kbd *kbd;
+
+- kbd = (struct hil_kbd *)serio->private;
++ kbd = serio_get_drvdata(serio);
+ if (kbd == NULL) {
+ BUG();
+ return;
+@@ -245,20 +245,20 @@ static void hil_kbd_disconnect(struct se
+ 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 @@ static void hil_kbd_connect(struct serio
+ 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
+--- 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 @@ static int __init
+ 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 @@ static struct parisc_device_id hil_tbl[]
+ 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
+--- a/drivers/input/keyboard/lkkbd.c
++++ b/drivers/input/keyboard/lkkbd.c
+@@ -102,7 +102,7 @@ static int ctrlclick_volume = 100; /* %
+ 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 @@ static lk_keycode_t lkkbd_keycode[LK_NUM
+ };
+
+ #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 @@ struct lkkbd {
+ 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 @@ lkkbd_interrupt (struct serio *serio, un
+ 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,11 +434,11 @@ lkkbd_interrupt (struct serio *serio, un
+
+ 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 "
+@@ -482,12 +481,12 @@ lkkbd_interrupt (struct serio *serio, un
+
+ 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 @@ lkkbd_reinit (void *data)
+ 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 @@ lkkbd_reinit (void *data)
+ }
+
+ /* 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 @@ static int
+ 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 @@ lkkbd_disconnect (struct serio *serio)
+ {
+ 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
+--- a/drivers/input/keyboard/maple_keyb.c
++++ b/drivers/input/keyboard/maple_keyb.c
+@@ -37,7 +37,7 @@ static unsigned char dc_kbd_keycode[256]
+
+
+ struct dc_kbd {
+- struct input_dev dev;
++ struct input_dev *dev;
+ unsigned char new[8];
+ unsigned char old[8];
+ };
+@@ -46,30 +46,24 @@ struct dc_kbd {
+ 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=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);
++ 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++) {
++
++ 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 @@ static void dc_kbd_callback(struct maple
+ 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;
+-
+- kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+-
+- 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);
++ 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;
++ }
+
+- kbd->dev.private = kbd;
++ kbd->dev = input_dev;
+
+- kbd->dev.name = dev->product_name;
+- kbd->dev.id.bustype = BUS_MAPLE;
++ 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);
+
+- 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 @@ static void dc_kbd_disconnect(struct map
+ {
+ 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
+--- a/drivers/input/keyboard/newtonkbd.c
++++ b/drivers/input/keyboard/newtonkbd.c
+@@ -57,11 +57,9 @@ static unsigned char nkbd_keycode[128] =
+ 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 @@ static irqreturn_t nkbd_interrupt(struct
+
+ /* 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 irqreturn_t nkbd_interrupt(struct
+ 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;
+- }
+-
+- 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);
++ if (err)
++ goto fail;
+
++ 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
+--- a/drivers/input/keyboard/spitzkbd.c
++++ b/drivers/input/keyboard/spitzkbd.c
+@@ -12,7 +12,7 @@
+ */
+
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/init.h>
+ #include <linux/input.h>
+ #include <linux/interrupt.h>
+@@ -85,7 +85,7 @@ static int spitz_senses[] = {
+
+ 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 @@ static void spitzkbd_scankeyboard(struct
+
+ 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 @@ static void spitzkbd_scankeyboard(struct
+ 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 @@ static void spitzkbd_scankeyboard(struct
+
+ 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 irqreturn_t spitzkbd_interrupt(in
+ static void spitzkbd_timer_callback(unsigned long data)
+ {
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
++
+ spitzkbd_scankeyboard(spitzkbd_data, NULL);
+ }
+
+@@ -298,9 +298,9 @@ static void spitzkbd_hinge_timer(unsigne
+ 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 @@ static void spitzkbd_hinge_timer(unsigne
+ }
+
+ #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;
+-
+- /* 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);
+- }
++ 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);
++
+ 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);
+-
+- 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;
+- }
++ 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);
++
++ /* 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 spitzkbd_resume(struct device
+
+ 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 @@ static int __init spitzkbd_probe(struct
+ 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(input_dev);
+
+- input_register_device(&spitzkbd->input);
+ mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+@@ -444,7 +453,7 @@ static int spitzkbd_remove(struct device
+ 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
+--- a/drivers/input/keyboard/sunkbd.c
++++ b/drivers/input/keyboard/sunkbd.c
+@@ -76,13 +76,14 @@ static unsigned char sunkbd_keycode[128]
+
+ 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 @@ static irqreturn_t sunkbd_interrupt(stru
+ 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 @@ static int sunkbd_initialize(struct sunk
+ 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 @@ static void sunkbd_reinit(void *data)
+
+ 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 void sunkbd_reinit(void *data)
+ 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));
+- for (i = 0; i < 128; i++)
+- set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
+- clear_bit(0, sunkbd->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);
++ 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], input_dev->keybit);
++ clear_bit(0, input_dev->keybit);
+
++ 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 int sunkbd_connect(struct serio *
+ 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
+--- a/drivers/input/keyboard/xtkbd.c
++++ b/drivers/input/keyboard/xtkbd.c
+@@ -56,11 +56,9 @@ static unsigned char xtkbd_keycode[256]
+ 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 @@ static irqreturn_t xtkbd_interrupt(struc
+ 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 irqreturn_t xtkbd_interrupt(struc
+ 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;
+-
+- 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;
+-
+- serio_set_drvdata(serio, xtkbd);
+-
+- err = serio_open(serio, drv);
+- if (err) {
+- serio_set_drvdata(serio, NULL);
+- kfree(xtkbd);
+- return err;
+- }
+-
++ xtkbd->dev = input_dev;
++ sprintf(xtkbd->phys, "%s/input0", serio->phys);
+ 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);
++ 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);
+
+- 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;
++ for (i = 0; i < 255; i++)
++ set_bit(xtkbd->keycode[i], input_dev->keybit);
++ clear_bit(0, input_dev->keybit);
+
+- input_register_device(&xtkbd->dev);
++ serio_set_drvdata(serio, xtkbd);
+
+- printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
++ err = serio_open(serio, drv);
++ if (err)
++ goto fail;
+
++ 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
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -14,7 +14,7 @@ if INPUT_MISC
+
+ 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
+--- a/drivers/input/misc/m68kspkr.c
++++ b/drivers/input/misc/m68kspkr.c
+@@ -24,9 +24,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz at linu
+ 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 m68kspkr_event(struct input_d
+
+ 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.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;
+-
+- input_register_device(&m68kspkr_dev);
++ m68kspkr_dev = input_allocate_device();
++ if (!m68kspkr_dev)
++ return -ENOMEM;
++
++ 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;
++
++ 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
+--- a/drivers/input/misc/pcspkr.c
++++ b/drivers/input/misc/pcspkr.c
+@@ -23,9 +23,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech at u
+ 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 pcspkr_event(struct input_dev
+
+ 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.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 = input_allocate_device();
++ if (!pcspkr_dev)
++ return -ENOMEM;
++
++ pcspkr_dev->name = "PC Speaker";
++ pcspkr_dev->phys = "isa0061/input0";
++ pcspkr_dev->id.bustype = BUS_ISA;
++ pcspkr_dev->id.vendor = 0x001f;
++ pcspkr_dev->id.product = 0x0001;
++ pcspkr_dev->id.version = 0x0100;
++
++ pcspkr_dev->evbit[0] = BIT(EV_SND);
++ pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
++ pcspkr_dev->event = pcspkr_event;
+
+- input_register_device(&pcspkr_dev);
+-
+- 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
+--- a/drivers/input/misc/sparcspkr.c
++++ b/drivers/input/misc/sparcspkr.c
+@@ -17,28 +17,24 @@
+ #endif
+
+ MODULE_AUTHOR("David S. Miller <davem at 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 @@ static int __init init_ebus_beep(struct
+ {
+ 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 @@ static int __init init_isa_beep(struct s
+ {
+ 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 int __init sparcspkr_init(void)
+
+ 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/Kconfig b/drivers/input/mouse/Kconfig
+--- a/drivers/input/mouse/Kconfig
++++ b/drivers/input/mouse/Kconfig
+@@ -17,7 +17,7 @@ config MOUSE_PS2
+ default y
+ select SERIO
+ select SERIO_LIBPS2
+- select SERIO_I8042 if PC
++ select SERIO_I8042 if X86_PC
+ select SERIO_GSCPS2 if GSC
+ ---help---
+ Say Y here if you have a PS/2 mouse connected to your system. This
+diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
+--- a/drivers/input/mouse/alps.c
++++ b/drivers/input/mouse/alps.c
+@@ -79,8 +79,8 @@ static void alps_process_packet(struct p
+ {
+ 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 int alps_reconnect(struct psmouse
+ 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 @@ int alps_init(struct psmouse *psmouse)
+ 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);
+-
+- 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_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);
++
++ 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;
+-
+- 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);
+-
+- input_register_device(&priv->dev2);
++ 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;
++
++ 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);
+
+- 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 @@ int alps_init(struct psmouse *psmouse)
+ 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
+--- a/drivers/input/mouse/alps.h
++++ b/drivers/input/mouse/alps.h
+@@ -22,7 +22,7 @@ struct alps_model_info {
+ };
+
+ 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
+--- a/drivers/input/mouse/amimouse.c
++++ b/drivers/input/mouse/amimouse.c
+@@ -34,10 +34,7 @@ MODULE_DESCRIPTION("Amiga mouse driver")
+ 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 @@ static irqreturn_t amimouse_interrupt(in
+
+ 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 @@ static int __init amimouse_init(void)
+ 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;
+-
+- 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;
++ if (!(amimouse_dev = input_allocate_device()))
++ return -ENOMEM;
++
++ 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;
++
++ 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;
+
+- input_register_device(&amimouse_dev);
++ input_register_device(amimouse_dev);
+
+- printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
+ 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
+--- a/drivers/input/mouse/hil_ptr.c
++++ b/drivers/input/mouse/hil_ptr.c
+@@ -196,7 +196,7 @@ static irqreturn_t hil_ptr_interrupt(str
+ 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 @@ static void hil_ptr_disconnect(struct se
+ {
+ struct hil_ptr *ptr;
+
+- ptr = (struct hil_ptr *)serio->private;
++ ptr = serio_get_drvdata(serio);
+ if (ptr == NULL) {
+ BUG();
+ return;
+@@ -238,21 +238,19 @@ static void hil_ptr_disconnect(struct se
+ 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 @@ static void hil_ptr_connect(struct serio
+ (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
+--- a/drivers/input/mouse/inport.c
++++ b/drivers/input/mouse/inport.c
+@@ -87,40 +87,7 @@ MODULE_PARM_DESC(irq, "IRQ number (5=def
+
+ __obsolete_setup("inport_irq=");
+
+-static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+-
+-static int inport_open(struct input_dev *dev)
+-{
+- if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
+- return -EBUSY;
+- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+- outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
+-
+- return 0;
+-}
+-
+-static void inport_close(struct input_dev *dev)
+-{
+- outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+- outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
+- 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 struct input_dev *inport_dev;
+
+ static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+@@ -129,31 +96,48 @@ static irqreturn_t inport_interrupt(int
+ 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);
++ input_regs(inport_dev, regs);
+
+ outb(INPORT_REG_X, INPORT_CONTROL_PORT);
+- input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_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));
++ 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);
++ 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);
++ input_sync(inport_dev);
+ return IRQ_HANDLED;
+ }
+
++static int inport_open(struct input_dev *dev)
++{
++ if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
++ return -EBUSY;
++ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
++ outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
++
++ return 0;
++}
++
++static void inport_close(struct input_dev *dev)
++{
++ outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
++ outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
++ free_irq(inport_irq, NULL);
++}
++
+ 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 @@ static int __init inport_init(void)
+ 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
+--- a/drivers/input/mouse/lifebook.c
++++ b/drivers/input/mouse/lifebook.c
+@@ -34,7 +34,7 @@ static struct dmi_system_id lifebook_dmi
+ 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_detect(struct psmouse *psmo
+
+ 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
+--- a/drivers/input/mouse/logibm.c
++++ b/drivers/input/mouse/logibm.c
+@@ -77,39 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ number (5=def
+
+ __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 @@ static irqreturn_t logibm_interrupt(int
+ 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 @@ static int __init logibm_init(void)
+ 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;
++ }
++
++ 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;
+
+- printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
++ 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
+--- a/drivers/input/mouse/logips2pp.c
++++ b/drivers/input/mouse/logips2pp.c
+@@ -40,7 +40,7 @@ struct ps2pp_info {
+
+ 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 struct ps2pp_info *get_model_info
+ 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 @@ int ps2pp_init(struct psmouse *psmouse,
+ }
+
+ 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
+--- a/drivers/input/mouse/maplemouse.c
++++ b/drivers/input/mouse/maplemouse.c
+@@ -41,13 +41,12 @@ static int dc_mouse_connect(struct maple
+ 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 @@ static int dc_mouse_connect(struct maple
+
+ 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 @@ static void dc_mouse_disconnect(struct m
+ 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
+--- a/drivers/input/mouse/pc110pad.c
++++ b/drivers/input/mouse/pc110pad.c
+@@ -53,13 +53,10 @@ MODULE_LICENSE("GPL");
+ 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 @@ static irqreturn_t pc110pad_interrupt(in
+ 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 void pc110pad_close(struct input_
+
+ 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 @@ static int __init pc110pad_init(void)
+
+ 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);
+-
+- pc110pad_dev.absmax[ABS_X] = 0x1ff;
+- pc110pad_dev.absmax[ABS_Y] = 0x0ff;
+-
+- pc110pad_dev.open = pc110pad_open;
+- pc110pad_dev.close = pc110pad_close;
+-
+- 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;
++ 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->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->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);
+
+- input_register_device(&pc110pad_dev);
++ pc110pad_dev->absmax[ABS_X] = 0x1ff;
++ pc110pad_dev->absmax[ABS_Y] = 0x0ff;
+
+- printk(KERN_INFO "input: %s at %#x irq %d\n",
+- pc110pad_name, pc110pad_io, pc110pad_irq);
++ pc110pad_dev->open = pc110pad_open;
++ pc110pad_dev->close = pc110pad_close;
++
++ 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
+--- a/drivers/input/mouse/psmouse-base.c
++++ b/drivers/input/mouse/psmouse-base.c
+@@ -114,7 +114,7 @@ struct psmouse_protocol {
+
+ 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 @@ static int genius_detect(struct psmouse
+ 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 @@ static int intellimouse_detect(struct ps
+ 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 @@ static int im_explorer_detect(struct psm
+ 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 @@ static int thinking_detect(struct psmous
+ 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 @@ static void psmouse_disconnect(struct se
+
+ 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 void psmouse_disconnect(struct se
+
+ 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 @@ static int psmouse_switch_protocol(struc
+ 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_switch_protocol(struc
+ 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 @@ static int psmouse_connect(struct serio
+ 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 @@ static int psmouse_connect(struct serio
+ 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 @@ static int psmouse_connect(struct serio
+
+ 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 @@ static int psmouse_connect(struct serio
+ 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 @@ static ssize_t psmouse_attr_set_protocol
+ {
+ 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 @@ static ssize_t psmouse_attr_set_protocol
+ 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 @@ static ssize_t psmouse_attr_set_protocol
+ 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 @@ static ssize_t psmouse_attr_set_protocol
+ 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 @@ static ssize_t psmouse_attr_set_protocol
+ 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
+--- a/drivers/input/mouse/psmouse.h
++++ b/drivers/input/mouse/psmouse.h
+@@ -36,7 +36,7 @@ typedef enum {
+
+ 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
+--- a/drivers/input/mouse/rpcmouse.c
++++ b/drivers/input/mouse/rpcmouse.c
+@@ -34,20 +34,7 @@ MODULE_DESCRIPTION("Acorn RiscPC mouse d
+ 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 @@ static irqreturn_t rpcmouse_irq(int irq,
+ 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
+--- a/drivers/input/mouse/sermouse.c
++++ b/drivers/input/mouse/sermouse.c
+@@ -48,7 +48,7 @@ static char *sermouse_protocols[] = { "N
+ "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 @@ struct sermouse {
+
+ 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_msc(struct
+
+ 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 @@ static void sermouse_disconnect(struct s
+ {
+ 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 void sermouse_disconnect(struct s
+ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
+ {
+ struct sermouse *sermouse;
+- unsigned char c;
+- int err;
+-
+- if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
+- return -ENODEV;
+-
+- 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);
++ struct input_dev *input_dev;
++ unsigned char c = serio->id.extra;
++ int err = -ENOMEM;
++
++ sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!sermouse || !input_dev)
++ goto fail;
+
++ 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;
+- }
+-
+- input_register_device(&sermouse->dev);
++ if (err)
++ goto fail;
+
+- 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
+--- a/drivers/input/mouse/synaptics.c
++++ b/drivers/input/mouse/synaptics.c
+@@ -342,7 +342,7 @@ static void synaptics_parse_hw_state(uns
+ */
+ 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 unsigned char synaptics_detect_pk
+
+ 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 @@ int synaptics_init(struct psmouse *psmou
+ 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
+--- a/drivers/input/mouse/vsxxxaa.c
++++ b/drivers/input/mouse/vsxxxaa.c
+@@ -112,7 +112,7 @@ MODULE_LICENSE ("GPL");
+
+
+ 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 @@ vsxxxaa_smells_like_packet (struct vsxxx
+ 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 @@ vsxxxaa_handle_REL_packet (struct vsxxxa
+ 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 @@ vsxxxaa_handle_ABS_packet (struct vsxxxa
+ 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 @@ vsxxxaa_disconnect (struct serio *serio)
+ {
+ 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 @@ static int
+ 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;
+-
+- 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 = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
++ input_dev = input_allocate_device ();
++ if (!mouse || !input_dev)
++ goto fail;
+
++ 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 */
+-
+- input_register_device (&mouse->dev);
++ serio->write (serio, 'T'); /* Test */
+
+- 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
+--- 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 file_operations mousedev_f
+ 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 @@ static struct input_handle *mousedev_con
+
+ 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 @@ static void mousedev_disconnect(struct i
+ 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 @@ static int __init mousedev_init(void)
+ 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 @@ static void __exit mousedev_exit(void)
+ 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/ct82c710.c b/drivers/input/serio/ct82c710.c
+--- a/drivers/input/serio/ct82c710.c
++++ b/drivers/input/serio/ct82c710.c
+@@ -37,6 +37,7 @@
+ #include <linux/serio.h>
+ #include <linux/errno.h>
+ #include <linux/err.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+
+diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
+--- a/drivers/input/serio/gscps2.c
++++ b/drivers/input/serio/gscps2.c
+@@ -211,9 +211,6 @@ static void gscps2_reset(struct gscps2po
+ 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 @@ static int gscps2_open(struct serio *por
+
+ gscps2_reset(ps2port);
+
++ /* enable it */
++ gscps2_enable(ps2port, ENABLE);
++
+ gscps2_interrupt(0, NULL, NULL);
+
+ return 0;
+@@ -331,7 +331,7 @@ static int __init gscps2_probe(struct pa
+ {
+ 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 @@ static int __init gscps2_probe(struct pa
+ 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 @@ static int __init gscps2_probe(struct pa
+
+ 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_device_id gscps2_de
+ };
+
+ 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
+--- a/drivers/input/serio/hil_mlc.c
++++ b/drivers/input/serio/hil_mlc.c
+@@ -801,7 +801,8 @@ static int hil_mlc_serio_open(struct ser
+ 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 @@ static void hil_mlc_serio_close(struct s
+ 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 @@ int hil_mlc_register(hil_mlc *mlc) {
+ 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
+--- a/drivers/input/serio/hp_sdc.c
++++ b/drivers/input/serio/hp_sdc.c
+@@ -764,7 +764,7 @@ MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
+ 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 @@ static int __init hp_sdc_init_hppa(struc
+ 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
+--- 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
+--- a/drivers/input/serio/i8042.c
++++ b/drivers/input/serio/i8042.c
+@@ -20,6 +20,7 @@
+ #include <linux/serio.h>
+ #include <linux/err.h>
+ #include <linux/rcupdate.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+
+@@ -911,12 +912,10 @@ static long i8042_panic_blink(long count
+ * 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 +925,10 @@ static int i8042_suspend(struct device *
+ * 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/serio/maceps2.c b/drivers/input/serio/maceps2.c
+--- a/drivers/input/serio/maceps2.c
++++ b/drivers/input/serio/maceps2.c
+@@ -14,7 +14,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/ioport.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/err.h>
+diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
+--- a/drivers/input/serio/q40kbd.c
++++ b/drivers/input/serio/q40kbd.c
+@@ -37,6 +37,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/err.h>
+ #include <linux/bitops.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
+--- a/drivers/input/serio/rpckbd.c
++++ b/drivers/input/serio/rpckbd.c
+@@ -34,6 +34,7 @@
+ #include <linux/init.h>
+ #include <linux/serio.h>
+ #include <linux/err.h>
++#include <linux/platform_device.h>
+
+ #include <asm/irq.h>
+ #include <asm/hardware.h>
+diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
+--- a/drivers/input/touchscreen/corgi_ts.c
++++ b/drivers/input/touchscreen/corgi_ts.c
+@@ -11,7 +11,7 @@
+
+
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/init.h>
+ #include <linux/input.h>
+ #include <linux/interrupt.h>
+@@ -41,8 +41,7 @@ struct ts_event {
+ };
+
+ 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 @@ static void new_data(struct corgi_ts *co
+ 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 @@ static irqreturn_t ts_interrupt(int irq,
+ }
+
+ #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);
+-
+- 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;
++ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+- 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 @@ static int __init corgits_probe(struct d
+ {
+ 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);
+-
+- strcpy(corgi_ts->phys, "corgits/input0");
+-
+- 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;
++ corgi_ts->input = input_dev;
++
++ init_timer(&corgi_ts->timer);
++ corgi_ts->timer.data = (unsigned long) corgi_ts;
++ corgi_ts->timer.function = corgi_ts_timer;
++
++ 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 @@ static int __init corgits_probe(struct d
+ 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 @@ static int corgits_remove(struct device
+ 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
+--- a/drivers/input/touchscreen/elo.c
++++ b/drivers/input/touchscreen/elo.c
+@@ -36,14 +36,12 @@ MODULE_LICENSE("GPL");
+
+ #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 @@ struct elo {
+
+ 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 @@ static void elo_process_data_10(struct e
+ 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_10(struct e
+
+ 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 @@ static void elo_process_data_6(struct el
+ 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_6(struct el
+
+ 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 @@ static void elo_disconnect(struct serio
+ {
+ 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 void elo_disconnect(struct serio
+ 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));
++ elo->serio = serio;
++ elo->id = serio->id.id;
++ elo->dev = input_dev;
++ snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
+
+- init_input_dev(&elo->dev);
+- elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+- elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
++ 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;
+
+- elo->id = serio->id.id;
++ 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;
+- }
+-
+- input_register_device(&elo->dev);
+-
+- printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys);
++ if (err)
++ goto fail;
+
++ 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
+--- a/drivers/input/touchscreen/gunze.c
++++ b/drivers/input/touchscreen/gunze.c
+@@ -48,14 +48,12 @@ MODULE_LICENSE("GPL");
+
+ #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 @@ struct gunze {
+
+ 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 irqreturn_t gunze_interrupt(struc
+
+ 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 void gunze_disconnect(struct seri
+ 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;
+- }
+-
+- input_register_device(&gunze->dev);
+-
+- printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
++ if (err)
++ goto fail;
+
++ 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
+--- 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 @@ MODULE_LICENSE("GPL");
+ #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 @@ unsigned int h3600_flite_power(struct in
+ 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 int h3600ts_pm_callback(struct pm
+ */
+ 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 void h3600ts_process_packet(struc
+ 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 @@ static int h3600ts_event(struct input_de
+ }
+ }
+ return -1;
++#endif
++ return 0;
+ }
+
+ /*
+@@ -380,14 +351,48 @@ static irqreturn_t h3600ts_interrupt(str
+ 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 @@ static int h3600ts_connect(struct serio
+ 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 @@ static void h3600ts_disconnect(struct se
+
+ 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
+--- 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 @@ static void do_softint(void *data)
+ }
+
+ 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 @@ static int __init hp680_ts_init(void)
+ 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.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.name = hp680_ts_name;
+- hp680_ts_dev.phys = hp680_ts_phys;
+- 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_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->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 = "HP Jornada touchscreen";
++ hp680_ts_dev->phys = "hp680_ts/input0";
++
++ 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 @@ static void __exit hp680_ts_exit(void)
+ 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
+--- a/drivers/input/touchscreen/mk712.c
++++ b/drivers/input/touchscreen/mk712.c
+@@ -77,7 +77,7 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touc
+ #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 irqreturn_t mk712_interrupt(int i
+ 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 @@ static irqreturn_t mk712_interrupt(int i
+ 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 @@ static irqreturn_t mk712_interrupt(int i
+ 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 @@ static void mk712_close(struct input_dev
+ 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 @@ int __init mk712_init(void)
+ (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))
+- {
+- printk(KERN_WARNING "mk712: unable to get IRQ\n");
+- release_region(mk712_io, 8);
+- return -EBUSY;
++ if (!(mk712_dev = input_allocate_device())) {
++ printk(KERN_ERR "mk712: not enough memory\n");
++ err = -ENOMEM;
++ goto fail;
+ }
+
+- input_register_device(&mk712_dev);
++ 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;
+
+- printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq);
++ 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");
++ err = -EBUSY;
++ goto fail;
++ }
++
++ 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
+--- a/drivers/input/touchscreen/mtouch.c
++++ b/drivers/input/touchscreen/mtouch.c
+@@ -51,14 +51,12 @@ MODULE_LICENSE("GPL");
+ #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 @@ struct mtouch {
+
+ 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 @@ static void mtouch_disconnect(struct ser
+ {
+ 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 void mtouch_disconnect(struct ser
+ 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;
+- }
+-
+- input_register_device(&mtouch->dev);
++ if (err)
++ goto fail;
+
+- 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
+--- 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 @@ static struct input_handle *tsdev_connec
+ 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 @@ static struct input_handle *tsdev_connec
+
+ 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 @@ static void tsdev_disconnect(struct inpu
+ 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
+--- a/drivers/isdn/capi/capi.c
++++ b/drivers/isdn/capi/capi.c
+@@ -1505,7 +1505,7 @@ static int __init capi_init(void)
+ 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
+--- 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
+--- a/drivers/isdn/hisax/hfc4s8s_l1.c
++++ b/drivers/isdn/hisax/hfc4s8s_l1.c
+@@ -1063,7 +1063,7 @@ tx_b_frame(struct hfc4s8s_btype *bch)
+ 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 @@ hfc4s8s_remove(struct pci_dev *pdev)
+ }
+
+ 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
+--- a/drivers/macintosh/adb.c
++++ b/drivers/macintosh/adb.c
+@@ -905,5 +905,5 @@ adbdev_init(void)
+ 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
+--- a/drivers/macintosh/adbhid.c
++++ b/drivers/macintosh/adbhid.c
+@@ -206,7 +206,7 @@ u8 adb_to_linux_keycodes[128] = {
+ };
+
+ struct adbhid {
+- struct input_dev input;
++ struct input_dev *input;
+ int id;
+ int default_id;
+ int original_handler_id;
+@@ -291,10 +291,10 @@ adbhid_input_keycode(int id, int keycode
+
+ 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 @@ adbhid_input_keycode(int id, int keycode
+ }
+
+ 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 @@ adbhid_mouse_input(unsigned char *data,
+ 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 @@ adbhid_buttons_input(unsigned char *data
+ return;
+ }
+
+- input_regs(&adbhid[id]->input, regs);
++ input_regs(adbhid[id]->input, regs);
+
+ switch (adbhid[id]->original_handler_id) {
+ default:
+@@ -477,19 +477,19 @@ adbhid_buttons_input(unsigned char *data
+
+ 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 @@ adbhid_buttons_input(unsigned char *data
+
+ 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 @@ adbhid_buttons_input(unsigned char *data
+ }
+ }
+ #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 @@ adbhid_buttons_input(unsigned char *data
+ }
+ }
+ #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 @@ adbhid_buttons_input(unsigned char *data
+ 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 @@ adbhid_buttons_input(unsigned char *data
+ break;
+ }
+
+- input_sync(&adbhid[id]->input);
++ input_sync(adbhid[id]->input);
+ }
+
+ static struct adb_request led_request;
+@@ -683,7 +683,7 @@ adb_message_handler(struct notifier_bloc
+ 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,164 @@ adb_message_handler(struct notifier_bloc
+ 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;
+-
+- memset(adbhid[id], 0, sizeof(struct adbhid));
+- sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
++ adbhid[id] = hid = kzalloc(sizeof(struct adbhid), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!hid || !input_dev) {
++ err = -ENOMEM;
++ goto fail;
+
+- init_input_dev(&adbhid[id]->input);
++ }
+
+- 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;
++ sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
++
++ hid->input = input_dev;
++ 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_register_device(&adbhid[id]->input);
++ input_dev->keycode = hid->keycode;
+
+- 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 +869,7 @@ adbhid_input_reregister(int id, int defa
+ 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/ans-lcd.c b/drivers/macintosh/ans-lcd.c
+--- a/drivers/macintosh/ans-lcd.c
++++ b/drivers/macintosh/ans-lcd.c
+@@ -27,7 +27,7 @@ static volatile unsigned char __iomem *a
+
+ #undef DEBUG
+
+-static void __pmac
++static void
+ anslcd_write_byte_ctrl ( unsigned char c )
+ {
+ #ifdef DEBUG
+@@ -43,14 +43,14 @@ anslcd_write_byte_ctrl ( unsigned char c
+ }
+ }
+
+-static void __pmac
++static void
+ anslcd_write_byte_data ( unsigned char c )
+ {
+ out_8(anslcd_ptr + ANSLCD_DATA_IX, c);
+ udelay(anslcd_short_delay);
+ }
+
+-static ssize_t __pmac
++static ssize_t
+ anslcd_write( struct file * file, const char __user * buf,
+ size_t count, loff_t *ppos )
+ {
+@@ -73,7 +73,7 @@ anslcd_write( struct file * file, const
+ return p - buf;
+ }
+
+-static int __pmac
++static int
+ anslcd_ioctl( struct inode * inode, struct file * file,
+ unsigned int cmd, unsigned long arg )
+ {
+@@ -115,7 +115,7 @@ anslcd_ioctl( struct inode * inode, stru
+ }
+ }
+
+-static int __pmac
++static int
+ anslcd_open( struct inode * inode, struct file * file )
+ {
+ return 0;
+diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
+--- a/drivers/macintosh/apm_emu.c
++++ b/drivers/macintosh/apm_emu.c
+@@ -430,8 +430,8 @@ static int apm_emu_get_info(char *buf, c
+ -1: Unknown
+ 8) min = minutes; sec = seconds */
+
+- unsigned short ac_line_status = 0xff;
+- unsigned short battery_status = 0xff;
++ unsigned short ac_line_status;
++ unsigned short battery_status = 0;
+ unsigned short battery_flag = 0xff;
+ int percentage = -1;
+ int time_units = -1;
+@@ -446,6 +446,7 @@ static int apm_emu_get_info(char *buf, c
+ ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0);
+ for (i=0; i<pmu_battery_count; i++) {
+ if (pmu_batteries[i].flags & PMU_BATT_PRESENT) {
++ battery_status++;
+ if (percentage < 0)
+ percentage = 0;
+ if (charge < 0)
+@@ -461,6 +462,9 @@ static int apm_emu_get_info(char *buf, c
+ charging++;
+ }
+ }
++ if (0 == battery_status)
++ ac_line_status = 1;
++ battery_status = 0xff;
+ if (real_count) {
+ if (amperage < 0) {
+ if (btype == PMU_BATT_TYPE_SMART)
+diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
+--- 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 @@ int mac_hid_mouse_emulate_buttons(int ca
+ && (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 @@ int mac_hid_mouse_emulate_buttons(int ca
+
+ 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;
++
++ 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);
+
+- init_input_dev(&emumousebtn);
++ input_register_device(emumousebtn);
+
+- 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);
+-
+- 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
+--- 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/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c
+--- a/drivers/macintosh/macio_sysfs.c
++++ b/drivers/macintosh/macio_sysfs.c
+@@ -39,6 +39,31 @@ compatible_show (struct device *dev, str
+ return length;
+ }
+
++static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct of_device *of;
++ char *compat;
++ int cplen;
++ int length;
++
++ of = &to_macio_device (dev)->ofdev;
++ compat = (char *) get_property (of->node, "compatible", &cplen);
++ if (!compat) compat = "", cplen = 1;
++ length = sprintf (buf, "of:N%sT%s", of->node->name, of->node->type);
++ buf += length;
++ while (cplen > 0) {
++ int l;
++ length += sprintf (buf, "C%s", compat);
++ buf += length;
++ l = strlen (compat) + 1;
++ compat += l;
++ cplen -= l;
++ }
++
++ return length;
++}
++
+ macio_config_of_attr (name, "%s\n");
+ macio_config_of_attr (type, "%s\n");
+
+@@ -46,5 +71,6 @@ struct device_attribute macio_dev_attrs[
+ __ATTR_RO(name),
+ __ATTR_RO(type),
+ __ATTR_RO(compatible),
++ __ATTR_RO(modalias),
+ __ATTR_NULL
+ };
+diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
+--- a/drivers/macintosh/mediabay.c
++++ b/drivers/macintosh/mediabay.c
+@@ -167,19 +167,19 @@ enum {
+ * Functions for polling content of media bay
+ */
+
+-static u8 __pmac
++static u8
+ ohare_mb_content(struct media_bay_info *bay)
+ {
+ return (MB_IN32(bay, OHARE_MBCR) >> 12) & 7;
+ }
+
+-static u8 __pmac
++static u8
+ heathrow_mb_content(struct media_bay_info *bay)
+ {
+ return (MB_IN32(bay, HEATHROW_MBCR) >> 12) & 7;
+ }
+
+-static u8 __pmac
++static u8
+ keylargo_mb_content(struct media_bay_info *bay)
+ {
+ int new_gpio;
+@@ -205,7 +205,7 @@ keylargo_mb_content(struct media_bay_inf
+ * into reset state as well
+ */
+
+-static void __pmac
++static void
+ ohare_mb_power(struct media_bay_info* bay, int on_off)
+ {
+ if (on_off) {
+@@ -224,7 +224,7 @@ ohare_mb_power(struct media_bay_info* ba
+ MB_BIC(bay, OHARE_MBCR, 0x00000F00);
+ }
+
+-static void __pmac
++static void
+ heathrow_mb_power(struct media_bay_info* bay, int on_off)
+ {
+ if (on_off) {
+@@ -243,7 +243,7 @@ heathrow_mb_power(struct media_bay_info*
+ MB_BIC(bay, HEATHROW_MBCR, 0x00000F00);
+ }
+
+-static void __pmac
++static void
+ keylargo_mb_power(struct media_bay_info* bay, int on_off)
+ {
+ if (on_off) {
+@@ -267,7 +267,7 @@ keylargo_mb_power(struct media_bay_info*
+ * enable the related busses
+ */
+
+-static int __pmac
++static int
+ ohare_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
+ {
+ switch(device_id) {
+@@ -287,7 +287,7 @@ ohare_mb_setup_bus(struct media_bay_info
+ return -ENODEV;
+ }
+
+-static int __pmac
++static int
+ heathrow_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
+ {
+ switch(device_id) {
+@@ -307,7 +307,7 @@ heathrow_mb_setup_bus(struct media_bay_i
+ return -ENODEV;
+ }
+
+-static int __pmac
++static int
+ keylargo_mb_setup_bus(struct media_bay_info* bay, u8 device_id)
+ {
+ switch(device_id) {
+@@ -330,43 +330,43 @@ keylargo_mb_setup_bus(struct media_bay_i
+ * Functions for tweaking resets
+ */
+
+-static void __pmac
++static void
+ ohare_mb_un_reset(struct media_bay_info* bay)
+ {
+ MB_BIS(bay, OHARE_FCR, OH_BAY_RESET_N);
+ }
+
+-static void __pmac keylargo_mb_init(struct media_bay_info *bay)
++static void keylargo_mb_init(struct media_bay_info *bay)
+ {
+ MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_ENABLE);
+ }
+
+-static void __pmac heathrow_mb_un_reset(struct media_bay_info* bay)
++static void heathrow_mb_un_reset(struct media_bay_info* bay)
+ {
+ MB_BIS(bay, HEATHROW_FCR, HRW_BAY_RESET_N);
+ }
+
+-static void __pmac keylargo_mb_un_reset(struct media_bay_info* bay)
++static void keylargo_mb_un_reset(struct media_bay_info* bay)
+ {
+ MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_DEV_RESET);
+ }
+
+-static void __pmac ohare_mb_un_reset_ide(struct media_bay_info* bay)
++static void ohare_mb_un_reset_ide(struct media_bay_info* bay)
+ {
+ MB_BIS(bay, OHARE_FCR, OH_IDE1_RESET_N);
+ }
+
+-static void __pmac heathrow_mb_un_reset_ide(struct media_bay_info* bay)
++static void heathrow_mb_un_reset_ide(struct media_bay_info* bay)
+ {
+ MB_BIS(bay, HEATHROW_FCR, HRW_IDE1_RESET_N);
+ }
+
+-static void __pmac keylargo_mb_un_reset_ide(struct media_bay_info* bay)
++static void keylargo_mb_un_reset_ide(struct media_bay_info* bay)
+ {
+ MB_BIS(bay, KEYLARGO_FCR1, KL1_EIDE0_RESET_N);
+ }
+
+-static inline void __pmac set_mb_power(struct media_bay_info* bay, int onoff)
++static inline void set_mb_power(struct media_bay_info* bay, int onoff)
+ {
+ /* Power up up and assert the bay reset line */
+ if (onoff) {
+@@ -382,7 +382,7 @@ static inline void __pmac set_mb_power(s
+ bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
+ }
+
+-static void __pmac poll_media_bay(struct media_bay_info* bay)
++static void poll_media_bay(struct media_bay_info* bay)
+ {
+ int id = bay->ops->content(bay);
+
+@@ -415,7 +415,7 @@ static void __pmac poll_media_bay(struct
+ }
+ }
+
+-int __pmac check_media_bay(struct device_node *which_bay, int what)
++int check_media_bay(struct device_node *which_bay, int what)
+ {
+ #ifdef CONFIG_BLK_DEV_IDE
+ int i;
+@@ -432,7 +432,7 @@ int __pmac check_media_bay(struct device
+ }
+ EXPORT_SYMBOL(check_media_bay);
+
+-int __pmac check_media_bay_by_base(unsigned long base, int what)
++int check_media_bay_by_base(unsigned long base, int what)
+ {
+ #ifdef CONFIG_BLK_DEV_IDE
+ int i;
+@@ -449,7 +449,7 @@ int __pmac check_media_bay_by_base(unsig
+ return -ENODEV;
+ }
+
+-int __pmac media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
++int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+ int irq, int index)
+ {
+ #ifdef CONFIG_BLK_DEV_IDE
+@@ -489,7 +489,7 @@ int __pmac media_bay_set_ide_infos(struc
+ return -ENODEV;
+ }
+
+-static void __pmac media_bay_step(int i)
++static void media_bay_step(int i)
+ {
+ struct media_bay_info* bay = &media_bays[i];
+
+@@ -619,7 +619,7 @@ static void __pmac media_bay_step(int i)
+ * with the IDE driver. It needs to be a thread because
+ * ide_register can't be called from interrupt context.
+ */
+-static int __pmac media_bay_task(void *x)
++static int media_bay_task(void *x)
+ {
+ int i;
+
+@@ -704,7 +704,7 @@ static int __devinit media_bay_attach(st
+
+ }
+
+-static int __pmac media_bay_suspend(struct macio_dev *mdev, pm_message_t state)
++static int media_bay_suspend(struct macio_dev *mdev, pm_message_t state)
+ {
+ struct media_bay_info *bay = macio_get_drvdata(mdev);
+
+@@ -719,7 +719,7 @@ static int __pmac media_bay_suspend(stru
+ return 0;
+ }
+
+-static int __pmac media_bay_resume(struct macio_dev *mdev)
++static int media_bay_resume(struct macio_dev *mdev)
+ {
+ struct media_bay_info *bay = macio_get_drvdata(mdev);
+
+@@ -760,7 +760,7 @@ static int __pmac media_bay_resume(struc
+
+ /* Definitions of "ops" structures.
+ */
+-static struct mb_ops ohare_mb_ops __pmacdata = {
++static struct mb_ops ohare_mb_ops = {
+ .name = "Ohare",
+ .content = ohare_mb_content,
+ .power = ohare_mb_power,
+@@ -769,7 +769,7 @@ static struct mb_ops ohare_mb_ops __pmac
+ .un_reset_ide = ohare_mb_un_reset_ide,
+ };
+
+-static struct mb_ops heathrow_mb_ops __pmacdata = {
++static struct mb_ops heathrow_mb_ops = {
+ .name = "Heathrow",
+ .content = heathrow_mb_content,
+ .power = heathrow_mb_power,
+@@ -778,7 +778,7 @@ static struct mb_ops heathrow_mb_ops __p
+ .un_reset_ide = heathrow_mb_un_reset_ide,
+ };
+
+-static struct mb_ops keylargo_mb_ops __pmacdata = {
++static struct mb_ops keylargo_mb_ops = {
+ .name = "KeyLargo",
+ .init = keylargo_mb_init,
+ .content = keylargo_mb_content,
+diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
+--- a/drivers/macintosh/smu.c
++++ b/drivers/macintosh/smu.c
+@@ -1094,7 +1094,7 @@ static int smu_release(struct inode *ino
+ }
+
+
+-static struct file_operations smu_device_fops __pmacdata = {
++static struct file_operations smu_device_fops = {
+ .llseek = no_llseek,
+ .read = smu_read,
+ .write = smu_write,
+@@ -1103,7 +1103,7 @@ static struct file_operations smu_device
+ .release = smu_release,
+ };
+
+-static struct miscdevice pmu_device __pmacdata = {
++static struct miscdevice pmu_device = {
+ MISC_DYNAMIC_MINOR, "smu", &smu_device_fops
+ };
+
+diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
+--- a/drivers/macintosh/via-cuda.c
++++ b/drivers/macintosh/via-cuda.c
+@@ -37,7 +37,6 @@ static DEFINE_SPINLOCK(cuda_lock);
+
+ #ifdef CONFIG_MAC
+ #define CUDA_IRQ IRQ_MAC_ADB
+-#define __openfirmware
+ #define eieio()
+ #else
+ #define CUDA_IRQ vias->intrs[0].line
+diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
+--- a/drivers/macintosh/via-pmu.c
++++ b/drivers/macintosh/via-pmu.c
+@@ -244,7 +244,7 @@ int pmu_wink(struct adb_request *req);
+ * - the number of response bytes which the PMU will return, or
+ * -1 if it will send a length byte.
+ */
+-static const s8 pmu_data_len[256][2] __openfirmwaredata = {
++static const s8 pmu_data_len[256][2] = {
+ /* 0 1 2 3 4 5 6 7 */
+ /*00*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+ /*08*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
+@@ -295,7 +295,7 @@ static struct backlight_controller pmu_b
+ };
+ #endif /* CONFIG_PMAC_BACKLIGHT */
+
+-int __openfirmware
++int
+ find_via_pmu(void)
+ {
+ if (via != 0)
+@@ -374,7 +374,7 @@ find_via_pmu(void)
+ }
+
+ #ifdef CONFIG_ADB
+-static int __openfirmware
++static int
+ pmu_probe(void)
+ {
+ return vias == NULL? -ENODEV: 0;
+@@ -405,7 +405,7 @@ static int __init via_pmu_start(void)
+ bright_req_2.complete = 1;
+ batt_req.complete = 1;
+
+-#ifdef CONFIG_PPC32
++#if defined(CONFIG_PPC32) && !defined(CONFIG_PPC_MERGE)
+ if (pmu_kind == PMU_KEYLARGO_BASED)
+ openpic_set_irq_priority(vias->intrs[0].line,
+ OPENPIC_PRIORITY_DEFAULT + 1);
+@@ -520,7 +520,7 @@ static int __init via_pmu_dev_init(void)
+
+ device_initcall(via_pmu_dev_init);
+
+-static int __openfirmware
++static int
+ init_pmu(void)
+ {
+ int timeout;
+@@ -588,17 +588,6 @@ pmu_get_model(void)
+ return pmu_kind;
+ }
+
+-#ifndef CONFIG_PPC64
+-static inline void wakeup_decrementer(void)
+-{
+- set_dec(tb_ticks_per_jiffy);
+- /* No currently-supported powerbook has a 601,
+- * so use get_tbl, not native
+- */
+- last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
+-}
+-#endif
+-
+ static void pmu_set_server_mode(int server_mode)
+ {
+ struct adb_request req;
+@@ -625,7 +614,7 @@ static void pmu_set_server_mode(int serv
+ /* This new version of the code for 2400/3400/3500 powerbooks
+ * is inspired from the implementation in gkrellm-pmu
+ */
+-static void __pmac
++static void
+ done_battery_state_ohare(struct adb_request* req)
+ {
+ /* format:
+@@ -713,7 +702,7 @@ done_battery_state_ohare(struct adb_requ
+ clear_bit(0, &async_req_locks);
+ }
+
+-static void __pmac
++static void
+ done_battery_state_smart(struct adb_request* req)
+ {
+ /* format:
+@@ -791,7 +780,7 @@ done_battery_state_smart(struct adb_requ
+ clear_bit(0, &async_req_locks);
+ }
+
+-static void __pmac
++static void
+ query_battery_state(void)
+ {
+ if (test_and_set_bit(0, &async_req_locks))
+@@ -804,7 +793,7 @@ query_battery_state(void)
+ 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1);
+ }
+
+-static int __pmac
++static int
+ proc_get_info(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+@@ -819,7 +808,7 @@ proc_get_info(char *page, char **start,
+ return p - page;
+ }
+
+-static int __pmac
++static int
+ proc_get_irqstats(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+@@ -846,7 +835,7 @@ proc_get_irqstats(char *page, char **sta
+ return p - page;
+ }
+
+-static int __pmac
++static int
+ proc_get_batt(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+@@ -870,7 +859,7 @@ proc_get_batt(char *page, char **start,
+ return p - page;
+ }
+
+-static int __pmac
++static int
+ proc_read_options(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+@@ -887,7 +876,7 @@ proc_read_options(char *page, char **sta
+ return p - page;
+ }
+
+-static int __pmac
++static int
+ proc_write_options(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+ {
+@@ -934,7 +923,7 @@ proc_write_options(struct file *file, co
+
+ #ifdef CONFIG_ADB
+ /* Send an ADB command */
+-static int __pmac
++static int
+ pmu_send_request(struct adb_request *req, int sync)
+ {
+ int i, ret;
+@@ -1014,7 +1003,7 @@ pmu_send_request(struct adb_request *req
+ }
+
+ /* Enable/disable autopolling */
+-static int __pmac
++static int
+ pmu_adb_autopoll(int devs)
+ {
+ struct adb_request req;
+@@ -1037,7 +1026,7 @@ pmu_adb_autopoll(int devs)
+ }
+
+ /* Reset the ADB bus */
+-static int __pmac
++static int
+ pmu_adb_reset_bus(void)
+ {
+ struct adb_request req;
+@@ -1072,7 +1061,7 @@ pmu_adb_reset_bus(void)
+ #endif /* CONFIG_ADB */
+
+ /* Construct and send a pmu request */
+-int __openfirmware
++int
+ pmu_request(struct adb_request *req, void (*done)(struct adb_request *),
+ int nbytes, ...)
+ {
+@@ -1098,7 +1087,7 @@ pmu_request(struct adb_request *req, voi
+ return pmu_queue_request(req);
+ }
+
+-int __pmac
++int
+ pmu_queue_request(struct adb_request *req)
+ {
+ unsigned long flags;
+@@ -1190,7 +1179,7 @@ pmu_done(struct adb_request *req)
+ (*done)(req);
+ }
+
+-static void __pmac
++static void
+ pmu_start(void)
+ {
+ struct adb_request *req;
+@@ -1214,7 +1203,7 @@ pmu_start(void)
+ send_byte(req->data[0]);
+ }
+
+-void __openfirmware
++void
+ pmu_poll(void)
+ {
+ if (!via)
+@@ -1224,7 +1213,7 @@ pmu_poll(void)
+ via_pmu_interrupt(0, NULL, NULL);
+ }
+
+-void __openfirmware
++void
+ pmu_poll_adb(void)
+ {
+ if (!via)
+@@ -1239,7 +1228,7 @@ pmu_poll_adb(void)
+ || req_awaiting_reply));
+ }
+
+-void __openfirmware
++void
+ pmu_wait_complete(struct adb_request *req)
+ {
+ if (!via)
+@@ -1253,7 +1242,7 @@ pmu_wait_complete(struct adb_request *re
+ * This is done to avoid spurrious shutdowns when we know we'll have
+ * interrupts switched off for a long time
+ */
+-void __openfirmware
++void
+ pmu_suspend(void)
+ {
+ unsigned long flags;
+@@ -1293,7 +1282,7 @@ pmu_suspend(void)
+ } while (1);
+ }
+
+-void __openfirmware
++void
+ pmu_resume(void)
+ {
+ unsigned long flags;
+@@ -1323,7 +1312,7 @@ pmu_resume(void)
+ }
+
+ /* Interrupt data could be the result data from an ADB cmd */
+-static void __pmac
++static void
+ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
+ {
+ unsigned char ints, pirq;
+@@ -1435,7 +1424,7 @@ next:
+ goto next;
+ }
+
+-static struct adb_request* __pmac
++static struct adb_request*
+ pmu_sr_intr(struct pt_regs *regs)
+ {
+ struct adb_request *req;
+@@ -1541,7 +1530,7 @@ pmu_sr_intr(struct pt_regs *regs)
+ return NULL;
+ }
+
+-static irqreturn_t __pmac
++static irqreturn_t
+ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
+ {
+ unsigned long flags;
+@@ -1629,7 +1618,7 @@ no_free_slot:
+ return IRQ_RETVAL(handled);
+ }
+
+-void __pmac
++void
+ pmu_unlock(void)
+ {
+ unsigned long flags;
+@@ -1642,7 +1631,7 @@ pmu_unlock(void)
+ }
+
+
+-static irqreturn_t __pmac
++static irqreturn_t
+ gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
+ {
+ unsigned long flags;
+@@ -1663,12 +1652,12 @@ gpio1_interrupt(int irq, void *arg, stru
+ }
+
+ #ifdef CONFIG_PMAC_BACKLIGHT
+-static int backlight_to_bright[] __pmacdata = {
++static int backlight_to_bright[] = {
+ 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,
+ 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e
+ };
+
+-static int __openfirmware
++static int
+ pmu_set_backlight_enable(int on, int level, void* data)
+ {
+ struct adb_request req;
+@@ -1688,7 +1677,7 @@ pmu_set_backlight_enable(int on, int lev
+ return 0;
+ }
+
+-static void __openfirmware
++static void
+ pmu_bright_complete(struct adb_request *req)
+ {
+ if (req == &bright_req_1)
+@@ -1697,7 +1686,7 @@ pmu_bright_complete(struct adb_request *
+ clear_bit(2, &async_req_locks);
+ }
+
+-static int __openfirmware
++static int
+ pmu_set_backlight_level(int level, void* data)
+ {
+ if (vias == NULL)
+@@ -1717,7 +1706,7 @@ pmu_set_backlight_level(int level, void*
+ }
+ #endif /* CONFIG_PMAC_BACKLIGHT */
+
+-void __pmac
++void
+ pmu_enable_irled(int on)
+ {
+ struct adb_request req;
+@@ -1732,7 +1721,7 @@ pmu_enable_irled(int on)
+ pmu_wait_complete(&req);
+ }
+
+-void __pmac
++void
+ pmu_restart(void)
+ {
+ struct adb_request req;
+@@ -1757,7 +1746,7 @@ pmu_restart(void)
+ ;
+ }
+
+-void __pmac
++void
+ pmu_shutdown(void)
+ {
+ struct adb_request req;
+@@ -2076,7 +2065,7 @@ pmu_unregister_sleep_notifier(struct pmu
+ }
+
+ /* Sleep is broadcast last-to-first */
+-static int __pmac
++static int
+ broadcast_sleep(int when, int fallback)
+ {
+ int ret = PBOOK_SLEEP_OK;
+@@ -2101,7 +2090,7 @@ broadcast_sleep(int when, int fallback)
+ }
+
+ /* Wake is broadcast first-to-last */
+-static int __pmac
++static int
+ broadcast_wake(void)
+ {
+ int ret = PBOOK_SLEEP_OK;
+@@ -2132,7 +2121,7 @@ static struct pci_save {
+ } *pbook_pci_saves;
+ static int pbook_npci_saves;
+
+-static void __pmac
++static void
+ pbook_alloc_pci_save(void)
+ {
+ int npci;
+@@ -2149,7 +2138,7 @@ pbook_alloc_pci_save(void)
+ pbook_npci_saves = npci;
+ }
+
+-static void __pmac
++static void
+ pbook_free_pci_save(void)
+ {
+ if (pbook_pci_saves == NULL)
+@@ -2159,7 +2148,7 @@ pbook_free_pci_save(void)
+ pbook_npci_saves = 0;
+ }
+
+-static void __pmac
++static void
+ pbook_pci_save(void)
+ {
+ struct pci_save *ps = pbook_pci_saves;
+@@ -2190,7 +2179,7 @@ pbook_pci_save(void)
+ * during boot, it will be in the pci dev list. If it's disabled at this point
+ * (and it will probably be), then you can't access it's config space.
+ */
+-static void __pmac
++static void
+ pbook_pci_restore(void)
+ {
+ u16 cmd;
+@@ -2238,7 +2227,7 @@ pbook_pci_restore(void)
+
+ #ifdef DEBUG_SLEEP
+ /* N.B. This doesn't work on the 3400 */
+-void __pmac
++void
+ pmu_blink(int n)
+ {
+ struct adb_request req;
+@@ -2277,9 +2266,9 @@ pmu_blink(int n)
+ * Put the powerbook to sleep.
+ */
+
+-static u32 save_via[8] __pmacdata;
++static u32 save_via[8];
+
+-static void __pmac
++static void
+ save_via_state(void)
+ {
+ save_via[0] = in_8(&via[ANH]);
+@@ -2291,7 +2280,7 @@ save_via_state(void)
+ save_via[6] = in_8(&via[T1CL]);
+ save_via[7] = in_8(&via[T1CH]);
+ }
+-static void __pmac
++static void
+ restore_via_state(void)
+ {
+ out_8(&via[ANH], save_via[0]);
+@@ -2307,7 +2296,7 @@ restore_via_state(void)
+ out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
+ }
+
+-static int __pmac
++static int
+ pmac_suspend_devices(void)
+ {
+ int ret;
+@@ -2397,7 +2386,7 @@ pmac_suspend_devices(void)
+ return 0;
+ }
+
+-static int __pmac
++static int
+ pmac_wakeup_devices(void)
+ {
+ mdelay(100);
+@@ -2436,7 +2425,7 @@ pmac_wakeup_devices(void)
+ #define GRACKLE_NAP (1<<4)
+ #define GRACKLE_SLEEP (1<<3)
+
+-int __pmac
++int
+ powerbook_sleep_grackle(void)
+ {
+ unsigned long save_l2cr;
+@@ -2520,7 +2509,7 @@ powerbook_sleep_grackle(void)
+ return 0;
+ }
+
+-static int __pmac
++static int
+ powerbook_sleep_Core99(void)
+ {
+ unsigned long save_l2cr;
+@@ -2620,7 +2609,7 @@ powerbook_sleep_Core99(void)
+ #define PB3400_MEM_CTRL 0xf8000000
+ #define PB3400_MEM_CTRL_SLEEP 0x70
+
+-static int __pmac
++static int
+ powerbook_sleep_3400(void)
+ {
+ int ret, i, x;
+@@ -2720,9 +2709,9 @@ struct pmu_private {
+ };
+
+ static LIST_HEAD(all_pmu_pvt);
+-static DEFINE_SPINLOCK(all_pvt_lock __pmacdata);
++static DEFINE_SPINLOCK(all_pvt_lock);
+
+-static void __pmac
++static void
+ pmu_pass_intr(unsigned char *data, int len)
+ {
+ struct pmu_private *pp;
+@@ -2751,7 +2740,7 @@ pmu_pass_intr(unsigned char *data, int l
+ spin_unlock_irqrestore(&all_pvt_lock, flags);
+ }
+
+-static int __pmac
++static int
+ pmu_open(struct inode *inode, struct file *file)
+ {
+ struct pmu_private *pp;
+@@ -2773,7 +2762,7 @@ pmu_open(struct inode *inode, struct fil
+ return 0;
+ }
+
+-static ssize_t __pmac
++static ssize_t
+ pmu_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+@@ -2825,14 +2814,14 @@ pmu_read(struct file *file, char __user
+ return ret;
+ }
+
+-static ssize_t __pmac
++static ssize_t
+ pmu_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ return 0;
+ }
+
+-static unsigned int __pmac
++static unsigned int
+ pmu_fpoll(struct file *filp, poll_table *wait)
+ {
+ struct pmu_private *pp = filp->private_data;
+@@ -2849,7 +2838,7 @@ pmu_fpoll(struct file *filp, poll_table
+ return mask;
+ }
+
+-static int __pmac
++static int
+ pmu_release(struct inode *inode, struct file *file)
+ {
+ struct pmu_private *pp = file->private_data;
+@@ -2874,8 +2863,7 @@ pmu_release(struct inode *inode, struct
+ return 0;
+ }
+
+-/* Note: removed __openfirmware here since it causes link errors */
+-static int __pmac
++static int
+ pmu_ioctl(struct inode * inode, struct file *filp,
+ u_int cmd, u_long arg)
+ {
+@@ -2957,7 +2945,7 @@ pmu_ioctl(struct inode * inode, struct f
+ return error;
+ }
+
+-static struct file_operations pmu_device_fops __pmacdata = {
++static struct file_operations pmu_device_fops = {
+ .read = pmu_read,
+ .write = pmu_write,
+ .poll = pmu_fpoll,
+@@ -2966,7 +2954,7 @@ static struct file_operations pmu_device
+ .release = pmu_release,
+ };
+
+-static struct miscdevice pmu_device __pmacdata = {
++static struct miscdevice pmu_device = {
+ PMU_MINOR, "pmu", &pmu_device_fops
+ };
+
+@@ -2982,7 +2970,7 @@ device_initcall(pmu_device_init);
+
+
+ #ifdef DEBUG_SLEEP
+-static inline void __pmac
++static inline void
+ polled_handshake(volatile unsigned char __iomem *via)
+ {
+ via[B] &= ~TREQ; eieio();
+@@ -2993,7 +2981,7 @@ polled_handshake(volatile unsigned char
+ ;
+ }
+
+-static inline void __pmac
++static inline void
+ polled_send_byte(volatile unsigned char __iomem *via, int x)
+ {
+ via[ACR] |= SR_OUT | SR_EXT; eieio();
+@@ -3001,7 +2989,7 @@ polled_send_byte(volatile unsigned char
+ polled_handshake(via);
+ }
+
+-static inline int __pmac
++static inline int
+ polled_recv_byte(volatile unsigned char __iomem *via)
+ {
+ int x;
+@@ -3013,7 +3001,7 @@ polled_recv_byte(volatile unsigned char
+ return x;
+ }
+
+-int __pmac
++int
+ pmu_polled_request(struct adb_request *req)
+ {
+ unsigned long flags;
+diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
+--- a/drivers/macintosh/via-pmu68k.c
++++ b/drivers/macintosh/via-pmu68k.c
+@@ -835,7 +835,7 @@ static struct pci_save {
+ } *pbook_pci_saves;
+ static int n_pbook_pci_saves;
+
+-static inline void __openfirmware
++static inline void
+ pbook_pci_save(void)
+ {
+ int npci;
+@@ -863,7 +863,7 @@ pbook_pci_save(void)
+ }
+ }
+
+-static inline void __openfirmware
++static inline void
+ pbook_pci_restore(void)
+ {
+ u16 cmd;
+@@ -902,7 +902,7 @@ pbook_pci_restore(void)
+ #define IRQ_ENABLE ((unsigned int *)0xf3000024)
+ #define MEM_CTRL ((unsigned int *)0xf8000070)
+
+-int __openfirmware powerbook_sleep(void)
++int powerbook_sleep(void)
+ {
+ int ret, i, x;
+ static int save_backlight;
+@@ -1001,25 +1001,24 @@ int __openfirmware powerbook_sleep(void)
+ /*
+ * Support for /dev/pmu device
+ */
+-static int __openfirmware pmu_open(struct inode *inode, struct file *file)
++static int pmu_open(struct inode *inode, struct file *file)
+ {
+ return 0;
+ }
+
+-static ssize_t __openfirmware pmu_read(struct file *file, char *buf,
++static ssize_t pmu_read(struct file *file, char *buf,
+ size_t count, loff_t *ppos)
+ {
+ return 0;
+ }
+
+-static ssize_t __openfirmware pmu_write(struct file *file, const char *buf,
++static ssize_t pmu_write(struct file *file, const char *buf,
+ size_t count, loff_t *ppos)
+ {
+ return 0;
+ }
+
+-/* Note: removed __openfirmware here since it causes link errors */
+-static int /*__openfirmware*/ pmu_ioctl(struct inode * inode, struct file *filp,
++static int pmu_ioctl(struct inode * inode, struct file *filp,
+ u_int cmd, u_long arg)
+ {
+ int error;
+diff --git a/drivers/mca/mca-device.c b/drivers/mca/mca-device.c
+--- 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
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -91,7 +91,7 @@ int bitmap_active(struct bitmap *bitmap)
+
+ #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
+--- 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 @@ static int crypt_iv_essiv_ctr(struct cry
+ 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 void crypt_iv_essiv_dtr(struct cr
+
+ 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 @@ crypt_alloc_buffer(struct crypt_config *
+ {
+ 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
+--- 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 @@ void ir_input_init(struct input_dev *dev
+ 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
+--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
++++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
+@@ -137,7 +137,8 @@ struct cinergyt2 {
+ 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 @@ static struct dvb_device cinergyt2_fe_te
+ };
+
+ #ifdef ENABLE_RC
++
+ static void cinergyt2_query_rc (void *data)
+ {
+ struct cinergyt2 *cinergyt2 = data;
+@@ -703,7 +705,7 @@ static void cinergyt2_query_rc (void *da
+ /* 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 @@ static void cinergyt2_query_rc (void *da
+ /* 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 @@ static void cinergyt2_query_rc (void *da
+ 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 @@ out:
+
+ 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 @@ static int cinergyt2_probe (struct usb_i
+ {
+ 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 @@ static int cinergyt2_probe (struct usb_i
+ &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";
+-
+- 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;
++ err = cinergyt2_register_rc(cinergyt2);
++ if (err)
++ goto bailout;
+
+- 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 @@ static void cinergyt2_disconnect (struct
+ 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 @@ static int cinergyt2_suspend (struct usb
+
+ 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 @@ static int cinergyt2_resume (struct usb_
+ 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
+--- 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
+--- a/drivers/media/dvb/dvb-core/dvbdev.c
++++ b/drivers/media/dvb/dvb-core/dvbdev.c
+@@ -235,7 +235,7 @@ int dvb_register_device(struct dvb_adapt
+ 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
+--- a/drivers/media/dvb/dvb-usb/dtt200u.c
++++ b/drivers/media/dvb/dvb-usb/dtt200u.c
+@@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u
+ .cold_ids = { &dtt200u_usb_table[0], NULL },
+ .warm_ids = { &dtt200u_usb_table[1], NULL },
+ },
+- { 0 },
++ { NULL },
+ }
+ };
+
+@@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_
+ .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
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+@@ -39,9 +39,9 @@ static void dvb_usb_read_remote_control(
+ 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 @@ static void dvb_usb_read_remote_control(
+ 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 @@ static void dvb_usb_read_remote_control(
+ 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 @@ static void dvb_usb_read_remote_control(
+ 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 @@ schedule:
+ 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 @@ int dvb_usb_remote_init(struct dvb_usb_d
+ 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 @@ int dvb_usb_remote_exit(struct dvb_usb_d
+ 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
+--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
+@@ -300,7 +300,8 @@ struct dvb_usb_device {
+ 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
+--- a/drivers/media/dvb/dvb-usb/vp7045.c
++++ b/drivers/media/dvb/dvb-usb/vp7045.c
+@@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_
+ .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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- a/drivers/media/dvb/frontends/s5h1420.c
++++ b/drivers/media/dvb/frontends/s5h1420.c
+@@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridg
+ #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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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 u16 key_map [256] = {
+
+ 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 @@ static void av7110_emit_key(unsigned lon
+ 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 @@ static void input_register_keys(void)
+ {
+ 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 @@ int __init av7110_ir_init(struct av7110
+ 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 @@ void __exit av7110_ir_exit(struct av7110
+ 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
+--- 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_debounce(unsigned
+ 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 void msp430_ir_interrupt(unsigned
+ 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 int msp430_ir_init(struct budget_
+ 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
+--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
++++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+@@ -152,7 +152,8 @@ struct ttusb_dec {
+ 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 @@ static void ttusb_dec_handle_irq( struct
+ * 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 @@ static void ttusb_dec_init_tasklet(struc
+ (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;
++
++ 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;
+
+- for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
+- set_bit(rc_keys[i], dec->rc_input_dev.keybit);
++ for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
++ set_bit(rc_keys[i], input_dev->keybit);
+
+- input_register_device(&dec->rc_input_dev);
++ input_register_device(input_dev);
+
+- if(usb_submit_urb(dec->irq_urb,GFP_KERNEL)) {
++ 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 @@ static void ttusb_dec_exit_rc(struct ttu
+ * 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 @@ static void ttusb_dec_exit_rc(struct ttu
+ 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 @@ static int ttusb_dec_probe(struct usb_in
+
+ 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
+--- 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
+--- a/drivers/media/video/bttvp.h
++++ b/drivers/media/video/bttvp.h
+@@ -240,7 +240,7 @@ struct bttv_pll_info {
+
+ /* 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
+--- a/drivers/media/video/cx88/cx88-input.c
++++ b/drivers/media/video/cx88/cx88-input.c
+@@ -260,7 +260,7 @@ static IR_KEYTAB_TYPE ir_codes_cinergy_1
+
+ 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 @@ static void cx88_ir_handle_key(struct cx
+ 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 @@ static void cx88_ir_work(void *data)
+ 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 @@ int cx88_ir_init(struct cx88_core *core,
+
+ if (NULL == ir_codes) {
+ kfree(ir);
++ input_free_device(input_dev);
+ return -ENODEV;
+ }
+
+@@ -433,19 +440,19 @@ int cx88_ir_init(struct cx88_core *core,
+ 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 @@ int cx88_ir_init(struct cx88_core *core,
+ }
+
+ /* 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 @@ int cx88_ir_fini(struct cx88_core *core)
+ flush_scheduled_work();
+ }
+
+- input_unregister_device(&ir->input);
++ input_unregister_device(ir->input);
+ kfree(ir);
+
+ /* done */
+@@ -515,7 +521,7 @@ void cx88_ir_irq(struct cx88_core *core)
+ 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 @@ void cx88_ir_irq(struct cx88_core *core)
+
+ 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 @@ void cx88_ir_irq(struct cx88_core *core)
+ 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
+--- 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 @@ MODULE_LICENSE("GPL");
+ #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 @@ out_free_client:
+ 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
+--- a/drivers/media/video/ir-kbd-gpio.c
++++ b/drivers/media/video/ir-kbd-gpio.c
+@@ -158,7 +158,7 @@ static IR_KEYTAB_TYPE ir_codes_apac_view
+
+ 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 @@ static void ir_handle_key(struct IR *ir)
+ 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 @@ static int ir_probe(struct device *dev)
+ {
+ 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 @@ static int ir_probe(struct device *dev)
+ }
+ if (NULL == ir_codes) {
+ kfree(ir);
++ input_free_device(input_dev);
+ return -ENODEV;
+ }
+
+@@ -341,19 +346,19 @@ static int ir_probe(struct device *dev)
+ 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 @@ static int ir_probe(struct device *dev)
+ }
+
+ /* 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 @@ static int ir_remove(struct device *dev)
+ 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
+--- a/drivers/media/video/ir-kbd-i2c.c
++++ b/drivers/media/video/ir-kbd-i2c.c
+@@ -121,10 +121,9 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[
+
+ };
+
+-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 @@ static void ir_key_poll(struct IR *ir)
+ }
+
+ 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 @@ static int ir_attach(struct i2c_adapter
+ 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 @@ static int ir_attach(struct i2c_adapter
+ 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 @@ static int ir_detach(struct i2c_client *
+ 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
+--- a/drivers/media/video/msp3400.c
++++ b/drivers/media/video/msp3400.c
+@@ -1420,8 +1420,8 @@ static int msp_detach(struct i2c_client
+ 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 @@ static int msp_command(struct i2c_client
+ 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 @@ static int msp_suspend(struct device * d
+ 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
+--- a/drivers/media/video/saa7134/saa7134-input.c
++++ b/drivers/media/video/saa7134/saa7134-input.c
+@@ -425,9 +425,9 @@ static int build_key(struct saa7134_dev
+
+ 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 @@ static void saa7134_input_timer(unsigned
+ 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 @@ int saa7134_input_init1(struct saa7134_d
+ 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 @@ int saa7134_input_init1(struct saa7134_d
+ 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 @@ int saa7134_input_init1(struct saa7134_d
+ 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 @@ void saa7134_input_fini(struct saa7134_d
+ 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
+--- a/drivers/media/video/saa7134/saa7134.h
++++ b/drivers/media/video/saa7134/saa7134.h
+@@ -351,7 +351,7 @@ struct saa7134_oss {
+
+ /* 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
+--- 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_VERSION(SAA7191_MODULE_VERSION);
+ MODULE_AUTHOR("Mikael Nousiainen <tmnousia at 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 @@ out_free_client:
+ 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 @@ static int saa7191_command(struct i2c_cl
+
+ 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 @@ static int saa7191_command(struct i2c_cl
+ 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
+--- a/drivers/media/video/tda9887.c
++++ b/drivers/media/video/tda9887.c
+@@ -784,13 +784,13 @@ tda9887_command(struct i2c_client *clien
+ 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
+--- a/drivers/media/video/tuner-core.c
++++ b/drivers/media/video/tuner-core.c
+@@ -697,7 +697,7 @@ static int tuner_command(struct i2c_clie
+ 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 @@ static int tuner_suspend(struct device *
+ 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
+--- 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
+--- a/drivers/message/i2o/core.h
++++ b/drivers/message/i2o/core.h
+@@ -36,9 +36,6 @@ extern void __exit i2o_pci_exit(void);
+ 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
+--- a/drivers/message/i2o/debug.c
++++ b/drivers/message/i2o/debug.c
+@@ -90,7 +90,7 @@ static void i2o_report_fail_status(u8 re
+ };
+
+ 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
+--- 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 @@ static inline int i2o_device_issue_claim
+ 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 @@ int i2o_device_claim(struct i2o_device *
+ up(&dev->lock);
+
+ return rc;
+-};
++}
+
+ /**
+ * i2o_device_claim_release - release a device that the OSM is using
+@@ -119,7 +121,8 @@ int i2o_device_claim_release(struct i2o_
+ up(&dev->lock);
+
+ return rc;
+-};
++}
++
+
+ /**
+ * i2o_device_release - release the memory for a I2O device
+@@ -135,39 +138,47 @@ static void i2o_device_release(struct de
+ 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 @@ static struct i2o_device *i2o_device_all
+
+ 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 @@ static struct i2o_device *i2o_device_add
+ }
+
+ 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 @@ static struct i2o_device *i2o_device_add
+ 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 @@ int i2o_device_parse_lct(struct i2o_cont
+ 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 @@ int i2o_parm_field_get(struct i2o_device
+ }
+
+ /*
+- * 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 @@ int i2o_parm_table_get(struct i2o_device
+ 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
+--- 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 @@ static int i2o_bus_match(struct device *
+ };
+
+ /* 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
+--- 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
+--- 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 @@ void i2o_iop_remove(struct i2o_controlle
+ 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 @@ static void i2o_iop_release(struct devic
+ };
+
+ /* 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 @@ struct i2o_controller *i2o_iop_alloc(voi
+ 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 @@ int i2o_iop_add(struct i2o_controller *c
+ 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 @@ int i2o_iop_add(struct i2o_controller *c
+ return 0;
+
+ class_del:
+- class_device_del(&c->classdev);
++ class_device_unregister(c->classdev);
+
+ device_del:
+ device_del(&c->device);
+@@ -1246,13 +1244,10 @@ static int __init i2o_iop_init(void)
+
+ 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 @@ static int __init i2o_iop_init(void)
+ 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 @@ static void __exit i2o_iop_exit(void)
+ 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
+--- a/drivers/mfd/mcp-sa11x0.c
++++ b/drivers/mfd/mcp-sa11x0.c
+@@ -18,7 +18,7 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/slab.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/dma.h>
+ #include <asm/hardware.h>
+@@ -219,26 +219,24 @@ static int mcp_sa11x0_remove(struct devi
+ 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
+--- 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 int adcsync;
+
+ 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 void ucb1x00_ts_mode_int(s
+ */
+ 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_re
+ */
+ 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_re
+ */
+ 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 @@ static inline unsigned int ucb1x00_ts_re
+ 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 @@ static int ucb1x00_thread(void *_ts)
+
+ 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 @@ static int ucb1x00_thread(void *_ts)
+ 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 @@ static int ucb1x00_ts_add(struct ucb1x00
+ {
+ 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;
+-
+- __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);
++ 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);
+
+- input_register_device(&ts->idev);
++ input_register_device(ts->idev);
+
+ dev->priv = ts;
+
+@@ -370,7 +406,8 @@ static int ucb1x00_ts_add(struct ucb1x00
+ 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/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
+--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
++++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
+@@ -21,7 +21,7 @@
+ #include <linux/miscdevice.h>
+ #include <linux/pci.h>
+ #include <linux/proc_fs.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <asm/uaccess.h>
+ #include <linux/hdpu_features.h>
+
+diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
+--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
++++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
+@@ -21,7 +21,7 @@
+ #include <linux/hdpu_features.h>
+ #include <linux/pci.h>
+
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ static int hdpu_nexus_probe(struct device *ddev);
+ static int hdpu_nexus_remove(struct device *ddev);
+diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
+--- a/drivers/mmc/Kconfig
++++ b/drivers/mmc/Kconfig
+@@ -60,4 +60,13 @@ config MMC_WBSD
+
+ 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
+--- a/drivers/mmc/Makefile
++++ b/drivers/mmc/Makefile
+@@ -18,5 +18,6 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
+ 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
+--- /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
+--- /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
+--- a/drivers/mmc/mmc_block.c
++++ b/drivers/mmc/mmc_block.c
+@@ -85,6 +85,12 @@ static void mmc_blk_put(struct mmc_blk_d
+ 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 @@ static int mmc_blk_open(struct inode *in
+ 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 @@ static int mmc_blk_probe(struct mmc_card
+ 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
+--- 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
+--- a/drivers/mmc/pxamci.c
++++ b/drivers/mmc/pxamci.c
+@@ -20,7 +20,7 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+ #include <linux/dma-mapping.h>
+@@ -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 @@ static int pxamci_remove(struct device *
+ }
+
+ #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
+--- a/drivers/mmc/wbsd.c
++++ b/drivers/mmc/wbsd.c
+@@ -26,7 +26,7 @@
+ #include <linux/moduleparam.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/delay.h>
+@@ -1033,13 +1033,16 @@ static void wbsd_set_ios(struct mmc_host
+ }
+ 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 @@ static int __devinit wbsd_scan(struct wb
+ {
+ 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 @@ static int __devinit wbsd_scan(struct wb
+ 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 @@ static int __devinit wbsd_scan(struct wb
+ 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 @@ static void __devexit wbsd_release_resou
+ * 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 @@ static void __devinit wbsd_chip_config(s
+ */
+ 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 @@ static int __devinit wbsd_chip_validate(
+
+ dma = wbsd_read_config(host, WBSD_CONF_DRQ);
+
++ wbsd_lock_config(host);
++
+ /*
+ * Validate against given configuration.
+ */
+@@ -1771,6 +1785,20 @@ static int __devinit wbsd_chip_validate(
+ 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 @@ static int __devinit wbsd_init(struct de
+ */
+ #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 @@ static void __devexit wbsd_shutdown(stru
+
+ 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 @@ static void __devexit wbsd_pnp_remove(st
+ */
+
+ #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
+--- 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
+--- 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
+--- 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
+--- a/drivers/mtd/maps/bast-flash.c
++++ b/drivers/mtd/maps/bast-flash.c
+@@ -33,7 +33,8 @@
+ #include <linux/string.h>
+ #include <linux/ioport.h>
+ #include <linux/device.h>
+-
++#include <linux/slab.h>
++#include <linux/platform_device.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/map.h>
+ #include <linux/mtd/partitions.h>
+diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
+--- a/drivers/mtd/maps/integrator-flash.c
++++ b/drivers/mtd/maps/integrator-flash.c
+@@ -32,7 +32,7 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/init.h>
+
+ #include <linux/mtd/mtd.h>
+diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
+--- a/drivers/mtd/maps/ixp2000.c
++++ b/drivers/mtd/maps/ixp2000.c
+@@ -22,11 +22,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/platform_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
+--- a/drivers/mtd/maps/ixp4xx.c
++++ b/drivers/mtd/maps/ixp4xx.c
+@@ -20,11 +20,15 @@
+ #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/platform_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
+--- 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
+--- 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
+--- 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
+--- a/drivers/mtd/maps/omap_nor.c
++++ b/drivers/mtd/maps/omap_nor.c
+@@ -30,12 +30,14 @@
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #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
+--- 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
+--- a/drivers/mtd/maps/plat-ram.c
++++ b/drivers/mtd/maps/plat-ram.c
+@@ -30,6 +30,8 @@
+ #include <linux/string.h>
+ #include <linux/ioport.h>
+ #include <linux/device.h>
++#include <linux/slab.h>
++#include <linux/platform_device.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
+--- a/drivers/mtd/maps/sa1100-flash.c
++++ b/drivers/mtd/maps/sa1100-flash.c
+@@ -13,7 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/slab.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/err.h>
+
+ #include <linux/mtd/mtd.h>
+@@ -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 @@ struct sa_subdev_info {
+ 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 @@ static int sa1100_probe_subdev(struct sa
+ 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 @@ static int sa1100_probe_subdev(struct sa
+ * 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 @@ static int sa1100_probe_subdev(struct sa
+ 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 @@ static void sa1100_destroy(struct sa_inf
+ 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 @@ sa1100_setup_mtd(struct platform_device
+
+ 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 @@ sa1100_setup_mtd(struct platform_device
+ 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 @@ sa1100_setup_mtd(struct platform_device
+ * 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 @@ sa1100_setup_mtd(struct platform_device
+ 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 @@ sa1100_setup_mtd(struct platform_device
+ return info;
+
+ err:
+- sa1100_destroy(info);
++ sa1100_destroy(info, plat);
+ out:
+ return ERR_PTR(ret);
+ }
+@@ -345,16 +360,16 @@ static const char *part_probes[] = { "cm
+ 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 @@ static int __init sa1100_mtd_probe(struc
+ } 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 @@ static int __init sa1100_mtd_probe(struc
+ 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 __init sa1100_mtd_probe(struc
+ 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 @@ static struct device_driver sa1100_mtd_d
+ .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
+--- 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
+--- 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
+--- 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 @@ static void mtd_notify_add(struct mtd_in
+ 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
+--- 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
+--- a/drivers/mtd/nand/s3c2410.c
++++ b/drivers/mtd/nand/s3c2410.c
+@@ -48,9 +48,10 @@
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_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
+--- a/drivers/net/8139cp.c
++++ b/drivers/net/8139cp.c
+@@ -1027,8 +1027,7 @@ static void cp_reset_hw (struct cp_priva
+ 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 @@ static struct ethtool_ops cp_ethtool_ops
+ .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 @@ static int cp_init_one (struct pci_dev *
+ 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
+--- a/drivers/net/8139too.c
++++ b/drivers/net/8139too.c
+@@ -552,7 +552,8 @@ const static struct {
+
+ { "RTL-8100B/8139D",
+ HW_REVID(1, 1, 1, 0, 1, 0, 1),
+- HasLWake,
++ HasHltClk /* XXX undocumented? */
++ | HasLWake,
+ },
+
+ { "RTL-8101",
+@@ -970,6 +971,7 @@ static int __devinit rtl8139_init_one (s
+ 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 @@ static struct ethtool_ops rtl8139_ethtoo
+ .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
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -475,6 +475,14 @@ config SGI_IOC3_ETH_HW_TX_CSUM
+ 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 @@ config IBMVETH
+ 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_POLL_WEIGHT
++ int "MAL NAPI polling weight"
++ depends on IBM_EMAC
++ default "32"
+
+-config IBM_EMAC_FGAP
+- int "Frame gap"
++config IBM_EMAC_RX_COPY_THRESHOLD
++ int "RX skb copy threshold (bytes)"
+ depends on IBM_EMAC
+- default "8"
++ default "256"
+
+-config IBM_EMAC_SKBRES
+- int "Skb reserve amount"
++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 FORCEDETH
+
+ 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 @@ config NE_H8300
+ 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 SPIDER_NET
+ 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 @@ config S2IO
+ 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 @@ config ISERIES_VETH
+ 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
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -13,7 +13,7 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
+ 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_SKFP) += skfp/
+ 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_EQUALIZER) += eql.o
+ 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_IRDA) += irda/
+ obj-$(CONFIG_ETRAX_ETHERNET) += cris/
+
+ obj-$(CONFIG_NETCONSOLE) += netconsole.o
++
++obj-$(CONFIG_FS_ENET) += fs_enet/
++
+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
+--- a/drivers/net/arm/am79c961a.c
++++ b/drivers/net/arm/am79c961a.c
+@@ -26,10 +26,11 @@
+ #include <linux/init.h>
+ #include <linux/crc32.h>
+ #include <linux/bitops.h>
++#include <linux/platform_device.h>
+
+-#include <asm/system.h>
+-#include <asm/irq.h>
++#include <asm/hardware.h>
+ #include <asm/io.h>
++#include <asm/system.h>
+
+ #define TX_BUFFERS 15
+ #define RX_BUFFERS 25
+@@ -279,10 +280,13 @@ static void am79c961_timer(unsigned long
+ lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
+ carrier = netif_carrier_ok(dev);
+
+- if (lnkstat && !carrier)
++ if (lnkstat && !carrier) {
+ netif_carrier_on(dev);
+- else if (!lnkstat && carrier)
++ printk("%s: link up\n", dev->name);
++ } else if (!lnkstat && carrier) {
+ netif_carrier_off(dev);
++ printk("%s: link down\n", dev->name);
++ }
+
+ mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
+ }
+@@ -664,17 +668,25 @@ static void __init am79c961_banner(void)
+ printk(KERN_INFO "%s", version);
+ }
+
+-static int __init am79c961_init(void)
++static int __init am79c961_probe(struct device *_dev)
+ {
++ struct platform_device *pdev = to_platform_device(_dev);
++ struct resource *res;
+ struct net_device *dev;
+ struct dev_priv *priv;
+ int i, ret;
+
++ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ if (!res)
++ return -ENODEV;
++
+ dev = alloc_etherdev(sizeof(struct dev_priv));
+ ret = -ENOMEM;
+ if (!dev)
+ goto out;
+
++ SET_NETDEV_DEV(dev, &pdev->dev);
++
+ priv = netdev_priv(dev);
+
+ /*
+@@ -682,8 +694,8 @@ static int __init am79c961_init(void)
+ * The PNP initialisation should have been
+ * done by the ether bootp loader.
+ */
+- dev->base_addr = 0x220;
+- dev->irq = IRQ_EBSA110_ETHERNET;
++ dev->base_addr = res->start;
++ dev->irq = platform_get_irq(pdev, 0);
+
+ ret = -ENODEV;
+ if (!request_region(dev->base_addr, 0x18, dev->name))
+@@ -704,11 +716,11 @@ static int __init am79c961_init(void)
+ inb(dev->base_addr + 4) != 0x2b)
+ goto release;
+
+- am79c961_banner();
+-
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
+
++ am79c961_banner();
++
+ spin_lock_init(&priv->chip_lock);
+ init_timer(&priv->timer);
+ priv->timer.data = (unsigned long)dev;
+@@ -731,6 +743,7 @@ static int __init am79c961_init(void)
+ if (ret == 0) {
+ printk(KERN_INFO "%s: ether address ", dev->name);
+
++ /* Retrive and print the ethernet address. */
+ for (i = 0; i < 6; i++)
+ printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
+
+@@ -745,4 +758,15 @@ out:
+ return ret;
+ }
+
++static struct device_driver am79c961_driver = {
++ .name = "am79c961",
++ .bus = &platform_bus_type,
++ .probe = am79c961_probe,
++};
++
++static int __init am79c961_init(void)
++{
++ return driver_register(&am79c961_driver);
++}
++
+ __initcall(am79c961_init);
+diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/arm/am79c961a.h
+--- a/drivers/net/arm/am79c961a.h
++++ b/drivers/net/arm/am79c961a.h
+@@ -143,6 +143,4 @@ struct dev_priv {
+ struct timer_list timer;
+ };
+
+-extern int am79c961_probe (struct net_device *dev);
+-
+ #endif
+diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
+--- a/drivers/net/au1000_eth.c
++++ b/drivers/net/au1000_eth.c
+@@ -151,13 +151,6 @@ struct au1000_private *au_macs[NUM_ETH_I
+ 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 @@ static struct mii_chip_info {
+ {"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 @@ found:
+ #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 @@ au1000_probe(u32 ioaddr, int irq, int po
+ 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 @@ err_out:
+ /* 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 @@ static void __exit au1000_cleanup_module
+ 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
+--- 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 int b44_poll(struct net_device *d
+ 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 @@ static int b44_alloc_rx_skb(struct b44 *
+ 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 @@ static void b44_recycle_rx(struct b44 *b
+ 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 @@ static void b44_recycle_rx(struct b44 *b
+
+ 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 @@ static int b44_start_xmit(struct sk_buff
+ 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 @@ static void b44_init_rings(struct b44 *b
+ 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_init_rings(struct b44 *b
+ */
+ 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 @@ static int b44_alloc_consistent(struct b
+
+ 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 @@ static int b44_get_settings(struct net_d
+
+ 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 @@ static struct ethtool_ops b44_ethtool_op
+ .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 @@ static int __devinit b44_get_invariants(
+ 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 @@ static int b44_suspend(struct pci_dev *p
+ b44_free_rings(bp);
+
+ spin_unlock_irq(&bp->lock);
++
++ free_irq(dev->irq, dev);
+ pci_disable_device(pdev);
+ return 0;
+ }
+@@ -1946,6 +2059,9 @@ static int b44_resume(struct pci_dev *pd
+ 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 struct pci_driver b44_driver = {
+
+ 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
+--- a/drivers/net/b44.h
++++ b/drivers/net/b44.h
+@@ -400,6 +400,8 @@ struct b44 {
+ #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
+--- a/drivers/net/bmac.c
++++ b/drivers/net/bmac.c
+@@ -1658,6 +1658,7 @@ static struct of_device_id bmac_match[]
+ },
+ {},
+ };
++MODULE_DEVICE_TABLE (of, bmac_match);
+
+ static struct macio_driver bmac_driver =
+ {
+@@ -1689,10 +1690,8 @@ static void __exit bmac_exit(void)
+ {
+ 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
+--- a/drivers/net/bnx2.c
++++ b/drivers/net/bnx2.c
+@@ -314,20 +314,16 @@ bnx2_free_mem(struct bnx2 *bp)
+ 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
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -4241,6 +4241,43 @@ out:
+ 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 @@ static int bond_xmit_activebackup(struct
+ 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
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -489,7 +489,7 @@ static int cas_page_free(struct cas *cp,
+ /* 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 @@ static void cas_spare_free(struct cas *c
+ }
+
+ /* 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
+--- a/drivers/net/cs89x0.c
++++ b/drivers/net/cs89x0.c
+@@ -182,6 +182,10 @@ static unsigned int cs8900_irq_map[] = {
+ #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 @@ cs89x0_probe1(struct net_device *dev, in
+ 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 @@ cs89x0_probe1(struct net_device *dev, in
+ 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 @@ net_open(struct net_device *dev)
+ 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
+--- 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
+--- 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 @@ MODULE_LICENSE("GPL");
+ #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 @@ struct lance_init_block {
+ /*
+ * 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 @@ out:
+ 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 @@ static int __init dec_lance_init(const i
+ 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 @@ static int __init dec_lance_init(const i
+ 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 @@ static int __init dec_lance_init(const i
+ /* 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 @@ static int __init dec_lance_init(const i
+
+ 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/depca.c b/drivers/net/depca.c
+--- a/drivers/net/depca.c
++++ b/drivers/net/depca.c
+@@ -254,7 +254,7 @@
+ #include <linux/unistd.h>
+ #include <linux/ctype.h>
+ #include <linux/moduleparam.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/bitops.h>
+
+ #include <asm/uaccess.h>
+diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
+--- a/drivers/net/dm9000.c
++++ b/drivers/net/dm9000.c
+@@ -66,6 +66,7 @@
+ #include <linux/mii.h>
+ #include <linux/dm9000.h>
+ #include <linux/delay.h>
++#include <linux/platform_device.h>
+
+ #include <asm/delay.h>
+ #include <asm/irq.h>
+@@ -1140,11 +1141,11 @@ dm9000_phy_write(struct net_device *dev,
+ }
+
+ 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 +1155,12 @@ dm9000_drv_suspend(struct device *dev, p
+ }
+
+ 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
+--- a/drivers/net/e100.c
++++ b/drivers/net/e100.c
+@@ -2201,6 +2201,7 @@ static struct ethtool_ops e100_ethtool_o
+ .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 @@ static int __devinit e100_probe(struct p
+ 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
+--- 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 @@ struct e1000_buffer {
+ 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_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_desc_ring {
++struct e1000_rx_ring {
+ /* pointer to the descriptor ring memory */
+ void *desc;
+ /* physical address of the descriptor ring */
+@@ -186,6 +213,10 @@ struct e1000_desc_ring {
+ /* 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 @@ struct e1000_adapter {
+ 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 @@ struct e1000_adapter {
+
+ /* 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_adapter {
+ 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
+--- a/drivers/net/e1000/e1000_ethtool.c
++++ b/drivers/net/e1000/e1000_ethtool.c
+@@ -39,10 +39,10 @@ extern int e1000_up(struct e1000_adapter
+ 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 @@ static const struct e1000_stats e1000_gs
+ { "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 @@ e1000_set_eeprom(struct net_device *netd
+ 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 @@ e1000_get_ringparam(struct net_device *n
+ {
+ 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 @@ e1000_set_ringparam(struct net_device *n
+ {
+ 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_set_ringparam(struct net_device *n
+ 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 @@ e1000_set_ringparam(struct net_device *n
+ 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 @@ e1000_set_ringparam(struct net_device *n
+
+ 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 @@ e1000_reg_test(struct e1000_adapter *ada
+ * 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 @@ e1000_intr_test(struct e1000_adapter *ad
+ 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 @@ e1000_free_desc_rings(struct e1000_adapt
+ 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 @@ e1000_set_phy_loopback(struct e1000_adap
+ 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 @@ e1000_check_lbtest_frame(struct sk_buff
+ 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 @@ e1000_diag_test(struct net_device *netde
+ data[2] = 0;
+ data[3] = 0;
+ }
++ msleep_interruptible(4 * 1000);
+ }
+
+ static void
+@@ -1625,7 +1660,7 @@ e1000_phys_id(struct net_device *netdev,
+ 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 @@ struct ethtool_ops e1000_ethtool_ops = {
+ .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
+--- a/drivers/net/e1000/e1000_hw.c
++++ b/drivers/net/e1000/e1000_hw.c
+@@ -83,14 +83,14 @@ uint16_t e1000_igp_cable_length_table[IG
+
+ 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 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ 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 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ 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 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ }
+
+ switch(hw->mac_type) {
++ case e1000_82571:
++ case e1000_82572:
+ case e1000_82573:
+ hw->eeprom_semaphore_present = TRUE;
+ /* fall through */
+@@ -351,6 +363,8 @@ e1000_set_media_type(struct e1000_hw *hw
+ 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_reset_hw(struct e1000_hw *hw)
+ 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 @@ e1000_init_hw(struct e1000_hw *hw)
+ 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_init_hw(struct e1000_hw *hw)
+ 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 @@ e1000_setup_fiber_serdes_link(struct e10
+
+ 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 @@ e1000_phy_reset(struct e1000_hw *hw)
+
+ 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 @@ e1000_detect_gig_phy(struct e1000_hw *hw
+
+ 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 @@ e1000_init_eeprom_params(struct e1000_hw
+ 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 @@ e1000_acquire_eeprom(struct e1000_hw *hw
+ 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 @@ e1000_write_eeprom(struct e1000_hw *hw,
+ 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 @@ e1000_read_mac_addr(struct e1000_hw * hw
+ 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_init_rx_addrs(struct e1000_hw *hw)
+ 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 @@ e1000_mc_addr_list_update(struct e1000_h
+ /* 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 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw
+ temp = E1000_READ_REG(hw, ICTXQEC);
+ temp = E1000_READ_REG(hw, ICTXQMTC);
+ temp = E1000_READ_REG(hw, ICRXDMTC);
+-
+ }
+
+ /******************************************************************************
+@@ -5151,6 +5244,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
+ 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 @@ e1000_get_cable_length(struct e1000_hw *
+ 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 @@ e1000_get_cable_length(struct e1000_hw *
+ 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 @@ e1000_get_auto_rd_done(struct e1000_hw *
+ 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 @@ e1000_get_auto_rd_done(struct e1000_hw *
+ 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 @@ e1000_put_hw_eeprom_semaphore(struct e10
+ 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 @@ e1000_arc_subsystem_valid(struct e1000_h
+ * 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
+--- a/drivers/net/e1000/e1000_hw.h
++++ b/drivers/net/e1000/e1000_hw.h
+@@ -57,6 +57,8 @@ typedef enum {
+ 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 @@ uint8_t e1000_arc_subsystem_valid(struct
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_ffvt_entry {
+ #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 @@ struct e1000_hw {
+ 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 @@ struct e1000_hw {
+ #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 @@ struct e1000_hw {
+ #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 @@ struct e1000_hw {
+ #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 @@ struct e1000_hw {
+ #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 @@ struct e1000_host_command_info {
+ #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 @@ struct e1000_host_command_info {
+ /* 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 @@ struct e1000_host_command_info {
+ #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 @@ struct e1000_host_command_info {
+ #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 @@ struct e1000_host_command_info {
+
+ /* 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
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -43,7 +43,7 @@ char e1000_driver_string[] = "Intel(R) P
+ #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 @@ static struct pci_device_id e1000_pci_tb
+ 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 @@ static struct pci_device_id e1000_pci_tb
+ 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 @@ int e1000_up(struct e1000_adapter *adapt
+ 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 int e1000_init_module(void);
+ 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 struct net_device_stats * e1000_g
+ 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_add_vid(struct
+ 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 int e1000_resume(struct pci_dev *
+ 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 @@ int
+ 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_up(struct e1000_adapter *adapter)
+ 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 @@ e1000_down(struct e1000_adapter *adapter
+ 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 @@ e1000_down(struct e1000_adapter *adapter
+ 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 @@ e1000_reset(struct e1000_adapter *adapte
+ 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 @@ e1000_probe(struct pci_dev *pdev,
+ 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 @@ e1000_probe(struct pci_dev *pdev,
+ 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 @@ e1000_probe(struct pci_dev *pdev,
+
+ /* 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 @@ e1000_remove(struct pci_dev *pdev)
+ {
+ 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 @@ e1000_remove(struct pci_dev *pdev)
+ }
+
+ 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 @@ e1000_remove(struct pci_dev *pdev)
+ }
+
+ 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 @@ e1000_sw_init(struct e1000_adapter *adap
+ 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 @@ e1000_sw_init(struct e1000_adapter *adap
+ 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 @@ e1000_open(struct net_device *netdev)
+
+ /* 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 @@ e1000_open(struct net_device *netdev)
+ 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_close(struct net_device *netdev)
+
+ 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_check_64k_bound(struct e1000_adapt
+ /**
+ * 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 @@ setup_tx_desc_die:
+
+ 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 @@ setup_tx_desc_die:
+ 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 @@ e1000_configure_tx(struct e1000_adapter
+ 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);
++
++ 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(&adapter->hw);
++ 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 @@ e1000_setup_rx_resources(struct e1000_ad
+
+ 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 @@ setup_rx_desc_die:
+ "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 @@ setup_rx_desc_die:
+ 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 @@ setup_rx_desc_die:
+ }
+
+ /**
++ * 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 @@ e1000_setup_rctl(struct e1000_adapter *a
+ 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 @@ e1000_setup_rctl(struct e1000_adapter *a
+ * 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 @@ e1000_setup_rctl(struct e1000_adapter *a
+
+ 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 @@ e1000_setup_rctl(struct e1000_adapter *a
+ 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));
+-
+- E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
+-
+- /* Setup the HW Rx Head and Tail Descriptor Pointers */
+- E1000_WRITE_REG(&adapter->hw, RDH, 0);
+- E1000_WRITE_REG(&adapter->hw, RDT, 0);
++ 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);
++ }
++
++ /* 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;
++ }
++
++#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)
++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);
++ e1000_clean_tx_ring(adapter, tx_ring);
+
+- vfree(adapter->tx_ring.buffer_info);
+- adapter->tx_ring.buffer_info = NULL;
++ vfree(tx_ring->buffer_info);
++ tx_ring->buffer_info = NULL;
+
+- pci_free_consistent(pdev, adapter->tx_ring.size,
+- adapter->tx_ring.desc, adapter->tx_ring.dma);
++ 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_all_tx_resources(struct e1000_adapter *adapter)
++{
++ int i;
+
+- 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_unmap_and_free_tx_resource(struct
+ /**
+ * 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 @@ e1000_clean_tx_ring(struct e1000_adapter
+ 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_free_rx_resources(struct e1000_ada
+ }
+
+ /**
+- * 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 @@ e1000_clean_rx_ring(struct e1000_adapter
+ 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 @@ e1000_clean_rx_ring(struct e1000_adapter
+ 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 @@ e1000_enter_82542_rst(struct e1000_adapt
+ mdelay(5);
+
+ if(netif_running(netdev))
+- e1000_clean_rx_ring(adapter);
++ e1000_clean_all_rx_rings(adapter);
+ }
+
+ static void
+@@ -1576,7 +2008,7 @@ e1000_leave_82542_rst(struct e1000_adapt
+
+ 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_set_mac(struct net_device *netdev,
+
+ 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 @@ e1000_set_multi(struct net_device *netde
+ 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 @@ e1000_set_multi(struct net_device *netde
+ /* 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 @@ e1000_set_multi(struct net_device *netde
+
+ 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 @@ static void
+ 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_watchdog_task(struct e1000_adapter
+
+ 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 @@ e1000_watchdog_task(struct e1000_adapter
+ /* 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 @@ e1000_watchdog_task(struct e1000_adapter
+ #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 @@ e1000_tso(struct e1000_adapter *adapter,
+ 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 @@ e1000_tso(struct e1000_adapter *adapter,
+ 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 @@ e1000_tso(struct e1000_adapter *adapter,
+ }
+
+ 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 @@ e1000_tx_csum(struct e1000_adapter *adap
+ 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 @@ e1000_tx_csum(struct e1000_adapter *adap
+ 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 @@ e1000_tx_csum(struct e1000_adapter *adap
+ #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 @@ e1000_tx_map(struct e1000_adapter *adapt
+ }
+
+ 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 @@ e1000_tx_queue(struct e1000_adapter *ada
+ 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 @@ static int
+ 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 @@ e1000_xmit_frame(struct sk_buff *skb, st
+ 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 @@ e1000_xmit_frame(struct sk_buff *skb, st
+ 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 @@ e1000_xmit_frame(struct sk_buff *skb, st
+ 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 @@ e1000_xmit_frame(struct sk_buff *skb, st
+ 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 @@ e1000_change_mtu(struct net_device *netd
+ 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 @@ e1000_update_stats(struct e1000_adapter
+ 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 @@ e1000_intr(int irq, void *data, struct p
+ 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 @@ e1000_intr(int irq, void *data, struct p
+ }
+
+ #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 @@ e1000_intr(int irq, void *data, struct p
+ }
+
+ 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 @@ e1000_intr(int irq, void *data, struct p
+ **/
+
+ 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 @@ e1000_clean(struct net_device *netdev, i
+ **/
+
+ 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 @@ e1000_clean_tx_irq(struct e1000_adapter
+ 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 @@ e1000_clean_tx_irq(struct e1000_adapter
+ #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 @@ e1000_clean_tx_irq(struct e1000_adapter
+
+ 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 @@ e1000_clean_tx_irq(struct e1000_adapter
+
+ 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 @@ e1000_clean_tx_irq(struct e1000_adapter
+ " 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 @@ e1000_clean_tx_irq(struct e1000_adapter
+ }
+ }
+ #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 @@ e1000_rx_checksum(struct e1000_adapter *
+
+ 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 @@ e1000_clean_rx_irq(struct e1000_adapter
+ }
+ #endif /* CONFIG_E1000_NAPI */
+ netdev->last_rx = jiffies;
++ rx_ring->pkt++;
+
+ next_desc:
+ rx_desc->status = 0;
+@@ -2953,7 +3499,7 @@ next_desc:
+ 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 @@ next_desc:
+
+ 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 @@ e1000_clean_rx_irq_ps(struct e1000_adapt
+ /* 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 @@ e1000_clean_rx_irq_ps(struct e1000_adapt
+ 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 @@ e1000_clean_rx_irq_ps(struct e1000_adapt
+ }
+ #endif /* CONFIG_E1000_NAPI */
+ netdev->last_rx = jiffies;
++ rx_ring->pkt++;
+
+ next_desc:
+ rx_desc->wb.middle.status_error &= ~0xFF;
+@@ -3081,7 +3631,7 @@ next_desc:
+ 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 @@ next_desc:
+ **/
+
+ 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 @@ e1000_alloc_rx_buffers(struct e1000_adap
+ * 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 @@ e1000_alloc_rx_buffers(struct e1000_adap
+ **/
+
+ 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 @@ e1000_alloc_rx_buffers_ps(struct e1000_a
+ 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 @@ e1000_alloc_rx_buffers_ps(struct e1000_a
+ * 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 @@ e1000_set_spd_dplx(struct e1000_adapter
+ return 0;
+ }
+
++#ifdef CONFIG_PM
+ static int
+ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+@@ -3715,6 +4270,12 @@ e1000_suspend(struct pci_dev *pdev, pm_m
+ }
+
+ 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 @@ e1000_suspend(struct pci_dev *pdev, pm_m
+ 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 @@ e1000_resume(struct pci_dev *pdev)
+ }
+
+ 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 @@ e1000_netpoll(struct net_device *netdev)
+ 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
+--- a/drivers/net/e1000/e1000_param.c
++++ b/drivers/net/e1000/e1000_param.c
+@@ -306,7 +306,8 @@ e1000_check_options(struct e1000_adapter
+ .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 @@ e1000_check_options(struct e1000_adapter
+ } 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 @@ e1000_check_options(struct e1000_adapter
+ .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 @@ e1000_check_options(struct e1000_adapter
+ } 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
+--- a/drivers/net/eepro.c
++++ b/drivers/net/eepro.c
+@@ -552,8 +552,7 @@ static int __init do_eepro_probe(struct
+ {
+ 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 @@ static int __init do_eepro_probe(struct
+ 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 @@ static void __init eepro_print_info (str
+ 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 @@ static void __init eepro_print_info (str
+ 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 @@ static void __init eepro_print_info (str
+
+ 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 @@ static int __init eepro_probe1(struct ne
+ 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 @@ static int __init eepro_probe1(struct ne
+ /* 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 @@ static int __init eepro_probe1(struct ne
+ dev->irq = 9;
+ }
+ }
+-
++
+ dev->open = eepro_open;
+ dev->stop = eepro_close;
+ dev->hard_start_xmit = eepro_send_packet;
+@@ -863,7 +865,7 @@ static int __init eepro_probe1(struct ne
+ 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 @@ static int eepro_open(struct net_device
+
+
+ /* 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 @@ static int eepro_open(struct net_device
+ 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 @@ set_multicast_list(struct net_device *de
+ 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 @@ hardware_send_packet(struct net_device *
+ 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 @@ eepro_rx(struct net_device *dev)
+ 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 @@ eepro_transmit_interrupt(struct net_devi
+ {
+ 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 @@ static int eepro_ethtool_get_settings(st
+ {
+ 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_AUTHOR("Pascal Dupuis and others"
+ 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
+--- a/drivers/net/epic100.c
++++ b/drivers/net/epic100.c
+@@ -1334,7 +1334,7 @@ static void epic_rx_err(struct net_devic
+ 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 @@ rx_action:
+
+ 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
+--- 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 @@ enum {
+ #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 @@ typedef union _ring_type {
+ /* 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 @@ typedef union _ring_type {
+
+ /*
+ * 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 @@ struct fe_priv {
+ u32 orig_mac[2];
+ u32 irqmask;
+ u32 desc_ver;
++ u32 txrxctl_bits;
+
+ void __iomem *base;
+
+@@ -534,7 +545,7 @@ static inline struct fe_priv *get_nvpriv
+
+ 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 mii_rw(struct net_device *dev
+
+ 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 int phy_init(struct net_device *d
+
+ 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_stop_tx(struct net_device
+
+ 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 void nv_txrx_reset(struct net_dev
+ */
+ 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 struct net_device_stats *nv_get_s
+ */
+ 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 int nv_alloc_rx(struct net_device
+ 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_do_rx_refill(unsigned lon
+
+ 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_rx(struct net_device
+
+ 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 @@ static int nv_init_ring(struct net_devic
+ 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_tx(struct net_devic
+
+ 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 void drain_ring(struct net_device
+ */
+ 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;
++ 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);
++
++ 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;
+- np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
+- PCI_DMA_TODEVICE);
++
++ 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)
++ 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
++#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]);
+- else {
++ 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);
++ }
+
+- 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 );
+- 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);
++ 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 @@ static int nv_start_xmit(struct sk_buff
+ 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 int nv_start_xmit(struct sk_buff
+ */
+ 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 @@ static void nv_tx_done(struct net_device
+ 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_done(struct net_device
+ */
+ 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 int nv_getlen(struct net_device *
+
+ 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 void set_bufsize(struct net_devic
+ */
+ 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 @@ static int nv_change_mtu(struct net_devi
+ 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 void nv_copy_mac_to_hw(struct net
+ */
+ 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 int nv_set_mac_address(struct net
+ */
+ 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 void nv_set_multicast(struct net_
+
+ 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 void nv_link_irq(struct net_devic
+ 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 irqreturn_t nv_nic_irq(int foo, v
+ 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_poll_controller(struct ne
+
+ 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_drvinfo(struct net_de
+
+ 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 void nv_get_wol(struct net_device
+
+ 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 int nv_get_regs_len(struct net_de
+
+ 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 void nv_get_regs(struct net_devic
+
+ 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 @@ static struct ethtool_ops ops = {
+ .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 @@ static int nv_open(struct net_device *de
+ /* 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 @@ out_drain:
+
+ 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 @@ static int __devinit nv_probe(struct pci
+ 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 @@ static int __devinit nv_probe(struct pci
+ 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 @@ static int __devinit nv_probe(struct pci
+ 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 @@ static int __devinit nv_probe(struct pci
+ 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 @@ out:
+ 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 @@ static struct pci_device_id pci_tbl[] =
+ },
+ { /* 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 @@ static struct pci_device_id pci_tbl[] =
+ },
+ { /* 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
+--- /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
+--- /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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at ru.mvista.com>
++ *
++ * Heavily based on original FEC driver by Dan Malek <dan at embeddededge.com>
++ * and modifications by Joakim Tjernlund <joakim.tjernlund at 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 at 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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at ru.mvista.com>
++ *
++ * Heavily based on original FEC driver by Dan Malek <dan at embeddededge.com>
++ * and modifications by Joakim Tjernlund <joakim.tjernlund at 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
+--- /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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at 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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at 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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at 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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at 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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at 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
+--- 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>
+@@ -85,7 +81,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/spinlock.h>
+ #include <linux/mm.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+ #include <linux/udp.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_set_mac_address(struct n
+ 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 @@ static int gfar_poll(struct net_device *
+ #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 @@ int gfar_uses_fcb(struct gfar_private *p
+ 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 @@ static int gfar_probe(struct device *dev
+
+ 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 @@ static int gfar_probe(struct device *dev
+ /* 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 @@ static int gfar_probe(struct device *dev
+ 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 @@ static int gfar_probe(struct device *dev
+ 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 @@ static int gfar_remove(struct device *de
+ 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);
+-
+- if(NULL == mii_info) {
+- if (netif_msg_ifup(priv))
+- printk(KERN_ERR "%s: Could not allocate mii_info\n",
+- dev->name);
+- return -ENOMEM;
+- }
+-
+- mii_info->speed = SPEED_1000;
+- mii_info->duplex = DUPLEX_FULL;
+- mii_info->pause = 0;
+- mii_info->link = 1;
+-
+- mii_info->advertising = (ADVERTISED_10baseT_Half |
+- ADVERTISED_10baseT_Full |
+- ADVERTISED_100baseT_Half |
+- ADVERTISED_100baseT_Full |
+- ADVERTISED_1000baseT_Full);
+- mii_info->autoneg = 1;
++ phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
+
+- 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;
++ if (IS_ERR(phydev)) {
++ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
++ return PTR_ERR(phydev);
+ }
+
+- mii_info->phyinfo = curphy;
++ /* Remove any features not supported by the controller */
++ phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
++ phydev->advertising = phydev->supported;
+
+- /* 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 @@ void stop_gfar(struct net_device *dev)
+ 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 @@ void stop_gfar(struct net_device *dev)
+ 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 @@ void stop_gfar(struct net_device *dev)
+
+ /* 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 @@ int startup_gfar(struct net_device *dev)
+ (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 @@ int startup_gfar(struct net_device *dev)
+ (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 @@ int startup_gfar(struct net_device *dev)
+ }
+ }
+
+- /* 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 @@ tx_skb_fail:
+ priv->tx_bd_base,
+ gfar_read(®s->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 @@ static int gfar_start_xmit(struct sk_buf
+ 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 @@ static int gfar_close(struct net_device
+ 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 @@ struct sk_buff * gfar_new_skb(struct net
+ 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 @@ static int gfar_process_frame(struct net
+ 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 @@ static irqreturn_t gfar_interrupt(int ir
+ 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 @@ static void adjust_link(struct net_devic
+ {
+ 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;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (phydev->link) {
++ u32 tempval = gfar_read(®s->maccfg2);
+
+- if (mii_info->link) {
+ /* 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(®s->maccfg2);
++ if (phydev->duplex != priv->oldduplex) {
++ new_state = 1;
++ if (!(phydev->duplex))
+ tempval &= ~(MACCFG2_FULL_DUPLEX);
+- gfar_write(®s->maccfg2, tempval);
+-
+- if (netif_msg_link(priv))
+- printk(KERN_INFO "%s: Half Duplex\n",
+- dev->name);
+- } else {
+- tempval = gfar_read(®s->maccfg2);
++ else
+ tempval |= MACCFG2_FULL_DUPLEX;
+- gfar_write(®s->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(®s->maccfg2);
+ tempval =
+ ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
+- gfar_write(®s->maccfg2, tempval);
+ break;
+ case 100:
+ case 10:
+- tempval = gfar_read(®s->maccfg2);
+ tempval =
+ ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
+- gfar_write(®s->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(®s->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 struct device_driver gfar_driver
+
+ 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
+--- 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 @@ struct gfar {
+ 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_private {
+ 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 @@ struct gfar_private {
+ 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 inline void gfar_write(volatile u
+
+ 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
+--- 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 @@ static void gfar_gdrvinfo(struct net_dev
+ 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;
+-
+- 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;
++ struct phy_device *phydev = priv->phydev;
++
++ 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 @@ static unsigned int gfar_usecs2ticks(str
+ 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 @@ static unsigned int gfar_ticks2usecs(str
+ 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 @@ static int gfar_gcoalesce(struct net_dev
+ 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 @@ static int gfar_scoalesce(struct net_dev
+ 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 @@ static int gfar_scoalesce(struct net_dev
+ 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 @@ static void gfar_set_msglevel(struct net
+
+ 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
+--- /dev/null
++++ b/drivers/net/gianfar_mii.c
+@@ -0,0 +1,220 @@
++/*
++ * 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 at 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 <linux/platform_device.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(®s->miimadd, (mii_id << 8) | regnum);
++
++ /* Write out the value we want */
++ gfar_write(®s->miimcon, value);
++
++ /* Wait for the transaction to finish */
++ while (gfar_read(®s->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(®s->miimadd, (mii_id << 8) | regnum);
++
++ /* Clear miimcom, and then initiate a read */
++ gfar_write(®s->miimcom, 0);
++ gfar_write(®s->miimcom, MII_READ_COMMAND);
++
++ /* Wait for the transaction to finish */
++ while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
++ cpu_relax();
++
++ /* Grab the value of the register from miimstat */
++ value = gfar_read(®s->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(®s->miimcfg, MIIMCFG_RESET);
++
++ /* Setup the MII Mgmt clock speed */
++ gfar_write(®s->miimcfg, MIIMCFG_INIT_VALUE);
++
++ /* Wait until the bus is free */
++ while ((gfar_read(®s->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
+--- /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 at 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
+--- 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 at 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(®base->miimadd, (mii_id << 8) | regnum);
+-
+- /* Write out the value we want */
+- gfar_write(®base->miimcon, value);
+-
+- /* Wait for the transaction to finish */
+- while (gfar_read(®base->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(®base->miimadd, (mii_id << 8) | regnum);
+-
+- /* Clear miimcom, and then initiate a read */
+- gfar_write(®base->miimcom, 0);
+- gfar_write(®base->miimcom, MII_READ_COMMAND);
+-
+- /* Wait for the transaction to finish */
+- while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+- cpu_relax();
+-
+- /* Grab the value of the register from miimstat */
+- value = gfar_read(®base->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
+--- 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 at 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
+--- 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
+--- a/drivers/net/hamradio/bpqether.c
++++ b/drivers/net/hamradio/bpqether.c
+@@ -144,7 +144,7 @@ static inline struct net_device *bpq_get
+ {
+ 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 @@ static void *bpq_seq_start(struct seq_fi
+ 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 @@ static void *bpq_seq_next(struct seq_fil
+ 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 @@ static int bpq_device_event(struct notif
+ 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 @@ static int bpq_device_event(struct notif
+ default:
+ break;
+ }
+- rcu_read_unlock();
+
+ return NOTIFY_DONE;
+ }
+diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
+--- a/drivers/net/hamradio/mkiss.c
++++ b/drivers/net/hamradio/mkiss.c
+@@ -14,13 +14,14 @@
+ *
+ * Copyright (C) Hans Alblas PE1AYX <hans at esrac.ele.tue.nl>
+ * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf at linux-mips.org>
++ * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas at 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 @@ struct mkiss {
+
+ 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 @@ static int check_crc_flex(unsigned char
+ 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 @@ static void ax_bump(struct mkiss *ax)
+
+ spin_lock_bh(&ax->buflock);
+ if (ax->rbuff[0] > 0x0f) {
+- if (ax->rbuff[0] & 0x20) {
+- ax->crcmode = CRC_MODE_FLEX;
++ 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;
++ *ax->rbuff &= ~0x80;
++ } else if (ax->rbuff[0] & 0x20) {
+ if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
+- ax->stats.rx_errors++;
++ 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
++
++ /*
++ * 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 @@ static void ax_changedmtu(struct mkiss *
+ "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 @@ static void ax_encaps(struct net_device
+ 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);
++ }
++ }
+
+- default:
+- count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+- break;
+- }
+-
+ 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 @@ static void ax_encaps(struct net_device
+ 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 @@ static void ax_setup(struct net_device *
+ * 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 @@ static void mkiss_put(struct mkiss *ax)
+ 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 @@ static int mkiss_open(struct tty_struct
+ 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 @@ static int mkiss_ioctl(struct tty_struct
+
+ 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 @@ out:
+ }
+
+ static struct tty_ldisc ax_ldisc = {
++ .owner = THIS_MODULE,
+ .magic = TTY_LDISC_MAGIC,
+ .name = "mkiss",
+ .open = mkiss_open,
+@@ -904,6 +1016,8 @@ static void __exit mkiss_exit_driver(voi
+
+ MODULE_AUTHOR("Ralf Baechle DL5RB <ralf at 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
+--- 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
+--- a/drivers/net/hp100.c
++++ b/drivers/net/hp100.c
+@@ -2517,10 +2517,8 @@ static int hp100_down_vg_link(struct net
+ 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 @@ static int hp100_down_vg_link(struct net
+ 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 @@ static int hp100_down_vg_link(struct net
+ 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 @@ static int hp100_down_vg_link(struct net
+ 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 @@ static int hp100_down_vg_link(struct net
+
+ 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 @@ static int hp100_login_to_vg_hub(struct
+ 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 @@ static int hp100_login_to_vg_hub(struct
+ 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 @@ static int hp100_login_to_vg_hub(struct
+ #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
+--- 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
+--- 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 at mvista.com
+- * June, 2002
++ * Copyright (c) 2004, 2005 Zultys Technologies.
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+ *
+- * Copyright 2002 MontaVista Softare Inc.
++ * Based on original work by
++ * Matt Porter <mporter at kernel.crashing.org>
++ * Armin Kuster <akuster at 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_
++
++#include <linux/config.h>
++#include <linux/types.h>
++
++/* 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
++
++/* 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;
++};
++
++#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
++
++/* 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
+
+-#ifndef _IBM_EMAC_H_
+-#define _IBM_EMAC_H_
+-/* General defines needed for the driver */
+-
+-/* 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;
+-
+-/* 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
+-
+-/* 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)
+-
+-/* Transmit Mode Register 0 */
+-#define EMAC_TMR0_GNP0 0x80000000
+-#define EMAC_TMR0_GNP1 0x40000000
+-#define EMAC_TMR0_GNPD 0x20000000
+-#define EMAC_TMR0_FC 0x10000000
++#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 @@ typedef struct emac_regs {
+ #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)
++
++/* 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
+
+-/* Receive Mode Register */
++/* 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 @@ typedef struct emac_regs {
+ #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 @@ typedef struct emac_regs {
+ #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 @@ typedef struct emac_regs {
+ #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
+-
+-/* 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
++#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
++
++/* 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_DFLT ( \
+- MAL_TX_CTRL_INTR | EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP )
++#define EMAC_TX_CTRL_TAH_CSUM 0x000e
+
+-/* 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 @@ typedef struct emac_regs {
+ #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 @@ typedef struct emac_regs {
+ #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
+--- 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 at kernel.crashing.org>
++ * Driver for PowerPC 4xx on-chip ethernet controller.
+ *
+- * Based on original work by
++ * Copyright (c) 2004, 2005 Zultys Technologies.
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+ *
++ * Based on original work by
++ * Matt Porter <mporter at kernel.crashing.org>
++ * (c) 2003 Benjamin Herrenschmidt <benh at kernel.crashing.org>
+ * Armin Kuster <akuster at mvista.com>
+ * Johnnie Peters <jpeters at 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 at 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 at zultys.com> or <ebs at 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");
+-
+-#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
+-};
++/* minimum number of free TX descriptors required to wake up TX process */
++#define EMAC_TX_WAKEUP_THRESH (NUM_TX_BUFF / 4)
+
+-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;
+-
+-/* If EMACs share a common MDIO device, this points to it */
+-static struct net_device *mdio_ndev = NULL;
++static u32 busy_phy_map;
+
+-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)
++#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 inline void EMAC_RX_CLK_TX(int idx)
+ {
+- struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(rgmii_dev);
+- const char *mode_name[] = { "RTBI", "RGMII", "TBI", "GMII" };
+- int mode = -1;
++ unsigned long flags;
++ local_irq_save(flags);
+
+- if (!rgmii) {
+- rgmii = kmalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);
++#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
+
+- if (rgmii == NULL) {
+- printk(KERN_ERR
+- "rgmii%d: Out of memory allocating RGMII structure!\n",
+- rgmii_dev->def->index);
+- return -ENOMEM;
+- }
++ local_irq_restore(flags);
++}
+
+- memset(rgmii, 0, sizeof(*rgmii));
++static inline void EMAC_RX_CLK_DEFAULT(int idx)
++{
++ unsigned long flags;
++ local_irq_save(flags);
+
+- 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);
++#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
+
+- kfree(rgmii);
+- return -ENOMEM;
+- }
+- ocp_set_drvdata(rgmii_dev, rgmii);
+- }
++ local_irq_restore(flags);
++}
++#else
++#define EMAC_RX_CLK_TX(idx) ((void)0)
++#define EMAC_RX_CLK_DEFAULT(idx) ((void)0)
++#endif
+
+- 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;
+- }
+- }
++#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
+
+- /* Set mode to RGMII if nothing valid is detected */
+- if (mode < 0)
+- mode = RGMII;
++/* 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
++}
+
+- printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",
+- rgmii_dev->def->index, input, mode_name[mode]);
++/* 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"
++};
+
+- rgmii->mode[input] = mode;
+- rgmii->users++;
++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);
+
+- return 0;
++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 void
+-emac_rgmii_port_speed(struct ocp_device *ocpdev, int input, int speed)
++static inline int emac_phy_gpcs(int phy_mode)
+ {
+- struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev);
+- unsigned int rgmii_speed;
++ return phy_mode == PHY_MODE_TBI ||
++ phy_mode == PHY_MODE_RTBI;
++}
+
+- rgmii_speed = in_be32(&rgmii->base->ssr);
++static inline void emac_tx_enable(struct ocp_enet_private *dev)
++{
++ struct emac_regs *p = dev->emacp;
++ unsigned long flags;
++ u32 r;
+
+- rgmii_speed &= ~rgmii_speed_mask[input];
++ local_irq_save(flags);
+
+- if (speed == 1000)
+- rgmii_speed |= rgmii_speed1000[input];
+- else if (speed == 100)
+- rgmii_speed |= rgmii_speed100[input];
++ DBG("%d: tx_enable" NL, dev->def->index);
+
+- out_be32(&rgmii->base->ssr, rgmii_speed);
++ 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_close_rgmii(struct ocp_device *ocpdev)
++static void emac_tx_disable(struct ocp_enet_private *dev)
+ {
+- struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev);
+- BUG_ON(!rgmii || rgmii->users == 0);
++ struct emac_regs *p = dev->emacp;
++ unsigned long flags;
++ u32 r;
++
++ local_irq_save(flags);
++
++ DBG("%d: tx_disable" NL, dev->def->index);
+
+- if (!--rgmii->users) {
+- ocp_set_drvdata(ocpdev, NULL);
+- iounmap((void *)rgmii->base);
+- kfree(rgmii);
++ 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 int emac_init_zmii(struct ocp_device *zmii_dev, int input, int phy_mode)
++static void emac_rx_enable(struct ocp_enet_private *dev)
+ {
+- struct ibm_ocp_zmii *zmii = ZMII_PRIV(zmii_dev);
+- const char *mode_name[] = { "SMII", "RMII", "MII" };
+- int mode = -1;
++ struct emac_regs *p = dev->emacp;
++ unsigned long flags;
++ u32 r;
+
+- 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);
++ local_irq_save(flags);
++ if (unlikely(dev->commac.rx_stopped))
++ goto out;
+
+- kfree(zmii);
+- return -ENOMEM;
+- }
+- ocp_set_drvdata(zmii_dev, zmii);
+- }
++ DBG("%d: rx_enable" NL, dev->def->index);
+
+- 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;
++ 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);
+ }
+-
+- /* 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;
++ out:
++ local_irq_restore(flags);
+ }
+
+-static void emac_enable_zmii_port(struct ocp_device *ocpdev, int input)
++static void emac_rx_disable(struct ocp_enet_private *dev)
+ {
+- 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);
+-}
++ struct emac_regs *p = dev->emacp;
++ unsigned long flags;
++ u32 r;
+
+-static void
+-emac_zmii_port_speed(struct ocp_device *ocpdev, int input, int speed)
+-{
+- struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
++ local_irq_save(flags);
+
+- if (speed == 100)
+- zmii_speed |= zmii_speed100[input];
+- else
+- zmii_speed &= ~zmii_speed100[input];
++ DBG("%d: rx_disable" NL, dev->def->index);
+
+- out_be32(&zmii->base->ssr, zmii_speed);
++ 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 void emac_close_zmii(struct ocp_device *ocpdev)
++static inline void emac_rx_disable_async(struct ocp_enet_private *dev)
+ {
+- struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
+- BUG_ON(!zmii || zmii->users == 0);
++ struct emac_regs *p = dev->emacp;
++ unsigned long flags;
++ u32 r;
+
+- if (!--zmii->users) {
+- ocp_set_drvdata(ocpdev, NULL);
+- iounmap((void *)zmii->base);
+- kfree(zmii);
+- }
++ 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);
+ }
+
+-int emac_phy_read(struct net_device *dev, int mii_id, int reg)
++static int emac_reset(struct ocp_enet_private *dev)
+ {
+- int count;
+- uint32_t stacr;
+- struct ocp_enet_private *fep = dev->priv;
+- emac_t *emacp = fep->emacp;
++ struct emac_regs *p = dev->emacp;
++ unsigned long flags;
++ int n = 20;
+
+- MDIO_DEBUG(("%s: phy_read, id: 0x%x, reg: 0x%x\n", dev->name, mii_id,
+- reg));
++ DBG("%d: reset" NL, dev->def->index);
+
+- /* Enable proper ZMII port */
+- if (fep->zmii_dev)
+- emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input);
++ local_irq_save(flags);
+
+- /* Use the EMAC that has the MDIO port */
+- if (fep->mdio_dev) {
+- dev = fep->mdio_dev;
+- fep = dev->priv;
+- emacp = fep->emacp;
++ 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);
+ }
+
+- count = 0;
+- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+- && (count++ < MDIO_DELAY))
+- udelay(1);
+- MDIO_DEBUG((" (count was %d)\n", count));
++ out_be32(&p->mr0, EMAC_MR0_SRST);
++ while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n)
++ --n;
++ local_irq_restore(flags);
+
+- if ((stacr & EMAC_STACR_OC) == 0) {
+- printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name);
+- return -1;
++ if (n) {
++ dev->reset_failed = 0;
++ return 0;
++ } else {
++ emac_report_timeout_error(dev, "reset timeout");
++ dev->reset_failed = 1;
++ return -ETIMEDOUT;
+ }
++}
+
+- /* 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);
++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;
+
+- out_be32(&emacp->em0stacr, stacr);
++ DBG("%d: hash_mc %d" NL, dev->def->index, dev->ndev->mc_count);
+
+- count = 0;
+- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+- && (count++ < MDIO_DELAY))
+- udelay(1);
+- MDIO_DEBUG((" (count was %d)\n", 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]);
+
+- if ((stacr & EMAC_STACR_OC) == 0) {
+- printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name);
+- return -1;
++ 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]);
++}
+
+- /* Check for a read error */
+- if (stacr & EMAC_STACR_PHYE) {
+- MDIO_DEBUG(("EMAC MDIO PHY error !\n"));
+- return -1;
+- }
++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;
+
+- MDIO_DEBUG((" -> 0x%x\n", stacr >> 16));
++ 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;
++}
+
+- return (stacr >> 16);
++static inline int emac_opb_mhz(void)
++{
++ return (ocp_sys_info.opb_bus_freq + 500000) / 1000000;
+ }
+
+-void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
++/* BHs disabled */
++static int emac_configure(struct ocp_enet_private *dev)
+ {
+- int count;
+- uint32_t stacr;
+- struct ocp_enet_private *fep = dev->priv;
+- emac_t *emacp = fep->emacp;
++ struct emac_regs *p = dev->emacp;
++ struct net_device *ndev = dev->ndev;
++ int gige;
++ u32 r;
+
+- MDIO_DEBUG(("%s phy_write, id: 0x%x, reg: 0x%x, data: 0x%x\n",
+- dev->name, mii_id, reg, data));
++ DBG("%d: configure" NL, dev->def->index);
+
+- /* Enable proper ZMII port */
+- if (fep->zmii_dev)
+- emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input);
++ if (emac_reset(dev) < 0)
++ return -ETIMEDOUT;
+
+- /* Use the EMAC that has the MDIO port */
+- if (fep->mdio_dev) {
+- dev = fep->mdio_dev;
+- fep = dev->priv;
+- emacp = fep->emacp;
+- }
++ tah_reset(dev->tah_dev);
+
+- count = 0;
+- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+- && (count++ < MDIO_DELAY))
+- udelay(1);
+- MDIO_DEBUG((" (count was %d)\n", count));
++ /* 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);
+
+- if ((stacr & EMAC_STACR_OC) == 0) {
+- printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
+- return;
++ /* 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;
+ }
+
+- /* Clear the speed bits and make a read request to the PHY */
++ 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);
+
+- stacr = ((EMAC_STACR_WRITE | (reg & 0x1f)) & ~EMAC_STACR_CLK_100MHZ);
+- stacr |= ((mii_id & 0x1f) << 5) | ((data & 0xffff) << 16);
++#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);
+
+- out_be32(&emacp->em0stacr, stacr);
++ /* 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
+
+- count = 0;
+- while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+- && (count++ < MDIO_DELAY))
+- udelay(1);
+- MDIO_DEBUG((" (count was %d)\n", count));
++ 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;
++}
+
+- if ((stacr & EMAC_STACR_OC) == 0)
+- printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
++/* BHs disabled */
++static void emac_reinitialize(struct ocp_enet_private *dev)
++{
++ DBG("%d: reinitialize" NL, dev->def->index);
+
+- /* Check for a write error */
+- if ((stacr & EMAC_STACR_PHYE) != 0) {
+- MDIO_DEBUG(("EMAC MDIO PHY error !\n"));
++ if (!emac_configure(dev)) {
++ emac_tx_enable(dev);
++ emac_rx_enable(dev);
+ }
+ }
+
+-static void emac_txeob_dev(void *param, u32 chanmask)
++/* BHs disabled */
++static void emac_full_tx_reset(struct net_device *ndev)
+ {
+- struct net_device *dev = param;
+- struct ocp_enet_private *fep = dev->priv;
+- unsigned long flags;
++ struct ocp_enet_private *dev = ndev->priv;
++ struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+- spin_lock_irqsave(&fep->lock, flags);
++ DBG("%d: full_tx_reset" NL, dev->def->index);
+
+- PKT_DEBUG(("emac_txeob_dev() entry, tx_cnt: %d\n", fep->tx_cnt));
++ 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;
+
+- while (fep->tx_cnt &&
+- !(fep->tx_desc[fep->ack_slot].ctrl & MAL_TX_CTRL_READY)) {
++ emac_configure(dev);
+
+- 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]);
++ mal_enable_tx_channel(dev->mal, emacdata->mal_tx_chan);
++ emac_tx_enable(dev);
++ emac_rx_enable(dev);
+
+- 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);
++ netif_wake_queue(ndev);
+ }
+
+-/*
+- 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.
+- */
+-static void emac_rx_fill(struct net_device *dev, int end)
++static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg)
+ {
+- int i;
+- struct ocp_enet_private *fep = dev->priv;
++ struct emac_regs *p = dev->emacp;
++ u32 r;
++ int n;
+
+- 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);
++ DBG2("%d: mdio_read(%02x,%02x)" NL, dev->def->index, id, reg);
+
+- 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;
++ /* Enable proper MDIO port */
++ zmii_enable_mdio(dev->zmii_dev, dev->zmii_input);
+
+- }
+-
+- if (skb_res)
+- skb_reserve(fep->rx_skb[i], skb_res);
++ /* Wait for management interface to become idle */
++ n = 10;
++ while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) {
++ udelay(1);
++ if (!--n)
++ goto to;
++ }
+
+- /* 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);
++ /* 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));
++
++ /* Wait for read to complete */
++ n = 100;
++ while (!((r = in_be32(&p->stacr)) & EMAC_STACR_OC)) {
++ udelay(1);
++ if (!--n)
++ goto to;
++ }
+
+- } while ((i = (i + 1) % NUM_RX_BUFF) != end);
++ if (unlikely(r & EMAC_STACR_PHYE)) {
++ DBG("%d: mdio_read(%02x, %02x) failed" NL, dev->def->index,
++ id, reg);
++ return -EREMOTEIO;
++ }
+
+- fep->rx_slot = i;
++ 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_rx_csum(struct net_device *dev, unsigned short ctrl, struct sk_buff *skb)
++static void __emac_mdio_write(struct ocp_enet_private *dev, u8 id, u8 reg,
++ u16 val)
+ {
+- struct ocp_enet_private *fep = dev->priv;
++ struct emac_regs *p = dev->emacp;
++ int n;
++
++ DBG2("%d: mdio_write(%02x,%02x,%04x)" NL, dev->def->index, id, reg,
++ val);
+
+- /* Exit if interface has no TAH engine */
+- if (!fep->tah_dev) {
+- skb->ip_summed = CHECKSUM_NONE;
+- return;
++ /* 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;
+ }
+
+- /* 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++; */
++ /* 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_rx_clean(struct net_device *dev)
++static int emac_mdio_read(struct net_device *ndev, int id, int reg)
+ {
+- 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);
++ struct ocp_enet_private *dev = ndev->priv;
++ int res;
+
+- PKT_DEBUG(("emac_rx_clean() exit, rx_slot: %d\n", fep->rx_slot));
+-
+- return i;
++ 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_rxeob_dev(void *param, u32 chanmask)
++static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
+ {
+- struct net_device *dev = param;
+- struct ocp_enet_private *fep = dev->priv;
+- unsigned long flags;
+- int n;
++ struct ocp_enet_private *dev = ndev->priv;
+
+- 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);
++ local_bh_disable();
++ __emac_mdio_write(dev->mdio_dev ? dev->mdio_dev : dev, (u8) id,
++ (u8) reg, (u16) val);
++ local_bh_enable();
+ }
+
+-/*
+- * This interrupt should never occurr, we don't program
+- * the MAL for contiunous mode.
+- */
+-static void emac_txde_dev(void *param, u32 chanmask)
++/* BHs disabled */
++static void emac_set_multicast_list(struct net_device *ndev)
+ {
+- struct net_device *dev = param;
+- struct ocp_enet_private *fep = dev->priv;
++ struct ocp_enet_private *dev = ndev->priv;
++ struct emac_regs *p = dev->emacp;
++ u32 rmr = emac_iff2rmr(ndev);
+
+- printk(KERN_WARNING "%s: transmit descriptor error\n", dev->name);
++ DBG("%d: multicast %08x" NL, dev->def->index, rmr);
++ BUG_ON(!netif_running(dev->ndev));
+
+- emac_mac_dump(dev);
+- emac_mal_dump(dev);
+-
+- /* Reenable the transmit channel */
+- mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
++ /* 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
++ */
++ emac_rx_disable(dev);
++ if (rmr & EMAC_RMR_MAE)
++ emac_hash_mc(dev);
++ out_be32(&p->rmr, rmr);
++ emac_rx_enable(dev);
+ }
+
+-/*
+- * 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)
++/* BHs disabled */
++static int emac_resize_rx_ring(struct ocp_enet_private *dev, int new_mtu)
+ {
+- struct net_device *dev = param;
+- struct ocp_enet_private *fep = dev->priv;
+- unsigned long flags;
++ 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;
+
+- if (net_ratelimit()) {
+- printk(KERN_WARNING "%s: receive descriptor error\n",
+- fep->ndev->name);
++ emac_rx_disable(dev);
++ mal_disable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+
+- emac_mac_dump(dev);
+- emac_mal_dump(dev);
+- emac_desc_dump(dev);
++ if (dev->rx_sg_skb) {
++ ++dev->estats.rx_dropped_resize;
++ dev_kfree_skb(dev->rx_sg_skb);
++ dev->rx_sg_skb = NULL;
+ }
+
+- /* Disable RX channel */
+- spin_lock_irqsave(&fep->lock, flags);
+- mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
++ /* 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;
+
+- /* For now, charge the error against all emacs */
+- fep->stats.rx_errors++;
++ 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);
++ }
+
+- /* so do we have any good packets still? */
+- emac_rx_clean(dev);
++ /* Reallocate RX ring only if bigger skb buffers are required */
++ if (rx_skb_size <= dev->rx_skb_size)
++ goto skip;
+
+- /* When the interface is restarted it resets processing to the
+- * first descriptor in the table.
+- */
++ /* 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;
++ }
+
+- fep->rx_slot = 0;
+- emac_rx_fill(dev, 0);
++ BUG_ON(!dev->rx_skb[i]);
++ dev_kfree_skb(dev->rx_skb[i]);
+
+- set_mal_dcrn(fep->mal, DCRN_MALRXEOBISR, fep->commac.rx_chan_mask);
+- set_mal_dcrn(fep->mal, DCRN_MALRXDEIR, fep->commac.rx_chan_mask);
++ 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;
+
+- /* Reenable the receive channels */
+- mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
+- spin_unlock_irqrestore(&fep->lock, flags);
++ 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;
+ }
+
+-static irqreturn_t
+-emac_mac_irq(int irq, void *dev_instance, struct pt_regs *regs)
++/* Process ctx, rtnl_lock semaphore */
++static int emac_change_mtu(struct net_device *ndev, 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_enet_private *dev = ndev->priv;
++ int 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++;
++ if (new_mtu < EMAC_MIN_MTU || new_mtu > EMAC_MAX_MTU)
++ return -EINVAL;
+
+- /* Reenable the transmit channel */
+- mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
++ DBG("%d: change_mtu(%d)" NL, dev->def->index, new_mtu);
+
+- } else {
+- fep->stats.rx_errors++;
++ 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 (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++;
+-
+- emac_err_dump(dev, tmp_em0isr);
++ 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();
+
+- out_be32(&emacp->em0isr, tmp_em0isr);
+-
+- return IRQ_HANDLED;
++ return ret;
+ }
+
+-static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
++static void emac_clean_tx_ring(struct ocp_enet_private *dev)
+ {
+- 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;
+-
+- spin_lock_irqsave(&fep->lock, flags);
+-
+- len -= skb->data_len;
+-
+- 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;
+- }
+-
+- 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;
++ 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;
+ }
+- if (skb->ip_summed == CHECKSUM_HW)
+- ctrl |= EMAC_TX_CTRL_TAH_CSUM;
+-
+- fep->tx_desc[fep->tx_slot].ctrl = ctrl;
+-
+- len -= size;
+- offset += size;
++ dev->tx_desc[i].ctrl = 0;
++ dev->tx_desc[i].data_ptr = 0;
++ }
++}
+
+- /* Bump tx count */
+- if (++fep->tx_cnt == NUM_TX_BUFF)
+- netif_stop_queue(dev);
++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;
++ }
+
+- /* Next descriptor */
+- if (++fep->tx_slot == NUM_TX_BUFF)
+- fep->tx_slot = 0;
++ if (dev->rx_sg_skb) {
++ dev_kfree_skb(dev->rx_sg_skb);
++ dev->rx_sg_skb = NULL;
+ }
++}
+
+- for (f = 0; f < nr_frags; f++) {
+- struct skb_frag_struct *frag;
++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;
+
+- frag = &skb_shinfo(skb)->frags[f];
+- len = frag->size;
+- offset = 0;
++ dev->rx_skb[slot] = skb;
++ dev->rx_desc[slot].data_len = 0;
+
+- while (len) {
+- size = min(len, DESC_BUF_SIZE);
++ 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);
+
+- 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;
+- }
++ return 0;
++}
+
+- if (skb->ip_summed == CHECKSUM_HW)
+- ctrl |= EMAC_TX_CTRL_TAH_CSUM;
++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);
++}
+
+- 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;
++/* 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();
+
+- len -= size;
+- offset += size;
++ return 0;
++ oom:
++ emac_clean_rx_ring(dev);
++ free_irq(dev->def->irq, dev);
++ return -ENOMEM;
++}
+
+- /* Bump tx count */
+- if (++fep->tx_cnt == NUM_TX_BUFF)
+- netif_stop_queue(dev);
++/* BHs disabled */
++static int emac_link_differs(struct ocp_enet_private *dev)
++{
++ u32 r = in_be32(&dev->emacp->mr1);
+
+- /* Next descriptor */
+- if (++fep->tx_slot == NUM_TX_BUFF)
+- fep->tx_slot = 0;
+- }
+- }
++ int duplex = r & EMAC_MR1_FDE ? DUPLEX_FULL : DUPLEX_HALF;
++ int speed, pause, asym_pause;
+
+- /*
+- * Deferred set READY on first descriptor of packet to
+- * avoid TX MAL race.
+- */
+- fep->tx_desc[tx_slot_first].ctrl |= MAL_TX_CTRL_READY;
++ 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;
+
+- /* Send the packet out. */
+- out_be32(&emacp->em0tmr0, EMAC_TMR0_XMIT);
++ 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;
++}
+
+- fep->stats.tx_packets++;
+- fep->stats.tx_bytes += skb->len;
++/* BHs disabled */
++static void emac_link_timer(unsigned long data)
++{
++ struct ocp_enet_private *dev = (struct ocp_enet_private *)data;
++ int link_poll_interval;
+
+- PKT_DEBUG(("emac_start_xmit() exitn"));
++ DBG2("%d: link timer" NL, dev->def->index);
+
+- spin_unlock_irqrestore(&fep->lock, flags);
++ if (dev->phy.def->ops->poll_link(&dev->phy)) {
++ if (!netif_carrier_ok(dev->ndev)) {
++ EMAC_RX_CLK_DEFAULT(dev->def->index);
+
+- return 0;
+-}
++ /* Get new link parameters */
++ dev->phy.def->ops->read_link(&dev->phy);
+
+-static int emac_adjust_to_link(struct ocp_enet_private *fep)
+-{
+- emac_t *emacp = fep->emacp;
+- unsigned long mode_reg;
+- int full_duplex, speed;
++ if (dev->tah_dev || emac_link_differs(dev))
++ emac_full_tx_reset(dev->ndev);
+
+- full_duplex = 0;
+- speed = SPEED_10;
++ 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);
++ }
+
+- /* set mode register 1 defaults */
+- mode_reg = EMAC_M1_DEFAULT;
++ /* 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);
+
+- /* 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;
++ 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);
++}
+
+- /* 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;
++/* 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;
+
+- 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);
+- }
++ DBG("%d: close" NL, dev->def->index);
+
+- 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);
++ local_bh_disable();
++
++ if (dev->phy.address >= 0)
++ del_timer_sync(&dev->link_timer);
+
+- LINK_DEBUG(("%s: adjust to link, speed: %d, duplex: %d, opened: %d\n",
+- fep->ndev->name, speed, full_duplex, fep->opened));
++ 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();
+
+- 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);
++ emac_clean_tx_ring(dev);
++ emac_clean_rx_ring(dev);
++ free_irq(dev->def->irq, dev);
+
+ return 0;
+ }
+
+-static int emac_set_mac_address(struct net_device *ndev, void *p)
++static inline u16 emac_tx_csum(struct ocp_enet_private *dev,
++ struct sk_buff *skb)
+ {
+- struct ocp_enet_private *fep = ndev->priv;
+- emac_t *emacp = fep->emacp;
+- struct sockaddr *addr = p;
++#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;
++}
+
+- if (!is_valid_ether_addr(addr->sa_data))
+- return -EADDRNOTAVAIL;
++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;
+
+- memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
++ /* Send the packet out */
++ out_be32(&p->tmr0, EMAC_TMR0_XMIT);
+
+- /* set the high address */
+- out_be32(&emacp->em0iahr,
+- (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]);
++ if (unlikely(++dev->tx_cnt == NUM_TX_BUFF)) {
++ netif_stop_queue(ndev);
++ DBG2("%d: stopped TX queue" NL, dev->def->index);
++ }
+
+- /* 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]);
++ ndev->trans_start = jiffies;
++ ++dev->stats.tx_packets;
++ dev->stats.tx_bytes += len;
+
+ return 0;
+ }
+
+-static int emac_change_mtu(struct net_device *dev, int new_mtu)
++/* BHs disabled */
++static int emac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ {
+- 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;
+- }
++ struct ocp_enet_private *dev = ndev->priv;
++ unsigned int len = skb->len;
++ int slot;
+
+- 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);
++ u16 ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY |
++ MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb);
+
+- /* Re-init rx skbs */
+- fep->rx_slot = 0;
+- emac_rx_fill(dev, 0);
++ slot = dev->tx_slot++;
++ if (dev->tx_slot == NUM_TX_BUFF) {
++ dev->tx_slot = 0;
++ ctrl |= MAL_TX_CTRL_WRAP;
++ }
+
+- /* Restart the rx engine */
+- mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
+- out_be32(&emacp->em0mr0, em0mr0 | EMAC_M0_RXE);
++ DBG2("%d: xmit(%u) %d" NL, dev->def->index, len, slot);
+
+- spin_unlock_irqrestore(&fep->lock, flags);
+- }
++ 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 0;
++ return emac_xmit_finish(dev, len);
+ }
+
+-static void __emac_set_multicast_list(struct net_device *dev)
++#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)
+ {
+- 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;
++ while (1) {
++ u16 ctrl = base_ctrl;
++ int chunk = min(len, MAL_MAX_TX_SIZE);
++ len -= chunk;
+
+- /* Need to hash on the multicast address. */
+- for (dmi = dev->mc_list; dmi; dmi = dmi->next) {
+- unsigned long mc_crc;
+- unsigned int bit_number;
++ slot = (slot + 1) % NUM_TX_BUFF;
+
+- 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];
++ 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;
+
+- /* Turn on multicast addressing */
+- rmr |= EMAC_RMR_MAE;
++ pd += chunk;
+ }
+- out_be32(&emacp->em0rmr, rmr);
++ return slot;
+ }
+
+-static int emac_init_tah(struct ocp_enet_private *fep)
++/* BHs disabled (SG version for TAH equipped EMACs) */
++static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev)
+ {
+- tah_t *tahp;
++ 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;
+
+- /* Initialize TAH and enable checksum verification */
+- tahp = (tah_t *) ioremap(fep->tah_dev->def->paddr, sizeof(*tahp));
++ /* This is common "fast" path */
++ if (likely(!nr_frags && len <= MAL_MAX_TX_SIZE))
++ return emac_start_xmit(skb, ndev);
+
+- if (tahp == NULL) {
+- printk(KERN_ERR "tah%d: Cannot ioremap TAH registers!\n",
+- fep->tah_dev->def->index);
++ len -= skb->data_len;
+
+- return -ENOMEM;
++ /* 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);
+ }
+
+- out_be32(&tahp->tah_mr, TAH_MR_SR);
++ DBG2("%d: xmit_sg(%u) %d - %d" NL, dev->def->index, skb->len,
++ dev->tx_slot, slot);
+
+- /* wait for reset to complete */
+- while (in_be32(&tahp->tah_mr) & TAH_MR_SR) ;
++ /* Attach skb to the last slot so we don't release it too early */
++ dev->tx_skb[slot] = skb;
+
+- /* 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);
++ /* 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;
+
+- iounmap(tahp);
++ return emac_xmit_finish(dev, skb->len);
+
+- return 0;
++ 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 void emac_init_rings(struct net_device *dev)
++static inline void emac_recycle_rx_skb(struct ocp_enet_private *dev, int slot,
++ int len)
+ {
+- struct ocp_enet_private *ep = dev->priv;
+- int loop;
++ struct sk_buff *skb = dev->rx_skb[slot];
++ DBG2("%d: recycle %d %d" NL, dev->def->index, slot, len);
+
+- 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
+- */
+- }
++ if (len)
++ dma_map_single(dev->ldev, skb->data - 2,
++ EMAC_DMA_ALIGN(len + 2), DMA_FROM_DEVICE);
+
+- ep->tx_cnt = 0;
+- ep->tx_slot = 0;
+- ep->ack_slot = 0;
++ 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_reset_configure(struct ocp_enet_private *fep)
++static void emac_parse_rx_error(struct ocp_enet_private *dev, u16 ctrl)
+ {
+- emac_t *emacp = fep->emacp;
+- int i;
++ struct ibm_emac_error_stats *st = &dev->estats;
++ DBG("%d: BD RX error %04x" NL, dev->def->index, ctrl);
+
+- mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
+- mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
++ ++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;
++}
+
+- /*
+- * 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);
+- }
++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
++}
+
+- if (i >= 100) {
+- printk(KERN_ERR "%s: Cannot reset EMAC\n",
+- fep->ndev->name);
+- return;
++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;
+
+- /* Switch IRQs off for now */
+- out_be32(&emacp->em0iser, 0);
++ DBG2("%d: poll_rx(%d)" NL, dev->def->index, budget);
+
+- /* Configure MAL rx channel */
+- mal_set_rcbs(fep->mal, fep->mal_rx_chan, DESC_BUF_SIZE_REG);
++ again:
++ while (budget > 0) {
++ int len;
++ struct sk_buff *skb;
++ u16 ctrl = dev->rx_desc[slot].ctrl;
+
+- /* set the high address */
+- out_be32(&emacp->em0iahr,
+- (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]);
++ if (ctrl & MAL_RX_CTRL_EMPTY)
++ break;
+
+- /* 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]);
++ 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)) {
+
+- /* Adjust to link */
+- if (netif_carrier_ok(fep->ndev))
+- emac_adjust_to_link(fep);
++ skb = dev->rx_sg_skb;
++ dev->rx_sg_skb = NULL;
+
+- /* enable broadcast/individual address and RX FIFO defaults */
+- out_be32(&emacp->em0rmr, EMAC_RMR_DEFAULT);
++ 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;
++ }
+
+- /* set transmit request threshold register */
+- out_be32(&emacp->em0trtr, EMAC_TRTR_DEFAULT);
++ if (received) {
++ DBG2("%d: rx %d BDs" NL, dev->def->index, received);
++ dev->rx_slot = slot;
++ }
+
+- /* Reconfigure multicast */
+- __emac_set_multicast_list(fep->ndev);
++ if (unlikely(budget && dev->commac.rx_stopped)) {
++ struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+- /* 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);
++ barrier();
++ if (!(dev->rx_desc[slot].ctrl & MAL_RX_CTRL_EMPTY)) {
++ DBG2("%d: rx restart" NL, dev->def->index);
++ received = 0;
++ goto again;
++ }
+
+- /* set frame gap */
+- out_be32(&emacp->em0ipgvr, CONFIG_IBM_EMAC_FGAP);
+-
+- /* set VLAN Tag Protocol Identifier */
+- out_be32(&emacp->em0vtpid, 0x8100);
++ 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;
++ }
+
+- /* Init ring buffers */
+- emac_init_rings(fep->ndev);
++ 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;
+ }
+
+-static void emac_kick(struct ocp_enet_private *fep)
++/* BHs disabled */
++static int emac_peek_rx(void *param)
+ {
+- 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);
++ struct ocp_enet_private *dev = param;
++ return !(dev->rx_desc[dev->rx_slot].ctrl & MAL_RX_CTRL_EMPTY);
+ }
+
+-static void
+-emac_start_link(struct ocp_enet_private *fep, struct ethtool_cmd *ep)
++/* BHs disabled */
++static int emac_peek_rx_sg(void *param)
+ {
+- u32 advertise;
+- int autoneg;
+- int forced_speed;
+- int forced_duplex;
++ 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;
++ }
++}
+
+- /* 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;
++/* 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;
+
+- /* 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;
+- }
+- }
++ return IRQ_HANDLED;
++}
+
+- /* 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 struct net_device_stats *emac_stats(struct net_device *ndev)
++{
++ 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;
++
++ DBG2("%d: stats" NL, dev->def->index);
++
++ /* 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;
++
++ 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);
++
++ 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 void emac_link_timer(unsigned long data)
++static void emac_remove(struct ocp_device *ocpdev)
+ {
+- struct ocp_enet_private *fep = (struct ocp_enet_private *)data;
+- int link;
++ struct ocp_enet_private *dev = ocp_get_drvdata(ocpdev);
+
+- if (fep->going_away)
+- return;
++ DBG("%d: remove" NL, dev->def->index);
+
+- spin_lock_irq(&fep->lock);
++ ocp_set_drvdata(ocpdev, 0);
++ unregister_netdev(dev->ndev);
+
+- link = fep->phy_mii.def->ops->poll_link(&fep->phy_mii);
+- LINK_DEBUG(("%s: poll_link: %d\n", fep->ndev->name, link));
++ tah_fini(dev->tah_dev);
++ rgmii_fini(dev->rgmii_dev, dev->rgmii_input);
++ zmii_fini(dev->zmii_dev, dev->zmii_input);
+
+- 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);
++ emac_dbg_register(dev->def->index, 0);
++
++ mal_unregister_commac(dev->mal, &dev->commac);
++ iounmap((void *)dev->emacp);
++ kfree(dev->ndev);
+ }
+
+-static void emac_set_multicast_list(struct net_device *dev)
+-{
+- struct ocp_enet_private *fep = dev->priv;
++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,
++};
+
+- spin_lock_irq(&fep->lock);
+- __emac_set_multicast_list(dev);
+- spin_unlock_irq(&fep->lock);
+-}
++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,
++};
+
+-static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
++/* Ethtool support */
++static int emac_ethtool_get_settings(struct net_device *ndev,
++ struct ethtool_cmd *cmd)
+ {
+- struct ocp_enet_private *fep = ndev->priv;
++ struct ocp_enet_private *dev = 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)
++{
++ rp->rx_max_pending = rp->rx_pending = NUM_RX_BUFF;
++ rp->tx_max_pending = rp->tx_pending = NUM_TX_BUFF;
++}
++
++static void emac_ethtool_get_pauseparam(struct net_device *ndev,
++ struct ethtool_pauseparam *pp)
+ {
+- struct ocp_enet_private *fep = ndev->priv;
++ struct ocp_enet_private *dev = ndev->priv;
+
+- strcpy(info->driver, DRV_NAME);
+- 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;
++ 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 int emac_nway_reset(struct net_device *ndev)
++static u32 emac_ethtool_get_rx_csum(struct net_device *ndev)
+ {
+- struct ocp_enet_private *fep = ndev->priv;
++ struct ocp_enet_private *dev = ndev->priv;
++ return dev->tah_dev != 0;
++}
+
+- if (!fep->want_autoneg)
+- return -EINVAL;
+- spin_lock_irq(&fep->lock);
+- emac_start_link(fep, NULL);
+- spin_unlock_irq(&fep->lock);
+- return 0;
++static int emac_get_regs_len(struct ocp_enet_private *dev)
++{
++ return sizeof(struct emac_ethtool_regs_subhdr) + EMAC_ETHTOOL_REGS_SIZE;
+ }
+
+-static u32 emac_get_link(struct net_device *ndev)
++static int emac_ethtool_get_regs_len(struct net_device *ndev)
+ {
+- return netif_carrier_ok(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 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
+-};
++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 int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++static void emac_ethtool_get_regs(struct net_device *ndev,
++ struct ethtool_regs *regs, void *buf)
+ {
+- struct ocp_enet_private *fep = dev->priv;
+- uint16_t *data = (uint16_t *) & rq->ifr_ifru;
++ struct ocp_enet_private *dev = ndev->priv;
++ struct emac_ethtool_regs_hdr *hdr = buf;
+
+- switch (cmd) {
+- case SIOCGMIIPHY:
+- data[0] = fep->mii_phy_addr;
+- /* Fall through */
+- case SIOCGMIIREG:
+- data[3] = emac_phy_read(dev, fep->mii_phy_addr, data[1]);
+- return 0;
+- case SIOCSMIIREG:
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
++ hdr->components = 0;
++ buf = hdr + 1;
+
+- emac_phy_write(dev, fep->mii_phy_addr, data[1], data[2]);
+- return 0;
+- default:
+- return -EOPNOTSUPP;
++ 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_open(struct net_device *dev)
++static int emac_ethtool_nway_reset(struct net_device *ndev)
+ {
+- struct ocp_enet_private *fep = dev->priv;
+- int rc;
++ struct ocp_enet_private *dev = ndev->priv;
++ int res = 0;
+
+- spin_lock_irq(&fep->lock);
++ DBG("%d: nway_reset" NL, dev->def->index);
+
+- fep->opened = 1;
+- netif_carrier_off(dev);
++ if (dev->phy.address < 0)
++ return -EOPNOTSUPP;
+
+- /* Reset & configure the chip */
+- emac_reset_configure(fep);
++ local_bh_disable();
++ if (!dev->phy.autoneg) {
++ res = -EINVAL;
++ goto out;
++ }
+
+- spin_unlock_irq(&fep->lock);
++ dev->phy.def->ops->setup_aneg(&dev->phy, dev->phy.advertising);
++ emac_force_link_update(dev);
+
+- /* 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);
++ out:
++ local_bh_enable();
++ return res;
++}
+
+- netif_start_queue(dev);
+- bail:
+- return rc;
++static int emac_ethtool_get_stats_count(struct net_device *ndev)
++{
++ return EMAC_ETHTOOL_STATS_COUNT;
+ }
+
+-static int emac_close(struct net_device *dev)
++static void emac_ethtool_get_strings(struct net_device *ndev, u32 stringset,
++ u8 * buf)
+ {
+- struct ocp_enet_private *fep = dev->priv;
+- emac_t *emacp = fep->emacp;
++ if (stringset == ETH_SS_STATS)
++ memcpy(buf, &emac_stats_keys, sizeof(emac_stats_keys));
++}
+
+- /* 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);
++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();
++}
+
+- /*
+- * 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);
++static void emac_ethtool_get_drvinfo(struct net_device *ndev,
++ struct ethtool_drvinfo *info)
++{
++ struct ocp_enet_private *dev = ndev->priv;
+
+- 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);
+- }
+- }
++ strcpy(info->driver, "ibm_emac");
++ strcpy(info->version, DRV_VERSION);
++ info->fw_version[0] = '\0';
++ 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);
++}
+
+- /* Free the irq's */
+- free_irq(dev->irq, dev);
++static struct ethtool_ops emac_ethtool_ops = {
++ .get_settings = emac_ethtool_get_settings,
++ .set_settings = emac_ethtool_set_settings,
++ .get_drvinfo = emac_ethtool_get_drvinfo,
+
+- spin_unlock_irq(&fep->lock);
++ .get_regs_len = emac_ethtool_get_regs_len,
++ .get_regs = emac_ethtool_get_regs,
+
+- return 0;
+-}
++ .nway_reset = emac_ethtool_nway_reset,
+
+-static void emac_remove(struct ocp_device *ocpdev)
+-{
+- struct net_device *dev = ocp_get_drvdata(ocpdev);
+- struct ocp_enet_private *ep = dev->priv;
++ .get_ringparam = emac_ethtool_get_ringparam,
++ .get_pauseparam = emac_ethtool_get_pauseparam,
+
+- /* 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,
++ .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,
+ };
+
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-static void emac_netpoll(struct net_device *ndev)
++static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+ {
+- emac_rxeob_dev((void *)ndev, 0);
+- emac_txeob_dev((void *)ndev, 0);
++ 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:
++ case SIOCDEVPRIVATE:
++ data[0] = dev->phy.address;
++ /* Fall through */
++ case SIOCGMIIREG:
++ 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_mdio_write(ndev, dev->phy.address, data[1], data[2]);
++ return 0;
++ default:
++ return -EOPNOTSUPP;
++ }
+ }
+-#endif
+
+-static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
++static int __init emac_probe(struct ocp_device *ocpdev)
+ {
+- 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;
++
++ DBG("%d: probe" NL, ocpdev->def->index);
+
+- emacdata = (struct ocp_func_emac_data *)ocpdev->def->additions;
+ if (!emacdata) {
+ printk(KERN_ERR "emac%d: Missing additional data!\n",
+ ocpdev->def->index);
+@@ -1738,304 +1936,312 @@ static int emac_init_device(struct ocp_d
+
+ /* 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;
++ }
++ 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;
+ }
+- ep->mdio_dev = mdio_ndev;
+- } else {
+- ep->mdio_dev = ndev;
+ }
+
+- ocp_set_drvdata(ocpdev, ndev);
++ /* Attach to ZMII, if needed */
++ if ((err = zmii_attach(dev)) != 0)
++ goto out2;
++
++ /* Attach to RGMII, if needed */
++ if ((err = rgmii_attach(dev)) != 0)
++ goto out3;
++
++ /* Attach to TAH, if needed */
++ if ((err = tah_attach(dev)) != 0)
++ goto out4;
++
++ /* 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;
++ }
++
++ /* Fill in MAC address */
++ for (i = 0; i < 6; ++i)
++ ndev->dev_addr[i] = emacdata->mac_addr[i];
+
+- spin_lock_init(&ep->lock);
++ /* 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);
+
+- /* 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);
+- }
++ 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);
+
+- /* 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;
+-
+- /* 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;
+-
+- /* 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;
++ 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;
+ }
+- }
+- 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;
+-
+- /* 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;
++
++ /* Init PHY */
++ if (dev->phy.def->ops->init)
++ dev->phy.def->ops->init(&dev->phy);
+
+- /* 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;
++ /* 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 {
+- ep->phy_mii.speed = SPEED_10;
+- ep->phy_mii.duplex = DUPLEX_HALF;
++ 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);
+ }
+- }
+- emac_start_link(ep, NULL);
++ } else {
++ emac_reset(dev);
+
+- /* read the MAC Address */
+- for (i = 0; i < 6; i++)
+- ndev->dev_addr[i] = emacdata->mac_addr[i];
++ /* 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);
++
++ err = register_netdev(ndev);
++ if (err) {
++ printk(KERN_ERR "emac%d: failed to register net device (%d)!\n",
++ dev->def->index, err);
++ goto out6;
++ }
+
+- rc = register_netdev(ndev);
+- if (rc != 0)
+- goto bail;
++ ocp_set_drvdata(ocpdev, dev);
+
+- printk("%s: IBM emac, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+- ndev->name,
++ 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);
+-
+- 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 (dev->phy.address >= 0)
++ printk("%s: found %s PHY (0x%02x)\n", ndev->name,
++ dev->phy.def->name, dev->phy.address);
+
+- /* 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");
++
++ DBG(": init" NL);
+
+- if (skb_res > 2) {
+- printk(KERN_WARNING "Invalid skb_res: %d, cropping to 2\n",
+- skb_res);
+- skb_res = 2;
++ 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
+--- 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 at mvista.com
+- * Sept, 2001
++ * Copyright (c) 2004, 2005 Zultys Technologies.
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+ *
+- * Orignial driver
+- * Johnnie Peters
+- * jpeters at mvista.com
+- *
+- * Copyright 2000 MontaVista Softare Inc.
++ * Based on original work by
++ * Armin Kuster <akuster at mvista.com>
++ * Johnnie Peters <jpeters at 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
+-#endif
++#define NUM_TX_BUFF CONFIG_IBM_EMAC_TXB
++#define NUM_RX_BUFF CONFIG_IBM_EMAC_RXB
+
+-/* 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.
+- */
+-#ifndef CONFIG_IBM_EMAC_SKBRES
+-#define SKB_RES 2
+-#else
+-#define SKB_RES CONFIG_IBM_EMAC_SKBRES
++/* Simple sanity check */
++#if NUM_TX_BUFF > 256 || NUM_RX_BUFF > 256
++#error Invalid number of buffer descriptors (greater than 256)
+ #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.
++// 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.
+ */
+-#define MAX_NUM_BUF_DESC 255
+-#define DESC_BUF_SIZE 4080 /* max 4096-16 */
+-#define DESC_BUF_SIZE_REG (DESC_BUF_SIZE / 16)
+-
+-/* Transmitter timeout. */
+-#define TX_TIMEOUT (2*HZ)
+-
+-/* MDIO latency delay */
+-#define MDIO_DELAY 250
+-
+-/* 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))
+-
+-#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
++
++/* 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;
++};
++
++/* Error statistics */
++struct ibm_emac_error_stats {
++ u64 tx_undo;
++
++ /* 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;
++
++ /* 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 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 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 ocp_device *rgmii_dev;
+- int rgmii_input;
+-
+- struct ocp_device *zmii_dev;
+- int zmii_input;
+-
+- struct ibm_ocp_mal *mal;
+- int mal_tx_chan, mal_rx_chan;
+- struct mal_commac commac;
+-
+- struct ocp_device *tah_dev;
+-
+- int opened;
+- int going_away;
+- int wol_irq;
+- emac_t *emacp;
+- struct ocp_device *ocpdev;
+- struct net_device *ndev;
+- spinlock_t lock;
++ struct net_device *ndev; /* 0 */
++ struct emac_regs *emacp;
++
++ struct mal_descriptor *tx_desc;
++ int tx_cnt;
++ int tx_slot;
++ int ack_slot;
++
++ struct mal_descriptor *rx_desc;
++ int rx_slot;
++ struct sk_buff *rx_sg_skb; /* 1 */
++ int rx_skb_size;
++ int rx_sync_size;
++
++ struct ibm_emac_stats stats;
++ struct ocp_device *tah_dev;
++
++ struct ibm_ocp_mal *mal;
++ struct mal_commac commac;
++
++ struct sk_buff *tx_skb[NUM_TX_BUFF];
++ struct sk_buff *rx_skb[NUM_RX_BUFF];
++
++ struct ocp_device *zmii_dev;
++ int zmii_input;
++ struct ocp_enet_private *mdio_dev;
++ struct ocp_device *rgmii_dev;
++ int rgmii_input;
++
++ 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;
++};
++
++/* 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;
+ };
+-#endif /* _IBM_EMAC_CORE_H_ */
++
++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
+--- 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 at mvista.com
+- * April , 2002
+- *
+- * Copyright 2002 MontaVista Softare Inc.
++ * Copyright (c) 2004, 2005 Zultys Technologies
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at 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);
+-
+-void emac_phy_dump(struct net_device *dev)
+-{
+- struct ocp_enet_private *fep = dev->priv;
+- unsigned long i;
+- uint data;
+-
+- 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;
++
++#include "ibm_emac_core.h"
++
++static void emac_desc_dump(int idx, struct ocp_enet_private *p)
++{
++ 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("** 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)));
++ }
++ 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)));
+ }
++ 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_desc_dump(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 ocp_enet_private *fep = dev->priv;
+- int curr_slot;
++ unsigned long flags;
+
+- 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);
++ 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_mac_dump(struct net_device *dev)
++void mal_dbg_register(int idx, struct ibm_ocp_mal *mal)
+ {
+- struct ocp_enet_private *fep = dev->priv;
+- volatile emac_t *emacp = fep->emacp;
++ unsigned long flags;
+
+- 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);
++ if (idx >= sizeof(__mals) / sizeof(__mals[0])) {
++ printk(KERN_WARNING
++ "invalid index %d when registering MAL for debugging\n",
++ idx);
++ return;
+ }
++
++ 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();
+ }
+
+-void emac_serr_dump_1(struct net_device *dev)
++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)
+ {
+- struct ibm_ocp_mal *mal = ((struct ocp_enet_private *)dev->priv)->mal;
+- int mal_error = get_mal_dcrn(mal, DCRN_MALESR);
++ return register_sysrq_key('c', &emac_sysrq_op);
++}
+
+- 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");
+-}
+-
+-void emac_err_dump(struct net_device *dev, int em0isr)
+-{
+- printk(KERN_DEBUG "%s: on-chip ethernet error:\n", dev->name);
+-
+- 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");
++void __exit emac_fini_debug(void)
++{
++ unregister_sysrq_key('c', &emac_sysrq_op);
++}
+
+- emac_mac_dump(dev);
+- emac_mal_dump(dev);
++#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
+--- /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 at zultys.com> or <ebs at 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
+--- 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 at mvista.com
+- * Juen, 2002
++ * Memory Access Layer (MAL) support
++ *
++ * Copyright (c) 2004, 2005 Zultys Technologies.
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+ *
+- * Copyright 2002 MontaVista Softare Inc.
++ * Based on original work by
++ * Benjamin Herrenschmidt <benh at kernel.crashing.org>,
++ * David Gibson <hermes at gibson.dropbear.id.au>,
++ *
++ * Armin Kuster <akuster at 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;
+ }
+
+-static irqreturn_t mal_serr(int irq, void *dev_instance, struct pt_regs *regs)
++int mal_tx_bd_offset(struct ibm_ocp_mal *mal, int channel)
+ {
+- struct ibm_ocp_mal *mal = dev_instance;
+- unsigned long mal_error;
++ struct ocp_func_mal_data *maldata = mal->def->additions;
++ BUG_ON(channel < 0 || channel >= maldata->num_tx_chans);
++ return channel * NUM_TX_BUFF;
++}
+
+- /*
+- * This SERR applies to one of the devices on the MAL, here we charge
+- * it against the first EMAC registered for the MAL.
+- */
++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;
++}
+
+- mal_error = get_mal_dcrn(mal, DCRN_MALESR);
++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();
++}
+
+- printk(KERN_ERR "%s: System Error (MALESR=%lx)\n",
+- "MAL" /* FIXME: get the name right */ , mal_error);
++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);
++}
+
+- /* FIXME: decipher error */
+- /* DIXME: distribute to commacs, if possible */
++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();
++}
+
+- /* Clear the error status register */
+- set_mal_dcrn(mal, DCRN_MALESR, mal_error);
++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);
++}
+
+- return IRQ_HANDLED;
++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();
+ }
+
+-static irqreturn_t mal_txeob(int irq, void *dev_instance, struct pt_regs *regs)
++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;
+- struct list_head *l;
+- unsigned long isr;
++ u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
+- isr = get_mal_dcrn(mal, DCRN_MALTXEOBISR);
+- set_mal_dcrn(mal, DCRN_MALTXEOBISR, isr);
++ /* Clear the error status register */
++ set_mal_dcrn(mal, MAL_ESR, esr);
+
+- read_lock(&mal_list_lock);
+- list_for_each(l, &mal->commac) {
+- struct mal_commac *mc = list_entry(l, struct mal_commac, list);
++ 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 (isr & mc->tx_chan_mask) {
+- mc->ops->txeob(mc->dev, isr & mc->tx_chan_mask);
++ 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);
+ }
+- read_unlock(&mal_list_lock);
++ 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;
++ 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;
++ 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;
++}
+
+- isr = get_mal_dcrn(mal, DCRN_MALRXEOBISR);
+- set_mal_dcrn(mal, DCRN_MALRXEOBISR, isr);
++static irqreturn_t mal_txde(int irq, void *dev_instance, struct pt_regs *regs)
++{
++ struct ibm_ocp_mal *mal = dev_instance;
++ u32 deir = get_mal_dcrn(mal, MAL_TXDEIR);
++ set_mal_dcrn(mal, MAL_TXDEIR, deir);
+
+- read_lock(&mal_list_lock);
+- list_for_each(l, &mal->commac) {
+- struct mal_commac *mc = list_entry(l, struct mal_commac, list);
++ MAL_DBG("%d: txde %08x" NL, mal->def->index, deir);
+
+- if (isr & mc->rx_chan_mask) {
+- mc->ops->rxeob(mc->dev, isr & mc->rx_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;
+ }
+
+-static irqreturn_t mal_txde(int irq, void *dev_instance, struct pt_regs *regs)
++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;
+-
+- deir = get_mal_dcrn(mal, DCRN_MALTXDEIR);
++ u32 deir = get_mal_dcrn(mal, MAL_RXDEIR);
+
+- /* FIXME: print which MAL correctly */
+- printk(KERN_WARNING "%s: Tx descriptor error (MALTXDEIR=%lx)\n",
+- "MAL", deir);
++ MAL_DBG("%d: rxde %08x" NL, mal->def->index, 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->tx_chan_mask) {
+- mc->ops->txde(mc->dev, deir & mc->tx_chan_mask);
++ if (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;
+ }
+
+-/*
+- * 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)
++static int mal_poll(struct net_device *ndev, int *budget)
+ {
+- struct ibm_ocp_mal *mal = dev_instance;
++ struct ibm_ocp_mal *mal = ndev->priv;
+ struct list_head *l;
+- unsigned long deir;
++ int rx_work_limit = min(ndev->quota, *budget), received = 0, done;
+
+- deir = get_mal_dcrn(mal, DCRN_MALRXDEIR);
++ 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);
++ }
+
+- /*
+- * This really is needed. This case encountered in stress testing.
++ /* Process RX skbs.
++ * We _might_ need something more smart here to enforce polling fairness.
+ */
+- 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) {
+- struct mal_commac *mc = list_entry(l, struct mal_commac, list);
++ 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 ?
++ }
++ }
++ }
+
+- if (deir & mc->rx_chan_mask) {
+- mc->ops->rxde(mc->dev, deir & mc->rx_chan_mask);
++ /* 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);
+ }
+- read_unlock(&mal_list_lock);
+
+- return IRQ_HANDLED;
++ 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));
+-
+- 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();
+- }
+-
+- /**************************/
++ mal->dcrbase = maldata->dcr_base;
++ mal->def = ocpdev->def;
+
+- INIT_LIST_HEAD(&mal->commac);
++ 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);
+
+- set_mal_dcrn(mal, DCRN_MALRXCARR, 0xFFFFFFFF);
+- set_mal_dcrn(mal, DCRN_MALTXCARR, 0xFFFFFFFF);
++ INIT_LIST_HEAD(&mal->list);
+
+- 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);
+-
+- /* 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) {
++ set_mal_dcrn(mal, MAL_CFG, MAL_CFG_DEFAULT | MAL_CFG_PLBB |
++ MAL_CFG_OPBBL | MAL_CFG_LEA);
++
++ 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 */
+-
+- 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_tx_chans; ++i)
++ set_mal_dcrn(mal, MAL_TXCTPR(i), mal->bd_dma +
++ sizeof(struct mal_descriptor) *
++ mal_tx_bd_offset(mal, i));
++
++ 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);
+-
+- 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_reset(mal);
++
++ 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 @@ static struct ocp_driver mal_driver = {
+ .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
+--- 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 at zultys.com> or <ebs at ebshome.net>
++ *
++ * Based on original work by
++ * Armin Kuster <akuster at 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_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_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
+
+ 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;
+
+-#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)
+-{
+- set_mal_dcrn(mal, DCRN_MALTXCASR,
+- get_mal_dcrn(mal, DCRN_MALTXCASR) | chanmask);
+-}
+-
+-static inline void mal_disable_tx_channels(struct ibm_ocp_mal *mal,
+- u32 chanmask)
+-{
+- set_mal_dcrn(mal, DCRN_MALTXCARR, chanmask);
+-}
++ struct ocp_def *def;
++};
+
+-static inline void mal_enable_rx_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_MALRXCASR,
+- get_mal_dcrn(mal, DCRN_MALRXCASR) | chanmask);
++ return mfdcr(mal->dcrbase + reg);
+ }
+
+-static inline void mal_disable_rx_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_MALRXCARR, chanmask);
++ mtdcr(mal->dcrbase + reg, val);
+ }
+
+-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);
++/* Register MAL devices */
++int mal_init(void) __init;
++void mal_exit(void) __exit;
++
++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);
++
++/* 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);
++
++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);
++
++/* 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];
++};
+
+-extern int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel,
+- unsigned long size);
++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 */
++#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
+--- a/drivers/net/ibm_emac/ibm_emac_phy.c
++++ b/drivers/net/ibm_emac/ibm_emac_phy.c
+@@ -1,96 +1,80 @@
+ /*
+- * 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 at kernel.crashing.org)
++ * (c) 2004-2005, Eugene Surovegin <ebs at 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)
++{
++ return phy->mdio_read(phy->dev, phy->address, reg);
++}
++
++static inline void phy_write(struct mii_phy *phy, int reg, int val)
+ {
+- u16 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);
+-
+- return (limit <= 0);
+-}
+-
+-static int cis8201_init(struct mii_phy *phy)
+-{
+- u16 epcr;
+-
+- epcr = phy_read(phy, MII_CIS8201_EPCR);
+- epcr &= ~EPCR_MODE_MASK;
+-
+- switch (phy->mode) {
+- case PHY_MODE_TBI:
+- epcr |= EPCR_TBI_MODE;
+- break;
+- case PHY_MODE_RTBI:
+- epcr |= EPCR_RTBI_MODE;
+- break;
+- case PHY_MODE_GMII:
+- epcr |= EPCR_GMII_MODE;
+- break;
+- case PHY_MODE_RGMII:
+- default:
+- epcr |= EPCR_RGMII_MODE;
+- }
++ phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
+
+- phy_write(phy, MII_CIS8201_EPCR, epcr);
+-
+- return 0;
++ return limit <= 0;
+ }
+
+ static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
+ {
+- u16 ctl, adv;
++ int ctl, adv;
+
+- phy->autoneg = 1;
++ phy->autoneg = AUTONEG_ENABLE;
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
+- phy->pause = 0;
++ phy->pause = phy->asym_pause = 0;
+ phy->advertising = advertise;
+
+ /* Setup standard advertise */
+ adv = phy_read(phy, MII_ADVERTISE);
+- adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
++ 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)
+@@ -99,8 +83,25 @@ static int genmii_setup_aneg(struct mii_
+ 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);
+@@ -111,14 +112,16 @@ static int genmii_setup_aneg(struct mii_
+
+ static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
+ {
+- u16 ctl;
++ int ctl;
+
+- phy->autoneg = 0;
++ phy->autoneg = AUTONEG_DISABLE;
+ phy->speed = speed;
+ phy->duplex = fd;
+- phy->pause = 0;
++ 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 */
+@@ -132,6 +135,8 @@ static int genmii_setup_forced(struct mi
+ ctl |= BMCR_SPEED100;
+ break;
+ case SPEED_1000:
++ ctl |= BMCR_SPEED1000;
++ break;
+ default:
+ return -EINVAL;
+ }
+@@ -144,112 +149,143 @@ static int genmii_setup_forced(struct mi
+
+ static int genmii_poll_link(struct mii_phy *phy)
+ {
+- u16 status;
++ int status;
+
+- (void)phy_read(phy, MII_BMSR);
++ /* Clear latched value with dummy read */
++ phy_read(phy, MII_BMSR);
+ status = phy_read(phy, MII_BMSR);
+- if ((status & BMSR_LSTATUS) == 0)
++ if (status < 0 || (status & BMSR_LSTATUS) == 0)
+ return 0;
+- if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
++ if (phy->autoneg == AUTONEG_ENABLE && !(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)
++static int genmii_read_link(struct mii_phy *phy)
+ {
+- u16 acsr;
++ 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 (phy->autoneg) {
+- acsr = phy_read(phy, MII_CIS8201_ACSR);
++ if (glpa < 0 || adv < 0)
++ return adv;
+
+- if (acsr & ACSR_DUPLEX_STATUS)
++ 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 (acsr & ACSR_SPEED_1000BASET) {
++ if (bmcr & BMCR_SPEED1000)
+ phy->speed = SPEED_1000;
+- } else if (acsr & ACSR_SPEED_100BASET)
++ else if (bmcr & BMCR_SPEED100)
+ 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
+- */
+
++ phy->pause = phy->asym_pause = 0;
++ }
+ return 0;
+ }
+
+-static int genmii_read_link(struct mii_phy *phy)
++/* 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 lpa;
++ int epcr;
+
+- if (phy->autoneg) {
+- lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
++ epcr = phy_read(phy, MII_CIS8201_EPCR);
++ if (epcr < 0)
++ return epcr;
+
+- phy->speed = SPEED_10;
+- phy->duplex = DUPLEX_HALF;
+- phy->pause = 0;
++ epcr &= ~EPCR_MODE_MASK;
+
+- 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;
++ switch (phy->mode) {
++ case PHY_MODE_TBI:
++ epcr |= EPCR_TBI_MODE;
++ break;
++ case PHY_MODE_RTBI:
++ epcr |= EPCR_RTBI_MODE;
++ break;
++ case PHY_MODE_GMII:
++ epcr |= EPCR_GMII_MODE;
++ break;
++ case PHY_MODE_RGMII:
++ default:
++ epcr |= EPCR_RGMII_MODE;
+ }
+- /* On non-aneg, we assume what we put in BMCR is the speed,
+- * though magic-aneg shouldn't prevent this case from occurring
+- */
++
++ phy_write(phy, MII_CIS8201_EPCR, epcr);
+
+ 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 @@ static struct mii_phy_def *mii_phy_table
+ 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;
+-
+- /* Take PHY out of isloate mode and reset it. */
+- rc = reset_one_mii_phy(phy, mii_id);
+- if (rc)
++ phy->address = address;
++ phy->speed = SPEED_10;
++ phy->duplex = DUPLEX_HALF;
++ phy->pause = phy->asym_pause = 0;
++
++ /* 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
+--- 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
+ *
+- * Benjamin Herrenschmidt <benh at kernel.crashing.org>
+- * February 2003
+- *
+- * 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.
++ * Driver for PowerPC 4xx on-chip ethernet controller, PHY support
+ *
+- * 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.
++ * Benjamin Herrenschmidt <benh at kernel.crashing.org>
++ * February 2003
+ *
+- * 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.
++ * Minor additions by Eugene Surovegin <ebs at 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 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_ops {
+ 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 @@ struct mii_phy_def {
+ /* 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 @@ struct mii_phy {
+ 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);
+-
+-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);
+-}
++int mii_phy_probe(struct mii_phy *phy, int address);
++int mii_reset_phy(struct mii_phy *phy);
+
+-#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
+--- /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 at zultys.com> or <ebs at ebshome.net>
++ *
++ * Based on original work by
++ * Matt Porter <mporter at 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
+--- 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 at mvista.com
+@@ -7,6 +9,9 @@
+ * Copyright 2004 MontaVista Software, Inc.
+ * Matt Porter <mporter at kernel.crashing.org>
+ *
++ * Copyright (c) 2004, 2005 Zultys Technologies.
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at 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
+-
+-/* Speed Selection reg */
+-
+-#define RGMII_SP2_100 0x00000002
+-#define RGMII_SP2_1000 0x00000004
+-#define RGMII_SP3_100 0x00000200
+-#define RGMII_SP3_1000 0x00000400
+-
+-#define RGMII_MII2_SPDMASK 0x00000007
+-#define RGMII_MII3_SPDMASK 0x00000700
+-
+-#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
++#ifdef CONFIG_IBM_EMAC_RGMII
++int rgmii_attach(void *emac) __init;
++
++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);
++}
++
++void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed);
++
++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;
++}
++
++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
+--- /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 at kernel.crashing.org>
++ *
++ * Copyright (c) 2005 Eugene Surovegin <ebs at 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
+--- 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 at kernel.crashing.org>
+ *
++ * Copyright (c) 2005 Eugene Surovegin <ebs at 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
+--- /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 at zultys.com> or <ebs at ebshome.net>
++ *
++ * Based on original work by
++ * Armin Kuster <akuster at 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
+--- 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 at mvista.com
+- * Dec, 2001
++ * Copyright (c) 2004, 2005 Zultys Technologies.
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+ *
+- * Copyright 2001 MontaVista Softare Inc.
++ * Based on original work by
++ * Armin Kuster <akuster at 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 @@ struct zmii_regs {
+ 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 */
+-
+-#define ZMII_FER_MASK(x) (0xf0000000 >> (4*x))
++#ifdef CONFIG_IBM_EMAC_ZMII
++int zmii_attach(void *emac) __init;
+
+-#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
+-
+-/* Speed Selection reg */
+-
+-#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
+-
+-#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
+-
+-/* 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
++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);
++}
++
++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);
++}
++
++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);
++}
++
++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;
++}
++
++void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf);
++
++#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
+--- a/drivers/net/ibmveth.c
++++ b/drivers/net/ibmveth.c
+@@ -96,7 +96,7 @@ static void ibmveth_proc_unregister_driv
+ 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 @@ static int ibmveth_alloc_buffer_pool(str
+ atomic_set(&pool->available, 0);
+ pool->producer_index = 0;
+ pool->consumer_index = 0;
++ pool->active = 0;
+
+ return 0;
+ }
+@@ -236,7 +237,7 @@ static void ibmveth_replenish_buffer_poo
+ 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 @@ static void ibmveth_replenish_buffer_poo
+ 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 @@ static void ibmveth_free_buffer_pool(str
+ {
+ 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 @@ static void ibmveth_free_buffer_pool(str
+ kfree(pool->skbuff);
+ pool->skbuff = NULL;
+ }
++ pool->active = 0;
+ }
+
+ /* remove a buffer from a pool */
+@@ -379,6 +361,12 @@ static void ibmveth_rxq_recycle_buffer(s
+ 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 inline void ibmveth_rxq_harvest_b
+
+ 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 @@ static void ibmveth_cleanup(struct ibmve
+ 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 @@ static int ibmveth_open(struct net_devic
+ 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;
+@@ -532,7 +514,7 @@ static int ibmveth_open(struct net_devic
+
+ if(lpar_rc != H_Success) {
+ ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
+- ibmveth_error_printk("buffer TCE:0x%x filter TCE:0x%x rxq desc:0x%lx MAC:0x%lx\n",
++ ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
+ adapter->buffer_list_dma,
+ adapter->filter_list_dma,
+ rxq_desc.desc,
+@@ -552,10 +534,10 @@ static int ibmveth_open(struct net_devic
+ return rc;
+ }
+
+- netif_start_queue(netdev);
++ ibmveth_debug_printk("initial replenish cycle\n");
++ ibmveth_interrupt(netdev->irq, netdev, NULL);
+
+- 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 @@ static int ibmveth_close(struct net_devi
+
+ 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 @@ static int ibmveth_start_xmit(struct sk_
+ 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 @@ static int ibmveth_start_xmit(struct sk_
+
+ 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 @@ static int ibmveth_start_xmit(struct sk_
+
+ 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 @@ static int ibmveth_start_xmit(struct sk_
+ DMA_TO_DEVICE);
+ curfrag++;
+ }
+- dev_kfree_skb(skb);
+- return 0;
++ goto out;
+ }
+ }
+
+@@ -720,11 +703,12 @@ static int ibmveth_start_xmit(struct sk_
+ 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 @@ static int ibmveth_start_xmit(struct sk_
+ 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 @@ static int ibmveth_poll(struct net_devic
+ 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 void ibmveth_set_multicast_list(s
+
+ 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 @@ static int __devinit ibmveth_probe(struc
+ 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);
+@@ -1146,14 +1174,16 @@ static struct vio_device_id ibmveth_devi
+ { "network", "IBM,l-lan"},
+ { "", "" }
+ };
+-
+ MODULE_DEVICE_TABLE(vio, ibmveth_device_table);
+
+ static struct vio_driver ibmveth_driver = {
+- .name = (char *)ibmveth_driver_name,
+- .id_table = ibmveth_device_table,
+- .probe = ibmveth_probe,
+- .remove = ibmveth_remove
++ .id_table = ibmveth_device_table,
++ .probe = ibmveth_probe,
++ .remove = ibmveth_remove,
++ .driver = {
++ .name = ibmveth_driver_name,
++ .owner = THIS_MODULE,
++ }
+ };
+
+ static int __init ibmveth_module_init(void)
+diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
+--- 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 @@ struct ibmveth_buff_pool {
+ u16 *free_map;
+ dma_addr_t *dma_addr;
+ struct sk_buff **skbuff;
++ int active;
+ };
+
+ struct ibmveth_rx_q {
+@@ -114,10 +118,6 @@ struct ibmveth_adapter {
+ 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 @@ struct ibmveth_adapter {
+ 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
+--- a/drivers/net/irda/Kconfig
++++ b/drivers/net/irda/Kconfig
+@@ -400,5 +400,15 @@ config VIA_FIR
+ 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
+--- a/drivers/net/irda/Makefile
++++ b/drivers/net/irda/Makefile
+@@ -18,6 +18,7 @@ obj-$(CONFIG_SMC_IRCC_FIR) += smsc-ircc2
+ 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
+--- a/drivers/net/irda/donauboe.c
++++ b/drivers/net/irda/donauboe.c
+@@ -1695,11 +1695,9 @@ toshoboe_open (struct pci_dev *pci_dev,
+
+ 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
+--- a/drivers/net/irda/irda-usb.c
++++ b/drivers/net/irda/irda-usb.c
+@@ -1168,10 +1168,8 @@ static inline void irda_usb_close(struct
+ 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
+--- a/drivers/net/irda/irport.c
++++ b/drivers/net/irda/irport.c
+@@ -235,8 +235,7 @@ static int irport_close(struct irport_cb
+ __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
+--- /dev/null
++++ b/drivers/net/irda/pxaficp_ir.c
+@@ -0,0 +1,866 @@
++/*
++ * 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/platform_device.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
+--- a/drivers/net/irda/sa1100_ir.c
++++ b/drivers/net/irda/sa1100_ir.c
+@@ -29,7 +29,7 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <net/irda/irda.h>
+@@ -291,12 +291,12 @@ static void sa1100_irda_shutdown(struct
+ /*
+ * 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 @@ static int sa1100_irda_suspend(struct de
+ /*
+ * 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
+--- a/drivers/net/irda/sir_dev.c
++++ b/drivers/net/irda/sir_dev.c
+@@ -490,8 +490,7 @@ static void sirdev_free_buffers(struct s
+ {
+ 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
+--- a/drivers/net/irda/smsc-ircc2.c
++++ b/drivers/net/irda/smsc-ircc2.c
+@@ -53,6 +53,7 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/serial_reg.h>
+ #include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/dma.h>
+@@ -213,8 +214,8 @@ static int smsc_ircc_probe_transceiver_
+
+ /* 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 +639,14 @@ static void smsc_ircc_setup_qos(struct s
+ */
+ 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 +660,10 @@ static void smsc_ircc_init_chip(struct s
+ 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 +1550,46 @@ static int ircc_is_receiving(struct smsc
+ }
+ #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 +1601,6 @@ static int smsc_ircc_net_open(struct net
+ {
+ struct smsc_ircc_cb *self;
+ char hwname[16];
+- unsigned long flags;
+
+ IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+@@ -1575,6 +1608,11 @@ static int smsc_ircc_net_open(struct net
+ 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 +1620,7 @@ static int smsc_ircc_net_open(struct net
+ 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 +1673,63 @@ static int smsc_ircc_net_close(struct ne
+ 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 +1742,6 @@ static int smsc_ircc_resume(struct devic
+ */
+ 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 +1751,7 @@ static int __exit smsc_ircc_close(struct
+ /* 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
+--- a/drivers/net/irda/stir4200.c
++++ b/drivers/net/irda/stir4200.c
+@@ -678,10 +678,9 @@ static void turnaround_delay(const struc
+ 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
+--- a/drivers/net/irda/vlsi_ir.c
++++ b/drivers/net/irda/vlsi_ir.c
+@@ -473,8 +473,7 @@ static int vlsi_free_ring(struct vlsi_ri
+ 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/iseries_veth.c b/drivers/net/iseries_veth.c
+--- a/drivers/net/iseries_veth.c
++++ b/drivers/net/iseries_veth.c
+@@ -70,8 +70,9 @@
+ #include <linux/delay.h>
+ #include <linux/mm.h>
+ #include <linux/ethtool.h>
++
++#include <asm/abs_addr.h>
+ #include <asm/iSeries/mf.h>
+-#include <asm/iSeries/iSeries_pci.h>
+ #include <asm/uaccess.h>
+
+ #include <asm/iSeries/HvLpConfig.h>
+@@ -1397,13 +1398,13 @@ static inline void veth_build_dma_list(s
+ * it just at the granularity of iSeries real->absolute
+ * mapping? Indeed, given the way the allocator works, can we
+ * count on them being absolutely contiguous? */
+- list[0].addr = ISERIES_HV_ADDR(p);
++ list[0].addr = iseries_hv_addr(p);
+ list[0].size = min(length,
+ PAGE_SIZE - ((unsigned long)p & ~PAGE_MASK));
+
+ done = list[0].size;
+ while (done < length) {
+- list[i].addr = ISERIES_HV_ADDR(p + done);
++ list[i].addr = iseries_hv_addr(p + done);
+ list[i].size = min(length-done, PAGE_SIZE);
+ done += list[i].size;
+ i++;
+@@ -1496,8 +1497,8 @@ static void veth_receive(struct veth_lpa
+ cnx->dst_inst,
+ HvLpDma_AddressType_RealAddress,
+ HvLpDma_AddressType_TceIndex,
+- ISERIES_HV_ADDR(&local_list),
+- ISERIES_HV_ADDR(&remote_list),
++ iseries_hv_addr(&local_list),
++ iseries_hv_addr(&remote_list),
+ length);
+ if (rc != HvLpDma_Rc_Good) {
+ dev_kfree_skb_irq(skb);
+@@ -1647,10 +1648,13 @@ static struct vio_device_id veth_device_
+ MODULE_DEVICE_TABLE(vio, veth_device_table);
+
+ static struct vio_driver veth_driver = {
+- .name = DRV_NAME,
+ .id_table = veth_device_table,
+ .probe = veth_probe,
+- .remove = veth_remove
++ .remove = veth_remove,
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ }
+ };
+
+ /*
+diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
+--- a/drivers/net/ixgb/ixgb_ethtool.c
++++ b/drivers/net/ixgb/ixgb_ethtool.c
+@@ -645,11 +645,10 @@ ixgb_phys_id(struct net_device *netdev,
+
+ 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 @@ struct ethtool_ops ixgb_ethtool_ops = {
+ .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
+--- a/drivers/net/ixgb/ixgb_main.c
++++ b/drivers/net/ixgb/ixgb_main.c
+@@ -460,8 +460,9 @@ ixgb_probe(struct pci_dev *pdev,
+ }
+
+ 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/jazzsonic.c b/drivers/net/jazzsonic.c
+--- a/drivers/net/jazzsonic.c
++++ b/drivers/net/jazzsonic.c
+@@ -33,7 +33,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <asm/bootinfo.h>
+diff --git a/drivers/net/lance.c b/drivers/net/lance.c
+--- a/drivers/net/lance.c
++++ b/drivers/net/lance.c
+@@ -298,7 +298,7 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_
+ 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 @@ lance_purge_ring(struct net_device *dev)
+
+ /* 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
+--- a/drivers/net/lasi_82596.c
++++ b/drivers/net/lasi_82596.c
+@@ -415,6 +415,10 @@ static int rx_ring_size = RX_RING_SIZE;
+ 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 @@ static int init_i596_mem(struct net_devi
+
+ 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 @@ static int __devinit i82596_probe(struct
+ 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 @@ static int __devinit i82596_probe(struct
+ 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 @@ lan_init_chip(struct parisc_device *dev)
+
+ 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 @@ static struct parisc_device_id lan_tbl[]
+ 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
+--- a/drivers/net/lne390.c
++++ b/drivers/net/lne390.c
+@@ -298,7 +298,7 @@ static int __init lne390_probe1(struct n
+ 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
+--- a/drivers/net/mace.c
++++ b/drivers/net/mace.c
+@@ -1016,6 +1016,7 @@ static struct of_device_id mace_match[]
+ },
+ {},
+ };
++MODULE_DEVICE_TABLE (of, mace_match);
+
+ static struct macio_driver mace_driver =
+ {
+@@ -1035,10 +1036,8 @@ static void __exit mace_cleanup(void)
+ {
+ 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/macsonic.c b/drivers/net/macsonic.c
+--- a/drivers/net/macsonic.c
++++ b/drivers/net/macsonic.c
+@@ -47,7 +47,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <asm/bootinfo.h>
+diff --git a/drivers/net/mii.c b/drivers/net/mii.c
+--- a/drivers/net/mii.c
++++ b/drivers/net/mii.c
+@@ -207,6 +207,20 @@ int mii_ethtool_sset(struct mii_if_info
+ 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_gset);
+ 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
+--- /dev/null
++++ b/drivers/net/mipsnet.c
+@@ -0,0 +1,372 @@
++/*
++ * 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 <linux/platform_device.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
+--- /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/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
+--- a/drivers/net/mv643xx_eth.c
++++ b/drivers/net/mv643xx_eth.c
+@@ -39,6 +39,8 @@
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+ #include <linux/ethtool.h>
++#include <linux/platform_device.h>
++
+ #include <asm/io.h>
+ #include <asm/types.h>
+ #include <asm/pgtable.h>
+@@ -1533,6 +1535,9 @@ static int mv643xx_eth_probe(struct devi
+ printk(KERN_NOTICE "%s: RX NAPI Enabled \n", dev->name);
+ #endif
+
++ if (mp->tx_sram_size > 0)
++ printk(KERN_NOTICE "%s: Using SRAM\n", dev->name);
++
+ return 0;
+
+ out:
+diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
+--- a/drivers/net/myri_sbus.c
++++ b/drivers/net/myri_sbus.c
+@@ -277,7 +277,7 @@ static void myri_init_rings(struct myri_
+ 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
+--- a/drivers/net/myri_sbus.h
++++ b/drivers/net/myri_sbus.h
+@@ -296,7 +296,7 @@ struct myri_eth {
+ /* 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
+--- a/drivers/net/ne.c
++++ b/drivers/net/ne.c
+@@ -54,6 +54,10 @@ static const char version2[] =
+ #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 @@ bad_clone_list[] __initdata = {
+ {"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 @@ struct net_device * __init ne_probe(int
+ 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 @@ static int __init ne_probe1(struct net_d
+ 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
+--- a/drivers/net/ne2k-pci.c
++++ b/drivers/net/ne2k-pci.c
+@@ -372,6 +372,7 @@ static int __devinit ne2k_pci_init_one (
+ 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 @@ static struct ethtool_ops ne2k_pci_ethto
+ .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 @@ static int ne2k_pci_resume (struct pci_d
+ 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
+--- a/drivers/net/ni65.c
++++ b/drivers/net/ni65.c
+@@ -696,8 +696,7 @@ static void ni65_free_buffer(struct priv
+ 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 @@ static void ni65_free_buffer(struct priv
+ 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
+--- a/drivers/net/ns83820.c
++++ b/drivers/net/ns83820.c
+@@ -1632,8 +1632,7 @@ static void ns83820_run_bist(struct net_
+ 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
+--- a/drivers/net/pcmcia/pcnet_cs.c
++++ b/drivers/net/pcmcia/pcnet_cs.c
+@@ -1020,6 +1020,12 @@ static void set_misc_reg(struct net_devi
+ } 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
+--- 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 @@ static int homepna[MAX_UNITS];
+ * 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 at tw.ibm.c0m> added set_ringparam().
++ * v1.31a 12 Sep 2005 Hubert WS Lin <wslin at tw.ibm.c0m> set min ring size to 4
++ * to allow loopback test to work unchanged.
+ */
+
+
+@@ -266,17 +269,17 @@ static int homepna[MAX_UNITS];
+ * 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 @@ struct pcnet32_access {
+ };
+
+ /*
+- * 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 @@ struct pcnet32_private {
+ 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 int pcnet32_get_regs_len(struct n
+ 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 @@ static void pcnet32_get_ringparam(struct
+ {
+ 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 @@ static struct ethtool_ops pcnet32_ethtoo
+ .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 @@ static struct ethtool_ops pcnet32_ethtoo
+ .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 @@ pcnet32_probe1(unsigned long ioaddr, int
+ 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 @@ pcnet32_probe1(unsigned long ioaddr, int
+ 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 @@ pcnet32_probe1(unsigned long ioaddr, int
+ }
+ 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 @@ pcnet32_probe1(unsigned long ioaddr, int
+ 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 @@ pcnet32_probe1(unsigned long ioaddr, int
+
+ /* 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 @@ pcnet32_probe1(unsigned long ioaddr, int
+
+ 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 @@ err_release_region:
+ }
+
+
++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 @@ pcnet32_open(struct net_device *dev)
+ 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 @@ pcnet32_open(struct net_device *dev)
+
+ 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 @@ err_free_ring:
+ 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 @@ pcnet32_purge_tx_ring(struct net_device
+ 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 @@ pcnet32_init_ring(struct net_device *dev
+ 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 @@ pcnet32_init_ring(struct net_device *dev
+ }
+ /* 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 @@ pcnet32_tx_timeout (struct net_device *d
+ 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 @@ pcnet32_start_xmit(struct sk_buff *skb,
+ /* 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 @@ pcnet32_start_xmit(struct sk_buff *skb,
+
+ 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 @@ pcnet32_interrupt(int irq, void *dev_id,
+ 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 @@ pcnet32_interrupt(int irq, void *dev_id,
+ 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 @@ static int
+ 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 @@ pcnet32_rx(struct net_device *dev)
+ 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 @@ pcnet32_rx(struct net_device *dev)
+ 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 @@ pcnet32_close(struct net_device *dev)
+ 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 @@ pcnet32_close(struct net_device *dev)
+ 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 @@ static void __devexit pcnet32_remove_one
+ 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 @@ static void __exit pcnet32_cleanup_modul
+ 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
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -12,14 +12,6 @@ config PHYLIB
+ 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
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -133,13 +133,9 @@ static int mdio_bus_suspend(struct devic
+ 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 @@ static int mdio_bus_resume(struct device
+ 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
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -242,10 +242,6 @@ EXPORT_SYMBOL(phy_sanitize_settings);
+ * 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 @@ int phy_start_aneg(struct phy_device *ph
+
+ err = phydev->drv->config_aneg(phydev);
+
+-#ifdef CONFIG_PHYCONTROL
+ if (err < 0)
+ goto out_unlock;
+
+@@ -395,14 +390,12 @@ int phy_start_aneg(struct phy_device *ph
+ }
+
+ 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 @@ static void phy_timer(unsigned long data
+ 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
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -101,7 +101,6 @@ struct phy_device * get_phy_device(struc
+ return dev;
+ }
+
+-#ifdef CONFIG_PHYCONTROL
+ /* phy_prepare_link:
+ *
+ * description: Tells the PHY infrastructure to handle the
+@@ -160,8 +159,6 @@ void phy_disconnect(struct phy_device *p
+ }
+ 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
+--- a/drivers/net/ppp_generic.c
++++ b/drivers/net/ppp_generic.c
+@@ -863,7 +863,7 @@ static int __init ppp_init(void)
+ 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
+--- a/drivers/net/r8169.c
++++ b/drivers/net/r8169.c
+@@ -1027,6 +1027,7 @@ static struct ethtool_ops rtl8169_ethtoo
+ .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 @@ rtl8169_init_one(struct pci_dev *pdev, c
+ /* 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
+--- /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 at kernel.crashing.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#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 at 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
+--- a/drivers/net/rrunner.c
++++ b/drivers/net/rrunner.c
+@@ -1710,10 +1710,8 @@ static int rr_ioctl(struct net_device *d
+ 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
+--- a/drivers/net/s2io-regs.h
++++ b/drivers/net/s2io-regs.h
+@@ -814,6 +814,17 @@ typedef struct _XENA_dev_config {
+ 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
+--- 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 @@ static unsigned int indicate_max_pkts;
+ #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 @@ static void free_shared_mem(struct s2io_
+ }
+ 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 @@ static int init_nic(struct s2io_nic *nic
+ 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 @@ static int init_nic(struct s2io_nic *nic
+ #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 @@ static int start_nic(struct s2io_nic *ni
+ }
+
+ /* 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 @@ static void tx_intr_handler(fifo_info_t
+ 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 @@ void s2io_reset(nic_t * sp)
+ /* 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 @@ int s2io_set_swapper(nic_t * sp)
+ 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 @@ int s2io_set_swapper(nic_t * sp)
+ 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 @@ int s2io_set_swapper(nic_t * sp)
+ 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 @@ int s2io_open(struct net_device *dev)
+ {
+ 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 @@ int s2io_open(struct net_device *dev)
+ 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 @@ int s2io_open(struct net_device *dev)
+ 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 @@ hw_init_failed:
+ 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 @@ s2io_alarm_handle(unsigned long data)
+ 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 @@ static void s2io_ethtool_gdrvinfo(struct
+ {
+ 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 @@ static int s2io_ethtool_setpause_data(st
+ */
+
+ #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);
+-
+- while (exit_cnt < 5) {
+- val64 = readq(&bar0->i2c_control);
+- if (I2C_CONTROL_CNTL_END(val64)) {
+- *data = I2C_CONTROL_GET_DATA(val64);
+- ret = 0;
+- break;
++ 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;
++ }
++ 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 @@ static int read_eeprom(nic_t * sp, int o
+ * 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);
+-
+- while (exit_cnt < 5) {
+- val64 = readq(&bar0->i2c_control);
+- if (I2C_CONTROL_CNTL_END(val64)) {
+- if (!(val64 & I2C_CONTROL_NACK))
+- ret = 0;
+- break;
++ 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;
++ }
++ 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 write_eeprom(nic_t * sp, int
+ 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 @@ static int s2io_ethtool_seeprom(struct n
+ 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_ethtool_seeprom(struct n
+ 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 @@ static int s2io_register_test(nic_t * sp
+ }
+
+ 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 @@ static int s2io_register_test(nic_t * sp
+ }
+
+ *data = fail;
+- return 0;
++ return fail;
+ }
+
+ /**
+@@ -4209,58 +4662,83 @@ static int s2io_register_test(nic_t * sp
+ 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))
+- fail = 1;
++ if (sp->device_type == XFRAME_I_DEVICE)
++ if (!write_eeprom(sp, 0x07C, 0, 3))
++ fail = 1;
+
+- /* Test Write Request at offset 0x7fc */
+- if (write_eeprom(sp, 0x7FC, 0x01234567, 3))
++ /* Test Write Request at offset 0x7f0 */
++ if (write_eeprom(sp, 0x7F0, 0x012345, 3))
+ fail = 1;
+- if (read_eeprom(sp, 0x7FC, &ret_data))
++ if (read_eeprom(sp, 0x7F0, &ret_data))
+ fail = 1;
+
+- if (ret_data != 0x01234567)
++ 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;
++ }
+
+ /* Reset the EEPROM data go FFFF */
+- write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3);
+-
+- /* 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;
++ write_eeprom(sp, 0x7F0, 0xFFFFFF, 3);
+
+- /* 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;
++ 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 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;
++ }
++
++ /* 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 @@ static int s2io_rldram_test(nic_t * sp,
+ {
+ 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 @@ static int s2io_rldram_test(nic_t * sp,
+
+ 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 @@ static int s2io_rldram_test(nic_t * sp,
+ }
+ 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 @@ static int s2io_rldram_test(nic_t * sp,
+ 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 @@ static int s2io_rldram_test(nic_t * sp,
+ 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 void s2io_card_down(nic_t * sp)
+
+ 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 @@ static int s2io_card_up(nic_t * sp)
+ 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 @@ static void s2io_init_pci(nic_t * sp)
+
+ MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik at 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(bimodal, bool, 0);
+ 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 @@ s2io_init_nic(struct pci_dev *pdev, cons
+ 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 @@ s2io_init_nic(struct pci_dev *pdev, cons
+ 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 @@ s2io_init_nic(struct pci_dev *pdev, cons
+ 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 @@ s2io_init_nic(struct pci_dev *pdev, cons
+ else
+ sp->device_type = XFRAME_I_DEVICE;
+
++
+ /* Initialize some PCI/PCI-X fields of the NIC. */
+ s2io_init_pci(sp);
+
+@@ -5571,12 +6087,23 @@ s2io_init_nic(struct pci_dev *pdev, cons
+ 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 @@ s2io_init_nic(struct pci_dev *pdev, cons
+ } 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 @@ s2io_init_nic(struct pci_dev *pdev, cons
+ 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 @@ static void __devexit s2io_rem_nic(struc
+ 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
+--- a/drivers/net/s2io.h
++++ b/drivers/net/s2io.h
+@@ -652,6 +652,30 @@ typedef struct {
+ #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 @@ struct s2io_nic {
+ * 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 @@ struct s2io_nic {
+ 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 int s2io_poll(struct net_device *
+ 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 @@ int s2io_set_swapper(nic_t * sp);
+ 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
+--- a/drivers/net/saa9730.c
++++ b/drivers/net/saa9730.c
+@@ -997,10 +997,7 @@ static void __devexit saa9730_remove_one
+
+ 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 @@ static int lan_saa9730_init(struct net_d
+ 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
+--- 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 @@ MODULE_PARM_DESC(int_timeout, "Timeout v
+ ********************************************************************* */
+
+
+-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_duplex_auto, sbmac_
+ 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 @@ typedef enum { sbmac_state_uninit, sbmac
+
+ #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 unsigned long paddr_t;
+ ********************************************************************* */
+
+ 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 @@ typedef struct sbmacdma_s {
+ 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 @@ typedef struct sbmacdma_s {
+ ********************************************************************* */
+
+ 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 @@ struct sbmac_softc {
+ 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 void sbmac_set_rx_mode(struct net
+ 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 @@ static uint64_t sbmac_orig_hwaddr[MAX_UN
+
+ #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 @@ static uint64_t sbmac_orig_hwaddr[MAX_UN
+
+ /**********************************************************************
+ * 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 @@ static void sbmac_mii_sync(struct sbmac_
+ 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 @@ static void sbmac_mii_senddata(struct sb
+ 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 @@ static void sbmac_mii_senddata(struct sb
+
+ /**********************************************************************
+ * 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 @@ static unsigned int sbmac_mii_read(struc
+ * 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 @@ static unsigned int sbmac_mii_read(struc
+ * 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 @@ static unsigned int sbmac_mii_read(struc
+
+ /**********************************************************************
+ * 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 @@ static void sbmac_mii_write(struct sbmac
+ 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 @@ static void sbmac_mii_write(struct sbmac
+ 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 @@ static void sbdma_initctx(sbmacdma_t *d,
+ 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 @@ static void sbdma_initctx(sbmacdma_t *d,
+ } else {
+ d->sbdma_int_pktcnt = 1;
+ }
+-
++
+ if ( int_timeout ) {
+ d->sbdma_int_timeout = int_timeout;
+ } else {
+@@ -789,13 +769,13 @@ static void sbdma_initctx(sbmacdma_t *d,
+
+ /**********************************************************************
+ * 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 @@ static void sbdma_channel_start(sbmacdma
+ /*
+ * 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 @@ static void sbdma_channel_start(sbmacdma
+
+ /**********************************************************************
+ * 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 @@ static void sbdma_channel_stop(sbmacdma_
+ /*
+ * 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 @@ static int sbdma_add_rcvbuffer(sbmacdma_
+ 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 @@ static int sbdma_add_rcvbuffer(sbmacdma_
+ *
+ * 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 @@ static int sbdma_add_rcvbuffer(sbmacdma_
+ * 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 @@ static int sbdma_add_rcvbuffer(sbmacdma_
+ }
+ 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 @@ static int sbdma_add_rcvbuffer(sbmacdma_
+
+ /* 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 @@ static int sbdma_add_txbuffer(sbmacdma_t
+ 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 @@ static int sbdma_add_txbuffer(sbmacdma_t
+
+ /**********************************************************************
+ * 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 @@ static void sbdma_emptyring(sbmacdma_t *
+ {
+ 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 @@ static void sbdma_emptyring(sbmacdma_t *
+
+ /**********************************************************************
+ * 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_emptyring(sbmacdma_t *
+ 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 @@ static void sbdma_fillring(sbmacdma_t *d
+
+ /**********************************************************************
+ * SBDMA_RX_PROCESS(sc,d)
+- *
+- * Process "completed" receive buffers on the specified DMA channel.
++ *
++ * 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.
++ * 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
+ ********************************************************************* */
+@@ -1163,56 +1139,56 @@ static void sbdma_rx_process(struct sbma
+ 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 @@ static void sbdma_rx_process(struct sbma
+ * 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 @@ static void sbdma_rx_process(struct sbma
+ sb->ip_summed = CHECKSUM_NONE;
+ }
+ }
+-
++
+ netif_rx(sb);
+ }
+ } else {
+@@ -1251,14 +1227,14 @@ static void sbdma_rx_process(struct sbma
+ 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 @@ static void sbdma_rx_process(struct sbma
+
+ /**********************************************************************
+ * 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 @@ static void sbdma_tx_process(struct sbma
+ 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 @@ static void sbdma_tx_process(struct sbma
+ * 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 @@ static int sbmac_initctx(struct sbmac_so
+ 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 @@ static void sbdma_uninitctx(struct sbmac
+ kfree(d->sbdma_dscrtable);
+ d->sbdma_dscrtable = NULL;
+ }
+-
++
+ if (d->sbdma_ctxtable) {
+ kfree(d->sbdma_ctxtable);
+ d->sbdma_ctxtable = NULL;
+@@ -1447,12 +1423,12 @@ static void sbmac_uninitctx(struct sbmac
+
+ /**********************************************************************
+ * 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_uninitctx(struct sbmac
+ 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 @@ static void sbmac_channel_start(struct s
+ 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 @@ static void sbmac_channel_start(struct s
+ * 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
++
++ /*
++ * Enable receiving unicasts and broadcasts
+ */
+-
+- SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN);
+-
++
++ __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
++
+ /*
+- * we're running now.
++ * 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_start(struct s
+ 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 @@ static sbmac_state_t sbmac_set_channel_s
+ 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 sbmac_state_t sbmac_set_channel_s
+ 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_promiscuous_mode(struc
+ 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 @@ static void sbmac_set_iphdr_offset(struc
+
+ /**********************************************************************
+ * 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 void sbmac_set_iphdr_offset(struc
+ 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 @@ static int sbmac_set_speed(struct sbmac_
+ /*
+ * 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 @@ static int sbmac_set_speed(struct sbmac_
+ 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 @@ static int sbmac_set_speed(struct sbmac_
+ 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 @@ static int sbmac_set_speed(struct sbmac_
+ 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_speed(struct sbmac_
+ 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 @@ static int sbmac_set_duplex(struct sbmac
+ /* 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 @@ static int sbmac_set_duplex(struct sbmac
+
+ /**********************************************************************
+ * SBMAC_INTR()
+- *
++ *
+ * Interrupt handler for MAC interrupts
+- *
+- * Input parameters:
++ *
++ * Input parameters:
+ * MAC structure
+- *
++ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+@@ -2066,27 +2039,27 @@ static irqreturn_t sbmac_intr(int irq,vo
+ 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 @@ static irqreturn_t sbmac_intr(int irq,vo
+ * 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 @@ static irqreturn_t sbmac_intr(int irq,vo
+
+ /**********************************************************************
+ * 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 @@ static int sbmac_start_tx(struct sk_buff
+
+ 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 int sbmac_start_tx(struct sk_buff
+ 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 @@ static void sbmac_setmulti(struct sbmac_
+ #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 void sbmac_setmulti(struct sbmac_
+ 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 @@ static int sbmac_parse_xdigit(char str)
+ 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 @@ static int sbmac_parse_hwaddr(char *str,
+ {
+ int digit1,digit2;
+ int idx = 6;
+-
++
+ while (*str && (idx > 0)) {
+ digit1 = sbmac_parse_xdigit(*str);
+ if (digit1 < 0)
+@@ -2302,7 +2275,7 @@ static int sbmac_parse_hwaddr(char *str,
+ str++;
+ if (!*str)
+ return -1;
+-
++
+ if ((*str == ':') || (*str == '-')) {
+ digit2 = digit1;
+ digit1 = 0;
+@@ -2313,10 +2286,10 @@ static int sbmac_parse_hwaddr(char *str,
+ return -1;
+ str++;
+ }
+-
++
+ *hwaddr++ = (digit1 << 4) | digit2;
+ idx--;
+-
++
+ if (*str == '-')
+ str++;
+ if (*str == ':')
+@@ -2337,12 +2310,12 @@ static int sb1250_change_mtu(struct net_
+
+ /**********************************************************************
+ * 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 @@ static int sbmac_init(struct net_device
+ 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 @@ static int sbmac_init(struct net_device
+ 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 @@ static int sbmac_init(struct net_device
+ * 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 @@ out_uninit:
+ 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 @@ static void sbmac_timer(unsigned long da
+ 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 @@ static void sbmac_timer(unsigned long da
+ 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_timer(unsigned long da
+ 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 @@ static struct net_device_stats *sbmac_ge
+ {
+ 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 @@ static void sbmac_set_rx_mode(struct net
+ /*
+ * 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 @@ static void sbmac_set_rx_mode(struct net
+ }
+ }
+ 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 @@ static int sbmac_mii_ioctl(struct net_de
+ 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 @@ static int sbmac_mii_ioctl(struct net_de
+ default:
+ retval = -EOPNOTSUPP;
+ }
+-
++
+ spin_unlock_irqrestore(&sc->sbm_lock, flags);
+ return retval;
+ }
+@@ -2781,7 +2786,7 @@ static int sbmac_close(struct net_device
+
+ sbdma_emptyring(&(sc->sbm_txdma));
+ sbdma_emptyring(&(sc->sbm_rxdma));
+-
++
+ return 0;
+ }
+
+@@ -2793,13 +2798,13 @@ sbmac_setup_hwaddr(int chan,char *addr)
+ {
+ 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 @@ sbmac_init_module(void)
+ {
+ 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 @@ sbmac_init_module(void)
+
+ 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 @@ sbmac_init_module(void)
+ */
+
+ 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 @@ sbmac_init_module(void)
+ 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
+--- 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 at engr.sgi.com)\n";
+-
+ static char *sgiseeqstr = "SGI Seeq8003";
+
+ /*
+@@ -113,9 +111,9 @@ static struct net_device *root_sgiseeq_d
+
+ 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 @@ void sgiseeq_dump_rings(void)
+
+ #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 @@ static int init_seeq(struct net_device *
+ 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 @@ static irqreturn_t sgiseeq_interrupt(int
+ 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 @@ static int sgiseeq_close(struct net_devi
+ {
+ 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 @@ static inline void setup_rx_ring(struct
+
+ #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 @@ static int sgiseeq_init(struct hpc3_regs
+ 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 @@ static int sgiseeq_init(struct hpc3_regs
+ 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 @@ static int sgiseeq_init(struct hpc3_regs
+ 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 @@ static int sgiseeq_init(struct hpc3_regs
+ 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 @@ err_out:
+
+ 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 @@ static void __exit sgiseeq_exit(void)
+ {
+ 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 @@ static void __exit sgiseeq_exit(void)
+ module_init(sgiseeq_probe);
+ module_exit(sgiseeq_exit);
+
++MODULE_DESCRIPTION("SGI Seeq 8003 driver");
++MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips at linux-mips.org>");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
+--- a/drivers/net/sis190.c
++++ b/drivers/net/sis190.c
+@@ -842,7 +842,7 @@ static void sis190_set_rx_mode(struct ne
+ 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
+--- a/drivers/net/sis900.c
++++ b/drivers/net/sis900.c
+@@ -1696,15 +1696,20 @@ static int sis900_rx(struct net_device *
+ 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 @@ static int sis900_rx(struct net_device *
+ 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 @@ static int sis900_rx(struct net_device *
+ 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 @@ static int sis900_rx(struct net_device *
+
+ /* 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
+--- a/drivers/net/skfp/smt.c
++++ b/drivers/net/skfp/smt.c
+@@ -1896,7 +1896,7 @@ void smt_swap_para(struct smt_header *sm
+
+ 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
+--- a/drivers/net/skge.c
++++ b/drivers/net/skge.c
+@@ -730,6 +730,7 @@ static struct ethtool_ops skge_ethtool_o
+ .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 @@ static struct net_device *skge_devinit(s
+
+ /* 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
+--- a/drivers/net/smc91x.c
++++ b/drivers/net/smc91x.c
+@@ -77,7 +77,7 @@ static const char version[] =
+ #include <linux/errno.h>
+ #include <linux/ioport.h>
+ #include <linux/crc32.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/spinlock.h>
+ #include <linux/ethtool.h>
+ #include <linux/mii.h>
+@@ -1983,6 +1983,10 @@ static int __init smc_probe(struct net_d
+ 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 @@ static int smc_drv_remove(struct device
+ 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 @@ static int smc_drv_suspend(struct device
+ 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
+--- a/drivers/net/smc91x.h
++++ b/drivers/net/smc91x.h
+@@ -230,12 +230,12 @@ SMC_outw(u16 val, void __iomem *ioaddr,
+ #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
+--- a/drivers/net/starfire.c
++++ b/drivers/net/starfire.c
+@@ -1091,8 +1091,10 @@ static int netdev_open(struct net_device
+ 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
+--- a/drivers/net/sunbmac.c
++++ b/drivers/net/sunbmac.c
+@@ -214,7 +214,8 @@ static void bigmac_init_rings(struct big
+ {
+ 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
+--- a/drivers/net/sunbmac.h
++++ b/drivers/net/sunbmac.h
+@@ -339,7 +339,7 @@ struct bigmac {
+ #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
+--- 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 at 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 at 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 @@ IV. Notes
+ 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_ioctl(struct net_devic
+ 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 @@ static int __devinit sundance_probe1 (st
+ #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 @@ static int __devinit sundance_probe1 (st
+ 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,33 +631,31 @@ static int __devinit sundance_probe1 (st
+ 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->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->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];
++
+ /* Parse override configuration */
+ np->an_enable = 1;
+ if (card_idx < MAX_UNITS) {
+@@ -692,7 +716,7 @@ static int __devinit sundance_probe1 (st
+ /* 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 @@ static irqreturn_t intr_handler(int irq,
+ ("%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 at 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 @@ static struct ethtool_ops ethtool_ops =
+ .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
+--- 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 @@ static struct pci_device_id tg3_pci_tbl[
+ 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 @@ static void tg3_write_mem(struct tg3 *tp
+ 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 @@ static void tg3_switch_clocks(struct tg3
+ 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 @@ static int tg3_set_power_state(struct tg
+ 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 @@ static inline void tg3_set_mtu(struct ne
+ 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 @@ static void tg3_init_rings(struct tg3 *t
+ 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_init_rings(struct tg3 *t
+ */
+ 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 @@ static int tg3_chip_reset(struct tg3 *tp
+ 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 @@ static int tg3_reset_hw(struct tg3 *tp)
+ 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 @@ static void tg3_timer(unsigned long __op
+ 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 @@ static int tg3_open(struct net_device *d
+ 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 @@ static int tg3_get_settings(struct net_d
+ 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 @@ static int tg3_set_settings(struct net_d
+ {
+ 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 @@ static int tg3_set_settings(struct net_d
+ 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 @@ static void __devinit tg3_get_nvram_info
+ }
+
+ 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 @@ static void __devinit tg3_get_eeprom_hw_
+
+ 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 @@ static int __devinit tg3_get_invariants(
+ }
+
+ /* 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 @@ static int __devinit tg3_get_invariants(
+
+ 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 @@ static int __devinit tg3_get_invariants(
+ * 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 @@ static int __devinit tg3_get_device_addr
+ 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 @@ static int __devinit tg3_test_dma(struct
+ } 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 @@ static char * __devinit tg3_phy_string(s
+ 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 @@ static int __devinit tg3_init_one(struct
+ }
+
+ /* 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
+--- 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 @@ struct tg3 {
+ 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 @@ struct tg3 {
+ #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 @@ struct tg3 {
+ (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
+--- a/drivers/net/tokenring/ibmtr.c
++++ b/drivers/net/tokenring/ibmtr.c
+@@ -318,7 +318,7 @@ static void ibmtr_cleanup_card(struct ne
+ 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 @@ static int tok_init_card(struct net_devi
+ 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 @@ static int tok_open(struct net_device *d
+ 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
+--- a/drivers/net/tokenring/olympic.c
++++ b/drivers/net/tokenring/olympic.c
+@@ -1101,7 +1101,7 @@ static int olympic_close(struct net_devi
+
+ 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/proteon.c b/drivers/net/tokenring/proteon.c
+--- a/drivers/net/tokenring/proteon.c
++++ b/drivers/net/tokenring/proteon.c
+@@ -29,6 +29,7 @@ static const char version[] = "proteon.c
+ #include <linux/init.h>
+ #include <linux/netdevice.h>
+ #include <linux/trdevice.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/io.h>
+diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
+--- a/drivers/net/tokenring/skisa.c
++++ b/drivers/net/tokenring/skisa.c
+@@ -36,6 +36,7 @@ static const char version[] = "skisa.c:
+ #include <linux/init.h>
+ #include <linux/netdevice.h>
+ #include <linux/trdevice.h>
++#include <linux/platform_device.h>
+
+ #include <asm/system.h>
+ #include <asm/io.h>
+diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
+--- a/drivers/net/tokenring/tms380tr.c
++++ b/drivers/net/tokenring/tms380tr.c
+@@ -1243,8 +1243,7 @@ void tms380tr_wait(unsigned long time)
+
+ 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
+--- a/drivers/net/tulip/de2104x.c
++++ b/drivers/net/tulip/de2104x.c
+@@ -1787,10 +1787,15 @@ static void __init de21041_get_srom_info
+ /* 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 @@ static int __init de_init_one (struct pc
+ 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 @@ static void __exit de_remove_one (struct
+ 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
+--- a/drivers/net/tulip/tulip_core.c
++++ b/drivers/net/tulip/tulip_core.c
+@@ -1727,8 +1727,7 @@ err_out_free_ring:
+ 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 @@ static void __devexit tulip_remove_one (
+ 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
+--- a/drivers/net/typhoon.c
++++ b/drivers/net/typhoon.c
+@@ -419,10 +419,9 @@ typhoon_reset(void __iomem *ioaddr, int
+ 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
+--- a/drivers/net/via-rhine.c
++++ b/drivers/net/via-rhine.c
+@@ -490,6 +490,8 @@ struct rhine_private {
+ 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 int mdio_read(struct net_device
+ 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 @@ static int __devinit rhine_init_one(stru
+
+ 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 @@ static int __devinit rhine_init_one(stru
+ 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 @@ static void rhine_check_media(struct net
+ 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 @@ static void rhine_disable_linkmon(void _
+ 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 int rhine_open(struct net_device
+ 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 @@ static void rhine_error(struct net_devic
+ 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 @@ static struct ethtool_ops netdev_ethtool
+ .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 @@ static int rhine_close(struct net_device
+ 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
+--- a/drivers/net/via-velocity.c
++++ b/drivers/net/via-velocity.c
+@@ -1212,10 +1212,8 @@ static void velocity_free_td_ring(struct
+ 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
+--- a/drivers/net/wan/cosa.c
++++ b/drivers/net/wan/cosa.c
+@@ -400,7 +400,7 @@ static int __init cosa_init(void)
+ 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 @@ static int get_wait_data(struct cosa_dat
+ 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 @@ static int put_wait_data(struct cosa_dat
+ }
+ #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
+--- a/drivers/net/wan/cycx_drv.c
++++ b/drivers/net/wan/cycx_drv.c
+@@ -109,7 +109,7 @@ static long cycx_2x_irq_options[] = { 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 @@ int __init cycx_drv_init(void)
+
+ /* 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 @@ int cycx_down(struct cycx_hw *hw)
+ }
+
+ /* 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
+--- a/drivers/net/wan/cycx_main.c
++++ b/drivers/net/wan/cycx_main.c
+@@ -103,7 +103,7 @@ static struct cycx_device *cycx_card_arr
+ * < 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
+--- 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 @@ static int cycx_wan_new_if(struct wan_de
+
+ /* 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 @@ static unsigned dec_to_uint(u8 *str, int
+ 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
+--- a/drivers/net/wan/dscc4.c
++++ b/drivers/net/wan/dscc4.c
+@@ -446,8 +446,8 @@ static inline unsigned int dscc4_tx_quie
+ 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 @@ int state_check(u32 state, struct dscc4_
+ 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 @@ static void dscc4_release_ring(struct ds
+ }
+ }
+
+-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 @@ static int dscc4_wait_ack_cec(struct dsc
+ 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 @@ static inline int dscc4_xpr_ack(struct d
+ (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 @@ static void dscc4_pci_reset(struct pci_d
+ /* 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 @@ try:
+ * 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
+--- a/drivers/net/wan/farsync.c
++++ b/drivers/net/wan/farsync.c
+@@ -74,11 +74,11 @@ MODULE_LICENSE("GPL");
+ /*
+ * 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 do_bottom_half_rx(struct fst
+ 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 @@ fst_issue_cmd(struct fst_port_info *port
+ /* 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 @@ do_bottom_half_rx(struct fst_card_info *
+ * 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
+--- a/drivers/net/wan/hdlc_fr.c
++++ b/drivers/net/wan/hdlc_fr.c
+@@ -330,7 +330,7 @@ static int pvc_close(struct net_device *
+
+
+
+-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
+--- 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 @@ void lmcConsoleLog(char *type, unsigned
+ }
+ sprintf(pstr, "\n");
+ printk(str);
++}
+ #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
+--- 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
+--- a/drivers/net/wan/pc300.h
++++ b/drivers/net/wan/pc300.h
+@@ -472,24 +472,8 @@ enum pc300_loopback_cmds {
+
+ #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
+--- a/drivers/net/wan/pc300_drv.c
++++ b/drivers/net/wan/pc300_drv.c
+@@ -291,6 +291,7 @@ static uclong detect_ram(pc300_t *);
+ 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 @@ static void rx_dma_buf_check(pc300_t * c
+ 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 @@ int dma_get_rx_frame_size(pc300_t * card
+ * 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 @@ int dma_buf_write(pc300_t * card, int ch
+ * 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 @@ int dma_buf_read(pc300_t * card, int ch,
+ 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 @@ void tx_dma_stop(pc300_t * card, int ch)
+ 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 @@ void rx_dma_stop(pc300_t * card, int ch)
+ 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 @@ void rx_dma_start(pc300_t * card, int ch
+ /*************************/
+ /*** 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 @@ void falc_issue_cmd(pc300_t * card, int
+ 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_intr_enable(pc300_t * card, in
+ }
+ }
+
+-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 @@ void falc_open_timeslot(pc300_t * card,
+ (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 @@ void falc_close_timeslot(pc300_t * card,
+ ~(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_close_all_timeslots(pc300_t *
+ }
+ }
+
+-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_open_all_timeslots(pc300_t * c
+ }
+ }
+
+-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_init_timeslot(pc300_t * card,
+ }
+ }
+
+-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 @@ void falc_enable_comm(pc300_t * card, in
+ ~((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 @@ void falc_disable_comm(pc300_t * card, i
+ ((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 @@ void falc_init_t1(pc300_t * card, int ch
+ 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 @@ void falc_init_e1(pc300_t * card, int ch
+ 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 @@ void falc_init_hdlc(pc300_t * card, int
+ 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 @@ void te_config(pc300_t * card, int ch)
+ 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_check_status(pc300_t * card, i
+ }
+ }
+
+-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 @@ void falc_update_stats(pc300_t * card, i
+ * 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 @@ void falc_remote_loop(pc300_t * card, in
+ * 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 @@ void falc_local_loop(pc300_t * card, int
+ * 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 @@ void falc_payload_loop(pc300_t * card, i
+ * 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 @@ void turn_off_xlu(pc300_t * card, int ch
+ * 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 @@ void turn_off_xld(pc300_t * card, int ch
+ * 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 @@ void falc_generate_loop_up_code(pc300_t
+ * 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 @@ void falc_generate_loop_down_code(pc300_
+ * 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 @@ void falc_pattern_test(pc300_t * card, i
+ * 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 @@ cpc_trace(struct net_device *dev, struct
+ 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 @@ void cpc_tx_timeout(struct net_device *d
+ 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 @@ int cpc_queue_xmit(struct sk_buff *skb,
+ 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 @@ static irqreturn_t cpc_intr(int irq, voi
+ 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_sca_status(pc300_t * card, int
+ }
+ }
+
+-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 @@ void cpc_falc_status(pc300_t * card, int
+ 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 @@ int cpc_change_mtu(struct net_device *de
+ 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 @@ static int clock_rate_calc(uclong rate,
+ }
+ }
+
+-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 @@ int ch_config(pc300dev_t * d)
+ 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 @@ int rx_config(pc300dev_t * d)
+ 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 @@ static int cpc_attach(struct net_device
+ 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 @@ void cpc_opench(pc300dev_t * d)
+ 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 @@ int cpc_open(struct net_device *dev)
+ 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
+--- a/drivers/net/wan/pc300_tty.c
++++ b/drivers/net/wan/pc300_tty.c
+@@ -112,10 +112,10 @@ typedef struct _st_cpc_tty_area {
+ 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_trace(pc300dev_t *de
+ 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 @@ static int cpc_tty_chars_in_buffer(struc
+ 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 @@ int pc300_tiocmset(struct tty_struct *tt
+ 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
+--- a/drivers/net/wan/sdla.c
++++ b/drivers/net/wan/sdla.c
+@@ -182,7 +182,7 @@ static char sdla_byte(struct net_device
+ 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_stop(struct net_device *dev)
+ }
+ }
+
+-void sdla_start(struct net_device *dev)
++static void sdla_start(struct net_device *dev)
+ {
+ struct frad_local *flp;
+
+@@ -247,7 +247,7 @@ void sdla_start(struct net_device *dev)
+ *
+ ***************************************************/
+
+-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_cmd(struct net_device *d
+
+ 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 @@ int sdla_activate(struct net_device *sla
+ 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 @@ int sdla_deactivate(struct net_device *s
+ 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 @@ int sdla_assoc(struct net_device *slave,
+ 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 @@ int sdla_deassoc(struct net_device *slav
+ 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 @@ NOTE: This is rather a useless action r
+ 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 @@ int sdla_change_mtu(struct net_device *d
+ 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
+--- a/drivers/net/wan/sdla_fr.c
++++ b/drivers/net/wan/sdla_fr.c
+@@ -822,7 +822,7 @@ static int new_if(struct wan_device* wan
+ 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 @@ static unsigned int dec_to_uint (unsigne
+ 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
+--- a/drivers/net/wan/sdla_x25.c
++++ b/drivers/net/wan/sdla_x25.c
+@@ -957,7 +957,7 @@ static int new_if(struct wan_device* wan
+ 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 @@ static unsigned int dec_to_uint (unsigne
+ 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 @@ static unsigned int hex_to_uint (unsigne
+ 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
+--- a/drivers/net/wan/sdladrv.c
++++ b/drivers/net/wan/sdladrv.c
+@@ -642,9 +642,7 @@ int sdla_mapmem (sdlahw_t* hw, unsigned
+ * 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 @@ int sdla_inten (sdlahw_t* hw)
+ * Disable interrupt generation.
+ */
+
+-EXPORT_SYMBOL(sdla_intde);
+-
++#if 0
+ int sdla_intde (sdlahw_t* hw)
+ {
+ unsigned port = hw->port;
+@@ -748,14 +745,13 @@ int sdla_intde (sdlahw_t* hw)
+ }
+ 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 @@ void read_S514_int_stat (sdlahw_t* hw, u
+ * 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 @@ int sdla_intr (sdlahw_t* hw)
+ }
+ return 0;
+ }
++#endif /* 0 */
+
+ /*============================================================================
+ * Execute Adapter Command.
+diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
+--- a/drivers/net/wan/syncppp.c
++++ b/drivers/net/wan/syncppp.c
+@@ -221,7 +221,7 @@ static void sppp_clear_timeout(struct sp
+ * 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 @@ done:
+ return;
+ }
+
+-EXPORT_SYMBOL(sppp_input);
+-
+ /*
+ * Handle transmit packets.
+ */
+@@ -990,7 +988,7 @@ EXPORT_SYMBOL(sppp_reopen);
+ * 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 @@ int sppp_change_mtu(struct net_device *d
+ return 0;
+ }
+
+-EXPORT_SYMBOL(sppp_change_mtu);
+-
+ /**
+ * sppp_do_ioctl - Ioctl handler for ppp/hdlc
+ * @dev: Device subject to ioctl
+@@ -1456,7 +1452,7 @@ static int sppp_rcv(struct sk_buff *skb,
+ 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
+--- 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 @@ static WifiCtlHdr wifictlhdr8023 = {
+ }
+ };
+
+-#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 @@ typedef struct wep_key_t {
+
+ /* 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 irqreturn_t airo_interrupt( int i
+ 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 @@ struct airo_info {
+ 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 @@ static void emmh32_setseed(emmh32_contex
+ 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 @@ void stop_airo_card( struct net_device *
+ 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 @@ static int mpi_map_card(struct airo_info
+ 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 @@ static int mpi_map_card(struct airo_info
+ /*
+ * 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 @@ static int mpi_map_card(struct airo_info
+ 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 @@ static int mpi_map_card(struct airo_info
+ 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 @@ static int mpi_map_card(struct airo_info
+ /* 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 @@ static void wifi_setup(struct net_device
+ 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 @@ static struct net_device *init_wifidev(s
+ 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 @@ static struct net_device *_init_airo_car
+ 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 @@ static u16 setup_card(struct airo_info *
+ 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 @@ static u16 setup_card(struct airo_info *
+ 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 @@ static u16 setup_card(struct airo_info *
+ 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_BSSList_open( struct ino
+
+ 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 @@ static int airo_pci_resume(struct pci_de
+ 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 @@ static void __exit airo_cleanup_module(
+ remove_proc_entry("aironet", proc_root_driver);
+ }
+
+-#ifdef WIRELESS_EXT
+ /*
+ * Initial Wireless Extension code for Aironet driver by :
+ * Jean Tourrilhes <jt at hpl.hp.com> - HPL - 17 November 00
+@@ -7107,8 +7085,6 @@ static const struct iw_handler_def airo_
+ .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 @@ static int airo_ioctl(struct net_device
+ 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 @@ static struct iw_statistics *airo_get_wi
+
+ 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
+--- a/drivers/net/wireless/airo_cs.c
++++ b/drivers/net/wireless/airo_cs.c
+@@ -258,9 +258,7 @@ static void airo_detach(dev_link_t *link
+
+ /* 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
+--- 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
+--- a/drivers/net/wireless/atmel.c
++++ b/drivers/net/wireless/atmel.c
+@@ -618,12 +618,12 @@ static int atmel_lock_mac(struct atmel_p
+ 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 void tx_update_descriptor(struct
+ 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 int start_tx (struct sk_buff *skb
+ }
+
+ 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 @@ static void atmel_transmit_management_fr
+ 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 @@ static int probe_crc(struct atmel_privat
+ 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 frag_rx_path(struct atmel_pr
+ 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 @@ void stop_atmel_card(struct net_device *
+ 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 @@ static int atmel_ioctl(struct net_device
+ 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 handle_beacon_probe(struct a
+
+ 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 @@ static void send_association_request(str
+ {
+ 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 @@ static void send_association_request(str
+ 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 int retrieve_bss(struct atmel_pri
+ }
+
+
+-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 @@ static void atmel_smooth_qual(struct atm
+ }
+
+ /* 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
+--- a/drivers/net/wireless/atmel_cs.c
++++ b/drivers/net/wireless/atmel_cs.c
+@@ -259,8 +259,7 @@ static void atmel_detach(dev_link_t *lin
+
+ /* 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
+--- 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 @@ int hermes_bap_pwrite(hermes_t *hw, int
+ 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_allocate);
+
+ 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
+--- 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 @@ struct hermes_tx_descriptor {
+ #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 agere_scan_apinfo {
+ 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 @@ union hermes_scan_info {
+ #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 @@ struct hermes_response {
+
+ /* "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 @@ int hermes_bap_pread(hermes_t *hw, int b
+ 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 void hermes_clear_words(st
+
+ 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_read_wordrec(he
+
+ 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
+--- a/drivers/net/wireless/hostap/hostap.c
++++ b/drivers/net/wireless/hostap/hostap.c
+@@ -716,9 +716,6 @@ static int prism2_close(struct net_devic
+ 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 @@ static int prism2_open(struct net_device
+ 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
+--- 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 prism2_rx_80211(struct net_device *d
+ 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 @@ int prism2_rx_80211(struct net_device *d
+ 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 @@ prism2_frag_cache_find(local_info_t *loc
+
+ /* 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 @@ prism2_frag_cache_get(local_info_t *loca
+ 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 @@ prism2_frag_cache_get(local_info_t *loca
+
+ /* 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 @@ hostap_rx_frame_mgmt(local_info_t *local
+ 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 struct net_device *prism2_
+
+
+ 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 @@ static int hostap_is_eapol_frame(local_i
+ {
+ 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 @@ static inline int
+ 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 @@ static inline int
+ 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 @@ void hostap_80211_rx(struct net_device *
+ {
+ 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 @@ void hostap_80211_rx(struct net_device *
+ 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 @@ void hostap_80211_rx(struct net_device *
+ 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 @@ void hostap_80211_rx(struct net_device *
+ 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 @@ void hostap_80211_rx(struct net_device *
+ /* 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 @@ void hostap_80211_rx(struct net_device *
+ 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
+--- 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 @@ int hostap_data_start_xmit(struct sk_buf
+ 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 @@ int hostap_mgmt_start_xmit(struct sk_buf
+ 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 @@ int hostap_mgmt_start_xmit(struct sk_buf
+ 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 sk_buff * hostap_tx_encrypt(struc
+ {
+ 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 @@ struct sk_buff * hostap_tx_encrypt(struc
+
+ 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 @@ struct sk_buff * hostap_tx_encrypt(struc
+ 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 @@ int hostap_master_start_xmit(struct sk_b
+ 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 @@ int hostap_master_start_xmit(struct sk_b
+ 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
+--- a/drivers/net/wireless/hostap/hostap_ap.c
++++ b/drivers/net/wireless/hostap/hostap_ap.c
+@@ -591,14 +591,14 @@ static void hostap_ap_tx_cb(struct sk_bu
+ {
+ 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 @@ static void hostap_ap_tx_cb_auth(struct
+ {
+ 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 @@ static void hostap_ap_tx_cb_auth(struct
+ 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 @@ static void hostap_ap_tx_cb_assoc(struct
+ {
+ 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 @@ static void hostap_ap_tx_cb_assoc(struct
+ 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_assoc(struct
+ 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 @@ static void prism2_send_mgmt(struct net_
+ {
+ 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 @@ static void prism2_send_mgmt(struct net_
+
+ 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 @@ static char * ap_auth_make_challenge(str
+ }
+
+ 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 @@ static char * ap_auth_make_challenge(str
+ 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 @@ static void handle_authen(local_info_t *
+ 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 @@ static void handle_assoc(local_info_t *l
+ 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 @@ static void handle_deauth(local_info_t *
+ 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 @@ static void handle_disassoc(local_info_t
+ 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 @@ static void handle_disassoc(local_info_t
+
+ /* 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 @@ static void ap_handle_data_nullfunc(loca
+
+ /* 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 @@ static void pspoll_send_buffered(local_i
+
+ /* 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_wds_oper_queue(void *
+ 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 @@ static void handle_ap_item(local_info_t
+ 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 @@ void hostap_rx(struct net_device *dev, s
+ 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 @@ void hostap_rx(struct net_device *dev, s
+
+ 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 @@ void hostap_rx(struct net_device *dev, s
+ 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 @@ static void schedule_packet_send(local_i
+ 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 @@ static int prism2_ap_get_sta_qual(local_
+ 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 @@ static int prism2_ap_translate_scan(stru
+ }
+ #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 @@ ap_tx_ret hostap_handle_sta_tx(local_inf
+ 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 @@ ap_tx_ret hostap_handle_sta_tx(local_inf
+ 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_release(void *ptr
+ 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 @@ static void hostap_update_sta_ps2(local_
+
+ /* 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 @@ ap_rx_ret hostap_handle_sta_rx(local_inf
+ 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 @@ ap_rx_ret hostap_handle_sta_rx(local_inf
+
+ /* 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 @@ int hostap_add_sta(struct ap_data *ap, u
+
+ /* 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 @@ int hostap_update_rx_stats(struct ap_dat
+ 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
+--- a/drivers/net/wireless/hostap/hostap_ap.h
++++ b/drivers/net/wireless/hostap/hostap_ap.h
+@@ -233,7 +233,7 @@ struct hostap_tx_data {
+ 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 @@ ap_rx_ret hostap_handle_sta_rx(local_inf
+ 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
+--- a/drivers/net/wireless/hostap/hostap_cs.c
++++ b/drivers/net/wireless/hostap/hostap_cs.c
+@@ -492,42 +492,10 @@ static void prism2_pccard_genesis_reset(
+ }
+
+
+-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 @@ static void prism2_detach(dev_link_t *li
+ *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 @@ static int prism2_event(event_t event, i
+ {
+ 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 @@ static int prism2_event(event_t event, i
+ 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 @@ static int prism2_event(event_t event, i
+ 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
+--- a/drivers/net/wireless/hostap/hostap_hw.c
++++ b/drivers/net/wireless/hostap/hostap_hw.c
+@@ -3322,6 +3322,18 @@ static void prism2_free_local_data(struc
+ 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 @@ static void prism2_free_local_data(struc
+ 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 @@ static void prism2_free_local_data(struc
+ 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
+--- a/drivers/net/wireless/hostap/hostap_ioctl.c
++++ b/drivers/net/wireless/hostap/hostap_ioctl.c
+@@ -50,7 +50,8 @@ static struct iw_statistics *hostap_get_
+ #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 @@ static struct iw_statistics *hostap_get_
+ 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 @@ static int prism2_ioctl_giwaplist(struct
+
+ kfree(addr);
+ kfree(qual);
+-
+ return 0;
+ }
+
+@@ -1827,13 +1827,6 @@ static char * __prism2_translate_scan(lo
+ 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 @@ static char * __prism2_translate_scan(lo
+ 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 @@ static char * __prism2_translate_scan(lo
+ 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 @@ static char * __prism2_translate_scan(lo
+ 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 @@ static char * __prism2_translate_scan(lo
+ 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 @@ static char * __prism2_translate_scan(lo
+ 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 @@ static char * __prism2_translate_scan(lo
+ }
+
+ /* 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 @@ static int prism2_ioctl_priv_download(lo
+ ret = local->func->download(local, param);
+
+ out:
+- if (param != NULL)
+- kfree(param);
+-
++ kfree(param);
+ return ret;
+ }
+ #endif /* PRISM2_DOWNLOAD_SUPPORT */
+@@ -3897,9 +3887,7 @@ static int prism2_ioctl_priv_hostapd(loc
+ }
+
+ 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
+--- a/drivers/net/wireless/hostap/hostap_pci.c
++++ b/drivers/net/wireless/hostap/hostap_pci.c
+@@ -59,11 +59,13 @@ static struct pci_device_id prism2_pci_i
+ 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 void hfa384x_outb_debug(st
+ 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 u8 hfa384x_inb_debug(struc
+ 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 void hfa384x_outw_debug(st
+ 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 @@ static struct prism2_helper_functions pr
+ {
+ .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 @@ static int prism2_pci_probe(struct pci_d
+ return hostap_hw_ready(dev);
+
+ fail:
+- kfree(hw_priv);
+-
+ if (irq_registered && dev)
+ free_irq(dev->irq, dev);
+
+@@ -364,10 +368,8 @@ static int prism2_pci_probe(struct pci_d
+
+ 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 @@ static void prism2_pci_remove(struct pci
+ 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 @@ static int prism2_pci_resume(struct pci_
+ 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
+--- a/drivers/net/wireless/hostap/hostap_plx.c
++++ b/drivers/net/wireless/hostap/hostap_plx.c
+@@ -328,8 +328,6 @@ static struct prism2_helper_functions pr
+ {
+ .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 @@ static int prism2_plx_probe(struct pci_d
+ 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 @@ static void prism2_plx_remove(struct pci
+ 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 @@ static void prism2_plx_remove(struct pci
+ 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
+--- a/drivers/net/wireless/hostap/hostap_wlan.h
++++ b/drivers/net/wireless/hostap/hostap_wlan.h
+@@ -552,8 +552,6 @@ struct prism2_helper_functions {
+ * (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
+--- a/drivers/net/wireless/ipw2100.c
++++ b/drivers/net/wireless/ipw2100.c
+@@ -800,8 +800,7 @@ static int ipw2100_hw_send_command(struc
+ * 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 @@ static int ipw2100_start_adapter(struct
+ 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 @@ static int ipw2100_hw_phy_off(struct ipw
+ (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 @@ fail_up:
+
+ 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 @@ static int ipw2100_hw_stop_adapter(struc
+ 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 @@ static void ipw2100_tx_send_data(struct
+ 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 @@ static void ipw2100_tx_send_data(struct
+ 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 @@ static irqreturn_t ipw2100_interrupt(int
+ 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
+--- a/drivers/net/wireless/ipw2100.h
++++ b/drivers/net/wireless/ipw2100.h
+@@ -808,7 +808,7 @@ struct ipw2100_priv {
+ 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
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -4030,6 +4030,10 @@ static struct ipw_rx_queue *ipw_rx_queue
+ 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 @@ static void ipw_rx(struct ipw_priv *priv
+ {
+ 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 @@ static void ipw_rx(struct ipw_priv *priv
+ #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 @@ static int ipw_wx_set_freq(struct net_de
+
+ 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 @@ static int ipw_wx_set_wireless_mode(stru
+ }
+
+ 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 @@ static int ipw_wx_set_wireless_mode(stru
+ 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 @@ we need to heavily modify the ieee80211_
+
+ 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 inline void ipw_tx_skb(struct ipw
+ }
+
+ 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 @@ static int ipw_pci_probe(struct pci_dev
+ 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 @@ static int ipw_pci_probe(struct pci_dev
+ ": 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
+--- a/drivers/net/wireless/ipw2200.h
++++ b/drivers/net/wireless/ipw2200.h
+@@ -1654,12 +1654,12 @@ static const long ipw_frequencies[] = {
+
+ #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
+--- 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 void update_stats(struct net_devi
+ 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 @@ static dev_link_t *dev_list;
+ 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 @@ typedef struct netwave_private {
+ 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 @@ static inline void wait_WOC(unsigned int
+ 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 @@ static void netwave_snapshot(netwave_pri
+ sizeof(struct site_survey));
+ }
+ }
+-#endif
+
+-#ifdef WIRELESS_EXT
+ /*
+ * Function netwave_get_wireless_stats (dev)
+ *
+@@ -411,7 +382,6 @@ static struct iw_statistics *netwave_get
+
+ return &priv->iw_stats;
+ }
+-#endif
+
+ /*
+ * Function netwave_attach (void)
+@@ -471,13 +441,7 @@ static dev_link_t *netwave_attach(void)
+ 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 @@ static int netwave_set_nwid(struct net_d
+ /* 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 @@ static int netwave_get_nwid(struct net_d
+ 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 @@ static int netwave_get_scramble(struct n
+ {
+ 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 @@ static int netwave_get_mode(struct net_d
+
+ return 0;
+ }
+-#endif /* WIRELESS_EXT > 8 */
+
+ /*
+ * Wireless Handler : get range info
+@@ -702,11 +648,9 @@ static int netwave_get_range(struct net_
+ /* 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 @@ static int netwave_get_range(struct net_
+ 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 @@ static const struct iw_priv_args netwave
+ "getsitesurvey" },
+ };
+
+-#if WIRELESS_EXT > 12
+-
+ static const iw_handler netwave_handler[] =
+ {
+ NULL, /* SIOCSIWNAME */
+@@ -839,131 +777,8 @@ static const struct iw_handler_def netwa
+ .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
+--- 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 @@ MODULE_PARM_DESC(force_monitor, "Allow m
+
+ /* 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 @@ static struct {
+ /********************************************************************/
+
+ /* 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 @@ struct hermes_tx_descriptor_802_11 {
+ 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 @@ static struct iw_statistics *orinoco_get
+ /* 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 @@ static int orinoco_xmit(struct sk_buff *
+ 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 @@ static int orinoco_xmit(struct sk_buff *
+ 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 @@ static void __orinoco_ev_txexc(struct ne
+ 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 @@ static void __orinoco_ev_txexc(struct ne
+ * 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 int is_ethersnap(void *_hd
+ 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 @@ static void orinoco_join_ap(struct net_d
+ 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 @@ static void orinoco_join_ap(struct net_d
+ 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 @@ static void orinoco_join_ap(struct net_d
+ 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 @@ static void orinoco_send_wevents(struct
+ 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 @@ static void __orinoco_ev_info(struct net
+ 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 @@ struct net_device *alloc_orinocodev(int
+ 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 @@ static int orinoco_ioctl_getiwrange(stru
+ }
+ }
+
+- 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 @@ static int orinoco_ioctl_getiwrange(stru
+ 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 @@ static int orinoco_ioctl_getrid(struct n
+ 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 @@ static int orinoco_ioctl_setscan(struct
+ 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 @@ static inline int orinoco_translate_scan
+ 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 @@ static const iw_handler orinoco_handler[
+ [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
+--- 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 @@ struct header_struct {
+ /* 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 @@ struct orinoco_private {
+ 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
+--- 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 @@ static dev_link_t *dev_list; /* = NULL *
+ /* 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 @@ static char version[] __initdata = DRIVE
+ "Pavel Roskin <proski at 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 @@ static struct pcmcia_driver orinoco_driv
+ .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
+--- 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 @@ static int nortel_pci_cor_reset(struct o
+ 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
+--- 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
+--- 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
+--- 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
+--- a/drivers/net/wireless/prism54/isl_ioctl.c
++++ b/drivers/net/wireless/prism54/isl_ioctl.c
+@@ -462,14 +462,12 @@ prism54_get_range(struct net_device *nde
+ /* 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 @@ prism54_get_scan(struct net_device *ndev
+ 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 @@ const struct iw_handler_def prism54_hand
+ .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
+--- a/drivers/net/wireless/prism54/islpci_dev.c
++++ b/drivers/net/wireless/prism54/islpci_dev.c
+@@ -439,8 +439,7 @@ prism54_bring_down(islpci_private *priv)
+ 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 @@ islpci_reset_if(islpci_private *priv)
+ /* 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 @@ islpci_free_memory(islpci_private *priv)
+ 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 @@ islpci_setup(struct pci_dev *pdev)
+ 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
+--- a/drivers/net/wireless/prism54/islpci_dev.h
++++ b/drivers/net/wireless/prism54/islpci_dev.h
+@@ -100,9 +100,7 @@ typedef struct {
+
+ 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
+--- a/drivers/net/wireless/prism54/islpci_eth.c
++++ b/drivers/net/wireless/prism54/islpci_eth.c
+@@ -97,12 +97,6 @@ islpci_eth_transmit(struct sk_buff *skb,
+ /* 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 @@ islpci_eth_transmit(struct sk_buff *skb,
+ /* 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 @@ islpci_eth_transmit(struct sk_buff *skb,
+ 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
+--- a/drivers/net/wireless/prism54/islpci_mgt.c
++++ b/drivers/net/wireless/prism54/islpci_mgt.c
+@@ -137,7 +137,7 @@ islpci_mgmt_rx_fill(struct net_device *n
+ 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 @@ islpci_mgt_transaction(struct net_device
+ 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 @@ islpci_mgt_transaction(struct net_device
+ 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
+--- a/drivers/net/wireless/prism54/oid_mgt.c
++++ b/drivers/net/wireless/prism54/oid_mgt.c
+@@ -268,11 +268,10 @@ mgt_clean(islpci_private *priv)
+
+ 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
+--- a/drivers/net/wireless/ray_cs.c
++++ b/drivers/net/wireless/ray_cs.c
+@@ -1649,28 +1649,28 @@ static iw_stats * ray_get_wireless_stats
+ */
+
+ 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 @@ static const iw_handler ray_handler[] =
+ #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
+--- 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 @@ static dev_link_t *dev_list; /* = NULL *
+ /* 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 @@ static void spectrum_cs_detach(dev_link_
+ * 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 @@ struct dblock {
+ * 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 @@ struct pdr {
+ * 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 @@ spectrum_plug_pdi(hermes_t *hw, struct p
+
+ /* 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 @@ spectrum_read_pda(hermes_t *hw, u16 *pda
+ /* 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 @@ spectrum_dl_image(hermes_t *hw, dev_link
+ 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 @@ spectrum_dl_firmware(hermes_t *hw, dev_l
+ {
+ 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 @@ spectrum_dl_firmware(hermes_t *hw, dev_l
+ secondary_fw_name);
+ return -ENOENT;
+ }
+-#endif
+
+ /* Load primary firmware */
+ ret = spectrum_dl_image(hw, link, primsym);
+@@ -1085,7 +1038,7 @@ static char version[] __initdata = DRIVE
+ 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 @@ static struct pcmcia_driver orinoco_driv
+ .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
+--- a/drivers/net/wireless/strip.c
++++ b/drivers/net/wireless/strip.c
+@@ -860,12 +860,9 @@ static int allocate_buffers(struct strip
+ 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 @@ static int strip_change_mtu(struct net_d
+ 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 @@ static int strip_close_low(struct net_de
+ /*
+ * 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
+--- a/drivers/net/wireless/wavelan.c
++++ b/drivers/net/wireless/wavelan.c
+@@ -430,7 +430,6 @@ static void fee_read(unsigned long ioadd
+ }
+ }
+
+-#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */
+
+ /*------------------------------------------------------------------*/
+ /*
+@@ -514,7 +513,6 @@ static void fee_write(unsigned long ioad
+ fee_wait(ioaddr, 10, 100);
+ #endif /* EEPROM_IS_PROTECTED */
+ }
+-#endif /* WIRELESS_EXT */
+
+ /************************ I82586 SUBROUTINES *************************/
+ /*
+@@ -973,11 +971,9 @@ static void wv_mmc_show(struct net_devic
+ 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 @@ static int wavelan_set_mac_address(struc
+ }
+ #endif /* SET_MAC_ADDRESS */
+
+-#ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */
+
+ /*------------------------------------------------------------------*/
+ /*
+@@ -2473,7 +2468,6 @@ static iw_stats *wavelan_get_wireless_st
+ #endif
+ return &lp->wstats;
+ }
+-#endif /* WIRELESS_EXT */
+
+ /************************* PACKET RECEPTION *************************/
+ /*
+@@ -4194,11 +4188,9 @@ static int __init wavelan_config(struct
+ 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
+--- 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 @@ struct net_local
+ 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
+--- a/drivers/net/wireless/wavelan_cs.c
++++ b/drivers/net/wireless/wavelan_cs.c
+@@ -415,7 +415,6 @@ fee_read(u_long base, /* i/o port of th
+ }
+ }
+
+-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
+
+ /*------------------------------------------------------------------*/
+ /*
+@@ -500,7 +499,6 @@ fee_write(u_long base, /* i/o port of th
+ fee_wait(base, 10, 100);
+ #endif /* EEPROM_IS_PROTECTED */
+ }
+-#endif /* WIRELESS_EXT */
+
+ /******************* WaveLAN Roaming routines... ********************/
+
+@@ -1161,10 +1159,8 @@ wv_mmc_show(struct net_device * dev)
+ 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 @@ wavelan_set_mac_address(struct net_devic
+ }
+ #endif /* SET_MAC_ADDRESS */
+
+-#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
+
+ /*------------------------------------------------------------------*/
+ /*
+@@ -2793,7 +2788,6 @@ wavelan_get_wireless_stats(struct net_de
+ #endif
+ return &lp->wstats;
+ }
+-#endif /* WIRELESS_EXT */
+
+ /************************* PACKET RECEPTION *************************/
+ /*
+@@ -4679,11 +4673,9 @@ wavelan_attach(void)
+ 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
+--- 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 @@ struct net_local
+ 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
+--- a/drivers/net/wireless/wl3501.h
++++ b/drivers/net/wireless/wl3501.h
+@@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
+
+ 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
+--- a/drivers/parisc/asp.c
++++ b/drivers/parisc/asp.c
+@@ -77,12 +77,12 @@ asp_init_chip(struct parisc_device *dev)
+ 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 @@ static struct parisc_device_id asp_tbl[]
+ };
+
+ 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
+--- 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 ioa_registers {
+ */
+
+ 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 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_
+ ** 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 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_
+ ** 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 @@ ccio_clear_io_tlb(struct ioc *ioc, dma_a
+ 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 @@ ccio_mark_invalid(struct ioc *ioc, dma_a
+ ** 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 @@ ccio_unmap_single(struct device *dev, dm
+ * 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 struct parisc_device_id ccio_tbl[
+ 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 @@ ccio_ioc_init(struct ioc *ioc)
+
+ 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 @@ ccio_ioc_init(struct ioc *ioc)
+ 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 @@ ccio_ioc_init(struct ioc *ioc)
+ 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 @@ ccio_ioc_init(struct ioc *ioc)
+ ** 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 @@ static void __init ccio_init_resources(s
+
+ 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 @@ static int new_ioc_area(struct resource
+
+ 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 @@ int ccio_allocate_resource(const struct
+
+ 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 @@ int ccio_request_resource(const struct p
+ 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 @@ static int ccio_probe(struct parisc_devi
+
+ 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 @@ static int ccio_probe(struct parisc_devi
+ *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
+--- a/drivers/parisc/ccio-rm-dma.c
++++ b/drivers/parisc/ccio-rm-dma.c
+@@ -167,7 +167,7 @@ ccio_probe(struct parisc_device *dev)
+ {
+ 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
+--- a/drivers/parisc/dino.c
++++ b/drivers/parisc/dino.c
+@@ -178,6 +178,8 @@ static int dino_cfg_read(struct pci_bus
+ 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 @@ static int dino_cfg_write(struct pci_bus
+ 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 @@ static void dino_disable_irq(unsigned in
+ 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 @@ static void dino_enable_irq(unsigned int
+ 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 @@ dino_card_setup(struct pci_bus *bus, voi
+ 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 @@ static void __init
+ 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 @@ void ccio_cujo20_fixup(struct parisc_dev
+ ** 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 @@ dino_driver_callback(struct parisc_devic
+ }
+ }
+
+- 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 @@ dino_driver_callback(struct parisc_devic
+ 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 @@ dino_driver_callback(struct parisc_devic
+ 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_device_id dino_tbl[
+ };
+
+ 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
+--- a/drivers/parisc/eisa.c
++++ b/drivers/parisc/eisa.c
+@@ -315,7 +315,7 @@ static int __devinit eisa_probe(struct p
+ 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 @@ static struct parisc_device_id eisa_tbl[
+ 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
+--- a/drivers/parisc/gsc.c
++++ b/drivers/parisc/gsc.c
+@@ -183,12 +183,20 @@ void gsc_asic_assign_irq(struct gsc_asic
+ *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 @@ void gsc_fixup_irqs(struct parisc_device
+ 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
+--- a/drivers/parisc/hppb.c
++++ b/drivers/parisc/hppb.c
+@@ -68,14 +68,14 @@ static int hppb_probe(struct parisc_devi
+ 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_device_id hppb_tbl[
+ };
+
+ 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
+--- a/drivers/parisc/iosapic.c
++++ b/drivers/parisc/iosapic.c
+@@ -244,7 +244,7 @@ static struct irt_entry *iosapic_alloc_i
+ * 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
+--- a/drivers/parisc/lasi.c
++++ b/drivers/parisc/lasi.c
+@@ -175,7 +175,7 @@ lasi_init_chip(struct parisc_device *dev
+ 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 @@ static struct parisc_device_id lasi_tbl[
+ };
+
+ 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
+--- a/drivers/parisc/lba_pci.c
++++ b/drivers/parisc/lba_pci.c
+@@ -1288,7 +1288,7 @@ lba_legacy_resources(struct parisc_devic
+ ** 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 @@ lba_driver_probe(struct parisc_device *d
+ 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 @@ lba_driver_probe(struct parisc_device *d
+ }
+
+ 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 @@ lba_driver_probe(struct parisc_device *d
+ * 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 __init lba_init(void)
+ */
+ 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
+--- 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 at tiscali.it>
++ * - Switch from using a tasklet to a work queue, so the led_LCD_driver
++ * can sleep.
++ * David Pye <dmp at 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 @@ lcd_info __attribute__((aligned(8))) =
+ #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 @@ static void led_LASI_driver(unsigned cha
+ /*
+ **
+ ** 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;
+- }
++ static int i;
++ static unsigned char mask[4] = { LED_HEARTBEAT, LED_DISK_IO,
++ LED_LAN_RCV, LED_LAN_TX };
++
++ static struct lcd_block * blockp[4] = {
++ &lcd_info.heartbeat,
++ &lcd_info.disk_io,
++ &lcd_info.lan_rcv,
++ &lcd_info.lan_tx
++ };
+
+- 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 );
+- }
+-
+- /* 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 */
++ /* 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 @@ static __inline__ int led_get_net_activi
+
+ 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 __inline__ int led_get_diskio_act
+ 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,86 +420,70 @@ static __inline__ int led_get_diskio_act
+ 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)
+- {
+- /* 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;
+- }
+-
+- /* look for network activity and flash LEDs respectively */
+- if (led_lanrxtx && ((NORMALIZED_COUNT(count)+(8/2)) & 7) == 0)
++ if (likely(led_heartbeat))
+ {
+- currentleds &= ~(LED_LAN_RCV | LED_LAN_TX);
+- currentleds |= led_get_net_activity();
++ /* 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;
+ }
+
+- /* 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;
+- }
+-
+- /* update the LCD/LEDs */
+- if (currentleds != lastleds) {
+- led_func_ptr(currentleds);
+- lastleds = currentleds;
+- }
+-}
+
+-/* main led tasklet struct (scheduled from time.c) */
+-DECLARE_TASKLET_DISABLED(led_tasklet, led_tasklet_func, 0);
++ if (currentleds != lastleds)
++ {
++ led_func_ptr(currentleds); /* Update the LCD/LEDs */
++ lastleds = currentleds;
++ }
+
++ queue_delayed_work(led_wq, &led_task, LED_UPDATE_INTERVAL);
++}
+
+ /*
+ ** led_halt()
+@@ -522,9 +513,13 @@ static int led_halt(struct notifier_bloc
+ 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 @@ int __init register_led_driver(int model
+ 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 @@ int __init register_led_driver(int model
+ 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 @@ void __init register_led_regions(void)
+ ** 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 @@ int lcd_print( char *str )
+ 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 @@ int lcd_print( char *str )
+ 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
+--- a/drivers/parisc/pdc_stable.c
++++ b/drivers/parisc/pdc_stable.c
+@@ -536,7 +536,7 @@ pdcs_info_read(struct subsystem *entry,
+
+ 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
+--- a/drivers/parisc/sba_iommu.c
++++ b/drivers/parisc/sba_iommu.c
+@@ -91,8 +91,8 @@ extern struct proc_dir_entry * proc_mcki
+ #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 @@ struct ioc {
+ 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 @@ static unsigned long piranha_bad_128k =
+ /* 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 @@ static int reserve_sba_gart = 1;
+ #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 @@ static int reserve_sba_gart = 1;
+
+ #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 @@ static void sba_dump_tlb(void __iomem *h
+ #else
+ #define sba_dump_ranges(x)
+ #define sba_dump_tlb(x)
+-#endif
++#endif /* DEBUG_SBA_INIT */
+
+
+ #ifdef ASSERT_PDIR_SANITY
+@@ -674,7 +674,7 @@ sba_free_range(struct ioc *ioc, dma_addr
+ *
+ ***************************************************************/
+
+-#if SBA_HINT_SUPPORT
++#ifdef SBA_HINT_SUPPORT
+ #define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
+ #endif
+
+@@ -743,9 +743,8 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t
+ * (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 @@ static SBA_INLINE void
+ 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 @@ sba_mark_invalid(struct ioc *ioc, dma_ad
+ 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);
+ }
+
+- ioc = GET_IOC(dev);
++ /* 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;
+
+- /* check if mask is > than the largest IO Virt Address */
++ ioc = GET_IOC(dev);
+
+- 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 @@ sba_map_single(struct device *dev, void
+ 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 @@ sba_unmap_single(struct device *dev, dma
+ 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 @@ sba_unmap_single(struct device *dev, dma
+ * 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 @@ sba_map_sg(struct device *dev, struct sc
+ */
+ 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 @@ sba_alloc_pdir(unsigned int pdir_size)
+ 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 @@ sba_alloc_pdir(unsigned int pdir_size)
+ return (void *) pdir_base;
+ }
+
++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;
++}
++
+ /* setup Mercury or Elroy IBASE/IMASK registers. */
+-static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
++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 */
++ /* 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 @@ sba_ioc_init_pluto(struct parisc_device
+ 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 @@ sba_ioc_init_pluto(struct parisc_device
+ 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 @@ sba_ioc_init_pluto(struct parisc_device
+
+ 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 @@ sba_ioc_init_pluto(struct parisc_device
+ */
+ 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 @@ sba_ioc_init(struct parisc_device *sba,
+ 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 @@ sba_ioc_init(struct parisc_device *sba,
+ 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 @@ sba_ioc_init(struct parisc_device *sba,
+
+ 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 @@ sba_driver_callback(struct parisc_device
+ 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 @@ sba_driver_callback(struct parisc_device
+ }
+
+ 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
+--- a/drivers/parisc/superio.c
++++ b/drivers/parisc/superio.c
+@@ -11,6 +11,7 @@
+ * (C) Copyright 2000 Alex deVries <alex at 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 at 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 @@ static void __devinit superio_serial_ini
+
+ 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 @@ static void __devinit superio_serial_ini
+
+ 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
+--- a/drivers/parisc/wax.c
++++ b/drivers/parisc/wax.c
+@@ -81,7 +81,7 @@ wax_init_chip(struct parisc_device *dev)
+ 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
+--- a/drivers/parport/parport_gsc.c
++++ b/drivers/parport/parport_gsc.c
+@@ -359,11 +359,12 @@ static int __devinit parport_init_chip(s
+ 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
+--- a/drivers/pci/access.c
++++ b/drivers/pci/access.c
+@@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword)
+ 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
+--- a/drivers/pci/hotplug/acpiphp_glue.c
++++ b/drivers/pci/hotplug/acpiphp_glue.c
+@@ -58,6 +58,9 @@ static LIST_HEAD(bridge_list);
+
+ 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 @@ static int enable_device(struct acpiphp_
+ }
+ }
+
++ 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
+--- 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
+--- 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 void __iomem *csr_int_mask;
+
+ 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 @@ static int zt5550_hc_config(struct pci_d
+ 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 @@ static int zt5550_hc_config(struct pci_d
+ 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 @@ static int zt5550_hc_config(struct pci_d
+ 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 @@ static int zt5550_hc_cleanup(void)
+ 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
+--- a/drivers/pci/hotplug/cpqphp_core.c
++++ b/drivers/pci/hotplug/cpqphp_core.c
+@@ -794,12 +794,21 @@ static int cpqhpc_probe(struct pci_dev *
+ 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 @@ static int cpqhpc_probe(struct pci_dev *
+ 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 @@ static int cpqhpc_probe(struct pci_dev *
+ 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 @@ err_free_bus:
+ 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
+--- 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
+--- a/drivers/pci/hotplug/ibmphp_core.c
++++ b/drivers/pci/hotplug/ibmphp_core.c
+@@ -1077,7 +1077,7 @@ static int enable_slot(struct hotplug_sl
+ 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
+--- a/drivers/pci/hotplug/pciehp_pci.c
++++ b/drivers/pci/hotplug/pciehp_pci.c
+@@ -113,7 +113,7 @@ int pciehp_unconfigure_device(struct pci
+ */
+ 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
+--- 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
+--- 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
+--- a/drivers/pci/hotplug/rpaphp.h
++++ b/drivers/pci/hotplug/rpaphp.h
+@@ -92,9 +92,10 @@ extern struct pci_bus *rpaphp_find_pci_b
+ 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
+--- a/drivers/pci/hotplug/rpaphp_core.c
++++ b/drivers/pci/hotplug/rpaphp_core.c
+@@ -426,8 +426,11 @@ static int disable_slot(struct hotplug_s
+
+ 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
+--- 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 @@ static void rpaphp_eeh_remove_bus_device
+ 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
+--- 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
+--- 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 @@ extern int shpchp_debug;
+ #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 slot {
+ 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 event_info {
+ 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 controller {
+ 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 @@ struct resource_lists {
+ * 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_switch_change(u8
+ 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 @@ enum ctrl_offsets {
+ 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 @@ static inline struct slot *shpchp_find_s
+
+ 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 @@ static inline int wait_for_ctrl_irq (str
+ 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 @@ static inline int wait_for_ctrl_irq (str
+ 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 @@ enum php_ctlr_type {
+ 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 @@ struct hpc_ops {
+ 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
+--- 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 at compaq.com>, Greg Kroah-Hartman <greg at kroah.com>, Dely Sy <dely.l.sy at intel.com>"
+@@ -113,8 +105,6 @@ static int init_slots(struct controller
+ 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 @@ static int get_cur_bus_speed (struct hot
+ 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 @@ static int shpc_probe(struct pci_dev *pd
+ 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 @@ static int shpc_probe(struct pci_dev *pd
+ }
+ 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 @@ static int shpc_probe(struct pci_dev *pd
+ 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 @@ err_out_none:
+
+ static int shpc_start_thread(void)
+ {
+- int loop;
+ int retval = 0;
+
+ dbg("Initialize + Start the notification/polling mechanism \n");
+@@ -488,48 +469,21 @@ static int shpc_start_thread(void)
+ 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 @@ static void __exit unload_shpchpd(void)
+ 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 @@ static int __init shpcd_init(void)
+ 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 @@ static void __exit shpcd_cleanup(void)
+ 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
+--- 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 struct semaphore event_exit; /*
+ 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 @@ u8 shpchp_handle_switch_change(u8 hp_slo
+ 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 @@ u8 shpchp_handle_switch_change(u8 hp_slo
+
+ 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 @@ u8 shpchp_handle_switch_change(u8 hp_slo
+ * 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 @@ u8 shpchp_handle_presence_change(u8 hp_s
+ 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 @@ u8 shpchp_handle_presence_change(u8 hp_s
+ /*
+ * 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 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ 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 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ * 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 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ 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 @@ u8 shpchp_handle_power_fault(u8 hp_slot,
+ 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 @@ static u32 change_bus_speed(struct contr
+ 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 @@ enum pci_bus_speed asp, enum pci_bus_spe
+ * 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 @@ static u32 board_added(struct pci_func *
+ 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);
++ 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;
++ }
+
+- return(rc);
+- }
+- shpchp_save_slot_config(ctrl, func);
++ p_slot->status = 0;
++ p_slot->is_a_board = 0x01;
++ p_slot->pwr_save = 1;
+
+- func->status = 0;
+- func->switch_save = 0x10;
+- func->is_a_board = 0x01;
+- func->pwr_save = 1;
++ /* Wait for exclusive access to hardware */
++ down(&ctrl->crit_sect);
+
+- /* 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);
++ p_slot->hpc_ops->green_led_on(p_slot);
+
+- /* Wait for exclusive access to hardware */
+- down(&ctrl->crit_sect);
++ /* Wait for the command to complete */
++ wait_for_ctrl_irq (ctrl);
+
+- p_slot->hpc_ops->green_led_on(p_slot);
++ /* Done with exclusive hardware access */
++ up(&ctrl->crit_sect);
+
+- /* Wait for the command to complete */
+- wait_for_ctrl_irq (ctrl);
++ 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);
+
+- } 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;
+- }
+-
++ 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);
++ return rc;
+ }
+- return 0;
++
++ /* Done with exclusive hardware access */
++ up(&ctrl->crit_sect);
++
++ return(rc);
+ }
+
+
+@@ -1464,55 +574,23 @@ static u32 board_added(struct pci_func *
+ * 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;
+-
+- if (func == NULL)
+- return(1);
++ int rc;
+
+- if (shpchp_unconfigure_device(func))
++ if (shpchp_unconfigure_device(p_slot))
+ 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 @@ static u32 remove_board(struct pci_func
+ /* 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 @@ static void shpchp_pushbutton_thread (un
+ 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 @@ int shpchp_event_start_thread (void)
+ 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 @@ int shpchp_event_start_thread (void)
+ 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 @@ static void interrupt_event_handler(stru
+ {
+ 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 @@ static void interrupt_event_handler(stru
+ 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 @@ int shpchp_enable_slot (struct slot *p_s
+ {
+ 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 @@ int shpchp_enable_slot (struct slot *p_s
+ }
+ 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 @@ int shpchp_disable_slot (struct slot *p_
+ }
+ 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
+--- 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 void start_int_poll_timer(struct
+
+ 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 @@ static int shpc_write_cmd(struct slot *s
+ * 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 shpc_write_cmd(struct slot *s
+
+ 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_check_cmd_status(struct c
+
+ 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_attention_status(stru
+
+ 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_power_status(struct s
+
+ 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_latch_status(struct s
+
+ 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_adapter_status(struct
+
+ 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_prog_int(struct slot
+
+ 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_adapter_speed(struct
+
+ 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_get_mode1_ECC_cap(struct
+
+ 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_query_power_fault(struct
+
+ 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 int hpc_set_attention_status(stru
+
+ 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_on(struct
+
+ 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_off(struct
+
+ 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 shpc_get_ctlr_slot_config(struct con
+ 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 @@ int shpc_get_ctlr_slot_config(struct con
+
+ 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 @@ static void hpc_release_ctlr(struct cont
+ }
+ }
+ 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 @@ DBG_LEAVE_ROUTINE
+
+ 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_power_on_slot(struct slot
+
+ 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_enable(struct slot *
+
+ 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 @@ static int hpc_slot_disable(struct slot
+ 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 @@ static irqreturn_t shpc_isr(int IRQ, voi
+
+ 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 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ * 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 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ 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 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ /* 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 @@ static irqreturn_t shpc_isr(int IRQ, voi
+
+ /* 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 @@ static irqreturn_t shpc_isr(int IRQ, voi
+ 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 irqreturn_t shpc_isr(int IRQ, voi
+
+ 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_max_bus_speed (struct
+
+ 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 @@ static struct hpc_ops shpchp_hpc_ops = {
+ .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 @@ static struct hpc_ops shpchp_hpc_ops = {
+ .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 @@ int shpc_init(struct controller * ctrl,
+ 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 @@ int shpc_init(struct controller * ctrl,
+
+ 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 @@ int shpc_init(struct controller * ctrl,
+ 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 @@ int shpc_init(struct controller * ctrl,
+ 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 @@ int shpc_init(struct controller * ctrl,
+ 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 @@ int shpc_init(struct controller * ctrl,
+
+ /* 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 @@ int shpc_init(struct controller * ctrl,
+ 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 @@ int shpc_init(struct controller * ctrl,
+ 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 @@ int shpc_init(struct controller * ctrl,
+ 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
+--- 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;
+-
+- if (func->pci_dev == NULL)
+- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+-
+- /* 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;
+- }
+- }
+-
+- 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);
+-
+- }
+-
++ u16 pci_cmd, pci_bctl;
++ struct pci_dev *cdev;
++ struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
++
++ /* 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;
++
++ 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);
++ }
++ }
++}
++
++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);
+- }
+- }
+- 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++;
+- }
++ 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;
+ }
+-
+- } 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++);
++ pci_remove_bus_device(temp);
+ }
+-
+- 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
+--- 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)
++void shpchp_create_ctrl_files (struct controller *ctrl)
+ {
+- 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;
++ device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+ }
+-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
+
+-void shpchp_create_ctrl_files (struct controller *ctrl)
++void shpchp_remove_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);
++ 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
+--- 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 at 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 at kroah.com>, <kristen.c.accardi at 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
+--- 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 @@ static u8 * acpi_path_name( acpi_handle
+ 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 @@ static void acpi_get__hpp ( struct acpi_
+ 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));
+-
+- 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);
++ hpp->cache_line_size = nui[0];
++ hpp->latency_timer = nui[1];
++ hpp->enable_serr = nui[2];
++ hpp->enable_perr = nui[3];
++
++ 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);
+-}
+-
+-static void acpi_run_oshp ( struct acpi_bridge *ab)
+-{
+- acpi_status status;
+- u8 *path_name = acpi_path_name(ab->handle);
+-
+- /* run OSHP */
+- status = acpi_evaluate_object(ab->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)
++static void acpi_run_oshp(acpi_handle handle)
+ {
+- 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);
++ /* run OSHP */
++ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
+ 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);
+- }
+-
+- 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;
++ dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
+ }
+- 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 @@ int shpchprm_get_physical_slot_number(st
+ 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;
+-}
+-
+-int shpchprm_set_hpp(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type
+- )
+-{
+- 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;
+-
+- 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;
++ /*
++ * 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);
+ }
+
+-void shpchprm_enable_card(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type)
++void get_hp_params_from_firmware(struct pci_dev *dev,
++ struct hotplug_params *hpp)
+ {
+- 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);
+- }
++ acpi_status status = AE_NOT_FOUND;
++ struct pci_dev *pdev = dev;
+
+- 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
+--- 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 @@ int shpchprm_get_physical_slot_number(st
+ 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 __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;
+-}
+-
+-/*
+- * 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)
+-{
+- 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);
+-}
+-
+-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)
+ {
+- 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;
++ return;
+ }
+
+-void shpchprm_enable_card(
+- struct controller *ctrl,
+- struct pci_func *func,
+- u8 card_type)
++void get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+- 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);
+- }
++ return;
+ }
+
+-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
+--- 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 at 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 at kroah.com>, <kristen.c.accardi at 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
+--- 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 "shpchp.h"
+-#include "shpchprm.h"
+-#include "shpchprm_nonacpi.h"
++#include <linux/slab.h>
+
+-void shpchprm_cleanup(void)
+-{
+- return;
+-}
+-
+-int shpchprm_print_pirt(void)
+-{
+- return 0;
+-}
++#include "shpchp.h"
+
+ int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
+ {
+@@ -60,375 +45,13 @@ int shpchprm_get_physical_slot_number(st
+ return 0;
+ }
+
+-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 phprm_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 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)
++void get_hp_params_from_firmware(struct pci_dev *dev,
++ struct hotplug_params *hpp)
+ {
+- 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;
++ return;
+ }
+
+-int shpchprm_init(enum php_ctlr_type ctrl_type)
++void get_hp_hw_control_from_firmware(struct pci_dev *dev)
+ {
+- 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
+--- 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 at 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 at kroah.com>, <kristen.c.accardi at 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
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -575,6 +575,8 @@ static int msi_capability_init(struct pc
+ /**
+ * 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
+--- 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 @@ struct pci_dynid {
+ #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 @@ static int pci_call_probe(struct pci_dri
+
+ /**
+ * __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 @@ int pci_register_driver(struct pci_drive
+ * 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_dev_driver(const struct pci_dev *dev
+
+ /**
+ * 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
+--- a/drivers/pci/pci-sysfs.c
++++ b/drivers/pci/pci-sysfs.c
+@@ -130,7 +130,7 @@ pci_read_config(struct kobject *kobj, ch
+
+ 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 @@ pci_read_config(struct kobject *kobj, ch
+
+ 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 @@ pci_read_config(struct kobject *kobj, ch
+
+ 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 @@ pci_read_config(struct kobject *kobj, ch
+
+ 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 @@ pci_read_config(struct kobject *kobj, ch
+
+ 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 @@ pci_write_config(struct kobject *kobj, c
+ }
+
+ 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 @@ pci_write_config(struct kobject *kobj, c
+ 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 @@ pci_write_config(struct kobject *kobj, c
+ 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 @@ pci_write_config(struct kobject *kobj, c
+ 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
+--- 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_restore_bars(struct pci_dev *dev)
+ 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 @@ pci_restore_bars(struct pci_dev *dev)
+ * -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 @@ pci_set_power_state(struct pci_dev *dev,
+ * 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_clear_mwi(struct pci_dev *dev)
+
+ /**
+ * 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
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -15,6 +15,13 @@ extern int pci_bus_alloc_resource(struct
+ 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
+--- 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 int pcie_port_remove_service(stru
+
+ 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 @@ static int pcie_port_suspend_service(str
+ 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
+--- 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
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -669,6 +669,7 @@ static void pci_release_dev(struct devic
+
+ /**
+ * 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
+--- a/drivers/pci/proc.c
++++ b/drivers/pci/proc.c
+@@ -80,7 +80,7 @@ proc_bus_pci_read(struct file *file, cha
+
+ 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 @@ proc_bus_pci_read(struct file *file, cha
+
+ 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 @@ proc_bus_pci_read(struct file *file, cha
+
+ 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 @@ proc_bus_pci_read(struct file *file, cha
+
+ 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 @@ proc_bus_pci_read(struct file *file, cha
+
+ 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 @@ proc_bus_pci_write(struct file *file, co
+ 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 @@ proc_bus_pci_write(struct file *file, co
+ 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 @@ proc_bus_pci_write(struct file *file, co
+ 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 @@ proc_bus_pci_write(struct file *file, co
+ 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 @@ proc_bus_pci_write(struct file *file, co
+ 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 @@ static int show_dev_config(struct seq_fi
+
+ 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
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -7,6 +7,9 @@
+ *
+ * Copyright (c) 1999 Martin Mares <mj at 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 @@ static void piix4_mem_quirk(struct pci_d
+ /*
+ * 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 @@ static void __devinit quirk_piix4_acpi(s
+ pci_read_config_dword(dev, 0x40, ®ion);
+ quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
+ pci_read_config_dword(dev, 0x90, ®ion);
+- 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_I
+ 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, ®ion);
++ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
++
++ pci_read_config_dword(dev, 0x48, ®ion);
++ 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 @@ static void quirk_via_irq(struct pci_dev
+ 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 @@ static void __init asus_hides_smbus_host
+ 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 @@ static void __init asus_hides_smbus_host
+ 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_I
+ 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_I
+ 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 @@ static void __init quirk_sis_96x_smbus(s
+ 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
+--- 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
+--- 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 @@ sys_pciconfig_read(unsigned long bus, un
+ 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 @@ sys_pciconfig_write(unsigned long bus, u
+ 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 @@ sys_pciconfig_write(unsigned long bus, u
+ 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 @@ sys_pciconfig_write(unsigned long bus, u
+ 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/Kconfig b/drivers/pcmcia/Kconfig
+--- a/drivers/pcmcia/Kconfig
++++ b/drivers/pcmcia/Kconfig
+@@ -154,6 +154,16 @@ config TCIC
+ "Bridge" is the name used for the hardware inside your computer that
+ PCMCIA cards are plugged into. If unsure, say N.
+
++config PCMCIA_M8XX
++ tristate "MPC8xx PCMCIA support"
++ depends on PCMCIA && PPC
++ select PCCARD_NONSTATIC
++ help
++ Say Y here to include support for PowerPC 8xx series PCMCIA
++ controller.
++
++ This driver is also available as a module called m8xx_pcmcia.
++
+ config HD64465_PCMCIA
+ tristate "HD64465 host bridge support"
+ depends on HD64465 && PCMCIA
+diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
+--- a/drivers/pcmcia/Makefile
++++ b/drivers/pcmcia/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_PD6729) += pd6729.o
+ obj-$(CONFIG_I82365) += i82365.o
+ obj-$(CONFIG_I82092) += i82092.o
+ obj-$(CONFIG_TCIC) += tcic.o
++obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
+ obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
+ obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
+ obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
+@@ -42,9 +43,11 @@ pxa2xx_core-y += soc_common.o pxa2xx
+ 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
+@@ -57,6 +60,7 @@ sa1111_cs-$(CONFIG_SA1100_JORNADA720) +
+ 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
+--- 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 @@ static int db1x00_pcmcia_hw_init(struct
+ {
+ #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 @@ db1x00_pcmcia_socket_state(struct au1000
+ 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
+--- a/drivers/pcmcia/au1000_generic.c
++++ b/drivers/pcmcia/au1000_generic.c
+@@ -42,7 +42,7 @@
+ #include <linux/notifier.h>
+ #include <linux/interrupt.h>
+ #include <linux/spinlock.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -490,7 +490,7 @@ int au1x00_drv_pcmcia_remove(struct devi
+ 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_probe(struc
+ }
+
+
+-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 @@ static int __init au1x00_pcmcia_init(voi
+ int error = 0;
+ if ((error = driver_register(&au1x00_pcmcia_driver)))
+ return error;
+- platform_device_register(&au1x00_device);
+ return error;
+ }
+
+@@ -573,7 +551,6 @@ static int __init au1x00_pcmcia_init(voi
+ 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
+--- 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
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -1157,7 +1157,8 @@ static struct pcmcia_callback pcmcia_bus
+ .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 @@ static int __devinit pcmcia_bus_add_sock
+ 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
+--- a/drivers/pcmcia/hd64465_ss.c
++++ b/drivers/pcmcia/hd64465_ss.c
+@@ -37,7 +37,7 @@
+ #include <asm/errno.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/hd64465/hd64465.h>
+@@ -844,27 +844,11 @@ static void hs_exit_socket(hs_socket_t *
+ 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
+--- a/drivers/pcmcia/i82365.c
++++ b/drivers/pcmcia/i82365.c
+@@ -47,7 +47,7 @@
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/bitops.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+@@ -1332,27 +1332,11 @@ static struct pccard_operations pcic_ope
+
+ /*====================================================================*/
+
+-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
+--- a/drivers/pcmcia/m32r_cfc.c
++++ b/drivers/pcmcia/m32r_cfc.c
+@@ -23,7 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/bitops.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+@@ -731,28 +731,11 @@ static struct pccard_operations pcc_oper
+
+ /*====================================================================*/
+
+-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
+--- a/drivers/pcmcia/m32r_pcc.c
++++ b/drivers/pcmcia/m32r_pcc.c
+@@ -23,7 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+ #include <asm/bitops.h>
+@@ -695,28 +695,11 @@ static struct pccard_operations pcc_oper
+
+ /*====================================================================*/
+
+-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/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
+new file mode 100644
+--- /dev/null
++++ b/drivers/pcmcia/m8xx_pcmcia.c
+@@ -0,0 +1,1290 @@
++/*
++ * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
++ *
++ * (C) 1999-2000 Magnus Damm <damm at bitsmart.com>
++ * (C) 2001-2002 Montavista Software, Inc.
++ * <mlocke at mvista.com>
++ *
++ * Support for two slots by Cyclades Corporation
++ * <oliver.kurth at cyclades.de>
++ * Further fixes, v2.6 kernel port
++ * <marcelo.tosatti at cyclades.com>
++ *
++ * "The ExCA standard specifies that socket controllers should provide
++ * two IO and five memory windows per socket, which can be independently
++ * configured and positioned in the host address space and mapped to
++ * arbitrary segments of card address space. " - David A Hinds. 1999
++ *
++ * This controller does _not_ meet the ExCA standard.
++ *
++ * m8xx pcmcia controller brief info:
++ * + 8 windows (attrib, mem, i/o)
++ * + up to two slots (SLOT_A and SLOT_B)
++ * + inputpins, outputpins, event and mask registers.
++ * - no offset register. sigh.
++ *
++ * Because of the lacking offset register we must map the whole card.
++ * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
++ * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
++ * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
++ * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
++ * They are maximum 64KByte each...
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/string.h>
++
++#include <asm/io.h>
++#include <asm/bitops.h>
++#include <asm/segment.h>
++#include <asm/system.h>
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/timer.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/mpc8xx.h>
++#include <asm/8xx_immap.h>
++#include <asm/irq.h>
++
++#include <pcmcia/version.h>
++#include <pcmcia/cs_types.h>
++#include <pcmcia/cs.h>
++#include <pcmcia/ss.h>
++
++#ifdef PCMCIA_DEBUG
++static int pc_debug = PCMCIA_DEBUG;
++module_param(pc_debug, int, 0);
++#define dprintk(args...) printk(KERN_DEBUG "m8xx_pcmcia: " args);
++#else
++#define dprintk(args...)
++#endif
++
++#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
++#define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args)
++
++static const char *version = "Version 0.06, Aug 2005";
++MODULE_LICENSE("Dual MPL/GPL");
++
++#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
++
++/* The RPX series use SLOT_B */
++#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
++#define CONFIG_PCMCIA_SLOT_B
++#define CONFIG_BD_IS_MHZ
++#endif
++
++/* The ADS board use SLOT_A */
++#ifdef CONFIG_ADS
++#define CONFIG_PCMCIA_SLOT_A
++#define CONFIG_BD_IS_MHZ
++#endif
++
++/* The FADS series are a mess */
++#ifdef CONFIG_FADS
++#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
++#define CONFIG_PCMCIA_SLOT_A
++#else
++#define CONFIG_PCMCIA_SLOT_B
++#endif
++#endif
++
++/* Cyclades ACS uses both slots */
++#ifdef CONFIG_PRxK
++#define CONFIG_PCMCIA_SLOT_A
++#define CONFIG_PCMCIA_SLOT_B
++#endif
++
++#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
++
++#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
++
++#define PCMCIA_SOCKETS_NO 2
++/* We have only 8 windows, dualsocket support will be limited. */
++#define PCMCIA_MEM_WIN_NO 2
++#define PCMCIA_IO_WIN_NO 2
++#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"
++
++#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)
++
++#define PCMCIA_SOCKETS_NO 1
++/* full support for one slot */
++#define PCMCIA_MEM_WIN_NO 5
++#define PCMCIA_IO_WIN_NO 2
++
++/* define _slot_ to be able to optimize macros */
++
++#ifdef CONFIG_PCMCIA_SLOT_A
++#define _slot_ 0
++#define PCMCIA_SLOT_MSG "SLOT_A"
++#else
++#define _slot_ 1
++#define PCMCIA_SLOT_MSG "SLOT_B"
++#endif
++
++#else
++#error m8xx_pcmcia: Bad configuration!
++#endif
++
++/* ------------------------------------------------------------------------- */
++
++#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */
++#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */
++#define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */
++
++#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level */
++
++/* ------------------------------------------------------------------------- */
++
++/* 2.4.x and newer has this always in HZ */
++#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))
++
++static int pcmcia_schlvl = PCMCIA_SCHLVL;
++
++static spinlock_t events_lock = SPIN_LOCK_UNLOCKED;
++
++
++#define PCMCIA_SOCKET_KEY_5V 1
++#define PCMCIA_SOCKET_KEY_LV 2
++
++/* look up table for pgcrx registers */
++static u32 *m8xx_pgcrx[2] = {
++ &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra,
++ &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb
++};
++
++/*
++ * This structure is used to address each window in the PCMCIA controller.
++ *
++ * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly
++ * after pcmcia_win[n]...
++ */
++
++struct pcmcia_win {
++ u32 br;
++ u32 or;
++};
++
++/*
++ * For some reason the hardware guys decided to make both slots share
++ * some registers.
++ *
++ * Could someone invent object oriented hardware ?
++ *
++ * The macros are used to get the right bit from the registers.
++ * SLOT_A : slot = 0
++ * SLOT_B : slot = 1
++ */
++
++#define M8XX_PCMCIA_VS1(slot) (0x80000000 >> (slot << 4))
++#define M8XX_PCMCIA_VS2(slot) (0x40000000 >> (slot << 4))
++#define M8XX_PCMCIA_VS_MASK(slot) (0xc0000000 >> (slot << 4))
++#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))
++
++#define M8XX_PCMCIA_WP(slot) (0x20000000 >> (slot << 4))
++#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
++#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
++#define M8XX_PCMCIA_BVD2(slot) (0x04000000 >> (slot << 4))
++#define M8XX_PCMCIA_BVD1(slot) (0x02000000 >> (slot << 4))
++#define M8XX_PCMCIA_RDY(slot) (0x01000000 >> (slot << 4))
++#define M8XX_PCMCIA_RDY_L(slot) (0x00800000 >> (slot << 4))
++#define M8XX_PCMCIA_RDY_H(slot) (0x00400000 >> (slot << 4))
++#define M8XX_PCMCIA_RDY_R(slot) (0x00200000 >> (slot << 4))
++#define M8XX_PCMCIA_RDY_F(slot) (0x00100000 >> (slot << 4))
++#define M8XX_PCMCIA_MASK(slot) (0xFFFF0000 >> (slot << 4))
++
++#define M8XX_PCMCIA_POR_VALID 0x00000001
++#define M8XX_PCMCIA_POR_WRPROT 0x00000002
++#define M8XX_PCMCIA_POR_ATTRMEM 0x00000010
++#define M8XX_PCMCIA_POR_IO 0x00000018
++#define M8XX_PCMCIA_POR_16BIT 0x00000040
++
++#define M8XX_PGCRX(slot) m8xx_pgcrx[slot]
++
++#define M8XX_PGCRX_CXOE 0x00000080
++#define M8XX_PGCRX_CXRESET 0x00000040
++
++/* we keep one lookup table per socket to check flags */
++
++#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */
++
++struct event_table {
++ u32 regbit;
++ u32 eventbit;
++};
++
++struct socket_info {
++ void (*handler)(void *info, u32 events);
++ void *info;
++
++ u32 slot;
++
++ socket_state_t state;
++ struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
++ struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
++ struct event_table events[PCMCIA_EVENTS_MAX];
++ struct pcmcia_socket socket;
++};
++
++static struct socket_info socket[PCMCIA_SOCKETS_NO];
++
++/*
++ * Search this table to see if the windowsize is
++ * supported...
++ */
++
++#define M8XX_SIZES_NO 32
++
++static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] =
++{
++ 0x00000001, 0x00000002, 0x00000008, 0x00000004,
++ 0x00000080, 0x00000040, 0x00000010, 0x00000020,
++ 0x00008000, 0x00004000, 0x00001000, 0x00002000,
++ 0x00000100, 0x00000200, 0x00000800, 0x00000400,
++
++ 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
++ 0x00010000, 0x00020000, 0x00080000, 0x00040000,
++ 0x00800000, 0x00400000, 0x00100000, 0x00200000
++};
++
++/* ------------------------------------------------------------------------- */
++
++static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs);
++
++#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
++
++/* ------------------------------------------------------------------------- */
++/* board specific stuff: */
++/* voltage_set(), hardware_enable() and hardware_disable() */
++/* ------------------------------------------------------------------------- */
++/* RPX Boards from Embedded Planet */
++
++#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
++
++/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
++ * SYPCR is write once only, therefore must the slowest memory be faster
++ * than the bus monitor or we will get a machine check due to the bus timeout.
++ */
++
++#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
++
++#undef PCMCIA_BMT_LIMIT
++#define PCMCIA_BMT_LIMIT (6*8)
++
++static int voltage_set(int slot, int vcc, int vpp)
++{
++ u32 reg = 0;
++
++ switch(vcc) {
++ case 0: break;
++ case 33:
++ reg |= BCSR1_PCVCTL4;
++ break;
++ case 50:
++ reg |= BCSR1_PCVCTL5;
++ break;
++ default:
++ return 1;
++ }
++
++ switch(vpp) {
++ case 0: break;
++ case 33:
++ case 50:
++ if(vcc == vpp)
++ reg |= BCSR1_PCVCTL6;
++ else
++ return 1;
++ break;
++ case 120:
++ reg |= BCSR1_PCVCTL7;
++ default:
++ return 1;
++ }
++
++ if(!((vcc == 50) || (vcc == 0)))
++ return 1;
++
++ /* first, turn off all power */
++
++ out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 | BCSR1_PCVCTL6 | BCSR1_PCVCTL7));
++
++ /* enable new powersettings */
++
++ out_be32(((u32 *)RPX_CSR_ADDR), in_be32(((u32 *)RPX_CSR_ADDR)) | reg);
++
++ return 0;
++}
++
++#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
++#define hardware_enable(_slot_) /* No hardware to enable */
++#define hardware_disable(_slot_) /* No hardware to disable */
++
++#endif /* CONFIG_RPXCLASSIC */
++
++/* FADS Boards from Motorola */
++
++#if defined(CONFIG_FADS)
++
++#define PCMCIA_BOARD_MSG "FADS"
++
++static int voltage_set(int slot, int vcc, int vpp)
++{
++ u32 reg = 0;
++
++ switch(vcc) {
++ case 0:
++ break;
++ case 33:
++ reg |= BCSR1_PCCVCC0;
++ break;
++ case 50:
++ reg |= BCSR1_PCCVCC1;
++ break;
++ default:
++ return 1;
++ }
++
++ switch(vpp) {
++ case 0:
++ break;
++ case 33:
++ case 50:
++ if(vcc == vpp)
++ reg |= BCSR1_PCCVPP1;
++ else
++ return 1;
++ break;
++ case 120:
++ if ((vcc == 33) || (vcc == 50))
++ reg |= BCSR1_PCCVPP0;
++ else
++ return 1;
++ default:
++ return 1;
++ }
++
++ /* first, turn off all power */
++ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
++
++ /* enable new powersettings */
++ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | reg);
++
++ return 0;
++}
++
++#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
++
++static void hardware_enable(int slot)
++{
++ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~BCSR1_PCCEN);
++}
++
++static void hardware_disable(int slot)
++{
++ out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | BCSR1_PCCEN);
++}
++
++#endif
++
++/* ------------------------------------------------------------------------- */
++/* Motorola MBX860 */
++
++#if defined(CONFIG_MBX)
++
++#define PCMCIA_BOARD_MSG "MBX"
++
++static int voltage_set(int slot, int vcc, int vpp)
++{
++ u8 reg = 0;
++
++ switch(vcc) {
++ case 0:
++ break;
++ case 33:
++ reg |= CSR2_VCC_33;
++ break;
++ case 50:
++ reg |= CSR2_VCC_50;
++ break;
++ default:
++ return 1;
++ }
++
++ switch(vpp) {
++ case 0:
++ break;
++ case 33:
++ case 50:
++ if(vcc == vpp)
++ reg |= CSR2_VPP_VCC;
++ else
++ return 1;
++ break;
++ case 120:
++ if ((vcc == 33) || (vcc == 50))
++ reg |= CSR2_VPP_12;
++ else
++ return 1;
++ default:
++ return 1;
++ }
++
++ /* first, turn off all power */
++ out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
++
++ /* enable new powersettings */
++ out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) | reg);
++
++ return 0;
++}
++
++#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
++#define hardware_enable(_slot_) /* No hardware to enable */
++#define hardware_disable(_slot_) /* No hardware to disable */
++
++#endif /* CONFIG_MBX */
++
++#if defined(CONFIG_PRxK)
++#include <asm/cpld.h>
++extern volatile fpga_pc_regs *fpga_pc;
++
++#define PCMCIA_BOARD_MSG "MPC855T"
++
++static int voltage_set(int slot, int vcc, int vpp)
++{
++ u8 reg = 0;
++ u8 regread;
++ cpld_regs *ccpld = get_cpld();
++
++ switch(vcc) {
++ case 0:
++ break;
++ case 33:
++ reg |= PCMCIA_VCC_33;
++ break;
++ case 50:
++ reg |= PCMCIA_VCC_50;
++ break;
++ default:
++ return 1;
++ }
++
++ switch(vpp) {
++ case 0:
++ break;
++ case 33:
++ case 50:
++ if(vcc == vpp)
++ reg |= PCMCIA_VPP_VCC;
++ else
++ return 1;
++ break;
++ case 120:
++ if ((vcc == 33) || (vcc == 50))
++ reg |= PCMCIA_VPP_12;
++ else
++ return 1;
++ default:
++ return 1;
++ }
++
++ reg = reg >> (slot << 2);
++ regread = in_8(&ccpld->fpga_pc_ctl);
++ if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
++ /* enable new powersettings */
++ regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
++ out_8(&ccpld->fpga_pc_ctl, reg | regread);
++ msleep(100);
++ }
++
++ return 0;
++}
++
++#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
++#define hardware_enable(_slot_) /* No hardware to enable */
++#define hardware_disable(_slot_) /* No hardware to disable */
++
++#endif /* CONFIG_PRxK */
++
++static void m8xx_shutdown(void)
++{
++ u32 m, i;
++ struct pcmcia_win *w;
++
++ for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
++ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
++
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i));
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i));
++
++ /* turn off interrupt and disable CxOE */
++ out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
++
++ /* turn off memory windows */
++ for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
++ out_be32(&w->or, 0); /* set to not valid */
++ w++;
++ }
++
++ /* turn off voltage */
++ voltage_set(i, 0, 0);
++
++ /* disable external hardware */
++ hardware_disable(i);
++ }
++
++ free_irq(pcmcia_schlvl, NULL);
++}
++
++/* copied from tcic.c */
++
++static int m8xx_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 m8xx_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 m8xx_driver = {
++ .name = "m8xx-pcmcia",
++ .bus = &platform_bus_type,
++ .suspend = m8xx_drv_suspend,
++ .resume = m8xx_drv_resume,
++};
++
++static struct platform_device m8xx_device = {
++ .name = "m8xx-pcmcia",
++ .id = 0,
++};
++
++static u32 pending_events[PCMCIA_SOCKETS_NO];
++static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
++
++static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
++{
++ struct socket_info *s;
++ struct event_table *e;
++ unsigned int i, events, pscr, pipr, per;
++
++ dprintk("Interrupt!\n");
++ /* get interrupt sources */
++
++ pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr);
++ pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
++ per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per);
++
++ for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
++ s = &socket[i];
++ e = &s->events[0];
++ events = 0;
++
++ while(e->regbit) {
++ if(pscr & e->regbit)
++ events |= e->eventbit;
++
++ e++;
++ }
++
++ /*
++ * report only if both card detect signals are the same
++ * not too nice done,
++ * we depend on that CD2 is the bit to the left of CD1...
++ */
++ if(events & SS_DETECT)
++ if(((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
++ (pipr & M8XX_PCMCIA_CD1(i)))
++ {
++ events &= ~SS_DETECT;
++ }
++
++#ifdef PCMCIA_GLITCHY_CD
++ /*
++ * I've experienced CD problems with my ADS board.
++ * We make an extra check to see if there was a
++ * real change of Card detection.
++ */
++
++ if((events & SS_DETECT) &&
++ ((pipr &
++ (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
++ (s->state.Vcc | s->state.Vpp)) {
++ events &= ~SS_DETECT;
++ /*printk( "CD glitch workaround - CD = 0x%08x!\n",
++ (pipr & (M8XX_PCMCIA_CD2(i)
++ | M8XX_PCMCIA_CD1(i))));*/
++ }
++#endif
++
++ /* call the handler */
++
++ dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, "
++ "pipr = 0x%08x\n",
++ i, events, pscr, pipr);
++
++ if(events) {
++ spin_lock(&pending_event_lock);
++ pending_events[i] |= events;
++ spin_unlock(&pending_event_lock);
++ /*
++ * Turn off RDY_L bits in the PER mask on
++ * CD interrupt receival.
++ *
++ * They can generate bad interrupts on the
++ * ACS4,8,16,32. - marcelo
++ */
++ per &= ~M8XX_PCMCIA_RDY_L(0);
++ per &= ~M8XX_PCMCIA_RDY_L(1);
++
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per);
++
++ if (events)
++ pcmcia_parse_events(&socket[i].socket, events);
++ }
++ }
++
++ /* clear the interrupt sources */
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr);
++
++ dprintk("Interrupt done.\n");
++
++ return IRQ_HANDLED;
++}
++
++static u32 m8xx_get_graycode(u32 size)
++{
++ u32 k;
++
++ for(k = 0; k < M8XX_SIZES_NO; k++)
++ if(m8xx_size_to_gray[k] == size)
++ break;
++
++ if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
++ k = -1;
++
++ return k;
++}
++
++static u32 m8xx_get_speed(u32 ns, u32 is_io)
++{
++ u32 reg, clocks, psst, psl, psht;
++
++ if(!ns) {
++
++ /*
++ * We get called with IO maps setup to 0ns
++ * if not specified by the user.
++ * They should be 255ns.
++ */
++
++ if(is_io)
++ ns = 255;
++ else
++ ns = 100; /* fast memory if 0 */
++ }
++
++ /*
++ * In PSST, PSL, PSHT fields we tell the controller
++ * timing parameters in CLKOUT clock cycles.
++ * CLKOUT is the same as GCLK2_50.
++ */
++
++/* how we want to adjust the timing - in percent */
++
++#define ADJ 180 /* 80 % longer accesstime - to be sure */
++
++ clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
++ clocks = (clocks * ADJ) / (100*1000);
++ if(clocks >= PCMCIA_BMT_LIMIT) {
++ printk( "Max access time limit reached\n");
++ clocks = PCMCIA_BMT_LIMIT-1;
++ }
++
++ psst = clocks / 7; /* setup time */
++ psht = clocks / 7; /* hold time */
++ psl = (clocks * 5) / 7; /* strobe length */
++
++ psst += clocks - (psst + psht + psl);
++
++ reg = psst << 12;
++ reg |= psl << 7;
++ reg |= psht << 16;
++
++ return reg;
++}
++
++static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
++{
++ int lsock = container_of(sock, struct socket_info, socket)->slot;
++ struct socket_info *s = &socket[lsock];
++ unsigned int pipr, reg;
++
++ pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
++
++ *value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
++ | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
++ *value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
++
++ if (s->state.flags & SS_IOCARD)
++ *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0;
++ else {
++ *value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0;
++ *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0;
++ *value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0;
++ }
++
++ if (s->state.Vcc | s->state.Vpp)
++ *value |= SS_POWERON;
++
++ /*
++ * Voltage detection:
++ * This driver only supports 16-Bit pc-cards.
++ * Cardbus is not handled here.
++ *
++ * To determine what voltage to use we must read the VS1 and VS2 pin.
++ * Depending on what socket type is present,
++ * different combinations mean different things.
++ *
++ * Card Key Socket Key VS1 VS2 Card Vcc for CIS parse
++ *
++ * 5V 5V, LV* NC NC 5V only 5V (if available)
++ *
++ * 5V 5V, LV* GND NC 5 or 3.3V as low as possible
++ *
++ * 5V 5V, LV* GND GND 5, 3.3, x.xV as low as possible
++ *
++ * LV* 5V - - shall not fit into socket
++ *
++ * LV* LV* GND NC 3.3V only 3.3V
++ *
++ * LV* LV* NC GND x.xV x.xV (if avail.)
++ *
++ * LV* LV* GND GND 3.3 or x.xV as low as possible
++ *
++ * *LV means Low Voltage
++ *
++ *
++ * That gives us the following table:
++ *
++ * Socket VS1 VS2 Voltage
++ *
++ * 5V NC NC 5V
++ * 5V NC GND none (should not be possible)
++ * 5V GND NC >= 3.3V
++ * 5V GND GND >= x.xV
++ *
++ * LV NC NC 5V (if available)
++ * LV NC GND x.xV (if available)
++ * LV GND NC 3.3V
++ * LV GND GND >= x.xV
++ *
++ * So, how do I determine if I have a 5V or a LV
++ * socket on my board? Look at the socket!
++ *
++ *
++ * Socket with 5V key:
++ * ++--------------------------------------------+
++ * || |
++ * || ||
++ * || ||
++ * | |
++ * +---------------------------------------------+
++ *
++ * Socket with LV key:
++ * ++--------------------------------------------+
++ * || |
++ * | ||
++ * | ||
++ * | |
++ * +---------------------------------------------+
++ *
++ *
++ * With other words - LV only cards does not fit
++ * into the 5V socket!
++ */
++
++ /* read out VS1 and VS2 */
++
++ reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
++ >> M8XX_PCMCIA_VS_SHIFT(lsock);
++
++ if(socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
++ switch(reg) {
++ case 1:
++ *value |= SS_3VCARD;
++ break; /* GND, NC - 3.3V only */
++ case 2:
++ *value |= SS_XVCARD;
++ break; /* NC. GND - x.xV only */
++ };
++ }
++
++ dprintk("GetStatus(%d) = %#2.2x\n", lsock, *value);
++ return 0;
++}
++
++static int m8xx_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
++{
++ int lsock = container_of(sock, struct socket_info, socket)->slot;
++ *state = socket[lsock].state; /* copy the whole structure */
++
++ dprintk("GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
++ "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
++ state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
++ return 0;
++}
++
++static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
++{
++ int lsock = container_of(sock, struct socket_info, socket)->slot;
++ struct socket_info *s = &socket[lsock];
++ struct event_table *e;
++ unsigned int reg;
++ unsigned long flags;
++
++ dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
++ "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
++ state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
++
++ /* First, set voltage - bail out if invalid */
++ if(voltage_set(lsock, state->Vcc, state->Vpp))
++ return -EINVAL;
++
++ /* Take care of reset... */
++ if(state->flags & SS_RESET)
++ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */
++ else
++ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
++
++ /* ... and output enable. */
++
++ /* The CxOE signal is connected to a 74541 on the ADS.
++ I guess most other boards used the ADS as a reference.
++ I tried to control the CxOE signal with SS_OUTPUT_ENA,
++ but the reset signal seems connected via the 541.
++ If the CxOE is left high are some signals tristated and
++ no pullups are present -> the cards act wierd.
++ So right now the buffers are enabled if the power is on. */
++
++ if(state->Vcc || state->Vpp)
++ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
++ else
++ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
++
++ /*
++ * We'd better turn off interrupts before
++ * we mess with the events-table..
++ */
++
++ spin_lock_irqsave(&events_lock, flags);
++
++ /*
++ * Play around with the interrupt mask to be able to
++ * give the events the generic pcmcia driver wants us to.
++ */
++
++ e = &s->events[0];
++ reg = 0;
++
++ if(state->csc_mask & SS_DETECT) {
++ e->eventbit = SS_DETECT;
++ reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
++ | M8XX_PCMCIA_CD1(lsock));
++ e++;
++ }
++ if(state->flags & SS_IOCARD) {
++ /*
++ * I/O card
++ */
++ if(state->csc_mask & SS_STSCHG) {
++ e->eventbit = SS_STSCHG;
++ reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
++ e++;
++ }
++ /*
++ * If io_irq is non-zero we should enable irq.
++ */
++ if(state->io_irq) {
++ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24);
++ /*
++ * Strange thing here:
++ * The manual does not tell us which interrupt
++ * the sources generate.
++ * Anyhow, I found out that RDY_L generates IREQLVL.
++ *
++ * We use level triggerd interrupts, and they don't
++ * have to be cleared in PSCR in the interrupt handler.
++ */
++ reg |= M8XX_PCMCIA_RDY_L(lsock);
++ }
++ else
++ out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
++ }
++ else {
++ /*
++ * Memory card
++ */
++ if(state->csc_mask & SS_BATDEAD) {
++ e->eventbit = SS_BATDEAD;
++ reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
++ e++;
++ }
++ if(state->csc_mask & SS_BATWARN) {
++ e->eventbit = SS_BATWARN;
++ reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
++ e++;
++ }
++ /* What should I trigger on - low/high,raise,fall? */
++ if(state->csc_mask & SS_READY) {
++ e->eventbit = SS_READY;
++ reg |= e->regbit = 0; //??
++ e++;
++ }
++ }
++
++ e->regbit = 0; /* terminate list */
++
++ /*
++ * Clear the status changed .
++ * Port A and Port B share the same port.
++ * Writing ones will clear the bits.
++ */
++
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg);
++
++ /*
++ * Write the mask.
++ * Port A and Port B share the same port.
++ * Need for read-modify-write.
++ * Ones will enable the interrupt.
++ */
++
++ /*
++ reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per
++ & M8XX_PCMCIA_MASK(lsock);
++ */
++
++ reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
++ (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
++
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg);
++
++ spin_unlock_irqrestore(&events_lock, flags);
++
++ /* copy the struct and modify the copy */
++
++ s->state = *state;
++
++ return 0;
++}
++
++static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
++{
++ int lsock = container_of(sock, struct socket_info, socket)->slot;
++
++ struct socket_info *s = &socket[lsock];
++ struct pcmcia_win *w;
++ unsigned int reg, winnr;
++
++#define M8XX_SIZE (io->stop - io->start + 1)
++#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
++
++ dprintk( "SetIOMap(%d, %d, %#2.2x, %d ns, "
++ "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
++ io->speed, io->start, io->stop);
++
++ if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
++ || (io->stop > 0xffff) || (io->stop < io->start))
++ return -EINVAL;
++
++ if((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
++ return -EINVAL;
++
++ if(io->flags & MAP_ACTIVE) {
++
++ dprintk( "io->flags & MAP_ACTIVE\n");
++
++ winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
++ + (lsock * PCMCIA_IO_WIN_NO) + io->map;
++
++ /* setup registers */
++
++ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
++ w += winnr;
++
++ out_be32(&w->or, 0); /* turn off window first */
++ out_be32(&w->br, M8XX_BASE);
++
++ reg <<= 27;
++ reg |= M8XX_PCMCIA_POR_IO |(lsock << 2);
++
++ reg |= m8xx_get_speed(io->speed, 1);
++
++ if(io->flags & MAP_WRPROT)
++ reg |= M8XX_PCMCIA_POR_WRPROT;
++
++ /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/
++ if(io->flags & MAP_16BIT)
++ reg |= M8XX_PCMCIA_POR_16BIT;
++
++ if(io->flags & MAP_ACTIVE)
++ reg |= M8XX_PCMCIA_POR_VALID;
++
++ out_be32(&w->or, reg);
++
++ dprintk("Socket %u: Mapped io window %u at %#8.8x, "
++ "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
++ } else {
++ /* shutdown IO window */
++ winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
++ + (lsock * PCMCIA_IO_WIN_NO) + io->map;
++
++ /* setup registers */
++
++ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
++ w += winnr;
++
++ out_be32(&w->or, 0); /* turn off window */
++ out_be32(&w->br, 0); /* turn off base address */
++
++ dprintk("Socket %u: Unmapped io window %u at %#8.8x, "
++ "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
++ }
++
++ /* copy the struct and modify the copy */
++ s->io_win[io->map] = *io;
++ s->io_win[io->map].flags &= (MAP_WRPROT
++ | MAP_16BIT
++ | MAP_ACTIVE);
++ dprintk("SetIOMap exit\n");
++
++ return 0;
++}
++
++static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
++{
++ int lsock = container_of(sock, struct socket_info, socket)->slot;
++ struct socket_info *s = &socket[lsock];
++ struct pcmcia_win *w;
++ struct pccard_mem_map *old;
++ unsigned int reg, winnr;
++
++ dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, "
++ "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
++ mem->speed, mem->static_start, mem->card_start);
++
++ if ((mem->map >= PCMCIA_MEM_WIN_NO)
++// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
++ || (mem->card_start >= 0x04000000)
++ || (mem->static_start & 0xfff) /* 4KByte resolution */
++ || (mem->card_start & 0xfff))
++ return -EINVAL;
++
++ if((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
++ printk( "Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
++ return -EINVAL;
++ }
++ reg <<= 27;
++
++ winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;
++
++ /* Setup the window in the pcmcia controller */
++
++ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
++ w += winnr;
++
++ reg |= lsock << 2;
++
++ reg |= m8xx_get_speed(mem->speed, 0);
++
++ if(mem->flags & MAP_ATTRIB)
++ reg |= M8XX_PCMCIA_POR_ATTRMEM;
++
++ if(mem->flags & MAP_WRPROT)
++ reg |= M8XX_PCMCIA_POR_WRPROT;
++
++ if(mem->flags & MAP_16BIT)
++ reg |= M8XX_PCMCIA_POR_16BIT;
++
++ if(mem->flags & MAP_ACTIVE)
++ reg |= M8XX_PCMCIA_POR_VALID;
++
++ out_be32(&w->or, reg);
++
++ dprintk("Socket %u: Mapped memory window %u at %#8.8x, "
++ "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
++
++ if(mem->flags & MAP_ACTIVE) {
++ /* get the new base address */
++ mem->static_start = PCMCIA_MEM_WIN_BASE +
++ (PCMCIA_MEM_WIN_SIZE * winnr)
++ + mem->card_start;
++ }
++
++ dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
++ "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
++ mem->speed, mem->static_start, mem->card_start);
++
++ /* copy the struct and modify the copy */
++
++ old = &s->mem_win[mem->map];
++
++ *old = *mem;
++ old->flags &= (MAP_ATTRIB
++ | MAP_WRPROT
++ | MAP_16BIT
++ | MAP_ACTIVE);
++
++ return 0;
++}
++
++static int m8xx_sock_init(struct pcmcia_socket *sock)
++{
++ int i;
++ pccard_io_map io = { 0, 0, 0, 0, 1 };
++ pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
++
++ dprintk( "sock_init(%d)\n", s);
++
++ m8xx_set_socket(sock, &dead_socket);
++ for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
++ io.map = i;
++ m8xx_set_io_map(sock, &io);
++ }
++ for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) {
++ mem.map = i;
++ m8xx_set_mem_map(sock, &mem);
++ }
++
++ return 0;
++
++}
++
++static int m8xx_suspend(struct pcmcia_socket *sock)
++{
++ return m8xx_set_socket(sock, &dead_socket);
++}
++
++static struct pccard_operations m8xx_services = {
++ .init = m8xx_sock_init,
++ .suspend = m8xx_suspend,
++ .get_status = m8xx_get_status,
++ .get_socket = m8xx_get_socket,
++ .set_socket = m8xx_set_socket,
++ .set_io_map = m8xx_set_io_map,
++ .set_mem_map = m8xx_set_mem_map,
++};
++
++static int __init m8xx_init(void)
++{
++ struct pcmcia_win *w;
++ unsigned int i,m;
++
++ pcmcia_info("%s\n", version);
++
++ if (driver_register(&m8xx_driver))
++ return -1;
++
++ pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
++ " with IRQ %u.\n", pcmcia_schlvl);
++
++ /* Configure Status change interrupt */
++
++ if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0,
++ "m8xx_pcmcia", NULL)) {
++ pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
++ pcmcia_schlvl);
++ return -1;
++ }
++
++ w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
++
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr,
++ M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
++
++ out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per,
++ in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
++ ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)));
++
++/* connect interrupt and disable CxOE */
++
++ out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
++ out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
++
++/* intialize the fixed memory windows */
++
++ for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
++ for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
++ out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
++ (PCMCIA_MEM_WIN_SIZE
++ * (m + i * PCMCIA_MEM_WIN_NO)));
++
++ out_be32(&w->or, 0); /* set to not valid */
++
++ w++;
++ }
++ }
++
++/* turn off voltage */
++ voltage_set(0, 0, 0);
++ voltage_set(1, 0, 0);
++
++/* Enable external hardware */
++ hardware_enable(0);
++ hardware_enable(1);
++
++ platform_device_register(&m8xx_device);
++
++ for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) {
++ socket[i].slot = i;
++ socket[i].socket.owner = THIS_MODULE;
++ socket[i].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
++ socket[i].socket.irq_mask = 0x000;
++ socket[i].socket.map_size = 0x1000;
++ socket[i].socket.io_offset = 0;
++ socket[i].socket.pci_irq = i ? 7 : 9;
++ socket[i].socket.ops = &m8xx_services;
++ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
++ socket[i].socket.cb_dev = NULL;
++ socket[i].socket.dev.dev = &m8xx_device.dev;
++ }
++
++ for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
++ pcmcia_register_socket(&socket[i].socket);
++
++ return 0;
++}
++
++static void __exit m8xx_exit(void)
++{
++ int i;
++
++ for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
++ pcmcia_unregister_socket(&socket[i].socket);
++
++ m8xx_shutdown();
++
++ platform_device_unregister(&m8xx_device);
++ driver_unregister(&m8xx_driver);
++}
++
++module_init(m8xx_init);
++module_exit(m8xx_exit);
+diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
+--- a/drivers/pcmcia/omap_cf.c
++++ b/drivers/pcmcia/omap_cf.c
+@@ -12,7 +12,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -329,27 +329,13 @@ static int __devexit omap_cf_remove(stru
+ 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
+--- a/drivers/pcmcia/pxa2xx_base.c
++++ b/drivers/pcmcia/pxa2xx_base.c
+@@ -23,6 +23,7 @@
+ #include <linux/ioport.h>
+ #include <linux/kernel.h>
+ #include <linux/spinlock.h>
++#include <linux/platform_device.h>
+
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+@@ -205,32 +206,20 @@ int pxa2xx_drv_pcmcia_probe(struct devic
+ }
+ 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_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
+--- a/drivers/pcmcia/pxa2xx_mainstone.c
++++ b/drivers/pcmcia/pxa2xx_mainstone.c
+@@ -17,7 +17,7 @@
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ #include <pcmcia/ss.h>
+
+diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
+--- a/drivers/pcmcia/pxa2xx_sharpsl.c
++++ b/drivers/pcmcia/pxa2xx_sharpsl.c
+@@ -16,12 +16,17 @@
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_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 @@ static int sharpsl_pcmcia_hw_init(struct
+ {
+ int ret;
+
++#ifndef CONFIG_SA1100_COLLIE
+ /*
+ * Setup default state of GPIO outputs
+ * before we enable them as outputs.
+@@ -60,6 +66,7 @@ static int sharpsl_pcmcia_hw_init(struct
+ 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 @@ static void sharpsl_pcmcia_socket_init(s
+ 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 pcmcia_low_level sharpsl_p
+
+ 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 @@ static void __exit sharpsl_pcmcia_exit(v
+
+ 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
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -779,7 +779,7 @@ static int nonstatic_autoadd_resources(s
+ 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 @@ static struct class_device_attribute *pc
+ 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 @@ static int __devinit pccard_sysfs_add_rs
+ 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
+--- a/drivers/pcmcia/sa1100_generic.c
++++ b/drivers/pcmcia/sa1100_generic.c
+@@ -33,13 +33,18 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/config.h>
++#include <linux/platform_device.h>
+
+ #include <pcmcia/cs_types.h>
+ #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 +61,9 @@ static int (*sa11x0_pcmcia_hw_init[])(st
+ #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 +82,13 @@ static int sa11x0_drv_pcmcia_probe(struc
+ 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
+--- a/drivers/pcmcia/sa1111_generic.c
++++ b/drivers/pcmcia/sa1111_generic.c
+@@ -122,7 +122,7 @@ void sa1111_pcmcia_socket_suspend(struct
+
+ 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
+--- a/drivers/pcmcia/socket_sysfs.c
++++ b/drivers/pcmcia/socket_sysfs.c
+@@ -341,7 +341,8 @@ static struct bin_attribute pccard_cis_a
+ .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 @@ static int __devinit pccard_sysfs_add_so
+ 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
+--- a/drivers/pcmcia/tcic.c
++++ b/drivers/pcmcia/tcic.c
+@@ -44,7 +44,7 @@
+ #include <linux/ioport.h>
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/bitops.h>
+
+ #include <asm/io.h>
+@@ -372,27 +372,11 @@ static int __init get_tcic_id(void)
+
+ /*====================================================================*/
+
+-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
+--- a/drivers/pcmcia/vrc4171_card.c
++++ b/drivers/pcmcia/vrc4171_card.c
+@@ -24,6 +24,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/sched.h>
+ #include <linux/types.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+
+@@ -774,31 +775,11 @@ static int __devinit vrc4171_card_setup(
+
+ __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
+--- a/drivers/pcmcia/yenta_socket.c
++++ b/drivers/pcmcia/yenta_socket.c
+@@ -151,6 +151,40 @@ static void exca_writew(struct yenta_soc
+ 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 @@ static void yenta_close(struct pci_dev *
+ {
+ 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 @@ static int __devinit yenta_probe (struct
+
+ /* 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
+--- 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
+--- 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
+--- a/drivers/s390/char/con3270.c
++++ b/drivers/s390/char/con3270.c
+@@ -213,6 +213,9 @@ con3270_update(struct con3270 *cp)
+ 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 @@ con3270_write(struct console *co, const
+ 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 @@ con3270_init(void)
+ (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
+--- a/drivers/s390/char/fs3270.c
++++ b/drivers/s390/char/fs3270.c
+@@ -33,8 +33,11 @@ struct fs3270 {
+ 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 @@ fs3270_wake_up(struct raw3270_request *r
+ 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;
++
++ 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);
+ }
+
+-/*
+- * Switch to the fullscreen view.
+- */
+ 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 @@ fs3270_irq(struct fs3270 *fp, struct raw
+ /* 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 @@ fs3270_read(struct file *filp, char *dat
+ 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 @@ fs3270_read(struct file *filp, char *dat
+ 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 @@ fs3270_read(struct file *filp, char *dat
+ 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 @@ fs3270_write(struct file *filp, const ch
+ 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 @@ fs3270_write(struct file *filp, const ch
+ 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 @@ fs3270_ioctl(struct inode *inode, struct
+ }
+
+ /*
+- * Allocate tty3270 structure.
++ * Allocate fs3270 structure.
+ */
+ static struct fs3270 *
+ fs3270_alloc_view(void)
+@@ -243,8 +371,8 @@ fs3270_alloc_view(void)
+ 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 @@ fs3270_alloc_view(void)
+ }
+
+ /*
+- * 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 @@ static int
+ 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 @@ fs3270_open(struct inode *inode, struct
+ 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 @@ fs3270_open(struct inode *inode, struct
+ 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 @@ fs3270_close(struct inode *inode, struct
+
+ 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
+--- 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 raw3270 {
+ 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 @@ raw3270_start(struct raw3270_view *view,
+ }
+
+ 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 @@ raw3270_reset_device(struct raw3270 *rp)
+ 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 @@ raw3270_setup_device(struct ccw_device *
+
+ /*
+ * 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 @@ raw3270_setup_device(struct ccw_device *
+ }
+ 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 @@ raw3270_deactivate_view(struct raw3270_v
+ 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 @@ raw3270_add_view(struct raw3270_view *vi
+ 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 @@ raw3270_add_view(struct raw3270_view *vi
+ 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 @@ raw3270_del_view(struct raw3270_view *vi
+ 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 @@ raw3270_delete_device(struct raw3270 *rp
+
+ /* 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 @@ raw3270_create_attributes(struct raw3270
+ {
+ //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 @@ raw3270_set_online (struct ccw_device *c
+ 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 @@ raw3270_set_online (struct ccw_device *c
+ np->notifier(rp->minor, 1);
+ up(&raw3270_sem);
+ return 0;
++
++failure:
++ raw3270_delete_device(rp);
++ return rc;
+ }
+
+ /*
+@@ -1217,6 +1281,14 @@ raw3270_remove (struct ccw_device *cdev)
+ 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 @@ raw3270_init(void)
+ 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 @@ static void
+ raw3270_exit(void)
+ {
+ ccw_driver_unregister(&raw3270_ccw_driver);
++ class_destroy(class3270);
+ }
+
+ MODULE_LICENSE("GPL");
+@@ -1335,7 +1409,9 @@ EXPORT_SYMBOL(raw3270_find_view);
+ 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
+--- 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_del_view(struct raw3270_vie
+ 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
+--- a/drivers/s390/char/tape_class.c
++++ b/drivers/s390/char/tape_class.c
+@@ -72,6 +72,7 @@ struct tape_class_device *register_tape_
+
+ 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
+--- a/drivers/s390/char/tty3270.c
++++ b/drivers/s390/char/tty3270.c
+@@ -653,18 +653,12 @@ tty3270_activate(struct raw3270_view *vi
+ 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 @@ tty3270_alloc_view(void)
+ 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 @@ tty3270_del_views(void)
+ 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 @@ tty3270_open(struct tty_struct *tty, str
+ 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 @@ tty3270_open(struct tty_struct *tty, str
+ (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 @@ tty3270_open(struct tty_struct *tty, str
+
+ 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 @@ tty3270_init(void)
+ 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 @@ tty3270_init(void)
+ 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
+--- a/drivers/s390/char/vmlogrdr.c
++++ b/drivers/s390/char/vmlogrdr.c
+@@ -788,6 +788,7 @@ vmlogrdr_register_device(struct vmlogrdr
+ }
+ 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
+--- 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
+--- 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 @@ cutype_show (struct device *dev, struct
+ }
+
+ 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(chpids, 0444, chpids_
+ 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 @@ subchannel_add_files (struct device *dev
+ 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
+--- 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
+--- a/drivers/s390/net/fsm.c
++++ b/drivers/s390/net/fsm.c
+@@ -16,7 +16,7 @@ MODULE_LICENSE("GPL");
+
+ 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
+--- a/drivers/s390/net/fsm.h
++++ b/drivers/s390/net/fsm.h
+@@ -110,7 +110,7 @@ extern 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 tmpl_len, gfp_t order);
+
+ /**
+ * Releases an FSM
+diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
+--- a/drivers/s390/net/qeth.h
++++ b/drivers/s390/net/qeth.h
+@@ -275,6 +275,10 @@ qeth_is_ipa_enabled(struct qeth_ipa_info
+ 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 @@ struct qeth_hdr_layer2 {
+ __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 @@ enum qeth_header_ids {
+ 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 @@ enum qeth_card_states {
+ * Protocol versions
+ */
+ enum qeth_prot_versions {
+- QETH_PROT_SNA = 0x0001,
+ QETH_PROT_IPV4 = 0x0004,
+ QETH_PROT_IPV6 = 0x0006,
+ };
+@@ -761,6 +777,11 @@ enum qeth_threads {
+ 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 @@ struct qeth_card {
+ 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 @@ qeth_get_hlen(__u8 link_type)
+ 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 @@ static inline int
+ 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 @@ qeth_mtu_is_valid(struct qeth_card * car
+ 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 @@ qeth_get_arphdr_type(int cardtype, int l
+ {
+ 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 @@ qeth_fill_header(struct qeth_card *, str
+ 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
+--- 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 @@ extern void
+ 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 @@ qeth_get_cardname(struct qeth_card *card
+ 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 @@ qeth_get_cardname_short(struct qeth_card
+ }
+ 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
+--- a/drivers/s390/net/qeth_main.c
++++ b/drivers/s390/net/qeth_main.c
+@@ -196,7 +196,6 @@ qeth_notifier_register(struct task_struc
+ {
+ 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 @@ qeth_set_intial_options(struct qeth_card
+ 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_determine_card_type(struct qeth_car
+
+ 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 @@ qeth_probe_device(struct ccwgroup_device
+ 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 @@ qeth_probe_device(struct ccwgroup_device
+ 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 @@ qeth_check_ipa_data(struct qeth_card *ca
+ 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 @@ qeth_send_control_data_cb(struct qeth_ch
+ 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 @@ qeth_send_control_data_cb(struct qeth_ch
+ keep_reply = reply->callback(card,
+ reply,
+ (unsigned long)cmd);
+- }
+- else
++ } else
+ keep_reply = reply->callback(card,
+ reply,
+ (unsigned long)iob);
+@@ -1768,6 +1781,24 @@ out:
+ 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 @@ qeth_send_control_data(struct qeth_card
+ {
+ 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 @@ qeth_send_control_data(struct qeth_card
+ 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_send_control_data(struct qeth_card
+ 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 @@ qeth_send_control_data(struct qeth_card
+ }
+
+ 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_send_ipa_cmd(struct qeth_card *card
+
+ 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(struct qeth_card *card)
+ *(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 @@ qeth_check_for_inbound_error(struct qeth
+ }
+
+ 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 @@ qeth_get_next_skb(struct qeth_card *card
+
+ 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 @@ qeth_get_next_skb(struct qeth_card *card
+ 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 @@ qeth_process_inbound_buffer(struct qeth_
+ 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 @@ qeth_process_inbound_buffer(struct qeth_
+ 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 @@ qeth_init_qdio_info(struct qeth_card *ca
+ 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 @@ qeth_mpc_initialize(struct qeth_card *ca
+
+ 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 @@ qeth_get_netdevice(enum qeth_card_types
+ 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 @@ qeth_open(struct net_device *dev)
+ 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 @@ qeth_get_cast_type(struct qeth_card *car
+ {
+ 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 @@ static inline int
+ 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 @@ qeth_send_packet(struct qeth_card *card,
+ }
+ }
+ }
++ 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_send_packet(struct qeth_card *card,
+ 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 @@ qeth_mdio_read(struct net_device *dev, i
+ 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 @@ qeth_do_ioctl(struct net_device *dev, st
+ (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 @@ qeth_set_multicast_list(struct net_devic
+ {
+ 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 @@ qeth_get_addr_buffer(enum qeth_prot_vers
+ 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_layer2_set_mac_address(struct net_d
+ 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_netdev_init(struct net_device *dev)
+ 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_init_func_level(struct qeth_card *c
+ 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 @@ retry:
+ 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 @@ retry:
+ 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 @@ qeth_softsetup_card(struct qeth_card *ca
+ 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 @@ qeth_stop_card(struct qeth_card *card, i
+ 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_start_again(struct qeth_card *card,
+ {
+ 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 @@ qeth_start_again(struct qeth_card *card,
+ 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 @@ __qeth_set_online(struct ccwgroup_device
+ 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 @@ qeth_set_online(struct ccwgroup_device *
+ 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 @@ again:
+ 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 at de.ibm.com>");
+diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
+--- 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 @@ unsigned char IPA_PDU_HEADER[]={
+ 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
+--- a/drivers/s390/net/qeth_mpc.h
++++ b/drivers/s390/net/qeth_mpc.h
+@@ -46,13 +46,16 @@ extern unsigned char IPA_PDU_HEADER[];
+ /* 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 @@ enum qeth_link_types {
+ 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 @@ enum qeth_ipa_cmds {
+ 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 @@ enum qeth_ipa_arp_return_codes {
+ #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 @@ extern unsigned char ULP_ENABLE[];
+ /* 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
+--- 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 @@ static struct attribute_group qeth_devic
+ .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 @@ int
+ 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 @@ qeth_create_device_attributes(struct dev
+ 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
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -489,11 +489,11 @@ config SCSI_SATA_NV
+
+ 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 @@ config SCSI_SATA_QSTOR
+
+ 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 @@ config SCSI_SATA_SIL
+
+ 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
+--- a/drivers/scsi/Makefile
++++ b/drivers/scsi/Makefile
+@@ -130,6 +130,7 @@ obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o
+ 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_SX4) += libata.o
+ 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
+--- 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_port_stop(struct ata_po
+ 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 @@ static Scsi_Host_Template ahci_sht = {
+ .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 @@ static u32 ahci_scr_read (struct ata_por
+ 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 @@ static void ahci_scr_write (struct ata_p
+ 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 void ahci_phy_reset(struct ata_po
+
+ 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 @@ static void ahci_eng_timeout(struct ata_
+ * 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 @@ static inline int ahci_host_intr(struct
+ 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 @@ static irqreturn_t ahci_interrupt (int i
+
+ 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 @@ static int ahci_host_init(struct ata_pro
+
+ 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 @@ static int ahci_host_init(struct ata_pro
+ 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 @@ static void ahci_print_info(struct ata_p
+ 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 @@ static void ahci_print_info(struct ata_p
+ 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 @@ static int ahci_init_one (struct pci_dev
+ 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
+--- 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 @@ static inline int copy_SCp_to_sg(struct
+
+ 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
+--- 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 @@ static Scsi_Host_Template piix_sht = {
+ .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 @@ static struct ata_port_operations piix_p
+ .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 piix_init_one (struct pci_dev
+ {
+ 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 @@ static int piix_init_one (struct pci_dev
+ 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
+--- a/drivers/scsi/ch.c
++++ b/drivers/scsi/ch.c
+@@ -936,7 +936,7 @@ static int ch_probe(struct device *dev)
+ 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
+--- a/drivers/scsi/dec_esp.c
++++ b/drivers/scsi/dec_esp.c
+@@ -228,7 +228,7 @@ static int dec_esp_detect(Scsi_Host_Temp
+ 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
+--- a/drivers/scsi/eata.c
++++ b/drivers/scsi/eata.c
+@@ -1357,7 +1357,7 @@ static int port_detect(unsigned long por
+
+ 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
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -30,6 +30,7 @@
+ #include <linux/init.h>
+ #include <linux/completion.h>
+ #include <linux/transport_class.h>
++#include <linux/platform_device.h>
+
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
+@@ -287,7 +288,8 @@ static void scsi_host_dev_release(struct
+ 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/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
+--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
+@@ -1543,13 +1543,16 @@ static struct vio_device_id ibmvscsi_dev
+ {"vscsi", "IBM,v-scsi"},
+ { "", "" }
+ };
+-
+ MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table);
++
+ static struct vio_driver ibmvscsi_driver = {
+- .name = "ibmvscsi",
+ .id_table = ibmvscsi_device_table,
+ .probe = ibmvscsi_probe,
+- .remove = ibmvscsi_remove
++ .remove = ibmvscsi_remove,
++ .driver = {
++ .name = "ibmvscsi",
++ .owner = THIS_MODULE,
++ }
+ };
+
+ int __init ibmvscsi_module_init(void)
+diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
+--- a/drivers/scsi/ide-scsi.c
++++ b/drivers/scsi/ide-scsi.c
+@@ -184,13 +184,16 @@ static void idescsi_input_buffers (ide_d
+ 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);
++ 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);
++ drive->hwif->atapi_input_bytes(drive,
++ buf + pc->b_count, count);
+ }
+ bcount -= count; pc->b_count += count;
+ if (pc->b_count == pc->sg->length) {
+@@ -216,13 +219,16 @@ static void idescsi_output_buffers (ide_
+ 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);
++ 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);
++ drive->hwif->atapi_output_bytes(drive,
++ buf + pc->b_count, count);
+ }
+ bcount -= count; pc->b_count += count;
+ if (pc->b_count == pc->sg->length) {
+diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
+--- a/drivers/scsi/ipr.c
++++ b/drivers/scsi/ipr.c
+@@ -4944,6 +4944,7 @@ static int ipr_reset_restore_cfg_space(s
+ 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 @@ static int ipr_reset_start_bist(struct i
+ 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
+--- a/drivers/scsi/lasi700.c
++++ b/drivers/scsi/lasi700.c
+@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(parisc, lasi700_ids)
+ 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 @@ lasi700_probe(struct parisc_device *dev)
+ 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 @@ lasi700_driver_remove(struct parisc_devi
+ }
+
+ 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
+--- 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_LICENSE("GPL");
+ 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 @@ MODULE_VERSION(DRV_VERSION);
+ * 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 @@ static void ata_tf_load_pio(struct ata_p
+ * 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 @@ static void ata_tf_load_mmio(struct ata_
+ * 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 @@ void ata_tf_load(struct ata_port *ap, st
+ * 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 @@ static void ata_exec_command_pio(struct
+ * 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 @@ static void ata_exec_command_mmio(struct
+ * 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);
+@@ -292,28 +295,6 @@ void ata_exec_command(struct ata_port *a
+ }
+
+ /**
+- * ata_exec - issue ATA command to host controller
+- * @ap: port to which command is being issued
+- * @tf: ATA taskfile register set
+- *
+- * Issues PIO/MMIO write to ATA command register, with proper
+- * synchronization with interrupt handler / other threads.
+- *
+- * LOCKING:
+- * Obtains host_set lock.
+- */
+-
+-static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- unsigned long flags;
+-
+- DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+- spin_lock_irqsave(&ap->host_set->lock, flags);
+- ap->ops->exec_command(ap, tf);
+- spin_unlock_irqrestore(&ap->host_set->lock, flags);
+-}
+-
+-/**
+ * ata_tf_to_host - issue ATA taskfile to host controller
+ * @ap: port to which command is being issued
+ * @tf: ATA taskfile register set
+@@ -323,30 +304,11 @@ static inline void ata_exec(struct ata_p
+ * other threads.
+ *
+ * LOCKING:
+- * Obtains host_set lock.
+- */
+-
+-static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- ap->ops->tf_load(ap, tf);
+-
+- ata_exec(ap, tf);
+-}
+-
+-/**
+- * ata_tf_to_host_nolock - issue ATA taskfile to host controller
+- * @ap: port to which command is being issued
+- * @tf: ATA taskfile register set
+- *
+- * Issues ATA taskfile register set to ATA host controller,
+- * with proper synchronization with interrupt handler and
+- * other threads.
+- *
+- * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+
+-void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
++static inline void ata_tf_to_host(struct ata_port *ap,
++ const struct ata_taskfile *tf)
+ {
+ ap->ops->tf_load(ap, tf);
+ ap->ops->exec_command(ap, tf);
+@@ -368,6 +330,8 @@ static void ata_tf_read_pio(struct ata_p
+ {
+ 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 +364,8 @@ static void ata_tf_read_mmio(struct ata_
+ {
+ 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 +486,6 @@ u8 ata_altstatus(struct ata_port *ap)
+
+
+ /**
+- * 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 +498,7 @@ u8 ata_chk_err(struct ata_port *ap)
+ * 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 +539,7 @@ void ata_tf_to_fis(struct ata_taskfile *
+ * 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 +557,53 @@ void ata_tf_from_fis(u8 *fis, struct ata
+ 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;
+-
+- if (pio)
+- proto = dev->xfer_protocol = ATA_PROT_PIO;
+- else
+- proto = dev->xfer_protocol = ATA_PROT_DMA;
++ struct ata_taskfile *tf = &qc->tf;
++ struct ata_device *dev = qc->dev;
+
+- cmd = ata_prot_to_cmd(proto, lba48);
+- if (cmd < 0)
+- BUG();
++ int index, lba48, write;
++
++ lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
++ write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
++
++ 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 +785,7 @@ static unsigned int ata_devchk(struct at
+ * 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 +837,8 @@ static u8 ata_dev_try_classify(struct at
+
+ 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 +877,7 @@ static u8 ata_dev_try_classify(struct at
+ * 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 +994,7 @@ void ata_dev_select(struct ata_port *ap,
+ * 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 +1022,31 @@ static inline void ata_dump_id(struct at
+ 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 +1072,9 @@ static inline void ata_dump_id(struct at
+ 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 +1128,11 @@ retry:
+ 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 +1145,7 @@ retry:
+ * 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 +1172,9 @@ retry:
+ * 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 +1182,8 @@ retry:
+ 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 +1192,75 @@ retry:
+ 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 +1294,7 @@ err_out:
+ }
+
+
+-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 +1480,153 @@ void ata_port_disable(struct ata_port *a
+ 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 +1733,7 @@ static void ata_host_set_dma(struct ata_
+ */
+ 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 +1762,6 @@ static void ata_set_mode(struct ata_port
+ 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:
+@@ -1746,12 +1871,14 @@ static void ata_bus_post_reset(struct at
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
++ * Obtains host_set lock.
+ *
+ */
+
+ static unsigned int ata_bus_edd(struct ata_port *ap)
+ {
+ struct ata_taskfile tf;
++ unsigned long flags;
+
+ /* set up execute-device-diag (bus reset) taskfile */
+ /* also, take interrupts to a known state (disabled) */
+@@ -1762,7 +1889,9 @@ static unsigned int ata_bus_edd(struct a
+ tf.protocol = ATA_PROT_NODATA;
+
+ /* do bus reset */
++ spin_lock_irqsave(&ap->host_set->lock, flags);
+ ata_tf_to_host(ap, &tf);
++ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ /* spec says at least 2ms. but who knows with those
+ * crazy ATAPI devices...
+@@ -1910,7 +2039,8 @@ err_out:
+ 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 +2078,7 @@ static const char * ata_dma_blacklist []
+ "_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 +2103,9 @@ static int ata_dma_blacklisted(struct at
+ 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 +2117,14 @@ static unsigned int ata_get_mode_mask(st
+ 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 +2134,14 @@ static unsigned int ata_get_mode_mask(st
+ 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 +2205,7 @@ static int fgb(u32 bitmap)
+ * 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 +2274,110 @@ static void ata_dev_set_xfermode(struct
+ }
+
+ /**
++ * 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 +2518,12 @@ void ata_qc_prep(struct ata_queued_cmd *
+
+ 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 +2626,7 @@ static int ata_sg_setup(struct ata_queue
+ * 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 +2634,38 @@ void ata_poll_qc_complete(struct ata_que
+ 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;
+-
+- switch (ap->pio_task_state) {
+- case PIO_ST:
+- case PIO_ST_POLL:
+- poll_state = PIO_ST_POLL;
+- reg_state = PIO_ST;
++ unsigned int poll_state = HSM_ST_UNKNOWN;
++ unsigned int reg_state = HSM_ST_UNKNOWN;
++ const unsigned int tmout_state = HSM_ST_TMOUT;
++
++ 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 +2675,20 @@ static unsigned long ata_pio_poll(struct
+ 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 +2707,14 @@ static int ata_pio_complete (struct ata_
+ * 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 +2722,16 @@ static int ata_pio_complete (struct ata_
+
+ 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 +2740,7 @@ static int ata_pio_complete (struct ata_
+
+
+ /**
+- * 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 +2749,7 @@ static int ata_pio_complete (struct ata_
+ * vice-versa.
+ *
+ * LOCKING:
++ * Inherited from caller.
+ */
+ void swap_buf_le16(u16 *buf, unsigned int buf_words)
+ {
+@@ -2544,7 +2772,6 @@ void swap_buf_le16(u16 *buf, unsigned in
+ *
+ * LOCKING:
+ * Inherited from caller.
+- *
+ */
+
+ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
+@@ -2590,7 +2817,6 @@ static void ata_mmio_data_xfer(struct at
+ *
+ * LOCKING:
+ * Inherited from caller.
+- *
+ */
+
+ static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
+@@ -2630,7 +2856,6 @@ static void ata_pio_data_xfer(struct ata
+ *
+ * LOCKING:
+ * Inherited from caller.
+- *
+ */
+
+ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
+@@ -2662,7 +2887,7 @@ static void ata_pio_sector(struct ata_qu
+ 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 +2937,7 @@ static void __atapi_pio_bytes(struct ata
+ 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 +2959,7 @@ next_sg:
+ 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 +3008,6 @@ next_sg:
+ *
+ * LOCKING:
+ * Inherited from caller.
+- *
+ */
+
+ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
+@@ -2815,12 +3039,12 @@ static void atapi_pio_bytes(struct ata_q
+ 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 +3056,19 @@ static void ata_pio_block(struct ata_por
+ 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 +3080,7 @@ static void ata_pio_block(struct ata_por
+ 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 +3088,7 @@ static void ata_pio_block(struct ata_por
+ } 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 +3099,15 @@ static void ata_pio_block(struct ata_por
+ 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->pio_task_state = PIO_ST_IDLE;
++ ap->hsm_task_state = HSM_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 +3120,25 @@ fsm_start:
+ 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 +3149,6 @@ fsm_start:
+ 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 +3230,7 @@ static void ata_qc_timeout(struct ata_qu
+ 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 +3266,14 @@ void ata_eng_timeout(struct ata_port *ap
+ 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 +3330,12 @@ struct ata_queued_cmd *ata_qc_new_init(s
+ 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 +3373,6 @@ static void __ata_qc_complete(struct ata
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+- *
+ */
+ void ata_qc_free(struct ata_queued_cmd *qc)
+ {
+@@ -3221,10 +3392,9 @@ void ata_qc_free(struct ata_queued_cmd *
+ *
+ * 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 +3411,7 @@ void ata_qc_complete(struct ata_queued_c
+ 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
+@@ -3348,7 +3518,7 @@ int ata_qc_issue_prot(struct ata_queued_
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_NODATA:
+- ata_tf_to_host_nolock(ap, &qc->tf);
++ ata_tf_to_host(ap, &qc->tf);
+ break;
+
+ case ATA_PROT_DMA:
+@@ -3359,20 +3529,20 @@ int ata_qc_issue_prot(struct ata_queued_
+
+ 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;
++ ata_tf_to_host(ap, &qc->tf);
++ ap->hsm_task_state = HSM_ST;
+ queue_work(ata_wq, &ap->pio_task);
+ break;
+
+ case ATA_PROT_ATAPI:
+ ata_qc_set_polling(qc);
+- ata_tf_to_host_nolock(ap, &qc->tf);
++ ata_tf_to_host(ap, &qc->tf);
+ queue_work(ata_wq, &ap->packet_task);
+ break;
+
+ case ATA_PROT_ATAPI_NODATA:
+ ap->flags |= ATA_FLAG_NOINTR;
+- ata_tf_to_host_nolock(ap, &qc->tf);
++ ata_tf_to_host(ap, &qc->tf);
+ queue_work(ata_wq, &ap->packet_task);
+ break;
+
+@@ -3586,7 +3756,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
+ 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 +3849,7 @@ inline unsigned int ata_host_intr (struc
+ 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 +3885,6 @@ idle_irq:
+ *
+ * RETURNS:
+ * IRQ_NONE or IRQ_HANDLED.
+- *
+ */
+
+ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+@@ -3775,7 +3944,7 @@ static void atapi_packet_task(void *_dat
+ /* 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 +3975,16 @@ static void atapi_packet_task(void *_dat
+ 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 +3998,7 @@ err_out:
+ * 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 +4024,7 @@ int ata_port_start (struct ata_port *ap)
+ * 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 +4047,7 @@ void ata_host_stop (struct ata_host_set
+ * @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 +4075,11 @@ static void ata_host_remove(struct ata_p
+ *
+ * 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;
+
+@@ -3916,8 +4089,6 @@ static void ata_host_init(struct ata_por
+ host->unique_id = ata_unique_id++;
+ host->max_cmd_len = 12;
+
+- scsi_assign_lock(host, &host_set->lock);
+-
+ ap->flags = ATA_FLAG_PORT_DISABLED;
+ ap->id = host->unique_id;
+ ap->host = host;
+@@ -3962,10 +4133,9 @@ static void ata_host_init(struct ata_por
+ *
+ * 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 +4180,9 @@ err_out:
+ *
+ * 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 +4190,10 @@ int ata_device_add(struct ata_probe_ent
+
+ 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 +4233,8 @@ int ata_device_add(struct ata_probe_ent
+ 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 +4279,7 @@ int ata_device_add(struct ata_probe_ent
+ 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 +4292,7 @@ err_out:
+ 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 +4309,6 @@ err_out:
+ * Inherited from calling layer (may sleep).
+ */
+
+-
+ void ata_host_set_remove(struct ata_host_set *host_set)
+ {
+ struct ata_port *ap;
+@@ -4232,19 +4398,17 @@ void ata_std_ports(struct ata_ioports *i
+ }
+
+ 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 +4437,86 @@ void ata_pci_host_stop (struct ata_host_
+ * 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);
+-
+- 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;
+-
+- ata_std_ports(&probe_ent->port[0]);
+- ata_std_ports(&probe_ent->port[1]);
++ 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++;
++ }
++
++ 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++;
++ }
+
++ 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 +4539,12 @@ ata_pci_init_legacy_mode(struct pci_dev
+ *
+ * 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 +4561,7 @@ int ata_pci_init_one (struct pci_dev *pd
+
+ 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 +4569,20 @@ int ata_pci_init_one (struct pci_dev *pd
+ }
+
+ /* 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 +4593,7 @@ int ata_pci_init_one (struct pci_dev *pd
+ 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 +4638,17 @@ int ata_pci_init_one (struct pci_dev *pd
+ 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 +4686,7 @@ err_out:
+ * @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 +4707,7 @@ void ata_pci_remove_one (struct pci_dev
+ }
+
+ /* 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 +4760,27 @@ static void __exit ata_exit(void)
+ 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 +4805,6 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis);
+ 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 +4821,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset);
+ 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 +4833,9 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
+ 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
+--- a/drivers/scsi/libata-scsi.c
++++ b/drivers/scsi/libata-scsi.c
+@@ -39,16 +39,67 @@
+ #include <scsi/scsi.h>
+ #include "scsi.h"
+ #include <scsi/scsi_host.h>
++#include <scsi/scsi_device.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);
++#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, struct scsi_device *scsidev);
++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.
+ * @sdev: SCSI device for which BIOS geometry is to be determined
+@@ -78,6 +129,150 @@ int ata_std_bios_param(struct scsi_devic
+ 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 +302,16 @@ int ata_scsi_ioctl(struct scsi_device *s
+ 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 +370,70 @@ struct ata_queued_cmd *ata_scsi_qc_new(s
+ }
+
+ /**
++ * ata_dump_status - user friendly display of error info
++ * @id: id of the port in question
++ * @tf: ptr to filled out taskfile
++ *
++ * 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
+- * @qc: Command that we are erroring out
+ * @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. 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.
++ * 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 +474,192 @@ void ata_to_sense_error(struct ata_queue
+ {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_BUSY) {
++ drv_err = 0; /* Ignore the err bits, they're invalid */
++ }
+
+- 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_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;
++ }
++ }
++ /* No immediate match */
++ printk(KERN_WARNING "ata%u: no sense translation for "
++ "error 0x%02x\n", id, drv_err);
+ }
+- 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 ");
++
++ /* Fall back to interpreting status bits */
++ 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;
+ }
+- if(err & 0x40) printk("UncorrectableError ");
+- if(err & 0x10) printk("SectorIdNotFound ");
+- if(err & 0x02) printk("TrackZeroNotFound ");
+- if(err & 0x01) printk("AddrMarkNotFound ");
+- printk("}\n");
++ }
++ /* 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);
+
+- /* Should we dump sector info here too ?? */
++ 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;
+
+- /* 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++;
++ 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;
+ }
+- /* 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;
+- }
+- i++;
++/**
++ * 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;
+ }
+- /* No error ?? */
+- printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
+- /* additional-sense-code[-qualifier] */
+
+ 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 +758,7 @@ int ata_scsi_error(struct Scsi_Host *hos
+ */
+
+ 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 +768,26 @@ static unsigned int ata_scsi_start_stop_
+ ; /* 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 +802,11 @@ static unsigned int ata_scsi_start_stop_
+ */
+
+ return 0;
++
++invalid_fld:
++ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
++ /* "Invalid field in cbd" */
++ return 1;
+ }
+
+
+@@ -471,14 +825,14 @@ static unsigned int ata_scsi_start_stop_
+ * 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 +842,99 @@ static unsigned int ata_scsi_flush_xlat(
+ }
+
+ /**
++ * 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 +948,110 @@ static unsigned int ata_scsi_flush_xlat(
+ * 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;
+- } else {
+- if (n_sect > 256)
+- 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;
+
+- if (lba48) {
+- tf->command = ATA_CMD_VERIFY_EXT;
++ /* use LBA28 */
++ tf->command = ATA_CMD_VERIFY;
+
+- tf->hob_nsect = (n_sect >> 8) & 0xff;
++ tf->device |= (block >> 24) & 0xf;
++ }
+
+- tf->hob_lbah = (sect >> 40) & 0xff;
+- tf->hob_lbam = (sect >> 32) & 0xff;
+- tf->hob_lbal = (sect >> 24) & 0xff;
++ tf->nsect = n_block & 0xff;
++
++ tf->lbah = (block >> 16) & 0xff;
++ tf->lbam = (block >> 8) & 0xff;
++ tf->lbal = block & 0xff;
++
++ tf->device |= ATA_LBA;
+ } else {
+- tf->command = ATA_CMD_VERIFY;
++ /* CHS */
++ u32 sect, head, cyl, track;
++
++ if (n_block > 256)
++ goto invalid_fld;
+
+- tf->device |= (sect >> 24) & 0xf;
++ /* 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;
++
++ tf->command = ATA_CMD_VERIFY;
++ 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;
++ return 0;
+
+- tf->lbah = (sect >> 16) & 0xff;
+- tf->lbam = (sect >> 8) & 0xff;
+- tf->lbal = sect & 0xff;
++invalid_fld:
++ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
++ /* "Invalid field in cbd" */
++ return 1;
+
+- return 0;
++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 +1074,175 @@ static unsigned int ata_scsi_verify_xlat
+ * 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->nsect = scsicmd[8];
+- tf->lbal = scsicmd[5];
+- tf->lbam = scsicmd[4];
+- tf->lbah = scsicmd[3];
++ tf->hob_nsect = (n_block >> 8) & 0xff;
+
+- VPRINTK("ten-byte command\n");
+- if (qc->nsect == 0) /* we don't support length==0 cmds */
+- return 1;
+- return 0;
+- }
++ tf->hob_lbah = (block >> 40) & 0xff;
++ tf->hob_lbam = (block >> 32) & 0xff;
++ tf->hob_lbal = (block >> 24) & 0xff;
++ } else {
++ /* use LBA28 */
+
+- 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;
++ /* The request -may- be too large for LBA28. */
++ if ((block >> 28) || (n_block > 256))
++ goto out_of_range;
++
++ tf->device |= (block >> 24) & 0xf;
+ }
+
+- tf->lbal = scsicmd[3];
+- tf->lbam = scsicmd[2];
+- tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
++ ata_rwcmd_protocol(qc);
+
+- VPRINTK("six-byte command\n");
+- return 0;
+- }
++ qc->nsect = n_block;
++ tf->nsect = n_block & 0xff;
+
+- 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];
++ tf->lbah = (block >> 16) & 0xff;
++ tf->lbam = (block >> 8) & 0xff;
++ tf->lbal = block & 0xff;
+
+- 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];
++ 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;
++ }
+
+- qc->nsect = scsicmd[13];
+- }
++ return 0;
+
+- tf->nsect = scsicmd[13];
+- tf->lbal = scsicmd[9];
+- tf->lbam = scsicmd[8];
+- tf->lbah = scsicmd[7];
++invalid_fld:
++ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
++ /* "Invalid field in cbd" */
++ return 1;
+
+- VPRINTK("sixteen-byte command\n");
+- if (qc->nsect == 0) /* we don't support length==0 cmds */
+- return 1;
+- return 0;
+- }
++out_of_range:
++ ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
++ /* "Logical Block Address out of range" */
++ return 1;
+
+- 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 +1264,12 @@ static int ata_scsi_qc_complete(struct a
+ * 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 +1286,7 @@ static void ata_scsi_translate(struct at
+
+ 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 +1294,7 @@ static void ata_scsi_translate(struct at
+ 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 +1309,28 @@ static void ata_scsi_translate(struct at
+ 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 +1397,8 @@ static inline void ata_scsi_rbuf_put(str
+ * 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 +1417,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_
+ 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 +1633,9 @@ static void ata_msense_push(u8 **ptr_io,
+ 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 +1659,9 @@ static unsigned int ata_msense_caching(u
+
+ 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 +1678,10 @@ static unsigned int ata_msense_ctl_mode(
+
+ 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 +1690,9 @@ static unsigned int ata_msense_rw_recove
+ * @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 +1702,115 @@ unsigned int ata_scsiop_mode_sense(struc
+ 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;
++ 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;
+- else
+- output_len = 8;
++ 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;
++
++ 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(scsicmd[2] & 0x3f) {
+- case 0x01: /* r/w error recovery */
++ 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 +1833,20 @@ unsigned int ata_scsiop_read_cap(struct
+
+ 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 +1910,34 @@ unsigned int ata_scsiop_report_luns(stru
+ }
+
+ /**
++ * 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 +1955,89 @@ unsigned int ata_scsiop_report_luns(stru
+ 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 +2045,30 @@ static int atapi_qc_complete(struct ata_
+ 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 +2083,7 @@ static int atapi_qc_complete(struct ata_
+ * 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 +2152,7 @@ static unsigned int atapi_xlat(struct at
+ */
+
+ 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 +2177,143 @@ ata_scsi_find_dev(struct ata_port *ap, s
+ 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 +2346,11 @@ static inline ata_xlat_func_t ata_get_xl
+ 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;
+ }
+@@ -1565,8 +2406,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd *
+ struct ata_port *ap;
+ struct ata_device *dev;
+ struct scsi_device *scsidev = cmd->device;
++ struct Scsi_Host *shost = scsidev->host;
+
+- ap = (struct ata_port *) &scsidev->host->hostdata[0];
++ ap = (struct ata_port *) &shost->hostdata[0];
++
++ spin_unlock(shost->host_lock);
++ spin_lock(&ap->host_set->lock);
+
+ ata_scsi_dump_cdb(ap, cmd);
+
+@@ -1589,6 +2434,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd *
+ ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
+
+ out_unlock:
++ spin_unlock(&ap->host_set->lock);
++ spin_lock(shost->host_lock);
+ return 0;
+ }
+
+@@ -1610,7 +2457,7 @@ void ata_scsi_simulate(u16 *id,
+ 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 +2477,7 @@ void ata_scsi_simulate(u16 *id,
+
+ 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 +2487,7 @@ void ata_scsi_simulate(u16 *id,
+ 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 +2497,7 @@ void ata_scsi_simulate(u16 *id,
+
+ 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 +2508,38 @@ void ata_scsi_simulate(u16 *id,
+ 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
+--- a/drivers/scsi/libata.h
++++ b/drivers/scsi/libata.h
+@@ -39,19 +39,24 @@ struct ata_scsi_args {
+
+ /* 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 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 +81,10 @@ extern unsigned int ata_scsiop_report_lu
+ 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
+--- 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
+--- a/drivers/scsi/megaraid/megaraid_mbox.c
++++ b/drivers/scsi/megaraid/megaraid_mbox.c
+@@ -76,7 +76,7 @@ static void megaraid_exit(void);
+
+ 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 @@ static struct pci_driver megaraid_pci_dr
+ .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 @@ megaraid_detach_one(struct pci_dev *pdev
+ * 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
+--- a/drivers/scsi/mesh.c
++++ b/drivers/scsi/mesh.c
+@@ -730,7 +730,7 @@ static void start_phase(struct mesh_stat
+ * 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
+--- a/drivers/scsi/osst.c
++++ b/drivers/scsi/osst.c
+@@ -5146,7 +5146,8 @@ static long osst_compat_ioctl(struct fil
+ /* 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 @@ static struct osst_buffer * new_tape_buf
+ /* 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 @@ static void osst_sysfs_add(dev_t dev, st
+
+ 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
+--- /dev/null
++++ b/drivers/scsi/pdc_adma.c
+@@ -0,0 +1,741 @@
++/*
++ * pdc_adma.c - Pacific Digital Corporation ADMA
++ *
++ * Maintained by: Mark Lord <mlord at 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/sata_mv.c b/drivers/scsi/sata_mv.c
+--- 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 @@ enum {
+ 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 @@ enum {
+ 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 @@ enum {
+
+ /* Port registers */
+ EDMA_CFG_OFS = 0,
++ EDMA_CFG_Q_DEPTH = 0, /* queueing disabled */
++ EDMA_CFG_NCQ = (1 << 5),
++ EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */
++ EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */
++ EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */
+
+ EDMA_ERR_IRQ_CAUSE_OFS = 0x8,
+ EDMA_ERR_IRQ_MASK_OFS = 0xc,
+@@ -161,33 +190,84 @@ enum {
+ 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),
+ };
+
+-struct mv_port_priv {
++/* 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;
+ };
+
+-struct mv_host_priv {
++/* 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 @@ static Scsi_Host_Template mv_sht = {
+ .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 @@ static Scsi_Host_Template mv_sht = {
+ .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 @@ static struct ata_port_operations mv_ops
+
+ .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 @@ static struct ata_port_operations mv_ops
+ .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 @@ static inline void writelfl(unsigned lon
+ (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,24 +396,150 @@ static inline void __iomem *mv_ap_base(s
+ 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 ((hp_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
++}
++
++static void mv_irq_clear(struct ata_port *ap)
+ {
+- return ((flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+ }
+
+-static inline int mv_is_edma_active(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);
+- return (EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
++ 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 */
++ }
+ }
+
+-static inline int mv_port_bdma_capable(struct ata_port *ap)
++#ifdef ATA_DEBUG
++static void mv_dump_mem(void __iomem *start, unsigned bytes)
+ {
+- return (ap->flags & MV_FLAG_BDMA);
++ 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_irq_clear(struct ata_port *ap)
++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)
+@@ -389,30 +582,37 @@ static void mv_scr_write(struct ata_port
+ }
+ }
+
+-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,39 +625,399 @@ static int mv_master_reset(void __iomem
+ } 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;
+ }
+
+-static void mv_err_intr(struct ata_port *ap)
++/**
++ * 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)
+ {
+- void __iomem *port_mmio;
+- u32 edma_err_cause, serr = 0;
++ 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;
+
+- /* 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
++ 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.
+ */
+- BUG_ON(NULL == ap);
+- port_mmio = mv_ap_base(ap);
++ 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 = mv_ap_base(ap);
++ u32 edma_err_cause, serr = 0;
+
+ edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+@@ -465,8 +1025,12 @@ static void mv_err_intr(struct ata_port
+ 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 @@ static void mv_err_intr(struct ata_port
+ }
+ }
+
+-/* 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 @@ static void mv_host_intr(struct ata_host
+ 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 @@ static void mv_host_intr(struct ata_host
+ /* 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 @@ static void mv_host_intr(struct ata_host
+ 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 @@ static irqreturn_t mv_interrupt(int irq,
+ 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 @@ static void mv_phy_reset(struct ata_port
+ 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 */
++ struct ata_queued_cmd *qc;
++ unsigned long flags;
++
++ 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));
++
++ 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 */
+- writel(~0, (void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS);
++ 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((void __iomem *)base + EDMA_CFG_OFS),
+- readl((void __iomem *)base + EDMA_ERR_IRQ_CAUSE_OFS),
+- readl((void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS));
++ 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 @@ static int mv_host_init(struct ata_probe
+
+ 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 @@ static int mv_host_init(struct ata_probe
+ 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 @@ static int mv_init_one(struct pci_dev *p
+ 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 @@ static int mv_init_one(struct pci_dev *p
+ 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 @@ static int mv_init_one(struct pci_dev *p
+ 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 @@ static int mv_init_one(struct pci_dev *p
+ 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
+--- 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 @@ static Scsi_Host_Template nv_sht = {
+ .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 @@ static u32 nv_scr_read (struct ata_port
+ 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 @@ static void nv_scr_write (struct ata_por
+ 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 @@ static int nv_init_one (struct pci_dev *
+ 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 @@ static int nv_init_one (struct pci_dev *
+ 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
+--- 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_port_stop(struct ata_por
+ 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 @@ static Scsi_Host_Template pdc_ata_sht =
+ .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 @@ static struct ata_port_operations pdc_sa
+ .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 ata_port_info pdc_port_inf
+ 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 @@ static struct pci_device_id pdc_ata_pci_
+ 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 @@ static u32 pdc_sata_scr_read (struct ata
+ {
+ 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 @@ static void pdc_sata_scr_write (struct a
+ {
+ 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 @@ static void pdc_eng_timeout(struct ata_p
+ 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 @@ static void pdc_eng_timeout(struct ata_p
+ 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 @@ out:
+ 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 @@ static inline void pdc_packet_start(stru
+
+ 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 @@ static int pdc_qc_issue_prot(struct ata_
+ 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_tf_load_mmio(struct ata_
+ }
+
+
+-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 @@ static int pdc_ata_init_one (struct pci_
+ 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
+--- 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 @@ enum {
+ 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 @@ enum {
+ 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 @@ static Scsi_Host_Template qs_ata_sht = {
+ .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 @@ static inline unsigned int qs_intr_pkt(s
+ 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 @@ static inline unsigned int qs_intr_mmio(
+ 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 @@ static inline unsigned int qs_intr_mmio(
+
+ /* 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 @@ static int qs_set_dma_masks(struct pci_d
+ 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 @@ static int qs_ata_init_one(struct pci_de
+ 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
+--- 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 @@ static Scsi_Host_Template sil_sht = {
+ .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 inline unsigned long sil_scr_addr
+
+ 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 u32 sil_scr_read (struct ata_port
+
+ 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 @@ static int sil_init_one (struct pci_dev
+ 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 @@ static int sil_init_one (struct pci_dev
+ 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
+--- /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
+--- 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 @@ static Scsi_Host_Template sis_sht = {
+ .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 void sis_scr_write (struct ata_po
+
+ 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 @@ static int sis_init_one (struct pci_dev
+ 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 @@ static int sis_init_one (struct pci_dev
+ 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 @@ static int sis_init_one (struct pci_dev
+ 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
+--- 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_scr_write (struct at
+ }
+
+
+-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_load(struct ata_p
+ 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 Scsi_Host_Template k2_sata_sht =
+ };
+
+
+-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 @@ static int k2_sata_init_one (struct pci_
+ 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
+--- 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_port_priv {
+ };
+
+ struct pdc_host_priv {
+- void *dimm_mmio;
++ void __iomem *dimm_mmio;
+
+ unsigned int doing_hdma;
+ unsigned int hdma_prod;
+@@ -157,8 +158,8 @@ static void pdc_20621_phy_reset (struct
+ 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 @@ static Scsi_Host_Template pdc_sata_sht =
+ .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 @@ static void pdc20621_host_stop(struct at
+ {
+ 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 @@ static void pdc20621_packet_start(struct
+ 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 @@ static inline unsigned int pdc20621_host
+ 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 @@ static inline unsigned int pdc20621_host
+ 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 @@ static inline unsigned int pdc20621_host
+ 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 @@ static inline unsigned int pdc20621_host
+
+ 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 @@ static void pdc_eng_timeout(struct ata_p
+ 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 @@ static void pdc_eng_timeout(struct ata_p
+ 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 @@ out:
+ 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_tf_load_mmio(struct ata_
+ }
+
+
+-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 @@ static void pdc20621_put_to_dimm(struct
+ 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 @@ static void pdc20621_put_to_dimm(struct
+ 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 @@ static void pdc20621_put_to_dimm(struct
+ 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 @@ static int pdc_sata_init_one (struct pci
+ 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
+--- 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 @@ static Scsi_Host_Template uli_sht = {
+ .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 void uli_scr_write (struct ata_po
+
+ 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 @@ static int uli_init_one (struct pci_dev
+ 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
+--- 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 @@ static Scsi_Host_Template svia_sht = {
+ .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 @@ static struct ata_probe_ent *vt6420_init
+ 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 @@ static void svia_configure(struct pci_de
+ 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 @@ static void svia_configure(struct pci_de
+ /* 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 @@ static void svia_configure(struct pci_de
+ /* 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 @@ static int svia_init_one (struct pci_dev
+ 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 @@ static int svia_init_one (struct pci_dev
+ 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 @@ static int svia_init_one (struct pci_dev
+ 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 @@ static int svia_init_one (struct pci_dev
+ 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
+--- 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 @@ static u32 vsc_sata_scr_read (struct ata
+ {
+ 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 @@ static void vsc_sata_scr_write (struct a
+ {
+ 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_intr_mask_update(struct
+ }
+
+
+-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_load(struct ata_
+ 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 Scsi_Host_Template vsc_sata_sht =
+ };
+
+
+-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 @@ static int __devinit vsc_sata_init_one (
+ 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
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -130,7 +130,7 @@ EXPORT_SYMBOL(scsi_device_types);
+ * 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 @@ struct scsi_host_cmd_pool {
+ 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 struct scsi_host_cmd_pool scsi_cm
+ 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 @@ static struct scsi_cmnd *__scsi_get_comm
+ *
+ * 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
+--- a/drivers/scsi/scsi_ioctl.c
++++ b/drivers/scsi/scsi_ioctl.c
+@@ -205,7 +205,8 @@ int scsi_ioctl_send_command(struct scsi_
+ 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
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -677,7 +677,7 @@ static struct scsi_cmnd *scsi_end_reques
+ 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
+--- 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
+--- 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
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -49,6 +49,7 @@ static int sg_version_num = 30533; /* 2
+ #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 @@ static int sg_allow_dio = SG_ALLOW_DIO_D
+
+ #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_alloc(struct gendisk *disk
+ }
+
+ 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 @@ sg_add(struct class_device *cl_dev)
+ 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 @@ out:
+ }
+
+ 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 @@ st_unmap_user_pages(struct scatterlist *
+ 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 @@ sg_build_indirect(Sg_scatter_hold * schp
+ 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 @@ static char *
+ 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
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -3577,7 +3577,8 @@ static long st_compat_ioctl(struct file
+ 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 @@ static struct st_buffer *
+ /* 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 @@ static void do_create_class_files(struct
+ 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 @@ static int sgl_unmap_user_pages(struct s
+ 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
+--- 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
+--- 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
+--- a/drivers/scsi/zalon.c
++++ b/drivers/scsi/zalon.c
+@@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev)
+ 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 @@ zalon_probe(struct parisc_device *dev)
+ 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
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -33,7 +33,7 @@
+ #include <linux/sysrq.h>
+ #include <linux/mca.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial_reg.h>
+@@ -2358,13 +2358,10 @@ static int __devexit serial8250_remove(s
+ 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 @@ static int serial8250_suspend(struct dev
+ 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
+--- 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 @@ serial_init_chip(struct parisc_device *d
+ */
+ 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
+--- 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
+--- 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
+--- a/drivers/serial/clps711x.c
++++ b/drivers/serial/clps711x.c
+@@ -408,7 +408,11 @@ static struct uart_port clps711x_ports[U
+ {
+ .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 @@ static struct uart_port clps711x_ports[U
+ {
+ .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 @@ console_initcall(clps711xuart_console_in
+ 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
+--- a/drivers/serial/imx.c
++++ b/drivers/serial/imx.c
+@@ -36,7 +36,7 @@
+ #include <linux/init.h>
+ #include <linux/console.h>
+ #include <linux/sysrq.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial_core.h>
+@@ -921,21 +921,21 @@ static struct uart_driver imx_reg = {
+ .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;
+@@ -995,6 +995,7 @@ static int __init imx_serial_init(void)
+ static void __exit imx_serial_exit(void)
+ {
+ uart_unregister_driver(&imx_reg);
++ driver_unregister(&serial_imx_driver);
+ }
+
+ module_init(imx_serial_init);
+diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
+--- a/drivers/serial/ioc4_serial.c
++++ b/drivers/serial/ioc4_serial.c
+@@ -308,6 +308,8 @@ struct ioc4_serial {
+ 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 @@ typedef ioc4_intr_func_f *ioc4_intr_func
+ #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 @@ static int inline ioc4_attach_local(stru
+ 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 @@ ioc4_change_speed(struct uart_port *the_
+ 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 @@ ioc4_change_speed(struct uart_port *the_
+ */
+ 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 @@ static inline int ic4_startup_local(stru
+ 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 @@ static inline int ic4_startup_local(stru
+ /* 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 inline int ic4_startup_local(stru
+ */
+ 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 @@ static inline int do_read(struct uart_po
+ * 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 @@ static inline int do_read(struct uart_po
+ }
+ return total;
+ }
++
+ /**
+ * receive_chars - upper level read. Called with ip_lock.
+ * @the_port: port to read from
+@@ -2307,9 +2312,11 @@ static void receive_chars(struct uart_po
+ {
+ 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 @@ static void receive_chars(struct uart_po
+ 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 @@ static void receive_chars(struct uart_po
+ 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 @@ static void ic4_shutdown(struct uart_por
+
+ 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 unsigned int ic4_get_mctrl(struct
+ 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 @@ static int ic4_startup(struct uart_port
+ }
+
+ /* 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 @@ static void
+ 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 @@ ioc4_serial_core_attach(struct pci_dev *
+ __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 @@ ioc4_serial_attach_one(struct ioc4_drive
+ 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
+--- a/drivers/serial/mpc52xx_uart.c
++++ b/drivers/serial/mpc52xx_uart.c
+@@ -45,7 +45,7 @@
+ */
+
+ #include <linux/config.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/tty.h>
+ #include <linux/serial.h>
+@@ -781,22 +781,22 @@ mpc52xx_uart_remove(struct device *dev)
+
+ #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
+--- a/drivers/serial/mpsc.c
++++ b/drivers/serial/mpsc.c
+@@ -52,6 +52,8 @@
+ * 4) AFAICT, hardware flow control isn't supported by the controller --MAG.
+ */
+
++#include <linux/platform_device.h>
++
+ #include "mpsc.h"
+
+ /*
+@@ -1100,6 +1102,8 @@ mpsc_start_rx(struct mpsc_port_info *pi)
+ {
+ 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
+--- 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 @@ static int __init mux_probe(struct paris
+ 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 @@ static int __init mux_probe(struct paris
+ 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 @@ static struct parisc_device_id mux_tbl[]
+ 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
+--- a/drivers/serial/pxa.c
++++ b/drivers/serial/pxa.c
+@@ -39,7 +39,7 @@
+ #include <linux/circ_buf.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial_core.h>
+@@ -358,6 +358,9 @@ static int serial_pxa_startup(struct uar
+ unsigned long flags;
+ int retval;
+
++ if (port->line == 3) /* HWUART */
++ up->mcr |= UART_MCR_AFE;
++ else
+ up->mcr = 0;
+
+ /*
+@@ -481,8 +484,10 @@ serial_pxa_set_termios(struct uart_port
+
+ 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 @@ static struct uart_pxa_port serial_pxa_p
+ .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 @@ static struct uart_driver serial_pxa_reg
+ .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
+--- a/drivers/serial/s3c2410.c
++++ b/drivers/serial/s3c2410.c
+@@ -63,7 +63,7 @@
+
+ #include <linux/module.h>
+ #include <linux/ioport.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/init.h>
+ #include <linux/sysrq.h>
+ #include <linux/console.h>
+@@ -1134,23 +1134,22 @@ static int s3c24xx_serial_remove(struct
+
+ #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
+--- a/drivers/serial/sa1100.c
++++ b/drivers/serial/sa1100.c
+@@ -35,7 +35,7 @@
+ #include <linux/init.h>
+ #include <linux/console.h>
+ #include <linux/sysrq.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial_core.h>
+@@ -834,21 +834,21 @@ static struct uart_driver sa1100_reg = {
+ .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
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -147,8 +147,7 @@ static int uart_startup(struct uart_stat
+ * 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;
+@@ -1968,7 +1967,9 @@ uart_report_port(struct uart_driver *drv
+ break;
+ }
+
+- printk(KERN_INFO "%s%d at %s (irq = %d) is a %s\n",
++ printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
++ port->dev ? port->dev->bus_id : "",
++ port->dev ? ": " : "",
+ drv->dev_name, port->line, address, port->irq, uart_type(port));
+ }
+
+diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
+--- a/drivers/serial/vr41xx_siu.c
++++ b/drivers/serial/vr41xx_siu.c
+@@ -26,7 +26,7 @@
+ #endif
+
+ #include <linux/console.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/err.h>
+ #include <linux/ioport.h>
+ #include <linux/init.h>
+@@ -976,14 +976,11 @@ static int siu_remove(struct device *dev
+ 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 @@ static int siu_suspend(struct device *de
+ 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
+--- 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
+--- 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 @@ unsigned long get_tc_speed(void)
+ 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 @@ static void __init tc_probe(unsigned lon
+ 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 @@ static void __init tc_probe(unsigned lon
+ 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 @@ static void __init tc_probe(unsigned lon
+ 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 @@ void __init tc_init(void)
+ 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 @@ void __init tc_init(void)
+ 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 @@ void __init tc_init(void)
+
+ 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(release_tc_card);
+ 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
+--- 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/ioasic_addrs.h>
+ #include <asm/dec/machtype.h>
++#include <asm/dec/serial.h>
++#include <asm/dec/system.h>
+ #include <asm/dec/tc.h>
+-#include <asm/dec/ioasic_addrs.h>
+-#endif
++
+ #ifdef CONFIG_KGDB
+ #include <asm/kgdb.h>
+ #endif
+@@ -192,18 +192,6 @@ static void probe_sccs(void);
+ 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 @@ static void __init probe_sccs(void)
+ 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 @@ static void __init probe_sccs(void)
+ * 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
+--- a/drivers/usb/Makefile
++++ b/drivers/usb/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_USB) += core/
+
+ 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_ETRAX_USB_HOST) += host/
+
+ 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
+--- a/drivers/usb/class/Kconfig
++++ b/drivers/usb/class/Kconfig
+@@ -28,29 +28,6 @@ config USB_AUDIO
+ 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
+--- 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
+--- 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 at kroah.com>
+- * Copyright (C) 2000 Mark Douglas Corner <mcorner at 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 at 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 at 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, ¤t_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
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -827,11 +827,10 @@ skip_normal_probe:
+ 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
+--- a/drivers/usb/class/usblp.c
++++ b/drivers/usb/class/usblp.c
+@@ -844,9 +844,8 @@ static struct file_operations usblp_fops
+ };
+
+ 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
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -61,14 +61,17 @@ config USB_DYNAMIC_MINORS
+ 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
+--- 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
+--- a/drivers/usb/core/buffer.c
++++ b/drivers/usb/core/buffer.c
+@@ -106,7 +106,7 @@ void hcd_buffer_destroy (struct usb_hcd
+ 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
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -112,8 +112,12 @@ void usb_release_interface_cache(struct
+ 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 @@ static int usb_parse_interface(struct de
+ }
+
+ 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 @@ static int usb_parse_configuration(struc
+ }
+
+ 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 @@ void usb_destroy_configuration(struct us
+ 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 @@ int usb_get_configuration(struct usb_dev
+ }
+
+ 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
+--- 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 @@ err:
+ 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 @@ static inline struct async *async_getpen
+ 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 @@ static void async_completed(struct urb *
+ 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 @@ static int check_ctrlrecip(struct dev_st
+ 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 @@ static int proc_control(struct dev_state
+ 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 @@ static int proc_control(struct dev_state
+ 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 @@ static int proc_bulk(struct dev_state *p
+ 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 @@ static int proc_bulk(struct dev_state *p
+ 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 @@ static int proc_bulk(struct dev_state *p
+ 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 @@ static int proc_setconfig(struct dev_sta
+ 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 @@ static int proc_do_submiturb(struct dev_
+ kfree(dr);
+ return -EFAULT;
+ }
++ snoop(&ps->dev->dev, "control urb\n");
+ break;
+
+ case USBDEVFS_URB_TYPE_BULK:
+@@ -910,6 +968,7 @@ static int proc_do_submiturb(struct dev_
+ 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 @@ static int proc_do_submiturb(struct dev_
+ return -EINVAL;
+ }
+ uurb->buffer_length = totlen;
++ snoop(&ps->dev->dev, "iso urb\n");
+ break;
+
+ case USBDEVFS_URB_TYPE_INTERRUPT:
+@@ -954,6 +1014,7 @@ static int proc_do_submiturb(struct dev_
+ 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 @@ static int proc_do_submiturb(struct dev_
+ 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 @@ static int proc_releaseinterface(struct
+ 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 @@ static int proc_ioctl (struct dev_state
+
+ 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 @@ static int proc_ioctl (struct dev_state
+ 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 @@ static int proc_ioctl (struct dev_state
+
+ /* 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 @@ static int usbdev_ioctl(struct inode *in
+ 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 @@ static int usbdev_ioctl(struct inode *in
+
+ 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 @@ struct file_operations usbfs_device_file
+ .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 @@ int __init usbdev_init(void)
+ 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
+--- 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 @@ int usb_major_init(void)
+ goto out;
+ }
+
+- devfs_mk_dir("usb");
+-
+ out:
+ return error;
+ }
+@@ -97,7 +94,6 @@ out:
+ void usb_major_cleanup(void)
+ {
+ class_destroy(usb_class);
+- devfs_remove("usb");
+ unregister_chrdev(USB_MAJOR, "usb");
+ }
+
+@@ -112,8 +108,7 @@ void usb_major_cleanup(void)
+ * 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 @@ int usb_register_dev(struct usb_interfac
+
+ 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 @@ EXPORT_SYMBOL(usb_register_dev);
+ * 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 @@ void usb_deregister_dev(struct usb_inter
+ 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
+--- 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 @@ int usb_hcd_pci_suspend (struct pci_dev
+
+ 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 @@ int usb_hcd_pci_suspend (struct pci_dev
+ */
+ 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 @@ int usb_hcd_pci_suspend (struct pci_dev
+
+ 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 @@ int usb_hcd_pci_suspend (struct pci_dev
+ 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 @@ int usb_hcd_pci_resume (struct pci_dev *
+ 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 @@ int usb_hcd_pci_resume (struct pci_dev *
+
+ 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
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -130,7 +130,7 @@ static const u8 usb2_rh_dev_descriptor [
+ 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 @@ static const u8 usb11_rh_dev_descriptor
+ 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 @@ static int rh_call_control (struct usb_h
+
+ 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 @@ error:
+ "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 *usb_alloc_bus (struct us
+ {
+ 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 @@ static int usb_register_bus(struct usb_b
+ 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 @@ static int usb_register_bus(struct usb_b
+ 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 @@ static void usb_deregister_bus (struct u
+ 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 @@ static void urb_unlink (struct urb *urb)
+ * 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 @@ static int hcd_submit_urb (struct urb *u
+ 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 @@ static int hcd_unlink_urb (struct urb *u
+ 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 @@ rescan:
+
+ /*-------------------------------------------------------------------------*/
+
+-#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 @@ static int hcd_hub_resume (struct usb_bu
+ * 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,13 +1532,9 @@ void usb_hcd_resume_root_hub (struct usb
+ usb_resume_root_hub (hcd->self.root_hub);
+ spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+ }
++EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
+
+-#else
+-void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+-{
+-}
+ #endif
+-EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
+
+ /*-------------------------------------------------------------------------*/
+
+@@ -1529,10 +1587,6 @@ static struct usb_operations usb_hcd_ope
+ .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
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -142,22 +142,18 @@ struct hcd_timeout { /* timeouts we allo
+
+ 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 @@ struct hc_driver {
+ 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 @@ struct hc_driver {
+ 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 @@ struct hc_driver {
+ 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 @@ int hcd_buffer_create (struct usb_hcd *h
+ 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 long usb_calc_bus_time (int speed
+
+ 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 @@ extern int usb_find_interface_driver (st
+
+ #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 @@ extern int usb_find_interface_driver (st
+ * 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 @@ struct usb_mon_operations {
+ 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 @@ static inline void usbmon_urb_complete(s
+ 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(str
+ 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
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -436,9 +436,10 @@ static void hub_power_on(struct usb_hub
+ {
+ 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 @@ static void hub_power_on(struct usb_hub
+ msleep(max(pgood_delay, (unsigned) 100));
+ }
+
+-static void hub_quiesce(struct usb_hub *hub)
++static inline void __hub_quiesce(struct usb_hub *hub)
+ {
+- /* stop khubd and related activity */
++ /* (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)
++{
++ /* (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 @@ static void hub_activate(struct usb_hub
+
+ 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 @@ static int hub_configure(struct usb_hub
+ 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 @@ static int hub_configure(struct usb_hub
+ 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 @@ static int hub_configure(struct usb_hub
+ } 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 @@ static int hub_configure(struct usb_hub
+ 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 @@ static int hub_configure(struct usb_hub
+ }
+
+ /* 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 @@ static int hub_configure(struct usb_hub
+ }
+
+ /* 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 @@ static int hub_configure(struct usb_hub
+ (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 @@ descriptor_error:
+ /* 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 @@ void usb_set_device_state(struct usb_dev
+ 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 @@ void usb_disconnect(struct usb_device **
+ */
+ 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 @@ static inline void show_string(struct us
+ {}
+ #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 @@ int usb_new_device(struct usb_device *ud
+ }
+
+ /* 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 @@ int usb_new_device(struct usb_device *ud
+ * (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 @@ int usb_new_device(struct usb_device *ud
+ }
+
+ /* 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 @@ static void hub_port_logical_disconnect(
+ /* 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 @@ static int hub_port_suspend(struct usb_h
+ * 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 @@ static int hub_port_suspend(struct usb_h
+ * 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 @@ static int __usb_suspend_device (struct
+ 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...)
+- */
+- 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.
++ /* we only change a device's upstream USB link.
++ * root hubs have no upstream USB 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 @@ static int __usb_suspend_device (struct
+ * 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 @@ static int finish_port_resume(struct usb
+ 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 @@ static int finish_port_resume(struct usb
+ 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 @@ static int finish_port_resume(struct usb
+ }
+
+ /* 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 @@ static int finish_port_resume(struct usb
+ 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 @@ hub_port_resume(struct usb_hub *hub, int
+ /* TRSMRCY = 10 msec */
+ msleep(10);
+ if (udev)
+- status = finish_port_resume(udev);
++ status = finish_device_resume(udev);
+ }
+ }
+ if (status < 0)
+@@ -1868,12 +1802,12 @@ hub_port_resume(struct usb_hub *hub, int
+ 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 @@ int usb_resume_device(struct usb_device
+ 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 @@ static int remote_wakeup(struct usb_devi
+ {
+ 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 @@ static int remote_wakeup(struct usb_devi
+ 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 @@ static int hub_resume(struct usb_interfa
+ {
+ 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 @@ static int hub_resume(struct usb_interfa
+ 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,43 +1983,31 @@ static int hub_resume(struct usb_interfa
+ }
+ up(&udev->serialize);
+ }
+- intf->dev.power.power_state = PMSG_ON;
+-
+- hub->resume_root_hub = 0;
+- hub_activate(hub);
++ }
++#endif
+ return 0;
+ }
+
+-void usb_resume_root_hub(struct usb_device *hdev)
++void usb_suspend_root_hub(struct usb_device *hdev)
+ {
+ struct usb_hub *hub = hdev_to_hub(hdev);
+
+- hub->resume_root_hub = 1;
+- kick_khubd(hub);
++ /* 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));
+ }
+
+-#else /* !CONFIG_USB_SUSPEND */
+-
+-int usb_suspend_device(struct usb_device *udev, pm_message_t state)
++void usb_resume_root_hub(struct usb_device *hdev)
+ {
+- return 0;
+-}
++ struct usb_hub *hub = hdev_to_hub(hdev);
+
+-int usb_resume_device(struct usb_device *udev)
+-{
+- return 0;
++ hub->resume_root_hub = 1;
++ kick_khubd(hub);
+ }
+
+-#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 @@ static void hub_port_connect_change(stru
+ {
+ 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 @@ static void hub_port_connect_change(stru
+ 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 @@ static void hub_events(void)
+ 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
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -131,7 +131,7 @@ struct usb_hub_descriptor {
+ __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
+--- 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_update_special (void)
+ }
+ }
+
+-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 @@ void usbfs_add_bus(struct usb_bus *bus)
+ 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 @@ void usbfs_remove_bus(struct usb_bus *bu
+ 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 @@ void usbfs_add_device(struct usb_device
+ }
+ 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 @@ void usbfs_remove_device(struct usb_devi
+ 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 @@ int __init usbfs_init(void)
+ if (retval)
+ return retval;
+
++ usb_register_notify(&usbfs_nb);
++
+ /* create mount point for usbfs */
+ usbdir = proc_mkdir("usb", proc_bus);
+
+@@ -740,6 +757,7 @@ int __init usbfs_init(void)
+
+ 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
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -187,21 +187,37 @@ int usb_control_msg(struct usb_device *d
+ * 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 @@ int usb_sg_init (
+ struct scatterlist *sg,
+ int nents,
+ size_t length,
+- unsigned mem_flags
++ gfp_t mem_flags
+ )
+ {
+ int i;
+@@ -771,6 +787,31 @@ int usb_string(struct usb_device *dev, i
+ 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 @@ void usb_disable_device(struct usb_devic
+ 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 @@ int usb_set_interface(struct usb_device
+ */
+
+ /* 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 @@ int usb_set_interface(struct usb_device
+ * (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 @@ int usb_reset_configuration(struct usb_d
+ 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 @@ int usb_reset_configuration(struct usb_d
+ 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 @@ int usb_reset_configuration(struct usb_d
+
+ 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 @@ int usb_set_configuration(struct usb_dev
+ }
+
+ 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 @@ free_interfaces:
+ 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 @@ free_interfaces:
+ 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 @@ free_interfaces:
+ }
+ 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 @@ free_interfaces:
+ */
+ 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 @@ free_interfaces:
+ 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
+--- /dev/null
++++ b/drivers/usb/core/notify.c
+@@ -0,0 +1,120 @@
++/*
++ * All the USB notify logic
++ *
++ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh at 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
+--- 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 (bNumInterfaces, 1, "
+ 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 @@ static DEVICE_ATTR(configuration, S_IRUG
+ 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 @@ static DEVICE_ATTR(bConfigurationValue,
+
+ /* 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 @@ static DEVICE_ATTR(maxchild, S_IRUGO, sh
+ /* 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 @@ usb_descriptor_attr_le16(bcdDevice, "%04
+
+ #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 @@ void usb_create_sysfs_dev_files (struct
+ 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 @@ void usb_remove_sysfs_dev_files (struct
+ /* 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 (bInterfaceClass, "%02x\n"
+ 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 ssize_t show_interface_string(str
+ }
+ 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 @@ static struct attribute_group intf_attr_
+ .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
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -60,7 +60,7 @@ void usb_init_urb(struct urb *urb)
+ *
+ * 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 @@ struct urb * usb_get_urb(struct urb *urb
+ * 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 @@ int usb_submit_urb(struct urb *urb, unsi
+ (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
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -107,10 +107,19 @@ static int usb_probe_interface(struct de
+ 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 @@ static int usb_unbind_interface(struct d
+ 0);
+ usb_set_intfdata(intf, NULL);
+ intf->condition = USB_INTERFACE_UNBOUND;
++ mark_quiesced(intf);
+
+ return 0;
+ }
+@@ -299,6 +309,7 @@ int usb_driver_claim_interface(struct us
+ 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 @@ void usb_driver_release_interface(struct
+ dev->driver = NULL;
+ usb_set_intfdata(iface, NULL);
+ iface->condition = USB_INTERFACE_UNBOUND;
++ mark_quiesced(iface);
+ }
+
+ /**
+@@ -557,6 +569,7 @@ static int usb_hotplug (struct device *d
+ {
+ struct usb_interface *intf;
+ struct usb_device *usb_dev;
++ struct usb_host_interface *alt;
+ int i = 0;
+ int length = 0;
+
+@@ -573,7 +586,8 @@ static int usb_hotplug (struct device *d
+
+ 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 @@ static int usb_hotplug (struct device *d
+ 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 @@ usb_alloc_dev(struct usb_device *parent,
+ {
+ 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 @@ int __usb_get_extra_descriptor(char *buf
+ 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 @@ void usb_buffer_unmap_sg (struct usb_dev
+ usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+
+-static int usb_generic_suspend(struct device *dev, pm_message_t message)
++static int verify_suspended(struct device *dev, void *unused)
+ {
+- struct usb_interface *intf;
+- struct usb_driver *driver;
++ return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
++}
+
+- if (dev->driver == &usb_generic_driver)
+- return usb_suspend_device (to_usb_device(dev), message);
++static int usb_generic_suspend(struct device *dev, pm_message_t message)
++{
++ struct usb_interface *intf;
++ struct usb_driver *driver;
++ int status;
++
++ /* 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 @@ static int usb_generic_suspend(struct de
+ 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 @@ static int usb_generic_resume(struct dev
+ 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
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -13,12 +13,14 @@ extern void usb_disable_device (struct u
+
+ 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 void usb_major_cleanup(void);
+ 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 void usbfs_conn_disc_event(void);
+
+ 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 @@ struct dev_state {
+ 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
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -50,7 +50,7 @@
+ #include <linux/list.h>
+ #include <linux/interrupt.h>
+ #include <linux/version.h>
+-
++#include <linux/platform_device.h>
+ #include <linux/usb.h>
+ #include <linux/usb_gadget.h>
+
+@@ -470,7 +470,7 @@ static int dummy_disable (struct usb_ep
+ }
+
+ 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 @@ dummy_alloc_buffer (
+ 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 @@ fifo_complete (struct usb_ep *ep, struct
+
+ 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 @@ static int dummy_udc_remove (struct devi
+ 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 @@ static int dummy_udc_suspend (struct dev
+ 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 int dummy_udc_resume (struct devi
+
+ 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 @@ static int dummy_urb_enqueue (
+ 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 @@ static int dummy_hub_control (
+ 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 @@ static int dummy_hub_suspend (struct usb
+ 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 @@ static const struct hc_driver dummy_hcd
+
+ .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 @@ static int dummy_hcd_remove (struct devi
+ 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
+--- a/drivers/usb/gadget/ether.c
++++ b/drivers/usb/gadget/ether.c
+@@ -945,11 +945,11 @@ config_buf (enum usb_device_speed speed,
+
+ /*-------------------------------------------------------------------------*/
+
+-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 @@ static void eth_reset_config (struct eth
+ * 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 defer_kevent (struct eth_dev
+ 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 @@ clean:
+ }
+
+ 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 @@ extra:
+ 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 @@ fail:
+ 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 @@ drop:
+ * 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 @@ static int rndis_control_ack (struct net
+
+ #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 int eth_stop (struct net_device *
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ static struct usb_gadget_driver eth_driv
+
+ .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
+--- 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 @@ struct fsg_dev {
+ 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 wakeup_thread(struct fsg_dev
+ 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 @@ static void raise_exception(struct fsg_d
+ 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 @@ static int fsg_main_thread(void *fsg_)
+ {
+ 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 @@ static int fsg_main_thread(void *fsg_)
+ * 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 @@ static int fsg_main_thread(void *fsg_)
+ 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 @@ static int __init fsg_bind(struct usb_ga
+
+ /* 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 @@ static int __init fsg_bind(struct usb_ga
+ 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 @@ static int __init fsg_bind(struct usb_ga
+ 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 @@ static struct usb_gadget_driver fsg_dri
+
+ .driver = {
+ .name = (char *) shortname,
++ .owner = THIS_MODULE,
+ // .release = ...
+ // .suspend = ...
+ // .resume = ...
+@@ -4057,10 +4056,9 @@ static int __init fsg_alloc(void)
+ {
+ 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 @@ static int __init fsg_init(void)
+ 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
+--- a/drivers/usb/gadget/goku_udc.c
++++ b/drivers/usb/gadget/goku_udc.c
+@@ -269,7 +269,7 @@ static int goku_ep_disable(struct usb_ep
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ goku_free_request(struct usb_ep *_ep, st
+ */
+ 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 @@ finished:
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
+ 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
+--- a/drivers/usb/gadget/lh7a40x_udc.c
++++ b/drivers/usb/gadget/lh7a40x_udc.c
+@@ -21,6 +21,8 @@
+ *
+ */
+
++#include <linux/platform_device.h>
++
+ #include "lh7a40x_udc.h"
+
+ //#define DEBUG printk
+@@ -71,13 +73,13 @@ static char *state_names[] = {
+ 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 +1108,7 @@ static int lh7a40x_ep_disable(struct usb
+ }
+
+ static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
+- unsigned gfp_flags)
++ gfp_t gfp_flags)
+ {
+ struct lh7a40x_request *req;
+
+@@ -1134,7 +1136,7 @@ static void lh7a40x_free_request(struct
+ }
+
+ 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 +1160,7 @@ static void lh7a40x_free_buffer(struct u
+ * 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 +2142,7 @@ static int lh7a40x_udc_remove(struct dev
+
+ 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
+--- a/drivers/usb/gadget/net2280.c
++++ b/drivers/usb/gadget/net2280.c
+@@ -376,7 +376,7 @@ static int net2280_disable (struct usb_e
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ net2280_alloc_buffer (
+ struct usb_ep *_ep,
+ unsigned bytes,
+ dma_addr_t *dma,
+- unsigned gfp_flags
++ gfp_t gfp_flags
+ )
+ {
+ void *retval;
+@@ -897,7 +897,7 @@ done (struct net2280_ep *ep, struct net2
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
+ 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
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -38,7 +38,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/mm.h>
+ #include <linux/moduleparam.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/usb_ch9.h>
+ #include <linux/usb_gadget.h>
+ #include <linux/usb_otg.h>
+@@ -269,7 +269,7 @@ static int omap_ep_disable(struct usb_ep
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ omap_alloc_buffer(
+ 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 next_out_dma(struct omap_ep
+ }
+
+ 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 @@ finish_out_dma(struct omap_ep *ep, struc
+ 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 @@ static void dma_irq(struct omap_udc *udc
+ 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 @@ static void dma_channel_release(struct o
+ 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 void dma_channel_release(struct o
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ static void devstate_irq(struct omap_udc
+ 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 @@ static int __exit omap_udc_remove(struct
+ * 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 @@ static int omap_udc_suspend(struct devic
+ 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 int omap_udc_resume(struct device
+
+ 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
+--- a/drivers/usb/gadget/pxa2xx_udc.c
++++ b/drivers/usb/gadget/pxa2xx_udc.c
+@@ -43,7 +43,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/proc_fs.h>
+ #include <linux/mm.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <asm/byteorder.h>
+@@ -332,7 +332,7 @@ static int pxa2xx_ep_disable (struct usb
+ * 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 @@ pxa2xx_ep_free_request (struct usb_ep *_
+ */
+ 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 inline void ep0_idle (struct pxa2
+ }
+
+ 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 @@ done:
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ static int __exit pxa2xx_udc_remove(stru
+ * 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 int pxa2xx_udc_resume(struct devi
+
+ 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
+--- a/drivers/usb/gadget/pxa2xx_udc.h
++++ b/drivers/usb/gadget/pxa2xx_udc.h
+@@ -69,11 +69,11 @@ struct pxa2xx_ep {
+ * 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
+--- a/drivers/usb/gadget/serial.c
++++ b/drivers/usb/gadget/serial.c
+@@ -300,18 +300,18 @@ static int gs_build_config_buf(u8 *buf,
+ 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 @@ static int gs_build_config_buf(u8 *buf,
+ * 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 @@ static void gs_free_req(struct usb_ep *e
+ * 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 @@ static void gs_free_req_entry(struct usb
+ *
+ * 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 @@ static void gs_free_ports(struct gs_dev
+ *
+ * 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
+--- a/drivers/usb/gadget/zero.c
++++ b/drivers/usb/gadget/zero.c
+@@ -612,7 +612,7 @@ static void source_sink_complete (struct
+ }
+
+ 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 @@ source_sink_start_ep (struct usb_ep *ep,
+ }
+
+ 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 void loopback_complete (struct us
+ }
+
+ 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 @@ static void zero_reset_config (struct ze
+ * 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 @@ static struct usb_gadget_driver zero_dri
+
+ .driver = {
+ .name = (char *) shortname,
++ .owner = THIS_MODULE,
+ // .shutdown = ...
+ // .suspend = ...
+ // .resume = ...
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+--- 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
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -182,6 +182,9 @@ static int ehci_halt (struct ehci_hcd *e
+ {
+ 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 @@ static void ehci_watchdog (unsigned long
+ 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 @@ static void ehci_port_power (struct ehci
+ msleep(20);
+ }
+
++/*-------------------------------------------------------------------------*/
++
++/*
++ * 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;
+
+-/* called by khubd or root hub init threads */
++ /* 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_hc_reset (struct usb_hcd *hcd)
++static void ehci_stop (struct usb_hcd *hcd)
+ {
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+- u32 temp;
+- unsigned count = 256/4;
+
+- spin_lock_init (&ehci->lock);
++ ehci_dbg (ehci, "stop\n");
+
+- 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;
+- }
++ /* Turn off port power on all root hub ports. */
++ ehci_port_power (ehci, 0);
+
+- /* 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;
+- }
+- }
++ /* no more interrupts ... */
++ del_timer_sync (&ehci->watchdog);
+
+- 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
++ spin_lock_irq(&ehci->lock);
++ if (HC_IS_RUNNING (hcd->state))
++ ehci_quiesce (ehci);
+
+- ehci_port_power (ehci, 0);
++ ehci_reset (ehci);
++ writel (0, &ehci->regs->intr_enable);
++ spin_unlock_irq(&ehci->lock);
+
+- /* 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;
+- }
+- }
++ /* 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
+- }
+
+- /* force HC to halt state */
+- return ehci_halt (ehci);
++ dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
+ }
+
+-static int ehci_start (struct usb_hcd *hcd)
++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 @@ static int ehci_start (struct usb_hcd *h
+ }
+ 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 @@ static int ehci_start (struct usb_hcd *h
+ 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 @@ static int ehci_start (struct usb_hcd *h
+ 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 @@ static int ehci_urb_enqueue (
+ 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 @@ done:
+ 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;
+-
+- 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);
++#ifdef CONFIG_PCI
++#include "ehci-pci.c"
++#endif
+
+-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
+--- 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 @@ static int ehci_hub_suspend (struct usb_
+
+
+ /* 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 @@ static int ehci_hub_resume (struct usb_h
+
+ #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
+--- a/drivers/usb/host/ehci-mem.c
++++ b/drivers/usb/host/ehci-mem.c
+@@ -45,7 +45,7 @@ static inline void ehci_qtd_init (struct
+ 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 @@ static void qh_destroy (struct kref *kre
+ 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 @@ static void ehci_mem_cleanup (struct ehc
+ }
+
+ /* 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
+--- /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
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -477,7 +477,7 @@ qh_urb_transaction (
+ 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 @@ static struct ehci_qh *
+ 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 @@ submit_async (
+ 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
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -589,7 +589,7 @@ static int intr_submit (
+ 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 @@ done:
+ /* 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 @@ iso_stream_find (struct ehci_hcd *ehci,
+ /* 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 @@ itd_urb_transaction (
+ 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 @@ itd_complete (
+ /*-------------------------------------------------------------------------*/
+
+ 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 @@ sitd_urb_transaction (
+ 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 @@ sitd_complete (
+
+
+ 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
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -97,6 +97,7 @@ struct ehci_hcd { /* one per controlle
+ #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
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -70,6 +70,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/usb.h>
+ #include <linux/usb_isp116x.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -638,7 +639,7 @@ static irqreturn_t isp116x_irq(struct us
+ + 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 +695,7 @@ static int balance(struct isp116x *isp11
+
+ 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 +1161,7 @@ static int isp116x_hub_control(struct us
+
+ #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 +1201,7 @@ static int isp116x_hub_suspend(struct us
+ 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 +1264,11 @@ static int isp116x_hub_resume(struct usb
+ 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 +1627,8 @@ static struct hc_driver isp116x_hc_drive
+
+ .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 +1723,6 @@ static int __init isp116x_probe(struct d
+ 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 +1764,13 @@ static int __init isp116x_probe(struct d
+ /*
+ 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 +1778,14 @@ static int isp116x_suspend(struct device
+ /*
+ 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);
++
++ dev->power.power_state = PMSG_ON;
+
+- ret = usb_resume_device(hcd->self.root_hub);
+- if (!ret) {
+- dev->power.power_state = PMSG_ON;
+- VDBG("%s resumed\n", (char *)hcd_name);
+- }
+ return ret;
+ }
+
+diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
+--- a/drivers/usb/host/isp116x.h
++++ b/drivers/usb/host/isp116x.h
+@@ -253,7 +253,6 @@ static const int cc_to_error[16] = {
+
+ 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
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -18,6 +18,8 @@
+ * This file is licenced under the GPL.
+ */
+
++#include <linux/platform_device.h>
++
+ #include <asm/mach-au1x00/au1000.h>
+
+ #define USBH_ENABLE_BE (1<<0)
+@@ -214,6 +216,11 @@ static const struct hc_driver ohci_au1xx
+ */
+ .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 +266,7 @@ static int ohci_hcd_au1xxx_drv_resume(st
+
+ 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
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -193,10 +193,6 @@ ohci_dump_status (struct ohci_hcd *contr
+
+ maybe_print_eds (controller, "donehead",
+ ohci_readl (controller, ®s->donehead), next, size);
+-
+- /* broken fminterval means traffic won't flow! */
+- ohci_dbg (controller, "fminterval %08x\n",
+- ohci_readl (controller, ®s->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
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -180,7 +180,7 @@ static int ohci_urb_enqueue (
+ 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 @@ static irqreturn_t ohci_irq (struct usb_
+ ohci_vdbg (ohci, "resume detect\n");
+ ohci_writel (ohci, OHCI_INTR_RD, ®s->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 @@ static void ohci_stop (struct usb_hcd *h
+
+ /* 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
+--- 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 dl_done_list (struct ohci_hc
+ 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 @@ static int ohci_hub_suspend (struct usb_
+ 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 @@ static int ohci_hub_suspend (struct usb_
+ 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 @@ static int ohci_hub_suspend (struct usb_
+ 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 @@ static inline struct ed *find_head (stru
+ }
+
+ /* 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 @@ static int ohci_hub_resume (struct usb_h
+ 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 @@ static int ohci_hub_resume (struct usb_h
+ 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 @@ static int ohci_hub_resume (struct usb_h
+ }
+
+ /* 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 @@ static int ohci_hub_resume (struct usb_h
+ (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 @@ done:
+ #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 @@ done:
+ && 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 @@ static int ohci_hub_control (
+ 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
+--- a/drivers/usb/host/ohci-lh7a404.c
++++ b/drivers/usb/host/ohci-lh7a404.c
+@@ -16,6 +16,8 @@
+ * This file is licenced under the GPL.
+ */
+
++#include <linux/platform_device.h>
++
+ #include <asm/hardware.h>
+
+
+@@ -193,6 +195,11 @@ static const struct hc_driver ohci_lh7a4
+ */
+ .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 +246,7 @@ static int ohci_hcd_lh7a404_drv_resume(s
+
+ 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
+--- a/drivers/usb/host/ohci-mem.c
++++ b/drivers/usb/host/ohci-mem.c
+@@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_h
+ 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 @@ dma_to_td (struct ohci_hcd *hc, dma_addr
+
+ /* 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 @@ td_free (struct ohci_hcd *hc, struct td
+
+ /* 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
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -14,6 +14,10 @@
+ * This file is licenced under the GPL.
+ */
+
++#include <linux/signal.h> /* SA_INTERRUPT */
++#include <linux/jiffies.h>
++#include <linux/platform_device.h>
++
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/mach-types.h>
+@@ -420,9 +424,9 @@ static const struct hc_driver ohci_omap_
+ */
+ .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 +459,32 @@ static int ohci_hcd_omap_drv_remove(stru
+
+ #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;
++ if (time_before(jiffies, ohci->next_statechange))
++ msleep(5);
++ ohci->next_statechange = jiffies;
+
+- 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;
++ 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, u32 level)
++static int ohci_omap_resume(struct device *dev)
+ {
+ 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(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 +496,7 @@ static int ohci_omap_resume(struct devic
+ */
+ 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
+--- 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 @@ ohci_pci_start (struct usb_hcd *hcd)
+
+ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ {
+- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+-
+- /* 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
++ /* root hub was already suspended */
+
+- /* 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_suspend (struct usb_
+
+ 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 @@ static int ohci_pci_resume (struct usb_h
+ }
+ #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 @@ static const struct hc_driver ohci_pci_h
+ */
+ .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 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
+ 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
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -14,6 +14,8 @@
+ * This file is licenced under the GPL.
+ */
+
++#include <linux/platform_device.h>
++
+ /* configure so an HC device and id are always provided */
+ /* always called with process context; sleeping is OK */
+
+@@ -163,9 +165,9 @@ static const struct hc_driver ohci_ppc_s
+ */
+ .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 +195,11 @@ static int ohci_hcd_ppc_soc_drv_remove(s
+
+ 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
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -20,6 +20,9 @@
+ */
+
+ #include <linux/device.h>
++#include <linux/signal.h>
++#include <linux/platform_device.h>
++
+ #include <asm/mach-types.h>
+ #include <asm/hardware.h>
+ #include <asm/arch/pxa-regs.h>
+@@ -278,10 +281,11 @@ static const struct hc_driver ohci_pxa27
+ */
+ .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 +313,7 @@ static int ohci_hcd_pxa27x_drv_remove(st
+ 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 +322,7 @@ static int ohci_hcd_pxa27x_drv_suspend(s
+ 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
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -19,6 +19,8 @@
+ * This file is licenced under the GPL.
+ */
+
++#include <linux/platform_device.h>
++
+ #include <asm/hardware.h>
+ #include <asm/hardware/clock.h>
+ #include <asm/arch/usb-control.h>
+@@ -448,11 +450,11 @@ static const struct hc_driver ohci_s3c24
+ */
+ .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 +476,7 @@ static int ohci_hcd_s3c2410_drv_remove(s
+
+ 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
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -235,10 +235,11 @@ static const struct hc_driver ohci_sa111
+ */
+ .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
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -389,7 +389,6 @@ struct ohci_hcd {
+ 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
+--- /dev/null
++++ b/drivers/usb/host/pci-quirks.c
+@@ -0,0 +1,319 @@
++/*
++ * 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 at 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 inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
++{
++ u16 cmd;
++ return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask);
++}
++
++#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
++#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
++
++static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
++{
++ unsigned long base = 0;
++ int i;
++
++ if (!pio_enabled(pdev))
++ return;
++
++ 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 int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
++{
++ return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
++}
++
++static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
++{
++ void __iomem *base;
++ int wait_time;
++ u32 control;
++
++ if (!mmio_resource_enabled(pdev, 0))
++ return;
++
++ 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;
++
++ if (!mmio_resource_enabled(pdev, 0))
++ return;
++
++ 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
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -54,6 +54,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/usb.h>
+ #include <linux/usb_sl811.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -818,7 +819,7 @@ static int sl811h_urb_enqueue(
+ 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 +1364,7 @@ error:
+ #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 +1372,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd)
+ }
+
+ static int
+-sl811h_hub_resume(struct usb_hcd *hcd)
++sl811h_bus_resume(struct usb_hcd *hcd)
+ {
+ // SOFs on
+ DBG("%s\n", __FUNCTION__);
+@@ -1380,8 +1381,8 @@ sl811h_hub_resume(struct usb_hcd *hcd)
+
+ #else
+
+-#define sl811h_hub_suspend NULL
+-#define sl811h_hub_resume NULL
++#define sl811h_bus_suspend NULL
++#define sl811h_bus_resume NULL
+
+ #endif
+
+@@ -1623,8 +1624,8 @@ static struct hc_driver sl811h_hc_driver
+ */
+ .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 +1785,14 @@ sl811h_probe(struct device *dev)
+ */
+
+ 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 +1801,11 @@ sl811h_suspend(struct device *dev, pm_me
+ }
+
+ 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 +1817,7 @@ sl811h_resume(struct device *dev, u32 ph
+ }
+
+ dev->power.power_state = PMSG_ON;
+- return sl811h_hub_resume(hcd);
++ return sl811h_bus_resume(hcd);
+ }
+
+ #else
+@@ -1837,6 +1832,7 @@ sl811h_resume(struct device *dev, u32 ph
+ 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/sl811_cs.c b/drivers/usb/host/sl811_cs.c
+--- a/drivers/usb/host/sl811_cs.c
++++ b/drivers/usb/host/sl811_cs.c
+@@ -19,6 +19,7 @@
+ #include <linux/string.h>
+ #include <linux/timer.h>
+ #include <linux/ioport.h>
++#include <linux/platform_device.h>
+
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
+--- a/drivers/usb/host/uhci-debug.c
++++ b/drivers/usb/host/uhci-debug.c
+@@ -348,7 +348,6 @@ static int uhci_show_urbp(struct uhci_hc
+
+ 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 @@ static int uhci_sprint_schedule(struct u
+ 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
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -101,37 +101,16 @@ static void uhci_get_current_frame_numbe
+ #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 reset_hc(struct uhci_hcd *uh
+ */
+ 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 hc_died(struct uhci_hcd *uhc
+ */
+ 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 @@ static void configure_hc(struct uhci_hcd
+ 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 @@ __acquires(uhci->lock)
+
+ 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 @@ static void release_uhci(struct uhci_hcd
+ 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 @@ static int uhci_start(struct usb_hcd *hc
+ 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 @@ static int uhci_start(struct usb_hcd *hc
+
+ 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 @@ static int uhci_start(struct usb_hcd *hc
+ 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 @@ static int uhci_start(struct usb_hcd *hc
+ * 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_frame_cpu:
++ dma_free_coherent(uhci_dev(uhci),
++ UHCI_NUMFRAMES * sizeof(*uhci->frame),
++ uhci->frame, uhci->frame_dma_handle);
+
+-err_alloc_fl:
++err_alloc_frame:
+ debugfs_remove(uhci->dentry);
+- uhci->dentry = NULL;
+
+ err_create_debug_entry:
+ return retval;
+@@ -726,7 +659,7 @@ static void uhci_stop(struct usb_hcd *hc
+
+ 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 @@ static int uhci_suspend(struct usb_hcd *
+ 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 @@ static int uhci_resume(struct usb_hcd *h
+ 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 @@ static const struct hc_driver uhci_drive
+ #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 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
+ 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
+--- 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 uhci_qh {
+
+ 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 @@ static __le32 inline qh_element(struct u
+ return element;
+ }
+
++
++/*
++ * Transfer Descriptors
++ */
++
+ /*
+ * for TD <status>:
+ */
+@@ -183,17 +184,10 @@ static __le32 inline qh_element(struct u
+ *
+ * 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 @@ struct uhci_td {
+ /* 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 @@ static u32 inline td_status(struct uhci_
+
+
+ /*
++ * 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 @@ static u32 inline td_status(struct uhci_
+ *
+ * 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 @@ static inline int __interval_to_skel(int
+ return 0; /* int128 for 128-255 ms (Max.) */
+ }
+
++
++/*
++ * The UHCI controller and root hub
++ */
++
+ /*
+- * States for the 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 @@ static inline int __interval_to_skel(int
+ */
+ 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 @@ enum uhci_rh_state {
+ 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_hcd {
+ 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 @@ struct uhci_hcd {
+ 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 @@ static inline struct usb_hcd *uhci_to_hc
+
+ #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 @@ struct urb_priv {
+ /* 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 @@ struct urb_priv {
+
+ #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
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(st
+ 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 @@ static void uhci_insert_td_frame_list(st
+ 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 @@ static void uhci_remove_td(struct uhci_h
+ 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 @@ static struct urb_priv *uhci_alloc_urb_p
+
+ memset((void *)urbp, 0, sizeof(*urbp));
+
+- urbp->inserttime = jiffies;
+ urbp->fsbrtime = jiffies;
+ urbp->urb = urb;
+
+@@ -462,8 +471,6 @@ static void uhci_add_td_to_urb(struct ur
+ {
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+- td->urb = urb;
+-
+ list_add_tail(&td->list, &urbp->td_list);
+ }
+
+@@ -473,8 +480,6 @@ static void uhci_remove_td_from_urb(stru
+ 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 @@ static void uhci_destroy_urb_priv(struct
+
+ 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 @@ static int uhci_submit_isochronous(struc
+ 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 @@ static int uhci_submit_isochronous(struc
+ 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 @@ static int uhci_submit_isochronous(struc
+
+ 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 @@ static int uhci_result_isochronous(struc
+ 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 @@ static int uhci_result_isochronous(struc
+
+ i++;
+ }
++ unlink_isochronous_tds(uhci, urb);
+
+ return ret;
+ }
+@@ -1164,7 +1170,7 @@ static struct urb *uhci_find_urb_ep(stru
+
+ 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 @@ static int uhci_urb_dequeue(struct usb_h
+ 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
+--- a/drivers/usb/image/mdc800.c
++++ b/drivers/usb/image/mdc800.c
+@@ -425,9 +425,8 @@ static void mdc800_usb_download_notify (
+ 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 @@ static struct usb_driver mdc800_usb_driv
+ 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 @@ static int __init usb_mdc800_init (void)
+ 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));
+-
+- 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_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;
++
++ 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
+--- a/drivers/usb/image/microtek.c
++++ b/drivers/usb/image/microtek.c
+@@ -773,11 +773,10 @@ static int mts_usb_probe(struct usb_inte
+ }
+
+
+- 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
+--- a/drivers/usb/input/acecad.c
++++ b/drivers/usb/input/acecad.c
+@@ -53,7 +53,7 @@ struct usb_acecad {
+ 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 @@ static void usb_acecad_irq(struct urb *u
+ {
+ 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 @@ static int usb_acecad_probe(struct usb_i
+ 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 @@ static int usb_acecad_probe(struct usb_i
+ 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 @@ static int usb_acecad_probe(struct usb_i
+ 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 @@ static int usb_acecad_probe(struct usb_i
+ 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;
+-
+- 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->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;
++
++ 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 @@ static int usb_acecad_probe(struct usb_i
+ 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 @@ static void usb_acecad_disconnect(struct
+ 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
+--- a/drivers/usb/input/aiptek.c
++++ b/drivers/usb/input/aiptek.c
+@@ -317,7 +317,7 @@ struct aiptek_settings {
+ };
+
+ 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 @@ static void aiptek_irq(struct urb *urb,
+ {
+ 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 @@ static int aiptek_program_tablet(struct
+ /* 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 @@ static ssize_t show_tabletSize(struct de
+ 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 @@ static ssize_t show_tabletProductId(stru
+ 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 @@ static ssize_t show_tabletVendorId(struc
+ 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 @@ aiptek_probe(struct usb_interface *intf,
+ 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 @@ aiptek_probe(struct usb_interface *intf,
+ */
+ 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 @@ aiptek_probe(struct usb_interface *intf,
+
+ /* 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 @@ aiptek_probe(struct usb_interface *intf,
+ 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 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;
++ set_bit(macroKeyEvents[i], inputdev->keybit);
+
+- /* 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_probe(struct usb_interface *intf,
+ 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 @@ aiptek_probe(struct usb_interface *intf,
+ 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 @@ aiptek_probe(struct usb_interface *intf,
+ 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 @@ static void aiptek_disconnect(struct usb
+ /* 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
+--- 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 @@ MODULE_DEVICE_TABLE (usb, atp_table);
+ * 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 @@ MODULE_DEVICE_TABLE (usb, atp_table);
+
+ /* 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 @@ struct atp {
+ 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 @@ static void atp_complete(struct urb* urb
+ 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 @@ static void atp_complete(struct urb* urb
+ "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 @@ static void atp_complete(struct urb* urb
+ 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 void atp_close(struct input_dev *
+
+ 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 @@ static int atp_probe(struct usb_interfac
+ }
+ }
+ 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;
++
++ input_dev->private = dev;
++ input_dev->open = atp_open;
++ input_dev->close = atp_close;
+
+- set_bit(EV_ABS, dev->input.evbit);
++ 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 @@ static void atp_disconnect(struct usb_in
+ 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
+--- 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 char accel[] = { 1, 2, 4, 6, 9, 1
+ 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 @@ struct ati_remote {
+ #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 @@ static struct
+
+ /* 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 @@ static void ati_remote_input_report(stru
+ {
+ 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,38 +583,55 @@ static void ati_remote_irq_in(struct urb
+ }
+
+ /*
+- * 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)
+ {
+- if (ati_remote->irq_urb)
+- usb_kill_urb(ati_remote->irq_urb);
++ ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
++ &ati_remote->inbuf_dma);
++ if (!ati_remote->inbuf)
++ return -1;
+
+- if (ati_remote->out_urb)
+- usb_kill_urb(ati_remote->out_urb);
++ ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
++ &ati_remote->outbuf_dma);
++ if (!ati_remote->outbuf)
++ return -1;
+
+- input_unregister_device(&ati_remote->idev);
++ ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
++ if (!ati_remote->irq_urb)
++ return -1;
+
+- if (ati_remote->inbuf)
+- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+- ati_remote->inbuf, ati_remote->inbuf_dma);
++ ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
++ if (!ati_remote->out_urb)
++ return -1;
+
+- if (ati_remote->outbuf)
+- usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
+- ati_remote->outbuf, ati_remote->outbuf_dma);
++ return 0;
++}
+
++/*
++ * ati_remote_free_buffers
++ */
++static void ati_remote_free_buffers(struct ati_remote *ati_remote)
++{
+ 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);
++ if (ati_remote->inbuf)
++ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
++ ati_remote->inbuf, ati_remote->inbuf_dma);
++
++ if (ati_remote->outbuf)
++ usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
++ 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 @@ static void ati_remote_input_init(struct
+ 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 @@ static int ati_remote_initialize(struct
+ (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_initialize(struct
+ 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];
+-
+- /* 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));
++ 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;
+
+- 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 @@ static void ati_remote_disconnect(struct
+ 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
+--- a/drivers/usb/input/hid-core.c
++++ b/drivers/usb/input/hid-core.c
+@@ -1619,8 +1619,8 @@ static struct hid_device *usb_hid_config
+ 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 @@ static struct hid_device *usb_hid_config
+ 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 @@ static struct hid_device *usb_hid_config
+
+ 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->product) {
++ if (dev->manufacturer)
++ strlcat(hid->name, " ", sizeof(hid->name));
++ strlcat(hid->name, dev->product, 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));
+-
+- 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 @@ static int hid_suspend(struct usb_interf
+ 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 @@ static int hid_resume(struct usb_interfa
+ 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
+--- a/drivers/usb/input/hid-input.c
++++ b/drivers/usb/input/hid-input.c
+@@ -76,8 +76,8 @@ static struct {
+ 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 @@ void hidinput_hid_event(struct hid_devic
+
+ if (!field->hidinput)
+ return;
+- input = &field->hidinput->input;
++
++ input = field->hidinput->input;
+
+ input_regs(input, regs);
+
+@@ -533,13 +534,10 @@ void hidinput_hid_event(struct hid_devic
+
+ 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 @@ int hidinput_connect(struct hid_device *
+ 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 @@ int hidinput_connect(struct hid_device *
+ 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));
+
+- list_add_tail(&hidinput->list, &hid->inputs);
++ 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.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;
++ hidinput->input = input_dev;
++ list_add_tail(&hidinput->list, &hid->inputs);
+ }
+
+ for (i = 0; i < report->maxfield; i++)
+@@ -657,7 +659,7 @@ int hidinput_connect(struct hid_device *
+ * 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 @@ int hidinput_connect(struct hid_device *
+ * 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 @@ int hidinput_connect(struct hid_device *
+
+ 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
+--- a/drivers/usb/input/hid-lgff.c
++++ b/drivers/usb/input/hid-lgff.c
+@@ -255,22 +255,19 @@ static void hid_lgff_input_init(struct h
+ 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;
+- }
+-
+- hidinput->input.upload_effect = hid_lgff_upload_effect;
+- hidinput->input.flush = hid_lgff_flush;
++ input_dev->upload_effect = hid_lgff_upload_effect;
++ input_dev->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
+--- a/drivers/usb/input/hid-tmff.c
++++ b/drivers/usb/input/hid-tmff.c
+@@ -111,6 +111,7 @@ int hid_tmff_init(struct hid_device *hid
+ 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 @@ int hid_tmff_init(struct hid_device *hid
+ 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 @@ int hid_tmff_init(struct hid_device *hid
+ }
+
+ /* 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
+--- a/drivers/usb/input/hid.h
++++ b/drivers/usb/input/hid.h
+@@ -371,7 +371,7 @@ struct hid_control_fifo {
+ 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
+--- a/drivers/usb/input/hiddev.c
++++ b/drivers/usb/input/hiddev.c
+@@ -732,9 +732,8 @@ static struct file_operations hiddev_fop
+ };
+
+ 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
+--- a/drivers/usb/input/itmtouch.c
++++ b/drivers/usb/input/itmtouch.c
+@@ -73,7 +73,7 @@ MODULE_LICENSE( DRIVER_LICENSE );
+
+ 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 struct usb_device_id itmtouch_ids
+
+ 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 void itmtouch_close(struct input_
+ 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;
+-
+- 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->manufacturer)
++ strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name));
++
++ 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 @@ static int itmtouch_probe(struct usb_int
+ 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 @@ static void itmtouch_disconnect(struct u
+ 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
+--- a/drivers/usb/input/kbtab.c
++++ b/drivers/usb/input/kbtab.c
+@@ -34,7 +34,7 @@ MODULE_PARM_DESC(kb_pressure_click, "pre
+ 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 @@ static void kbtab_irq(struct urb *urb, s
+ {
+ 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 @@ static int kbtab_probe(struct usb_interf
+ 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;
+- }
+-
+- 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);
++ if (!kbtab->irq)
++ goto fail2;
+
+- 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;
++ kbtab->usbdev = dev;
++ kbtab->dev = input_dev;
+
+- usb_make_path(dev, path, 64);
+- sprintf(kbtab->phys, "%s/input0", path);
++ usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys));
++ strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys));
+
+- 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;
++ 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 @@ static int kbtab_probe(struct usb_interf
+ 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/map_to_7segment.h b/drivers/usb/input/map_to_7segment.h
+--- a/drivers/usb/input/map_to_7segment.h
++++ b/drivers/usb/input/map_to_7segment.h
+@@ -79,7 +79,7 @@ struct seg7_conversion_map {
+
+ 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
+--- a/drivers/usb/input/mtouchusb.c
++++ b/drivers/usb/input/mtouchusb.c
+@@ -98,7 +98,7 @@ struct mtouch_usb {
+ 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 @@ static void mtouchusb_irq(struct urb *ur
+ 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 void mtouchusb_free_buffers(struc
+ 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 @@ static int mtouchusb_probe(struct usb_in
+ 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 @@ static int mtouchusb_probe(struct usb_in
+ 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 @@ static int mtouchusb_probe(struct usb_in
+ 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 @@ static int mtouchusb_probe(struct usb_in
+ 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 @@ static void mtouchusb_disconnect(struct
+ 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
+--- a/drivers/usb/input/pid.c
++++ b/drivers/usb/input/pid.c
+@@ -198,7 +198,7 @@ static int hid_pid_upload_effect(struct
+ }
+
+ 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 @@ int hid_pid_init(struct hid_device *hid)
+ {
+ 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 @@ int hid_pid_init(struct hid_device *hid)
+ 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
+--- a/drivers/usb/input/powermate.c
++++ b/drivers/usb/input/powermate.c
+@@ -68,7 +68,7 @@ struct powermate_device {
+ 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 @@ static void powermate_irq(struct urb *ur
+ }
+
+ /* 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 @@ static void powermate_sync_state(struct
+
+ 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 @@ static void powermate_sync_state(struct
+ 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 @@ static void powermate_pulse_led(struct p
+ 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 @@ static int powermate_alloc_buffers(struc
+ 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 @@ static int powermate_probe(struct usb_in
+ 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 @@ static int powermate_probe(struct usb_in
+ 0, interface->desc.bInterfaceNumber, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+
+- if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL)))
+- return -ENOMEM;
+-
+- memset(pm, 0, sizeof(struct powermate_device));
+- pm->udev = udev;
++ pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!pm || !input_dev)
++ goto fail1;
+
+- 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 @@ static int powermate_probe(struct usb_in
+
+ /* 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 @@ static int powermate_probe(struct usb_in
+
+ 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 @@ static void powermate_disconnect(struct
+ 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
+--- a/drivers/usb/input/touchkitusb.c
++++ b/drivers/usb/input/touchkitusb.c
+@@ -68,14 +68,16 @@ struct touchkit_usb {
+ 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 @@ static void touchkit_irq(struct urb *urb
+ 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 void touchkit_free_buffers(struct
+ 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 @@ static void touchkit_disconnect(struct u
+
+ 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
+--- a/drivers/usb/input/usbkbd.c
++++ b/drivers/usb/input/usbkbd.c
+@@ -66,7 +66,7 @@ static unsigned char usb_kbd_keycode[256
+ };
+
+ 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 @@ static void usb_kbd_irq(struct urb *urb,
+ 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 void usb_kbd_free_mem(struct usb_
+ 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 @@ static int usb_kbd_probe(struct usb_inte
+ 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;
++
++ 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;
+
+- 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);
++ 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 @@ static int usb_kbd_probe(struct usb_inte
+ 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 @@ static void usb_kbd_disconnect(struct us
+ 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
+--- a/drivers/usb/input/usbmouse.c
++++ b/drivers/usb/input/usbmouse.c
+@@ -50,7 +50,7 @@ struct usb_mouse {
+ 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 @@ static void usb_mouse_irq(struct urb *ur
+ {
+ 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 @@ static void usb_mouse_close(struct input
+ 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 @@ static int usb_mouse_probe(struct usb_in
+ 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 @@ static int usb_mouse_probe(struct usb_in
+ 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 @@ static void usb_mouse_disconnect(struct
+ 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
+--- a/drivers/usb/input/wacom.c
++++ b/drivers/usb/input/wacom.c
+@@ -111,7 +111,7 @@ struct wacom_features {
+ 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 @@ static void wacom_pl_irq(struct urb *urb
+ {
+ 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 @@ static void wacom_ptu_irq(struct urb *ur
+ {
+ 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 @@ static void wacom_penpartner_irq(struct
+ {
+ 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 @@ static void wacom_graphire_irq(struct ur
+ {
+ 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 @@ static int wacom_intuos_inout(struct urb
+ {
+ 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 @@ static void wacom_intuos_general(struct
+ {
+ 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 @@ static void wacom_intuos_irq(struct urb
+ {
+ 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 @@ static int wacom_probe(struct usb_interf
+ {
+ 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 @@ static int wacom_probe(struct usb_interf
+ 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 @@ static void wacom_disconnect(struct usb_
+ 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
+--- a/drivers/usb/input/xpad.c
++++ b/drivers/usb/input/xpad.c
+@@ -103,7 +103,7 @@ static struct usb_device_id xpad_table [
+ 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 @@ struct usb_xpad {
+
+ 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 void xpad_close (struct input_dev
+ 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,89 +225,80 @@ static int xpad_probe(struct usb_interfa
+ 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;
+- }
+-
+- 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,
+- xpad, ep_irq_in->bInterval);
+- xpad->irq_in->transfer_dma = xpad->idata_dma;
+- xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++ 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;
+
+- 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);
++ input_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);
++ 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, xpad->dev.absbit);
++ set_bit(t, input_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;
++ input_set_abs_params(input_dev, t, -32768, 32767, 16, 128);
+ break;
+ case ABS_Z:
+ case ABS_RZ: /* the triggers */
+- xpad->dev.absmax[t] = 255;
+- xpad->dev.absmin[t] = 0;
++ input_set_abs_params(input_dev, t, 0, 255, 0, 0);
+ break;
+ case ABS_HAT0X:
+ case ABS_HAT0Y: /* the d-pad */
+- xpad->dev.absmax[t] = 1;
+- xpad->dev.absmin[t] = -1;
++ input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+ break;
+ }
+ }
+
+- input_register_device(&xpad->dev);
++ 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,
++ xpad, ep_irq_in->bInterval);
++ xpad->irq_in->transfer_dma = xpad->idata_dma;
++ xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+- 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 @@ static void xpad_disconnect(struct usb_i
+ 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
+--- 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 @@ static const struct lcd_segment_map {
+ };
+
+ 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 int map_p1k_to_key(int scancode)
+ */
+ 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 @@ static int usb_cleanup(struct yealink_de
+ }
+ 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 @@ static int usb_probe(struct usb_interfac
+ 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 @@ static int usb_probe(struct usb_interfac
+
+ 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 @@ static int usb_probe(struct usb_interfac
+ 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/konicawc.c b/drivers/usb/media/konicawc.c
+--- a/drivers/usb/media/konicawc.c
++++ b/drivers/usb/media/konicawc.c
+@@ -119,7 +119,7 @@ struct konicawc {
+ 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 @@ static void konicawc_adjust_picture(stru
+ 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 @@ static int konicawc_compress_iso(struct
+ 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 @@ static int konicawc_set_video_mode(struc
+ 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 @@ static void konicawc_configure_video(str
+ 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 @@ static int konicawc_probe(struct usb_int
+ 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 @@ static void konicawc_free_uvd(struct uvd
+ 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
+--- a/drivers/usb/misc/auerswald.c
++++ b/drivers/usb/misc/auerswald.c
+@@ -1873,9 +1873,8 @@ static struct file_operations auerswald_
+ };
+
+ 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
+--- a/drivers/usb/misc/idmouse.c
++++ b/drivers/usb/misc/idmouse.c
+@@ -105,11 +105,10 @@ static struct file_operations idmouse_fo
+ .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 @@ static ssize_t idmouse_read(struct file
+ 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
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -271,12 +271,11 @@ static struct file_operations tower_fops
+
+ /*
+ * 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
+--- a/drivers/usb/misc/rio500.c
++++ b/drivers/usb/misc/rio500.c
+@@ -443,9 +443,8 @@ file_operations usb_rio_fops = {
+ };
+
+ 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
+--- a/drivers/usb/misc/sisusbvga/sisusb.c
++++ b/drivers/usb/misc/sisusbvga/sisusb.c
+@@ -2440,7 +2440,7 @@ int
+ 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 file_operations usb_sisusb
+ };
+
+ 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
+--- a/drivers/usb/misc/usblcd.c
++++ b/drivers/usb/misc/usblcd.c
+@@ -251,13 +251,12 @@ static struct file_operations lcd_fops =
+ };
+
+ /*
+- * * 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
+--- 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 @@ alloc_sglist (int nents, int max, int va
+ 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 @@ alloc_sglist (int nents, int max, int va
+ 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 @@ test_ctrl_queue (struct usbtest_dev *dev
+ 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 @@ usbtest_probe (struct usb_interface *int
+
+ 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
+--- a/drivers/usb/misc/uss720.c
++++ b/drivers/usb/misc/uss720.c
+@@ -137,7 +137,7 @@ static void async_complete(struct urb *u
+
+ 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 unsigned int kill_all_async_reque
+
+ /* --------------------------------------------------------------------- */
+
+-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 @@ static int get_1284_register(struct parp
+ 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
+--- 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 @@ static void mon_bus_remove(struct usb_bu
+ 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 @@ static struct usb_mon_operations mon_ops
+ .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 @@ static int __init mon_init(void)
+ }
+ // 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 @@ static void __exit mon_exit(void)
+ 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
+--- a/drivers/usb/net/Kconfig
++++ b/drivers/usb/net/Kconfig
+@@ -294,7 +294,7 @@ config USB_NET_ZAURUS
+ 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
+--- a/drivers/usb/net/asix.c
++++ b/drivers/usb/net/asix.c
+@@ -753,7 +753,7 @@ static int ax88772_rx_fixup(struct usbne
+ }
+
+ 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
+--- a/drivers/usb/net/gl620a.c
++++ b/drivers/usb/net/gl620a.c
+@@ -301,7 +301,7 @@ static int genelink_rx_fixup(struct usbn
+ }
+
+ 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
+--- a/drivers/usb/net/kaweth.c
++++ b/drivers/usb/net/kaweth.c
+@@ -469,7 +469,7 @@ static int kaweth_reset(struct kaweth_de
+ 0,
+ KAWETH_CONTROL_TIMEOUT);
+
+- udelay(10000);
++ mdelay(10);
+
+ kaweth_dbg("kaweth_reset() returns %d.",result);
+
+@@ -477,13 +477,13 @@ static int kaweth_reset(struct kaweth_de
+ }
+
+ 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 @@ static void kaweth_resubmit_tl(void *d)
+ * 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
+--- a/drivers/usb/net/net1080.c
++++ b/drivers/usb/net/net1080.c
+@@ -500,7 +500,7 @@ static int net1080_rx_fixup(struct usbne
+ }
+
+ 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
+--- a/drivers/usb/net/pegasus.c
++++ b/drivers/usb/net/pegasus.c
+@@ -1384,7 +1384,6 @@ static int pegasus_suspend (struct usb_i
+ 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 @@ static int pegasus_resume (struct usb_in
+ {
+ 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
+--- a/drivers/usb/net/pegasus.h
++++ b/drivers/usb/net/pegasus.h
+@@ -181,6 +181,8 @@ PEGASUS_DEV( "Accton USB 10/100 Ethernet
+ 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
+--- a/drivers/usb/net/rndis_host.c
++++ b/drivers/usb/net/rndis_host.c
+@@ -517,7 +517,7 @@ static int rndis_rx_fixup(struct usbnet
+ }
+
+ 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
+--- a/drivers/usb/net/rtl8150.c
++++ b/drivers/usb/net/rtl8150.c
+@@ -909,6 +909,7 @@ static void rtl8150_disconnect(struct us
+ 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
+--- a/drivers/usb/net/usbnet.c
++++ b/drivers/usb/net/usbnet.c
+@@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
+
+ 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 @@ int usbnet_suspend (struct usb_interface
+ 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 @@ int usbnet_resume (struct usb_interface
+ {
+ 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
+--- a/drivers/usb/net/usbnet.h
++++ b/drivers/usb/net/usbnet.h
+@@ -107,7 +107,7 @@ struct driver_info {
+
+ /* 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
+--- 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
+--- a/drivers/usb/net/zd1201.c
++++ b/drivers/usb/net/zd1201.c
+@@ -521,7 +521,7 @@ static int zd1201_setconfig(struct zd120
+ 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
+--- /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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at netmech.com> for the information.
++
++ (03/21/2002) gkh
++ Added support for the Palm m130 device, thanks to Udo Eisenbarth
++ <udo.eisenbarth at 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 at 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
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -394,6 +394,15 @@ config USB_SERIAL_MCT_U232
+ 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
+--- a/drivers/usb/serial/Makefile
++++ b/drivers/usb/serial/Makefile
+@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) +=
+ 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
+--- a/drivers/usb/serial/airprime.c
++++ b/drivers/usb/serial/airprime.c
+@@ -30,9 +30,11 @@ static struct usb_driver airprime_driver
+ .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
+--- a/drivers/usb/serial/belkin_sa.c
++++ b/drivers/usb/serial/belkin_sa.c
+@@ -121,10 +121,12 @@ static struct usb_driver belkin_driver =
+ };
+
+ /* 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
+--- 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 @@ struct bus_type usb_serial_bus_type = {
+
+ 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 @@ static int usb_serial_device_probe (stru
+
+ 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 @@ static int usb_serial_device_probe (stru
+ 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 @@ exit:
+
+ 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 @@ static int usb_serial_device_remove (str
+
+ 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
+--- a/drivers/usb/serial/cp2101.c
++++ b/drivers/usb/serial/cp2101.c
+@@ -67,15 +67,17 @@ MODULE_DEVICE_TABLE (usb, id_table);
+
+ 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
+--- a/drivers/usb/serial/cyberjack.c
++++ b/drivers/usb/serial/cyberjack.c
+@@ -83,10 +83,12 @@ static struct usb_driver cyberjack_drive
+ .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
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -176,10 +176,12 @@ static unsigned int cypress_buf_put(st
+ 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 @@ static struct usb_serial_device_type cyp
+ .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
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -503,10 +503,12 @@ static struct usb_driver digi_driver = {
+
+ /* 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 @@ static struct usb_serial_device_type dig
+ .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
+--- a/drivers/usb/serial/empeg.c
++++ b/drivers/usb/serial/empeg.c
+@@ -112,9 +112,11 @@ static struct usb_driver empeg_driver =
+ .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
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -411,6 +411,8 @@ static struct usb_device_id id_table_com
+ { 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 @@ static struct usb_device_id id_table_com
+ /* { 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 @@ static struct usb_device_id id_table_com
+ { 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 unsigned short int ftdi_232am_bau
+ 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
+--- 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
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -1468,16 +1468,13 @@ static void garmin_shutdown (struct usb_
+ }
+
+
+-
+-
+-
+-
+-
+ /* 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
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -36,10 +36,11 @@ MODULE_PARM_DESC(product, "User specifie
+ 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
+--- a/drivers/usb/serial/hp4x.c
++++ b/drivers/usb/serial/hp4x.c
+@@ -38,15 +38,17 @@ MODULE_DEVICE_TABLE(usb, id_table);
+
+ 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
+--- 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 at brimson.com>,
+ * or Al Borchers <alborchers at 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
+--- a/drivers/usb/serial/io_tables.h
++++ b/drivers/usb/serial/io_tables.h
+@@ -75,10 +75,12 @@ static struct usb_device_id id_table_com
+
+ 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 @@ static struct usb_serial_device_type edg
+ .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 @@ static struct usb_serial_device_type edg
+ .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
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -2982,10 +2982,12 @@ static unsigned int edge_buf_get(struct
+ }
+
+
+-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 @@ static struct usb_serial_device_type edg
+ .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
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -92,24 +92,7 @@ static void ipaq_destroy_lists(struct us
+ 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 @@ static struct usb_device_id ipaq_id_tabl
+ { 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 @@ static struct usb_device_id ipaq_id_tabl
+ { 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 @@ static struct usb_device_id ipaq_id_tabl
+ { 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(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
+ { 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(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(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(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(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(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */
+ { 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, 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(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(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(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(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(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */
+- { 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(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
+ { } /* Terminating entry */
+ };
+
+@@ -547,9 +551,12 @@ static struct usb_driver ipaq_driver = {
+
+
+ /* 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
+--- a/drivers/usb/serial/ipw.c
++++ b/drivers/usb/serial/ipw.c
+@@ -443,10 +443,12 @@ static int ipw_disconnect(struct usb_ser
+ 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
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -133,9 +133,12 @@ static struct usb_driver ir_driver = {
+ };
+
+
+-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/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -123,10 +123,12 @@ static struct usb_driver kl5kusb105d_dri
+ .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
+--- a/drivers/usb/serial/kobil_sct.c
++++ b/drivers/usb/serial/kobil_sct.c
+@@ -105,9 +105,12 @@ static struct usb_driver kobil_driver =
+ };
+
+
+-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
+--- a/drivers/usb/serial/mct_u232.c
++++ b/drivers/usb/serial/mct_u232.c
+@@ -132,10 +132,12 @@ static struct usb_driver mct_u232_driver
+ .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
+--- /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 at 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 at 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
+--- a/drivers/usb/serial/omninet.c
++++ b/drivers/usb/serial/omninet.c
+@@ -88,10 +88,12 @@ static struct usb_driver omninet_driver
+ };
+
+
+-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
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -105,10 +105,12 @@ static struct usb_driver option_driver =
+ /* 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
+--- 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 at 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 @@ static unsigned int pl2303_buf_get(struc
+
+
+ /* 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 @@ static int __init pl2303_init (void)
+ 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_init(pl2303_init);
+ 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
+--- a/drivers/usb/serial/safe_serial.c
++++ b/drivers/usb/serial/safe_serial.c
+@@ -92,7 +92,7 @@ MODULE_DESCRIPTION (DRIVER_DESC);
+ 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 @@ static int safe_startup (struct usb_seri
+ 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
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -255,9 +255,12 @@ static struct usb_driver ti_usb_driver =
+ .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 @@ static struct usb_serial_device_type ti_
+ .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
+--- 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 at kroah.com)
++ * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg at kroah.com)
+ * Copyright (C) 2000 Peter Berger (pberger at brimson.com)
+ * Copyright (C) 2000 Al Borchers (borchers at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at kroah.com, http://www.kroah.com/linux/"
+ #define DRIVER_DESC "USB Serial Driver core"
+
+@@ -427,7 +121,7 @@ static void destroy_serial(struct kref *
+
+ 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 @@ static int serial_open (struct tty_struc
+ /* 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 @@ static int serial_open (struct tty_struc
+ 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 @@ static void serial_close(struct tty_stru
+ 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 @@ static int serial_read_proc (char *page,
+ 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 void port_release(struct device *
+
+ 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 @@ static struct usb_serial * create_serial
+ }
+ 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 @@ int usb_serial_probe(struct usb_interfac
+ 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 @@ int usb_serial_probe(struct usb_interfac
+ 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 @@ int usb_serial_probe(struct usb_interfac
+
+ 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 @@ int usb_serial_probe(struct usb_interfac
+ #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 @@ int usb_serial_probe(struct usb_interfac
+ 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 @@ int usb_serial_probe(struct usb_interfac
+
+ /* 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 @@ static int __init usb_serial_init(void)
+ goto exit_generic;
+ }
+
+- info(DRIVER_DESC " " DRIVER_VERSION);
++ info(DRIVER_DESC);
+
+ return result;
+
+@@ -1375,7 +1069,7 @@ module_exit(usb_serial_exit);
+ } \
+ } 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 @@ static void fixup_generic(struct usb_ser
+ 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 @@ EXPORT_SYMBOL_GPL(usb_serial_port_softin
+ /* 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
+--- 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 at 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 @@ static inline void usb_set_serial_port_d
+ /**
+ * 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 @@ static inline void usb_set_serial_port_d
+ */
+ 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 @@ static inline void usb_set_serial_data (
+ }
+
+ /**
+- * 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 @@ static inline void usb_set_serial_data (
+ * @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 @@ struct usb_serial_device_type {
+ 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 void usb_serial_generic_shutdown
+ 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
+--- 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 at 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 at 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 at netmech.com> for the information.
+- *
+- * (03/21/2002) gkh
+- * Added support for the Palm m130 device, thanks to Udo Eisenbarth
+- * <udo.eisenbarth at 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 at kroah.com>"
+ #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
+
+@@ -311,10 +181,12 @@ static struct usb_driver visor_driver =
+ };
+
+ /* 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 @@ static struct usb_serial_device_type han
+ };
+
+ /* 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 @@ static struct usb_serial_device_type cli
+ };
+
+ /* 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 @@ static int palm_os_3_probe (struct usb_s
+ 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 @@ static int palm_os_3_probe (struct usb_s
+ */
+ 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 @@ static int __init visor_init (void)
+ 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
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -156,10 +156,12 @@ static void whiteheat_unthrottle (struct
+ 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 @@ static struct usb_serial_device_type whi
+ .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 @@ static int whiteheat_attach (struct usb_
+ 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 @@ static int whiteheat_attach (struct usb_
+ 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 @@ static int whiteheat_attach (struct usb_
+
+ 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 @@ static int whiteheat_attach (struct usb_
+
+ 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 @@ static int whiteheat_attach (struct usb_
+
+ 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 at 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 at connecttech.com\n", serial->type->description);
+ return -ENODEV;
+
+ no_command_private:
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+--- 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
+--- a/drivers/usb/storage/onetouch.c
++++ b/drivers/usb/storage/onetouch.c
+@@ -5,7 +5,7 @@
+ * Copyright (c) 2005 Nick Sillik <n.sillik at temple.edu>
+ *
+ * Initial work by:
+- * Copyright (c) 2003 Erik Thyren <erth7411 at student.uu.se>
++ * Copyright (c) 2003 Erik Thyren <erth7411 at student.uu.se>
+ *
+ * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann)
+ *
+@@ -46,7 +46,7 @@ void onetouch_release_input(void *onetou
+ 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 @@ static void usb_onetouch_irq(struct urb
+ {
+ 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 @@ static void usb_onetouch_irq(struct urb
+ }
+
+ 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 @@ int onetouch_connect_input(struct us_dat
+ 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 @@ int onetouch_connect_input(struct us_dat
+ 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 @@ int onetouch_connect_input(struct us_dat
+ 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 @@ void onetouch_release_input(void *onetou
+
+ 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
+--- 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_flash_transport(struct
+ 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 @@ static int usbat_check_status(struct us_
+ 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 @@ static int usbat_set_shuttle_features(st
+ 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 @@ static int usbat_wait_not_busy(struct us
+
+ 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 @@ static int usbat_hp8200e_rw_block_test(s
+
+ 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 @@ static int usbat_hp8200e_rw_block_test(s
+ } 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 @@ static int usbat_hp8200e_rw_block_test(s
+
+ }
+
+-
+- //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 @@ static int usbat_hp8200e_rw_block_test(s
+
+ 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 @@ static int usbat_multiple_write(struct u
+
+ 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 @@ static int usbat_read_blocks(struct us_d
+ 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 @@ static int usbat_write_blocks(struct us_
+ 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 @@ static int usbat_device_reset(struct us_
+ {
+ 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 @@ static int usbat_device_enable_cdt(struc
+ {
+ 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 @@ static int usbat_flash_check_media(struc
+ 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 @@ static int usbat_flash_check_media(struc
+ 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 @@ static int usbat_identify_device(struct
+ 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 @@ static int usbat_flash_get_sector_count(
+ 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 @@ static int usbat_flash_get_sector_count(
+ 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 @@ static int usbat_flash_get_sector_count(
+
+ 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 @@ static int usbat_flash_read_data(struct
+ 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 @@ static int usbat_flash_read_data(struct
+ 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 @@ static int usbat_flash_write_data(struct
+ 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 @@ static int usbat_flash_write_data(struct
+ 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 @@ static int usbat_hp8200e_handle_read10(s
+ 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 @@ static int usbat_hp8200e_handle_read10(s
+ 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 @@ static int usbat_select_and_test_registe
+ 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 @@ int init_usbat(struct us_data *us)
+ 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 @@ int init_usbat(struct us_data *us)
+
+ 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 @@ int init_usbat(struct us_data *us)
+
+ 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 @@ static int usbat_hp8200e_transport(struc
+ 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 @@ static int usbat_hp8200e_transport(struc
+ 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 @@ static int usbat_hp8200e_transport(struc
+ 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 @@ static int usbat_flash_transport(struct
+ 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 @@ static int usbat_flash_transport(struct
+ }
+
+ 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 @@ static int usbat_flash_transport(struct
+ }
+
+ 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 @@ static int usbat_flash_transport(struct
+ }
+
+ 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
+--- 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 @@ struct usbat_info {
+ 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
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -636,11 +636,11 @@ void usb_stor_invoke_transport(struct sc
+
+ /* 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 @@ void usb_stor_invoke_transport(struct sc
+ 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 usb_stor_Bulk_max_lun(struct us_data
+ 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
+--- 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
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -71,12 +71,12 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x
+ 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 at zulu.ro> */
+@@ -106,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_INQUIRY ),
+
++/* Reported by Stefan Werner <dustbln at 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 at suse.de> from novell bug #105878 */
+ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
+ "SMSC",
+@@ -244,6 +251,13 @@ UNUSUAL_DEV( 0x04da, 0x2372, 0x0000, 0x
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
+
++/* Reported by Simeon Simeonov <simeonov_2000 at 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 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x
+
+ #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 @@ UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
++/*
++ * Reported by Tyson Vinson <lornoss at 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 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x
+ 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 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x
+ #endif
+
+ /* Reported by Eero Volotinen <eero at 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
+--- 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 atomic_t total_threads = ATOMIC_I
+ 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 @@ static struct us_unusual_dev us_unusual_
+ { 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 @@ static int usb_stor_control_thread(void
+ 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 @@ static int associate_dev(struct us_data
+ 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 @@ static int get_transport(struct us_data
+ 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 get_pipes(struct us_data *us)
+ 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 @@ static int usb_stor_acquire_resources(st
+ 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 @@ static void dissociate_dev(struct us_dat
+ {
+ 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 @@ static int usb_stor_scan_thread(void * _
+ {
+ 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 @@ retry:
+
+ /* 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 @@ static int storage_probe(struct usb_inte
+ 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 @@ static int storage_probe(struct usb_inte
+ }
+
+ /* 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 @@ static void storage_disconnect(struct us
+ * 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
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -117,6 +117,7 @@ enum { US_DO_ALL_FLAGS };
+ */
+
+ #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 us_data {
+ 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
+--- a/drivers/usb/usb-skeleton.c
++++ b/drivers/usb/usb-skeleton.c
+@@ -223,9 +223,8 @@ static struct file_operations skel_fops
+ * 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
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -494,7 +494,7 @@ config FB_TGA
+
+ 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_RIVA_DEBUG
+
+ 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_I810_I2C
+
+ 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_HIT
+
+ 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_AA
+
+ 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_PMAG_BA
+
+ 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_PMAGB_B
+
+ 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
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -86,7 +86,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
+ 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/acornfb.c b/drivers/video/acornfb.c
+--- a/drivers/video/acornfb.c
++++ b/drivers/video/acornfb.c
+@@ -26,7 +26,7 @@
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/fb.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <asm/hardware.h>
+diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
+--- 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/arcfb.c b/drivers/video/arcfb.c
+--- a/drivers/video/arcfb.c
++++ b/drivers/video/arcfb.c
+@@ -47,6 +47,7 @@
+ #include <linux/fb.h>
+ #include <linux/init.h>
+ #include <linux/arcfb.h>
++#include <linux/platform_device.h>
+
+ #include <asm/uaccess.h>
+
+diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
+--- 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 at embeddedalley.com>, based on submissions by
++ * Karl Lessard <klessard at sunrisetelecom.com>
++ * <c.pellegrin at exadron.com>
++ *
+ * Copyright 2002 MontaVista Software
+ * Author: MontaVista Software, Inc.
+ * ppopov at mvista.com or source at 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 "au1100fb.h"
++#include <asm/mach-au1x00/au1000.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>
++#define DEBUG 0
++
++#include "au1100fb.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;
+-
+-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;
++#define to_au1100fb_device(_info) \
++ (_info ? container_of(_info, struct au1100fb_device, info) : NULL);
+
+- struct { unsigned red, green, blue, pad; } palette[256];
++/* 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] =
++{
++ /* 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 } },
+
+-#if defined(FBCON_HAS_CFB16)
+- u16 fbcon_cmap16[16];
+-#endif
++ /* The last is used to describe 12bpp format */
++ { { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
+ };
+
+-
+-struct au1100fb_par {
+- struct fb_var_screeninfo var;
+-
+- int line_length; // in bytes
+- int cmap_len; // color-map length
++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 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 struct fb_var_screeninfo au1100fb_var __initdata = {
++ .activate = FB_ACTIVATE_NOW,
++ .height = -1,
++ .width = -1,
++ .vmode = FB_VMODE_NONINTERLACED,
+ };
+
+-static void au1100_detect(void)
+-{
+- /*
+- * This function should detect the current video mode settings
+- * and store it as the default video mode
+- */
++static struct au1100fb_drv_info drv_info;
+
+- /*
+- * Yeh, well, we're not going to change any settings so we're
+- * always stuck with the default ...
++/*
++ * Set hardware with var settings. This will enable the controller with a specific
++ * mode, normally validated with the fb_check_var method
+ */
+-
+-}
+-
+-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;
+-
+- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+-
+- 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;
+- return 0;
+-}
+-
+-static void set_color_bitfields(struct fb_var_screeninfo *var)
+-{
+- 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 fb_info *info = &fbdev->info;
++ u32 words;
++ int index;
+
+- 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 (!fbdev)
+ return -EINVAL;
++
++ /* 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);
++ }
+ }
+- if(var->bits_per_pixel != p_lcd->bpp) {
+- return -EINVAL;
++
++ 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);
+
+- memset(par, 0, sizeof(struct au1100fb_par));
+- par->var = *var;
++ fbdev->regs->lcd_pwmdiv = 0;
++ fbdev->regs->lcd_pwmhi = 0;
+
+- /* 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);
+- return -EINVAL;
++ /* Resume controller */
++ fbdev->regs->lcd_control |= LCD_CONTROL_GO;
+
+- }
+- set_color_bitfields(&par->var);
+- par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
+ return 0;
+ }
+
+-static int au1100_encode_var(struct fb_var_screeninfo *var,
+- const void *par, struct fb_info_gen *_info)
++/* 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)
+ {
++ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
++ u32 *palette = fbdev->regs->lcd_pallettebase;
++ u32 value;
+
+- *var = ((struct au1100fb_par *)par)->var;
+- return 0;
+-}
+-
+-static void
+-au1100_get_par(void *_par, struct fb_info_gen *_info)
+-{
+- *(struct au1100fb_par *)_par = current_par;
+-}
++ if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
++ return -EINVAL;
+
+-static void au1100_set_par(const void *par, struct fb_info_gen *info)
+-{
+- /* nothing to do: we don't change any settings */
+-}
++ if (fbi->var.grayscale) {
++ /* Convert color to grayscale */
++ red = green = blue =
++ (19595 * red + 38470 * green + 7471 * blue) >> 16;
++ }
+
+-static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+- unsigned *blue, unsigned *transp,
+- struct fb_info *info)
+-{
++ if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
++ /* Place color in the pseudopalette */
++ if (regno > 16)
++ return -EINVAL;
+
+- struct au1100fb_info* i = (struct au1100fb_info*)info;
++ palette = (u32*)fbi->pseudo_palette;
+
+- if (regno > 255)
+- return 1;
++ red >>= (16 - fbi->var.red.length);
++ green >>= (16 - fbi->var.green.length);
++ blue >>= (16 - fbi->var.blue.length);
++
++ value = (red << fbi->var.red.offset) |
++ (green << fbi->var.green.offset)|
++ (blue << fbi->var.blue.offset);
++ value &= 0xFFFF;
++
++ } else if (panel_is_active(fbdev->panel)) {
++ /* COLOR TFT PALLETTIZED (use RGB 565) */
++ value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F);
++ value &= 0xFFFF;
++
++ } 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;
++ }
+
+- *red = i->palette[regno].red;
+- *green = i->palette[regno].green;
+- *blue = i->palette[regno].blue;
+- *transp = 0;
++ palette[regno] = value;
+
+ return 0;
+ }
+
+-static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green,
+- unsigned blue, unsigned transp,
+- struct fb_info *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_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;
+- }
+-
+- return 0;
+-}
+-
++ struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+
+-static int au1100_blank(int blank_mode, struct fb_info_gen *_info)
+-{
++ 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 @@ static int au1100_blank(int blank_mode,
+ 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 @@ static int au1100_blank(int blank_mode,
+ 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 @@ au1100fb_mmap(struct fb_info *_fb,
+ 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;
+-}
++ .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,
++};
+
+-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
+-};
++/*-------------------------------------------------------------------------*/
+
++/* AU1100 LCD controller device driver */
+
+-int au1100_setmode(void)
++int au1100fb_drv_probe(struct device *dev)
+ {
+- int words;
++ struct au1100fb_device *fbdev = NULL;
++ struct resource *regs_res;
++ unsigned long page;
++ u32 sys_clksrc;
+
+- /* 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");
++ if (!dev)
+ return -EINVAL;
++
++ /* Allocate new device private */
++ if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
++ print_err("fail to allocate device private record");
++ return -ENOMEM;
+ }
++ memset((void*)fbdev, 0, sizeof(struct au1100fb_device));
+
+- /*
+- * Setup LCD controller
+- */
++ fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
+
+- 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;
++ dev_set_drvdata(dev, (void*)fbdev);
+
+- /* 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
++ /* 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;
++ }
+
+- p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
++ au1100fb_fix.mmio_start = regs_res->start;
++ au1100fb_fix.mmio_len = regs_res->end - regs_res->start + 1;
+
+- return 0;
+-}
++ 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);
+
+-int __init au1100fb_init(void)
+-{
+- uint32 sys_clksrc;
+- unsigned long page;
++ print_dbg("Register memory map at %p", fbdev->regs);
++ print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
+
+- /*
+- * Get the panel information/display mode and update the registry
+- */
+- p_lcd = &panels[my_lcd_index];
+-
+- 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;
++ /* 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;
+
+- 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");
++ 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;
+ }
+- fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start);
++
++ 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);
+-
+- /* FIXME add check to make sure auxpll is what is expected! */
+- au1100_setmode();
+-
+- fb_info.gen.parsize = sizeof(struct au1100fb_par);
+- fb_info.gen.fbhw = &au1100_switch;
+-
+- strcpy(fb_info.gen.info.modename, "Au1100 LCD");
+- fb_info.gen.info.changevar = NULL;
+- fb_info.gen.info.node = -1;
+-
+- 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;
+-
+- /* 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);
++ /* 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);
++
++ /* 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;
++
++ fbdev->info.screen_base = fbdev->fb_mem;
++ fbdev->info.fbops = &au1100fb_ops;
++ fbdev->info.fix = au1100fb_fix;
++
++ if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) {
++ return -ENOMEM;
++ }
++ memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16);
++
++ 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;
++ }
++
++ 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)
+ {
+- char* this_opt;
+- int i;
+- int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels);
++ /* 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,
++};
+
++/*-------------------------------------------------------------------------*/
+
+- if (!options || !*options)
+- return;
++/* Kernel driver */
+
+- 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;
++int au1100fb_setup(char *options)
++{
++ char* this_opt;
++ int num_panels = ARRAY_SIZE(known_lcd_panels);
++ char* mode = NULL;
++ int panel_idx = 0;
++
++ 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;
++}
+
+-#ifdef MODULE
+-MODULE_LICENSE("GPL");
+-int init_module(void)
++int __init au1100fb_init(void)
+ {
+- return au1100fb_init();
++ char* options;
++ int ret;
++
++ print_info("" DRIVER_DESC "");
++
++ 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 cleanup_module(void)
++void __exit au1100fb_cleanup(void)
+ {
+- au1100fb_cleanup(void);
++ driver_unregister(&au1100fb_driver);
++
++ if (drv_info.opt_mode)
++ kfree(drv_info.opt_mode);
+ }
+
+-MODULE_AUTHOR("Pete Popov <ppopov at mvista.com>");
+-MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver");
+-#endif /* MODULE */
++module_init(au1100fb_init);
++module_exit(au1100fb_cleanup);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h
+--- a/drivers/video/au1100fb.h
++++ b/drivers/video/au1100fb.h
+@@ -30,352 +30,352 @@
+ #ifndef _AU1100LCD_H
+ #define _AU1100LCD_H
+
++#include <asm/mach-au1x00/au1000.h>
++
++#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)
++
++#if DEBUG
++#define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg)
++#else
++#define print_dbg(f, arg...) do {} while (0)
++#endif
++
++#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
++
+ /********************************************************************/
+-#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];
+
+-} AU1100_LCD;
++/* 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
+
+ /********************************************************************/
+
+-#define AU1100_LCD_ADDR 0xB5000000
++struct au1100fb_panel
++{
++ const char name[25]; /* Full name <vendor>_<model> */
+
+-/*
+- * Register bit definitions
+- */
++ u32 control_base; /* Mode-independent control values */
++ u32 clkcontrol_base; /* Panel pixclock preferences */
+
+-/* 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)
++ u32 horztiming;
++ u32 verttiming;
+
+-/********************************************************************/
++ u32 xres; /* Maximum horizontal resolution */
++ u32 yres; /* Maximum vertical resolution */
++ u32 bpp; /* Maximum depth supported */
++};
+
+-struct known_lcd_panels
++struct au1100fb_regs
+ {
+- 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;
++ 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;
+ };
+
+-#if defined(__BIG_ENDIAN)
+-#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_11
+-#else
+-#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_00
+-#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.
++#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
+ */
+-struct known_lcd_panels panels[] =
++static struct au1100fb_panel known_lcd_panels[] =
+ {
+- { /* 0: Pb1100 LCDA: Sharp 320x240 TFT panel */
+- 320, /* xres */
+- 240, /* yres */
+- 16, /* bpp */
+-
+- "Sharp_320x240_16",
+- /* mode_control */
++ /* 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
++ /* 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,
+ },
++};
+
+- { /* 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,
++struct au1100fb_drv_info {
++ int panel_idx;
++ char *opt_mode;
++};
+
+- /* mode_pwmdiv */
+- 0,
++/********************************************************************/
+
+- /* mode_pwmhi */
+- 0,
++/* Inline helpers */
+
+- /* mode_toyclksrc */
+- ((1<<7) | (1<<6) | (0<<5)),
++#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)
+
+- /* mode_backlight */
+- 7
+- },
+-};
+ #endif /* _AU1100LCD_H */
+diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
+--- a/drivers/video/backlight/corgi_bl.c
++++ b/drivers/video/backlight/corgi_bl.c
+@@ -14,7 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/spinlock.h>
+ #include <linux/fb.h>
+ #include <linux/backlight.h>
+@@ -73,17 +73,15 @@ static void corgibl_blank(int blank)
+ }
+
+ #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
+--- a/drivers/video/cirrusfb.c
++++ b/drivers/video/cirrusfb.c
+@@ -275,20 +275,20 @@ static const struct cirrusfb_board_info_
+
+ #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
+--- a/drivers/video/console/Kconfig
++++ b/drivers/video/console/Kconfig
+@@ -28,7 +28,7 @@ config VGA_CONSOLE
+
+ 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 STI_CONSOLE
+
+ 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 FONTS
+
+ 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_8x8
+
+ 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_8x16
+
+ 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
+--- 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
+--- a/drivers/video/console/sticore.c
++++ b/drivers/video/console/sticore.c
+@@ -511,12 +511,12 @@ sti_select_fbfont( struct sti_cooked_rom
+ 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 @@ sti_select_fbfont( struct sti_cooked_rom
+
+ nf = kmalloc(size, GFP_KERNEL);
+ if (!nf)
+- return NULL;
++ return NULL;
+ memset(nf, 0, size);
+
+ nf->first_char = 0;
+@@ -546,8 +546,8 @@ sti_select_fbfont( struct sti_cooked_rom
+
+ 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 @@ sti_select_font(struct sti_cooked_rom *r
+ 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 @@ sti_search_font(struct sti_cooked_rom *r
+ 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 @@ sti_get_bmode_rom (unsigned long address
+ {
+ 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;
+-
+- 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);
++ 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->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 @@ sti_get_wmode_rom (unsigned long address
+ {
+ 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 @@ sti_read_rom(int wordmode, struct sti_st
+ if (!cooked)
+ goto out_err;
+
+- if (wordmode)
+- raw = sti_get_wmode_rom (address);
+- else
+- raw = sti_get_bmode_rom (address);
+-
+- if (!raw)
+- goto out_err;
+-
++ if (wordmode)
++ raw = sti_get_wmode_rom (address);
++ else
++ raw = sti_get_bmode_rom (address);
++
++ 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_read_rom(int wordmode, struct sti_st
+ 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 @@ sti_try_rom_generic(unsigned long addres
+ 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 void __init sticore_check_for_def
+ */
+ 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
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -579,6 +579,7 @@ static void vga_set_palette(struct vc_da
+ {
+ 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 @@ static void vga_pal_blank(struct vgastat
+ {
+ 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/dnfb.c b/drivers/video/dnfb.c
+--- a/drivers/video/dnfb.c
++++ b/drivers/video/dnfb.c
+@@ -6,6 +6,8 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
++#include <linux/platform_device.h>
++
+ #include <asm/setup.h>
+ #include <asm/system.h>
+ #include <asm/irq.h>
+diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
+--- a/drivers/video/epson1355fb.c
++++ b/drivers/video/epson1355fb.c
+@@ -54,6 +54,8 @@
+ #include <linux/fb.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
++#include <linux/platform_device.h>
++
+ #include <asm/types.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
+--- a/drivers/video/fbmem.c
++++ b/drivers/video/fbmem.c
+@@ -918,7 +918,7 @@ fb_mmap(struct file *file, struct vm_are
+ }
+ #endif
+ #elif defined(__powerpc__)
+- vma->vm_page_prot = phys_mem_access_prot(file, off,
++ vma->vm_page_prot = phys_mem_access_prot(file, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ #elif defined(__alpha__)
+@@ -1031,7 +1031,7 @@ register_framebuffer(struct fb_info *fb_
+ 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
+--- a/drivers/video/gbefb.c
++++ b/drivers/video/gbefb.c
+@@ -11,7 +11,7 @@
+
+ #include <linux/config.h>
+ #include <linux/delay.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/errno.h>
+ #include <linux/fb.h>
+@@ -1126,7 +1126,7 @@ static int __init gbefb_probe(struct dev
+ 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 @@ static int __init gbefb_probe(struct dev
+ 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 @@ static int __init gbefb_probe(struct dev
+ 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
+--- a/drivers/video/imxfb.c
++++ b/drivers/video/imxfb.c
+@@ -31,7 +31,7 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/cpufreq.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <asm/hardware.h>
+@@ -424,23 +424,21 @@ static void imxfb_setup_gpio(struct imxf
+ * 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
+--- a/drivers/video/pxafb.c
++++ b/drivers/video/pxafb.c
+@@ -36,7 +36,7 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/cpufreq.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <asm/hardware.h>
+@@ -981,21 +981,19 @@ pxafb_freq_policy(struct notifier_block
+ * 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/q40fb.c b/drivers/video/q40fb.c
+--- a/drivers/video/q40fb.c
++++ b/drivers/video/q40fb.c
+@@ -18,6 +18,7 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
++#include <linux/platform_device.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/setup.h>
+diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
+--- a/drivers/video/s1d13xxxfb.c
++++ b/drivers/video/s1d13xxxfb.c
+@@ -30,7 +30,7 @@
+
+ #include <linux/config.h>
+ #include <linux/module.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/delay.h>
+
+ #include <linux/types.h>
+@@ -655,7 +655,7 @@ bail:
+ }
+
+ #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 @@ static int s1d13xxxfb_suspend(struct dev
+ 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
+--- a/drivers/video/s3c2410fb.c
++++ b/drivers/video/s3c2410fb.c
+@@ -86,6 +86,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/workqueue.h>
+ #include <linux/wait.h>
++#include <linux/platform_device.h>
+
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+@@ -847,37 +848,32 @@ static int s3c2410fb_remove(struct devic
+
+ /* 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);
+-
+- s3c2410fb_init_registers(info);
++ clk_enable(info->clk);
++ msleep(1);
+
+- }
++ s3c2410fb_init_registers(info);
+
+ return 0;
+ }
+diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
+--- a/drivers/video/sa1100fb.c
++++ b/drivers/video/sa1100fb.c
+@@ -173,7 +173,7 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/cpufreq.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+
+ #include <asm/hardware.h>
+@@ -1309,21 +1309,19 @@ sa1100fb_freq_policy(struct notifier_blo
+ * 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/sgivwfb.c b/drivers/video/sgivwfb.c
+--- a/drivers/video/sgivwfb.c
++++ b/drivers/video/sgivwfb.c
+@@ -18,6 +18,8 @@
+ #include <linux/fb.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
++#include <linux/platform_device.h>
++
+ #include <asm/io.h>
+ #include <asm/mtrr.h>
+
+diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
+--- a/drivers/video/vesafb.c
++++ b/drivers/video/vesafb.c
+@@ -19,6 +19,8 @@
+ #include <linux/fb.h>
+ #include <linux/ioport.h>
+ #include <linux/init.h>
++#include <linux/platform_device.h>
++
+ #include <video/vga.h>
+ #include <asm/io.h>
+ #include <asm/mtrr.h>
+diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
+--- a/drivers/video/vfb.c
++++ b/drivers/video/vfb.c
+@@ -20,6 +20,8 @@
+ #include <linux/vmalloc.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
++#include <linux/platform_device.h>
++
+ #include <asm/uaccess.h>
+ #include <linux/fb.h>
+ #include <linux/init.h>
+diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
+--- a/drivers/video/w100fb.c
++++ b/drivers/video/w100fb.c
+@@ -25,7 +25,7 @@
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/string.h>
+ #include <linux/vmalloc.h>
+ #include <asm/io.h>
+@@ -438,36 +438,34 @@ static void w100fb_restore_vidmem(struct
+ }
+ }
+
+-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;
+-
+- w100fb_save_vidmem(par);
+- if(tg && tg->suspend)
+- tg->suspend(par);
+- w100_suspend(W100_SUSPEND_ALL);
+- par->blanked = 1;
+- }
++ 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;
++
+ 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
+--- 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
+--- 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
+--- 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
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -810,7 +810,7 @@ config TMPFS
+
+ 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
+--- a/fs/Kconfig.binfmt
++++ b/fs/Kconfig.binfmt
+@@ -57,7 +57,7 @@ config BINFMT_SHARED_FLAT
+
+ 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
+--- a/fs/afs/file.c
++++ b/fs/afs/file.c
+@@ -29,7 +29,7 @@ static int afs_file_release(struct inode
+
+ 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 @@ static int afs_file_invalidatepage(struc
+ /*
+ * 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 @@ static int afs_file_releasepage(struct p
+ 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
+--- a/fs/attr.c
++++ b/fs/attr.c
+@@ -117,9 +117,6 @@ int notify_change(struct dentry * dentry
+ 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
+--- a/fs/binfmt_aout.c
++++ b/fs/binfmt_aout.c
+@@ -318,7 +318,6 @@ static int load_aout_binary(struct linux
+ 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
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -773,7 +773,6 @@ static int load_elf_binary(struct linux_
+
+ /* 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 @@ static int elf_core_dump(long signr, str
+ 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
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -294,14 +294,7 @@ static int load_elf_fdpic_binary(struct
+ &interp_params,
+ ¤t->mm->start_stack,
+ ¤t->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
+--- a/fs/binfmt_flat.c
++++ b/fs/binfmt_flat.c
+@@ -650,7 +650,6 @@ static int load_flat_file(struct linux_b
+ 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
+--- a/fs/binfmt_som.c
++++ b/fs/binfmt_som.c
+@@ -259,7 +259,6 @@ load_som_binary(struct linux_binprm * bp
+ 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
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -778,7 +778,7 @@ static int bio_map_kern_endio(struct bio
+
+
+ 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 @@ static struct bio *__bio_map_kern(reques
+ * 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
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -96,7 +96,7 @@ static void
+ __clear_page_buffers(struct page *page)
+ {
+ ClearPagePrivate(page);
+- page->private = 0;
++ set_page_private(page, 0);
+ page_cache_release(page);
+ }
+
+@@ -502,7 +502,7 @@ static void free_more_memory(void)
+ 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 @@ EXPORT_SYMBOL(__getblk);
+ 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 @@ __bread(struct block_device *bdev, secto
+ {
+ 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 @@ static inline void discard_buffer(struct
+ *
+ * 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 @@ out:
+ }
+ 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 @@ int block_write_full_page(struct page *p
+ * 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/cifs/AUTHORS b/fs/cifs/AUTHORS
+--- a/fs/cifs/AUTHORS
++++ b/fs/cifs/AUTHORS
+@@ -32,6 +32,10 @@ Domen Puncer
+ Jesper Juhl (in particular for lots of whitespace/formatting cleanup)
+ Vince Negri and Dave Stahl (for finding an important caching bug)
+ Adrian Bunk (kcalloc cleanups)
++Miklos Szeredi
++Kazeon team for various fixes especially for 2.4 version.
++Asser Ferno (Change Notify support)
++Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup
+
+ Test case and Bug Report contributors
+ -------------------------------------
+diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
+--- a/fs/cifs/CHANGES
++++ b/fs/cifs/CHANGES
+@@ -1,8 +1,52 @@
++Version 1.39
++------------
++Defer close of a file handle slightly if pending writes depend on that file handle
++(this reduces the EBADF bad file handle errors that can be logged under heavy
++stress on writes).
++
++Version 1.38
++------------
++Fix tcp socket retransmission timeouts (e.g. on ENOSPACE from the socket)
++to be smaller at first (but increasing) so large write performance performance
++over GigE is better. Do not hang thread on illegal byte range lock response
++from Windows (Windows can send an RFC1001 size which does not match smb size) by
++allowing an SMBs TCP length to be up to a few bytes longer than it should be.
++wsize and rsize can now be larger than negotiated buffer size if server
++supports large readx/writex, even when directio mount flag not specified.
++Write size will in many cases now be 16K instead of 4K which greatly helps
++file copy performance on lightly loaded networks. Fix oops in dnotify
++when experimental config flag enabled. Make cifsFYI more granular.
++
++Version 1.37
++------------
++Fix readdir caching when unlink removes file in current search buffer,
++and this is followed by a rewind search to just before the deleted entry.
++Do not attempt to set ctime unless atime and/or mtime change requested
++(most servers throw it away anyway). Fix length check of received smbs
++to be more accurate. Fix big endian problem with mapchars mount option,
++and with a field returned by statfs.
++
++Version 1.36
++------------
++Add support for mounting to older pre-CIFS servers such as Windows9x and ME.
++For these older servers, add option for passing netbios name of server in
++on mount (servernetbiosname). Add suspend support for power management, to
++avoid cifsd thread preventing software suspend from working.
++Add mount option for disabling the default behavior of sending byte range lock
++requests to the server (necessary for certain applications which break with
++mandatory lock behavior such as Evolution), and also mount option for
++requesting case insensitive matching for path based requests (requesting
++case sensitive is the default).
++
+ Version 1.35
+ ------------
+ Add writepage performance improvements. Fix path name conversions
+ for long filenames on mounts which were done with "mapchars" mount option
+-specified.
++specified. Ensure multiplex ids do not collide. Fix case in which
++rmmod can oops if done soon after last unmount. Fix truncated
++search (readdir) output when resume filename was a long filename.
++Fix filename conversion when mapchars mount option was specified and
++filename was a long filename.
+
+ Version 1.34
+ ------------
+@@ -11,7 +55,7 @@ Do not oops if root user kills cifs oplo
+ kills the cifsd thread (NB: killing the cifs kernel threads is not
+ recommended, unmount and rmmod cifs will kill them when they are
+ no longer needed). Fix readdir to ASCII servers (ie older servers
+-which do not support Unicode) and also require asterik.
++which do not support Unicode) and also require asterisk.
+ Fix out of memory case in which data could be written one page
+ off in the page cache.
+
+@@ -101,7 +145,7 @@ improperly zeroed buffer in CIFS Unix ex
+
+ Version 1.25
+ ------------
+-Fix internationlization problem in cifs readdir with filenames that map to
++Fix internationalization problem in cifs readdir with filenames that map to
+ longer UTF8 strings than the string on the wire was in Unicode. Add workaround
+ for readdir to netapp servers. Fix search rewind (seek into readdir to return
+ non-consecutive entries). Do not do readdir when server negotiates
+@@ -276,7 +320,7 @@ Fix caching problem when files opened by
+ page cache could contain stale data, and write through did
+ not occur often enough while file was still open when read ahead
+ (read oplock) not allowed. Treat "sep=" when first mount option
+-as an overrride of comma as the default separator between mount
++as an override of comma as the default separator between mount
+ options.
+
+ Version 1.01
+@@ -286,7 +330,7 @@ Allow passwords longer than 16 bytes. Al
+ Version 1.00
+ ------------
+ Gracefully clean up failed mounts when attempting to mount to servers such as
+-Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
++Windows 98 that terminate tcp sessions during protocol negotiation. Handle
+ embedded commas in mount parsing of passwords.
+
+ Version 0.99
+@@ -295,7 +339,7 @@ Invalidate local inode cached pages on o
+ instance is closed so that the client does not continue using stale local
+ copy rather than later modified server copy of file. Do not reconnect
+ when server drops the tcp session prematurely before negotiate
+-protocol response. Fix oops in roepen_file when dentry freed. Allow
++protocol response. Fix oops in reopen_file when dentry freed. Allow
+ the support for CIFS Unix Extensions to be disabled via proc interface.
+
+ Version 0.98
+@@ -637,7 +681,7 @@ versions of 2.4 kernel (now builds and w
+ Version 0.41
+ ------------
+ Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
+-files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
++files now return the correct number of links on fstat as they are repeatedly linked and unlinked.
+
+ Version 0.40
+ ------------
+@@ -704,7 +748,7 @@ session)
+ and cleaned them up and made them more consistent with other cifs functions.
+
+ 7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
+-(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
++(with or without Unix extensions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
+ nor is the symlink support using the Unix extensions
+
+ 8) Started adding the readlink and follow_link code
+diff --git a/fs/cifs/README b/fs/cifs/README
+--- a/fs/cifs/README
++++ b/fs/cifs/README
+@@ -294,8 +294,10 @@ A partial list of the supported mount op
+ during the local client kernel build will be used.
+ If server does not support Unicode, this parameter is
+ unused.
+- rsize default read size
+- wsize default write size
++ rsize default read size (usually 16K)
++ wsize default write size (usually 16K, 32K is often better over GigE)
++ maximum wsize currently allowed by CIFS is 57344 (14 4096 byte
++ pages)
+ rw mount the network share read-write (note that the
+ server may still consider the share read-only)
+ ro mount network share read-only
+@@ -407,6 +409,13 @@ A partial list of the supported mount op
+ This has no effect if the server does not support
+ Unicode on the wire.
+ nomapchars Do not translate any of these seven characters (default).
++ nocase Request case insensitive path name matching (case
++ sensitive is the default if the server suports it).
++ nobrl Do not send byte range lock requests to the server.
++ This is necessary for certain applications that break
++ with cifs style mandatory byte range locks (and most
++ cifs servers do not yet support requesting advisory
++ byte range locks).
+ remount remount the share (often used to change from ro to rw mounts
+ or vice versa)
+
+@@ -473,9 +482,16 @@ These experimental features and tracing
+ kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
+ tracing to the kernel message log type:
+
+- echo 1 > /proc/fs/cifs/cifsFYI
++ echo 7 > /proc/fs/cifs/cifsFYI
+
+-and for more extensive tracing including the start of smb requests and responses
++cifsFYI functions as a bit mask. Setting it to 1 enables additional kernel
++logging of various informational messages. 2 enables logging of non-zero
++SMB return codes while 4 enables logging of requests that take longer
++than one second to complete (except for byte range lock requests).
++Setting it to 4 requires defining CONFIG_CIFS_STATS2 manually in the
++source code (typically by setting it in the beginning of cifsglob.h),
++and setting it to seven enables all three. Finally, tracing
++the start of smb requests and responses can be enabled via:
+
+ echo 1 > /proc/fs/cifs/traceSMB
+
+diff --git a/fs/cifs/TODO b/fs/cifs/TODO
+--- a/fs/cifs/TODO
++++ b/fs/cifs/TODO
+@@ -1,4 +1,4 @@
+-version 1.34 April 29, 2005
++version 1.37 October 9, 2005
+
+ A Partial List of Missing Features
+ ==================================
+@@ -7,14 +7,14 @@ Contributions are welcome. There are pl
+ for visible, important contributions to this module. Here
+ is a partial list of the known problems and missing features:
+
+-a) Support for SecurityDescriptors for chmod/chgrp/chown so
+-these can be supported for Windows servers
++a) Support for SecurityDescriptors(Windows/CIFS ACLs) for chmod/chgrp/chown
++so that these operations can be supported to Windows servers
+
+-b) Better pam/winbind integration (e.g. to handle uid mapping
+-better)
++b) Mapping POSIX ACLs (and eventually NFSv4 ACLs) to CIFS
++SecurityDescriptors
+
+-c) multi-user mounts - multiplexed sessionsetups over single vc
+-(ie tcp session) - more testing needed
++c) Better pam/winbind integration (e.g. to handle uid mapping
++better)
+
+ d) Kerberos/SPNEGO session setup support - (started)
+
+@@ -29,12 +29,17 @@ f) Directory entry caching relies on a 1
+ using FindNotify or equivalent. - (started)
+
+ g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
+-style byte range lock differences
++style byte range lock differences. Save byte range locks so
++reconnect can replay them.
+
+-h) quota support
++h) Support unlock all (unlock 0,MAX_OFFSET)
++by unlocking all known byte range locks that we locked on the file.
+
+-j) finish writepages support (multi-page write behind for improved
+-performance) and syncpage
++i) quota support (needs minor kernel change since quota calls
++to make it to network filesystems or deviceless filesystems)
++
++j) investigate sync behavior (including syncpage) and check
++for proper behavior of intr/nointr
+
+ k) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
+ extra copy in/out of the socket buffers in some cases.
+@@ -57,20 +62,18 @@ p) Add support for storing symlink and f
+ in the Extended Attribute format their SFU clients would recognize.
+
+ q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
+-will autorefresh (started)
++will autorefresh (partially complete by Asser). Needs minor kernel
++vfs change to support removing D_NOTIFY on a file.
+
+ r) Add GUI tool to configure /proc/fs/cifs settings and for display of
+ the CIFS statistics (started)
+
+-q) implement support for security and trusted categories of xattrs
++s) implement support for security and trusted categories of xattrs
+ (requires minor protocol extension) to enable better support for SELINUX
+
+-r) Implement O_DIRECT flag on open (already supported on mount)
+-
+-s) Allow remapping of last remaining character (\) to +0xF000 which
+-(this character is valid for POSIX but not for Windows)
++t) Implement O_DIRECT flag on open (already supported on mount)
+
+-t) Create UID mapping facility so server UIDs can be mapped on a per
++u) Create UID mapping facility so server UIDs can be mapped on a per
+ mount or a per server basis to client UIDs or nobody if no mapping
+ exists. This is helpful when Unix extensions are negotiated to
+ allow better permission checking when UIDs differ on the server
+@@ -78,6 +81,17 @@ and client. Add new protocol request to
+ standard for asking the server for the corresponding name of a
+ particular uid.
+
++v) Add support for CIFS Unix and also the newer POSIX extensions to the
++server side for Samba 4.
++
++w) Finish up the dos time conversion routines needed to return old server
++time to the client (default time, of now or time 0 is used now for these
++very old servers)
++
++x) Add support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers)
++
++y) Finish testing of Windows 9x/Windows ME server support (started).
++
+ KNOWN BUGS (updated April 29, 2005)
+ ====================================
+ See http://bugzilla.samba.org - search on product "CifsVFS" for
+diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
+--- a/fs/cifs/asn1.c
++++ b/fs/cifs/asn1.c
+@@ -191,7 +191,8 @@ asn1_header_decode(struct asn1_ctx *ctx,
+ unsigned char **eoc,
+ unsigned int *cls, unsigned int *con, unsigned int *tag)
+ {
+- unsigned int def, len;
++ unsigned int def = 0;
++ unsigned int len = 0;
+
+ if (!asn1_id_decode(ctx, cls, con, tag))
+ return 0;
+diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
+--- a/fs/cifs/cifs_debug.c
++++ b/fs/cifs/cifs_debug.c
+@@ -81,6 +81,8 @@ cifs_debug_data_read(char *buf, char **b
+ buf += length;
+ length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
+ buf += length;
++ length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid);
++ buf += length;
+ length = sprintf(buf, "Servers:");
+ buf += length;
+
+@@ -97,7 +99,7 @@ cifs_debug_data_read(char *buf, char **b
+ } else {
+ length =
+ sprintf(buf,
+- "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
++ "\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t",
+ i, ses->serverName, ses->serverDomain,
+ atomic_read(&ses->inUse),
+ ses->serverOS, ses->serverNOS,
+@@ -105,12 +107,18 @@ cifs_debug_data_read(char *buf, char **b
+ buf += length;
+ }
+ if(ses->server) {
+- buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
++ buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
+ ses->server->tcpStatus,
+ atomic_read(&ses->server->socketUseCount),
+ ses->server->secMode,
+ atomic_read(&ses->server->inFlight));
+-
++
++#ifdef CONFIG_CIFS_STATS2
++ buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
++ atomic_read(&ses->server->inSend),
++ atomic_read(&ses->server->num_waiters));
++#endif
++
+ length = sprintf(buf, "\nMIDs:\n");
+ buf += length;
+
+@@ -149,7 +157,7 @@ cifs_debug_data_read(char *buf, char **b
+ dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
+ length =
+ sprintf(buf,
+- "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
++ "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
+ i, tcon->treeName,
+ atomic_read(&tcon->useCount),
+ tcon->nativeFileSystem,
+@@ -195,6 +203,49 @@ cifs_debug_data_read(char *buf, char **b
+ }
+
+ #ifdef CONFIG_CIFS_STATS
++
++static int
++cifs_stats_write(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char c;
++ int rc;
++ struct list_head *tmp;
++ struct cifsTconInfo *tcon;
++
++ rc = get_user(c, buffer);
++ if (rc)
++ return rc;
++
++ if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
++ read_lock(&GlobalSMBSeslock);
++ list_for_each(tmp, &GlobalTreeConnectionList) {
++ tcon = list_entry(tmp, struct cifsTconInfo,
++ cifsConnectionList);
++ atomic_set(&tcon->num_smbs_sent, 0);
++ atomic_set(&tcon->num_writes, 0);
++ atomic_set(&tcon->num_reads, 0);
++ atomic_set(&tcon->num_oplock_brks, 0);
++ atomic_set(&tcon->num_opens, 0);
++ atomic_set(&tcon->num_closes, 0);
++ atomic_set(&tcon->num_deletes, 0);
++ atomic_set(&tcon->num_mkdirs, 0);
++ atomic_set(&tcon->num_rmdirs, 0);
++ atomic_set(&tcon->num_renames, 0);
++ atomic_set(&tcon->num_t2renames, 0);
++ atomic_set(&tcon->num_ffirst, 0);
++ atomic_set(&tcon->num_fnext, 0);
++ atomic_set(&tcon->num_fclose, 0);
++ atomic_set(&tcon->num_hardlinks, 0);
++ atomic_set(&tcon->num_symlinks, 0);
++ atomic_set(&tcon->num_locks, 0);
++ }
++ read_unlock(&GlobalSMBSeslock);
++ }
++
++ return count;
++}
++
+ static int
+ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
+ int count, int *eof, void *data)
+@@ -254,35 +305,51 @@ cifs_stats_read(char *buf, char **beginB
+ buf += sprintf(buf, "\tDISCONNECTED ");
+ length += 14;
+ }
+- item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
++ item_length = sprintf(buf, "\nSMBs: %d Oplock Breaks: %d",
+ atomic_read(&tcon->num_smbs_sent),
+ atomic_read(&tcon->num_oplock_brks));
+ buf += item_length;
+ length += item_length;
+- item_length = sprintf(buf,"\nReads: %d Bytes %lld",
++ item_length = sprintf(buf, "\nReads: %d Bytes: %lld",
+ atomic_read(&tcon->num_reads),
+ (long long)(tcon->bytes_read));
+ buf += item_length;
+ length += item_length;
+- item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
++ item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
+ atomic_read(&tcon->num_writes),
+ (long long)(tcon->bytes_written));
++ buf += item_length;
++ length += item_length;
++ item_length = sprintf(buf,
++ "\nLocks: %d HardLinks: %d Symlinks: %d",
++ atomic_read(&tcon->num_locks),
++ atomic_read(&tcon->num_hardlinks),
++ atomic_read(&tcon->num_symlinks));
++ buf += item_length;
++ length += item_length;
++
++ item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
++ atomic_read(&tcon->num_opens),
++ atomic_read(&tcon->num_closes),
++ atomic_read(&tcon->num_deletes));
+ buf += item_length;
+ length += item_length;
+- item_length = sprintf(buf,
+- "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
+- atomic_read(&tcon->num_opens),
+- atomic_read(&tcon->num_deletes),
++ item_length = sprintf(buf, "\nMkdirs: %d Rmdirs: %d",
+ atomic_read(&tcon->num_mkdirs),
+ atomic_read(&tcon->num_rmdirs));
+ buf += item_length;
+ length += item_length;
+- item_length = sprintf(buf,
+- "\nRenames: %d T2 Renames %d",
++ item_length = sprintf(buf, "\nRenames: %d T2 Renames %d",
+ atomic_read(&tcon->num_renames),
+ atomic_read(&tcon->num_t2renames));
+ buf += item_length;
+ length += item_length;
++ item_length = sprintf(buf, "\nFindFirst: %d FNext %d FClose %d",
++ atomic_read(&tcon->num_ffirst),
++ atomic_read(&tcon->num_fnext),
++ atomic_read(&tcon->num_fclose));
++ buf += item_length;
++ length += item_length;
+ }
+ read_unlock(&GlobalSMBSeslock);
+
+@@ -341,8 +408,10 @@ cifs_proc_init(void)
+ cifs_debug_data_read, NULL);
+
+ #ifdef CONFIG_CIFS_STATS
+- create_proc_read_entry("Stats", 0, proc_fs_cifs,
++ pde = create_proc_read_entry("Stats", 0, proc_fs_cifs,
+ cifs_stats_read, NULL);
++ if (pde)
++ pde->write_proc = cifs_stats_write;
+ #endif
+ pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
+ cifsFYI_read, NULL);
+@@ -360,7 +429,7 @@ cifs_proc_init(void)
+ if (pde)
+ pde->write_proc = oplockEnabled_write;
+
+- pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs,
++ pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
+ quotaEnabled_read, NULL);
+ if (pde)
+ pde->write_proc = quotaEnabled_write;
+@@ -419,7 +488,7 @@ cifs_proc_clean(void)
+ remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
+ remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
+ remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
+- remove_proc_entry("ReenableOldCifsReaddirCode",proc_fs_cifs);
++ remove_proc_entry("Experimental",proc_fs_cifs);
+ remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
+ remove_proc_entry("cifs", proc_root_fs);
+ }
+@@ -459,6 +528,8 @@ cifsFYI_write(struct file *file, const c
+ cifsFYI = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ cifsFYI = 1;
++ else if((c > '1') && (c <= '9'))
++ cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
+
+ return count;
+ }
+diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
+--- a/fs/cifs/cifs_debug.h
++++ b/fs/cifs/cifs_debug.h
+@@ -26,6 +26,9 @@
+ void cifs_dump_mem(char *label, void *data, int length);
+ extern int traceSMB; /* flag which enables the function below */
+ void dump_smb(struct smb_hdr *, int);
++#define CIFS_INFO 0x01
++#define CIFS_RC 0x02
++#define CIFS_TIMER 0x04
+
+ /*
+ * debug ON
+@@ -36,7 +39,7 @@ void dump_smb(struct smb_hdr *, int);
+
+ /* information message: e.g., configuration, major event */
+ extern int cifsFYI;
+-#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
++#define cifsfyi(format,arg...) if (cifsFYI & CIFS_INFO) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
+
+ #define cFYI(button,prspec) if (button) cifsfyi prspec
+
+diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
+--- a/fs/cifs/cifs_fs_sb.h
++++ b/fs/cifs/cifs_fs_sb.h
+@@ -24,6 +24,9 @@
+ #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
+ #define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
+ #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
++#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
++#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
++#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
+
+ struct cifs_sb_info {
+ struct cifsTconInfo *tcon; /* primary mount */
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -59,6 +59,8 @@ unsigned int ntlmv2_support = 0;
+ unsigned int sign_CIFS_PDUs = 1;
+ extern struct task_struct * oplockThread; /* remove sparse warning */
+ struct task_struct * oplockThread = NULL;
++extern struct task_struct * dnotifyThread; /* remove sparse warning */
++struct task_struct * dnotifyThread = NULL;
+ unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
+ module_param(CIFSMaxBufSize, int, 0);
+ MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
+@@ -73,6 +75,7 @@ module_param(cifs_max_pending, int, 0);
+ MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
+
+ static DECLARE_COMPLETION(cifs_oplock_exited);
++static DECLARE_COMPLETION(cifs_dnotify_exited);
+
+ extern mempool_t *cifs_sm_req_poolp;
+ extern mempool_t *cifs_req_poolp;
+@@ -202,6 +205,10 @@ cifs_statfs(struct super_block *sb, stru
+ #endif /* CIFS_EXPERIMENTAL */
+ rc = CIFSSMBQFSInfo(xid, pTcon, buf);
+
++ /* Old Windows servers do not support level 103, retry with level
++ one if old server failed the previous call */
++ if(rc)
++ rc = SMBOldQFSInfo(xid, pTcon, buf);
+ /*
+ int f_type;
+ __fsid_t f_fsid;
+@@ -253,7 +260,7 @@ cifs_alloc_inode(struct super_block *sb)
+ cifs_inode->clientCanCacheAll = FALSE;
+ cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
+ cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
+-
++ cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
+ INIT_LIST_HEAD(&cifs_inode->openFileList);
+ return &cifs_inode->vfs_inode;
+ }
+@@ -398,6 +405,34 @@ static struct quotactl_ops cifs_quotactl
+ };
+ #endif
+
++static void cifs_umount_begin(struct super_block * sblock)
++{
++ struct cifs_sb_info *cifs_sb;
++ struct cifsTconInfo * tcon;
++
++ cifs_sb = CIFS_SB(sblock);
++ if(cifs_sb == NULL)
++ return;
++
++ tcon = cifs_sb->tcon;
++ if(tcon == NULL)
++ return;
++ down(&tcon->tconSem);
++ if (atomic_read(&tcon->useCount) == 1)
++ tcon->tidStatus = CifsExiting;
++ up(&tcon->tconSem);
++
++ if(tcon->ses && tcon->ses->server)
++ {
++ cERROR(1,("wake up tasks now - umount begin not complete"));
++ wake_up_all(&tcon->ses->server->request_q);
++ }
++/* BB FIXME - finish add checks for tidStatus BB */
++
++ return;
++}
++
++
+ static int cifs_remount(struct super_block *sb, int *flags, char *data)
+ {
+ *flags |= MS_NODIRATIME;
+@@ -415,7 +450,7 @@ struct super_operations cifs_super_ops =
+ unless later we add lazy close of inodes or unless the kernel forgets to call
+ us with the same number of releases (closes) as opens */
+ .show_options = cifs_show_options,
+-/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
++/* .umount_begin = cifs_umount_begin, */ /* BB finish in the future */
+ .remount_fs = cifs_remount,
+ };
+
+@@ -783,9 +818,7 @@ static int cifs_oplock_thread(void * dum
+ do {
+ if (try_to_freeze())
+ continue;
+- set_current_state(TASK_INTERRUPTIBLE);
+
+- schedule_timeout(1*HZ);
+ spin_lock(&GlobalMid_Lock);
+ if(list_empty(&GlobalOplock_Q)) {
+ spin_unlock(&GlobalMid_Lock);
+@@ -834,10 +867,27 @@ static int cifs_oplock_thread(void * dum
+ }
+ } else
+ spin_unlock(&GlobalMid_Lock);
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(1); /* yield in case q were corrupt */
+ }
+ } while(!signal_pending(current));
+- complete_and_exit (&cifs_oplock_exited, 0);
+ oplockThread = NULL;
++ complete_and_exit (&cifs_oplock_exited, 0);
++}
++
++static int cifs_dnotify_thread(void * dummyarg)
++{
++ daemonize("cifsdnotifyd");
++ allow_signal(SIGTERM);
++
++ dnotifyThread = current;
++ do {
++ if(try_to_freeze())
++ continue;
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(39*HZ);
++ } while(!signal_pending(current));
++ complete_and_exit (&cifs_dnotify_exited, 0);
+ }
+
+ static int __init
+@@ -851,6 +901,10 @@ init_cifs(void)
+ INIT_LIST_HEAD(&GlobalSMBSessionList);
+ INIT_LIST_HEAD(&GlobalTreeConnectionList);
+ INIT_LIST_HEAD(&GlobalOplock_Q);
++#ifdef CONFIG_CIFS_EXPERIMENTAL
++ INIT_LIST_HEAD(&GlobalDnotifyReqList);
++ INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
++#endif
+ /*
+ * Initialize Global counters
+ */
+@@ -886,10 +940,16 @@ init_cifs(void)
+ if (!rc) {
+ rc = (int)kernel_thread(cifs_oplock_thread, NULL,
+ CLONE_FS | CLONE_FILES | CLONE_VM);
+- if(rc > 0)
+- return 0;
+- else
++ if(rc > 0) {
++ rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
++ CLONE_FS | CLONE_FILES | CLONE_VM);
++ if(rc > 0)
++ return 0;
++ else
++ cERROR(1,("error %d create dnotify thread", rc));
++ } else {
+ cERROR(1,("error %d create oplock thread",rc));
++ }
+ }
+ cifs_destroy_request_bufs();
+ }
+@@ -918,6 +978,10 @@ exit_cifs(void)
+ send_sig(SIGTERM, oplockThread, 1);
+ wait_for_completion(&cifs_oplock_exited);
+ }
++ if(dnotifyThread) {
++ send_sig(SIGTERM, dnotifyThread, 1);
++ wait_for_completion(&cifs_dnotify_exited);
++ }
+ }
+
+ MODULE_AUTHOR("Steve French <sfrench at us.ibm.com>");
+diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
+--- a/fs/cifs/cifsfs.h
++++ b/fs/cifs/cifsfs.h
+@@ -81,6 +81,7 @@ extern int cifs_dir_notify(struct file *
+
+ /* Functions related to dir entries */
+ extern struct dentry_operations cifs_dentry_ops;
++extern struct dentry_operations cifs_ci_dentry_ops;
+
+ /* Functions related to symlinks */
+ extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
+@@ -96,5 +97,5 @@ extern ssize_t cifs_getxattr(struct dent
+ extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
+ extern int cifs_ioctl (struct inode * inode, struct file * filep,
+ unsigned int command, unsigned long arg);
+-#define CIFS_VERSION "1.35"
++#define CIFS_VERSION "1.39"
+ #endif /* _CIFSFS_H */
+diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -110,8 +110,9 @@ enum protocolEnum {
+ */
+
+ struct TCP_Server_Info {
+- char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
+- char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
++ /* 15 character server name + 0x20 16th byte indicating type = srv */
++ char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
++ char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
+ struct socket *ssocket;
+ union {
+ struct sockaddr_in sockAddr;
+@@ -122,13 +123,17 @@ struct TCP_Server_Info {
+ struct list_head pending_mid_q;
+ void *Server_NlsInfo; /* BB - placeholder for future NLS info */
+ unsigned short server_codepage; /* codepage for the server */
+- unsigned long ip_address; /* IP addr for the server if known */
++ unsigned long ip_address; /* IP addr for the server if known */
+ enum protocolEnum protocolType;
+ char versionMajor;
+ char versionMinor;
+ unsigned svlocal:1; /* local server or remote */
+ atomic_t socketUseCount; /* number of open cifs sessions on socket */
+ atomic_t inFlight; /* number of requests on the wire to server */
++#ifdef CONFIG_CIFS_STATS2
++ atomic_t inSend; /* requests trying to send */
++ atomic_t num_waiters; /* blocked waiting to get in sendrecv */
++#endif
+ enum statusEnum tcpStatus; /* what we think the status is */
+ struct semaphore tcpSem;
+ struct task_struct *tsk;
+@@ -147,8 +152,10 @@ struct TCP_Server_Info {
+ /* (returned on Negotiate */
+ int capabilities; /* allow selective disabling of caps by smb sess */
+ __u16 timeZone;
++ __u16 CurrentMid; /* multiplex id - rotating counter */
+ char cryptKey[CIFS_CRYPTO_KEY_SIZE];
+- char workstation_RFC1001_name[16]; /* 16th byte is always zero */
++ /* 16th byte of RFC1001 workstation name is always null */
++ char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
+ __u32 sequence_number; /* needed for CIFS PDU signature */
+ char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
+ };
+@@ -214,19 +221,41 @@ struct cifsTconInfo {
+ atomic_t num_reads;
+ atomic_t num_oplock_brks;
+ atomic_t num_opens;
++ atomic_t num_closes;
+ atomic_t num_deletes;
+ atomic_t num_mkdirs;
+ atomic_t num_rmdirs;
+ atomic_t num_renames;
+ atomic_t num_t2renames;
++ atomic_t num_ffirst;
++ atomic_t num_fnext;
++ atomic_t num_fclose;
++ atomic_t num_hardlinks;
++ atomic_t num_symlinks;
++ atomic_t num_locks;
++#ifdef CONFIG_CIFS_STATS2
++ unsigned long long time_writes;
++ unsigned long long time_reads;
++ unsigned long long time_opens;
++ unsigned long long time_deletes;
++ unsigned long long time_closes;
++ unsigned long long time_mkdirs;
++ unsigned long long time_rmdirs;
++ unsigned long long time_renames;
++ unsigned long long time_t2renames;
++ unsigned long long time_ffirst;
++ unsigned long long time_fnext;
++ unsigned long long time_fclose;
++#endif /* CONFIG_CIFS_STATS2 */
+ __u64 bytes_read;
+ __u64 bytes_written;
+ spinlock_t stat_lock;
+-#endif
++#endif /* CONFIG_CIFS_STATS */
+ FILE_SYSTEM_DEVICE_INFO fsDevInfo;
+ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
+ FILE_SYSTEM_UNIX_INFO fsUnixInfo;
+ unsigned retry:1;
++ unsigned nocase:1;
+ /* BB add field for back pointer to sb struct? */
+ };
+
+@@ -270,6 +299,7 @@ struct cifsFileInfo {
+ struct inode * pInode; /* needed for oplock break */
+ unsigned closePend:1; /* file is marked to close */
+ unsigned invalidHandle:1; /* file closed via session abend */
++ atomic_t wrtPending; /* handle in use - defer close */
+ struct semaphore fh_sem; /* prevents reopen race after dead ses*/
+ char * search_resume_name; /* BB removeme BB */
+ unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */
+@@ -306,6 +336,41 @@ CIFS_SB(struct super_block *sb)
+ return sb->s_fs_info;
+ }
+
++static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
++{
++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
++ return '/';
++ else
++ return '\\';
++}
++
++#ifdef CONFIG_CIFS_STATS
++#define cifs_stats_inc atomic_inc
++
++static inline void cifs_stats_bytes_written(struct cifsTconInfo *tcon,
++ unsigned int bytes)
++{
++ if (bytes) {
++ spin_lock(&tcon->stat_lock);
++ tcon->bytes_written += bytes;
++ spin_unlock(&tcon->stat_lock);
++ }
++}
++
++static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,
++ unsigned int bytes)
++{
++ spin_lock(&tcon->stat_lock);
++ tcon->bytes_read += bytes;
++ spin_unlock(&tcon->stat_lock);
++}
++#else
++
++#define cifs_stats_inc(field) do {} while(0)
++#define cifs_stats_bytes_written(tcon, bytes) do {} while(0)
++#define cifs_stats_bytes_read(tcon, bytes) do {} while(0)
++
++#endif
+
+ /* one of these for every pending CIFS request to the server */
+ struct mid_q_entry {
+@@ -313,7 +378,11 @@ struct mid_q_entry {
+ __u16 mid; /* multiplex id */
+ __u16 pid; /* process id */
+ __u32 sequence_number; /* for CIFS signing */
+- struct timeval when_sent; /* time when smb sent */
++ unsigned long when_alloc; /* when mid was created */
++#ifdef CONFIG_CIFS_STATS2
++ unsigned long when_sent; /* time when smb send finished */
++ unsigned long when_received; /* when demux complete (taken off wire) */
++#endif
+ struct cifsSesInfo *ses; /* smb was sent to this server */
+ struct task_struct *tsk; /* task waiting for response */
+ struct smb_hdr *resp_buf; /* response buffer */
+@@ -331,6 +400,20 @@ struct oplock_q_entry {
+ __u16 netfid;
+ };
+
++/* for pending dnotify requests */
++struct dir_notify_req {
++ struct list_head lhead;
++ __le16 Pid;
++ __le16 PidHigh;
++ __u16 Mid;
++ __u16 Tid;
++ __u16 Uid;
++ __u16 netfid;
++ __u32 filter; /* CompletionFilter (for multishot) */
++ int multishot;
++ struct file * pfile;
++};
++
+ #define MID_FREE 0
+ #define MID_REQUEST_ALLOCATED 1
+ #define MID_REQUEST_SUBMITTED 2
+@@ -399,6 +482,9 @@ GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
+
+ GLOBAL_EXTERN struct list_head GlobalOplock_Q;
+
++GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
++GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */
++
+ /*
+ * Global transaction id (XID) information
+ */
+diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
+--- a/fs/cifs/cifspdu.h
++++ b/fs/cifs/cifspdu.h
+@@ -36,9 +36,11 @@
+ #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
+ #define SMB_COM_DELETE 0x06 /* trivial response */
+ #define SMB_COM_RENAME 0x07 /* trivial response */
++#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */
+ #define SMB_COM_SETATTR 0x09 /* trivial response */
+ #define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
+ #define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
++#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */
+ #define SMB_COM_READ_ANDX 0x2E
+ #define SMB_COM_WRITE_ANDX 0x2F
+ #define SMB_COM_TRANSACTION2 0x32
+@@ -52,6 +54,7 @@
+ #define SMB_COM_NT_TRANSACT 0xA0
+ #define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
+ #define SMB_COM_NT_CREATE_ANDX 0xA2
++#define SMB_COM_NT_CANCEL 0xA4 /* no response */
+ #define SMB_COM_NT_RENAME 0xA5 /* trivial response */
+
+ /* Transact2 subcommand codes */
+@@ -59,6 +62,7 @@
+ #define TRANS2_FIND_FIRST 0x01
+ #define TRANS2_FIND_NEXT 0x02
+ #define TRANS2_QUERY_FS_INFORMATION 0x03
++#define TRANS2_SET_FS_INFORMATION 0x04
+ #define TRANS2_QUERY_PATH_INFORMATION 0x05
+ #define TRANS2_SET_PATH_INFORMATION 0x06
+ #define TRANS2_QUERY_FILE_INFORMATION 0x07
+@@ -76,7 +80,7 @@
+ #define NT_TRANSACT_GET_USER_QUOTA 0x07
+ #define NT_TRANSACT_SET_USER_QUOTA 0x08
+
+-#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
++#define MAX_CIFS_HDR_SIZE 256 /* is future chained NTCreateXReadX bigger? */
+
+ /* internal cifs vfs structures */
+ /*****************************************************************
+@@ -129,10 +133,11 @@
+ /*
+ * SMB flag definitions
+ */
+-#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
++#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */
+ #define SMBFLG_RCV_POSTED 0x02 /* obsolete */
+ #define SMBFLG_RSVD 0x04
+-#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
++#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off
++ implies case sensitive file handling request) */
+ #define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
+ #define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
+ #define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
+@@ -141,7 +146,8 @@
+ /*
+ * SMB flag2 definitions
+ */
+-#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3) path names in response */
++#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3)
++ path names in response */
+ #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+ #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
+ #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+@@ -160,32 +166,32 @@
+ * file and can have any suitable combination of the following values:
+ */
+
+-#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
+-#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
+-#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
+-#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
+- /* with the file can be read */
+-#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
+- /* with the file can be written */
+-#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
+- /* the file using system paging I/O */
++#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
++#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
++#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
++#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
++ /* with the file can be read */
++#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
++ /* with the file can be written */
++#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
++ /* the file using system paging I/O */
+ #define FILE_DELETE_CHILD 0x00000040
+-#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
+- /* file can be read */
+-#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
+- /* file can be written */
+-#define DELETE 0x00010000 /* The file can be deleted */
+-#define READ_CONTROL 0x00020000 /* The access control list and */
+- /* ownership associated with the */
+- /* file can be read */
+-#define WRITE_DAC 0x00040000 /* The access control list and */
+- /* ownership associated with the */
+- /* file can be written. */
+-#define WRITE_OWNER 0x00080000 /* Ownership information associated */
+- /* with the file can be written */
+-#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
+- /* synchronize with the completion */
+- /* of an input/output request */
++#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
++ /* file can be read */
++#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
++ /* file can be written */
++#define DELETE 0x00010000 /* The file can be deleted */
++#define READ_CONTROL 0x00020000 /* The access control list and */
++ /* ownership associated with the */
++ /* file can be read */
++#define WRITE_DAC 0x00040000 /* The access control list and */
++ /* ownership associated with the */
++ /* file can be written. */
++#define WRITE_OWNER 0x00080000 /* Ownership information associated */
++ /* with the file can be written */
++#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
++ /* synchronize with the completion */
++ /* of an input/output request */
+ #define GENERIC_ALL 0x10000000
+ #define GENERIC_EXECUTE 0x20000000
+ #define GENERIC_WRITE 0x40000000
+@@ -193,7 +199,7 @@
+ /* In summary - Relevant file */
+ /* access flags from CIFS are */
+ /* file_read_data, file_write_data */
+- /* file_execute, file_read_attributes */
++ /* file_execute, file_read_attributes*/
+ /* write_dac, and delete. */
+
+ /*
+@@ -238,7 +244,8 @@
+ #define ATTR_SPARSE 0x0200
+ #define ATTR_REPARSE 0x0400
+ #define ATTR_COMPRESSED 0x0800
+-#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
++#define ATTR_OFFLINE 0x1000 /* ie file not immediately available -
++ on offline storage */
+ #define ATTR_NOT_CONTENT_INDEXED 0x2000
+ #define ATTR_ENCRYPTED 0x4000
+ #define ATTR_POSIX_SEMANTICS 0x01000000
+@@ -267,10 +274,18 @@
+ /* CreateOptions */
+ #define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
+ #define CREATE_WRITE_THROUGH 0x00000002
+-#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
++#define CREATE_SEQUENTIAL 0x00000004
++#define CREATE_SYNC_ALERT 0x00000010
++#define CREATE_ASYNC_ALERT 0x00000020
++#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
++#define CREATE_NO_EA_KNOWLEDGE 0x00000200
++#define CREATE_EIGHT_DOT_THREE 0x00000400
+ #define CREATE_RANDOM_ACCESS 0x00000800
+ #define CREATE_DELETE_ON_CLOSE 0x00001000
++#define CREATE_OPEN_BY_ID 0x00002000
+ #define OPEN_REPARSE_POINT 0x00200000
++#define CREATE_OPTIONS_MASK 0x007FFFFF
++#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
+
+ /* ImpersonationLevel flags */
+ #define SECURITY_ANONYMOUS 0
+@@ -297,10 +312,10 @@
+ #define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
+ #define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
+
+-#pragma pack(1)
+-
+ struct smb_hdr {
+- __u32 smb_buf_length; /* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */
++ __u32 smb_buf_length; /* big endian on wire *//* BB length is only two
++ or three bytes - with one or two byte type preceding it that are
++ zero - we could mask the type byte off just in case BB */
+ __u8 Protocol[4];
+ __u8 Command;
+ union {
+@@ -308,9 +323,9 @@ struct smb_hdr {
+ __u8 ErrorClass;
+ __u8 Reserved;
+ __le16 Error;
+- } DosError;
++ } __attribute__((packed)) DosError;
+ __le32 CifsError;
+- } Status;
++ } __attribute__((packed)) Status;
+ __u8 Flags;
+ __le16 Flags2; /* note: le */
+ __le16 PidHigh;
+@@ -318,16 +333,16 @@ struct smb_hdr {
+ struct {
+ __le32 SequenceNumber; /* le */
+ __u32 Reserved; /* zero */
+- } Sequence;
++ } __attribute__((packed)) Sequence;
+ __u8 SecuritySignature[8]; /* le */
+- } Signature;
++ } __attribute__((packed)) Signature;
+ __u8 pad[2];
+ __u16 Tid;
+ __le16 Pid;
+ __u16 Uid;
+ __u16 Mid;
+ __u8 WordCount;
+-};
++} __attribute__((packed));
+ /* given a pointer to an smb_hdr retrieve the value of byte count */
+ #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
+ #define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
+@@ -379,7 +394,7 @@ typedef struct negotiate_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ unsigned char DialectsArray[1];
+-} NEGOTIATE_REQ;
++} __attribute__((packed)) NEGOTIATE_REQ;
+
+ typedef struct negotiate_rsp {
+ struct smb_hdr hdr; /* wct = 17 */
+@@ -397,16 +412,16 @@ typedef struct negotiate_rsp {
+ __u8 EncryptionKeyLength;
+ __u16 ByteCount;
+ union {
+- unsigned char EncryptionKey[1]; /* if cap extended security is off */
++ unsigned char EncryptionKey[1]; /* cap extended security off */
+ /* followed by Domain name - if extended security is off */
+ /* followed by 16 bytes of server GUID */
+- /* followed by security blob if cap_extended_security negotiated */
++ /* then security blob if cap_extended_security negotiated */
+ struct {
+ unsigned char GUID[16];
+ unsigned char SecurityBlob[1];
+- } extended_response;
+- } u;
+-} NEGOTIATE_RSP;
++ } __attribute__((packed)) extended_response;
++ } __attribute__((packed)) u;
++} __attribute__((packed)) NEGOTIATE_RSP;
+
+ /* SecurityMode bits */
+ #define SECMODE_USER 0x01 /* off indicates share level security */
+@@ -452,7 +467,8 @@ typedef union smb_com_session_setup_andx
+ unsigned char SecurityBlob[1]; /* followed by */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+- } req; /* NTLM request format (with extended security */
++ } __attribute__((packed)) req; /* NTLM request format (with
++ extended security */
+
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 13 */
+@@ -463,18 +479,19 @@ typedef union smb_com_session_setup_andx
+ __le16 MaxMpxCount;
+ __le16 VcNumber;
+ __u32 SessionKey;
+- __le16 CaseInsensitivePasswordLength; /* ASCII password length */
+- __le16 CaseSensitivePasswordLength; /* Unicode password length */
++ __le16 CaseInsensitivePasswordLength; /* ASCII password len */
++ __le16 CaseSensitivePasswordLength; /* Unicode password length*/
+ __u32 Reserved; /* see below */
+ __le32 Capabilities;
+ __le16 ByteCount;
+- unsigned char CaseInsensitivePassword[1]; /* followed by: */
++ unsigned char CaseInsensitivePassword[1]; /* followed by: */
+ /* unsigned char * CaseSensitivePassword; */
+ /* STRING AccountName */
+ /* STRING PrimaryDomain */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+- } req_no_secext; /* NTLM request format (without extended security */
++ } __attribute__((packed)) req_no_secext; /* NTLM request format (without
++ extended security */
+
+ struct { /* default (NTLM) response format */
+ struct smb_hdr hdr; /* wct = 4 */
+@@ -488,7 +505,7 @@ typedef union smb_com_session_setup_andx
+ /* unsigned char * NativeOS; */
+ /* unsigned char * NativeLanMan; */
+ /* unsigned char * PrimaryDomain; */
+- } resp; /* NTLM response format (with or without extended security */
++ } __attribute__((packed)) resp; /* NTLM response format (with or without extended security */
+
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 10 */
+@@ -507,7 +524,7 @@ typedef union smb_com_session_setup_andx
+ /* STRING PrimaryDomain */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+- } old_req; /* pre-NTLM (LANMAN2.1) request format */
++ } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) request format */
+
+ struct { /* default (NTLM) response format */
+ struct smb_hdr hdr; /* wct = 3 */
+@@ -519,8 +536,8 @@ typedef union smb_com_session_setup_andx
+ unsigned char NativeOS[1]; /* followed by */
+ /* unsigned char * NativeLanMan; */
+ /* unsigned char * PrimaryDomain; */
+- } old_resp; /* pre-NTLM (LANMAN2.1) response format */
+-} SESSION_SETUP_ANDX;
++ } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response format */
++} __attribute__((packed)) SESSION_SETUP_ANDX;
+
+ #define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
+
+@@ -530,7 +547,8 @@ typedef union smb_com_session_setup_andx
+ #define CAP_NT_SMBS 0x00000010
+ #define CAP_STATUS32 0x00000040
+ #define CAP_LEVEL_II_OPLOCKS 0x00000080
+-#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
++#define CAP_NT_FIND 0x00000200 /* reserved should be zero
++ (because NT_SMBs implies the same thing?) */
+ #define CAP_BULK_TRANSFER 0x20000000
+ #define CAP_EXTENDED_SECURITY 0x80000000
+
+@@ -548,7 +566,7 @@ typedef struct smb_com_tconx_req {
+ unsigned char Password[1]; /* followed by */
+ /* STRING Path *//* \\server\share name */
+ /* STRING Service */
+-} TCONX_REQ;
++} __attribute__((packed)) TCONX_REQ;
+
+ typedef struct smb_com_tconx_rsp {
+ struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
+@@ -559,13 +577,14 @@ typedef struct smb_com_tconx_rsp {
+ __u16 ByteCount;
+ unsigned char Service[1]; /* always ASCII, not Unicode */
+ /* STRING NativeFileSystem */
+-} TCONX_RSP;
++} __attribute__((packed)) TCONX_RSP;
+
+ /* tree connect Flags */
+ #define DISCONNECT_TID 0x0001
+ #define TCON_EXTENDED_SECINFO 0x0008
+ /* OptionalSupport bits */
+-#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
++#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits
++ (exclusive searches supported) */
+ #define SMB_SHARE_IS_IN_DFS 0x0002
+
+ typedef struct smb_com_logoff_andx_req {
+@@ -574,7 +593,7 @@ typedef struct smb_com_logoff_andx_req {
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 ByteCount;
+-} LOGOFF_ANDX_REQ;
++} __attribute__((packed)) LOGOFF_ANDX_REQ;
+
+ typedef struct smb_com_logoff_andx_rsp {
+ struct smb_hdr hdr; /* wct = 2 */
+@@ -582,38 +601,39 @@ typedef struct smb_com_logoff_andx_rsp {
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 ByteCount;
+-} LOGOFF_ANDX_RSP;
++} __attribute__((packed)) LOGOFF_ANDX_RSP;
+
+ typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
+ struct {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bcc = 0 */
+- } req;
++ } __attribute__((packed)) req;
+ struct {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bcc = 0 */
+- } resp;
+-} TREE_DISCONNECT;
++ } __attribute__((packed)) resp;
++} __attribute__((packed)) TREE_DISCONNECT;
+
+ typedef struct smb_com_close_req {
+ struct smb_hdr hdr; /* wct = 3 */
+ __u16 FileID;
+ __u32 LastWriteTime; /* should be zero */
+ __u16 ByteCount; /* 0 */
+-} CLOSE_REQ;
++} __attribute__((packed)) CLOSE_REQ;
+
+ typedef struct smb_com_close_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+-} CLOSE_RSP;
++} __attribute__((packed)) CLOSE_RSP;
+
+ typedef struct smb_com_findclose_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __u16 FileID;
+ __u16 ByteCount; /* 0 */
+-} FINDCLOSE_REQ;
++} __attribute__((packed)) FINDCLOSE_REQ;
+
+ /* OpenFlags */
++#define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */
+ #define REQ_OPLOCK 0x00000002
+ #define REQ_BATCHOPLOCK 0x00000004
+ #define REQ_OPENDIRONLY 0x00000008
+@@ -637,7 +657,7 @@ typedef struct smb_com_open_req { /* als
+ __u8 SecurityFlags;
+ __le16 ByteCount;
+ char fileName[1];
+-} OPEN_REQ;
++} __attribute__((packed)) OPEN_REQ;
+
+ /* open response: oplock levels */
+ #define OPLOCK_NONE 0
+@@ -667,7 +687,63 @@ typedef struct smb_com_open_rsp {
+ __le16 DeviceState;
+ __u8 DirectoryFlag;
+ __u16 ByteCount; /* bct = 0 */
+-} OPEN_RSP;
++} __attribute__((packed)) OPEN_RSP;
++
++/* format of legacy open request */
++typedef struct smb_com_openx_req {
++ struct smb_hdr hdr; /* wct = 15 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __le16 AndXOffset;
++ __le16 OpenFlags;
++ __le16 Mode;
++ __le16 Sattr; /* search attributes */
++ __le16 FileAttributes; /* dos attrs */
++ __le32 CreateTime; /* os2 format */
++ __le16 OpenFunction;
++ __le32 EndOfFile;
++ __le32 Timeout;
++ __le32 Reserved;
++ __le16 ByteCount; /* file name follows */
++ char fileName[1];
++} __attribute__((packed)) OPENX_REQ;
++
++typedef struct smb_com_openx_rsp {
++ struct smb_hdr hdr; /* wct = 15 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __le16 AndXOffset;
++ __u16 Fid;
++ __le16 FileAttributes;
++ __le32 LastWriteTime; /* os2 format */
++ __le32 EndOfFile;
++ __le16 Access;
++ __le16 FileType;
++ __le16 IPCState;
++ __le16 Action;
++ __u32 FileId;
++ __u16 Reserved;
++ __u16 ByteCount;
++} __attribute__((packed)) OPENX_RSP;
++
++/* Legacy write request for older servers */
++typedef struct smb_com_writex_req {
++ struct smb_hdr hdr; /* wct = 12 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __le16 AndXOffset;
++ __u16 Fid;
++ __le32 OffsetLow;
++ __u32 Reserved; /* Timeout */
++ __le16 WriteMode; /* 1 = write through */
++ __le16 Remaining;
++ __le16 Reserved2;
++ __le16 DataLengthLow;
++ __le16 DataOffset;
++ __le16 ByteCount;
++ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
++ char Data[0];
++} __attribute__((packed)) WRITEX_REQ;
+
+ typedef struct smb_com_write_req {
+ struct smb_hdr hdr; /* wct = 14 */
+@@ -686,7 +762,7 @@ typedef struct smb_com_write_req {
+ __le16 ByteCount;
+ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
+ char Data[0];
+-} WRITE_REQ;
++} __attribute__((packed)) WRITE_REQ;
+
+ typedef struct smb_com_write_rsp {
+ struct smb_hdr hdr; /* wct = 6 */
+@@ -698,7 +774,22 @@ typedef struct smb_com_write_rsp {
+ __le16 CountHigh;
+ __u16 Reserved;
+ __u16 ByteCount;
+-} WRITE_RSP;
++} __attribute__((packed)) WRITE_RSP;
++
++/* legacy read request for older servers */
++typedef struct smb_com_readx_req {
++ struct smb_hdr hdr; /* wct = 10 */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __le16 AndXOffset;
++ __u16 Fid;
++ __le32 OffsetLow;
++ __le16 MaxCount;
++ __le16 MinCount; /* obsolete */
++ __le32 Reserved;
++ __le16 Remaining;
++ __le16 ByteCount;
++} __attribute__((packed)) READX_REQ;
+
+ typedef struct smb_com_read_req {
+ struct smb_hdr hdr; /* wct = 12 */
+@@ -713,7 +804,7 @@ typedef struct smb_com_read_req {
+ __le16 Remaining;
+ __le32 OffsetHigh;
+ __le16 ByteCount;
+-} READ_REQ;
++} __attribute__((packed)) READ_REQ;
+
+ typedef struct smb_com_read_rsp {
+ struct smb_hdr hdr; /* wct = 12 */
+@@ -730,7 +821,7 @@ typedef struct smb_com_read_rsp {
+ __u16 ByteCount;
+ __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
+ char Data[1];
+-} READ_RSP;
++} __attribute__((packed)) READ_RSP;
+
+ typedef struct locking_andx_range {
+ __le16 Pid;
+@@ -739,7 +830,7 @@ typedef struct locking_andx_range {
+ __le32 OffsetLow;
+ __le32 LengthHigh;
+ __le32 LengthLow;
+-} LOCKING_ANDX_RANGE;
++} __attribute__((packed)) LOCKING_ANDX_RANGE;
+
+ #define LOCKING_ANDX_SHARED_LOCK 0x01
+ #define LOCKING_ANDX_OPLOCK_RELEASE 0x02
+@@ -760,7 +851,7 @@ typedef struct smb_com_lock_req {
+ __le16 NumberOfLocks;
+ __le16 ByteCount;
+ LOCKING_ANDX_RANGE Locks[1];
+-} LOCK_REQ;
++} __attribute__((packed)) LOCK_REQ;
+
+
+ typedef struct cifs_posix_lock {
+@@ -770,7 +861,7 @@ typedef struct cifs_posix_lock {
+ __le64 start;
+ __le64 length;
+ /* BB what about additional owner info to identify network client */
+-} CIFS_POSIX_LOCK;
++} __attribute__((packed)) CIFS_POSIX_LOCK;
+
+ typedef struct smb_com_lock_rsp {
+ struct smb_hdr hdr; /* wct = 2 */
+@@ -778,7 +869,7 @@ typedef struct smb_com_lock_rsp {
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 ByteCount;
+-} LOCK_RSP;
++} __attribute__((packed)) LOCK_RSP;
+
+ typedef struct smb_com_rename_req {
+ struct smb_hdr hdr; /* wct = 1 */
+@@ -788,7 +879,7 @@ typedef struct smb_com_rename_req {
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName */
+-} RENAME_REQ;
++} __attribute__((packed)) RENAME_REQ;
+
+ /* copy request flags */
+ #define COPY_MUST_BE_FILE 0x0001
+@@ -808,7 +899,7 @@ typedef struct smb_com_copy_req {
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName string */
+-} COPY_REQ;
++} __attribute__((packed)) COPY_REQ;
+
+ typedef struct smb_com_copy_rsp {
+ struct smb_hdr hdr; /* wct = 1 */
+@@ -816,7 +907,7 @@ typedef struct smb_com_copy_rsp {
+ __u16 ByteCount; /* may be zero */
+ __u8 BufferFormat; /* 0x04 - only present if errored file follows */
+ unsigned char ErrorFileName[1]; /* only present if error in copy */
+-} COPY_RSP;
++} __attribute__((packed)) COPY_RSP;
+
+ #define CREATE_HARD_LINK 0x103
+ #define MOVEFILE_COPY_ALLOWED 0x0002
+@@ -832,12 +923,12 @@ typedef struct smb_com_nt_rename_req { /
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName */
+-} NT_RENAME_REQ;
++} __attribute__((packed)) NT_RENAME_REQ;
+
+ typedef struct smb_com_rename_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+-} RENAME_RSP;
++} __attribute__((packed)) RENAME_RSP;
+
+ typedef struct smb_com_delete_file_req {
+ struct smb_hdr hdr; /* wct = 1 */
+@@ -845,36 +936,52 @@ typedef struct smb_com_delete_file_req {
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+-} DELETE_FILE_REQ;
++} __attribute__((packed)) DELETE_FILE_REQ;
+
+ typedef struct smb_com_delete_file_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+-} DELETE_FILE_RSP;
++} __attribute__((packed)) DELETE_FILE_RSP;
+
+ typedef struct smb_com_delete_directory_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char DirName[1];
+-} DELETE_DIRECTORY_REQ;
++} __attribute__((packed)) DELETE_DIRECTORY_REQ;
+
+ typedef struct smb_com_delete_directory_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+-} DELETE_DIRECTORY_RSP;
++} __attribute__((packed)) DELETE_DIRECTORY_RSP;
+
+ typedef struct smb_com_create_directory_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char DirName[1];
+-} CREATE_DIRECTORY_REQ;
++} __attribute__((packed)) CREATE_DIRECTORY_REQ;
+
+ typedef struct smb_com_create_directory_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+-} CREATE_DIRECTORY_RSP;
++} __attribute__((packed)) CREATE_DIRECTORY_RSP;
++
++typedef struct smb_com_query_information_req {
++ struct smb_hdr hdr; /* wct = 0 */
++ __le16 ByteCount; /* 1 + namelen + 1 */
++ __u8 BufferFormat; /* 4 = ASCII */
++ unsigned char FileName[1];
++} __attribute__((packed)) QUERY_INFORMATION_REQ;
++
++typedef struct smb_com_query_information_rsp {
++ struct smb_hdr hdr; /* wct = 10 */
++ __le16 attr;
++ __le32 last_write_time;
++ __le32 size;
++ __u16 reserved[5];
++ __le16 ByteCount; /* bcc = 0 */
++} __attribute__((packed)) QUERY_INFORMATION_RSP;
+
+ typedef struct smb_com_setattr_req {
+ struct smb_hdr hdr; /* wct = 8 */
+@@ -885,12 +992,12 @@ typedef struct smb_com_setattr_req {
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+-} SETATTR_REQ;
++} __attribute__((packed)) SETATTR_REQ;
+
+ typedef struct smb_com_setattr_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+-} SETATTR_RSP;
++} __attribute__((packed)) SETATTR_RSP;
+
+ /* empty wct response to setattr */
+
+@@ -920,7 +1027,7 @@ typedef struct smb_com_transaction_ioctl
+ __le16 ByteCount;
+ __u8 Pad[3];
+ __u8 Data[1];
+-} TRANSACT_IOCTL_REQ;
++} __attribute__((packed)) TRANSACT_IOCTL_REQ;
+
+ typedef struct smb_com_transaction_ioctl_rsp {
+ struct smb_hdr hdr; /* wct = 19 */
+@@ -937,7 +1044,7 @@ typedef struct smb_com_transaction_ioctl
+ __le16 ReturnedDataLen;
+ __u16 ByteCount;
+ __u8 Pad[3];
+-} TRANSACT_IOCTL_RSP;
++} __attribute__((packed)) TRANSACT_IOCTL_RSP;
+
+ typedef struct smb_com_transaction_change_notify_req {
+ struct smb_hdr hdr; /* wct = 23 */
+@@ -961,7 +1068,7 @@ typedef struct smb_com_transaction_chang
+ __le16 ByteCount;
+ /* __u8 Pad[3];*/
+ /* __u8 Data[1];*/
+-} TRANSACT_CHANGE_NOTIFY_REQ;
++} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
+
+ typedef struct smb_com_transaction_change_notify_rsp {
+ struct smb_hdr hdr; /* wct = 18 */
+@@ -977,7 +1084,7 @@ typedef struct smb_com_transaction_chang
+ __u8 SetupCount; /* 0 */
+ __u16 ByteCount;
+ /* __u8 Pad[3]; */
+-} TRANSACT_CHANGE_NOTIFY_RSP;
++} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_RSP;
+ /* Completion Filter flags for Notify */
+ #define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
+ #define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
+@@ -1008,7 +1115,7 @@ struct file_notify_information {
+ __le32 Action;
+ __le32 FileNameLength;
+ __u8 FileName[0];
+-};
++} __attribute__((packed));
+
+ struct reparse_data {
+ __u32 ReparseTag;
+@@ -1019,7 +1126,7 @@ struct reparse_data {
+ __u16 TargetNameOffset;
+ __u16 TargetNameLen;
+ char LinkNamesBuf[1];
+-};
++} __attribute__((packed));
+
+ struct cifs_quota_data {
+ __u32 rsrvd1; /* 0 */
+@@ -1029,7 +1136,7 @@ struct cifs_quota_data {
+ __u64 soft_limit;
+ __u64 hard_limit;
+ char sid[1]; /* variable size? */
+-};
++} __attribute__((packed));
+
+ /* quota sub commands */
+ #define QUOTA_LIST_CONTINUE 0
+@@ -1055,12 +1162,12 @@ struct trans2_req {
+ __u8 Reserved3;
+ __le16 SubCommand; /* 1st setup word - SetupCount words follow */
+ __le16 ByteCount;
+-};
++} __attribute__((packed));
+
+ struct smb_t2_req {
+ struct smb_hdr hdr;
+ struct trans2_req t2_req;
+-};
++} __attribute__((packed));
+
+ struct trans2_resp {
+ /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */
+@@ -1079,12 +1186,12 @@ struct trans2_resp {
+ __u16 ByteCount;
+ __u16 Reserved2;*/
+ /* data area follows */
+-};
++} __attribute__((packed));
+
+ struct smb_t2_rsp {
+ struct smb_hdr hdr;
+ struct trans2_resp t2_rsp;
+-};
++} __attribute__((packed));
+
+ /* PathInfo/FileInfo infolevels */
+ #define SMB_INFO_STANDARD 1
+@@ -1171,14 +1278,14 @@ typedef struct smb_com_transaction2_qpi_
+ __le16 InformationLevel;
+ __u32 Reserved4;
+ char FileName[1];
+-} TRANSACTION2_QPI_REQ;
++} __attribute__((packed)) TRANSACTION2_QPI_REQ;
+
+ typedef struct smb_com_transaction2_qpi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
+-} TRANSACTION2_QPI_RSP;
++} __attribute__((packed)) TRANSACTION2_QPI_RSP;
+
+ typedef struct smb_com_transaction2_spi_req {
+ struct smb_hdr hdr; /* wct = 15 */
+@@ -1204,21 +1311,21 @@ typedef struct smb_com_transaction2_spi_
+ __le16 InformationLevel;
+ __u32 Reserved4;
+ char FileName[1];
+-} TRANSACTION2_SPI_REQ;
++} __attribute__((packed)) TRANSACTION2_SPI_REQ;
+
+ typedef struct smb_com_transaction2_spi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
+-} TRANSACTION2_SPI_RSP;
++} __attribute__((packed)) TRANSACTION2_SPI_RSP;
+
+ struct set_file_rename {
+ __le32 overwrite; /* 1 = overwrite dest */
+ __u32 root_fid; /* zero */
+ __le32 target_name_len;
+ char target_name[0]; /* Must be unicode */
+-};
++} __attribute__((packed));
+
+ struct smb_com_transaction2_sfi_req {
+ struct smb_hdr hdr; /* wct = 15 */
+@@ -1244,7 +1351,7 @@ struct smb_com_transaction2_sfi_req {
+ __u16 Fid;
+ __le16 InformationLevel;
+ __u16 Reserved4;
+-};
++} __attribute__((packed));
+
+ struct smb_com_transaction2_sfi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+@@ -1252,7 +1359,7 @@ struct smb_com_transaction2_sfi_rsp {
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved -
+ present for infolevels > 100 */
+-};
++} __attribute__((packed));
+
+ struct smb_t2_qfi_req {
+ struct smb_hdr hdr;
+@@ -1260,7 +1367,7 @@ struct smb_t2_qfi_req {
+ __u8 Pad;
+ __u16 Fid;
+ __le16 InformationLevel;
+-};
++} __attribute__((packed));
+
+ struct smb_t2_qfi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+@@ -1268,7 +1375,7 @@ struct smb_t2_qfi_rsp {
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved -
+ present for infolevels > 100 */
+-};
++} __attribute__((packed));
+
+ /*
+ * Flags on T2 FINDFIRST and FINDNEXT
+@@ -1310,13 +1417,13 @@ typedef struct smb_com_transaction2_ffir
+ __le16 InformationLevel;
+ __le32 SearchStorageType;
+ char FileName[1];
+-} TRANSACTION2_FFIRST_REQ;
++} __attribute__((packed)) TRANSACTION2_FFIRST_REQ;
+
+ typedef struct smb_com_transaction2_ffirst_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+-} TRANSACTION2_FFIRST_RSP;
++} __attribute__((packed)) TRANSACTION2_FFIRST_RSP;
+
+ typedef struct smb_com_transaction2_ffirst_rsp_parms {
+ __u16 SearchHandle;
+@@ -1324,7 +1431,7 @@ typedef struct smb_com_transaction2_ffir
+ __le16 EndofSearch;
+ __le16 EAErrorOffset;
+ __le16 LastNameOffset;
+-} T2_FFIRST_RSP_PARMS;
++} __attribute__((packed)) T2_FFIRST_RSP_PARMS;
+
+ typedef struct smb_com_transaction2_fnext_req {
+ struct smb_hdr hdr; /* wct = 15 */
+@@ -1352,20 +1459,20 @@ typedef struct smb_com_transaction2_fnex
+ __u32 ResumeKey;
+ __le16 SearchFlags;
+ char ResumeFileName[1];
+-} TRANSACTION2_FNEXT_REQ;
++} __attribute__((packed)) TRANSACTION2_FNEXT_REQ;
+
+ typedef struct smb_com_transaction2_fnext_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+-} TRANSACTION2_FNEXT_RSP;
++} __attribute__((packed)) TRANSACTION2_FNEXT_RSP;
+
+ typedef struct smb_com_transaction2_fnext_rsp_parms {
+ __le16 SearchCount;
+ __le16 EndofSearch;
+ __le16 EAErrorOffset;
+ __le16 LastNameOffset;
+-} T2_FNEXT_RSP_PARMS;
++} __attribute__((packed)) T2_FNEXT_RSP_PARMS;
+
+ /* QFSInfo Levels */
+ #define SMB_INFO_ALLOCATION 1
+@@ -1402,14 +1509,51 @@ typedef struct smb_com_transaction2_qfsi
+ __le16 ByteCount;
+ __u8 Pad;
+ __le16 InformationLevel;
+-} TRANSACTION2_QFSI_REQ;
++} __attribute__((packed)) TRANSACTION2_QFSI_REQ;
+
+ typedef struct smb_com_transaction_qfsi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u8 Pad; /* may be three bytes *//* followed by data area */
+-} TRANSACTION2_QFSI_RSP;
++} __attribute__((packed)) TRANSACTION2_QFSI_RSP;
++
++
++/* SETFSInfo Levels */
++#define SMB_SET_CIFS_UNIX_INFO 0x200
++typedef struct smb_com_transaction2_setfsi_req {
++ struct smb_hdr hdr; /* wct = 15 */
++ __le16 TotalParameterCount;
++ __le16 TotalDataCount;
++ __le16 MaxParameterCount;
++ __le16 MaxDataCount;
++ __u8 MaxSetupCount;
++ __u8 Reserved;
++ __le16 Flags;
++ __le32 Timeout;
++ __u16 Reserved2;
++ __le16 ParameterCount; /* 4 */
++ __le16 ParameterOffset;
++ __le16 DataCount; /* 12 */
++ __le16 DataOffset;
++ __u8 SetupCount; /* one */
++ __u8 Reserved3;
++ __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
++ __le16 ByteCount;
++ __u8 Pad;
++ __u16 FileNum; /* Parameters start. */
++ __le16 InformationLevel;/* Parameters end. */
++ __le16 ClientUnixMajor; /* Data start. */
++ __le16 ClientUnixMinor;
++ __le64 ClientUnixCap; /* Data end */
++} __attribute__((packed)) TRANSACTION2_SETFSI_REQ;
++
++typedef struct smb_com_transaction2_setfsi_rsp {
++ struct smb_hdr hdr; /* wct = 10 */
++ struct trans2_resp t2;
++ __u16 ByteCount;
++} __attribute__((packed)) TRANSACTION2_SETFSI_RSP;
++
+
+ typedef struct smb_com_transaction2_get_dfs_refer_req {
+ struct smb_hdr hdr; /* wct = 15 */
+@@ -1433,7 +1577,7 @@ typedef struct smb_com_transaction2_get_
+ __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
+ __le16 MaxReferralLevel;
+ char RequestFileName[1];
+-} TRANSACTION2_GET_DFS_REFER_REQ;
++} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
+
+ typedef struct dfs_referral_level_3 {
+ __le16 VersionNumber;
+@@ -1445,7 +1589,7 @@ typedef struct dfs_referral_level_3 {
+ __le16 DfsPathOffset;
+ __le16 DfsAlternatePathOffset;
+ __le16 NetworkAddressOffset;
+-} REFERRAL3;
++} __attribute__((packed)) REFERRAL3;
+
+ typedef struct smb_com_transaction_get_dfs_refer_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+@@ -1458,7 +1602,7 @@ typedef struct smb_com_transaction_get_d
+ __u16 Pad2;
+ REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
+ /* followed by the strings pointed to by the referral structures */
+-} TRANSACTION2_GET_DFS_REFER_RSP;
++} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP;
+
+ /* DFS Flags */
+ #define DFSREF_REFERRAL_SERVER 0x0001
+@@ -1512,7 +1656,7 @@ struct serverInfo {
+ unsigned char versionMinor;
+ unsigned long type;
+ unsigned int commentOffset;
+-};
++} __attribute__((packed));
+
+ /*
+ * The following structure is the format of the data returned on a NetShareEnum
+@@ -1524,39 +1668,55 @@ struct shareInfo {
+ char pad;
+ unsigned short type;
+ unsigned int commentOffset;
+-};
++} __attribute__((packed));
+
+ struct aliasInfo {
+ char aliasName[9];
+ char pad;
+ unsigned int commentOffset;
+ unsigned char type[2];
+-};
++} __attribute__((packed));
+
+ struct aliasInfo92 {
+ int aliasNameOffset;
+ int serverNameOffset;
+ int shareNameOffset;
+-};
++} __attribute__((packed));
+
+ typedef struct {
+ __le64 TotalAllocationUnits;
+ __le64 FreeAllocationUnits;
+ __le32 SectorsPerAllocationUnit;
+ __le32 BytesPerSector;
+-} FILE_SYSTEM_INFO; /* size info, level 0x103 */
++} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */
++
++typedef struct {
++ __le32 fsid;
++ __le32 SectorsPerAllocationUnit;
++ __le32 TotalAllocationUnits;
++ __le32 FreeAllocationUnits;
++ __le16 BytesPerSector;
++} __attribute__((packed)) FILE_SYSTEM_ALLOC_INFO;
+
+ typedef struct {
+ __le16 MajorVersionNumber;
+ __le16 MinorVersionNumber;
+ __le64 Capability;
+-} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
++} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
++
++/* Version numbers for CIFS UNIX major and minor. */
++#define CIFS_UNIX_MAJOR_VERSION 1
++#define CIFS_UNIX_MINOR_VERSION 0
++
+ /* Linux/Unix extensions capability flags */
+ #define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
+ #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
+ #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
+ #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
++#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */
++
+ #define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
++
+ typedef struct {
+ /* For undefined recommended transfer size return -1 in that field */
+ __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
+@@ -1577,7 +1737,7 @@ typedef struct {
+ __le64 FileSysIdentifier; /* fsid */
+ /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
+ /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
+-} FILE_SYSTEM_POSIX_INFO;
++} __attribute__((packed)) FILE_SYSTEM_POSIX_INFO;
+
+ /* DeviceType Flags */
+ #define FILE_DEVICE_CD_ROM 0x00000002
+@@ -1602,14 +1762,14 @@ typedef struct {
+ typedef struct {
+ __le32 DeviceType;
+ __le32 DeviceCharacteristics;
+-} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
++} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
+
+ typedef struct {
+ __le32 Attributes;
+ __le32 MaxPathNameComponentLength;
+ __le32 FileSystemNameLen;
+ char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
+-} FILE_SYSTEM_ATTRIBUTE_INFO;
++} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
+
+ /******************************************************************************/
+ /* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
+@@ -1636,7 +1796,7 @@ typedef struct { /* data block encoding
+ __le32 AlignmentRequirement;
+ __le32 FileNameLength;
+ char FileName[1];
+-} FILE_ALL_INFO; /* level 0x107 QPathInfo */
++} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */
+
+ /* defines for enumerating possible values of the Unix type field below */
+ #define UNIX_FILE 0
+@@ -1660,11 +1820,11 @@ typedef struct {
+ __u64 UniqueId;
+ __le64 Permissions;
+ __le64 Nlinks;
+-} FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
++} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
+
+ typedef struct {
+ char LinkDest[1];
+-} FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
++} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
+
+ /* The following three structures are needed only for
+ setting time to NT4 and some older servers via
+@@ -1673,13 +1833,13 @@ typedef struct {
+ __u16 Day:5;
+ __u16 Month:4;
+ __u16 Year:7;
+-} SMB_DATE;
++} __attribute__((packed)) SMB_DATE;
+
+ typedef struct {
+ __u16 TwoSeconds:5;
+ __u16 Minutes:6;
+ __u16 Hours:5;
+-} SMB_TIME;
++} __attribute__((packed)) SMB_TIME;
+
+ typedef struct {
+ __le16 CreationDate; /* SMB Date see above */
+@@ -1692,7 +1852,7 @@ typedef struct {
+ __le32 AllocationSize;
+ __le16 Attributes; /* verify not u32 */
+ __le32 EASize;
+-} FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
++} __attribute__((packed)) FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
+
+ typedef struct {
+ __le64 CreationTime;
+@@ -1701,19 +1861,19 @@ typedef struct {
+ __le64 ChangeTime;
+ __le32 Attributes;
+ __u32 Pad;
+-} FILE_BASIC_INFO; /* size info, level 0x101 */
++} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */
+
+ struct file_allocation_info {
+ __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
+-}; /* size used on disk, level 0x103 for set, 0x105 for query */
++} __attribute__((packed)); /* size used on disk, level 0x103 for set, 0x105 for query */
+
+ struct file_end_of_file_info {
+ __le64 FileSize; /* offset to end of file */
+-}; /* size info, level 0x104 for set, 0x106 for query */
++} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
+
+ struct file_alt_name_info {
+ __u8 alt_name[1];
+-}; /* level 0x0108 */
++} __attribute__((packed)); /* level 0x0108 */
+
+ struct file_stream_info {
+ __le32 number_of_streams; /* BB check sizes and verify location */
+@@ -1730,7 +1890,7 @@ struct file_compression_info {
+ __u8 ch_shift;
+ __u8 cl_shift;
+ __u8 pad[3];
+-}; /* level 0x10b */
++} __attribute__((packed)); /* level 0x10b */
+
+ /* POSIX ACL set/query path info structures */
+ #define CIFS_ACL_VERSION 1
+@@ -1738,7 +1898,7 @@ struct cifs_posix_ace { /* access contro
+ __u8 cifs_e_tag;
+ __u8 cifs_e_perm;
+ __le64 cifs_uid; /* or gid */
+-};
++} __attribute__((packed));
+
+ struct cifs_posix_acl { /* access conrol list (ACL) */
+ __le16 version;
+@@ -1747,7 +1907,7 @@ struct cifs_posix_acl { /* access conrol
+ struct cifs_posix_ace ace_array[0];
+ /* followed by
+ struct cifs_posix_ace default_ace_arraay[] */
+-}; /* level 0x204 */
++} __attribute__((packed)); /* level 0x204 */
+
+ /* types of access control entries already defined in posix_acl.h */
+ /* #define CIFS_POSIX_ACL_USER_OBJ 0x01
+@@ -1766,15 +1926,15 @@ struct cifs_posix_acl { /* access conrol
+
+ struct file_internal_info {
+ __u64 UniqueId; /* inode number */
+-}; /* level 0x3ee */
++} __attribute__((packed)); /* level 0x3ee */
+ struct file_mode_info {
+ __le32 Mode;
+-}; /* level 0x3f8 */
++} __attribute__((packed)); /* level 0x3f8 */
+
+ struct file_attrib_tag {
+ __le32 Attribute;
+ __le32 ReparseTag;
+-}; /* level 0x40b */
++} __attribute__((packed)); /* level 0x40b */
+
+
+ /********************************************************/
+@@ -1798,7 +1958,7 @@ typedef struct {
+ __le64 Permissions;
+ __le64 Nlinks;
+ char FileName[1];
+-} FILE_UNIX_INFO; /* level 0x202 */
++} __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */
+
+ typedef struct {
+ __le32 NextEntryOffset;
+@@ -1812,7 +1972,7 @@ typedef struct {
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ char FileName[1];
+-} FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */
++} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */
+
+ typedef struct {
+ __le32 NextEntryOffset;
+@@ -1827,7 +1987,7 @@ typedef struct {
+ __le32 FileNameLength;
+ __le32 EaSize; /* length of the xattrs */
+ char FileName[1];
+-} FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */
++} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */
+
+ typedef struct {
+ __le32 NextEntryOffset;
+@@ -1844,7 +2004,7 @@ typedef struct {
+ __le32 Reserved;
+ __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
+ char FileName[1];
+-} SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */
++} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */
+
+ typedef struct {
+ __le32 NextEntryOffset;
+@@ -1862,18 +2022,18 @@ typedef struct {
+ __u8 Reserved;
+ __u8 ShortName[12];
+ char FileName[1];
+-} FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */
++} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */
+
+
+ struct gea {
+ unsigned char name_len;
+ char name[1];
+-};
++} __attribute__((packed));
+
+ struct gealist {
+ unsigned long list_len;
+ struct gea list[1];
+-};
++} __attribute__((packed));
+
+ struct fea {
+ unsigned char EA_flags;
+@@ -1881,21 +2041,21 @@ struct fea {
+ __le16 value_len;
+ char name[1];
+ /* optionally followed by value */
+-};
++} __attribute__((packed));
+ /* flags for _FEA.fEA */
+ #define FEA_NEEDEA 0x80 /* need EA bit */
+
+ struct fealist {
+ __le32 list_len;
+ struct fea list[1];
+-};
++} __attribute__((packed));
+
+ /* used to hold an arbitrary blob of data */
+ struct data_blob {
+ __u8 *data;
+ size_t length;
+ void (*free) (struct data_blob * data_blob);
+-};
++} __attribute__((packed));
+
+
+ #ifdef CONFIG_CIFS_POSIX
+@@ -1907,18 +2067,17 @@ struct data_blob {
+ perhaps add a CreateDevice - to create Pipes and other special .inodes
+ Also note POSIX open flags
+ 2) Close - to return the last write time to do cache across close more safely
+- 3) PosixQFSInfo - to return statfs info
+- 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
+- 5) Mkdir - set mode
++ 3) FindFirst return unique inode number - what about resume key, two
++ forms short (matches readdir) and full (enough info to cache inodes)
++ 4) Mkdir - set mode
+
+ And under consideration:
+- 6) FindClose2 (return nanosecond timestamp ??)
+- 7) Use nanosecond timestamps throughout all time fields if
++ 5) FindClose2 (return nanosecond timestamp ??)
++ 6) Use nanosecond timestamps throughout all time fields if
+ corresponding attribute flag is set
+- 8) sendfile - handle based copy
+- 9) Direct i/o
+- 10) "POSIX ACL" support
+- 11) Misc fcntls?
++ 7) sendfile - handle based copy
++ 8) Direct i/o
++ 9) Misc fcntls?
+
+ what about fixing 64 bit alignment
+
+@@ -1974,7 +2133,7 @@ struct data_blob {
+
+ */
+
+-/* xsymlink is a symlink format that can be used
++/* xsymlink is a symlink format (used by MacOS) that can be used
+ to save symlink info in a regular file when
+ mounted to operating systems that do not
+ support the cifs Unix extensions or EAs (for xattr
+@@ -1999,7 +2158,7 @@ struct xsymlink {
+ char cr2; /* \n */
+ /* if room left, then end with \n then 0x20s by convention but not required */
+ char path[1024];
+-};
++} __attribute__((packed));
+
+ typedef struct file_xattr_info {
+ /* BB do we need another field for flags? BB */
+@@ -2007,7 +2166,7 @@ typedef struct file_xattr_info {
+ __u32 xattr_value_len;
+ char xattr_name[0];
+ /* followed by xattr_value[xattr_value_len], no pad */
+-} FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
++} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
+
+
+ /* flags for chattr command */
+@@ -2033,10 +2192,8 @@ typedef struct file_xattr_info {
+ typedef struct file_chattr_info {
+ __le64 mask; /* list of all possible attribute bits */
+ __le64 mode; /* list of actual attribute bits on this inode */
+-} FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
++} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
+
+ #endif
+
+-#pragma pack() /* resume default structure packing */
+-
+ #endif /* _CIFSPDU_H */
+diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -47,19 +47,24 @@ extern int SendReceive(const unsigned in
+ struct smb_hdr * /* input */ ,
+ struct smb_hdr * /* out */ ,
+ int * /* bytes returned */ , const int long_op);
++extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
++ struct kvec *, int /* nvec */,
++ int * /* bytes returned */ , const int long_op);
+ extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
+ extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
+ extern int is_valid_oplock_break(struct smb_hdr *smb);
+ extern int is_size_safe_to_change(struct cifsInodeInfo *);
++extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
+ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
++extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
+ extern int decode_negTokenInit(unsigned char *security_blob, int length,
+ enum securityEnum *secType);
+ extern int cifs_inet_pton(int, char * source, void *dst);
+ extern int map_smb_to_linux_error(struct smb_hdr *smb);
+ extern void header_assemble(struct smb_hdr *, char /* command */ ,
+- const struct cifsTconInfo *, int /* specifies length
+- of fixed section (word count) in two byte units */
+- );
++ const struct cifsTconInfo *, int /* length of
++ fixed section (word count) in two byte units */);
++extern __u16 GetNextMid(struct TCP_Server_Info *server);
+ extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
+ struct cifsTconInfo *);
+ extern void DeleteOplockQEntry(struct oplock_q_entry *);
+@@ -89,7 +94,7 @@ extern int CIFSTCon(unsigned int xid, st
+
+ extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
+ const char *searchName, const struct nls_table *nls_codepage,
+- __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
++ __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
+
+ extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
+ __u16 searchHandle, struct cifs_search_info * psrch_inf);
+@@ -101,6 +106,10 @@ extern int CIFSSMBQPathInfo(const int xi
+ const unsigned char *searchName,
+ FILE_ALL_INFO * findData,
+ const struct nls_table *nls_codepage, int remap);
++extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ FILE_ALL_INFO * findData,
++ const struct nls_table *nls_codepage, int remap);
+
+ extern int CIFSSMBUnixQPathInfo(const int xid,
+ struct cifsTconInfo *tcon,
+@@ -125,6 +134,11 @@ extern int get_dfs_path(int xid, struct
+ int remap);
+ extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
+ struct kstatfs *FSData);
++extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
++ struct kstatfs *FSData);
++extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
++ __u64 cap);
++
+ extern int CIFSSMBQFSAttributeInfo(const int xid,
+ struct cifsTconInfo *tcon);
+ extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
+@@ -207,6 +221,11 @@ extern int CIFSSMBOpen(const int xid, st
+ const int access_flags, const int omode,
+ __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
+ const struct nls_table *nls_codepage, int remap);
++extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
++ const char *fileName, const int disposition,
++ const int access_flags, const int omode,
++ __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
++ const struct nls_table *nls_codepage, int remap);
+ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
+ const int smb_file_id);
+
+@@ -222,7 +241,7 @@ extern int CIFSSMBWrite(const int xid, s
+ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
+ const int netfid, const unsigned int count,
+ const __u64 offset, unsigned int *nbytes,
+- const char __user *buf,const int long_op);
++ struct kvec *iov, const int nvec, const int long_op);
+ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName, __u64 * inode_number,
+ const struct nls_table *nls_codepage,
+@@ -264,7 +283,8 @@ extern int CIFSSMBCopy(int xid,
+ int remap_special_chars);
+ extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
+ const int notify_subdirs,const __u16 netfid,
+- __u32 filter, const struct nls_table *nls_codepage);
++ __u32 filter, struct file * file, int multishot,
++ const struct nls_table *nls_codepage);
+ extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName, char * EAData,
+ size_t bufsize, const struct nls_table *nls_codepage,
+diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -125,6 +125,9 @@ small_smb_init(int smb_command, int wct,
+ rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
+ , nls_codepage);
+ up(&tcon->ses->sesSem);
++ /* BB FIXME add code to check if wsize needs
++ update due to negotiated smb buffer size
++ shrinking */
+ if(rc == 0)
+ atomic_inc(&tconInfoReconnectCount);
+
+@@ -166,11 +169,9 @@ small_smb_init(int smb_command, int wct,
+
+ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
+
+-#ifdef CONFIG_CIFS_STATS
+- if(tcon != NULL) {
+- atomic_inc(&tcon->num_smbs_sent);
+- }
+-#endif /* CONFIG_CIFS_STATS */
++ if(tcon != NULL)
++ cifs_stats_inc(&tcon->num_smbs_sent);
++
+ return rc;
+ }
+
+@@ -222,6 +223,9 @@ smb_init(int smb_command, int wct, struc
+ rc = CIFSTCon(0, tcon->ses, tcon->treeName,
+ tcon, nls_codepage);
+ up(&tcon->ses->sesSem);
++ /* BB FIXME add code to check if wsize needs
++ update due to negotiated smb buffer size
++ shrinking */
+ if(rc == 0)
+ atomic_inc(&tconInfoReconnectCount);
+
+@@ -269,11 +273,9 @@ smb_init(int smb_command, int wct, struc
+ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
+ wct /*wct */ );
+
+-#ifdef CONFIG_CIFS_STATS
+- if(tcon != NULL) {
+- atomic_inc(&tcon->num_smbs_sent);
+- }
+-#endif /* CONFIG_CIFS_STATS */
++ if(tcon != NULL)
++ cifs_stats_inc(&tcon->num_smbs_sent);
++
+ return rc;
+ }
+
+@@ -330,7 +332,7 @@ CIFSSMBNegotiate(unsigned int xid, struc
+ (void **) &pSMB, (void **) &pSMBr);
+ if (rc)
+ return rc;
+-
++ pSMB->hdr.Mid = GetNextMid(server);
+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
+ if (extended_security)
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+@@ -422,8 +424,8 @@ CIFSSMBNegotiate(unsigned int xid, struc
+ }
+
+ }
+- if (pSMB)
+- cifs_buf_release(pSMB);
++
++ cifs_buf_release(pSMB);
+ return rc;
+ }
+
+@@ -518,6 +520,8 @@ CIFSSMBLogoff(const int xid, struct cifs
+ smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
+
+ if(ses->server) {
++ pSMB->hdr.Mid = GetNextMid(ses->server);
++
+ if(ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+@@ -537,9 +541,8 @@ CIFSSMBLogoff(const int xid, struct cifs
+ rc = -ESHUTDOWN;
+ }
+ }
+- if (pSMB)
+- cifs_small_buf_release(pSMB);
+ up(&ses->sesSem);
++ cifs_small_buf_release(pSMB);
+
+ /* if session dead then we do not need to do ulogoff,
+ since server closed smb session, no sense reporting
+@@ -583,14 +586,10 @@ DelFileRetry:
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_deletes);
+ if (rc) {
+ cFYI(1, ("Error in RMFile = %d", rc));
+ }
+-#ifdef CONFIG_CIFS_STATS
+- else {
+- atomic_inc(&tcon->num_deletes);
+- }
+-#endif
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+@@ -632,14 +631,10 @@ RmDirRetry:
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_rmdirs);
+ if (rc) {
+ cFYI(1, ("Error in RMDir = %d", rc));
+ }
+-#ifdef CONFIG_CIFS_STATS
+- else {
+- atomic_inc(&tcon->num_rmdirs);
+- }
+-#endif
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+@@ -680,20 +675,161 @@ MkDirRetry:
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_mkdirs);
+ if (rc) {
+ cFYI(1, ("Error in Mkdir = %d", rc));
+ }
+-#ifdef CONFIG_CIFS_STATS
+- else {
+- atomic_inc(&tcon->num_mkdirs);
+- }
+-#endif
++
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto MkDirRetry;
+ return rc;
+ }
+
++static __u16 convert_disposition(int disposition)
++{
++ __u16 ofun = 0;
++
++ switch (disposition) {
++ case FILE_SUPERSEDE:
++ ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
++ break;
++ case FILE_OPEN:
++ ofun = SMBOPEN_OAPPEND;
++ break;
++ case FILE_CREATE:
++ ofun = SMBOPEN_OCREATE;
++ break;
++ case FILE_OPEN_IF:
++ ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
++ break;
++ case FILE_OVERWRITE:
++ ofun = SMBOPEN_OTRUNC;
++ break;
++ case FILE_OVERWRITE_IF:
++ ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
++ break;
++ default:
++ cFYI(1,("unknown disposition %d",disposition));
++ ofun = SMBOPEN_OAPPEND; /* regular open */
++ }
++ return ofun;
++}
++
++int
++SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
++ const char *fileName, const int openDisposition,
++ const int access_flags, const int create_options, __u16 * netfid,
++ int *pOplock, FILE_ALL_INFO * pfile_info,
++ const struct nls_table *nls_codepage, int remap)
++{
++ int rc = -EACCES;
++ OPENX_REQ *pSMB = NULL;
++ OPENX_RSP *pSMBr = NULL;
++ int bytes_returned;
++ int name_len;
++ __u16 count;
++
++OldOpenRetry:
++ rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ pSMB->AndXCommand = 0xFF; /* none */
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ count = 1; /* account for one byte pad to word boundary */
++ name_len =
++ cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
++ fileName, PATH_MAX, nls_codepage, remap);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else { /* BB improve check for buffer overruns BB */
++ count = 0; /* no pad */
++ name_len = strnlen(fileName, PATH_MAX);
++ name_len++; /* trailing null */
++ strncpy(pSMB->fileName, fileName, name_len);
++ }
++ if (*pOplock & REQ_OPLOCK)
++ pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
++ else if (*pOplock & REQ_BATCHOPLOCK) {
++ pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
++ }
++ pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
++ /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
++ /* 0 = read
++ 1 = write
++ 2 = rw
++ 3 = execute
++ */
++ pSMB->Mode = cpu_to_le16(2);
++ pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
++ /* set file as system file if special file such
++ as fifo and server expecting SFU style and
++ no Unix extensions */
++
++ if(create_options & CREATE_OPTION_SPECIAL)
++ pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
++ else
++ pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
++
++ /* if ((omode & S_IWUGO) == 0)
++ pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
++ /* Above line causes problems due to vfs splitting create into two
++ pieces - need to set mode after file created not while it is
++ being created */
++
++ /* BB FIXME BB */
++/* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
++ /* BB FIXME END BB */
++
++ pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
++ pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
++ count += name_len;
++ pSMB->hdr.smb_buf_length += count;
++
++ pSMB->ByteCount = cpu_to_le16(count);
++ /* long_op set to 1 to allow for oplock break timeouts */
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 1);
++ cifs_stats_inc(&tcon->num_opens);
++ if (rc) {
++ cFYI(1, ("Error in Open = %d", rc));
++ } else {
++ /* BB verify if wct == 15 */
++
++/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
++
++ *netfid = pSMBr->Fid; /* cifs fid stays in le */
++ /* Let caller know file was created so we can set the mode. */
++ /* Do we care about the CreateAction in any other cases? */
++ /* BB FIXME BB */
++/* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
++ *pOplock |= CIFS_CREATE_ACTION; */
++ /* BB FIXME END */
++
++ if(pfile_info) {
++ pfile_info->CreationTime = 0; /* BB convert CreateTime*/
++ pfile_info->LastAccessTime = 0; /* BB fixme */
++ pfile_info->LastWriteTime = 0; /* BB fixme */
++ pfile_info->ChangeTime = 0; /* BB fixme */
++ pfile_info->Attributes =
++ cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
++ /* the file_info buf is endian converted by caller */
++ pfile_info->AllocationSize =
++ cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
++ pfile_info->EndOfFile = pfile_info->AllocationSize;
++ pfile_info->NumberOfLinks = cpu_to_le32(1);
++ }
++ }
++
++ cifs_buf_release(pSMB);
++ if (rc == -EAGAIN)
++ goto OldOpenRetry;
++ return rc;
++}
++
+ int
+ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
+ const char *fileName, const int openDisposition,
+@@ -738,7 +874,13 @@ openRetry:
+ }
+ pSMB->DesiredAccess = cpu_to_le32(access_flags);
+ pSMB->AllocationSize = 0;
+- pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
++ /* set file as system file if special file such
++ as fifo and server expecting SFU style and
++ no Unix extensions */
++ if(create_options & CREATE_OPTION_SPECIAL)
++ pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
++ else
++ pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
+ /* XP does not handle ATTR_POSIX_SEMANTICS */
+ /* but it helps speed up case sensitive checks for other
+ servers such as Samba */
+@@ -752,7 +894,7 @@ openRetry:
+ being created */
+ pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
+ pSMB->CreateDisposition = cpu_to_le32(openDisposition);
+- pSMB->CreateOptions = cpu_to_le32(create_options);
++ pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
+ /* BB Expirement with various impersonation levels and verify */
+ pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
+ pSMB->SecurityFlags =
+@@ -765,6 +907,7 @@ openRetry:
+ /* long_op set to 1 to allow for oplock break timeouts */
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 1);
++ cifs_stats_inc(&tcon->num_opens);
+ if (rc) {
+ cFYI(1, ("Error in Open = %d", rc));
+ } else {
+@@ -782,11 +925,8 @@ openRetry:
+ pfile_info->EndOfFile = pSMBr->EndOfFile;
+ pfile_info->NumberOfLinks = cpu_to_le32(1);
+ }
+-
+-#ifdef CONFIG_CIFS_STATS
+- atomic_inc(&tcon->num_opens);
+-#endif
+ }
++
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto openRetry;
+@@ -807,11 +947,16 @@ CIFSSMBRead(const int xid, struct cifsTc
+ READ_RSP *pSMBr = NULL;
+ char *pReadData = NULL;
+ int bytes_returned;
++ int wct;
+
+ cFYI(1,("Reading %d bytes on fid %d",count,netfid));
++ if(tcon->ses->capabilities & CAP_LARGE_FILES)
++ wct = 12;
++ else
++ wct = 10; /* old style read */
+
+ *nbytes = 0;
+- rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
++ rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+@@ -823,14 +968,26 @@ CIFSSMBRead(const int xid, struct cifsTc
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
+- pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
++ if(wct == 12)
++ pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
++ else if((lseek >> 32) > 0) /* can not handle this big offset for old */
++ return -EIO;
++
+ pSMB->Remaining = 0;
+ pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
+ pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
+- pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
+-
++ if(wct == 12)
++ pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
++ else {
++ /* old style read */
++ struct smb_com_readx_req * pSMBW =
++ (struct smb_com_readx_req *)pSMB;
++ pSMBW->ByteCount = 0;
++ }
++
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_reads);
+ if (rc) {
+ cERROR(1, ("Send error in read = %d", rc));
+ } else {
+@@ -876,12 +1033,20 @@ CIFSSMBWrite(const int xid, struct cifsT
+ int rc = -EACCES;
+ WRITE_REQ *pSMB = NULL;
+ WRITE_RSP *pSMBr = NULL;
+- int bytes_returned;
++ int bytes_returned, wct;
+ __u32 bytes_sent;
+ __u16 byte_count;
+
+ /* cFYI(1,("write at %lld %d bytes",offset,count));*/
+- rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
++ if(tcon->ses == NULL)
++ return -ECONNABORTED;
++
++ if(tcon->ses->capabilities & CAP_LARGE_FILES)
++ wct = 14;
++ else
++ wct = 12;
++
++ rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+@@ -892,7 +1057,11 @@ CIFSSMBWrite(const int xid, struct cifsT
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+- pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
++ if(wct == 14)
++ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
++ else if((offset >> 32) > 0) /* can not handle this big offset for old */
++ return -EIO;
++
+ pSMB->Reserved = 0xFFFFFFFF;
+ pSMB->WriteMode = 0;
+ pSMB->Remaining = 0;
+@@ -911,7 +1080,7 @@ CIFSSMBWrite(const int xid, struct cifsT
+ if (bytes_sent > count)
+ bytes_sent = count;
+ pSMB->DataOffset =
+- cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
++ cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+ if(buf)
+ memcpy(pSMB->Data,buf,bytes_sent);
+ else if(ubuf) {
+@@ -919,20 +1088,31 @@ CIFSSMBWrite(const int xid, struct cifsT
+ cifs_buf_release(pSMB);
+ return -EFAULT;
+ }
+- } else {
++ } else if (count != 0) {
+ /* No buffer */
+ cifs_buf_release(pSMB);
+ return -EINVAL;
++ } /* else setting file size with write of zero bytes */
++ if(wct == 14)
++ byte_count = bytes_sent + 1; /* pad */
++ else /* wct == 12 */ {
++ byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
+ }
+-
+- byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
+ pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
+ pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
+- pSMB->hdr.smb_buf_length += bytes_sent+1;
+- pSMB->ByteCount = cpu_to_le16(byte_count);
++ pSMB->hdr.smb_buf_length += byte_count;
++
++ if(wct == 14)
++ pSMB->ByteCount = cpu_to_le16(byte_count);
++ else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
++ struct smb_com_writex_req * pSMBW =
++ (struct smb_com_writex_req *)pSMB;
++ pSMBW->ByteCount = cpu_to_le16(byte_count);
++ }
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
++ cifs_stats_inc(&tcon->num_writes);
+ if (rc) {
+ cFYI(1, ("Send error in write = %d", rc));
+ *nbytes = 0;
+@@ -951,56 +1131,72 @@ CIFSSMBWrite(const int xid, struct cifsT
+ }
+
+ #ifdef CONFIG_CIFS_EXPERIMENTAL
+-int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
++int
++CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
+ const int netfid, const unsigned int count,
+- const __u64 offset, unsigned int *nbytes, const char __user *buf,
+- const int long_op)
++ const __u64 offset, unsigned int *nbytes, struct kvec *iov,
++ int n_vec, const int long_op)
+ {
+ int rc = -EACCES;
+ WRITE_REQ *pSMB = NULL;
+- WRITE_RSP *pSMBr = NULL;
+- /*int bytes_returned;*/
+- unsigned bytes_sent;
+- __u16 byte_count;
++ int bytes_returned, wct;
++ int smb_hdr_len;
+
+- rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
+-
++ cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
++ if(tcon->ses->capabilities & CAP_LARGE_FILES)
++ wct = 14;
++ else
++ wct = 12;
++ rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
+ if (rc)
+ return rc;
+-
+- pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
+-
+ /* tcon and ses pointer are checked in smb_init */
+ if (tcon->ses->server == NULL)
+ return -ECONNABORTED;
+
+- pSMB->AndXCommand = 0xFF; /* none */
++ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+- pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
++ if(wct == 14)
++ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
++ else if((offset >> 32) > 0) /* can not handle this big offset for old */
++ return -EIO;
+ pSMB->Reserved = 0xFFFFFFFF;
+ pSMB->WriteMode = 0;
+ pSMB->Remaining = 0;
+- bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+- if (bytes_sent > count)
+- bytes_sent = count;
+- pSMB->DataLengthHigh = 0;
++
+ pSMB->DataOffset =
+ cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+
+- byte_count = bytes_sent + 1 /* pad */ ;
+- pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+- pSMB->DataLengthHigh = 0;
+- pSMB->hdr.smb_buf_length += byte_count;
+- pSMB->ByteCount = cpu_to_le16(byte_count);
+-
+-/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
+- (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
++ pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
++ pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
++ smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
++ if(wct == 14)
++ pSMB->hdr.smb_buf_length += count+1;
++ else /* wct == 12 */
++ pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
++ if(wct == 14)
++ pSMB->ByteCount = cpu_to_le16(count + 1);
++ else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
++ struct smb_com_writex_req * pSMBW =
++ (struct smb_com_writex_req *)pSMB;
++ pSMBW->ByteCount = cpu_to_le16(count + 5);
++ }
++ iov[0].iov_base = pSMB;
++ iov[0].iov_len = smb_hdr_len + 4;
++
++ rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
++ long_op);
++ cifs_stats_inc(&tcon->num_writes);
+ if (rc) {
+- cFYI(1, ("Send error in write2 (large write) = %d", rc));
++ cFYI(1, ("Send error Write2 = %d", rc));
+ *nbytes = 0;
+- } else
+- *nbytes = le16_to_cpu(pSMBr->Count);
++ } else {
++ WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
++ *nbytes = le16_to_cpu(pSMBr->CountHigh);
++ *nbytes = (*nbytes) << 16;
++ *nbytes += le16_to_cpu(pSMBr->Count);
++ }
+
+ cifs_small_buf_release(pSMB);
+
+@@ -1009,6 +1205,8 @@ int CIFSSMBWrite2(const int xid, struct
+
+ return rc;
+ }
++
++
+ #endif /* CIFS_EXPERIMENTAL */
+
+ int
+@@ -1065,7 +1263,7 @@ CIFSSMBLock(const int xid, struct cifsTc
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+-
++ cifs_stats_inc(&tcon->num_locks);
+ if (rc) {
+ cFYI(1, ("Send error in Lock = %d", rc));
+ }
+@@ -1099,6 +1297,7 @@ CIFSSMBClose(const int xid, struct cifsT
+ pSMB->ByteCount = 0;
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_closes);
+ if (rc) {
+ if(rc!=-EINTR) {
+ /* EINTR is expected when user ctl-c to kill app */
+@@ -1171,16 +1370,11 @@ renameRetry:
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_renames);
+ if (rc) {
+ cFYI(1, ("Send error in rename = %d", rc));
+ }
+
+-#ifdef CONFIG_CIFS_STATS
+- else {
+- atomic_inc(&tcon->num_renames);
+- }
+-#endif
+-
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+@@ -1255,14 +1449,11 @@ int CIFSSMBRenameOpenFile(const int xid,
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&pTcon->num_t2renames);
+ if (rc) {
+ cFYI(1,("Send error in Rename (by file handle) = %d", rc));
+ }
+-#ifdef CONFIG_CIFS_STATS
+- else {
+- atomic_inc(&pTcon->num_t2renames);
+- }
+-#endif
++
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+@@ -1416,6 +1607,7 @@ createSymLinkRetry:
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_symlinks);
+ if (rc) {
+ cFYI(1,
+ ("Send error in SetPathInfo (create symlink) = %d",
+@@ -1505,6 +1697,7 @@ createHardLinkRetry:
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_hardlinks);
+ if (rc) {
+ cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
+ }
+@@ -1575,6 +1768,7 @@ winCreateHardLinkRetry:
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_hardlinks);
+ if (rc) {
+ cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
+ }
+@@ -1775,8 +1969,7 @@ CIFSSMBQueryReparseLinkInfo(const int xi
+ }
+ }
+ qreparse_out:
+- if (pSMB)
+- cifs_buf_release(pSMB);
++ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+@@ -2165,6 +2358,67 @@ GetExtAttrOut:
+
+ #endif /* CONFIG_POSIX */
+
++/* Legacy Query Path Information call for lookup to old servers such
++ as Win9x/WinME */
++int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
++ const unsigned char *searchName,
++ FILE_ALL_INFO * pFinfo,
++ const struct nls_table *nls_codepage, int remap)
++{
++ QUERY_INFORMATION_REQ * pSMB;
++ QUERY_INFORMATION_RSP * pSMBr;
++ int rc = 0;
++ int bytes_returned;
++ int name_len;
++
++ cFYI(1, ("In SMBQPath path %s", searchName));
++QInfRetry:
++ rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
++ name_len =
++ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
++ PATH_MAX, nls_codepage, remap);
++ name_len++; /* trailing null */
++ name_len *= 2;
++ } else {
++ name_len = strnlen(searchName, PATH_MAX);
++ name_len++; /* trailing null */
++ strncpy(pSMB->FileName, searchName, name_len);
++ }
++ pSMB->BufferFormat = 0x04;
++ name_len++; /* account for buffer type byte */
++ pSMB->hdr.smb_buf_length += (__u16) name_len;
++ pSMB->ByteCount = cpu_to_le16(name_len);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QueryInfo = %d", rc));
++ } else if (pFinfo) { /* decode response */
++ memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
++ pFinfo->AllocationSize =
++ cpu_to_le64(le32_to_cpu(pSMBr->size));
++ pFinfo->EndOfFile = pFinfo->AllocationSize;
++ pFinfo->Attributes =
++ cpu_to_le32(le16_to_cpu(pSMBr->attr));
++ } else
++ rc = -EIO; /* bad buffer passed in */
++
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto QInfRetry;
++
++ return rc;
++}
++
++
++
++
+ int
+ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName,
+@@ -2396,7 +2650,7 @@ findUniqueRetry:
+ if (rc) {
+ cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
+ } else { /* decode response */
+-
++ cifs_stats_inc(&tcon->num_ffirst);
+ /* BB fill in */
+ }
+
+@@ -2414,7 +2668,7 @@ CIFSFindFirst(const int xid, struct cifs
+ const char *searchName,
+ const struct nls_table *nls_codepage,
+ __u16 * pnetfid,
+- struct cifs_search_info * psrch_inf, int remap)
++ struct cifs_search_info * psrch_inf, int remap, const char dirsep)
+ {
+ /* level 257 SMB_ */
+ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+@@ -2441,7 +2695,7 @@ findFirstRetry:
+ it got remapped to 0xF03A as if it were part of the
+ directory name instead of a wildcard */
+ name_len *= 2;
+- pSMB->FileName[name_len] = '\\';
++ pSMB->FileName[name_len] = dirsep;
+ pSMB->FileName[name_len+1] = 0;
+ pSMB->FileName[name_len+2] = '*';
+ pSMB->FileName[name_len+3] = 0;
+@@ -2455,7 +2709,7 @@ findFirstRetry:
+ if(name_len > buffersize-header)
+ free buffer exit; BB */
+ strncpy(pSMB->FileName, searchName, name_len);
+- pSMB->FileName[name_len] = '\\';
++ pSMB->FileName[name_len] = dirsep;
+ pSMB->FileName[name_len+1] = '*';
+ pSMB->FileName[name_len+2] = 0;
+ name_len += 3;
+@@ -2496,6 +2750,7 @@ findFirstRetry:
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ cifs_stats_inc(&tcon->num_ffirst);
+
+ if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
+ /* BB Add code to handle unsupported level rc */
+@@ -2617,7 +2872,7 @@ int CIFSFindNext(const int xid, struct c
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+-
++ cifs_stats_inc(&tcon->num_fnext);
+ if (rc) {
+ if (rc == -EBADF) {
+ psrch_inf->endOfSearch = TRUE;
+@@ -2694,6 +2949,7 @@ CIFSFindClose(const int xid, struct cifs
+ if (rc) {
+ cERROR(1, ("Send error in FindClose = %d", rc));
+ }
++ cifs_stats_inc(&tcon->num_fclose);
+ cifs_small_buf_release(pSMB);
+
+ /* Since session is dead, search handle closed on server already */
+@@ -2827,7 +3083,10 @@ getDFSRetry:
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+-
++
++ /* server pointer checked in called function,
++ but should never be null here anyway */
++ pSMB->hdr.Mid = GetNextMid(ses->server);
+ pSMB->hdr.Tid = ses->ipc_tid;
+ pSMB->hdr.Uid = ses->Suid;
+ if (ses->capabilities & CAP_STATUS32) {
+@@ -2968,6 +3227,92 @@ GetDFSRefExit:
+ return rc;
+ }
+
++/* Query File System Info such as free space to old servers such as Win 9x */
++int
++SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
++{
++/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
++ TRANSACTION2_QFSI_REQ *pSMB = NULL;
++ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
++ FILE_SYSTEM_ALLOC_INFO *response_data;
++ int rc = 0;
++ int bytes_returned = 0;
++ __u16 params, byte_count;
++
++ cFYI(1, ("OldQFSInfo"));
++oldQFSInfoRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ params = 2; /* level */
++ pSMB->TotalDataCount = 0;
++ pSMB->MaxParameterCount = cpu_to_le16(2);
++ pSMB->MaxDataCount = cpu_to_le16(1000);
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ byte_count = params + 1 /* pad */ ;
++ pSMB->TotalParameterCount = cpu_to_le16(params);
++ pSMB->ParameterCount = pSMB->TotalParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(offsetof(
++ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
++ pSMB->DataCount = 0;
++ pSMB->DataOffset = 0;
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
++ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
++ pSMB->hdr.smb_buf_length += byte_count;
++ pSMB->ByteCount = cpu_to_le16(byte_count);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cFYI(1, ("Send error in QFSInfo = %d", rc));
++ } else { /* decode response */
++ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
++
++ if (rc || (pSMBr->ByteCount < 18))
++ rc = -EIO; /* bad smb */
++ else {
++ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
++ cFYI(1,("qfsinf resp BCC: %d Offset %d",
++ pSMBr->ByteCount, data_offset));
++
++ response_data =
++ (FILE_SYSTEM_ALLOC_INFO *)
++ (((char *) &pSMBr->hdr.Protocol) + data_offset);
++ FSData->f_bsize =
++ le16_to_cpu(response_data->BytesPerSector) *
++ le32_to_cpu(response_data->
++ SectorsPerAllocationUnit);
++ FSData->f_blocks =
++ le32_to_cpu(response_data->TotalAllocationUnits);
++ FSData->f_bfree = FSData->f_bavail =
++ le32_to_cpu(response_data->FreeAllocationUnits);
++ cFYI(1,
++ ("Blocks: %lld Free: %lld Block size %ld",
++ (unsigned long long)FSData->f_blocks,
++ (unsigned long long)FSData->f_bfree,
++ FSData->f_bsize));
++ }
++ }
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto oldQFSInfoRetry;
++
++ return rc;
++}
++
+ int
+ CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
+ {
+@@ -2989,7 +3334,7 @@ QFSInfoRetry:
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+@@ -3012,17 +3357,14 @@ QFSInfoRetry:
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+- cERROR(1, ("Send error in QFSInfo = %d", rc));
++ cFYI(1, ("Send error in QFSInfo = %d", rc));
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+- if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
++ if (rc || (pSMBr->ByteCount < 24))
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+- cFYI(1,
+- ("Decoding qfsinfo response. BCC: %d Offset %d",
+- pSMBr->ByteCount, data_offset));
+
+ response_data =
+ (FILE_SYSTEM_INFO
+@@ -3257,6 +3599,77 @@ QFSUnixRetry:
+ return rc;
+ }
+
++int
++CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
++{
++/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
++ TRANSACTION2_SETFSI_REQ *pSMB = NULL;
++ TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
++ int rc = 0;
++ int bytes_returned = 0;
++ __u16 params, param_offset, offset, byte_count;
++
++ cFYI(1, ("In SETFSUnixInfo"));
++SETFSUnixRetry:
++ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
++ (void **) &pSMBr);
++ if (rc)
++ return rc;
++
++ params = 4; /* 2 bytes zero followed by info level. */
++ pSMB->MaxSetupCount = 0;
++ pSMB->Reserved = 0;
++ pSMB->Flags = 0;
++ pSMB->Timeout = 0;
++ pSMB->Reserved2 = 0;
++ param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
++ offset = param_offset + params;
++
++ pSMB->MaxParameterCount = cpu_to_le16(4);
++ pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
++ pSMB->SetupCount = 1;
++ pSMB->Reserved3 = 0;
++ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
++ byte_count = 1 /* pad */ + params + 12;
++
++ pSMB->DataCount = cpu_to_le16(12);
++ pSMB->ParameterCount = cpu_to_le16(params);
++ pSMB->TotalDataCount = pSMB->DataCount;
++ pSMB->TotalParameterCount = pSMB->ParameterCount;
++ pSMB->ParameterOffset = cpu_to_le16(param_offset);
++ pSMB->DataOffset = cpu_to_le16(offset);
++
++ /* Params. */
++ pSMB->FileNum = 0;
++ pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
++
++ /* Data. */
++ pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
++ pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
++ pSMB->ClientUnixCap = cpu_to_le64(cap);
++
++ pSMB->hdr.smb_buf_length += byte_count;
++ pSMB->ByteCount = cpu_to_le16(byte_count);
++
++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
++ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
++ if (rc) {
++ cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
++ } else { /* decode response */
++ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
++ if (rc) {
++ rc = -EIO; /* bad smb */
++ }
++ }
++ cifs_buf_release(pSMB);
++
++ if (rc == -EAGAIN)
++ goto SETFSUnixRetry;
++
++ return rc;
++}
++
++
+
+ int
+ CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
+@@ -3321,16 +3734,16 @@ QFSPosixRetry:
+ le64_to_cpu(response_data->TotalBlocks);
+ FSData->f_bfree =
+ le64_to_cpu(response_data->BlocksAvail);
+- if(response_data->UserBlocksAvail == -1) {
++ if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
+ FSData->f_bavail = FSData->f_bfree;
+ } else {
+ FSData->f_bavail =
+ le64_to_cpu(response_data->UserBlocksAvail);
+ }
+- if(response_data->TotalFileNodes != -1)
++ if(response_data->TotalFileNodes != cpu_to_le64(-1))
+ FSData->f_files =
+ le64_to_cpu(response_data->TotalFileNodes);
+- if(response_data->FreeFileNodes != -1)
++ if(response_data->FreeFileNodes != cpu_to_le64(-1))
+ FSData->f_ffree =
+ le64_to_cpu(response_data->FreeFileNodes);
+ }
+@@ -3376,7 +3789,7 @@ SetEOFRetry:
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+- } else { /* BB improve the check for buffer overruns BB */
++ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+@@ -3384,7 +3797,7 @@ SetEOFRetry:
+ params = 6 + name_len;
+ data_count = sizeof (struct file_end_of_file_info);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
++ pSMB->MaxDataCount = cpu_to_le16(4100);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+@@ -3766,7 +4179,7 @@ setPermsRetry:
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+- } else { /* BB improve the check for buffer overruns BB */
++ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, fileName, name_len);
+@@ -3839,12 +4252,14 @@ setPermsRetry:
+ }
+
+ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
+- const int notify_subdirs, const __u16 netfid,
+- __u32 filter, const struct nls_table *nls_codepage)
++ const int notify_subdirs, const __u16 netfid,
++ __u32 filter, struct file * pfile, int multishot,
++ const struct nls_table *nls_codepage)
+ {
+ int rc = 0;
+ struct smb_com_transaction_change_notify_req * pSMB = NULL;
+ struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
++ struct dir_notify_req *dnotify_req;
+ int bytes_returned;
+
+ cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
+@@ -3877,6 +4292,28 @@ int CIFSSMBNotify(const int xid, struct
+ (struct smb_hdr *) pSMBr, &bytes_returned, -1);
+ if (rc) {
+ cFYI(1, ("Error in Notify = %d", rc));
++ } else {
++ /* Add file to outstanding requests */
++ /* BB change to kmem cache alloc */
++ dnotify_req = (struct dir_notify_req *) kmalloc(
++ sizeof(struct dir_notify_req),
++ GFP_KERNEL);
++ if(dnotify_req) {
++ dnotify_req->Pid = pSMB->hdr.Pid;
++ dnotify_req->PidHigh = pSMB->hdr.PidHigh;
++ dnotify_req->Mid = pSMB->hdr.Mid;
++ dnotify_req->Tid = pSMB->hdr.Tid;
++ dnotify_req->Uid = pSMB->hdr.Uid;
++ dnotify_req->netfid = netfid;
++ dnotify_req->pfile = pfile;
++ dnotify_req->filter = filter;
++ dnotify_req->multishot = multishot;
++ spin_lock(&GlobalMid_Lock);
++ list_add_tail(&dnotify_req->lhead,
++ &GlobalDnotifyReqList);
++ spin_unlock(&GlobalMid_Lock);
++ } else
++ rc = -ENOMEM;
+ }
+ cifs_buf_release(pSMB);
+ return rc;
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -29,6 +29,8 @@
+ #include <linux/utsname.h>
+ #include <linux/mempool.h>
+ #include <linux/delay.h>
++#include <linux/completion.h>
++#include <linux/pagevec.h>
+ #include <asm/uaccess.h>
+ #include <asm/processor.h>
+ #include "cifspdu.h"
+@@ -44,6 +46,8 @@
+ #define CIFS_PORT 445
+ #define RFC1001_PORT 139
+
++static DECLARE_COMPLETION(cifsd_complete);
++
+ extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
+ unsigned char *p24);
+ extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
+@@ -60,6 +64,7 @@ struct smb_vol {
+ char *in6_addr; /* ipv6 address as human readable form of in6_addr */
+ char *iocharset; /* local code page for mapping to and from Unicode */
+ char source_rfc1001_name[16]; /* netbios name of client */
++ char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
+ uid_t linux_uid;
+ gid_t linux_gid;
+ mode_t file_mode;
+@@ -74,6 +79,10 @@ struct smb_vol {
+ unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
+ unsigned direct_io:1;
+ unsigned remap:1; /* set to remap seven reserved chars in filenames */
++ unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
++ unsigned sfu_emul:1;
++ unsigned nocase; /* request case insensitive filenames */
++ unsigned nobrl; /* disable sending byte range locks to srv */
+ unsigned int rsize;
+ unsigned int wsize;
+ unsigned int sockopt;
+@@ -82,7 +91,8 @@ struct smb_vol {
+
+ static int ipv4_connect(struct sockaddr_in *psin_server,
+ struct socket **csocket,
+- char * netb_name);
++ char * netb_name,
++ char * server_netb_name);
+ static int ipv6_connect(struct sockaddr_in6 *psin_server,
+ struct socket **csocket);
+
+@@ -175,9 +185,11 @@ cifs_reconnect(struct TCP_Server_Info *s
+ } else {
+ rc = ipv4_connect(&server->addr.sockAddr,
+ &server->ssocket,
+- server->workstation_RFC1001_name);
++ server->workstation_RFC1001_name,
++ server->server_RFC1001_name);
+ }
+ if(rc) {
++ cFYI(1,("reconnect error %d",rc));
+ msleep(3000);
+ } else {
+ atomic_inc(&tcpSesReconnectCount);
+@@ -293,12 +305,12 @@ static int coalesce_t2(struct smb_hdr *
+ byte_count += total_in_buf2;
+ BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
+
+- byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
++ byte_count = pTargetSMB->smb_buf_length;
+ byte_count += total_in_buf2;
+
+ /* BB also add check that we are not beyond maximum buffer size */
+
+- pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
++ pTargetSMB->smb_buf_length = byte_count;
+
+ if(remaining == total_in_buf2) {
+ cFYI(1,("found the last secondary response"));
+@@ -323,7 +335,7 @@ cifs_demultiplex_thread(struct TCP_Serve
+ struct cifsSesInfo *ses;
+ struct task_struct *task_to_wake = NULL;
+ struct mid_q_entry *mid_entry;
+- char *temp;
++ char temp;
+ int isLargeBuf = FALSE;
+ int isMultiRsp;
+ int reconnect;
+@@ -337,6 +349,7 @@ cifs_demultiplex_thread(struct TCP_Serve
+ atomic_inc(&tcpSesAllocCount);
+ length = tcpSesAllocCount.counter;
+ write_unlock(&GlobalSMBSeslock);
++ complete(&cifsd_complete);
+ if(length > 1) {
+ mempool_resize(cifs_req_poolp,
+ length + cifs_min_rcv,
+@@ -424,22 +437,32 @@ cifs_demultiplex_thread(struct TCP_Serve
+ continue;
+ }
+
+- /* the right amount was read from socket - 4 bytes */
++ /* The right amount was read from socket - 4 bytes */
++ /* so we can now interpret the length field */
+
++ /* the first byte big endian of the length field,
++ is actually not part of the length but the type
++ with the most common, zero, as regular data */
++ temp = *((char *) smb_buffer);
++
++ /* Note that FC 1001 length is big endian on the wire,
++ but we convert it here so it is always manipulated
++ as host byte order */
+ pdu_length = ntohl(smb_buffer->smb_buf_length);
+- cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
++ smb_buffer->smb_buf_length = pdu_length;
++
++ cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
+
+- temp = (char *) smb_buffer;
+- if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
++ if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
+ continue;
+- } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
++ } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
+ cFYI(1,("Good RFC 1002 session rsp"));
+ continue;
+- } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
++ } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
+ /* we get this from Windows 98 instead of
+ an error on SMB negprot response */
+ cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
+- temp[4]));
++ pdu_length));
+ if(server->tcpStatus == CifsNew) {
+ /* if nack on negprot (rather than
+ ret of smb negprot error) reconnecting
+@@ -461,9 +484,10 @@ cifs_demultiplex_thread(struct TCP_Serve
+ wake_up(&server->response_q);
+ continue;
+ }
+- } else if (temp[0] != (char) 0) {
++ } else if (temp != (char) 0) {
+ cERROR(1,("Unknown RFC 1002 frame"));
+- cifs_dump_mem(" Received Data: ", temp, length);
++ cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
++ length);
+ cifs_reconnect(server);
+ csocket = server->ssocket;
+ continue;
+@@ -533,7 +557,7 @@ cifs_demultiplex_thread(struct TCP_Serve
+
+ dump_smb(smb_buffer, length);
+ if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
+- cERROR(1, ("Bad SMB Received "));
++ cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
+ continue;
+ }
+
+@@ -581,6 +605,9 @@ cifs_demultiplex_thread(struct TCP_Serve
+ multi_t2_fnd:
+ task_to_wake = mid_entry->tsk;
+ mid_entry->midState = MID_RESPONSE_RECEIVED;
++#ifdef CONFIG_CIFS_STATS2
++ mid_entry->when_received = jiffies;
++#endif
+ break;
+ }
+ }
+@@ -598,7 +625,8 @@ multi_t2_fnd:
+ } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
+ && (isMultiRsp == FALSE)) {
+ cERROR(1, ("No task to wake, unknown frame rcvd!"));
+- cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
++ cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
++ sizeof(struct smb_hdr));
+ }
+ } /* end while !EXITING */
+
+@@ -676,7 +704,7 @@ multi_t2_fnd:
+ msleep(125);
+ }
+
+- if (list_empty(&server->pending_mid_q)) {
++ if (!list_empty(&server->pending_mid_q)) {
+ /* mpx threads have not exited yet give them
+ at least the smb send timeout time for long ops */
+ /* due to delays on oplock break requests, we need
+@@ -713,7 +741,7 @@ multi_t2_fnd:
+ GFP_KERNEL);
+ }
+
+- msleep(250);
++ complete_and_exit(&cifsd_complete, 0);
+ return 0;
+ }
+
+@@ -737,7 +765,9 @@ cifs_parse_mount_options(char *options,
+ toupper(system_utsname.nodename[i]);
+ }
+ vol->source_rfc1001_name[15] = 0;
+-
++ /* null target name indicates to use *SMBSERVR default called name
++ if we end up sending RFC1001 session initialize */
++ vol->target_rfc1001_name[0] = 0;
+ vol->linux_uid = current->uid; /* current->euid instead? */
+ vol->linux_gid = current->gid;
+ vol->dir_mode = S_IRWXUGO;
+@@ -747,6 +777,9 @@ cifs_parse_mount_options(char *options,
+ /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
+ vol->rw = TRUE;
+
++ /* default is always to request posix paths. */
++ vol->posix_paths = 1;
++
+ if (!options)
+ return 1;
+
+@@ -987,7 +1020,31 @@ cifs_parse_mount_options(char *options,
+ /* The string has 16th byte zero still from
+ set at top of the function */
+ if((i==15) && (value[i] != 0))
+- printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
++ printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
++ }
++ } else if (strnicmp(data, "servern", 7) == 0) {
++ /* servernetbiosname specified override *SMBSERVER */
++ if (!value || !*value || (*value == ' ')) {
++ cFYI(1,("empty server netbiosname specified"));
++ } else {
++ /* last byte, type, is 0x20 for servr type */
++ memset(vol->target_rfc1001_name,0x20,16);
++
++ for(i=0;i<15;i++) {
++ /* BB are there cases in which a comma can be
++ valid in this workstation netbios name (and need
++ special handling)? */
++
++ /* user or mount helper must uppercase netbiosname */
++ if (value[i]==0)
++ break;
++ else
++ vol->target_rfc1001_name[i] = value[i];
++ }
++ /* The string has 16th byte zero still from
++ set at top of the function */
++ if((i==15) && (value[i] != 0))
++ printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
+ }
+ } else if (strnicmp(data, "credentials", 4) == 0) {
+ /* ignore */
+@@ -1025,6 +1082,27 @@ cifs_parse_mount_options(char *options,
+ vol->remap = 1;
+ } else if (strnicmp(data, "nomapchars", 10) == 0) {
+ vol->remap = 0;
++ } else if (strnicmp(data, "sfu", 3) == 0) {
++ vol->sfu_emul = 1;
++ } else if (strnicmp(data, "nosfu", 5) == 0) {
++ vol->sfu_emul = 0;
++ } else if (strnicmp(data, "posixpaths", 10) == 0) {
++ vol->posix_paths = 1;
++ } else if (strnicmp(data, "noposixpaths", 12) == 0) {
++ vol->posix_paths = 0;
++ } else if ((strnicmp(data, "nocase", 6) == 0) ||
++ (strnicmp(data, "ignorecase", 10) == 0)) {
++ vol->nocase = 1;
++ } else if (strnicmp(data, "brl", 3) == 0) {
++ vol->nobrl = 0;
++ } else if ((strnicmp(data, "nobrl", 5) == 0) ||
++ (strnicmp(data, "nolock", 6) == 0)) {
++ vol->nobrl = 1;
++ /* turn off mandatory locking in mode
++ if remote locking is turned off since the
++ local vfs will do advisory */
++ if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
++ vol->file_mode = S_IALLUGO;
+ } else if (strnicmp(data, "setuids", 7) == 0) {
+ vol->setuids = 1;
+ } else if (strnicmp(data, "nosetuids", 9) == 0) {
+@@ -1244,7 +1322,7 @@ static void rfc1002mangle(char * target,
+
+ static int
+ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
+- char * netbios_name)
++ char * netbios_name, char * target_name)
+ {
+ int rc = 0;
+ int connected = 0;
+@@ -1309,10 +1387,16 @@ ipv4_connect(struct sockaddr_in *psin_se
+ /* Eventually check for other socket options to change from
+ the default. sock_setsockopt not used because it expects
+ user space buffer */
++ cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
++ (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
+ (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
++ /* make the bufsizes depend on wsize/rsize and max requests */
++ if((*csocket)->sk->sk_sndbuf < (200 * 1024))
++ (*csocket)->sk->sk_sndbuf = 200 * 1024;
++ if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
++ (*csocket)->sk->sk_rcvbuf = 140 * 1024;
+
+ /* send RFC1001 sessinit */
+-
+ if(psin_server->sin_port == htons(RFC1001_PORT)) {
+ /* some servers require RFC1001 sessinit before sending
+ negprot - BB check reconnection in case where second
+@@ -1322,8 +1406,14 @@ ipv4_connect(struct sockaddr_in *psin_se
+ ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
+ if(ses_init_buf) {
+ ses_init_buf->trailer.session_req.called_len = 32;
+- rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
+- DEFAULT_CIFS_CALLED_NAME,16);
++ if(target_name && (target_name[0] != 0)) {
++ rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
++ target_name, 16);
++ } else {
++ rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
++ DEFAULT_CIFS_CALLED_NAME,16);
++ }
++
+ ses_init_buf->trailer.session_req.calling_len = 32;
+ /* calling name ends in null (byte 16) from old smb
+ convention. */
+@@ -1556,7 +1646,9 @@ cifs_mount(struct super_block *sb, struc
+ sin_server.sin_port = htons(volume_info.port);
+ else
+ sin_server.sin_port = 0;
+- rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
++ rc = ipv4_connect(&sin_server,&csocket,
++ volume_info.source_rfc1001_name,
++ volume_info.target_rfc1001_name);
+ if (rc < 0) {
+ cERROR(1,
+ ("Error connecting to IPv4 socket. Aborting operation"));
+@@ -1606,9 +1698,11 @@ cifs_mount(struct super_block *sb, struc
+ kfree(volume_info.password);
+ FreeXid(xid);
+ return rc;
+- } else
+- rc = 0;
++ }
++ wait_for_completion(&cifsd_complete);
++ rc = 0;
+ memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
++ memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
+ srvTcp->sequence_number = 0;
+ }
+ }
+@@ -1653,17 +1747,27 @@ cifs_mount(struct super_block *sb, struc
+
+ /* search for existing tcon to this server share */
+ if (!rc) {
+- if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
++ if(volume_info.rsize > CIFSMaxBufSize) {
++ cERROR(1,("rsize %d too large, using MaxBufSize",
++ volume_info.rsize));
++ cifs_sb->rsize = CIFSMaxBufSize;
++ } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
+ cifs_sb->rsize = volume_info.rsize;
+- else
+- cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+- if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
++ else /* default */
++ cifs_sb->rsize = CIFSMaxBufSize;
++
++ if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
++ cERROR(1,("wsize %d too large using 4096 instead",
++ volume_info.wsize));
++ cifs_sb->wsize = 4096;
++ } else if(volume_info.wsize)
+ cifs_sb->wsize = volume_info.wsize;
+ else
+ cifs_sb->wsize = CIFSMaxBufSize; /* default */
+ if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
+- cifs_sb->rsize = PAGE_CACHE_SIZE;
+- cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
++ cifs_sb->rsize = PAGE_CACHE_SIZE;
++ /* Windows ME does this */
++ cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
+ }
+ cifs_sb->mnt_uid = volume_info.linux_uid;
+ cifs_sb->mnt_gid = volume_info.linux_gid;
+@@ -1681,8 +1785,13 @@ cifs_mount(struct super_block *sb, struc
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
+ if(volume_info.no_xattr)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
++ if(volume_info.sfu_emul)
++ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
++ if(volume_info.nobrl)
++ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
++
+ if(volume_info.direct_io) {
+- cERROR(1,("mounting share using direct i/o"));
++ cFYI(1,("mounting share using direct i/o"));
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
+ }
+
+@@ -1696,6 +1805,7 @@ cifs_mount(struct super_block *sb, struc
+ to the same server share the last value passed in
+ for the retry flag is used */
+ tcon->retry = volume_info.retry;
++ tcon->nocase = volume_info.nocase;
+ } else {
+ tcon = tconInfoAlloc();
+ if (tcon == NULL)
+@@ -1724,6 +1834,7 @@ cifs_mount(struct super_block *sb, struc
+ if (!rc) {
+ atomic_inc(&pSesInfo->inUse);
+ tcon->retry = volume_info.retry;
++ tcon->nocase = volume_info.nocase;
+ }
+ }
+ }
+@@ -1745,8 +1856,10 @@ cifs_mount(struct super_block *sb, struc
+ spin_lock(&GlobalMid_Lock);
+ srvTcp->tcpStatus = CifsExiting;
+ spin_unlock(&GlobalMid_Lock);
+- if(srvTcp->tsk)
++ if(srvTcp->tsk) {
+ send_sig(SIGKILL,srvTcp->tsk,1);
++ wait_for_completion(&cifsd_complete);
++ }
+ }
+ /* If find_unc succeeded then rc == 0 so we can not end */
+ if (tcon) /* up accidently freeing someone elses tcon struct */
+@@ -1759,8 +1872,10 @@ cifs_mount(struct super_block *sb, struc
+ temp_rc = CIFSSMBLogoff(xid, pSesInfo);
+ /* if the socketUseCount is now zero */
+ if((temp_rc == -ESHUTDOWN) &&
+- (pSesInfo->server->tsk))
++ (pSesInfo->server->tsk)) {
+ send_sig(SIGKILL,pSesInfo->server->tsk,1);
++ wait_for_completion(&cifsd_complete);
++ }
+ } else
+ cFYI(1, ("No session or bad tcon"));
+ sesInfoFree(pSesInfo);
+@@ -1783,8 +1898,27 @@ cifs_mount(struct super_block *sb, struc
+ cFYI(1,("server negotiated posix acl support"));
+ sb->s_flags |= MS_POSIXACL;
+ }
++
++ /* Try and negotiate POSIX pathnames if we can. */
++ if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
++ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
++ if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
++ cFYI(1,("negotiated posix pathnames support"));
++ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
++ } else {
++ cFYI(1,("posix pathnames support requested but not supported"));
++ }
++ }
+ }
+ }
++ if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
++ cifs_sb->wsize = min(cifs_sb->wsize,
++ (tcon->ses->server->maxBuf -
++ MAX_CIFS_HDR_SIZE));
++ if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
++ cifs_sb->rsize = min(cifs_sb->rsize,
++ (tcon->ses->server->maxBuf -
++ MAX_CIFS_HDR_SIZE));
+ }
+
+ /* volume_info.password is freed above when existing session found
+@@ -1832,6 +1966,7 @@ CIFSSessSetup(unsigned int xid, struct c
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 13 /* wct */ );
+
++ smb_buffer->Mid = GetNextMid(ses->server);
+ pSMB->req_no_secext.AndXCommand = 0xFF;
+ pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+ pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+@@ -2107,6 +2242,8 @@ CIFSSpnegoSessSetup(unsigned int xid, st
+ /* send SMBsessionSetup here */
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 12 /* wct */ );
++
++ smb_buffer->Mid = GetNextMid(ses->server);
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ pSMB->req.AndXCommand = 0xFF;
+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+@@ -2373,6 +2510,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i
+ /* send SMBsessionSetup here */
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 12 /* wct */ );
++
++ smb_buffer->Mid = GetNextMid(ses->server);
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
+
+@@ -2715,6 +2854,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi
+ /* send SMBsessionSetup here */
+ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+ NULL /* no tCon exists yet */ , 12 /* wct */ );
++
++ smb_buffer->Mid = GetNextMid(ses->server);
+ pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ pSMB->req.AndXCommand = 0xFF;
+@@ -3086,6 +3227,8 @@ CIFSTCon(unsigned int xid, struct cifsSe
+
+ header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
+ NULL /*no tid */ , 4 /*wct */ );
++
++ smb_buffer->Mid = GetNextMid(ses->server);
+ smb_buffer->Uid = ses->Suid;
+ pSMB = (TCONX_REQ *) smb_buffer;
+ pSMBr = (TCONX_RSP *) smb_buffer_response;
+@@ -3207,8 +3350,10 @@ cifs_umount(struct super_block *sb, stru
+ return 0;
+ } else if (rc == -ESHUTDOWN) {
+ cFYI(1,("Waking up socket by sending it signal"));
+- if(cifsd_task)
++ if(cifsd_task) {
+ send_sig(SIGKILL,cifsd_task,1);
++ wait_for_completion(&cifsd_complete);
++ }
+ rc = 0;
+ } /* else - we have an smb session
+ left on this socket do not kill cifsd */
+diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
+--- a/fs/cifs/dir.c
++++ b/fs/cifs/dir.c
+@@ -48,6 +48,7 @@ build_path_from_dentry(struct dentry *di
+ struct dentry *temp;
+ int namelen = 0;
+ char *full_path;
++ char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
+
+ if(direntry == NULL)
+ return NULL; /* not much we can do if dentry is freed and
+@@ -74,7 +75,7 @@ cifs_bp_rename_retry:
+ if (namelen < 0) {
+ break;
+ } else {
+- full_path[namelen] = '\\';
++ full_path[namelen] = dirsep;
+ strncpy(full_path + namelen + 1, temp->d_name.name,
+ temp->d_name.len);
+ cFYI(0, (" name: %s ", full_path + namelen));
+@@ -183,6 +184,13 @@ cifs_create(struct inode *inode, struct
+ desiredAccess, CREATE_NOT_DIR,
+ &fileHandle, &oplock, buf, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
++ if(rc == -EIO) {
++ /* old server, retry the open legacy style */
++ rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
++ desiredAccess, CREATE_NOT_DIR,
++ &fileHandle, &oplock, buf, cifs_sb->local_nls,
++ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
++ }
+ if (rc) {
+ cFYI(1, ("cifs_create returned 0x%x ", rc));
+ } else {
+@@ -208,7 +216,7 @@ cifs_create(struct inode *inode, struct
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ }
+ else {
+- /* BB implement via Windows security descriptors */
++ /* BB implement mode setting via Windows security descriptors */
+ /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
+ /* could set r/o dos attribute if mode & 0222 == 0 */
+ }
+@@ -225,10 +233,14 @@ cifs_create(struct inode *inode, struct
+ }
+
+ if (rc != 0) {
+- cFYI(1,("Create worked but get_inode_info failed with rc = %d",
++ cFYI(1,
++ ("Create worked but get_inode_info failed rc = %d",
+ rc));
+ } else {
+- direntry->d_op = &cifs_dentry_ops;
++ if (pTcon->nocase)
++ direntry->d_op = &cifs_ci_dentry_ops;
++ else
++ direntry->d_op = &cifs_dentry_ops;
+ d_instantiate(direntry, newinode);
+ }
+ if((nd->flags & LOOKUP_OPEN) == FALSE) {
+@@ -302,8 +314,7 @@ int cifs_mknod(struct inode *inode, stru
+ up(&direntry->d_sb->s_vfs_rename_sem);
+ if(full_path == NULL)
+ rc = -ENOMEM;
+-
+- if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
++ else if (pTcon->ses->capabilities & CAP_UNIX) {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ mode,(__u64)current->euid,(__u64)current->egid,
+@@ -321,10 +332,49 @@ int cifs_mknod(struct inode *inode, stru
+ if(!rc) {
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb,xid);
+- direntry->d_op = &cifs_dentry_ops;
++ if (pTcon->nocase)
++ direntry->d_op = &cifs_ci_dentry_ops;
++ else
++ direntry->d_op = &cifs_dentry_ops;
+ if(rc == 0)
+ d_instantiate(direntry, newinode);
+ }
++ } else {
++ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
++ int oplock = 0;
++ u16 fileHandle;
++ FILE_ALL_INFO * buf;
++
++ cFYI(1,("sfu compat create special file"));
++
++ buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
++ if(buf == NULL) {
++ kfree(full_path);
++ FreeXid(xid);
++ return -ENOMEM;
++ }
++
++ rc = CIFSSMBOpen(xid, pTcon, full_path,
++ FILE_CREATE, /* fail if exists */
++ GENERIC_WRITE /* BB would
++ WRITE_OWNER | WRITE_DAC be better? */,
++ /* Create a file and set the
++ file attribute to SYSTEM */
++ CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
++ &fileHandle, &oplock, buf,
++ cifs_sb->local_nls,
++ cifs_sb->mnt_cifs_flags &
++ CIFS_MOUNT_MAP_SPECIAL_CHR);
++
++ if(!rc) {
++ /* BB Do not bother to decode buf since no
++ local inode yet to put timestamps in */
++ CIFSSMBClose(xid, pTcon, fileHandle);
++ d_drop(direntry);
++ }
++ kfree(buf);
++ /* add code here to set EAs */
++ }
+ }
+
+ kfree(full_path);
+@@ -381,7 +431,10 @@ cifs_lookup(struct inode *parent_dir_ino
+ parent_dir_inode->i_sb,xid);
+
+ if ((rc == 0) && (newInode != NULL)) {
+- direntry->d_op = &cifs_dentry_ops;
++ if (pTcon->nocase)
++ direntry->d_op = &cifs_ci_dentry_ops;
++ else
++ direntry->d_op = &cifs_dentry_ops;
+ d_add(direntry, newInode);
+
+ /* since paths are not looked up by component - the parent directories are presumed to be good here */
+@@ -440,3 +493,42 @@ struct dentry_operations cifs_dentry_ops
+ /* d_delete: cifs_d_delete, *//* not needed except for debugging */
+ /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
+ };
++
++static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
++{
++ struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
++ unsigned long hash;
++ int i;
++
++ hash = init_name_hash();
++ for (i = 0; i < q->len; i++)
++ hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
++ hash);
++ q->hash = end_name_hash(hash);
++
++ return 0;
++}
++
++static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
++ struct qstr *b)
++{
++ struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
++
++ if ((a->len == b->len) &&
++ (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
++ /*
++ * To preserve case, don't let an existing negative dentry's
++ * case take precedence. If a is not a negative dentry, this
++ * should have no side effects
++ */
++ memcpy((unsigned char *)a->name, b->name, a->len);
++ return 0;
++ }
++ return 1;
++}
++
++struct dentry_operations cifs_ci_dentry_ops = {
++ .d_revalidate = cifs_d_revalidate,
++ .d_hash = cifs_ci_hash,
++ .d_compare = cifs_ci_compare,
++};
+diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
+--- a/fs/cifs/fcntl.c
++++ b/fs/cifs/fcntl.c
+@@ -78,6 +78,10 @@ int cifs_dir_notify(struct file * file,
+ __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
+ __u16 netfid;
+
++
++ if(experimEnabled == 0)
++ return 0;
++
+ xid = GetXid();
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+@@ -100,8 +104,10 @@ int cifs_dir_notify(struct file * file,
+ } else {
+ filter = convert_to_cifs_notify_flags(arg);
+ if(filter != 0) {
+- rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid,
+- filter, cifs_sb->local_nls);
++ rc = CIFSSMBNotify(xid, pTcon,
++ 0 /* no subdirs */, netfid,
++ filter, file, arg & DN_MULTISHOT,
++ cifs_sb->local_nls);
+ } else {
+ rc = -EINVAL;
+ }
+@@ -109,7 +115,7 @@ int cifs_dir_notify(struct file * file,
+ it would close automatically but may be a way
+ to do it easily when inode freed or when
+ notify info is cleared/changed */
+- cERROR(1,("notify rc %d",rc));
++ cFYI(1,("notify rc %d",rc));
+ }
+ }
+
+diff --git a/fs/cifs/file.c b/fs/cifs/file.c
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -21,11 +21,15 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+ #include <linux/fs.h>
++#include <linux/backing-dev.h>
+ #include <linux/stat.h>
+ #include <linux/fcntl.h>
++#include <linux/mpage.h>
+ #include <linux/pagemap.h>
+ #include <linux/pagevec.h>
+ #include <linux/smp_lock.h>
++#include <linux/writeback.h>
++#include <linux/delay.h>
+ #include <asm/div64.h>
+ #include "cifsfs.h"
+ #include "cifspdu.h"
+@@ -47,6 +51,11 @@ static inline struct cifsFileInfo *cifs_
+ private_data->pInode = inode;
+ private_data->invalidHandle = FALSE;
+ private_data->closePend = FALSE;
++ /* we have to track num writers to the inode, since writepages
++ does not tell us which handle the write is for so there can
++ be a close (overlapping with write) of the filehandle that
++ cifs_writepages chose to use */
++ atomic_set(&private_data->wrtPending,0);
+
+ return private_data;
+ }
+@@ -256,6 +265,13 @@ int cifs_open(struct inode *inode, struc
+ CREATE_NOT_DIR, &netfid, &oplock, buf,
+ cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
+ & CIFS_MOUNT_MAP_SPECIAL_CHR);
++ if (rc == -EIO) {
++ /* Old server, try legacy style OpenX */
++ rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
++ desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
++ cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
++ & CIFS_MOUNT_MAP_SPECIAL_CHR);
++ }
+ if (rc) {
+ cFYI(1, ("cifs_open returned 0x%x ", rc));
+ goto out;
+@@ -463,6 +479,20 @@ int cifs_close(struct inode *inode, stru
+ /* no sense reconnecting to close a file that is
+ already closed */
+ if (pTcon->tidStatus != CifsNeedReconnect) {
++ int timeout = 2;
++ while((atomic_read(&pSMBFile->wrtPending) != 0)
++ && (timeout < 1000) ) {
++ /* Give write a better chance to get to
++ server ahead of the close. We do not
++ want to add a wait_q here as it would
++ increase the memory utilization as
++ the struct would be in each open file,
++ but this should give enough time to
++ clear the socket */
++ cERROR(1,("close with pending writes"));
++ msleep(timeout);
++ timeout *= 4;
++ }
+ write_unlock(&file->f_owner.lock);
+ rc = CIFSSMBClose(xid, pTcon,
+ pSMBFile->netfid);
+@@ -744,14 +774,7 @@ ssize_t cifs_user_write(struct file *fil
+ 15 seconds is plenty */
+ }
+
+-#ifdef CONFIG_CIFS_STATS
+- if (total_written > 0) {
+- atomic_inc(&pTcon->num_writes);
+- spin_lock(&pTcon->stat_lock);
+- pTcon->bytes_written += total_written;
+- spin_unlock(&pTcon->stat_lock);
+- }
+-#endif
++ cifs_stats_bytes_written(pTcon, total_written);
+
+ /* since the write may have blocked check these pointers again */
+ if (file->f_dentry) {
+@@ -791,9 +814,8 @@ static ssize_t cifs_write(struct file *f
+
+ pTcon = cifs_sb->tcon;
+
+- /* cFYI(1,
+- (" write %d bytes to offset %lld of %s", write_size,
+- *poffset, file->f_dentry->d_name.name)); */
++ cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
++ *poffset, file->f_dentry->d_name.name));
+
+ if (file->private_data == NULL)
+ return -EBADF;
+@@ -846,7 +868,26 @@ static ssize_t cifs_write(struct file *f
+ if (rc != 0)
+ break;
+ }
+-
++#ifdef CONFIG_CIFS_EXPERIMENTAL
++ /* BB FIXME We can not sign across two buffers yet */
++ if((experimEnabled) && ((pTcon->ses->server->secMode &
++ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
++ struct kvec iov[2];
++ unsigned int len;
++
++ len = min((size_t)cifs_sb->wsize,
++ write_size - total_written);
++ /* iov[0] is reserved for smb header */
++ iov[1].iov_base = (char *)write_data +
++ total_written;
++ iov[1].iov_len = len;
++ rc = CIFSSMBWrite2(xid, pTcon,
++ open_file->netfid, len,
++ *poffset, &bytes_written,
++ iov, 1, long_op);
++ } else
++ /* BB FIXME fixup indentation of line below */
++#endif
+ rc = CIFSSMBWrite(xid, pTcon,
+ open_file->netfid,
+ min_t(const int, cifs_sb->wsize,
+@@ -867,14 +908,7 @@ static ssize_t cifs_write(struct file *f
+ 15 seconds is plenty */
+ }
+
+-#ifdef CONFIG_CIFS_STATS
+- if (total_written > 0) {
+- atomic_inc(&pTcon->num_writes);
+- spin_lock(&pTcon->stat_lock);
+- pTcon->bytes_written += total_written;
+- spin_unlock(&pTcon->stat_lock);
+- }
+-#endif
++ cifs_stats_bytes_written(pTcon, total_written);
+
+ /* since the write may have blocked check these pointers again */
+ if (file->f_dentry) {
+@@ -893,6 +927,43 @@ static ssize_t cifs_write(struct file *f
+ return total_written;
+ }
+
++struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
++{
++ struct cifsFileInfo *open_file;
++ int rc;
++
++ read_lock(&GlobalSMBSeslock);
++ list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
++ if (open_file->closePend)
++ continue;
++ if (open_file->pfile &&
++ ((open_file->pfile->f_flags & O_RDWR) ||
++ (open_file->pfile->f_flags & O_WRONLY))) {
++ atomic_inc(&open_file->wrtPending);
++ read_unlock(&GlobalSMBSeslock);
++ if((open_file->invalidHandle) &&
++ (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
++ rc = cifs_reopen_file(&cifs_inode->vfs_inode,
++ open_file->pfile, FALSE);
++ /* if it fails, try another handle - might be */
++ /* dangerous to hold up writepages with retry */
++ if(rc) {
++ cFYI(1,("failed on reopen file in wp"));
++ read_lock(&GlobalSMBSeslock);
++ /* can not use this handle, no write
++ pending on this one after all */
++ atomic_dec
++ (&open_file->wrtPending);
++ continue;
++ }
++ }
++ return open_file;
++ }
++ }
++ read_unlock(&GlobalSMBSeslock);
++ return NULL;
++}
++
+ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
+ {
+ struct address_space *mapping = page->mapping;
+@@ -903,10 +974,7 @@ static int cifs_partialpagewrite(struct
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ struct inode *inode;
+- struct cifsInodeInfo *cifsInode;
+- struct cifsFileInfo *open_file = NULL;
+- struct list_head *tmp;
+- struct list_head *tmp1;
++ struct cifsFileInfo *open_file;
+
+ if (!mapping || !mapping->host)
+ return -EFAULT;
+@@ -934,49 +1002,20 @@ static int cifs_partialpagewrite(struct
+ if (mapping->host->i_size - offset < (loff_t)to)
+ to = (unsigned)(mapping->host->i_size - offset);
+
+- cifsInode = CIFS_I(mapping->host);
+- read_lock(&GlobalSMBSeslock);
+- /* BB we should start at the end */
+- list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
+- open_file = list_entry(tmp, struct cifsFileInfo, flist);
+- if (open_file->closePend)
+- continue;
+- /* We check if file is open for writing first */
+- if ((open_file->pfile) &&
+- ((open_file->pfile->f_flags & O_RDWR) ||
+- (open_file->pfile->f_flags & O_WRONLY))) {
+- read_unlock(&GlobalSMBSeslock);
+- bytes_written = cifs_write(open_file->pfile,
+- write_data, to-from,
+- &offset);
+- read_lock(&GlobalSMBSeslock);
++ open_file = find_writable_file(CIFS_I(mapping->host));
++ if (open_file) {
++ bytes_written = cifs_write(open_file->pfile, write_data,
++ to-from, &offset);
++ atomic_dec(&open_file->wrtPending);
+ /* Does mm or vfs already set times? */
+- inode->i_atime =
+- inode->i_mtime = current_fs_time(inode->i_sb);
+- if ((bytes_written > 0) && (offset)) {
+- rc = 0;
+- } else if (bytes_written < 0) {
+- if (rc == -EBADF) {
+- /* have seen a case in which kernel seemed to
+- have closed/freed a file even with writes
+- active so we might as well see if there are
+- other file structs to try for the same
+- inode before giving up */
+- continue;
+- } else
+- rc = bytes_written;
+- }
+- break; /* now that we found a valid file handle and
+- tried to write to it we are done, no sense
+- continuing to loop looking for another */
+- }
+- if (tmp->next == NULL) {
+- cFYI(1, ("File instance %p removed", tmp));
+- break;
++ inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
++ if ((bytes_written > 0) && (offset)) {
++ rc = 0;
++ } else if (bytes_written < 0) {
++ if (rc != -EBADF)
++ rc = bytes_written;
+ }
+- }
+- read_unlock(&GlobalSMBSeslock);
+- if (open_file == NULL) {
++ } else {
+ cFYI(1, ("No writeable filehandles for inode"));
+ rc = -EIO;
+ }
+@@ -985,20 +1024,207 @@ static int cifs_partialpagewrite(struct
+ return rc;
+ }
+
+-#if 0
++#ifdef CONFIG_CIFS_EXPERIMENTAL
+ static int cifs_writepages(struct address_space *mapping,
+- struct writeback_control *wbc)
++ struct writeback_control *wbc)
+ {
+- int rc = -EFAULT;
++ struct backing_dev_info *bdi = mapping->backing_dev_info;
++ unsigned int bytes_to_write;
++ unsigned int bytes_written;
++ struct cifs_sb_info *cifs_sb;
++ int done = 0;
++ pgoff_t end = -1;
++ pgoff_t index;
++ int is_range = 0;
++ struct kvec iov[32];
++ int len;
++ int n_iov = 0;
++ pgoff_t next;
++ int nr_pages;
++ __u64 offset = 0;
++ struct cifsFileInfo *open_file;
++ struct page *page;
++ struct pagevec pvec;
++ int rc = 0;
++ int scanned = 0;
+ int xid;
+
++ cifs_sb = CIFS_SB(mapping->host->i_sb);
++
++ /*
++ * If wsize is smaller that the page cache size, default to writing
++ * one page at a time via cifs_writepage
++ */
++ if (cifs_sb->wsize < PAGE_CACHE_SIZE)
++ return generic_writepages(mapping, wbc);
++
++ /* BB FIXME we do not have code to sign across multiple buffers yet,
++ so go to older writepage style write which we can sign if needed */
++ if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
++ if(cifs_sb->tcon->ses->server->secMode &
++ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
++ return generic_writepages(mapping, wbc);
++
++ /*
++ * BB: Is this meaningful for a non-block-device file system?
++ * If it is, we should test it again after we do I/O
++ */
++ if (wbc->nonblocking && bdi_write_congested(bdi)) {
++ wbc->encountered_congestion = 1;
++ return 0;
++ }
++
+ xid = GetXid();
+
+- /* Find contiguous pages then iterate through repeating
+- call 16K write then Setpageuptodate or if LARGE_WRITE_X
+- support then send larger writes via kevec so as to eliminate
+- a memcpy */
++ pagevec_init(&pvec, 0);
++ if (wbc->sync_mode == WB_SYNC_NONE)
++ index = mapping->writeback_index; /* Start from prev offset */
++ else {
++ index = 0;
++ scanned = 1;
++ }
++ if (wbc->start || wbc->end) {
++ index = wbc->start >> PAGE_CACHE_SHIFT;
++ end = wbc->end >> PAGE_CACHE_SHIFT;
++ is_range = 1;
++ scanned = 1;
++ }
++retry:
++ while (!done && (index <= end) &&
++ (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
++ PAGECACHE_TAG_DIRTY,
++ min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
++ int first;
++ unsigned int i;
++
++ first = -1;
++ next = 0;
++ n_iov = 0;
++ bytes_to_write = 0;
++
++ for (i = 0; i < nr_pages; i++) {
++ page = pvec.pages[i];
++ /*
++ * At this point we hold neither mapping->tree_lock nor
++ * lock on the page itself: the page may be truncated or
++ * invalidated (changing page->mapping to NULL), or even
++ * swizzled back from swapper_space to tmpfs file
++ * mapping
++ */
++
++ if (first < 0)
++ lock_page(page);
++ else if (TestSetPageLocked(page))
++ break;
++
++ if (unlikely(page->mapping != mapping)) {
++ unlock_page(page);
++ break;
++ }
++
++ if (unlikely(is_range) && (page->index > end)) {
++ done = 1;
++ unlock_page(page);
++ break;
++ }
++
++ if (next && (page->index != next)) {
++ /* Not next consecutive page */
++ unlock_page(page);
++ break;
++ }
++
++ if (wbc->sync_mode != WB_SYNC_NONE)
++ wait_on_page_writeback(page);
++
++ if (PageWriteback(page) ||
++ !test_clear_page_dirty(page)) {
++ unlock_page(page);
++ break;
++ }
++
++ if (page_offset(page) >= mapping->host->i_size) {
++ done = 1;
++ unlock_page(page);
++ break;
++ }
++
++ /*
++ * BB can we get rid of this? pages are held by pvec
++ */
++ page_cache_get(page);
++
++ len = min(mapping->host->i_size - page_offset(page),
++ (loff_t)PAGE_CACHE_SIZE);
++
++ /* reserve iov[0] for the smb header */
++ n_iov++;
++ iov[n_iov].iov_base = kmap(page);
++ iov[n_iov].iov_len = len;
++ bytes_to_write += len;
++
++ if (first < 0) {
++ first = i;
++ offset = page_offset(page);
++ }
++ next = page->index + 1;
++ if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
++ break;
++ }
++ if (n_iov) {
++ /* Search for a writable handle every time we call
++ * CIFSSMBWrite2. We can't rely on the last handle
++ * we used to still be valid
++ */
++ open_file = find_writable_file(CIFS_I(mapping->host));
++ if (!open_file) {
++ cERROR(1, ("No writable handles for inode"));
++ rc = -EBADF;
++ } else {
++ rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
++ open_file->netfid,
++ bytes_to_write, offset,
++ &bytes_written, iov, n_iov,
++ 1);
++ atomic_dec(&open_file->wrtPending);
++ if (rc || bytes_written < bytes_to_write) {
++ cERROR(1,("Write2 ret %d, written = %d",
++ rc, bytes_written));
++ /* BB what if continued retry is
++ requested via mount flags? */
++ set_bit(AS_EIO, &mapping->flags);
++ SetPageError(page);
++ } else {
++ cifs_stats_bytes_written(cifs_sb->tcon,
++ bytes_written);
++ }
++ }
++ for (i = 0; i < n_iov; i++) {
++ page = pvec.pages[first + i];
++ kunmap(page);
++ unlock_page(page);
++ page_cache_release(page);
++ }
++ if ((wbc->nr_to_write -= n_iov) <= 0)
++ done = 1;
++ index = next;
++ }
++ pagevec_release(&pvec);
++ }
++ if (!scanned && !done) {
++ /*
++ * We hit the last page and there is more work to be done: wrap
++ * back to the start of the file
++ */
++ scanned = 1;
++ index = 0;
++ goto retry;
++ }
++ if (!is_range)
++ mapping->writeback_index = index;
++
+ FreeXid(xid);
++
+ return rc;
+ }
+ #endif
+@@ -1207,12 +1433,10 @@ ssize_t cifs_user_read(struct file *file
+ if (rc != 0)
+ break;
+ }
+-
+ rc = CIFSSMBRead(xid, pTcon,
+- open_file->netfid,
+- current_read_size, *poffset,
+- &bytes_read, &smb_read_data);
+-
++ open_file->netfid,
++ current_read_size, *poffset,
++ &bytes_read, &smb_read_data);
+ pSMBr = (struct smb_com_read_rsp *)smb_read_data;
+ if (copy_to_user(current_offset,
+ smb_read_data + 4 /* RFC1001 hdr */
+@@ -1235,12 +1459,7 @@ ssize_t cifs_user_read(struct file *file
+ return rc;
+ }
+ } else {
+-#ifdef CONFIG_CIFS_STATS
+- atomic_inc(&pTcon->num_reads);
+- spin_lock(&pTcon->stat_lock);
+- pTcon->bytes_read += total_read;
+- spin_unlock(&pTcon->stat_lock);
+-#endif
++ cifs_stats_bytes_read(pTcon, bytes_read);
+ *poffset += bytes_read;
+ }
+ }
+@@ -1280,6 +1499,13 @@ static ssize_t cifs_read(struct file *fi
+ total_read += bytes_read, current_offset += bytes_read) {
+ current_read_size = min_t(const int, read_size - total_read,
+ cifs_sb->rsize);
++ /* For windows me and 9x we do not want to request more
++ than it negotiated since it will refuse the read then */
++ if((pTcon->ses) &&
++ !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
++ current_read_size = min_t(const int, current_read_size,
++ pTcon->ses->server->maxBuf - 128);
++ }
+ rc = -EAGAIN;
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+@@ -1289,11 +1515,10 @@ static ssize_t cifs_read(struct file *fi
+ if (rc != 0)
+ break;
+ }
+-
+ rc = CIFSSMBRead(xid, pTcon,
+- open_file->netfid,
+- current_read_size, *poffset,
+- &bytes_read, ¤t_offset);
++ open_file->netfid,
++ current_read_size, *poffset,
++ &bytes_read, ¤t_offset);
+ }
+ if (rc || (bytes_read == 0)) {
+ if (total_read) {
+@@ -1303,12 +1528,7 @@ static ssize_t cifs_read(struct file *fi
+ return rc;
+ }
+ } else {
+-#ifdef CONFIG_CIFS_STATS
+- atomic_inc(&pTcon->num_reads);
+- spin_lock(&pTcon->stat_lock);
+- pTcon->bytes_read += total_read;
+- spin_unlock(&pTcon->stat_lock);
+-#endif
++ cifs_stats_bytes_read(pTcon, total_read);
+ *poffset += bytes_read;
+ }
+ }
+@@ -1452,10 +1672,11 @@ static int cifs_readpages(struct file *f
+ }
+
+ rc = CIFSSMBRead(xid, pTcon,
+- open_file->netfid,
+- read_size, offset,
+- &bytes_read, &smb_read_data);
+- /* BB need to check return code here */
++ open_file->netfid,
++ read_size, offset,
++ &bytes_read, &smb_read_data);
++
++ /* BB more RC checks ? */
+ if (rc== -EAGAIN) {
+ if (smb_read_data) {
+ cifs_buf_release(smb_read_data);
+@@ -1480,12 +1701,7 @@ static int cifs_readpages(struct file *f
+ le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
+
+ i += bytes_read >> PAGE_CACHE_SHIFT;
+-#ifdef CONFIG_CIFS_STATS
+- atomic_inc(&pTcon->num_reads);
+- spin_lock(&pTcon->stat_lock);
+- pTcon->bytes_read += bytes_read;
+- spin_unlock(&pTcon->stat_lock);
+-#endif
++ cifs_stats_bytes_read(pTcon, bytes_read);
+ if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
+ i++; /* account for partial page */
+
+@@ -1603,40 +1819,21 @@ static int cifs_readpage(struct file *fi
+ page caching in the current Linux kernel design */
+ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
+ {
+- struct list_head *tmp;
+- struct list_head *tmp1;
+ struct cifsFileInfo *open_file = NULL;
+- int rc = TRUE;
+
+- if (cifsInode == NULL)
+- return rc;
+-
+- read_lock(&GlobalSMBSeslock);
+- list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
+- open_file = list_entry(tmp, struct cifsFileInfo, flist);
+- if (open_file == NULL)
+- break;
+- if (open_file->closePend)
+- continue;
+- /* We check if file is open for writing,
+- BB we could supplement this with a check to see if file size
+- changes have been flushed to server - ie inode metadata dirty */
+- if ((open_file->pfile) &&
+- ((open_file->pfile->f_flags & O_RDWR) ||
+- (open_file->pfile->f_flags & O_WRONLY))) {
+- rc = FALSE;
+- break;
+- }
+- if (tmp->next == NULL) {
+- cFYI(1, ("File instance %p removed", tmp));
+- break;
+- }
+- }
+- read_unlock(&GlobalSMBSeslock);
+- return rc;
++ if (cifsInode)
++ open_file = find_writable_file(cifsInode);
++
++ if(open_file) {
++ /* there is not actually a write pending so let
++ this handle go free and allow it to
++ be closable if needed */
++ atomic_dec(&open_file->wrtPending);
++ return 0;
++ } else
++ return 1;
+ }
+
+-
+ static int cifs_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+ {
+@@ -1676,6 +1873,9 @@ struct address_space_operations cifs_add
+ .readpage = cifs_readpage,
+ .readpages = cifs_readpages,
+ .writepage = cifs_writepage,
++#ifdef CONFIG_CIFS_EXPERIMENTAL
++ .writepages = cifs_writepages,
++#endif
+ .prepare_write = cifs_prepare_write,
+ .commit_write = cifs_commit_write,
+ .set_page_dirty = __set_page_dirty_nobuffers,
+diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -166,7 +166,13 @@ int cifs_get_inode_info_unix(struct inod
+ inode->i_fop = &cifs_file_direct_ops;
+ else
+ inode->i_fop = &cifs_file_ops;
++ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
++ inode->i_fop->lock = NULL;
+ inode->i_data.a_ops = &cifs_addr_ops;
++ /* check if server can support readpages */
++ if(pTcon->ses->server->maxBuf <
++ 4096 + MAX_CIFS_HDR_SIZE)
++ inode->i_data.a_ops->readpages = NULL;
+ } else if (S_ISDIR(inode->i_mode)) {
+ cFYI(1, (" Directory inode"));
+ inode->i_op = &cifs_dir_inode_ops;
+@@ -213,8 +219,18 @@ int cifs_get_inode_info(struct inode **p
+ pfindData = (FILE_ALL_INFO *)buf;
+ /* could do find first instead but this returns more info */
+ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
+- cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
++ cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
++ /* BB optimize code so we do not make the above call
++ when server claims no NT SMB support and the above call
++ failed at least once - set flag in tcon or mount */
++ if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
++ rc = SMBQueryInformation(xid, pTcon, search_path,
++ pfindData, cifs_sb->local_nls,
++ cifs_sb->mnt_cifs_flags &
++ CIFS_MOUNT_MAP_SPECIAL_CHR);
++ }
++
+ }
+ /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
+ if (rc) {
+@@ -320,6 +336,16 @@ int cifs_get_inode_info(struct inode **p
+ on dirs */
+ inode->i_mode = cifs_sb->mnt_dir_mode;
+ inode->i_mode |= S_IFDIR;
++ } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
++ (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
++ /* No need to le64 convert size of zero */
++ (pfindData->EndOfFile == 0)) {
++ inode->i_mode = cifs_sb->mnt_file_mode;
++ inode->i_mode |= S_IFIFO;
++/* BB Finish for SFU style symlinks and devies */
++/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
++ (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
++
+ } else {
+ inode->i_mode |= S_IFREG;
+ /* treat the dos attribute of read-only as read-only
+@@ -359,7 +385,12 @@ int cifs_get_inode_info(struct inode **p
+ inode->i_fop = &cifs_file_direct_ops;
+ else
+ inode->i_fop = &cifs_file_ops;
++ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
++ inode->i_fop->lock = NULL;
+ inode->i_data.a_ops = &cifs_addr_ops;
++ if(pTcon->ses->server->maxBuf <
++ 4096 + MAX_CIFS_HDR_SIZE)
++ inode->i_data.a_ops->readpages = NULL;
+ } else if (S_ISDIR(inode->i_mode)) {
+ cFYI(1, (" Directory inode "));
+ inode->i_op = &cifs_dir_inode_ops;
+@@ -577,7 +608,10 @@ int cifs_mkdir(struct inode *inode, stru
+ rc = cifs_get_inode_info(&newinode, full_path, NULL,
+ inode->i_sb,xid);
+
+- direntry->d_op = &cifs_dentry_ops;
++ if (pTcon->nocase)
++ direntry->d_op = &cifs_ci_dentry_ops;
++ else
++ direntry->d_op = &cifs_dentry_ops;
+ d_instantiate(direntry, newinode);
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink = 2;
+@@ -928,7 +962,6 @@ int cifs_setattr(struct dentry *direntry
+ struct cifsTconInfo *pTcon;
+ char *full_path = NULL;
+ int rc = -EACCES;
+- int found = FALSE;
+ struct cifsFileInfo *open_file = NULL;
+ FILE_BASIC_INFO time_buf;
+ int set_time = FALSE;
+@@ -936,7 +969,6 @@ int cifs_setattr(struct dentry *direntry
+ __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
+ __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
+ struct cifsInodeInfo *cifsInode;
+- struct list_head *tmp;
+
+ xid = GetXid();
+
+@@ -961,7 +993,6 @@ int cifs_setattr(struct dentry *direntry
+ filemap_fdatawait(direntry->d_inode->i_mapping);
+
+ if (attrs->ia_valid & ATTR_SIZE) {
+- read_lock(&GlobalSMBSeslock);
+ /* To avoid spurious oplock breaks from server, in the case of
+ inodes that we already have open, avoid doing path based
+ setting of file size if we can do it by handle.
+@@ -969,40 +1000,23 @@ int cifs_setattr(struct dentry *direntry
+ when the local oplock break takes longer to flush
+ writebehind data than the SMB timeout for the SetPathInfo
+ request would allow */
+- list_for_each(tmp, &cifsInode->openFileList) {
+- open_file = list_entry(tmp, struct cifsFileInfo,
+- flist);
+- /* We check if file is open for writing first */
+- if ((open_file->pfile) &&
+- ((open_file->pfile->f_flags & O_RDWR) ||
+- (open_file->pfile->f_flags & O_WRONLY))) {
+- if (open_file->invalidHandle == FALSE) {
+- /* we found a valid, writeable network
+- file handle to use to try to set the
+- file size */
+- __u16 nfid = open_file->netfid;
+- __u32 npid = open_file->pid;
+- read_unlock(&GlobalSMBSeslock);
+- found = TRUE;
+- rc = CIFSSMBSetFileSize(xid, pTcon,
+- attrs->ia_size, nfid, npid,
+- FALSE);
+- cFYI(1, ("SetFileSize by handle "
+- "(setattrs) rc = %d", rc));
+- /* Do not need reopen and retry on
+- EAGAIN since we will retry by
+- pathname below */
+-
+- /* now that we found one valid file
+- handle no sense continuing to loop
+- trying others, so break here */
+- break;
+- }
++ open_file = find_writable_file(cifsInode);
++ if (open_file) {
++ __u16 nfid = open_file->netfid;
++ __u32 npid = open_file->pid;
++ rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
++ nfid, npid, FALSE);
++ atomic_dec(&open_file->wrtPending);
++ cFYI(1,("SetFSize for attrs rc = %d", rc));
++ if(rc == -EINVAL) {
++ int bytes_written;
++ rc = CIFSSMBWrite(xid, pTcon,
++ nfid, 0, attrs->ia_size,
++ &bytes_written, NULL, NULL,
++ 1 /* 45 seconds */);
++ cFYI(1,("Wrt seteof rc %d", rc));
+ }
+ }
+- if (found == FALSE)
+- read_unlock(&GlobalSMBSeslock);
+-
+ if (rc != 0) {
+ /* Set file size by pathname rather than by handle
+ either because no valid, writeable file handle for
+@@ -1013,7 +1027,30 @@ int cifs_setattr(struct dentry *direntry
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+- cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
++ cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
++ if(rc == -EINVAL) {
++ __u16 netfid;
++ int oplock = FALSE;
++
++ rc = SMBLegacyOpen(xid, pTcon, full_path,
++ FILE_OPEN,
++ SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
++ CREATE_NOT_DIR, &netfid, &oplock,
++ NULL, cifs_sb->local_nls,
++ cifs_sb->mnt_cifs_flags &
++ CIFS_MOUNT_MAP_SPECIAL_CHR);
++ if (rc==0) {
++ int bytes_written;
++ rc = CIFSSMBWrite(xid, pTcon,
++ netfid, 0,
++ attrs->ia_size,
++ &bytes_written, NULL,
++ NULL, 1 /* 45 sec */);
++ cFYI(1,("wrt seteof rc %d",rc));
++ CIFSSMBClose(xid, pTcon, netfid);
++ }
++
++ }
+ }
+
+ /* Server is ok setting allocation size implicitly - no need
+@@ -1026,24 +1063,22 @@ int cifs_setattr(struct dentry *direntry
+ rc = vmtruncate(direntry->d_inode, attrs->ia_size);
+ cifs_truncate_page(direntry->d_inode->i_mapping,
+ direntry->d_inode->i_size);
+- }
++ } else
++ goto cifs_setattr_exit;
+ }
+ if (attrs->ia_valid & ATTR_UID) {
+- cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
++ cFYI(1, ("UID changed to %d", attrs->ia_uid));
+ uid = attrs->ia_uid;
+- /* entry->uid = cpu_to_le16(attr->ia_uid); */
+ }
+ if (attrs->ia_valid & ATTR_GID) {
+- cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
++ cFYI(1, ("GID changed to %d", attrs->ia_gid));
+ gid = attrs->ia_gid;
+- /* entry->gid = cpu_to_le16(attr->ia_gid); */
+ }
+
+ time_buf.Attributes = 0;
+ if (attrs->ia_valid & ATTR_MODE) {
+- cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
++ cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
+ mode = attrs->ia_mode;
+- /* entry->mode = cpu_to_le16(attr->ia_mode); */
+ }
+
+ if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+@@ -1083,18 +1118,24 @@ int cifs_setattr(struct dentry *direntry
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
+ } else
+ time_buf.LastWriteTime = 0;
+-
+- if (attrs->ia_valid & ATTR_CTIME) {
++ /* Do not set ctime explicitly unless other time
++ stamps are changed explicitly (i.e. by utime()
++ since we would then have a mix of client and
++ server times */
++
++ if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
+ set_time = TRUE;
+- cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
++ /* Although Samba throws this field away
++ it may be useful to Windows - but we do
++ not want to set ctime unless some other
++ timestamp is changing */
++ cFYI(1, ("CIFS - CTIME changed "));
+ time_buf.ChangeTime =
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
+ } else
+ time_buf.ChangeTime = 0;
+
+ if (set_time || time_buf.Attributes) {
+- /* BB what if setting one attribute fails (such as size) but
+- time setting works? */
+ time_buf.CreationTime = 0; /* do not change */
+ /* In the future we should experiment - try setting timestamps
+ via Handle (SetFileInfo) instead of by path */
+@@ -1133,12 +1174,21 @@ int cifs_setattr(struct dentry *direntry
+ &time_buf, cifs_sb->local_nls); */
+ }
+ }
++ /* Even if error on time set, no sense failing the call if
++ the server would set the time to a reasonable value anyway,
++ and this check ensures that we are not being called from
++ sys_utimes in which case we ought to fail the call back to
++ the user when the server rejects the call */
++ if((rc) && (attrs->ia_valid &&
++ (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
++ rc = 0;
+ }
+
+ /* do not need local check to inode_check_ok since the server does
+ that */
+ if (!rc)
+ rc = inode_setattr(direntry->d_inode, attrs);
++cifs_setattr_exit:
+ kfree(full_path);
+ FreeXid(xid);
+ return rc;
+diff --git a/fs/cifs/link.c b/fs/cifs/link.c
+--- a/fs/cifs/link.c
++++ b/fs/cifs/link.c
+@@ -198,7 +198,10 @@ cifs_symlink(struct inode *inode, struct
+ ("Create symlink worked but get_inode_info failed with rc = %d ",
+ rc));
+ } else {
+- direntry->d_op = &cifs_dentry_ops;
++ if (pTcon->nocase)
++ direntry->d_op = &cifs_ci_dentry_ops;
++ else
++ direntry->d_op = &cifs_dentry_ops;
+ d_instantiate(direntry, newinode);
+ }
+ }
+diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
+--- a/fs/cifs/misc.c
++++ b/fs/cifs/misc.c
+@@ -34,8 +34,6 @@ extern mempool_t *cifs_sm_req_poolp;
+ extern mempool_t *cifs_req_poolp;
+ extern struct task_struct * oplockThread;
+
+-static __u16 GlobalMid; /* multiplex id - rotating counter */
+-
+ /* The xid serves as a useful identifier for each incoming vfs request,
+ in a similar way to the mid which is useful to track each sent smb,
+ and CurrentXid can also provide a running counter (although it
+@@ -51,6 +49,8 @@ _GetXid(void)
+ GlobalTotalActiveXid++;
+ if (GlobalTotalActiveXid > GlobalMaxActiveXid)
+ GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
++ if(GlobalTotalActiveXid > 65000)
++ cFYI(1,("warning: more than 65000 requests active"));
+ xid = GlobalCurrentXid++;
+ spin_unlock(&GlobalMid_Lock);
+ return xid;
+@@ -218,6 +218,76 @@ cifs_small_buf_release(void *buf_to_free
+ return;
+ }
+
++/*
++ Find a free multiplex id (SMB mid). Otherwise there could be
++ mid collisions which might cause problems, demultiplexing the
++ wrong response to this request. Multiplex ids could collide if
++ one of a series requests takes much longer than the others, or
++ if a very large number of long lived requests (byte range
++ locks or FindNotify requests) are pending. No more than
++ 64K-1 requests can be outstanding at one time. If no
++ mids are available, return zero. A future optimization
++ could make the combination of mids and uid the key we use
++ to demultiplex on (rather than mid alone).
++ In addition to the above check, the cifs demultiplex
++ code already used the command code as a secondary
++ check of the frame and if signing is negotiated the
++ response would be discarded if the mid were the same
++ but the signature was wrong. Since the mid is not put in the
++ pending queue until later (when it is about to be dispatched)
++ we do have to limit the number of outstanding requests
++ to somewhat less than 64K-1 although it is hard to imagine
++ so many threads being in the vfs at one time.
++*/
++__u16 GetNextMid(struct TCP_Server_Info *server)
++{
++ __u16 mid = 0;
++ __u16 last_mid;
++ int collision;
++
++ if(server == NULL)
++ return mid;
++
++ spin_lock(&GlobalMid_Lock);
++ last_mid = server->CurrentMid; /* we do not want to loop forever */
++ server->CurrentMid++;
++ /* This nested loop looks more expensive than it is.
++ In practice the list of pending requests is short,
++ fewer than 50, and the mids are likely to be unique
++ on the first pass through the loop unless some request
++ takes longer than the 64 thousand requests before it
++ (and it would also have to have been a request that
++ did not time out) */
++ while(server->CurrentMid != last_mid) {
++ struct list_head *tmp;
++ struct mid_q_entry *mid_entry;
++
++ collision = 0;
++ if(server->CurrentMid == 0)
++ server->CurrentMid++;
++
++ list_for_each(tmp, &server->pending_mid_q) {
++ mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
++
++ if ((mid_entry->mid == server->CurrentMid) &&
++ (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
++ /* This mid is in use, try a different one */
++ collision = 1;
++ break;
++ }
++ }
++ if(collision == 0) {
++ mid = server->CurrentMid;
++ break;
++ }
++ server->CurrentMid++;
++ }
++ spin_unlock(&GlobalMid_Lock);
++ return mid;
++}
++
++/* NB: MID can not be set if treeCon not passed in, in that
++ case it is responsbility of caller to set the mid */
+ void
+ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
+ const struct cifsTconInfo *treeCon, int word_count
+@@ -233,7 +303,8 @@ header_assemble(struct smb_hdr *buffer,
+ (2 * word_count) + sizeof (struct smb_hdr) -
+ 4 /* RFC 1001 length field does not count */ +
+ 2 /* for bcc field itself */ ;
+- /* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */
++ /* Note that this is the only network field that has to be converted
++ to big endian and it is done just before we send it */
+
+ buffer->Protocol[0] = 0xFF;
+ buffer->Protocol[1] = 'S';
+@@ -245,8 +316,6 @@ header_assemble(struct smb_hdr *buffer,
+ buffer->Pid = cpu_to_le16((__u16)current->tgid);
+ buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
+ spin_lock(&GlobalMid_Lock);
+- GlobalMid++;
+- buffer->Mid = GlobalMid;
+ spin_unlock(&GlobalMid_Lock);
+ if (treeCon) {
+ buffer->Tid = treeCon->tid;
+@@ -256,8 +325,9 @@ header_assemble(struct smb_hdr *buffer,
+ if (treeCon->ses->capabilities & CAP_STATUS32) {
+ buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ }
+-
+- buffer->Uid = treeCon->ses->Suid; /* always in LE format */
++ /* Uid is not converted */
++ buffer->Uid = treeCon->ses->Suid;
++ buffer->Mid = GetNextMid(treeCon->ses->server);
+ if(multiuser_mount != 0) {
+ /* For the multiuser case, there are few obvious technically */
+ /* possible mechanisms to match the local linux user (uid) */
+@@ -305,6 +375,8 @@ header_assemble(struct smb_hdr *buffer,
+ }
+ if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
+ buffer->Flags2 |= SMBFLG2_DFS;
++ if (treeCon->nocase)
++ buffer->Flags |= SMBFLG_CASELESS;
+ if((treeCon->ses) && (treeCon->ses->server))
+ if(treeCon->ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+@@ -347,7 +419,8 @@ checkSMBhdr(struct smb_hdr *smb, __u16 m
+ int
+ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
+ {
+- __u32 len = be32_to_cpu(smb->smb_buf_length);
++ __u32 len = smb->smb_buf_length;
++ __u32 clc_len; /* calculated length */
+ cFYI(0,
+ ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
+ length, len));
+@@ -368,23 +441,29 @@ checkSMB(struct smb_hdr *smb, __u16 mid,
+ cERROR(1,
+ ("smb_buf_length greater than MaxBufSize"));
+ cERROR(1,
+- ("bad smb detected. Illegal length. The mid=%d",
++ ("bad smb detected. Illegal length. mid=%d",
+ smb->Mid));
+ return 1;
+ }
+
+ if (checkSMBhdr(smb, mid))
+ return 1;
+-
+- if ((4 + len != smbCalcSize(smb))
++ clc_len = smbCalcSize_LE(smb);
++ if ((4 + len != clc_len)
+ || (4 + len != (unsigned int)length)) {
+- return 0;
+- } else {
+- cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
+- cERROR(1,
+- ("bad smb size detected. The Mid=%d", smb->Mid));
+- return 1;
++ cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
++ clc_len, 4 + len));
++ cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
++ /* Windows XP can return a few bytes too much, presumably
++ an illegal pad, at the end of byte range lock responses
++ so we allow for up to eight byte pad, as long as actual
++ received length is as long or longer than calculated length */
++ if((4+len > clc_len) && (len <= clc_len + 3))
++ return 0;
++ else
++ return 1;
+ }
++ return 0;
+ }
+ int
+ is_valid_oplock_break(struct smb_hdr *buf)
+@@ -448,9 +527,7 @@ is_valid_oplock_break(struct smb_hdr *bu
+ list_for_each(tmp, &GlobalTreeConnectionList) {
+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+ if (tcon->tid == buf->Tid) {
+-#ifdef CONFIG_CIFS_STATS
+- atomic_inc(&tcon->num_oplock_brks);
+-#endif
++ cifs_stats_inc(&tcon->num_oplock_brks);
+ list_for_each(tmp1,&tcon->openFileList){
+ netfile = list_entry(tmp1,struct cifsFileInfo,
+ tlist);
+@@ -603,6 +680,7 @@ cifsConvertToUCS(__le16 * target, const
+ int i,j,charlen;
+ int len_remaining = maxlen;
+ char src_char;
++ __u16 temp;
+
+ if(!mapChars)
+ return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
+@@ -639,13 +717,14 @@ cifsConvertToUCS(__le16 * target, const
+ break;*/
+ default:
+ charlen = cp->char2uni(source+i,
+- len_remaining, target+j);
++ len_remaining, &temp);
+ /* if no match, use question mark, which
+ at least in some cases servers as wild card */
+ if(charlen < 1) {
+ target[j] = cpu_to_le16(0x003f);
+ charlen = 1;
+- }
++ } else
++ target[j] = cpu_to_le16(temp);
+ len_remaining -= charlen;
+ /* character may take more than one byte in the
+ the source string, but will take exactly two
+diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
+--- a/fs/cifs/netmisc.c
++++ b/fs/cifs/netmisc.c
+@@ -133,7 +133,6 @@ static const struct smb_to_posix_error m
+ int
+ cifs_inet_pton(int address_family, char *cp,void *dst)
+ {
+- struct in_addr address;
+ int value;
+ int digit;
+ int i;
+@@ -190,8 +189,7 @@ cifs_inet_pton(int address_family, char
+ if (value > addr_class_max[end - bytes])
+ return 0;
+
+- address.s_addr = *((__be32 *) bytes) | htonl(value);
+- *((__be32 *)dst) = address.s_addr;
++ *((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
+ return 1; /* success */
+ }
+
+@@ -815,7 +813,7 @@ map_smb_to_linux_error(struct smb_hdr *s
+ if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
+ /* translate the newer STATUS codes to old style errors and then to POSIX errors */
+ __u32 err = le32_to_cpu(smb->Status.CifsError);
+- if(cifsFYI)
++ if(cifsFYI & CIFS_RC)
+ cifs_print_status(err);
+ ntstatus_to_dos(err, &smberrclass, &smberrcode);
+ } else {
+@@ -870,7 +868,14 @@ unsigned int
+ smbCalcSize(struct smb_hdr *ptr)
+ {
+ return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+- BCC(ptr));
++ 2 /* size of the bcc field */ + BCC(ptr));
++}
++
++unsigned int
++smbCalcSize_LE(struct smb_hdr *ptr)
++{
++ return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
++ 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
+ }
+
+ /* The following are taken from fs/ntfs/util.c */
+diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
+--- a/fs/cifs/ntlmssp.h
++++ b/fs/cifs/ntlmssp.h
+@@ -19,8 +19,6 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-#pragma pack(1)
+-
+ #define NTLMSSP_SIGNATURE "NTLMSSP"
+ /* Message Types */
+ #define NtLmNegotiate cpu_to_le32(1)
+@@ -63,7 +61,7 @@ typedef struct _SECURITY_BUFFER {
+ __le16 Length;
+ __le16 MaximumLength;
+ __le32 Buffer; /* offset to buffer */
+-} SECURITY_BUFFER;
++} __attribute__((packed)) SECURITY_BUFFER;
+
+ typedef struct _NEGOTIATE_MESSAGE {
+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+@@ -73,7 +71,7 @@ typedef struct _NEGOTIATE_MESSAGE {
+ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
+ char DomainString[0];
+ /* followed by WorkstationString */
+-} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
++} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
+
+ typedef struct _CHALLENGE_MESSAGE {
+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+@@ -83,7 +81,7 @@ typedef struct _CHALLENGE_MESSAGE {
+ __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
+ __u8 Reserved[8];
+ SECURITY_BUFFER TargetInfoArray;
+-} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
++} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
+
+ typedef struct _AUTHENTICATE_MESSAGE {
+ __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+@@ -96,6 +94,4 @@ typedef struct _AUTHENTICATE_MESSAGE {
+ SECURITY_BUFFER SessionKey;
+ __le32 NegotiateFlags;
+ char UserString[0];
+-} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+-
+-#pragma pack() /* resume default structure packing */
++} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -91,7 +91,10 @@ static int construct_dentry(struct qstr
+ }
+
+ *ptmp_inode = new_inode(file->f_dentry->d_sb);
+- tmp_dentry->d_op = &cifs_dentry_ops;
++ if (pTcon->nocase)
++ tmp_dentry->d_op = &cifs_ci_dentry_ops;
++ else
++ tmp_dentry->d_op = &cifs_dentry_ops;
+ if(*ptmp_inode == NULL)
+ return rc;
+ rc = 1;
+@@ -148,6 +151,13 @@ static void fill_in_inode(struct inode *
+ tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
+ }
+ tmp_inode->i_mode |= S_IFDIR;
++ } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
++ (attr & ATTR_SYSTEM) && (end_of_file == 0)) {
++ *pobject_type = DT_FIFO;
++ tmp_inode->i_mode |= S_IFIFO;
++/* BB Finish for SFU style symlinks and devies */
++/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
++ (attr & ATTR_SYSTEM) && ) { */
+ /* we no longer mark these because we could not follow them */
+ /* } else if (attr & ATTR_REPARSE) {
+ *pobject_type = DT_LNK;
+@@ -187,11 +197,17 @@ static void fill_in_inode(struct inode *
+ tmp_inode->i_fop = &cifs_file_direct_ops;
+ else
+ tmp_inode->i_fop = &cifs_file_ops;
++ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
++ tmp_inode->i_fop->lock = NULL;
+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
+-
++ if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
++ (cifs_sb->tcon->ses->server->maxBuf <
++ 4096 + MAX_CIFS_HDR_SIZE))
++ tmp_inode->i_data.a_ops->readpages = NULL;
+ if(isNewInode)
+- return; /* No sense invalidating pages for new inode since we
+- have not started caching readahead file data yet */
++ return; /* No sense invalidating pages for new inode
++ since have not started caching readahead file
++ data yet */
+
+ if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+ (local_size == tmp_inode->i_size)) {
+@@ -290,7 +306,13 @@ static void unix_fill_in_inode(struct in
+ tmp_inode->i_fop = &cifs_file_direct_ops;
+ else
+ tmp_inode->i_fop = &cifs_file_ops;
++ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
++ tmp_inode->i_fop->lock = NULL;
+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
++ if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
++ (cifs_sb->tcon->ses->server->maxBuf <
++ 4096 + MAX_CIFS_HDR_SIZE))
++ tmp_inode->i_data.a_ops->readpages = NULL;
+
+ if(isNewInode)
+ return; /* No sense invalidating pages for new inode since we
+@@ -374,7 +396,8 @@ ffirst_retry:
+
+ rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
+ &cifsFile->netfid, &cifsFile->srch_inf,
+- cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
++ cifs_sb->mnt_cifs_flags &
++ CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
+ if(rc == 0)
+ cifsFile->invalidHandle = FALSE;
+ if((rc == -EOPNOTSUPP) &&
+@@ -491,6 +514,30 @@ static int cifs_entry_is_dot(char *curre
+ return rc;
+ }
+
++/* Check if directory that we are searching has changed so we can decide
++ whether we can use the cached search results from the previous search */
++static int is_dir_changed(struct file * file)
++{
++ struct inode * inode;
++ struct cifsInodeInfo *cifsInfo;
++
++ if(file->f_dentry == NULL)
++ return 0;
++
++ inode = file->f_dentry->d_inode;
++
++ if(inode == NULL)
++ return 0;
++
++ cifsInfo = CIFS_I(inode);
++
++ if(cifsInfo->time == 0)
++ return 1; /* directory was changed, perhaps due to unlink */
++ else
++ return 0;
++
++}
++
+ /* find the corresponding entry in the search */
+ /* Note that the SMB server returns search entries for . and .. which
+ complicates logic here if we choose to parse for them and we do not
+@@ -507,7 +554,8 @@ static int find_cifs_entry(const int xid
+ struct cifsFileInfo * cifsFile = file->private_data;
+ /* check if index in the buffer */
+
+- if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL))
++ if((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
++ (num_to_ret == NULL))
+ return -ENOENT;
+
+ *ppCurrentEntry = NULL;
+@@ -515,7 +563,9 @@ static int find_cifs_entry(const int xid
+ cifsFile->srch_inf.index_of_last_entry -
+ cifsFile->srch_inf.entries_in_buffer;
+ /* dump_cifs_file_struct(file, "In fce ");*/
+- if(index_to_find < first_entry_in_buffer) {
++ if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
++ is_dir_changed(file)) ||
++ (index_to_find < first_entry_in_buffer)) {
+ /* close and restart search */
+ cFYI(1,("search backing up - close and restart search"));
+ cifsFile->invalidHandle = TRUE;
+@@ -536,7 +586,8 @@ static int find_cifs_entry(const int xid
+ while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
+ (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
+ cFYI(1,("calling findnext2"));
+- rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf);
++ rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
++ &cifsFile->srch_inf);
+ if(rc)
+ return -ENOENT;
+ }
+@@ -548,14 +599,13 @@ static int find_cifs_entry(const int xid
+ char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
+ smbCalcSize((struct smb_hdr *)
+ cifsFile->srch_inf.ntwrk_buf_start);
+-/* dump_cifs_file_struct(file,"found entry in fce "); */
+ first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
+ - cifsFile->srch_inf.entries_in_buffer;
+ pos_in_buf = index_to_find - first_entry_in_buffer;
+ cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
+ current_entry = cifsFile->srch_inf.srch_entries_start;
+ for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
+- /* go entry to next entry figuring out which we need to start with */
++ /* go entry by entry figuring out which is first */
+ /* if( . or ..)
+ skip */
+ rc = cifs_entry_is_dot(current_entry,cifsFile);
+@@ -582,11 +632,10 @@ static int find_cifs_entry(const int xid
+ }
+
+ if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
+- cFYI(1,("can not return entries when pos_in_buf beyond last entry"));
++ cFYI(1,("can not return entries pos_in_buf beyond last entry"));
+ *num_to_ret = 0;
+ } else
+ *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
+-/* dump_cifs_file_struct(file, "end fce ");*/
+
+ return rc;
+ }
+@@ -721,7 +770,8 @@ static int cifs_filldir(char *pfindEntry
+ (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
+ }
+
+- rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);
++ rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
++ tmp_inode->i_ino,obj_type);
+ if(rc) {
+ cFYI(1,("filldir rc = %d",rc));
+ }
+@@ -805,15 +855,12 @@ int cifs_readdir(struct file *file, void
+ FreeXid(xid);
+ return -EIO;
+ }
+-/* dump_cifs_file_struct(file, "Begin rdir "); */
+
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+ if(pTcon == NULL)
+ return -EINVAL;
+
+-/* cFYI(1,("readdir2 pos: %lld",file->f_pos)); */
+-
+ switch ((int) file->f_pos) {
+ case 0:
+ /*if (filldir(direntry, ".", 1, file->f_pos,
+@@ -866,7 +913,6 @@ int cifs_readdir(struct file *file, void
+ cifsFile->search_resume_name = NULL; */
+
+ /* BB account for . and .. in f_pos as special case */
+- /* dump_cifs_file_struct(file, "rdir after default ");*/
+
+ rc = find_cifs_entry(xid,pTcon, file,
+ ¤t_entry,&num_to_fill);
+@@ -906,14 +952,14 @@ int cifs_readdir(struct file *file, void
+ cifs_save_resume_key(current_entry,cifsFile);
+ break;
+ } else
+- current_entry = nxt_dir_entry(current_entry,end_of_smb);
++ current_entry = nxt_dir_entry(current_entry,
++ end_of_smb);
+ }
+ kfree(tmp_buf);
+ break;
+ } /* end switch */
+
+ rddir2_exit:
+- /* dump_cifs_file_struct(file, "end rdir "); */
+ FreeXid(xid);
+ return rc;
+ }
+diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
+--- a/fs/cifs/rfc1002pdu.h
++++ b/fs/cifs/rfc1002pdu.h
+@@ -21,8 +21,6 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-#pragma pack(1)
+-
+ /* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
+
+ /* RFC 1002 session packet types */
+@@ -48,17 +46,17 @@ struct rfc1002_session_packet {
+ __u8 calling_len;
+ __u8 calling_name[32];
+ __u8 scope2; /* null */
+- } session_req;
++ } __attribute__((packed)) session_req;
+ struct {
+ __u32 retarget_ip_addr;
+ __u16 port;
+- } retarget_resp;
++ } __attribute__((packed)) retarget_resp;
+ __u8 neg_ses_resp_error_code;
+ /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
+ SESSION_KEEP_ALIVE packet also does not include a trailer.
+ Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
+- } trailer;
+-};
++ } __attribute__((packed)) trailer;
++} __attribute__((packed));
+
+ /* Negative Session Response error codes */
+ #define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
+@@ -74,6 +72,3 @@ server netbios name). Currently server n
+ (tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
+
+ #define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
+-
+-#pragma pack() /* resume default structure packing */
+-
+diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -49,7 +49,8 @@ AllocMidQEntry(struct smb_hdr *smb_buffe
+ return NULL;
+ }
+
+- temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS);
++ temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
++ SLAB_KERNEL | SLAB_NOFS);
+ if (temp == NULL)
+ return temp;
+ else {
+@@ -58,7 +59,9 @@ AllocMidQEntry(struct smb_hdr *smb_buffe
+ temp->pid = current->pid;
+ temp->command = smb_buffer->Command;
+ cFYI(1, ("For smb_command %d", temp->command));
+- do_gettimeofday(&temp->when_sent);
++ /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
++ /* when mid allocated can be before when sent */
++ temp->when_alloc = jiffies;
+ temp->ses = ses;
+ temp->tsk = current;
+ }
+@@ -74,6 +77,9 @@ AllocMidQEntry(struct smb_hdr *smb_buffe
+ static void
+ DeleteMidQEntry(struct mid_q_entry *midEntry)
+ {
++#ifdef CONFIG_CIFS_STATS2
++ unsigned long now;
++#endif
+ spin_lock(&GlobalMid_Lock);
+ midEntry->midState = MID_FREE;
+ list_del(&midEntry->qhead);
+@@ -83,6 +89,22 @@ DeleteMidQEntry(struct mid_q_entry *midE
+ cifs_buf_release(midEntry->resp_buf);
+ else
+ cifs_small_buf_release(midEntry->resp_buf);
++#ifdef CONFIG_CIFS_STATS2
++ now = jiffies;
++ /* commands taking longer than one second are indications that
++ something is wrong, unless it is quite a slow link or server */
++ if((now - midEntry->when_alloc) > HZ) {
++ if((cifsFYI & CIFS_TIMER) &&
++ (midEntry->command != SMB_COM_LOCKING_ANDX)) {
++ printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
++ midEntry->command, midEntry->mid);
++ printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
++ now - midEntry->when_alloc,
++ now - midEntry->when_sent,
++ now - midEntry->when_received);
++ }
++ }
++#endif
+ mempool_free(midEntry, cifs_mid_poolp);
+ }
+
+@@ -146,32 +168,37 @@ smb_send(struct socket *ssocket, struct
+ Flags2 is converted in SendReceive */
+
+ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+- cFYI(1, ("Sending smb of length %d ", smb_buf_length));
++ cFYI(1, ("Sending smb of length %d", smb_buf_length));
+ dump_smb(smb_buffer, len);
+
+ while (len > 0) {
+ rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
+ if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+ i++;
+- if(i > 60) {
++ /* smaller timeout here than send2 since smaller size */
++ /* Although it may not be required, this also is smaller
++ oplock break time */
++ if(i > 12) {
+ cERROR(1,
+- ("sends on sock %p stuck for 30 seconds",
++ ("sends on sock %p stuck for 7 seconds",
+ ssocket));
+ rc = -EAGAIN;
+ break;
+ }
+- msleep(500);
++ msleep(1 << i);
+ continue;
+ }
+ if (rc < 0)
+ break;
++ else
++ i = 0; /* reset i after each successful send */
+ iov.iov_base += rc;
+ iov.iov_len -= rc;
+ len -= rc;
+ }
+
+ if (rc < 0) {
+- cERROR(1,("Error %d sending data on socket to server.", rc));
++ cERROR(1,("Error %d sending data on socket to server", rc));
+ } else {
+ rc = 0;
+ }
+@@ -179,26 +206,21 @@ smb_send(struct socket *ssocket, struct
+ return rc;
+ }
+
+-#ifdef CIFS_EXPERIMENTAL
+-/* BB finish off this function, adding support for writing set of pages as iovec */
+-/* and also adding support for operations that need to parse the response smb */
+-
+-int
+-smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
+- unsigned int smb_buf_length, struct kvec * write_vector
+- /* page list */, struct sockaddr *sin)
++#ifdef CONFIG_CIFS_EXPERIMENTAL
++static int
++smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
++ struct sockaddr *sin)
+ {
+ int rc = 0;
+ int i = 0;
+ struct msghdr smb_msg;
+- number_of_pages += 1; /* account for SMB header */
+- struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec));
+- unsigned len = smb_buf_length + 4;
+-
++ struct smb_hdr *smb_buffer = iov[0].iov_base;
++ unsigned int len = iov[0].iov_len;
++ unsigned int total_len;
++ int first_vec = 0;
++
+ if(ssocket == NULL)
+ return -ENOTSOCK; /* BB eventually add reconnect code here */
+- iov.iov_base = smb_buffer;
+- iov.iov_len = len;
+
+ smb_msg.msg_name = sin;
+ smb_msg.msg_namelen = sizeof (struct sockaddr);
+@@ -211,49 +233,80 @@ smb_sendv(struct socket *ssocket, struct
+ cifssmb.c and RFC1001 len is converted to bigendian in smb_send
+ Flags2 is converted in SendReceive */
+
++
++ total_len = 0;
++ for (i = 0; i < n_vec; i++)
++ total_len += iov[i].iov_len;
++
+ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+- cFYI(1, ("Sending smb of length %d ", smb_buf_length));
++ cFYI(1, ("Sending smb: total_len %d", total_len));
+ dump_smb(smb_buffer, len);
+
+- while (len > 0) {
+- rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages,
+- len);
++ while (total_len) {
++ rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
++ n_vec - first_vec, total_len);
+ if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+ i++;
+- if(i > 60) {
++ if(i >= 14) {
+ cERROR(1,
+- ("sends on sock %p stuck for 30 seconds",
++ ("sends on sock %p stuck for 15 seconds",
+ ssocket));
+ rc = -EAGAIN;
+ break;
+ }
+- msleep(500);
++ msleep(1 << i);
+ continue;
+ }
+ if (rc < 0)
+ break;
+- iov.iov_base += rc;
+- iov.iov_len -= rc;
+- len -= rc;
++
++ if (rc >= total_len) {
++ WARN_ON(rc > total_len);
++ break;
++ }
++ if(rc == 0) {
++ /* should never happen, letting socket clear before
++ retrying is our only obvious option here */
++ cERROR(1,("tcp sent no data"));
++ msleep(500);
++ continue;
++ }
++ total_len -= rc;
++ /* the line below resets i */
++ for (i = first_vec; i < n_vec; i++) {
++ if (iov[i].iov_len) {
++ if (rc > iov[i].iov_len) {
++ rc -= iov[i].iov_len;
++ iov[i].iov_len = 0;
++ } else {
++ iov[i].iov_base += rc;
++ iov[i].iov_len -= rc;
++ first_vec = i;
++ break;
++ }
++ }
++ }
++ i = 0; /* in case we get ENOSPC on the next send */
+ }
+
+ if (rc < 0) {
+- cERROR(1,("Error %d sending data on socket to server.", rc));
+- } else {
++ cERROR(1,("Error %d sending data on socket to server", rc));
++ } else
+ rc = 0;
+- }
+
+ return rc;
+ }
+
+-
+ int
+-CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
+- struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op)
++SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
++ struct kvec *iov, int n_vec, int *pbytes_returned,
++ const int long_op)
+ {
+ int rc = 0;
+- unsigned long timeout = 15 * HZ;
+- struct mid_q_entry *midQ = NULL;
++ unsigned int receive_len;
++ unsigned long timeout;
++ struct mid_q_entry *midQ;
++ struct smb_hdr *in_buf = iov[0].iov_base;
+
+ if (ses == NULL) {
+ cERROR(1,("Null smb session"));
+@@ -263,14 +316,8 @@ CIFSSendRcv(const unsigned int xid, stru
+ cERROR(1,("Null tcp session"));
+ return -EIO;
+ }
+- if(pbytes_returned == NULL)
+- return -EIO;
+- else
+- *pbytes_returned = 0;
+
+-
+-
+- if(ses->server->tcpStatus == CIFS_EXITING)
++ if(ses->server->tcpStatus == CifsExiting)
+ return -ENOENT;
+
+ /* Ensure that we do not send more than 50 overlapping requests
+@@ -282,11 +329,18 @@ CIFSSendRcv(const unsigned int xid, stru
+ } else {
+ spin_lock(&GlobalMid_Lock);
+ while(1) {
+- if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
++ if(atomic_read(&ses->server->inFlight) >=
++ cifs_max_pending){
+ spin_unlock(&GlobalMid_Lock);
++#ifdef CONFIG_CIFS_STATS2
++ atomic_inc(&ses->server->num_waiters);
++#endif
+ wait_event(ses->server->request_q,
+ atomic_read(&ses->server->inFlight)
+ < cifs_max_pending);
++#ifdef CONFIG_CIFS_STATS2
++ atomic_dec(&ses->server->num_waiters);
++#endif
+ spin_lock(&GlobalMid_Lock);
+ } else {
+ if(ses->server->tcpStatus == CifsExiting) {
+@@ -314,17 +368,17 @@ CIFSSendRcv(const unsigned int xid, stru
+
+ if (ses->server->tcpStatus == CifsExiting) {
+ rc = -ENOENT;
+- goto cifs_out_label;
++ goto out_unlock2;
+ } else if (ses->server->tcpStatus == CifsNeedReconnect) {
+ cFYI(1,("tcp session dead - return to caller to retry"));
+ rc = -EAGAIN;
+- goto cifs_out_label;
++ goto out_unlock2;
+ } else if (ses->status != CifsGood) {
+ /* check if SMB session is bad because we are setting it up */
+ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
+ (in_buf->Command != SMB_COM_NEGOTIATE)) {
+ rc = -EAGAIN;
+- goto cifs_out_label;
++ goto out_unlock2;
+ } /* else ok - we are setting up session */
+ }
+ midQ = AllocMidQEntry(in_buf, ses);
+@@ -338,51 +392,162 @@ CIFSSendRcv(const unsigned int xid, stru
+ return -ENOMEM;
+ }
+
+- if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+- up(&ses->server->tcpSem);
+- cERROR(1,
+- ("Illegal length, greater than maximum frame, %d ",
+- in_buf->smb_buf_length));
++/* BB FIXME */
++/* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
++
++ midQ->midState = MID_REQUEST_SUBMITTED;
++#ifdef CONFIG_CIFS_STATS2
++ atomic_inc(&ses->server->inSend);
++#endif
++ rc = smb_send2(ses->server->ssocket, iov, n_vec,
++ (struct sockaddr *) &(ses->server->addr.sockAddr));
++#ifdef CONFIG_CIFS_STATS2
++ atomic_dec(&ses->server->inSend);
++ midQ->when_sent = jiffies;
++#endif
++ if(rc < 0) {
+ DeleteMidQEntry(midQ);
++ up(&ses->server->tcpSem);
+ /* If not lock req, update # of requests on wire to server */
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+- return -EIO;
++ return rc;
++ } else
++ up(&ses->server->tcpSem);
++ if (long_op == -1)
++ goto cifs_no_response_exit2;
++ else if (long_op == 2) /* writes past end of file can take loong time */
++ timeout = 180 * HZ;
++ else if (long_op == 1)
++ timeout = 45 * HZ; /* should be greater than
++ servers oplock break timeout (about 43 seconds) */
++ else if (long_op > 2) {
++ timeout = MAX_SCHEDULE_TIMEOUT;
++ } else
++ timeout = 15 * HZ;
++ /* wait for 15 seconds or until woken up due to response arriving or
++ due to last connection to this server being unmounted */
++ if (signal_pending(current)) {
++ /* if signal pending do not hold up user for full smb timeout
++ but we still give response a change to complete */
++ timeout = 2 * HZ;
++ }
++
++ /* No user interrupts in wait - wreaks havoc with performance */
++ if(timeout != MAX_SCHEDULE_TIMEOUT) {
++ timeout += jiffies;
++ wait_event(ses->server->response_q,
++ (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
++ time_after(jiffies, timeout) ||
++ ((ses->server->tcpStatus != CifsGood) &&
++ (ses->server->tcpStatus != CifsNew)));
++ } else {
++ wait_event(ses->server->response_q,
++ (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
++ ((ses->server->tcpStatus != CifsGood) &&
++ (ses->server->tcpStatus != CifsNew)));
+ }
+
+- /* BB can we sign efficiently in this path? */
+- rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
++ spin_lock(&GlobalMid_Lock);
++ if (midQ->resp_buf) {
++ spin_unlock(&GlobalMid_Lock);
++ receive_len = midQ->resp_buf->smb_buf_length;
++ } else {
++ cERROR(1,("No response to cmd %d mid %d",
++ midQ->command, midQ->mid));
++ if(midQ->midState == MID_REQUEST_SUBMITTED) {
++ if(ses->server->tcpStatus == CifsExiting)
++ rc = -EHOSTDOWN;
++ else {
++ ses->server->tcpStatus = CifsNeedReconnect;
++ midQ->midState = MID_RETRY_NEEDED;
++ }
++ }
+
+- midQ->midState = MID_REQUEST_SUBMITTED;
+-/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+- piovec,
+- (struct sockaddr *) &(ses->server->addr.sockAddr));*/
+- if(rc < 0) {
++ if (rc != -EHOSTDOWN) {
++ if(midQ->midState == MID_RETRY_NEEDED) {
++ rc = -EAGAIN;
++ cFYI(1,("marking request for retry"));
++ } else {
++ rc = -EIO;
++ }
++ }
++ spin_unlock(&GlobalMid_Lock);
+ DeleteMidQEntry(midQ);
+- up(&ses->server->tcpSem);
+ /* If not lock req, update # of requests on wire to server */
+ if(long_op < 3) {
+ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+ return rc;
+- } else
+- up(&ses->server->tcpSem);
+-cifs_out_label:
+- if(midQ)
+- DeleteMidQEntry(midQ);
+-
++ }
++
++ if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
++ cERROR(1, ("Frame too large received. Length: %d Xid: %d",
++ receive_len, xid));
++ rc = -EIO;
++ } else { /* rcvd frame is ok */
++
++ if (midQ->resp_buf &&
++ (midQ->midState == MID_RESPONSE_RECEIVED)) {
++ in_buf->smb_buf_length = receive_len;
++ /* BB verify that length would not overrun small buf */
++ memcpy((char *)in_buf + 4,
++ (char *)midQ->resp_buf + 4,
++ receive_len);
++
++ dump_smb(in_buf, 80);
++ /* convert the length into a more usable form */
++ if((receive_len > 24) &&
++ (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
++ SECMODE_SIGN_ENABLED))) {
++ rc = cifs_verify_signature(in_buf,
++ ses->server->mac_signing_key,
++ midQ->sequence_number+1);
++ if(rc) {
++ cERROR(1,("Unexpected SMB signature"));
++ /* BB FIXME add code to kill session */
++ }
++ }
++
++ *pbytes_returned = in_buf->smb_buf_length;
++
++ /* BB special case reconnect tid and uid here? */
++ rc = map_smb_to_linux_error(in_buf);
++
++ /* convert ByteCount if necessary */
++ if (receive_len >=
++ sizeof (struct smb_hdr) -
++ 4 /* do not count RFC1001 header */ +
++ (2 * in_buf->WordCount) + 2 /* bcc */ )
++ BCC(in_buf) = le16_to_cpu(BCC(in_buf));
++ } else {
++ rc = -EIO;
++ cFYI(1,("Bad MID state?"));
++ }
++ }
++cifs_no_response_exit2:
++ DeleteMidQEntry(midQ);
++
+ if(long_op < 3) {
+- atomic_dec(&ses->server->inFlight);
++ atomic_dec(&ses->server->inFlight);
+ wake_up(&ses->server->request_q);
+ }
+
+ return rc;
+-}
+
++out_unlock2:
++ up(&ses->server->tcpSem);
++ /* If not lock req, update # of requests on wire to server */
++ if(long_op < 3) {
++ atomic_dec(&ses->server->inFlight);
++ wake_up(&ses->server->request_q);
++ }
+
++ return rc;
++}
+ #endif /* CIFS_EXPERIMENTAL */
+
+ int
+@@ -419,9 +584,15 @@ SendReceive(const unsigned int xid, stru
+ if(atomic_read(&ses->server->inFlight) >=
+ cifs_max_pending){
+ spin_unlock(&GlobalMid_Lock);
++#ifdef CONFIG_CIFS_STATS2
++ atomic_inc(&ses->server->num_waiters);
++#endif
+ wait_event(ses->server->request_q,
+ atomic_read(&ses->server->inFlight)
+ < cifs_max_pending);
++#ifdef CONFIG_CIFS_STATS2
++ atomic_dec(&ses->server->num_waiters);
++#endif
+ spin_lock(&GlobalMid_Lock);
+ } else {
+ if(ses->server->tcpStatus == CifsExiting) {
+@@ -490,8 +661,15 @@ SendReceive(const unsigned int xid, stru
+ rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+
+ midQ->midState = MID_REQUEST_SUBMITTED;
++#ifdef CONFIG_CIFS_STATS2
++ atomic_inc(&ses->server->inSend);
++#endif
+ rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+ (struct sockaddr *) &(ses->server->addr.sockAddr));
++#ifdef CONFIG_CIFS_STATS2
++ atomic_dec(&ses->server->inSend);
++ midQ->when_sent = jiffies;
++#endif
+ if(rc < 0) {
+ DeleteMidQEntry(midQ);
+ up(&ses->server->tcpSem);
+@@ -506,7 +684,7 @@ SendReceive(const unsigned int xid, stru
+ if (long_op == -1)
+ goto cifs_no_response_exit;
+ else if (long_op == 2) /* writes past end of file can take loong time */
+- timeout = 300 * HZ;
++ timeout = 180 * HZ;
+ else if (long_op == 1)
+ timeout = 45 * HZ; /* should be greater than
+ servers oplock break timeout (about 43 seconds) */
+@@ -540,9 +718,10 @@ SendReceive(const unsigned int xid, stru
+ spin_lock(&GlobalMid_Lock);
+ if (midQ->resp_buf) {
+ spin_unlock(&GlobalMid_Lock);
+- receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
++ receive_len = midQ->resp_buf->smb_buf_length;
+ } else {
+- cERROR(1,("No response buffer"));
++ cERROR(1,("No response for cmd %d mid %d",
++ midQ->command, midQ->mid));
+ if(midQ->midState == MID_REQUEST_SUBMITTED) {
+ if(ses->server->tcpStatus == CifsExiting)
+ rc = -EHOSTDOWN;
+@@ -610,7 +789,7 @@ SendReceive(const unsigned int xid, stru
+ BCC(out_buf) = le16_to_cpu(BCC(out_buf));
+ } else {
+ rc = -EIO;
+- cFYI(1,("Bad MID state? "));
++ cERROR(1,("Bad MID state? "));
+ }
+ }
+ cifs_no_response_exit:
+diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
+--- a/fs/coda/psdev.c
++++ b/fs/coda/psdev.c
+@@ -370,8 +370,8 @@ static int init_coda_psdev(void)
+ }
+ 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
+--- a/fs/compat.c
++++ b/fs/compat.c
+@@ -1490,7 +1490,6 @@ int compat_do_execve(char * filename,
+ /* 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
+--- a/fs/compat_ioctl.c
++++ b/fs/compat_ioctl.c
+@@ -3046,10 +3046,15 @@ HANDLE_IOCTL(RAW_GETBIND, raw_ioctl)
+ /* 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
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -689,7 +689,7 @@ void shrink_dcache_anon(struct hlist_hea
+ *
+ * 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
+--- a/fs/direct-io.c
++++ b/fs/direct-io.c
+@@ -162,6 +162,7 @@ static int dio_refill_pages(struct dio *
+ up_read(¤t->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 @@ static int dio_refill_pages(struct dio *
+ */
+ 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
+--- a/fs/dquot.c
++++ b/fs/dquot.c
+@@ -500,7 +500,7 @@ static void prune_dqcache(int count)
+ * 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 @@ static void add_dquot_ref(struct super_b
+ 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
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -126,8 +126,7 @@ asmlinkage long sys_uselib(const char __
+ 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 @@ asmlinkage long sys_uselib(const char __
+ 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 @@ asmlinkage long sys_uselib(const char __
+ out:
+ return error;
+ exit:
++ release_open_intent(&nd);
+ path_release(&nd);
+ goto out;
+ }
+@@ -309,40 +309,36 @@ void install_arg_page(struct vm_area_str
+ 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 @@ struct file *open_exec(const char *name)
+ 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 @@ struct file *open_exec(const char *name)
+ 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 @@ out:
+ return file;
+ }
+ }
++ release_open_intent(&nd);
+ path_release(&nd);
+ }
+ goto out;
+@@ -634,10 +630,9 @@ static inline int de_thread(struct task_
+ /*
+ * 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 @@ static inline int de_thread(struct task_
+ * 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 @@ static inline int de_thread(struct task_
+ }
+ sig->group_exit_task = NULL;
+ sig->notify_count = 0;
+- sig->real_timer.data = (unsigned long)current;
+ spin_unlock_irq(lock);
+
+ /*
+@@ -1207,7 +1203,6 @@ int do_execve(char * filename,
+ /* execve success */
+ security_bprm_free(bprm);
+ acct_update_integrals(current);
+- update_mem_hiwater(current);
+ kfree(bprm);
+ return retval;
+ }
+@@ -1422,19 +1417,16 @@ static void zap_threads (struct mm_struc
+ 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 @@ int do_coredump(long signr, int exit_cod
+ current->fsuid = 0; /* Dump root private */
+ }
+ mm->dumpable = 0;
+- init_completion(&mm->core_done);
++
++ retval = -EAGAIN;
+ spin_lock_irq(¤t->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(¤t->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
+--- a/fs/ext2/inode.c
++++ b/fs/ext2/inode.c
+@@ -440,6 +440,10 @@ static int ext2_alloc_branch(struct inod
+ * 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
+--- 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 @@ retry:
+ * 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 ext3_count_free_blocks(str
+ 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 @@ unsigned long ext3_count_free_blocks(str
+ 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
+--- 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
+--- /dev/null
++++ b/fs/ext3/bitmap.h
+@@ -0,0 +1,8 @@
++/* linux/fs/ext3/bitmap.c
++ *
++ * Copyright (C) 2005 Simtec Electronics
++ * Ben Dooks <ben at 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
+--- 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 ext3_count_free_inodes (st
+ 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 @@ unsigned long ext3_count_free_inodes (st
+ 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
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -491,7 +491,7 @@ static unsigned long ext3_find_goal(stru
+ * 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 @@ static int ext3_alloc_branch(handle_t *h
+ 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 @@ static int ext3_alloc_branch(handle_t *h
+ * 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 @@ struct buffer_head *ext3_getblk(handle_t
+ 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 @@ struct buffer_head *ext3_getblk(handle_t
+ }
+ return bh;
+ }
++err:
+ return NULL;
+ }
+
+@@ -1434,7 +1441,7 @@ static int ext3_invalidatepage(struct pa
+ 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
+--- 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
+--- /dev/null
++++ b/fs/ext3/namei.h
+@@ -0,0 +1,8 @@
++/* linux/fs/ext3/namei.h
++ *
++ * Copyright (C) 2005 Simtec Electronics
++ * Ben Dooks <ben at simtec.co.uk>
++ *
++*/
++
++extern struct dentry *ext3_get_parent(struct dentry *child);
+diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
+--- a/fs/ext3/resize.c
++++ b/fs/ext3/resize.c
+@@ -118,6 +118,8 @@ static struct buffer_head *bclean(handle
+ 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 @@ static int setup_new_group_blocks(struct
+ 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 @@ static void update_backups(struct super_
+ 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
+--- 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 @@ static void ext3_clear_inode(struct inod
+ 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 @@ static int ext3_show_options(struct seq_
+ 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 @@ static struct super_operations ext3_sops
+ #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
+--- a/fs/ext3/xattr.c
++++ b/fs/ext3/xattr.c
+@@ -210,7 +210,7 @@ ext3_xattr_find_entry(struct ext3_xattr_
+ 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 @@ ext3_xattr_list_entries(struct inode *in
+ 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 ext3_xattr_block_find {
+ 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_xattr_ibody_find {
+ 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
+--- a/fs/fat/dir.c
++++ b/fs/fat/dir.c
+@@ -222,6 +222,80 @@ fat_shortname2uni(struct nls_table *nls,
+ 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 @@ parse_record:
+ 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))
+- 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))
++ int status = fat_parse_long(inode, &cpos, &bh, &de,
++ &unicode, &nr_slots);
++ if (status < 0)
++ return status;
++ else if (status == PARSE_INVALID)
+ 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 @@ struct fat_ioctl_filldir_callback {
+ 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 @@ static int fat_readdirx(struct inode *in
+
+ 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 @@ GetNew:
+ }
+
+ 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))
+- 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)
++ 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;
+- 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 @@ out:
+ 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 @@ static int fat_dir_ioctl(struct inode *
+ 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
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -56,13 +56,13 @@ void filp_dtor(void * objp, struct kmem_
+
+ 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 @@ struct file *get_empty_filp(void)
+ 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 @@ void file_move(struct file *file, struct
+ 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 @@ int fs_may_remount_ro(struct super_block
+ /* 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
+--- 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
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -230,7 +230,6 @@ __sync_single_inode(struct inode *inode,
+ * The inode is clean, unused
+ */
+ list_move(&inode->i_list, &inode_unused);
+- inodes_stat.nr_unused++;
+ }
+ }
+ wake_up_inode(inode);
+@@ -238,14 +237,20 @@ __sync_single_inode(struct inode *inode,
+ }
+
+ /*
+- * 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|I_FREEING)));
++ 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 @@ __writeback_single_inode(struct inode *i
+
+ 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 @@ void sync_inodes(int wait)
+ }
+
+ /**
+- * 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
+--- a/fs/fuse/dev.c
++++ b/fs/fuse/dev.c
+@@ -151,9 +151,9 @@ void fuse_release_background(struct fuse
+ /*
+ * 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
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -741,13 +741,14 @@ static struct dentry *fuse_lookup(struct
+ 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
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -349,22 +349,22 @@ int fuse_fsync_common(struct file *file,
+ 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 @@ struct fuse_req *fuse_get_request(struct
+
+ /**
+ * 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_noreply(struct fuse_co
+ 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
+--- a/fs/hfs/inode.c
++++ b/fs/hfs/inode.c
+@@ -46,7 +46,7 @@ static sector_t hfs_bmap(struct address_
+ 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
+--- a/fs/hfsplus/inode.c
++++ b/fs/hfsplus/inode.c
+@@ -40,7 +40,7 @@ static sector_t hfsplus_bmap(struct addr
+ 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
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -45,10 +45,58 @@ static struct backing_dev_info hugetlbfs
+
+ 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 @@ static int hugetlbfs_file_mmap(struct fi
+ 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 @@ static int hugetlbfs_file_mmap(struct fi
+ 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 @@ out:
+ }
+
+ /*
+- * 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 @@ static int hugetlbfs_commit_write(struct
+ 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 truncate_hugepages(struct ad
+
+ 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);
+-
+- if (hlist_unhashed(&inode->i_hash))
+- goto out_truncate;
++ struct super_block *sb = inode->i_sb;
+
+- 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 @@ out_truncate:
+ 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 @@ out_truncate:
+ 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 @@ hugetlb_vmtruncate_list(struct prio_tree
+
+ 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 @@ hugetlb_vmtruncate_list(struct prio_tree
+ 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 @@ static struct inode *hugetlbfs_get_inode
+ 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 void hugetlbfs_put_super(struct s
+ }
+ }
+
++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;
+
++ if (unlikely(!hugetlbfs_dec_free_inodes(sbinfo)))
++ return NULL;
+ p = kmem_cache_alloc(hugetlbfs_inode_cachep, SLAB_KERNEL);
+- if (!p)
++ 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 @@ static struct address_space_operations h
+ .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 @@ static struct super_operations hugetlbfs
+ .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
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -475,7 +475,7 @@ static void prune_icache(int nr_to_scan)
+ * 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 @@ static void generic_forget_inode(struct
+ 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
+--- a/fs/jbd/journal.c
++++ b/fs/jbd/journal.c
+@@ -1606,7 +1606,7 @@ int journal_blocks_per_page(struct inode
+ * 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
+--- a/fs/jbd/transaction.c
++++ b/fs/jbd/transaction.c
+@@ -1621,7 +1621,7 @@ out:
+ * 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
+--- 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
+--- 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
+--- 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 @@ int dbSync(struct inode *ipbmap)
+ filemap_fdatawrite(ipbmap->i_mapping);
+ filemap_fdatawait(ipbmap->i_mapping);
+
+- ipbmap->i_state |= I_DIRTY;
+ diWriteSpecial(ipbmap, 0);
+
+ return (0);
+@@ -2467,7 +2466,9 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, i
+ * 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 @@ static void dbSplit(dmtree_t * tp, int l
+ *
+ * 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 @@ static void dbBackSplit(dmtree_t * tp, i
+ */
+ 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 @@ static void dbBackSplit(dmtree_t * tp, i
+ }
+ }
+
+- 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
+--- 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 @@ struct inode *diReadSpecial(struct super
+ /* release the page */
+ release_metapage(mp);
+
++ hlist_add_head(&ip->i_hash, &aggregate_hash);
++
+ return (ip);
+ }
+
+@@ -514,8 +522,6 @@ void diWriteSpecial(struct inode *ip, in
+ 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
+--- a/fs/jfs/jfs_metapage.c
++++ b/fs/jfs/jfs_metapage.c
+@@ -86,7 +86,7 @@ struct meta_anchor {
+ 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 @@ static inline int insert_metapage(struct
+ 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 @@ static inline void remove_metapage(struc
+ 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 @@ static inline void dec_io(struct page *p
+ #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 int insert_metapage(struct
+
+ 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 void init_once(void *foo, kmem_ca
+ }
+ }
+
+-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 @@ static int metapage_writepage(struct pag
+
+ 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 @@ add_failed:
+ 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
+--- a/fs/jfs/jfs_txnmgr.c
++++ b/fs/jfs/jfs_txnmgr.c
+@@ -2396,7 +2396,6 @@ static void txUpdateMap(struct tblock *
+ */
+ 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 @@ static void txUpdateMap(struct tblock *
+ } 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
+--- a/fs/jfs/jfs_xtree.c
++++ b/fs/jfs/jfs_xtree.c
+@@ -3516,16 +3516,10 @@ s64 xtTruncate(tid_t tid, struct inode *
+ /* 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 @@ s64 xtTruncate(tid_t tid, struct inode *
+ 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
+--- a/fs/jfs/super.c
++++ b/fs/jfs/super.c
+@@ -442,6 +442,7 @@ static int jfs_fill_super(struct super_b
+ 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
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -173,11 +173,10 @@ nlm_bind_host(struct nlm_host *host)
+
+ /* 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 @@ nlm_bind_host(struct nlm_host *host)
+ 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
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -316,21 +316,22 @@ static int flock_to_posix_lock(struct fi
+ /* 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) {
++ if (start < 0)
++ return -EINVAL;
++ 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;
+ }
+-
+- if (start < 0)
+- return -EINVAL;
+- if (l->l_len > 0 && end < 0)
+- return -EOVERFLOW;
+-
+ 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 @@ static int flock64_to_posix_lock(struct
+ 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 @@ static int __posix_lock_file(struct inod
+ /* 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
+--- a/fs/mbcache.c
++++ b/fs/mbcache.c
+@@ -116,7 +116,7 @@ mb_cache_indexes(struct mb_cache *cache)
+ * 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 @@ __mb_cache_entry_unhash(struct mb_cache_
+
+
+ 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 @@ forget:
+ * 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
+--- a/fs/msdos/namei.c
++++ b/fs/msdos/namei.c
+@@ -454,10 +454,10 @@ static int do_msdos_rename(struct inode
+ {
+ 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 @@ static int do_msdos_rename(struct inode
+ 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 @@ error_inode:
+ 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
+--- 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 @@ void path_release_on_umount(struct namei
+ 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 @@ static fastcall int __link_path_walk(con
+ 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 @@ static fastcall int __link_path_walk(con
+ 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 @@ out:
+ 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 @@ static inline int may_create(struct inod
+ }
+
+ /*
+- * 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 @@ static inline int lookup_flags(unsigned
+ 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 may_open(struct nameidata *nd, int a
+ */
+ 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 @@ int open_namei(const char * pathname, in
+ /*
+ * 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 @@ ok:
+ 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
+--- a/fs/nfs/delegation.c
++++ b/fs/nfs/delegation.c
+@@ -142,7 +142,7 @@ static void nfs_msync_inode(struct inode
+ /*
+ * 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
+--- a/fs/nfs/delegation.h
++++ b/fs/nfs/delegation.h
+@@ -25,7 +25,7 @@ struct nfs_delegation {
+
+ 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 @@ static inline int nfs_have_delegation(st
+ 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
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -532,6 +532,7 @@ static int nfs_readdir(struct file *filp
+ 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 @@ static int nfs_readdir(struct file *filp
+ }
+ }
+ unlock_kernel();
+- if (desc->error < 0)
+- return desc->error;
+ if (res < 0)
+ return res;
+ return 0;
+@@ -803,6 +802,7 @@ static int nfs_dentry_delete(struct dent
+ */
+ 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 @@ static struct dentry *nfs_lookup(struct
+ 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 int is_atomic_open(struct inode *
+ 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 @@ static struct dentry *nfs_atomic_lookup(
+ 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 @@ static struct dentry *nfs_atomic_lookup(
+
+ 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 @@ static int nfs_open_revalidate(struct de
+ */
+ 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 @@ static int nfs_create(struct inode *dir,
+
+ 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 @@ static int nfs_safe_remove(struct dentry
+
+ 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 @@ nfs_link(struct dentry *old_dentry, stru
+ 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 @@ static int nfs_rename(struct inode *old_
+ */
+ 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 @@ static int nfs_rename(struct inode *old_
+ #endif
+ goto out;
+ }
+- }
++ } else
++ new_inode->i_nlink--;
+
+ go_ahead:
+ /*
+@@ -1549,6 +1543,7 @@ go_ahead:
+ 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
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -205,8 +205,8 @@ nfs_file_flush(struct file *file)
+ 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 @@ out_swapfile:
+
+ 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
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -358,6 +358,35 @@ out_no_root:
+ 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 @@ nfs_create_client(struct nfs_server *ser
+ 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 @@ static int nfs_show_options(struct seq_f
+ { 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 @@ static int nfs_show_options(struct seq_f
+ };
+ 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 @@ static int nfs_show_options(struct seq_f
+ 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 @@ nfs_fhget(struct super_block *sb, struct
+ 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 @@ nfs_setattr(struct dentry *dentry, struc
+ 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 @@ int nfs_open(struct inode *inode, struct
+ 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 @@ __nfs_revalidate_inode(struct nfs_server
+ 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 @@ __nfs_revalidate_inode(struct nfs_server
+ * 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 @@ void nfs_revalidate_mapping(struct inode
+ 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 @@ void nfs_end_data_update(struct inode *i
+ 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 @@ void nfs_end_data_update(struct inode *i
+ * 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 @@ int nfs_refresh_inode(struct inode *inod
+ }
+
+ 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 @@ int nfs_refresh_inode(struct inode *inod
+ 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 @@ static int nfs_update_inode(struct inode
+ 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 @@ static int nfs_update_inode(struct inode
+ /* 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 @@ static int nfs_update_inode(struct inode
+ if (!nfs_have_delegation(inode, FMODE_READ))
+ nfsi->cache_validity |= invalid;
+
+- spin_unlock(&inode->i_lock);
+ return 0;
+ out_changed:
+ /*
+@@ -1639,8 +1722,7 @@ static void nfs4_clear_inode(struct inod
+ 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 @@ static int nfs4_fill_super(struct super_
+ 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 @@ static int nfs4_fill_super(struct super_
+ 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 @@ static int nfs4_fill_super(struct super_
+
+ 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
+--- a/fs/nfs/nfs2xdr.c
++++ b/fs/nfs/nfs2xdr.c
+@@ -143,7 +143,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fatt
+ 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
+--- a/fs/nfs/nfs3proc.c
++++ b/fs/nfs/nfs3proc.c
+@@ -78,7 +78,7 @@ nfs3_proc_get_root(struct nfs_server *se
+ 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 @@ nfs3_proc_getattr(struct nfs_server *ser
+ 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 @@ nfs3_proc_setattr(struct dentry *dentry,
+ 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 @@ nfs3_proc_lookup(struct inode *dir, stru
+ 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 @@ static int nfs3_proc_access(struct inode
+ int status;
+
+ dprintk("NFS call access\n");
+- fattr.valid = 0;
+
+ if (mode & MAY_READ)
+ arg.access |= NFS3_ACCESS_READ;
+@@ -189,6 +188,7 @@ static int nfs3_proc_access(struct inode
+ 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 @@ static int nfs3_proc_readlink(struct ino
+ 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 @@ static int nfs3_proc_read(struct nfs_rea
+
+ 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 @@ static int nfs3_proc_write(struct nfs_wr
+
+ 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 @@ static int nfs3_proc_commit(struct nfs_w
+
+ 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_commit(struct nfs_w
+ */
+ 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 @@ nfs3_proc_create(struct inode *dir, stru
+ 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 @@ nfs3_proc_remove(struct inode *dir, stru
+ 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 @@ nfs3_proc_unlink_setup(struct rpc_messag
+ 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 @@ nfs3_proc_unlink_done(struct dentry *dir
+ 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 @@ nfs3_proc_rename(struct inode *old_dir,
+ 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 @@ nfs3_proc_link(struct inode *inode, stru
+ 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 @@ nfs3_proc_symlink(struct inode *dir, str
+ 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 @@ nfs3_proc_mkdir(struct inode *dir, struc
+ 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 @@ nfs3_proc_rmdir(struct inode *dir, struc
+ 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 @@ nfs3_proc_readdir(struct dentry *dentry,
+ 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 @@ nfs3_proc_mknod(struct inode *dir, struc
+
+ 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 @@ nfs3_proc_statfs(struct nfs_server *serv
+ 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 @@ nfs3_proc_fsinfo(struct nfs_server *serv
+ 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 @@ nfs3_proc_pathconf(struct nfs_server *se
+ 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 @@ extern u32 *nfs3_decode_dirent(u32 *, st
+ 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 @@ nfs3_write_done(struct rpc_task *task)
+ 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 @@ nfs3_commit_done(struct rpc_task *task)
+ 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
+--- a/fs/nfs/nfs3xdr.c
++++ b/fs/nfs/nfs3xdr.c
+@@ -174,7 +174,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fatt
+
+ /* 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
+--- a/fs/nfs/nfs4_fs.h
++++ b/fs/nfs/nfs4_fs.h
+@@ -93,25 +93,50 @@ struct nfs4_client {
+ };
+
+ /*
++ * 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 @@ struct nfs4_lock_state {
+ 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 nfs4_state {
+ 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_setclientid_confirm
+ 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 struct nfs4_state * nfs4_get_open
+ 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
+--- 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 @@ static void update_changeattr(struct ino
+ {
+ 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 @@ static void update_open_stateid(struct n
+
+ 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 @@ static void update_open_stateid(struct n
+ 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 @@ static int _nfs4_open_reclaim(struct nfs
+ 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 @@ static int _nfs4_open_reclaim(struct nfs
+ }
+ 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 @@ static int _nfs4_open_reclaim(struct nfs
+ 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 @@ static int _nfs4_open_delegation_recall(
+ };
+ 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 @@ int nfs4_open_delegation_recall(struct d
+ 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 @@ static inline int _nfs4_proc_open_confir
+ 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 @@ static int _nfs4_proc_open(struct inode
+ 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 @@ static int _nfs4_open_expired(struct nfs
+ 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 @@ static int _nfs4_open_expired(struct nfs
+ };
+ struct nfs_openres o_res = {
+ .f_attr = &f_attr,
++ .dir_attr = &dir_attr,
+ .server = server,
+ };
+ int status = 0;
+@@ -465,6 +524,12 @@ static int _nfs4_open_expired(struct nfs
+ 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 @@ static int _nfs4_open_expired(struct nfs
+ 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 @@ static int _nfs4_open_delegated(struct i
+ 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 @@ static int _nfs4_open_delegated(struct i
+ 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 @@ out_err:
+ 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 @@ static int _nfs4_do_open(struct inode *d
+ 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 @@ static int _nfs4_do_open(struct inode *d
+ };
+ struct nfs_openres o_res = {
+ .f_attr = &f_attr,
++ .dir_attr = &dir_attr,
+ .server = server,
+ };
+
+@@ -665,8 +729,12 @@ static int _nfs4_do_open(struct inode *d
+ } 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 @@ static int _nfs4_do_open(struct inode *d
+ 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 @@ out_err:
+ 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 @@ static struct nfs4_state *nfs4_do_open(s
+ * 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 @@ static struct nfs4_state *nfs4_do_open(s
+ 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 @@ static int _nfs4_do_setattr(struct nfs_s
+ };
+ 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_closedata {
+ 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 @@ static void nfs4_close_done(struct rpc_t
+ 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 @@ static inline int nfs4_close_call(struct
+ */
+ 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;
++}
++
++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 inode *
++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 @@ nfs4_atomic_open(struct inode *dir, stru
+
+ 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 @@ nfs4_open_revalidate(struct inode *dir,
+ 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_server_capabilities(stru
+ 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 @@ static int _nfs4_lookup_root(struct nfs_
+ .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 @@ static int nfs4_proc_get_root(struct nfs
+ 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 @@ static int _nfs4_proc_getattr(struct nfs
+ .rpc_resp = &res,
+ };
+
+- fattr->valid = 0;
++ nfs_fattr_init(fattr);
+ return rpc_call_sync(server->client, &msg, 0);
+ }
+
+@@ -1130,7 +1278,7 @@ nfs4_proc_setattr(struct dentry *dentry,
+ 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 @@ static int _nfs4_proc_lookup(struct inod
+ .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 @@ static int _nfs4_proc_read(struct nfs_re
+ 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 @@ static int _nfs4_proc_write(struct nfs_w
+ 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 @@ static int _nfs4_proc_commit(struct nfs_
+ 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_commit(struct nfs_w
+
+ 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 @@ nfs4_proc_create(struct inode *dir, stru
+ 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 nfs_fattr dir_attr;
++ struct nfs4_remove_res res = {
++ .server = server,
++ .dir_attr = &dir_attr,
+ };
+- struct nfs4_change_info res;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
+ .rpc_argp = &args,
+@@ -1478,9 +1632,12 @@ static int _nfs4_proc_remove(struct inod
+ };
+ 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 @@ static int nfs4_proc_remove(struct inode
+
+ 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 @@ static int nfs4_proc_unlink_setup(struct
+
+ 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 @@ static int nfs4_proc_unlink_done(struct
+
+ 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_unlink_done(struct
+ 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 nfs_fattr old_fattr, new_fattr;
++ struct nfs4_rename_res res = {
++ .server = server,
++ .old_fattr = &old_fattr,
++ .new_fattr = &new_fattr,
+ };
+- struct nfs4_rename_res res = { };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
+ .rpc_argp = &arg,
+@@ -1551,11 +1721,15 @@ static int _nfs4_proc_rename(struct inod
+ };
+ 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_rename(struct inode
+
+ 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 nfs_fattr fattr, dir_attr;
++ struct nfs4_link_res res = {
++ .server = server,
++ .fattr = &fattr,
++ .dir_attr = &dir_attr,
+ };
+- struct nfs4_change_info cinfo = { };
+ 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 @@ static int _nfs4_proc_symlink(struct ino
+ 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 @@ static int _nfs4_proc_symlink(struct ino
+ .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 @@ static int _nfs4_proc_symlink(struct ino
+ 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 @@ static int _nfs4_proc_mkdir(struct inode
+ {
+ 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 @@ static int _nfs4_proc_mkdir(struct inode
+ .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 @@ static int _nfs4_proc_mkdir(struct inode
+ };
+ 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 @@ static int _nfs4_proc_mknod(struct inode
+ {
+ 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 @@ static int _nfs4_proc_mknod(struct inode
+ .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 @@ static int _nfs4_proc_mknod(struct inode
+ 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 @@ static int _nfs4_proc_mknod(struct inode
+ 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 @@ static int _nfs4_proc_statfs(struct nfs_
+ .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_do_fsinfo(struct nfs_ser
+
+ 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 @@ static int _nfs4_proc_pathconf(struct nf
+ return 0;
+ }
+
+- pathconf->fattr->valid = 0;
++ nfs_fattr_init(pathconf->fattr);
+ return rpc_call_sync(server->client, &msg, 0);
+ }
+
+@@ -1973,8 +2169,10 @@ nfs4_write_done(struct rpc_task *task)
+ 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 @@ nfs4_proc_write_setup(struct nfs_write_d
+ .rpc_cred = data->cred,
+ };
+ struct inode *inode = data->inode;
++ struct nfs_server *server = NFS_SERVER(inode);
+ int stable;
+ int flags;
+
+@@ -2001,6 +2200,8 @@ nfs4_proc_write_setup(struct nfs_write_d
+ } 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 @@ nfs4_commit_done(struct rpc_task *task)
+ 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 @@ nfs4_proc_commit_setup(struct nfs_write_
+ .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 @@ nfs4_proc_renew(struct nfs4_client *clp)
+ 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 @@ static inline ssize_t nfs4_get_acl_uncac
+ 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 @@ static int nfs4_proc_set_acl(struct inod
+
+ 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_proc_set_acl(struct inod
+ }
+
+ 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 @@ static int nfs4_delay(struct rpc_clnt *c
+ /* 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 @@ static int _nfs4_proc_getlk(struct nfs4_
+
+ 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 @@ static int _nfs4_proc_getlk(struct nfs4_
+ status = 0;
+ }
+ out:
+- up(&state->lock_sema);
+ up_read(&clp->cl_sem);
+ return status;
+ }
+@@ -2696,67 +2843,125 @@ static int do_vfs_lock(struct file *file
+ 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,
+ };
++ int 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_unlockdata *calldata;
++ struct inode *inode = state->inode;
++ struct nfs_server *server = NFS_SERVER(inode);
+ 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;
++ return status;
+ 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);
++ 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);
+
+- 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;
+-}
++ /* 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);
+
+-static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+-{
+- struct nfs4_exception exception = { };
+- int err;
++ atomic_set(&calldata->refcount, 2);
++ init_completion(&calldata->completion);
+
+- do {
+- err = nfs4_handle_exception(NFS_SERVER(state->inode),
+- _nfs4_proc_unlck(state, cmd, request),
+- &exception);
+- } while (exception.retry);
+- return err;
++ 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 @@ static int _nfs4_do_setlk(struct nfs4_st
+ 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 @@ static int _nfs4_do_setlk(struct nfs4_st
+ .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 = ⪙
+- 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 @@ static int _nfs4_proc_setlk(struct nfs4_
+ 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 @@ struct nfs_rpc_ops nfs_v4_clientops = {
+ .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
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -264,13 +264,16 @@ nfs4_alloc_state_owner(void)
+ {
+ 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 @@ nfs4_alloc_open_state(void)
+ 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 @@ nfs4_get_open_state(struct inode *inode,
+ 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 @@ out:
+
+ /*
+ * 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 @@ void nfs4_put_open_state(struct nfs4_sta
+ }
+
+ /*
+- * 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 @@ void nfs4_close_state(struct nfs4_state
+ 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 @@ void nfs4_close_state(struct nfs4_state
+ 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 @@ __nfs4_find_lock_state(struct nfs4_state
+ * 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 @@ static struct nfs4_lock_state *nfs4_allo
+ * 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 @@ static struct nfs4_lock_state *nfs4_get_
+ * 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 @@ void nfs4_copy_stateid(nfs4_stateid *dst
+ 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)
+-{
+- if (status == NFS_OK || seqid_mutating_err(-status))
+- lsp->ls_seqid++;
++struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
++{
++ 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)
+-{
+- 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)
++ * 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)
++{
++ 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 @@ static int nfs4_reclaim_open_state(struc
+ 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 @@ out_err:
+ 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 @@ restart_loop:
+ 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
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -95,6 +95,8 @@ static int nfs_stat_to_errno(int);
+ #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 @@ static int nfs_stat_to_errno(int);
+ 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 @@ static int nfs_stat_to_errno(int);
+ #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 @@ static int nfs_stat_to_errno(int);
+ 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 @@ static int nfs_stat_to_errno(int);
+ 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 @@ static int encode_close(struct xdr_strea
+ {
+ 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 @@ static int encode_lock(struct xdr_stream
+ 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 @@ static int encode_locku(struct xdr_strea
+ 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 @@ static inline void encode_openhdr(struct
+ */
+ 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 @@ static int encode_open_confirm(struct xd
+ 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 @@ static int encode_open_downgrade(struct
+ {
+ 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_renew(struct xdr_strea
+ }
+
+ 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 @@ static int nfs4_xdr_enc_remove(struct rp
+ {
+ 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 @@ static int nfs4_xdr_enc_rename(struct rp
+ {
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+- .nops = 4,
++ .nops = 7,
+ };
+ int status;
+
+@@ -1326,7 +1367,13 @@ static int nfs4_xdr_enc_rename(struct rp
+ 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 @@ static int nfs4_xdr_enc_link(struct rpc_
+ {
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+- .nops = 4,
++ .nops = 7,
+ };
+ int status;
+
+@@ -1350,7 +1397,13 @@ static int nfs4_xdr_enc_link(struct rpc_
+ 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 @@ static int nfs4_xdr_enc_create(struct rp
+ {
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+- .nops = 4,
++ .nops = 7,
+ };
+ int status;
+
+@@ -1370,10 +1423,16 @@ static int nfs4_xdr_enc_create(struct rp
+ 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 @@ static int nfs4_xdr_enc_close(struct rpc
+ {
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+- .nops = 2,
++ .nops = 3,
+ };
+ int status;
+
+@@ -1422,6 +1481,9 @@ static int nfs4_xdr_enc_close(struct rpc
+ 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 @@ static int nfs4_xdr_enc_open(struct rpc_
+ {
+ 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 @@ static int nfs4_xdr_enc_open(struct rpc_
+ 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 @@ static int nfs4_xdr_enc_open_confirm(str
+ };
+ 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 @@ static int nfs4_xdr_enc_open_noattr(stru
+ };
+ 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 @@ static int nfs4_xdr_enc_open_downgrade(s
+ {
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+- .nops = 2,
++ .nops = 3,
+ };
+ int status;
+
+@@ -1512,6 +1592,9 @@ static int nfs4_xdr_enc_open_downgrade(s
+ 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 @@ static int nfs4_xdr_enc_lock(struct rpc_
+ 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 @@ static int nfs4_xdr_enc_write(struct rpc
+ {
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+- .nops = 2,
++ .nops = 3,
+ };
+ int status;
+
+@@ -1723,6 +1813,9 @@ static int nfs4_xdr_enc_write(struct rpc
+ 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 @@ static int nfs4_xdr_enc_commit(struct rp
+ {
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+- .nops = 2,
++ .nops = 3,
+ };
+ int status;
+
+@@ -1744,6 +1837,9 @@ static int nfs4_xdr_enc_commit(struct rp
+ 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 @@ static int decode_server_caps(struct xdr
+ 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 @@ static int decode_statfs(struct xdr_stre
+
+ 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 @@ static int decode_pathconf(struct xdr_st
+
+ 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 @@ static int decode_getfattr(struct xdr_st
+ 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 @@ static int decode_fsinfo(struct xdr_stre
+
+ 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 @@ static int decode_lock(struct xdr_stream
+
+ 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 @@ static int decode_locku(struct xdr_strea
+
+ 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 @@ static int decode_open(struct xdr_stream
+ 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 @@ static int decode_renew(struct xdr_strea
+ 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 @@ static int decode_getacl(struct xdr_stre
+ if (attrlen <= *acl_len)
+ xdr_read_pages(xdr, attrlen);
+ *acl_len = attrlen;
+- }
++ } else
++ status = -EOPNOTSUPP;
+
+ out:
+ return status;
+@@ -3352,6 +3448,9 @@ static int nfs4_xdr_dec_open_downgrade(s
+ 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 @@ out:
+ /*
+ * 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 @@ static int nfs4_xdr_dec_remove(struct rp
+ 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 @@ static int nfs4_xdr_dec_rename(struct rp
+ 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 @@ out:
+ /*
+ * 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 @@ static int nfs4_xdr_dec_link(struct rpc_
+ 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 @@ static int nfs4_xdr_dec_create(struct rp
+ 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 @@ static int nfs4_xdr_dec_close(struct rpc
+ 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 @@ static int nfs4_xdr_dec_open(struct rpc_
+ 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 @@ static int nfs4_xdr_dec_write(struct rpc
+ 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 @@ static int nfs4_xdr_dec_commit(struct rp
+ 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
+--- a/fs/nfs/proc.c
++++ b/fs/nfs/proc.c
+@@ -61,7 +61,7 @@ nfs_proc_get_root(struct nfs_server *ser
+ 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 @@ nfs_proc_getattr(struct nfs_server *serv
+ 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 @@ nfs_proc_setattr(struct dentry *dentry,
+ 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 @@ nfs_proc_lookup(struct inode *dir, struc
+ 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 @@ static int nfs_proc_read(struct nfs_read
+
+ 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 @@ static int nfs_proc_write(struct nfs_wri
+
+ 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_write(struct nfs_wri
+
+ 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 @@ nfs_proc_create(struct inode *dir, struc
+ };
+ 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 @@ nfs_proc_mknod(struct inode *dir, struct
+ 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 @@ nfs_proc_remove(struct inode *dir, struc
+
+ 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 @@ nfs_proc_unlink_done(struct dentry *dir,
+ {
+ 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 @@ nfs_proc_rename(struct inode *old_dir, s
+
+ 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 @@ nfs_proc_link(struct inode *inode, struc
+
+ 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 @@ nfs_proc_symlink(struct inode *dir, stru
+ 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 @@ nfs_proc_mkdir(struct inode *dir, struct
+ 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 @@ nfs_proc_rmdir(struct inode *dir, struct
+
+ 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 @@ nfs_proc_statfs(struct nfs_server *serve
+ 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 @@ nfs_proc_fsinfo(struct nfs_server *serve
+ 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 @@ nfs_write_done(struct rpc_task *task)
+ 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
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -215,6 +215,7 @@ static void nfs_read_rpcsetup(struct nfs
+ 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
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -870,6 +870,7 @@ static void nfs_write_rpcsetup(struct nf
+ 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 @@ static void nfs_commit_rpcsetup(struct l
+ 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/ntfs/ChangeLog b/fs/ntfs/ChangeLog
+--- a/fs/ntfs/ChangeLog
++++ b/fs/ntfs/ChangeLog
+@@ -1,18 +1,15 @@
+ ToDo/Notes:
+ - Find and fix bugs.
+- - In between ntfs_prepare/commit_write, need exclusion between
+- simultaneous file extensions. This is given to us by holding i_sem
+- on the inode. The only places in the kernel when a file is resized
+- are prepare/commit write and truncate for both of which i_sem is
+- held. Just have to be careful in readpage/writepage and all other
+- helpers not running under i_sem that we play nice...
+- Also need to be careful with initialized_size extention in
+- ntfs_prepare_write. Basically, just be _very_ careful in this code...
+- UPDATE: The only things that need to be checked are read/writepage
+- which do not hold i_sem. Note writepage cannot change i_size but it
+- needs to cope with a concurrent i_size change, just like readpage.
+- Also both need to cope with concurrent changes to the other sizes,
+- i.e. initialized/allocated/compressed size, as well.
++ - The only places in the kernel where a file is resized are
++ ntfs_file_write*() and ntfs_truncate() for both of which i_sem is
++ held. Just have to be careful in read-/writepage and other helpers
++ not running under i_sem that we play nice... Also need to be careful
++ with initialized_size extension in ntfs_file_write*() and writepage.
++ UPDATE: The only things that need to be checked are the compressed
++ write and the other attribute resize/write cases like index
++ attributes, etc. For now none of these are implemented so are safe.
++ - Implement filling in of holes in aops.c::ntfs_writepage() and its
++ helpers.
+ - Implement mft.c::sync_mft_mirror_umount(). We currently will just
+ leave the volume dirty on umount if the final iput(vol->mft_ino)
+ causes a write of any mirrored mft records due to the mft mirror
+@@ -22,6 +19,68 @@ ToDo/Notes:
+ - Enable the code for setting the NT4 compatibility flag when we start
+ making NTFS 1.2 specific modifications.
+
++2.1.25 - (Almost) fully implement write(2) and truncate(2).
++
++ - Change ntfs_map_runlist_nolock(), ntfs_attr_find_vcn_nolock() and
++ {__,}ntfs_cluster_free() to also take an optional attribute search
++ context as argument. This allows calling these functions with the
++ mft record mapped. Update all callers.
++ - Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock()
++ error handling by passing in the active search context when calling
++ ntfs_cluster_free().
++ - Change ntfs_cluster_alloc() to take an extra boolean parameter
++ specifying whether the cluster are being allocated to extend an
++ attribute or to fill a hole.
++ - Change ntfs_attr_make_non_resident() to call ntfs_cluster_alloc()
++ with @is_extension set to TRUE and remove the runlist terminator
++ fixup code as this is now done by ntfs_cluster_alloc().
++ - Change ntfs_attr_make_non_resident to take the attribute value size
++ as an extra parameter. This is needed since we need to know the size
++ before we can map the mft record and our callers always know it. The
++ reason we cannot simply read the size from the vfs inode i_size is
++ that this is not necessarily uptodate. This happens when
++ ntfs_attr_make_non_resident() is called in the ->truncate call path.
++ - Fix ntfs_attr_make_non_resident() to update the vfs inode i_blocks
++ which is zero for a resident attribute but should no longer be zero
++ once the attribute is non-resident as it then has real clusters
++ allocated.
++ - Add fs/ntfs/attrib.[hc]::ntfs_attr_extend_allocation(), a function to
++ extend the allocation of an attributes. Optionally, the data size,
++ but not the initialized size can be extended, too.
++ - Implement fs/ntfs/inode.[hc]::ntfs_truncate(). It only supports
++ uncompressed and unencrypted files and it never creates sparse files
++ at least for the moment (making a file sparse requires us to modify
++ its directory entries and we do not support directory operations at
++ the moment). Also, support for highly fragmented files, i.e. ones
++ whose data attribute is split across multiple extents, is severly
++ limited. When such a case is encountered, EOPNOTSUPP is returned.
++ - Enable ATTR_SIZE attribute changes in ntfs_setattr(). This completes
++ the initial implementation of file truncation. Now both open(2)ing
++ a file with the O_TRUNC flag and the {,f}truncate(2) system calls
++ will resize a file appropriately. The limitations are that only
++ uncompressed and unencrypted files are supported. Also, there is
++ only very limited support for highly fragmented files (the ones whose
++ $DATA attribute is split into multiple attribute extents).
++ - In attrib.c::ntfs_attr_set() call balance_dirty_pages_ratelimited()
++ and cond_resched() in the main loop as we could be dirtying a lot of
++ pages and this ensures we play nice with the VM and the system as a
++ whole.
++ - Implement file operations ->write, ->aio_write, ->writev for regular
++ files. This replaces the old use of generic_file_write(), et al and
++ the address space operations ->prepare_write and ->commit_write.
++ This means that both sparse and non-sparse (unencrypted and
++ uncompressed) files can now be extended using the normal write(2)
++ code path. There are two limitations at present and these are that
++ we never create sparse files and that we only have limited support
++ for highly fragmented files, i.e. ones whose data attribute is split
++ across multiple extents. When such a case is encountered,
++ EOPNOTSUPP is returned.
++ - $EA attributes can be both resident and non-resident.
++ - Use %z for size_t to fix compilation warnings. (Andrew Morton)
++ - Fix compilation warnings with gcc-4.0.2 on SUSE 10.0.
++ - Document extended attribute ($EA) NEED_EA flag. (Based on libntfs
++ patch by Yura Pakhuchiy.)
++
+ 2.1.24 - Lots of bug fixes and support more clean journal states.
+
+ - Support journals ($LogFile) which have been modified by chkdsk. This
+diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
+--- a/fs/ntfs/Makefile
++++ b/fs/ntfs/Makefile
+@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o c
+ index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
+ unistr.o upcase.o
+
+-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.24\"
++EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.25\"
+
+ ifeq ($(CONFIG_NTFS_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
+diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
+--- a/fs/ntfs/aops.c
++++ b/fs/ntfs/aops.c
+@@ -1391,8 +1391,7 @@ retry_writepage:
+ if (NInoEncrypted(ni)) {
+ unlock_page(page);
+ BUG_ON(ni->type != AT_DATA);
+- ntfs_debug("Denying write access to encrypted "
+- "file.");
++ ntfs_debug("Denying write access to encrypted file.");
+ return -EACCES;
+ }
+ /* Compressed data streams are handled in compress.c. */
+@@ -1508,8 +1507,8 @@ retry_writepage:
+ /* Zero out of bounds area in the page cache page. */
+ memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
+ kunmap_atomic(kaddr, KM_USER0);
+- flush_dcache_mft_record_page(ctx->ntfs_ino);
+ flush_dcache_page(page);
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
+ /* We are done with the page. */
+ end_page_writeback(page);
+ /* Finally, mark the mft record dirty, so it gets written back. */
+@@ -1542,830 +1541,6 @@ err_out:
+ return err;
+ }
+
+-/**
+- * ntfs_prepare_nonresident_write -
+- *
+- */
+-static int ntfs_prepare_nonresident_write(struct page *page,
+- unsigned from, unsigned to)
+-{
+- VCN vcn;
+- LCN lcn;
+- s64 initialized_size;
+- loff_t i_size;
+- sector_t block, ablock, iblock;
+- struct inode *vi;
+- ntfs_inode *ni;
+- ntfs_volume *vol;
+- runlist_element *rl;
+- struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
+- unsigned long flags;
+- unsigned int vcn_ofs, block_start, block_end, blocksize;
+- int err;
+- BOOL is_retry;
+- unsigned char blocksize_bits;
+-
+- vi = page->mapping->host;
+- ni = NTFS_I(vi);
+- vol = ni->vol;
+-
+- ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
+- "0x%lx, from = %u, to = %u.", ni->mft_no, ni->type,
+- page->index, from, to);
+-
+- BUG_ON(!NInoNonResident(ni));
+-
+- blocksize_bits = vi->i_blkbits;
+- blocksize = 1 << blocksize_bits;
+-
+- /*
+- * create_empty_buffers() will create uptodate/dirty buffers if the
+- * page is uptodate/dirty.
+- */
+- if (!page_has_buffers(page))
+- create_empty_buffers(page, blocksize, 0);
+- bh = head = page_buffers(page);
+- if (unlikely(!bh))
+- return -ENOMEM;
+-
+- /* The first block in the page. */
+- block = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
+-
+- read_lock_irqsave(&ni->size_lock, flags);
+- /*
+- * The first out of bounds block for the allocated size. No need to
+- * round up as allocated_size is in multiples of cluster size and the
+- * minimum cluster size is 512 bytes, which is equal to the smallest
+- * blocksize.
+- */
+- ablock = ni->allocated_size >> blocksize_bits;
+- i_size = i_size_read(vi);
+- initialized_size = ni->initialized_size;
+- read_unlock_irqrestore(&ni->size_lock, flags);
+-
+- /* The last (fully or partially) initialized block. */
+- iblock = initialized_size >> blocksize_bits;
+-
+- /* Loop through all the buffers in the page. */
+- block_start = 0;
+- rl = NULL;
+- err = 0;
+- do {
+- block_end = block_start + blocksize;
+- /*
+- * If buffer @bh is outside the write, just mark it uptodate
+- * if the page is uptodate and continue with the next buffer.
+- */
+- if (block_end <= from || block_start >= to) {
+- if (PageUptodate(page)) {
+- if (!buffer_uptodate(bh))
+- set_buffer_uptodate(bh);
+- }
+- continue;
+- }
+- /*
+- * @bh is at least partially being written to.
+- * Make sure it is not marked as new.
+- */
+- //if (buffer_new(bh))
+- // clear_buffer_new(bh);
+-
+- if (block >= ablock) {
+- // TODO: block is above allocated_size, need to
+- // allocate it. Best done in one go to accommodate not
+- // only block but all above blocks up to and including:
+- // ((page->index << PAGE_CACHE_SHIFT) + to + blocksize
+- // - 1) >> blobksize_bits. Obviously will need to round
+- // up to next cluster boundary, too. This should be
+- // done with a helper function, so it can be reused.
+- ntfs_error(vol->sb, "Writing beyond allocated size "
+- "is not supported yet. Sorry.");
+- err = -EOPNOTSUPP;
+- goto err_out;
+- // Need to update ablock.
+- // Need to set_buffer_new() on all block bhs that are
+- // newly allocated.
+- }
+- /*
+- * Now we have enough allocated size to fulfill the whole
+- * request, i.e. block < ablock is true.
+- */
+- if (unlikely((block >= iblock) &&
+- (initialized_size < i_size))) {
+- /*
+- * If this page is fully outside initialized size, zero
+- * out all pages between the current initialized size
+- * and the current page. Just use ntfs_readpage() to do
+- * the zeroing transparently.
+- */
+- if (block > iblock) {
+- // TODO:
+- // For each page do:
+- // - read_cache_page()
+- // Again for each page do:
+- // - wait_on_page_locked()
+- // - Check (PageUptodate(page) &&
+- // !PageError(page))
+- // Update initialized size in the attribute and
+- // in the inode.
+- // Again, for each page do:
+- // __set_page_dirty_buffers();
+- // page_cache_release()
+- // We don't need to wait on the writes.
+- // Update iblock.
+- }
+- /*
+- * The current page straddles initialized size. Zero
+- * all non-uptodate buffers and set them uptodate (and
+- * dirty?). Note, there aren't any non-uptodate buffers
+- * if the page is uptodate.
+- * FIXME: For an uptodate page, the buffers may need to
+- * be written out because they were not initialized on
+- * disk before.
+- */
+- if (!PageUptodate(page)) {
+- // TODO:
+- // Zero any non-uptodate buffers up to i_size.
+- // Set them uptodate and dirty.
+- }
+- // TODO:
+- // Update initialized size in the attribute and in the
+- // inode (up to i_size).
+- // Update iblock.
+- // FIXME: This is inefficient. Try to batch the two
+- // size changes to happen in one go.
+- ntfs_error(vol->sb, "Writing beyond initialized size "
+- "is not supported yet. Sorry.");
+- err = -EOPNOTSUPP;
+- goto err_out;
+- // Do NOT set_buffer_new() BUT DO clear buffer range
+- // outside write request range.
+- // set_buffer_uptodate() on complete buffers as well as
+- // set_buffer_dirty().
+- }
+-
+- /* Need to map unmapped buffers. */
+- if (!buffer_mapped(bh)) {
+- /* Unmapped buffer. Need to map it. */
+- bh->b_bdev = vol->sb->s_bdev;
+-
+- /* Convert block into corresponding vcn and offset. */
+- vcn = (VCN)block << blocksize_bits >>
+- vol->cluster_size_bits;
+- vcn_ofs = ((VCN)block << blocksize_bits) &
+- vol->cluster_size_mask;
+-
+- is_retry = FALSE;
+- if (!rl) {
+-lock_retry_remap:
+- down_read(&ni->runlist.lock);
+- rl = ni->runlist.rl;
+- }
+- if (likely(rl != NULL)) {
+- /* Seek to element containing target vcn. */
+- while (rl->length && rl[1].vcn <= vcn)
+- rl++;
+- lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
+- } else
+- lcn = LCN_RL_NOT_MAPPED;
+- if (unlikely(lcn < 0)) {
+- /*
+- * We extended the attribute allocation above.
+- * If we hit an ENOENT here it means that the
+- * allocation was insufficient which is a bug.
+- */
+- BUG_ON(lcn == LCN_ENOENT);
+-
+- /* It is a hole, need to instantiate it. */
+- if (lcn == LCN_HOLE) {
+- // TODO: Instantiate the hole.
+- // clear_buffer_new(bh);
+- // unmap_underlying_metadata(bh->b_bdev,
+- // bh->b_blocknr);
+- // For non-uptodate buffers, need to
+- // zero out the region outside the
+- // request in this bh or all bhs,
+- // depending on what we implemented
+- // above.
+- // Need to flush_dcache_page().
+- // Or could use set_buffer_new()
+- // instead?
+- ntfs_error(vol->sb, "Writing into "
+- "sparse regions is "
+- "not supported yet. "
+- "Sorry.");
+- err = -EOPNOTSUPP;
+- if (!rl)
+- up_read(&ni->runlist.lock);
+- goto err_out;
+- } else if (!is_retry &&
+- lcn == LCN_RL_NOT_MAPPED) {
+- is_retry = TRUE;
+- /*
+- * Attempt to map runlist, dropping
+- * lock for the duration.
+- */
+- up_read(&ni->runlist.lock);
+- err = ntfs_map_runlist(ni, vcn);
+- if (likely(!err))
+- goto lock_retry_remap;
+- rl = NULL;
+- } else if (!rl)
+- up_read(&ni->runlist.lock);
+- /*
+- * Failed to map the buffer, even after
+- * retrying.
+- */
+- if (!err)
+- err = -EIO;
+- bh->b_blocknr = -1;
+- ntfs_error(vol->sb, "Failed to write to inode "
+- "0x%lx, attribute type 0x%x, "
+- "vcn 0x%llx, offset 0x%x "
+- "because its location on disk "
+- "could not be determined%s "
+- "(error code %i).",
+- ni->mft_no, ni->type,
+- (unsigned long long)vcn,
+- vcn_ofs, is_retry ? " even "
+- "after retrying" : "", err);
+- goto err_out;
+- }
+- /* We now have a successful remap, i.e. lcn >= 0. */
+-
+- /* Setup buffer head to correct block. */
+- bh->b_blocknr = ((lcn << vol->cluster_size_bits)
+- + vcn_ofs) >> blocksize_bits;
+- set_buffer_mapped(bh);
+-
+- // FIXME: Something analogous to this is needed for
+- // each newly allocated block, i.e. BH_New.
+- // FIXME: Might need to take this out of the
+- // if (!buffer_mapped(bh)) {}, depending on how we
+- // implement things during the allocated_size and
+- // initialized_size extension code above.
+- if (buffer_new(bh)) {
+- clear_buffer_new(bh);
+- unmap_underlying_metadata(bh->b_bdev,
+- bh->b_blocknr);
+- if (PageUptodate(page)) {
+- set_buffer_uptodate(bh);
+- continue;
+- }
+- /*
+- * Page is _not_ uptodate, zero surrounding
+- * region. NOTE: This is how we decide if to
+- * zero or not!
+- */
+- if (block_end > to || block_start < from) {
+- void *kaddr;
+-
+- kaddr = kmap_atomic(page, KM_USER0);
+- if (block_end > to)
+- memset(kaddr + to, 0,
+- block_end - to);
+- if (block_start < from)
+- memset(kaddr + block_start, 0,
+- from -
+- block_start);
+- flush_dcache_page(page);
+- kunmap_atomic(kaddr, KM_USER0);
+- }
+- continue;
+- }
+- }
+- /* @bh is mapped, set it uptodate if the page is uptodate. */
+- if (PageUptodate(page)) {
+- if (!buffer_uptodate(bh))
+- set_buffer_uptodate(bh);
+- continue;
+- }
+- /*
+- * The page is not uptodate. The buffer is mapped. If it is not
+- * uptodate, and it is only partially being written to, we need
+- * to read the buffer in before the write, i.e. right now.
+- */
+- if (!buffer_uptodate(bh) &&
+- (block_start < from || block_end > to)) {
+- ll_rw_block(READ, 1, &bh);
+- *wait_bh++ = bh;
+- }
+- } while (block++, block_start = block_end,
+- (bh = bh->b_this_page) != head);
+-
+- /* Release the lock if we took it. */
+- if (rl) {
+- up_read(&ni->runlist.lock);
+- rl = NULL;
+- }
+-
+- /* If we issued read requests, let them complete. */
+- while (wait_bh > wait) {
+- wait_on_buffer(*--wait_bh);
+- if (!buffer_uptodate(*wait_bh))
+- return -EIO;
+- }
+-
+- ntfs_debug("Done.");
+- return 0;
+-err_out:
+- /*
+- * Zero out any newly allocated blocks to avoid exposing stale data.
+- * If BH_New is set, we know that the block was newly allocated in the
+- * above loop.
+- * FIXME: What about initialized_size increments? Have we done all the
+- * required zeroing above? If not this error handling is broken, and
+- * in particular the if (block_end <= from) check is completely bogus.
+- */
+- bh = head;
+- block_start = 0;
+- is_retry = FALSE;
+- do {
+- block_end = block_start + blocksize;
+- if (block_end <= from)
+- continue;
+- if (block_start >= to)
+- break;
+- if (buffer_new(bh)) {
+- void *kaddr;
+-
+- clear_buffer_new(bh);
+- kaddr = kmap_atomic(page, KM_USER0);
+- memset(kaddr + block_start, 0, bh->b_size);
+- kunmap_atomic(kaddr, KM_USER0);
+- set_buffer_uptodate(bh);
+- mark_buffer_dirty(bh);
+- is_retry = TRUE;
+- }
+- } while (block_start = block_end, (bh = bh->b_this_page) != head);
+- if (is_retry)
+- flush_dcache_page(page);
+- if (rl)
+- up_read(&ni->runlist.lock);
+- return err;
+-}
+-
+-/**
+- * ntfs_prepare_write - prepare a page for receiving data
+- *
+- * This is called from generic_file_write() with i_sem held on the inode
+- * (@page->mapping->host). The @page is locked but not kmap()ped. The source
+- * data has not yet been copied into the @page.
+- *
+- * Need to extend the attribute/fill in holes if necessary, create blocks and
+- * make partially overwritten blocks uptodate,
+- *
+- * i_size is not to be modified yet.
+- *
+- * Return 0 on success or -errno on error.
+- *
+- * Should be using block_prepare_write() [support for sparse files] or
+- * cont_prepare_write() [no support for sparse files]. Cannot do that due to
+- * ntfs specifics but can look at them for implementation guidance.
+- *
+- * Note: In the range, @from is inclusive and @to is exclusive, i.e. @from is
+- * the first byte in the page that will be written to and @to is the first byte
+- * after the last byte that will be written to.
+- */
+-static int ntfs_prepare_write(struct file *file, struct page *page,
+- unsigned from, unsigned to)
+-{
+- s64 new_size;
+- loff_t i_size;
+- struct inode *vi = page->mapping->host;
+- ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi);
+- ntfs_volume *vol = ni->vol;
+- ntfs_attr_search_ctx *ctx = NULL;
+- MFT_RECORD *m = NULL;
+- ATTR_RECORD *a;
+- u8 *kaddr;
+- u32 attr_len;
+- int err;
+-
+- ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
+- "0x%lx, from = %u, to = %u.", vi->i_ino, ni->type,
+- page->index, from, to);
+- BUG_ON(!PageLocked(page));
+- BUG_ON(from > PAGE_CACHE_SIZE);
+- BUG_ON(to > PAGE_CACHE_SIZE);
+- BUG_ON(from > to);
+- BUG_ON(NInoMstProtected(ni));
+- /*
+- * If a previous ntfs_truncate() failed, repeat it and abort if it
+- * fails again.
+- */
+- if (unlikely(NInoTruncateFailed(ni))) {
+- down_write(&vi->i_alloc_sem);
+- err = ntfs_truncate(vi);
+- up_write(&vi->i_alloc_sem);
+- if (err || NInoTruncateFailed(ni)) {
+- if (!err)
+- err = -EIO;
+- goto err_out;
+- }
+- }
+- /* If the attribute is not resident, deal with it elsewhere. */
+- if (NInoNonResident(ni)) {
+- /*
+- * Only unnamed $DATA attributes can be compressed, encrypted,
+- * and/or sparse.
+- */
+- if (ni->type == AT_DATA && !ni->name_len) {
+- /* If file is encrypted, deny access, just like NT4. */
+- if (NInoEncrypted(ni)) {
+- ntfs_debug("Denying write access to encrypted "
+- "file.");
+- return -EACCES;
+- }
+- /* Compressed data streams are handled in compress.c. */
+- if (NInoCompressed(ni)) {
+- // TODO: Implement and replace this check with
+- // return ntfs_write_compressed_block(page);
+- ntfs_error(vi->i_sb, "Writing to compressed "
+- "files is not supported yet. "
+- "Sorry.");
+- return -EOPNOTSUPP;
+- }
+- // TODO: Implement and remove this check.
+- if (NInoSparse(ni)) {
+- ntfs_error(vi->i_sb, "Writing to sparse files "
+- "is not supported yet. Sorry.");
+- return -EOPNOTSUPP;
+- }
+- }
+- /* Normal data stream. */
+- return ntfs_prepare_nonresident_write(page, from, to);
+- }
+- /*
+- * Attribute is resident, implying it is not compressed, encrypted, or
+- * sparse.
+- */
+- BUG_ON(page_has_buffers(page));
+- new_size = ((s64)page->index << PAGE_CACHE_SHIFT) + to;
+- /* If we do not need to resize the attribute allocation we are done. */
+- if (new_size <= i_size_read(vi))
+- goto done;
+- /* Map, pin, and lock the (base) mft record. */
+- if (!NInoAttr(ni))
+- base_ni = ni;
+- else
+- base_ni = ni->ext.base_ntfs_ino;
+- m = map_mft_record(base_ni);
+- if (IS_ERR(m)) {
+- err = PTR_ERR(m);
+- m = NULL;
+- ctx = NULL;
+- goto err_out;
+- }
+- ctx = ntfs_attr_get_search_ctx(base_ni, m);
+- if (unlikely(!ctx)) {
+- err = -ENOMEM;
+- goto err_out;
+- }
+- err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+- CASE_SENSITIVE, 0, NULL, 0, ctx);
+- if (unlikely(err)) {
+- if (err == -ENOENT)
+- err = -EIO;
+- goto err_out;
+- }
+- m = ctx->mrec;
+- a = ctx->attr;
+- /* The total length of the attribute value. */
+- attr_len = le32_to_cpu(a->data.resident.value_length);
+- /* Fix an eventual previous failure of ntfs_commit_write(). */
+- i_size = i_size_read(vi);
+- if (unlikely(attr_len > i_size)) {
+- attr_len = i_size;
+- a->data.resident.value_length = cpu_to_le32(attr_len);
+- }
+- /* If we do not need to resize the attribute allocation we are done. */
+- if (new_size <= attr_len)
+- goto done_unm;
+- /* Check if new size is allowed in $AttrDef. */
+- err = ntfs_attr_size_bounds_check(vol, ni->type, new_size);
+- if (unlikely(err)) {
+- if (err == -ERANGE) {
+- ntfs_error(vol->sb, "Write would cause the inode "
+- "0x%lx to exceed the maximum size for "
+- "its attribute type (0x%x). Aborting "
+- "write.", vi->i_ino,
+- le32_to_cpu(ni->type));
+- } else {
+- ntfs_error(vol->sb, "Inode 0x%lx has unknown "
+- "attribute type 0x%x. Aborting "
+- "write.", vi->i_ino,
+- le32_to_cpu(ni->type));
+- err = -EIO;
+- }
+- goto err_out2;
+- }
+- /*
+- * Extend the attribute record to be able to store the new attribute
+- * size.
+- */
+- if (new_size >= vol->mft_record_size || ntfs_attr_record_resize(m, a,
+- le16_to_cpu(a->data.resident.value_offset) +
+- new_size)) {
+- /* Not enough space in the mft record. */
+- ntfs_error(vol->sb, "Not enough space in the mft record for "
+- "the resized attribute value. This is not "
+- "supported yet. Aborting write.");
+- err = -EOPNOTSUPP;
+- goto err_out2;
+- }
+- /*
+- * We have enough space in the mft record to fit the write. This
+- * implies the attribute is smaller than the mft record and hence the
+- * attribute must be in a single page and hence page->index must be 0.
+- */
+- BUG_ON(page->index);
+- /*
+- * If the beginning of the write is past the old size, enlarge the
+- * attribute value up to the beginning of the write and fill it with
+- * zeroes.
+- */
+- if (from > attr_len) {
+- memset((u8*)a + le16_to_cpu(a->data.resident.value_offset) +
+- attr_len, 0, from - attr_len);
+- a->data.resident.value_length = cpu_to_le32(from);
+- /* Zero the corresponding area in the page as well. */
+- if (PageUptodate(page)) {
+- kaddr = kmap_atomic(page, KM_USER0);
+- memset(kaddr + attr_len, 0, from - attr_len);
+- kunmap_atomic(kaddr, KM_USER0);
+- flush_dcache_page(page);
+- }
+- }
+- flush_dcache_mft_record_page(ctx->ntfs_ino);
+- mark_mft_record_dirty(ctx->ntfs_ino);
+-done_unm:
+- ntfs_attr_put_search_ctx(ctx);
+- unmap_mft_record(base_ni);
+- /*
+- * Because resident attributes are handled by memcpy() to/from the
+- * corresponding MFT record, and because this form of i/o is byte
+- * aligned rather than block aligned, there is no need to bring the
+- * page uptodate here as in the non-resident case where we need to
+- * bring the buffers straddled by the write uptodate before
+- * generic_file_write() does the copying from userspace.
+- *
+- * We thus defer the uptodate bringing of the page region outside the
+- * region written to to ntfs_commit_write(), which makes the code
+- * simpler and saves one atomic kmap which is good.
+- */
+-done:
+- ntfs_debug("Done.");
+- return 0;
+-err_out:
+- if (err == -ENOMEM)
+- ntfs_warning(vi->i_sb, "Error allocating memory required to "
+- "prepare the write.");
+- else {
+- ntfs_error(vi->i_sb, "Resident attribute prepare write failed "
+- "with error %i.", err);
+- NVolSetErrors(vol);
+- make_bad_inode(vi);
+- }
+-err_out2:
+- if (ctx)
+- ntfs_attr_put_search_ctx(ctx);
+- if (m)
+- unmap_mft_record(base_ni);
+- return err;
+-}
+-
+-/**
+- * ntfs_commit_nonresident_write -
+- *
+- */
+-static int ntfs_commit_nonresident_write(struct page *page,
+- unsigned from, unsigned to)
+-{
+- s64 pos = ((s64)page->index << PAGE_CACHE_SHIFT) + to;
+- struct inode *vi = page->mapping->host;
+- struct buffer_head *bh, *head;
+- unsigned int block_start, block_end, blocksize;
+- BOOL partial;
+-
+- ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
+- "0x%lx, from = %u, to = %u.", vi->i_ino,
+- NTFS_I(vi)->type, page->index, from, to);
+- blocksize = 1 << vi->i_blkbits;
+-
+- // FIXME: We need a whole slew of special cases in here for compressed
+- // files for example...
+- // For now, we know ntfs_prepare_write() would have failed so we can't
+- // get here in any of the cases which we have to special case, so we
+- // are just a ripped off, unrolled generic_commit_write().
+-
+- bh = head = page_buffers(page);
+- block_start = 0;
+- partial = FALSE;
+- do {
+- block_end = block_start + blocksize;
+- if (block_end <= from || block_start >= to) {
+- if (!buffer_uptodate(bh))
+- partial = TRUE;
+- } else {
+- set_buffer_uptodate(bh);
+- mark_buffer_dirty(bh);
+- }
+- } while (block_start = block_end, (bh = bh->b_this_page) != head);
+- /*
+- * If this is a partial write which happened to make all buffers
+- * uptodate then we can optimize away a bogus ->readpage() for the next
+- * read(). Here we 'discover' whether the page went uptodate as a
+- * result of this (potentially partial) write.
+- */
+- if (!partial)
+- SetPageUptodate(page);
+- /*
+- * Not convinced about this at all. See disparity comment above. For
+- * now we know ntfs_prepare_write() would have failed in the write
+- * exceeds i_size case, so this will never trigger which is fine.
+- */
+- if (pos > i_size_read(vi)) {
+- ntfs_error(vi->i_sb, "Writing beyond the existing file size is "
+- "not supported yet. Sorry.");
+- return -EOPNOTSUPP;
+- // vi->i_size = pos;
+- // mark_inode_dirty(vi);
+- }
+- ntfs_debug("Done.");
+- return 0;
+-}
+-
+-/**
+- * ntfs_commit_write - commit the received data
+- *
+- * This is called from generic_file_write() with i_sem held on the inode
+- * (@page->mapping->host). The @page is locked but not kmap()ped. The source
+- * data has already been copied into the @page. ntfs_prepare_write() has been
+- * called before the data copied and it returned success so we can take the
+- * results of various BUG checks and some error handling for granted.
+- *
+- * Need to mark modified blocks dirty so they get written out later when
+- * ntfs_writepage() is invoked by the VM.
+- *
+- * Return 0 on success or -errno on error.
+- *
+- * Should be using generic_commit_write(). This marks buffers uptodate and
+- * dirty, sets the page uptodate if all buffers in the page are uptodate, and
+- * updates i_size if the end of io is beyond i_size. In that case, it also
+- * marks the inode dirty.
+- *
+- * Cannot use generic_commit_write() due to ntfs specialities but can look at
+- * it for implementation guidance.
+- *
+- * If things have gone as outlined in ntfs_prepare_write(), then we do not
+- * need to do any page content modifications here at all, except in the write
+- * to resident attribute case, where we need to do the uptodate bringing here
+- * which we combine with the copying into the mft record which means we save
+- * one atomic kmap.
+- */
+-static int ntfs_commit_write(struct file *file, struct page *page,
+- unsigned from, unsigned to)
+-{
+- struct inode *vi = page->mapping->host;
+- ntfs_inode *base_ni, *ni = NTFS_I(vi);
+- char *kaddr, *kattr;
+- ntfs_attr_search_ctx *ctx;
+- MFT_RECORD *m;
+- ATTR_RECORD *a;
+- u32 attr_len;
+- int err;
+-
+- ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
+- "0x%lx, from = %u, to = %u.", vi->i_ino, ni->type,
+- page->index, from, to);
+- /* If the attribute is not resident, deal with it elsewhere. */
+- if (NInoNonResident(ni)) {
+- /* Only unnamed $DATA attributes can be compressed/encrypted. */
+- if (ni->type == AT_DATA && !ni->name_len) {
+- /* Encrypted files need separate handling. */
+- if (NInoEncrypted(ni)) {
+- // We never get here at present!
+- BUG();
+- }
+- /* Compressed data streams are handled in compress.c. */
+- if (NInoCompressed(ni)) {
+- // TODO: Implement this!
+- // return ntfs_write_compressed_block(page);
+- // We never get here at present!
+- BUG();
+- }
+- }
+- /* Normal data stream. */
+- return ntfs_commit_nonresident_write(page, from, to);
+- }
+- /*
+- * Attribute is resident, implying it is not compressed, encrypted, or
+- * sparse.
+- */
+- if (!NInoAttr(ni))
+- base_ni = ni;
+- else
+- base_ni = ni->ext.base_ntfs_ino;
+- /* Map, pin, and lock the mft record. */
+- m = map_mft_record(base_ni);
+- if (IS_ERR(m)) {
+- err = PTR_ERR(m);
+- m = NULL;
+- ctx = NULL;
+- goto err_out;
+- }
+- ctx = ntfs_attr_get_search_ctx(base_ni, m);
+- if (unlikely(!ctx)) {
+- err = -ENOMEM;
+- goto err_out;
+- }
+- err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+- CASE_SENSITIVE, 0, NULL, 0, ctx);
+- if (unlikely(err)) {
+- if (err == -ENOENT)
+- err = -EIO;
+- goto err_out;
+- }
+- a = ctx->attr;
+- /* The total length of the attribute value. */
+- attr_len = le32_to_cpu(a->data.resident.value_length);
+- BUG_ON(from > attr_len);
+- kattr = (u8*)a + le16_to_cpu(a->data.resident.value_offset);
+- kaddr = kmap_atomic(page, KM_USER0);
+- /* Copy the received data from the page to the mft record. */
+- memcpy(kattr + from, kaddr + from, to - from);
+- /* Update the attribute length if necessary. */
+- if (to > attr_len) {
+- attr_len = to;
+- a->data.resident.value_length = cpu_to_le32(attr_len);
+- }
+- /*
+- * If the page is not uptodate, bring the out of bounds area(s)
+- * uptodate by copying data from the mft record to the page.
+- */
+- if (!PageUptodate(page)) {
+- if (from > 0)
+- memcpy(kaddr, kattr, from);
+- if (to < attr_len)
+- memcpy(kaddr + to, kattr + to, attr_len - to);
+- /* Zero the region outside the end of the attribute value. */
+- if (attr_len < PAGE_CACHE_SIZE)
+- memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
+- /*
+- * The probability of not having done any of the above is
+- * extremely small, so we just flush unconditionally.
+- */
+- flush_dcache_page(page);
+- SetPageUptodate(page);
+- }
+- kunmap_atomic(kaddr, KM_USER0);
+- /* Update i_size if necessary. */
+- if (i_size_read(vi) < attr_len) {
+- unsigned long flags;
+-
+- write_lock_irqsave(&ni->size_lock, flags);
+- ni->allocated_size = ni->initialized_size = attr_len;
+- i_size_write(vi, attr_len);
+- write_unlock_irqrestore(&ni->size_lock, flags);
+- }
+- /* Mark the mft record dirty, so it gets written back. */
+- flush_dcache_mft_record_page(ctx->ntfs_ino);
+- mark_mft_record_dirty(ctx->ntfs_ino);
+- ntfs_attr_put_search_ctx(ctx);
+- unmap_mft_record(base_ni);
+- ntfs_debug("Done.");
+- return 0;
+-err_out:
+- if (err == -ENOMEM) {
+- ntfs_warning(vi->i_sb, "Error allocating memory required to "
+- "commit the write.");
+- if (PageUptodate(page)) {
+- ntfs_warning(vi->i_sb, "Page is uptodate, setting "
+- "dirty so the write will be retried "
+- "later on by the VM.");
+- /*
+- * Put the page on mapping->dirty_pages, but leave its
+- * buffers' dirty state as-is.
+- */
+- __set_page_dirty_nobuffers(page);
+- err = 0;
+- } else
+- ntfs_error(vi->i_sb, "Page is not uptodate. Written "
+- "data has been lost.");
+- } else {
+- ntfs_error(vi->i_sb, "Resident attribute commit write failed "
+- "with error %i.", err);
+- NVolSetErrors(ni->vol);
+- make_bad_inode(vi);
+- }
+- if (ctx)
+- ntfs_attr_put_search_ctx(ctx);
+- if (m)
+- unmap_mft_record(base_ni);
+- return err;
+-}
+-
+ #endif /* NTFS_RW */
+
+ /**
+@@ -2377,9 +1552,6 @@ struct address_space_operations ntfs_aop
+ disk request queue. */
+ #ifdef NTFS_RW
+ .writepage = ntfs_writepage, /* Write dirty page to disk. */
+- .prepare_write = ntfs_prepare_write, /* Prepare page and buffers
+- ready to receive data. */
+- .commit_write = ntfs_commit_write, /* Commit received data. */
+ #endif /* NTFS_RW */
+ };
+
+diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
+--- a/fs/ntfs/attrib.c
++++ b/fs/ntfs/attrib.c
+@@ -21,7 +21,9 @@
+ */
+
+ #include <linux/buffer_head.h>
++#include <linux/sched.h>
+ #include <linux/swap.h>
++#include <linux/writeback.h>
+
+ #include "attrib.h"
+ #include "debug.h"
+@@ -36,9 +38,27 @@
+ * ntfs_map_runlist_nolock - map (a part of) a runlist of an ntfs inode
+ * @ni: ntfs inode for which to map (part of) a runlist
+ * @vcn: map runlist part containing this vcn
++ * @ctx: active attribute search context if present or NULL if not
+ *
+ * Map the part of a runlist containing the @vcn of the ntfs inode @ni.
+ *
++ * If @ctx is specified, it is an active search context of @ni and its base mft
++ * record. This is needed when ntfs_map_runlist_nolock() encounters unmapped
++ * runlist fragments and allows their mapping. If you do not have the mft
++ * record mapped, you can specify @ctx as NULL and ntfs_map_runlist_nolock()
++ * will perform the necessary mapping and unmapping.
++ *
++ * Note, ntfs_map_runlist_nolock() saves the state of @ctx on entry and
++ * restores it before returning. Thus, @ctx will be left pointing to the same
++ * attribute on return as on entry. However, the actual pointers in @ctx may
++ * point to different memory locations on return, so you must remember to reset
++ * any cached pointers from the @ctx, i.e. after the call to
++ * ntfs_map_runlist_nolock(), you will probably want to do:
++ * m = ctx->mrec;
++ * a = ctx->attr;
++ * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
++ * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
++ *
+ * Return 0 on success and -errno on error. There is one special error code
+ * which is not an error as such. This is -ENOENT. It means that @vcn is out
+ * of bounds of the runlist.
+@@ -46,19 +66,32 @@
+ * Note the runlist can be NULL after this function returns if @vcn is zero and
+ * the attribute has zero allocated size, i.e. there simply is no runlist.
+ *
+- * Locking: - The runlist must be locked for writing.
+- * - This function modifies the runlist.
++ * WARNING: If @ctx is supplied, regardless of whether success or failure is
++ * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
++ * is no longer valid, i.e. you need to either call
++ * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
++ * In that case PTR_ERR(@ctx->mrec) will give you the error code for
++ * why the mapping of the old inode failed.
++ *
++ * Locking: - The runlist described by @ni must be locked for writing on entry
++ * and is locked on return. Note the runlist will be modified.
++ * - If @ctx is NULL, the base mft record of @ni must not be mapped on
++ * entry and it will be left unmapped on return.
++ * - If @ctx is not NULL, the base mft record must be mapped on entry
++ * and it will be left mapped on return.
+ */
+-int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
++int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
+ {
+ VCN end_vcn;
++ unsigned long flags;
+ ntfs_inode *base_ni;
+ MFT_RECORD *m;
+ ATTR_RECORD *a;
+- ntfs_attr_search_ctx *ctx;
+ runlist_element *rl;
+- unsigned long flags;
++ struct page *put_this_page = NULL;
+ int err = 0;
++ BOOL ctx_is_temporary, ctx_needs_reset;
++ ntfs_attr_search_ctx old_ctx = { NULL, };
+
+ ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
+ (unsigned long long)vcn);
+@@ -66,20 +99,77 @@ int ntfs_map_runlist_nolock(ntfs_inode *
+ base_ni = ni;
+ else
+ base_ni = ni->ext.base_ntfs_ino;
+- m = map_mft_record(base_ni);
+- if (IS_ERR(m))
+- return PTR_ERR(m);
+- ctx = ntfs_attr_get_search_ctx(base_ni, m);
+- if (unlikely(!ctx)) {
+- err = -ENOMEM;
+- goto err_out;
++ if (!ctx) {
++ ctx_is_temporary = ctx_needs_reset = TRUE;
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m))
++ return PTR_ERR(m);
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++ } else {
++ VCN allocated_size_vcn;
++
++ BUG_ON(IS_ERR(ctx->mrec));
++ a = ctx->attr;
++ BUG_ON(!a->non_resident);
++ ctx_is_temporary = FALSE;
++ end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn);
++ read_lock_irqsave(&ni->size_lock, flags);
++ allocated_size_vcn = ni->allocated_size >>
++ ni->vol->cluster_size_bits;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (!a->data.non_resident.lowest_vcn && end_vcn <= 0)
++ end_vcn = allocated_size_vcn - 1;
++ /*
++ * If we already have the attribute extent containing @vcn in
++ * @ctx, no need to look it up again. We slightly cheat in
++ * that if vcn exceeds the allocated size, we will refuse to
++ * map the runlist below, so there is definitely no need to get
++ * the right attribute extent.
++ */
++ if (vcn >= allocated_size_vcn || (a->type == ni->type &&
++ a->name_length == ni->name_len &&
++ !memcmp((u8*)a + le16_to_cpu(a->name_offset),
++ ni->name, ni->name_len) &&
++ sle64_to_cpu(a->data.non_resident.lowest_vcn)
++ <= vcn && end_vcn >= vcn))
++ ctx_needs_reset = FALSE;
++ else {
++ /* Save the old search context. */
++ old_ctx = *ctx;
++ /*
++ * If the currently mapped (extent) inode is not the
++ * base inode we will unmap it when we reinitialize the
++ * search context which means we need to get a
++ * reference to the page containing the mapped mft
++ * record so we do not accidentally drop changes to the
++ * mft record when it has not been marked dirty yet.
++ */
++ if (old_ctx.base_ntfs_ino && old_ctx.ntfs_ino !=
++ old_ctx.base_ntfs_ino) {
++ put_this_page = old_ctx.ntfs_ino->page;
++ page_cache_get(put_this_page);
++ }
++ /*
++ * Reinitialize the search context so we can lookup the
++ * needed attribute extent.
++ */
++ ntfs_attr_reinit_search_ctx(ctx);
++ ctx_needs_reset = TRUE;
++ }
+ }
+- err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+- CASE_SENSITIVE, vcn, NULL, 0, ctx);
+- if (unlikely(err)) {
+- if (err == -ENOENT)
+- err = -EIO;
+- goto err_out;
++ if (ctx_needs_reset) {
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, vcn, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ goto err_out;
++ }
++ BUG_ON(!ctx->attr->non_resident);
+ }
+ a = ctx->attr;
+ /*
+@@ -89,11 +179,9 @@ int ntfs_map_runlist_nolock(ntfs_inode *
+ * ntfs_mapping_pairs_decompress() fails.
+ */
+ end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1;
+- if (unlikely(!a->data.non_resident.lowest_vcn && end_vcn <= 1)) {
+- read_lock_irqsave(&ni->size_lock, flags);
+- end_vcn = ni->allocated_size >> ni->vol->cluster_size_bits;
+- read_unlock_irqrestore(&ni->size_lock, flags);
+- }
++ if (!a->data.non_resident.lowest_vcn && end_vcn == 1)
++ end_vcn = sle64_to_cpu(a->data.non_resident.allocated_size) >>
++ ni->vol->cluster_size_bits;
+ if (unlikely(vcn >= end_vcn)) {
+ err = -ENOENT;
+ goto err_out;
+@@ -104,9 +192,93 @@ int ntfs_map_runlist_nolock(ntfs_inode *
+ else
+ ni->runlist.rl = rl;
+ err_out:
+- if (likely(ctx))
+- ntfs_attr_put_search_ctx(ctx);
+- unmap_mft_record(base_ni);
++ if (ctx_is_temporary) {
++ if (likely(ctx))
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ } else if (ctx_needs_reset) {
++ /*
++ * If there is no attribute list, restoring the search context
++ * is acomplished simply by copying the saved context back over
++ * the caller supplied context. If there is an attribute list,
++ * things are more complicated as we need to deal with mapping
++ * of mft records and resulting potential changes in pointers.
++ */
++ if (NInoAttrList(base_ni)) {
++ /*
++ * If the currently mapped (extent) inode is not the
++ * one we had before, we need to unmap it and map the
++ * old one.
++ */
++ if (ctx->ntfs_ino != old_ctx.ntfs_ino) {
++ /*
++ * If the currently mapped inode is not the
++ * base inode, unmap it.
++ */
++ if (ctx->base_ntfs_ino && ctx->ntfs_ino !=
++ ctx->base_ntfs_ino) {
++ unmap_extent_mft_record(ctx->ntfs_ino);
++ ctx->mrec = ctx->base_mrec;
++ BUG_ON(!ctx->mrec);
++ }
++ /*
++ * If the old mapped inode is not the base
++ * inode, map it.
++ */
++ if (old_ctx.base_ntfs_ino &&
++ old_ctx.ntfs_ino !=
++ old_ctx.base_ntfs_ino) {
++retry_map:
++ ctx->mrec = map_mft_record(
++ old_ctx.ntfs_ino);
++ /*
++ * Something bad has happened. If out
++ * of memory retry till it succeeds.
++ * Any other errors are fatal and we
++ * return the error code in ctx->mrec.
++ * Let the caller deal with it... We
++ * just need to fudge things so the
++ * caller can reinit and/or put the
++ * search context safely.
++ */
++ if (IS_ERR(ctx->mrec)) {
++ if (PTR_ERR(ctx->mrec) ==
++ -ENOMEM) {
++ schedule();
++ goto retry_map;
++ } else
++ old_ctx.ntfs_ino =
++ old_ctx.
++ base_ntfs_ino;
++ }
++ }
++ }
++ /* Update the changed pointers in the saved context. */
++ if (ctx->mrec != old_ctx.mrec) {
++ if (!IS_ERR(ctx->mrec))
++ old_ctx.attr = (ATTR_RECORD*)(
++ (u8*)ctx->mrec +
++ ((u8*)old_ctx.attr -
++ (u8*)old_ctx.mrec));
++ old_ctx.mrec = ctx->mrec;
++ }
++ }
++ /* Restore the search context to the saved one. */
++ *ctx = old_ctx;
++ /*
++ * We drop the reference on the page we took earlier. In the
++ * case that IS_ERR(ctx->mrec) is true this means we might lose
++ * some changes to the mft record that had been made between
++ * the last time it was marked dirty/written out and now. This
++ * at this stage is not a problem as the mapping error is fatal
++ * enough that the mft record cannot be written out anyway and
++ * the caller is very likely to shutdown the whole inode
++ * immediately and mark the volume dirty for chkdsk to pick up
++ * the pieces anyway.
++ */
++ if (put_this_page)
++ page_cache_release(put_this_page);
++ }
+ return err;
+ }
+
+@@ -122,8 +294,8 @@ err_out:
+ * of bounds of the runlist.
+ *
+ * Locking: - The runlist must be unlocked on entry and is unlocked on return.
+- * - This function takes the runlist lock for writing and modifies the
+- * runlist.
++ * - This function takes the runlist lock for writing and may modify
++ * the runlist.
+ */
+ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
+ {
+@@ -133,7 +305,7 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN
+ /* Make sure someone else didn't do the work while we were sleeping. */
+ if (likely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) <=
+ LCN_RL_NOT_MAPPED))
+- err = ntfs_map_runlist_nolock(ni, vcn);
++ err = ntfs_map_runlist_nolock(ni, vcn, NULL);
+ up_write(&ni->runlist.lock);
+ return err;
+ }
+@@ -212,7 +384,7 @@ retry_remap:
+ goto retry_remap;
+ }
+ }
+- err = ntfs_map_runlist_nolock(ni, vcn);
++ err = ntfs_map_runlist_nolock(ni, vcn, NULL);
+ if (!write_locked) {
+ up_write(&ni->runlist.lock);
+ down_read(&ni->runlist.lock);
+@@ -236,9 +408,9 @@ retry_remap:
+
+ /**
+ * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode
+- * @ni: ntfs inode describing the runlist to search
+- * @vcn: vcn to find
+- * @write_locked: true if the runlist is locked for writing
++ * @ni: ntfs inode describing the runlist to search
++ * @vcn: vcn to find
++ * @ctx: active attribute search context if present or NULL if not
+ *
+ * Find the virtual cluster number @vcn in the runlist described by the ntfs
+ * inode @ni and return the address of the runlist element containing the @vcn.
+@@ -246,9 +418,22 @@ retry_remap:
+ * If the @vcn is not mapped yet, the attempt is made to map the attribute
+ * extent containing the @vcn and the vcn to lcn conversion is retried.
+ *
+- * If @write_locked is true the caller has locked the runlist for writing and
+- * if false for reading.
+- *
++ * If @ctx is specified, it is an active search context of @ni and its base mft
++ * record. This is needed when ntfs_attr_find_vcn_nolock() encounters unmapped
++ * runlist fragments and allows their mapping. If you do not have the mft
++ * record mapped, you can specify @ctx as NULL and ntfs_attr_find_vcn_nolock()
++ * will perform the necessary mapping and unmapping.
++ *
++ * Note, ntfs_attr_find_vcn_nolock() saves the state of @ctx on entry and
++ * restores it before returning. Thus, @ctx will be left pointing to the same
++ * attribute on return as on entry. However, the actual pointers in @ctx may
++ * point to different memory locations on return, so you must remember to reset
++ * any cached pointers from the @ctx, i.e. after the call to
++ * ntfs_attr_find_vcn_nolock(), you will probably want to do:
++ * m = ctx->mrec;
++ * a = ctx->attr;
++ * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
++ * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
+ * Note you need to distinguish between the lcn of the returned runlist element
+ * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on
+ * read and allocate clusters on write.
+@@ -263,22 +448,31 @@ retry_remap:
+ * -ENOMEM - Not enough memory to map runlist.
+ * -EIO - Critical error (runlist/file is corrupt, i/o error, etc).
+ *
+- * Locking: - The runlist must be locked on entry and is left locked on return.
+- * - If @write_locked is FALSE, i.e. the runlist is locked for reading,
+- * the lock may be dropped inside the function so you cannot rely on
+- * the runlist still being the same when this function returns.
++ * WARNING: If @ctx is supplied, regardless of whether success or failure is
++ * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
++ * is no longer valid, i.e. you need to either call
++ * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
++ * In that case PTR_ERR(@ctx->mrec) will give you the error code for
++ * why the mapping of the old inode failed.
++ *
++ * Locking: - The runlist described by @ni must be locked for writing on entry
++ * and is locked on return. Note the runlist may be modified when
++ * needed runlist fragments need to be mapped.
++ * - If @ctx is NULL, the base mft record of @ni must not be mapped on
++ * entry and it will be left unmapped on return.
++ * - If @ctx is not NULL, the base mft record must be mapped on entry
++ * and it will be left mapped on return.
+ */
+ runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
+- const BOOL write_locked)
++ ntfs_attr_search_ctx *ctx)
+ {
+ unsigned long flags;
+ runlist_element *rl;
+ int err = 0;
+ BOOL is_retry = FALSE;
+
+- ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.",
+- ni->mft_no, (unsigned long long)vcn,
+- write_locked ? "write" : "read");
++ ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, with%s ctx.",
++ ni->mft_no, (unsigned long long)vcn, ctx ? "" : "out");
+ BUG_ON(!ni);
+ BUG_ON(!NInoNonResident(ni));
+ BUG_ON(vcn < 0);
+@@ -312,33 +506,22 @@ retry_remap:
+ }
+ if (!err && !is_retry) {
+ /*
+- * The @vcn is in an unmapped region, map the runlist and
+- * retry.
++ * If the search context is invalid we cannot map the unmapped
++ * region.
+ */
+- if (!write_locked) {
+- up_read(&ni->runlist.lock);
+- down_write(&ni->runlist.lock);
+- if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) !=
+- LCN_RL_NOT_MAPPED)) {
+- up_write(&ni->runlist.lock);
+- down_read(&ni->runlist.lock);
++ if (IS_ERR(ctx->mrec))
++ err = PTR_ERR(ctx->mrec);
++ else {
++ /*
++ * The @vcn is in an unmapped region, map the runlist
++ * and retry.
++ */
++ err = ntfs_map_runlist_nolock(ni, vcn, ctx);
++ if (likely(!err)) {
++ is_retry = TRUE;
+ goto retry_remap;
+ }
+ }
+- err = ntfs_map_runlist_nolock(ni, vcn);
+- if (!write_locked) {
+- up_write(&ni->runlist.lock);
+- down_read(&ni->runlist.lock);
+- }
+- if (likely(!err)) {
+- is_retry = TRUE;
+- goto retry_remap;
+- }
+- /*
+- * -EINVAL coming from a failed mapping attempt is equivalent
+- * to i/o error for us as it should not happen in our code
+- * paths.
+- */
+ if (err == -EINVAL)
+ err = -EIO;
+ } else if (!err)
+@@ -1011,6 +1194,7 @@ int ntfs_attr_lookup(const ATTR_TYPE typ
+ ntfs_inode *base_ni;
+
+ ntfs_debug("Entering.");
++ BUG_ON(IS_ERR(ctx->mrec));
+ if (ctx->base_ntfs_ino)
+ base_ni = ctx->base_ntfs_ino;
+ else
+@@ -1227,7 +1411,7 @@ int ntfs_attr_can_be_non_resident(const
+ */
+ int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPE type)
+ {
+- if (type == AT_INDEX_ALLOCATION || type == AT_EA)
++ if (type == AT_INDEX_ALLOCATION)
+ return -EPERM;
+ return 0;
+ }
+@@ -1319,10 +1503,17 @@ int ntfs_resident_attr_value_resize(MFT_
+ /**
+ * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
+ * @ni: ntfs inode describing the attribute to convert
++ * @data_size: size of the resident data to copy to the non-resident attribute
+ *
+ * Convert the resident ntfs attribute described by the ntfs inode @ni to a
+ * non-resident one.
+ *
++ * @data_size must be equal to the attribute value size. This is needed since
++ * we need to know the size before we can map the mft record and our callers
++ * always know it. The reason we cannot simply read the size from the vfs
++ * inode i_size is that this is not necessarily uptodate. This happens when
++ * ntfs_attr_make_non_resident() is called in the ->truncate call path(s).
++ *
+ * Return 0 on success and -errno on error. The following error return codes
+ * are defined:
+ * -EPERM - The attribute is not allowed to be non-resident.
+@@ -1343,7 +1534,7 @@ int ntfs_resident_attr_value_resize(MFT_
+ *
+ * Locking: - The caller must hold i_sem on the inode.
+ */
+-int ntfs_attr_make_non_resident(ntfs_inode *ni)
++int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
+ {
+ s64 new_size;
+ struct inode *vi = VFS_I(ni);
+@@ -1381,11 +1572,9 @@ int ntfs_attr_make_non_resident(ntfs_ino
+ * The size needs to be aligned to a cluster boundary for allocation
+ * purposes.
+ */
+- new_size = (i_size_read(vi) + vol->cluster_size - 1) &
++ new_size = (data_size + vol->cluster_size - 1) &
+ ~(vol->cluster_size - 1);
+ if (new_size > 0) {
+- runlist_element *rl2;
+-
+ /*
+ * Will need the page later and since the page lock nests
+ * outside all ntfs locks, we need to get the page now.
+@@ -1396,7 +1585,7 @@ int ntfs_attr_make_non_resident(ntfs_ino
+ return -ENOMEM;
+ /* Start by allocating clusters to hold the attribute value. */
+ rl = ntfs_cluster_alloc(vol, 0, new_size >>
+- vol->cluster_size_bits, -1, DATA_ZONE);
++ vol->cluster_size_bits, -1, DATA_ZONE, TRUE);
+ if (IS_ERR(rl)) {
+ err = PTR_ERR(rl);
+ ntfs_debug("Failed to allocate cluster%s, error code "
+@@ -1405,12 +1594,6 @@ int ntfs_attr_make_non_resident(ntfs_ino
+ err);
+ goto page_err_out;
+ }
+- /* Change the runlist terminator to LCN_ENOENT. */
+- rl2 = rl;
+- while (rl2->length)
+- rl2++;
+- BUG_ON(rl2->lcn != LCN_RL_NOT_MAPPED);
+- rl2->lcn = LCN_ENOENT;
+ } else {
+ rl = NULL;
+ page = NULL;
+@@ -1473,7 +1656,7 @@ int ntfs_attr_make_non_resident(ntfs_ino
+ * attribute value.
+ */
+ attr_size = le32_to_cpu(a->data.resident.value_length);
+- BUG_ON(attr_size != i_size_read(vi));
++ BUG_ON(attr_size != data_size);
+ if (page && !PageUptodate(page)) {
+ kaddr = kmap_atomic(page, KM_USER0);
+ memcpy(kaddr, (u8*)a +
+@@ -1538,7 +1721,9 @@ int ntfs_attr_make_non_resident(ntfs_ino
+ ffs(ni->itype.compressed.block_size) - 1;
+ ni->itype.compressed.block_clusters = 1U <<
+ a->data.non_resident.compression_unit;
+- }
++ vi->i_blocks = ni->itype.compressed.size >> 9;
++ } else
++ vi->i_blocks = ni->allocated_size >> 9;
+ write_unlock_irqrestore(&ni->size_lock, flags);
+ /*
+ * This needs to be last since the address space operations ->readpage
+@@ -1652,6 +1837,640 @@ page_err_out:
+ }
+
+ /**
++ * ntfs_attr_extend_allocation - extend the allocated space of an attribute
++ * @ni: ntfs inode of the attribute whose allocation to extend
++ * @new_alloc_size: new size in bytes to which to extend the allocation to
++ * @new_data_size: new size in bytes to which to extend the data to
++ * @data_start: beginning of region which is required to be non-sparse
++ *
++ * Extend the allocated space of an attribute described by the ntfs inode @ni
++ * to @new_alloc_size bytes. If @data_start is -1, the whole extension may be
++ * implemented as a hole in the file (as long as both the volume and the ntfs
++ * inode @ni have sparse support enabled). If @data_start is >= 0, then the
++ * region between the old allocated size and @data_start - 1 may be made sparse
++ * but the regions between @data_start and @new_alloc_size must be backed by
++ * actual clusters.
++ *
++ * If @new_data_size is -1, it is ignored. If it is >= 0, then the data size
++ * of the attribute is extended to @new_data_size. Note that the i_size of the
++ * vfs inode is not updated. Only the data size in the base attribute record
++ * is updated. The caller has to update i_size separately if this is required.
++ * WARNING: It is a BUG() for @new_data_size to be smaller than the old data
++ * size as well as for @new_data_size to be greater than @new_alloc_size.
++ *
++ * For resident attributes this involves resizing the attribute record and if
++ * necessary moving it and/or other attributes into extent mft records and/or
++ * converting the attribute to a non-resident attribute which in turn involves
++ * extending the allocation of a non-resident attribute as described below.
++ *
++ * For non-resident attributes this involves allocating clusters in the data
++ * zone on the volume (except for regions that are being made sparse) and
++ * extending the run list to describe the allocated clusters as well as
++ * updating the mapping pairs array of the attribute. This in turn involves
++ * resizing the attribute record and if necessary moving it and/or other
++ * attributes into extent mft records and/or splitting the attribute record
++ * into multiple extent attribute records.
++ *
++ * Also, the attribute list attribute is updated if present and in some of the
++ * above cases (the ones where extent mft records/attributes come into play),
++ * an attribute list attribute is created if not already present.
++ *
++ * Return the new allocated size on success and -errno on error. In the case
++ * that an error is encountered but a partial extension at least up to
++ * @data_start (if present) is possible, the allocation is partially extended
++ * and this is returned. This means the caller must check the returned size to
++ * determine if the extension was partial. If @data_start is -1 then partial
++ * allocations are not performed.
++ *
++ * WARNING: Do not call ntfs_attr_extend_allocation() for $MFT/$DATA.
++ *
++ * Locking: This function takes the runlist lock of @ni for writing as well as
++ * locking the mft record of the base ntfs inode. These locks are maintained
++ * throughout execution of the function. These locks are required so that the
++ * attribute can be resized safely and so that it can for example be converted
++ * from resident to non-resident safely.
++ *
++ * TODO: At present attribute list attribute handling is not implemented.
++ *
++ * TODO: At present it is not safe to call this function for anything other
++ * than the $DATA attribute(s) of an uncompressed and unencrypted file.
++ */
++s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size,
++ const s64 new_data_size, const s64 data_start)
++{
++ VCN vcn;
++ s64 ll, allocated_size, start = data_start;
++ struct inode *vi = VFS_I(ni);
++ ntfs_volume *vol = ni->vol;
++ ntfs_inode *base_ni;
++ MFT_RECORD *m;
++ ATTR_RECORD *a;
++ ntfs_attr_search_ctx *ctx;
++ runlist_element *rl, *rl2;
++ unsigned long flags;
++ int err, mp_size;
++ u32 attr_len = 0; /* Silence stupid gcc warning. */
++ BOOL mp_rebuilt;
++
++#ifdef NTFS_DEBUG
++ read_lock_irqsave(&ni->size_lock, flags);
++ allocated_size = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, "
++ "old_allocated_size 0x%llx, "
++ "new_allocated_size 0x%llx, new_data_size 0x%llx, "
++ "data_start 0x%llx.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type),
++ (unsigned long long)allocated_size,
++ (unsigned long long)new_alloc_size,
++ (unsigned long long)new_data_size,
++ (unsigned long long)start);
++#endif
++retry_extend:
++ /*
++ * For non-resident attributes, @start and @new_size need to be aligned
++ * to cluster boundaries for allocation purposes.
++ */
++ if (NInoNonResident(ni)) {
++ if (start > 0)
++ start &= ~(s64)vol->cluster_size_mask;
++ new_alloc_size = (new_alloc_size + vol->cluster_size - 1) &
++ ~(s64)vol->cluster_size_mask;
++ }
++ BUG_ON(new_data_size >= 0 && new_data_size > new_alloc_size);
++ /* Check if new size is allowed in $AttrDef. */
++ err = ntfs_attr_size_bounds_check(vol, ni->type, new_alloc_size);
++ if (unlikely(err)) {
++ /* Only emit errors when the write will fail completely. */
++ read_lock_irqsave(&ni->size_lock, flags);
++ allocated_size = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (start < 0 || start >= allocated_size) {
++ if (err == -ERANGE) {
++ ntfs_error(vol->sb, "Cannot extend allocation "
++ "of inode 0x%lx, attribute "
++ "type 0x%x, because the new "
++ "allocation would exceed the "
++ "maximum allowed size for "
++ "this attribute type.",
++ vi->i_ino, (unsigned)
++ le32_to_cpu(ni->type));
++ } else {
++ ntfs_error(vol->sb, "Cannot extend allocation "
++ "of inode 0x%lx, attribute "
++ "type 0x%x, because this "
++ "attribute type is not "
++ "defined on the NTFS volume. "
++ "Possible corruption! You "
++ "should run chkdsk!",
++ vi->i_ino, (unsigned)
++ le32_to_cpu(ni->type));
++ }
++ }
++ /* Translate error code to be POSIX conformant for write(2). */
++ if (err == -ERANGE)
++ err = -EFBIG;
++ else
++ err = -EIO;
++ return err;
++ }
++ if (!NInoAttr(ni))
++ base_ni = ni;
++ else
++ base_ni = ni->ext.base_ntfs_ino;
++ /*
++ * We will be modifying both the runlist (if non-resident) and the mft
++ * record so lock them both down.
++ */
++ down_write(&ni->runlist.lock);
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m)) {
++ err = PTR_ERR(m);
++ m = NULL;
++ ctx = NULL;
++ goto err_out;
++ }
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++ read_lock_irqsave(&ni->size_lock, flags);
++ allocated_size = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ /*
++ * If non-resident, seek to the last extent. If resident, there is
++ * only one extent, so seek to that.
++ */
++ vcn = NInoNonResident(ni) ? allocated_size >> vol->cluster_size_bits :
++ 0;
++ /*
++ * Abort if someone did the work whilst we waited for the locks. If we
++ * just converted the attribute from resident to non-resident it is
++ * likely that exactly this has happened already. We cannot quite
++ * abort if we need to update the data size.
++ */
++ if (unlikely(new_alloc_size <= allocated_size)) {
++ ntfs_debug("Allocated size already exceeds requested size.");
++ new_alloc_size = allocated_size;
++ if (new_data_size < 0)
++ goto done;
++ /*
++ * We want the first attribute extent so that we can update the
++ * data size.
++ */
++ vcn = 0;
++ }
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, vcn, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ goto err_out;
++ }
++ m = ctx->mrec;
++ a = ctx->attr;
++ /* Use goto to reduce indentation. */
++ if (a->non_resident)
++ goto do_non_resident_extend;
++ BUG_ON(NInoNonResident(ni));
++ /* The total length of the attribute value. */
++ attr_len = le32_to_cpu(a->data.resident.value_length);
++ /*
++ * Extend the attribute record to be able to store the new attribute
++ * size. ntfs_attr_record_resize() will not do anything if the size is
++ * not changing.
++ */
++ if (new_alloc_size < vol->mft_record_size &&
++ !ntfs_attr_record_resize(m, a,
++ le16_to_cpu(a->data.resident.value_offset) +
++ new_alloc_size)) {
++ /* The resize succeeded! */
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->allocated_size = le32_to_cpu(a->length) -
++ le16_to_cpu(a->data.resident.value_offset);
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ if (new_data_size >= 0) {
++ BUG_ON(new_data_size < attr_len);
++ a->data.resident.value_length =
++ cpu_to_le32((u32)new_data_size);
++ }
++ goto flush_done;
++ }
++ /*
++ * We have to drop all the locks so we can call
++ * ntfs_attr_make_non_resident(). This could be optimised by try-
++ * locking the first page cache page and only if that fails dropping
++ * the locks, locking the page, and redoing all the locking and
++ * lookups. While this would be a huge optimisation, it is not worth
++ * it as this is definitely a slow code path.
++ */
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++ /*
++ * Not enough space in the mft record, try to make the attribute
++ * non-resident and if successful restart the extension process.
++ */
++ err = ntfs_attr_make_non_resident(ni, attr_len);
++ if (likely(!err))
++ goto retry_extend;
++ /*
++ * Could not make non-resident. If this is due to this not being
++ * permitted for this attribute type or there not being enough space,
++ * try to make other attributes non-resident. Otherwise fail.
++ */
++ if (unlikely(err != -EPERM && err != -ENOSPC)) {
++ /* Only emit errors when the write will fail completely. */
++ read_lock_irqsave(&ni->size_lock, flags);
++ allocated_size = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Cannot extend allocation of "
++ "inode 0x%lx, attribute type 0x%x, "
++ "because the conversion from resident "
++ "to non-resident attribute failed "
++ "with error code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ if (err != -ENOMEM)
++ err = -EIO;
++ goto conv_err_out;
++ }
++ /* TODO: Not implemented from here, abort. */
++ read_lock_irqsave(&ni->size_lock, flags);
++ allocated_size = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (start < 0 || start >= allocated_size) {
++ if (err == -ENOSPC)
++ ntfs_error(vol->sb, "Not enough space in the mft "
++ "record/on disk for the non-resident "
++ "attribute value. This case is not "
++ "implemented yet.");
++ else /* if (err == -EPERM) */
++ ntfs_error(vol->sb, "This attribute type may not be "
++ "non-resident. This case is not "
++ "implemented yet.");
++ }
++ err = -EOPNOTSUPP;
++ goto conv_err_out;
++#if 0
++ // TODO: Attempt to make other attributes non-resident.
++ if (!err)
++ goto do_resident_extend;
++ /*
++ * Both the attribute list attribute and the standard information
++ * attribute must remain in the base inode. Thus, if this is one of
++ * these attributes, we have to try to move other attributes out into
++ * extent mft records instead.
++ */
++ if (ni->type == AT_ATTRIBUTE_LIST ||
++ ni->type == AT_STANDARD_INFORMATION) {
++ // TODO: Attempt to move other attributes into extent mft
++ // records.
++ err = -EOPNOTSUPP;
++ if (!err)
++ goto do_resident_extend;
++ goto err_out;
++ }
++ // TODO: Attempt to move this attribute to an extent mft record, but
++ // only if it is not already the only attribute in an mft record in
++ // which case there would be nothing to gain.
++ err = -EOPNOTSUPP;
++ if (!err)
++ goto do_resident_extend;
++ /* There is nothing we can do to make enough space. )-: */
++ goto err_out;
++#endif
++do_non_resident_extend:
++ BUG_ON(!NInoNonResident(ni));
++ if (new_alloc_size == allocated_size) {
++ BUG_ON(vcn);
++ goto alloc_done;
++ }
++ /*
++ * If the data starts after the end of the old allocation, this is a
++ * $DATA attribute and sparse attributes are enabled on the volume and
++ * for this inode, then create a sparse region between the old
++ * allocated size and the start of the data. Otherwise simply proceed
++ * with filling the whole space between the old allocated size and the
++ * new allocated size with clusters.
++ */
++ if ((start >= 0 && start <= allocated_size) || ni->type != AT_DATA ||
++ !NVolSparseEnabled(vol) || NInoSparseDisabled(ni))
++ goto skip_sparse;
++ // TODO: This is not implemented yet. We just fill in with real
++ // clusters for now...
++ ntfs_debug("Inserting holes is not-implemented yet. Falling back to "
++ "allocating real clusters instead.");
++skip_sparse:
++ rl = ni->runlist.rl;
++ if (likely(rl)) {
++ /* Seek to the end of the runlist. */
++ while (rl->length)
++ rl++;
++ }
++ /* If this attribute extent is not mapped, map it now. */
++ if (unlikely(!rl || rl->lcn == LCN_RL_NOT_MAPPED ||
++ (rl->lcn == LCN_ENOENT && rl > ni->runlist.rl &&
++ (rl-1)->lcn == LCN_RL_NOT_MAPPED))) {
++ if (!rl && !allocated_size)
++ goto first_alloc;
++ rl = ntfs_mapping_pairs_decompress(vol, a, ni->runlist.rl);
++ if (IS_ERR(rl)) {
++ err = PTR_ERR(rl);
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Cannot extend allocation "
++ "of inode 0x%lx, attribute "
++ "type 0x%x, because the "
++ "mapping of a runlist "
++ "fragment failed with error "
++ "code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type),
++ err);
++ if (err != -ENOMEM)
++ err = -EIO;
++ goto err_out;
++ }
++ ni->runlist.rl = rl;
++ /* Seek to the end of the runlist. */
++ while (rl->length)
++ rl++;
++ }
++ /*
++ * We now know the runlist of the last extent is mapped and @rl is at
++ * the end of the runlist. We want to begin allocating clusters
++ * starting at the last allocated cluster to reduce fragmentation. If
++ * there are no valid LCNs in the attribute we let the cluster
++ * allocator choose the starting cluster.
++ */
++ /* If the last LCN is a hole or simillar seek back to last real LCN. */
++ while (rl->lcn < 0 && rl > ni->runlist.rl)
++ rl--;
++first_alloc:
++ // FIXME: Need to implement partial allocations so at least part of the
++ // write can be performed when start >= 0. (Needed for POSIX write(2)
++ // conformance.)
++ rl2 = ntfs_cluster_alloc(vol, allocated_size >> vol->cluster_size_bits,
++ (new_alloc_size - allocated_size) >>
++ vol->cluster_size_bits, (rl && (rl->lcn >= 0)) ?
++ rl->lcn + rl->length : -1, DATA_ZONE, TRUE);
++ if (IS_ERR(rl2)) {
++ err = PTR_ERR(rl2);
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Cannot extend allocation of "
++ "inode 0x%lx, attribute type 0x%x, "
++ "because the allocation of clusters "
++ "failed with error code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ if (err != -ENOMEM && err != -ENOSPC)
++ err = -EIO;
++ goto err_out;
++ }
++ rl = ntfs_runlists_merge(ni->runlist.rl, rl2);
++ if (IS_ERR(rl)) {
++ err = PTR_ERR(rl);
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Cannot extend allocation of "
++ "inode 0x%lx, attribute type 0x%x, "
++ "because the runlist merge failed "
++ "with error code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ if (err != -ENOMEM)
++ err = -EIO;
++ if (ntfs_cluster_free_from_rl(vol, rl2)) {
++ ntfs_error(vol->sb, "Failed to release allocated "
++ "cluster(s) in error code path. Run "
++ "chkdsk to recover the lost "
++ "cluster(s).");
++ NVolSetErrors(vol);
++ }
++ ntfs_free(rl2);
++ goto err_out;
++ }
++ ni->runlist.rl = rl;
++ ntfs_debug("Allocated 0x%llx clusters.", (long long)(new_alloc_size -
++ allocated_size) >> vol->cluster_size_bits);
++ /* Find the runlist element with which the attribute extent starts. */
++ ll = sle64_to_cpu(a->data.non_resident.lowest_vcn);
++ rl2 = ntfs_rl_find_vcn_nolock(rl, ll);
++ BUG_ON(!rl2);
++ BUG_ON(!rl2->length);
++ BUG_ON(rl2->lcn < LCN_HOLE);
++ mp_rebuilt = FALSE;
++ /* Get the size for the new mapping pairs array for this extent. */
++ mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, -1);
++ if (unlikely(mp_size <= 0)) {
++ err = mp_size;
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Cannot extend allocation of "
++ "inode 0x%lx, attribute type 0x%x, "
++ "because determining the size for the "
++ "mapping pairs failed with error code "
++ "%i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ err = -EIO;
++ goto undo_alloc;
++ }
++ /* Extend the attribute record to fit the bigger mapping pairs array. */
++ attr_len = le32_to_cpu(a->length);
++ err = ntfs_attr_record_resize(m, a, mp_size +
++ le16_to_cpu(a->data.non_resident.mapping_pairs_offset));
++ if (unlikely(err)) {
++ BUG_ON(err != -ENOSPC);
++ // TODO: Deal with this by moving this extent to a new mft
++ // record or by starting a new extent in a new mft record,
++ // possibly by extending this extent partially and filling it
++ // and creating a new extent for the remainder, or by making
++ // other attributes non-resident and/or by moving other
++ // attributes out of this mft record.
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Not enough space in the mft "
++ "record for the extended attribute "
++ "record. This case is not "
++ "implemented yet.");
++ err = -EOPNOTSUPP;
++ goto undo_alloc;
++ }
++ mp_rebuilt = TRUE;
++ /* Generate the mapping pairs array directly into the attr record. */
++ err = ntfs_mapping_pairs_build(vol, (u8*)a +
++ le16_to_cpu(a->data.non_resident.mapping_pairs_offset),
++ mp_size, rl2, ll, -1, NULL);
++ if (unlikely(err)) {
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Cannot extend allocation of "
++ "inode 0x%lx, attribute type 0x%x, "
++ "because building the mapping pairs "
++ "failed with error code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ err = -EIO;
++ goto undo_alloc;
++ }
++ /* Update the highest_vcn. */
++ a->data.non_resident.highest_vcn = cpu_to_sle64((new_alloc_size >>
++ vol->cluster_size_bits) - 1);
++ /*
++ * We now have extended the allocated size of the attribute. Reflect
++ * this in the ntfs_inode structure and the attribute record.
++ */
++ if (a->data.non_resident.lowest_vcn) {
++ /*
++ * We are not in the first attribute extent, switch to it, but
++ * first ensure the changes will make it to disk later.
++ */
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ ntfs_attr_reinit_search_ctx(ctx);
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, 0, NULL, 0, ctx);
++ if (unlikely(err))
++ goto restore_undo_alloc;
++ /* @m is not used any more so no need to set it. */
++ a = ctx->attr;
++ }
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->allocated_size = new_alloc_size;
++ a->data.non_resident.allocated_size = cpu_to_sle64(new_alloc_size);
++ /*
++ * FIXME: This would fail if @ni is a directory, $MFT, or an index,
++ * since those can have sparse/compressed set. For example can be
++ * set compressed even though it is not compressed itself and in that
++ * case the bit means that files are to be created compressed in the
++ * directory... At present this is ok as this code is only called for
++ * regular files, and only for their $DATA attribute(s).
++ * FIXME: The calculation is wrong if we created a hole above. For now
++ * it does not matter as we never create holes.
++ */
++ if (NInoSparse(ni) || NInoCompressed(ni)) {
++ ni->itype.compressed.size += new_alloc_size - allocated_size;
++ a->data.non_resident.compressed_size =
++ cpu_to_sle64(ni->itype.compressed.size);
++ vi->i_blocks = ni->itype.compressed.size >> 9;
++ } else
++ vi->i_blocks = new_alloc_size >> 9;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++alloc_done:
++ if (new_data_size >= 0) {
++ BUG_ON(new_data_size <
++ sle64_to_cpu(a->data.non_resident.data_size));
++ a->data.non_resident.data_size = cpu_to_sle64(new_data_size);
++ }
++flush_done:
++ /* Ensure the changes make it to disk. */
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++done:
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++ ntfs_debug("Done, new_allocated_size 0x%llx.",
++ (unsigned long long)new_alloc_size);
++ return new_alloc_size;
++restore_undo_alloc:
++ if (start < 0 || start >= allocated_size)
++ ntfs_error(vol->sb, "Cannot complete extension of allocation "
++ "of inode 0x%lx, attribute type 0x%x, because "
++ "lookup of first attribute extent failed with "
++ "error code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ if (err == -ENOENT)
++ err = -EIO;
++ ntfs_attr_reinit_search_ctx(ctx);
++ if (ntfs_attr_lookup(ni->type, ni->name, ni->name_len, CASE_SENSITIVE,
++ allocated_size >> vol->cluster_size_bits, NULL, 0,
++ ctx)) {
++ ntfs_error(vol->sb, "Failed to find last attribute extent of "
++ "attribute in error code path. Run chkdsk to "
++ "recover.");
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->allocated_size = new_alloc_size;
++ /*
++ * FIXME: This would fail if @ni is a directory... See above.
++ * FIXME: The calculation is wrong if we created a hole above.
++ * For now it does not matter as we never create holes.
++ */
++ if (NInoSparse(ni) || NInoCompressed(ni)) {
++ ni->itype.compressed.size += new_alloc_size -
++ allocated_size;
++ vi->i_blocks = ni->itype.compressed.size >> 9;
++ } else
++ vi->i_blocks = new_alloc_size >> 9;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++ /*
++ * The only thing that is now wrong is the allocated size of the
++ * base attribute extent which chkdsk should be able to fix.
++ */
++ NVolSetErrors(vol);
++ return err;
++ }
++ ctx->attr->data.non_resident.highest_vcn = cpu_to_sle64(
++ (allocated_size >> vol->cluster_size_bits) - 1);
++undo_alloc:
++ ll = allocated_size >> vol->cluster_size_bits;
++ if (ntfs_cluster_free(ni, ll, -1, ctx) < 0) {
++ ntfs_error(vol->sb, "Failed to release allocated cluster(s) "
++ "in error code path. Run chkdsk to recover "
++ "the lost cluster(s).");
++ NVolSetErrors(vol);
++ }
++ m = ctx->mrec;
++ a = ctx->attr;
++ /*
++ * If the runlist truncation fails and/or the search context is no
++ * longer valid, we cannot resize the attribute record or build the
++ * mapping pairs array thus we mark the inode bad so that no access to
++ * the freed clusters can happen.
++ */
++ if (ntfs_rl_truncate_nolock(vol, &ni->runlist, ll) || IS_ERR(m)) {
++ ntfs_error(vol->sb, "Failed to %s in error code path. Run "
++ "chkdsk to recover.", IS_ERR(m) ?
++ "restore attribute search context" :
++ "truncate attribute runlist");
++ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
++ } else if (mp_rebuilt) {
++ if (ntfs_attr_record_resize(m, a, attr_len)) {
++ ntfs_error(vol->sb, "Failed to restore attribute "
++ "record in error code path. Run "
++ "chkdsk to recover.");
++ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
++ } else /* if (success) */ {
++ if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
++ a->data.non_resident.
++ mapping_pairs_offset), attr_len -
++ le16_to_cpu(a->data.non_resident.
++ mapping_pairs_offset), rl2, ll, -1,
++ NULL)) {
++ ntfs_error(vol->sb, "Failed to restore "
++ "mapping pairs array in error "
++ "code path. Run chkdsk to "
++ "recover.");
++ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
++ }
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ }
++ }
++err_out:
++ if (ctx)
++ ntfs_attr_put_search_ctx(ctx);
++ if (m)
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++conv_err_out:
++ ntfs_debug("Failed. Returning error code %i.", err);
++ return err;
++}
++
++/**
+ * ntfs_attr_set - fill (a part of) an attribute with a byte
+ * @ni: ntfs inode describing the attribute to fill
+ * @ofs: offset inside the attribute at which to start to fill
+@@ -1773,6 +2592,8 @@ int ntfs_attr_set(ntfs_inode *ni, const
+ /* Finally unlock and release the page. */
+ unlock_page(page);
+ page_cache_release(page);
++ balance_dirty_pages_ratelimited(mapping);
++ cond_resched();
+ }
+ /* If there is a last partial page, need to do it the slow way. */
+ if (end_ofs) {
+diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
+--- a/fs/ntfs/attrib.h
++++ b/fs/ntfs/attrib.h
+@@ -60,14 +60,15 @@ typedef struct {
+ ATTR_RECORD *base_attr;
+ } ntfs_attr_search_ctx;
+
+-extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn);
++extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn,
++ ntfs_attr_search_ctx *ctx);
+ extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
+
+ extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
+ const BOOL write_locked);
+
+ extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni,
+- const VCN vcn, const BOOL write_locked);
++ const VCN vcn, ntfs_attr_search_ctx *ctx);
+
+ int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
+ const u32 name_len, const IGNORE_CASE_BOOL ic,
+@@ -102,7 +103,10 @@ extern int ntfs_attr_record_resize(MFT_R
+ extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
+ const u32 new_size);
+
+-extern int ntfs_attr_make_non_resident(ntfs_inode *ni);
++extern int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size);
++
++extern s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size,
++ const s64 new_data_size, const s64 data_start);
+
+ extern int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt,
+ const u8 val);
+diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
+--- a/fs/ntfs/file.c
++++ b/fs/ntfs/file.c
+@@ -19,11 +19,24 @@
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-#include <linux/pagemap.h>
+ #include <linux/buffer_head.h>
++#include <linux/pagemap.h>
++#include <linux/pagevec.h>
++#include <linux/sched.h>
++#include <linux/swap.h>
++#include <linux/uio.h>
++#include <linux/writeback.h>
+
++#include <asm/page.h>
++#include <asm/uaccess.h>
++
++#include "attrib.h"
++#include "bitmap.h"
+ #include "inode.h"
+ #include "debug.h"
++#include "lcnalloc.h"
++#include "malloc.h"
++#include "mft.h"
+ #include "ntfs.h"
+
+ /**
+@@ -56,6 +69,2185 @@ static int ntfs_file_open(struct inode *
+ #ifdef NTFS_RW
+
+ /**
++ * ntfs_attr_extend_initialized - extend the initialized size of an attribute
++ * @ni: ntfs inode of the attribute to extend
++ * @new_init_size: requested new initialized size in bytes
++ * @cached_page: store any allocated but unused page here
++ * @lru_pvec: lru-buffering pagevec of the caller
++ *
++ * Extend the initialized size of an attribute described by the ntfs inode @ni
++ * to @new_init_size bytes. This involves zeroing any non-sparse space between
++ * the old initialized size and @new_init_size both in the page cache and on
++ * disk (if relevant complete pages are already uptodate in the page cache then
++ * these are simply marked dirty).
++ *
++ * As a side-effect, the file size (vfs inode->i_size) may be incremented as,
++ * in the resident attribute case, it is tied to the initialized size and, in
++ * the non-resident attribute case, it may not fall below the initialized size.
++ *
++ * Note that if the attribute is resident, we do not need to touch the page
++ * cache at all. This is because if the page cache page is not uptodate we
++ * bring it uptodate later, when doing the write to the mft record since we
++ * then already have the page mapped. And if the page is uptodate, the
++ * non-initialized region will already have been zeroed when the page was
++ * brought uptodate and the region may in fact already have been overwritten
++ * with new data via mmap() based writes, so we cannot just zero it. And since
++ * POSIX specifies that the behaviour of resizing a file whilst it is mmap()ped
++ * is unspecified, we choose not to do zeroing and thus we do not need to touch
++ * the page at all. For a more detailed explanation see ntfs_truncate() in
++ * fs/ntfs/inode.c.
++ *
++ * @cached_page and @lru_pvec are just optimizations for dealing with multiple
++ * pages.
++ *
++ * Return 0 on success and -errno on error. In the case that an error is
++ * encountered it is possible that the initialized size will already have been
++ * incremented some way towards @new_init_size but it is guaranteed that if
++ * this is the case, the necessary zeroing will also have happened and that all
++ * metadata is self-consistent.
++ *
++ * Locking: i_sem on the vfs inode corrseponsind to the ntfs inode @ni must be
++ * held by the caller.
++ */
++static int ntfs_attr_extend_initialized(ntfs_inode *ni, const s64 new_init_size,
++ struct page **cached_page, struct pagevec *lru_pvec)
++{
++ s64 old_init_size;
++ loff_t old_i_size;
++ pgoff_t index, end_index;
++ unsigned long flags;
++ struct inode *vi = VFS_I(ni);
++ ntfs_inode *base_ni;
++ MFT_RECORD *m = NULL;
++ ATTR_RECORD *a;
++ ntfs_attr_search_ctx *ctx = NULL;
++ struct address_space *mapping;
++ struct page *page = NULL;
++ u8 *kattr;
++ int err;
++ u32 attr_len;
++
++ read_lock_irqsave(&ni->size_lock, flags);
++ old_init_size = ni->initialized_size;
++ old_i_size = i_size_read(vi);
++ BUG_ON(new_init_size > ni->allocated_size);
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, "
++ "old_initialized_size 0x%llx, "
++ "new_initialized_size 0x%llx, i_size 0x%llx.",
++ vi->i_ino, (unsigned)le32_to_cpu(ni->type),
++ (unsigned long long)old_init_size,
++ (unsigned long long)new_init_size, old_i_size);
++ if (!NInoAttr(ni))
++ base_ni = ni;
++ else
++ base_ni = ni->ext.base_ntfs_ino;
++ /* Use goto to reduce indentation and we need the label below anyway. */
++ if (NInoNonResident(ni))
++ goto do_non_resident_extend;
++ BUG_ON(old_init_size != old_i_size);
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m)) {
++ err = PTR_ERR(m);
++ m = NULL;
++ goto err_out;
++ }
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, 0, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ goto err_out;
++ }
++ m = ctx->mrec;
++ a = ctx->attr;
++ BUG_ON(a->non_resident);
++ /* The total length of the attribute value. */
++ attr_len = le32_to_cpu(a->data.resident.value_length);
++ BUG_ON(old_i_size != (loff_t)attr_len);
++ /*
++ * Do the zeroing in the mft record and update the attribute size in
++ * the mft record.
++ */
++ kattr = (u8*)a + le16_to_cpu(a->data.resident.value_offset);
++ memset(kattr + attr_len, 0, new_init_size - attr_len);
++ a->data.resident.value_length = cpu_to_le32((u32)new_init_size);
++ /* Finally, update the sizes in the vfs and ntfs inodes. */
++ write_lock_irqsave(&ni->size_lock, flags);
++ i_size_write(vi, new_init_size);
++ ni->initialized_size = new_init_size;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ goto done;
++do_non_resident_extend:
++ /*
++ * If the new initialized size @new_init_size exceeds the current file
++ * size (vfs inode->i_size), we need to extend the file size to the
++ * new initialized size.
++ */
++ if (new_init_size > old_i_size) {
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m)) {
++ err = PTR_ERR(m);
++ m = NULL;
++ goto err_out;
++ }
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, 0, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ goto err_out;
++ }
++ m = ctx->mrec;
++ a = ctx->attr;
++ BUG_ON(!a->non_resident);
++ BUG_ON(old_i_size != (loff_t)
++ sle64_to_cpu(a->data.non_resident.data_size));
++ a->data.non_resident.data_size = cpu_to_sle64(new_init_size);
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ /* Update the file size in the vfs inode. */
++ i_size_write(vi, new_init_size);
++ ntfs_attr_put_search_ctx(ctx);
++ ctx = NULL;
++ unmap_mft_record(base_ni);
++ m = NULL;
++ }
++ mapping = vi->i_mapping;
++ index = old_init_size >> PAGE_CACHE_SHIFT;
++ end_index = (new_init_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++ do {
++ /*
++ * Read the page. If the page is not present, this will zero
++ * the uninitialized regions for us.
++ */
++ page = read_cache_page(mapping, index,
++ (filler_t*)mapping->a_ops->readpage, NULL);
++ if (IS_ERR(page)) {
++ err = PTR_ERR(page);
++ goto init_err_out;
++ }
++ wait_on_page_locked(page);
++ if (unlikely(!PageUptodate(page) || PageError(page))) {
++ page_cache_release(page);
++ err = -EIO;
++ goto init_err_out;
++ }
++ /*
++ * Update the initialized size in the ntfs inode. This is
++ * enough to make ntfs_writepage() work.
++ */
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->initialized_size = (index + 1) << PAGE_CACHE_SHIFT;
++ if (ni->initialized_size > new_init_size)
++ ni->initialized_size = new_init_size;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ /* Set the page dirty so it gets written out. */
++ set_page_dirty(page);
++ page_cache_release(page);
++ /*
++ * Play nice with the vm and the rest of the system. This is
++ * very much needed as we can potentially be modifying the
++ * initialised size from a very small value to a really huge
++ * value, e.g.
++ * f = open(somefile, O_TRUNC);
++ * truncate(f, 10GiB);
++ * seek(f, 10GiB);
++ * write(f, 1);
++ * And this would mean we would be marking dirty hundreds of
++ * thousands of pages or as in the above example more than
++ * two and a half million pages!
++ *
++ * TODO: For sparse pages could optimize this workload by using
++ * the FsMisc / MiscFs page bit as a "PageIsSparse" bit. This
++ * would be set in readpage for sparse pages and here we would
++ * not need to mark dirty any pages which have this bit set.
++ * The only caveat is that we have to clear the bit everywhere
++ * where we allocate any clusters that lie in the page or that
++ * contain the page.
++ *
++ * TODO: An even greater optimization would be for us to only
++ * call readpage() on pages which are not in sparse regions as
++ * determined from the runlist. This would greatly reduce the
++ * number of pages we read and make dirty in the case of sparse
++ * files.
++ */
++ balance_dirty_pages_ratelimited(mapping);
++ cond_resched();
++ } while (++index < end_index);
++ read_lock_irqsave(&ni->size_lock, flags);
++ BUG_ON(ni->initialized_size != new_init_size);
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ /* Now bring in sync the initialized_size in the mft record. */
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m)) {
++ err = PTR_ERR(m);
++ m = NULL;
++ goto init_err_out;
++ }
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ goto init_err_out;
++ }
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, 0, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ goto init_err_out;
++ }
++ m = ctx->mrec;
++ a = ctx->attr;
++ BUG_ON(!a->non_resident);
++ a->data.non_resident.initialized_size = cpu_to_sle64(new_init_size);
++done:
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ if (ctx)
++ ntfs_attr_put_search_ctx(ctx);
++ if (m)
++ unmap_mft_record(base_ni);
++ ntfs_debug("Done, initialized_size 0x%llx, i_size 0x%llx.",
++ (unsigned long long)new_init_size, i_size_read(vi));
++ return 0;
++init_err_out:
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->initialized_size = old_init_size;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++err_out:
++ if (ctx)
++ ntfs_attr_put_search_ctx(ctx);
++ if (m)
++ unmap_mft_record(base_ni);
++ ntfs_debug("Failed. Returning error code %i.", err);
++ return err;
++}
++
++/**
++ * ntfs_fault_in_pages_readable -
++ *
++ * Fault a number of userspace pages into pagetables.
++ *
++ * Unlike include/linux/pagemap.h::fault_in_pages_readable(), this one copes
++ * with more than two userspace pages as well as handling the single page case
++ * elegantly.
++ *
++ * If you find this difficult to understand, then think of the while loop being
++ * the following code, except that we do without the integer variable ret:
++ *
++ * do {
++ * ret = __get_user(c, uaddr);
++ * uaddr += PAGE_SIZE;
++ * } while (!ret && uaddr < end);
++ *
++ * Note, the final __get_user() may well run out-of-bounds of the user buffer,
++ * but _not_ out-of-bounds of the page the user buffer belongs to, and since
++ * this is only a read and not a write, and since it is still in the same page,
++ * it should not matter and this makes the code much simpler.
++ */
++static inline void ntfs_fault_in_pages_readable(const char __user *uaddr,
++ int bytes)
++{
++ const char __user *end;
++ volatile char c;
++
++ /* Set @end to the first byte outside the last page we care about. */
++ end = (const char __user*)PAGE_ALIGN((ptrdiff_t __user)uaddr + bytes);
++
++ while (!__get_user(c, uaddr) && (uaddr += PAGE_SIZE, uaddr < end))
++ ;
++}
++
++/**
++ * ntfs_fault_in_pages_readable_iovec -
++ *
++ * Same as ntfs_fault_in_pages_readable() but operates on an array of iovecs.
++ */
++static inline void ntfs_fault_in_pages_readable_iovec(const struct iovec *iov,
++ size_t iov_ofs, int bytes)
++{
++ do {
++ const char __user *buf;
++ unsigned len;
++
++ buf = iov->iov_base + iov_ofs;
++ len = iov->iov_len - iov_ofs;
++ if (len > bytes)
++ len = bytes;
++ ntfs_fault_in_pages_readable(buf, len);
++ bytes -= len;
++ iov++;
++ iov_ofs = 0;
++ } while (bytes);
++}
++
++/**
++ * __ntfs_grab_cache_pages - obtain a number of locked pages
++ * @mapping: address space mapping from which to obtain page cache pages
++ * @index: starting index in @mapping at which to begin obtaining pages
++ * @nr_pages: number of page cache pages to obtain
++ * @pages: array of pages in which to return the obtained page cache pages
++ * @cached_page: allocated but as yet unused page
++ * @lru_pvec: lru-buffering pagevec of caller
++ *
++ * Obtain @nr_pages locked page cache pages from the mapping @maping and
++ * starting at index @index.
++ *
++ * If a page is newly created, increment its refcount and add it to the
++ * caller's lru-buffering pagevec @lru_pvec.
++ *
++ * This is the same as mm/filemap.c::__grab_cache_page(), except that @nr_pages
++ * are obtained at once instead of just one page and that 0 is returned on
++ * success and -errno on error.
++ *
++ * Note, the page locks are obtained in ascending page index order.
++ */
++static inline int __ntfs_grab_cache_pages(struct address_space *mapping,
++ pgoff_t index, const unsigned nr_pages, struct page **pages,
++ struct page **cached_page, struct pagevec *lru_pvec)
++{
++ int err, nr;
++
++ BUG_ON(!nr_pages);
++ err = nr = 0;
++ do {
++ pages[nr] = find_lock_page(mapping, index);
++ if (!pages[nr]) {
++ if (!*cached_page) {
++ *cached_page = page_cache_alloc(mapping);
++ if (unlikely(!*cached_page)) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++ }
++ err = add_to_page_cache(*cached_page, mapping, index,
++ GFP_KERNEL);
++ if (unlikely(err)) {
++ if (err == -EEXIST)
++ continue;
++ goto err_out;
++ }
++ pages[nr] = *cached_page;
++ page_cache_get(*cached_page);
++ if (unlikely(!pagevec_add(lru_pvec, *cached_page)))
++ __pagevec_lru_add(lru_pvec);
++ *cached_page = NULL;
++ }
++ index++;
++ nr++;
++ } while (nr < nr_pages);
++out:
++ return err;
++err_out:
++ while (nr > 0) {
++ unlock_page(pages[--nr]);
++ page_cache_release(pages[nr]);
++ }
++ goto out;
++}
++
++static inline int ntfs_submit_bh_for_read(struct buffer_head *bh)
++{
++ lock_buffer(bh);
++ get_bh(bh);
++ bh->b_end_io = end_buffer_read_sync;
++ return submit_bh(READ, bh);
++}
++
++/**
++ * ntfs_prepare_pages_for_non_resident_write - prepare pages for receiving data
++ * @pages: array of destination pages
++ * @nr_pages: number of pages in @pages
++ * @pos: byte position in file at which the write begins
++ * @bytes: number of bytes to be written
++ *
++ * This is called for non-resident attributes from ntfs_file_buffered_write()
++ * with i_sem held on the inode (@pages[0]->mapping->host). There are
++ * @nr_pages pages in @pages which are locked but not kmap()ped. The source
++ * data has not yet been copied into the @pages.
++ *
++ * Need to fill any holes with actual clusters, allocate buffers if necessary,
++ * ensure all the buffers are mapped, and bring uptodate any buffers that are
++ * only partially being written to.
++ *
++ * If @nr_pages is greater than one, we are guaranteed that the cluster size is
++ * greater than PAGE_CACHE_SIZE, that all pages in @pages are entirely inside
++ * the same cluster and that they are the entirety of that cluster, and that
++ * the cluster is sparse, i.e. we need to allocate a cluster to fill the hole.
++ *
++ * i_size is not to be modified yet.
++ *
++ * Return 0 on success or -errno on error.
++ */
++static int ntfs_prepare_pages_for_non_resident_write(struct page **pages,
++ unsigned nr_pages, s64 pos, size_t bytes)
++{
++ VCN vcn, highest_vcn = 0, cpos, cend, bh_cpos, bh_cend;
++ LCN lcn;
++ s64 bh_pos, vcn_len, end, initialized_size;
++ sector_t lcn_block;
++ struct page *page;
++ struct inode *vi;
++ ntfs_inode *ni, *base_ni = NULL;
++ ntfs_volume *vol;
++ runlist_element *rl, *rl2;
++ struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
++ ntfs_attr_search_ctx *ctx = NULL;
++ MFT_RECORD *m = NULL;
++ ATTR_RECORD *a = NULL;
++ unsigned long flags;
++ u32 attr_rec_len = 0;
++ unsigned blocksize, u;
++ int err, mp_size;
++ BOOL rl_write_locked, was_hole, is_retry;
++ unsigned char blocksize_bits;
++ struct {
++ u8 runlist_merged:1;
++ u8 mft_attr_mapped:1;
++ u8 mp_rebuilt:1;
++ u8 attr_switched:1;
++ } status = { 0, 0, 0, 0 };
++
++ BUG_ON(!nr_pages);
++ BUG_ON(!pages);
++ BUG_ON(!*pages);
++ vi = pages[0]->mapping->host;
++ ni = NTFS_I(vi);
++ vol = ni->vol;
++ ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, start page "
++ "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.",
++ vi->i_ino, ni->type, pages[0]->index, nr_pages,
++ (long long)pos, bytes);
++ blocksize_bits = vi->i_blkbits;
++ blocksize = 1 << blocksize_bits;
++ u = 0;
++ do {
++ struct page *page = pages[u];
++ /*
++ * create_empty_buffers() will create uptodate/dirty buffers if
++ * the page is uptodate/dirty.
++ */
++ if (!page_has_buffers(page)) {
++ create_empty_buffers(page, blocksize, 0);
++ if (unlikely(!page_has_buffers(page)))
++ return -ENOMEM;
++ }
++ } while (++u < nr_pages);
++ rl_write_locked = FALSE;
++ rl = NULL;
++ err = 0;
++ vcn = lcn = -1;
++ vcn_len = 0;
++ lcn_block = -1;
++ was_hole = FALSE;
++ cpos = pos >> vol->cluster_size_bits;
++ end = pos + bytes;
++ cend = (end + vol->cluster_size - 1) >> vol->cluster_size_bits;
++ /*
++ * Loop over each page and for each page over each buffer. Use goto to
++ * reduce indentation.
++ */
++ u = 0;
++do_next_page:
++ page = pages[u];
++ bh_pos = (s64)page->index << PAGE_CACHE_SHIFT;
++ bh = head = page_buffers(page);
++ do {
++ VCN cdelta;
++ s64 bh_end;
++ unsigned bh_cofs;
++
++ /* Clear buffer_new on all buffers to reinitialise state. */
++ if (buffer_new(bh))
++ clear_buffer_new(bh);
++ bh_end = bh_pos + blocksize;
++ bh_cpos = bh_pos >> vol->cluster_size_bits;
++ bh_cofs = bh_pos & vol->cluster_size_mask;
++ if (buffer_mapped(bh)) {
++ /*
++ * The buffer is already mapped. If it is uptodate,
++ * ignore it.
++ */
++ if (buffer_uptodate(bh))
++ continue;
++ /*
++ * The buffer is not uptodate. If the page is uptodate
++ * set the buffer uptodate and otherwise ignore it.
++ */
++ if (PageUptodate(page)) {
++ set_buffer_uptodate(bh);
++ continue;
++ }
++ /*
++ * Neither the page nor the buffer are uptodate. If
++ * the buffer is only partially being written to, we
++ * need to read it in before the write, i.e. now.
++ */
++ if ((bh_pos < pos && bh_end > pos) ||
++ (bh_pos < end && bh_end > end)) {
++ /*
++ * If the buffer is fully or partially within
++ * the initialized size, do an actual read.
++ * Otherwise, simply zero the buffer.
++ */
++ read_lock_irqsave(&ni->size_lock, flags);
++ initialized_size = ni->initialized_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (bh_pos < initialized_size) {
++ ntfs_submit_bh_for_read(bh);
++ *wait_bh++ = bh;
++ } else {
++ u8 *kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + bh_offset(bh), 0,
++ blocksize);
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ set_buffer_uptodate(bh);
++ }
++ }
++ continue;
++ }
++ /* Unmapped buffer. Need to map it. */
++ bh->b_bdev = vol->sb->s_bdev;
++ /*
++ * If the current buffer is in the same clusters as the map
++ * cache, there is no need to check the runlist again. The
++ * map cache is made up of @vcn, which is the first cached file
++ * cluster, @vcn_len which is the number of cached file
++ * clusters, @lcn is the device cluster corresponding to @vcn,
++ * and @lcn_block is the block number corresponding to @lcn.
++ */
++ cdelta = bh_cpos - vcn;
++ if (likely(!cdelta || (cdelta > 0 && cdelta < vcn_len))) {
++map_buffer_cached:
++ BUG_ON(lcn < 0);
++ bh->b_blocknr = lcn_block +
++ (cdelta << (vol->cluster_size_bits -
++ blocksize_bits)) +
++ (bh_cofs >> blocksize_bits);
++ set_buffer_mapped(bh);
++ /*
++ * If the page is uptodate so is the buffer. If the
++ * buffer is fully outside the write, we ignore it if
++ * it was already allocated and we mark it dirty so it
++ * gets written out if we allocated it. On the other
++ * hand, if we allocated the buffer but we are not
++ * marking it dirty we set buffer_new so we can do
++ * error recovery.
++ */
++ if (PageUptodate(page)) {
++ if (!buffer_uptodate(bh))
++ set_buffer_uptodate(bh);
++ if (unlikely(was_hole)) {
++ /* We allocated the buffer. */
++ unmap_underlying_metadata(bh->b_bdev,
++ bh->b_blocknr);
++ if (bh_end <= pos || bh_pos >= end)
++ mark_buffer_dirty(bh);
++ else
++ set_buffer_new(bh);
++ }
++ continue;
++ }
++ /* Page is _not_ uptodate. */
++ if (likely(!was_hole)) {
++ /*
++ * Buffer was already allocated. If it is not
++ * uptodate and is only partially being written
++ * to, we need to read it in before the write,
++ * i.e. now.
++ */
++ if (!buffer_uptodate(bh) && bh_pos < end &&
++ bh_end > pos &&
++ (bh_pos < pos ||
++ bh_end > end)) {
++ /*
++ * If the buffer is fully or partially
++ * within the initialized size, do an
++ * actual read. Otherwise, simply zero
++ * the buffer.
++ */
++ read_lock_irqsave(&ni->size_lock,
++ flags);
++ initialized_size = ni->initialized_size;
++ read_unlock_irqrestore(&ni->size_lock,
++ flags);
++ if (bh_pos < initialized_size) {
++ ntfs_submit_bh_for_read(bh);
++ *wait_bh++ = bh;
++ } else {
++ u8 *kaddr = kmap_atomic(page,
++ KM_USER0);
++ memset(kaddr + bh_offset(bh),
++ 0, blocksize);
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ set_buffer_uptodate(bh);
++ }
++ }
++ continue;
++ }
++ /* We allocated the buffer. */
++ unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
++ /*
++ * If the buffer is fully outside the write, zero it,
++ * set it uptodate, and mark it dirty so it gets
++ * written out. If it is partially being written to,
++ * zero region surrounding the write but leave it to
++ * commit write to do anything else. Finally, if the
++ * buffer is fully being overwritten, do nothing.
++ */
++ if (bh_end <= pos || bh_pos >= end) {
++ if (!buffer_uptodate(bh)) {
++ u8 *kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + bh_offset(bh), 0,
++ blocksize);
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ set_buffer_uptodate(bh);
++ }
++ mark_buffer_dirty(bh);
++ continue;
++ }
++ set_buffer_new(bh);
++ if (!buffer_uptodate(bh) &&
++ (bh_pos < pos || bh_end > end)) {
++ u8 *kaddr;
++ unsigned pofs;
++
++ kaddr = kmap_atomic(page, KM_USER0);
++ if (bh_pos < pos) {
++ pofs = bh_pos & ~PAGE_CACHE_MASK;
++ memset(kaddr + pofs, 0, pos - bh_pos);
++ }
++ if (bh_end > end) {
++ pofs = end & ~PAGE_CACHE_MASK;
++ memset(kaddr + pofs, 0, bh_end - end);
++ }
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ }
++ continue;
++ }
++ /*
++ * Slow path: this is the first buffer in the cluster. If it
++ * is outside allocated size and is not uptodate, zero it and
++ * set it uptodate.
++ */
++ read_lock_irqsave(&ni->size_lock, flags);
++ initialized_size = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (bh_pos > initialized_size) {
++ if (PageUptodate(page)) {
++ if (!buffer_uptodate(bh))
++ set_buffer_uptodate(bh);
++ } else if (!buffer_uptodate(bh)) {
++ u8 *kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + bh_offset(bh), 0, blocksize);
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ set_buffer_uptodate(bh);
++ }
++ continue;
++ }
++ is_retry = FALSE;
++ if (!rl) {
++ down_read(&ni->runlist.lock);
++retry_remap:
++ rl = ni->runlist.rl;
++ }
++ if (likely(rl != NULL)) {
++ /* Seek to element containing target cluster. */
++ while (rl->length && rl[1].vcn <= bh_cpos)
++ rl++;
++ lcn = ntfs_rl_vcn_to_lcn(rl, bh_cpos);
++ if (likely(lcn >= 0)) {
++ /*
++ * Successful remap, setup the map cache and
++ * use that to deal with the buffer.
++ */
++ was_hole = FALSE;
++ vcn = bh_cpos;
++ vcn_len = rl[1].vcn - vcn;
++ lcn_block = lcn << (vol->cluster_size_bits -
++ blocksize_bits);
++ cdelta = 0;
++ /*
++ * If the number of remaining clusters touched
++ * by the write is smaller or equal to the
++ * number of cached clusters, unlock the
++ * runlist as the map cache will be used from
++ * now on.
++ */
++ if (likely(vcn + vcn_len >= cend)) {
++ if (rl_write_locked) {
++ up_write(&ni->runlist.lock);
++ rl_write_locked = FALSE;
++ } else
++ up_read(&ni->runlist.lock);
++ rl = NULL;
++ }
++ goto map_buffer_cached;
++ }
++ } else
++ lcn = LCN_RL_NOT_MAPPED;
++ /*
++ * If it is not a hole and not out of bounds, the runlist is
++ * probably unmapped so try to map it now.
++ */
++ if (unlikely(lcn != LCN_HOLE && lcn != LCN_ENOENT)) {
++ if (likely(!is_retry && lcn == LCN_RL_NOT_MAPPED)) {
++ /* Attempt to map runlist. */
++ if (!rl_write_locked) {
++ /*
++ * We need the runlist locked for
++ * writing, so if it is locked for
++ * reading relock it now and retry in
++ * case it changed whilst we dropped
++ * the lock.
++ */
++ up_read(&ni->runlist.lock);
++ down_write(&ni->runlist.lock);
++ rl_write_locked = TRUE;
++ goto retry_remap;
++ }
++ err = ntfs_map_runlist_nolock(ni, bh_cpos,
++ NULL);
++ if (likely(!err)) {
++ is_retry = TRUE;
++ goto retry_remap;
++ }
++ /*
++ * If @vcn is out of bounds, pretend @lcn is
++ * LCN_ENOENT. As long as the buffer is out
++ * of bounds this will work fine.
++ */
++ if (err == -ENOENT) {
++ lcn = LCN_ENOENT;
++ err = 0;
++ goto rl_not_mapped_enoent;
++ }
++ } else
++ err = -EIO;
++ /* Failed to map the buffer, even after retrying. */
++ bh->b_blocknr = -1;
++ ntfs_error(vol->sb, "Failed to write to inode 0x%lx, "
++ "attribute type 0x%x, vcn 0x%llx, "
++ "vcn offset 0x%x, because its "
++ "location on disk could not be "
++ "determined%s (error code %i).",
++ ni->mft_no, ni->type,
++ (unsigned long long)bh_cpos,
++ (unsigned)bh_pos &
++ vol->cluster_size_mask,
++ is_retry ? " even after retrying" : "",
++ err);
++ break;
++ }
++rl_not_mapped_enoent:
++ /*
++ * The buffer is in a hole or out of bounds. We need to fill
++ * the hole, unless the buffer is in a cluster which is not
++ * touched by the write, in which case we just leave the buffer
++ * unmapped. This can only happen when the cluster size is
++ * less than the page cache size.
++ */
++ if (unlikely(vol->cluster_size < PAGE_CACHE_SIZE)) {
++ bh_cend = (bh_end + vol->cluster_size - 1) >>
++ vol->cluster_size_bits;
++ if ((bh_cend <= cpos || bh_cpos >= cend)) {
++ bh->b_blocknr = -1;
++ /*
++ * If the buffer is uptodate we skip it. If it
++ * is not but the page is uptodate, we can set
++ * the buffer uptodate. If the page is not
++ * uptodate, we can clear the buffer and set it
++ * uptodate. Whether this is worthwhile is
++ * debatable and this could be removed.
++ */
++ if (PageUptodate(page)) {
++ if (!buffer_uptodate(bh))
++ set_buffer_uptodate(bh);
++ } else if (!buffer_uptodate(bh)) {
++ u8 *kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + bh_offset(bh), 0,
++ blocksize);
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ set_buffer_uptodate(bh);
++ }
++ continue;
++ }
++ }
++ /*
++ * Out of bounds buffer is invalid if it was not really out of
++ * bounds.
++ */
++ BUG_ON(lcn != LCN_HOLE);
++ /*
++ * We need the runlist locked for writing, so if it is locked
++ * for reading relock it now and retry in case it changed
++ * whilst we dropped the lock.
++ */
++ BUG_ON(!rl);
++ if (!rl_write_locked) {
++ up_read(&ni->runlist.lock);
++ down_write(&ni->runlist.lock);
++ rl_write_locked = TRUE;
++ goto retry_remap;
++ }
++ /* Find the previous last allocated cluster. */
++ BUG_ON(rl->lcn != LCN_HOLE);
++ lcn = -1;
++ rl2 = rl;
++ while (--rl2 >= ni->runlist.rl) {
++ if (rl2->lcn >= 0) {
++ lcn = rl2->lcn + rl2->length;
++ break;
++ }
++ }
++ rl2 = ntfs_cluster_alloc(vol, bh_cpos, 1, lcn, DATA_ZONE,
++ FALSE);
++ if (IS_ERR(rl2)) {
++ err = PTR_ERR(rl2);
++ ntfs_debug("Failed to allocate cluster, error code %i.",
++ err);
++ break;
++ }
++ lcn = rl2->lcn;
++ rl = ntfs_runlists_merge(ni->runlist.rl, rl2);
++ if (IS_ERR(rl)) {
++ err = PTR_ERR(rl);
++ if (err != -ENOMEM)
++ err = -EIO;
++ if (ntfs_cluster_free_from_rl(vol, rl2)) {
++ ntfs_error(vol->sb, "Failed to release "
++ "allocated cluster in error "
++ "code path. Run chkdsk to "
++ "recover the lost cluster.");
++ NVolSetErrors(vol);
++ }
++ ntfs_free(rl2);
++ break;
++ }
++ ni->runlist.rl = rl;
++ status.runlist_merged = 1;
++ ntfs_debug("Allocated cluster, lcn 0x%llx.", lcn);
++ /* Map and lock the mft record and get the attribute record. */
++ if (!NInoAttr(ni))
++ base_ni = ni;
++ else
++ base_ni = ni->ext.base_ntfs_ino;
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m)) {
++ err = PTR_ERR(m);
++ break;
++ }
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ unmap_mft_record(base_ni);
++ break;
++ }
++ status.mft_attr_mapped = 1;
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, bh_cpos, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ break;
++ }
++ m = ctx->mrec;
++ a = ctx->attr;
++ /*
++ * Find the runlist element with which the attribute extent
++ * starts. Note, we cannot use the _attr_ version because we
++ * have mapped the mft record. That is ok because we know the
++ * runlist fragment must be mapped already to have ever gotten
++ * here, so we can just use the _rl_ version.
++ */
++ vcn = sle64_to_cpu(a->data.non_resident.lowest_vcn);
++ rl2 = ntfs_rl_find_vcn_nolock(rl, vcn);
++ BUG_ON(!rl2);
++ BUG_ON(!rl2->length);
++ BUG_ON(rl2->lcn < LCN_HOLE);
++ highest_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn);
++ /*
++ * If @highest_vcn is zero, calculate the real highest_vcn
++ * (which can really be zero).
++ */
++ if (!highest_vcn)
++ highest_vcn = (sle64_to_cpu(
++ a->data.non_resident.allocated_size) >>
++ vol->cluster_size_bits) - 1;
++ /*
++ * Determine the size of the mapping pairs array for the new
++ * extent, i.e. the old extent with the hole filled.
++ */
++ mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, vcn,
++ highest_vcn);
++ if (unlikely(mp_size <= 0)) {
++ if (!(err = mp_size))
++ err = -EIO;
++ ntfs_debug("Failed to get size for mapping pairs "
++ "array, error code %i.", err);
++ break;
++ }
++ /*
++ * Resize the attribute record to fit the new mapping pairs
++ * array.
++ */
++ attr_rec_len = le32_to_cpu(a->length);
++ err = ntfs_attr_record_resize(m, a, mp_size + le16_to_cpu(
++ a->data.non_resident.mapping_pairs_offset));
++ if (unlikely(err)) {
++ BUG_ON(err != -ENOSPC);
++ // TODO: Deal with this by using the current attribute
++ // and fill it with as much of the mapping pairs
++ // array as possible. Then loop over each attribute
++ // extent rewriting the mapping pairs arrays as we go
++ // along and if when we reach the end we have not
++ // enough space, try to resize the last attribute
++ // extent and if even that fails, add a new attribute
++ // extent.
++ // We could also try to resize at each step in the hope
++ // that we will not need to rewrite every single extent.
++ // Note, we may need to decompress some extents to fill
++ // the runlist as we are walking the extents...
++ ntfs_error(vol->sb, "Not enough space in the mft "
++ "record for the extended attribute "
++ "record. This case is not "
++ "implemented yet.");
++ err = -EOPNOTSUPP;
++ break ;
++ }
++ status.mp_rebuilt = 1;
++ /*
++ * Generate the mapping pairs array directly into the attribute
++ * record.
++ */
++ err = ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
++ a->data.non_resident.mapping_pairs_offset),
++ mp_size, rl2, vcn, highest_vcn, NULL);
++ if (unlikely(err)) {
++ ntfs_error(vol->sb, "Cannot fill hole in inode 0x%lx, "
++ "attribute type 0x%x, because building "
++ "the mapping pairs failed with error "
++ "code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ err = -EIO;
++ break;
++ }
++ /* Update the highest_vcn but only if it was not set. */
++ if (unlikely(!a->data.non_resident.highest_vcn))
++ a->data.non_resident.highest_vcn =
++ cpu_to_sle64(highest_vcn);
++ /*
++ * If the attribute is sparse/compressed, update the compressed
++ * size in the ntfs_inode structure and the attribute record.
++ */
++ if (likely(NInoSparse(ni) || NInoCompressed(ni))) {
++ /*
++ * If we are not in the first attribute extent, switch
++ * to it, but first ensure the changes will make it to
++ * disk later.
++ */
++ if (a->data.non_resident.lowest_vcn) {
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ ntfs_attr_reinit_search_ctx(ctx);
++ err = ntfs_attr_lookup(ni->type, ni->name,
++ ni->name_len, CASE_SENSITIVE,
++ 0, NULL, 0, ctx);
++ if (unlikely(err)) {
++ status.attr_switched = 1;
++ break;
++ }
++ /* @m is not used any more so do not set it. */
++ a = ctx->attr;
++ }
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->itype.compressed.size += vol->cluster_size;
++ a->data.non_resident.compressed_size =
++ cpu_to_sle64(ni->itype.compressed.size);
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ }
++ /* Ensure the changes make it to disk. */
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ /* Successfully filled the hole. */
++ status.runlist_merged = 0;
++ status.mft_attr_mapped = 0;
++ status.mp_rebuilt = 0;
++ /* Setup the map cache and use that to deal with the buffer. */
++ was_hole = TRUE;
++ vcn = bh_cpos;
++ vcn_len = 1;
++ lcn_block = lcn << (vol->cluster_size_bits - blocksize_bits);
++ cdelta = 0;
++ /*
++ * If the number of remaining clusters in the @pages is smaller
++ * or equal to the number of cached clusters, unlock the
++ * runlist as the map cache will be used from now on.
++ */
++ if (likely(vcn + vcn_len >= cend)) {
++ up_write(&ni->runlist.lock);
++ rl_write_locked = FALSE;
++ rl = NULL;
++ }
++ goto map_buffer_cached;
++ } while (bh_pos += blocksize, (bh = bh->b_this_page) != head);
++ /* If there are no errors, do the next page. */
++ if (likely(!err && ++u < nr_pages))
++ goto do_next_page;
++ /* If there are no errors, release the runlist lock if we took it. */
++ if (likely(!err)) {
++ if (unlikely(rl_write_locked)) {
++ up_write(&ni->runlist.lock);
++ rl_write_locked = FALSE;
++ } else if (unlikely(rl))
++ up_read(&ni->runlist.lock);
++ rl = NULL;
++ }
++ /* If we issued read requests, let them complete. */
++ read_lock_irqsave(&ni->size_lock, flags);
++ initialized_size = ni->initialized_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ while (wait_bh > wait) {
++ bh = *--wait_bh;
++ wait_on_buffer(bh);
++ if (likely(buffer_uptodate(bh))) {
++ page = bh->b_page;
++ bh_pos = ((s64)page->index << PAGE_CACHE_SHIFT) +
++ bh_offset(bh);
++ /*
++ * If the buffer overflows the initialized size, need
++ * to zero the overflowing region.
++ */
++ if (unlikely(bh_pos + blocksize > initialized_size)) {
++ u8 *kaddr;
++ int ofs = 0;
++
++ if (likely(bh_pos < initialized_size))
++ ofs = initialized_size - bh_pos;
++ kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + bh_offset(bh) + ofs, 0,
++ blocksize - ofs);
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ }
++ } else /* if (unlikely(!buffer_uptodate(bh))) */
++ err = -EIO;
++ }
++ if (likely(!err)) {
++ /* Clear buffer_new on all buffers. */
++ u = 0;
++ do {
++ bh = head = page_buffers(pages[u]);
++ do {
++ if (buffer_new(bh))
++ clear_buffer_new(bh);
++ } while ((bh = bh->b_this_page) != head);
++ } while (++u < nr_pages);
++ ntfs_debug("Done.");
++ return err;
++ }
++ if (status.attr_switched) {
++ /* Get back to the attribute extent we modified. */
++ ntfs_attr_reinit_search_ctx(ctx);
++ if (ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, bh_cpos, NULL, 0, ctx)) {
++ ntfs_error(vol->sb, "Failed to find required "
++ "attribute extent of attribute in "
++ "error code path. Run chkdsk to "
++ "recover.");
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->itype.compressed.size += vol->cluster_size;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ /*
++ * The only thing that is now wrong is the compressed
++ * size of the base attribute extent which chkdsk
++ * should be able to fix.
++ */
++ NVolSetErrors(vol);
++ } else {
++ m = ctx->mrec;
++ a = ctx->attr;
++ status.attr_switched = 0;
++ }
++ }
++ /*
++ * If the runlist has been modified, need to restore it by punching a
++ * hole into it and we then need to deallocate the on-disk cluster as
++ * well. Note, we only modify the runlist if we are able to generate a
++ * new mapping pairs array, i.e. only when the mapped attribute extent
++ * is not switched.
++ */
++ if (status.runlist_merged && !status.attr_switched) {
++ BUG_ON(!rl_write_locked);
++ /* Make the file cluster we allocated sparse in the runlist. */
++ if (ntfs_rl_punch_nolock(vol, &ni->runlist, bh_cpos, 1)) {
++ ntfs_error(vol->sb, "Failed to punch hole into "
++ "attribute runlist in error code "
++ "path. Run chkdsk to recover the "
++ "lost cluster.");
++ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
++ } else /* if (success) */ {
++ status.runlist_merged = 0;
++ /*
++ * Deallocate the on-disk cluster we allocated but only
++ * if we succeeded in punching its vcn out of the
++ * runlist.
++ */
++ down_write(&vol->lcnbmp_lock);
++ if (ntfs_bitmap_clear_bit(vol->lcnbmp_ino, lcn)) {
++ ntfs_error(vol->sb, "Failed to release "
++ "allocated cluster in error "
++ "code path. Run chkdsk to "
++ "recover the lost cluster.");
++ NVolSetErrors(vol);
++ }
++ up_write(&vol->lcnbmp_lock);
++ }
++ }
++ /*
++ * Resize the attribute record to its old size and rebuild the mapping
++ * pairs array. Note, we only can do this if the runlist has been
++ * restored to its old state which also implies that the mapped
++ * attribute extent is not switched.
++ */
++ if (status.mp_rebuilt && !status.runlist_merged) {
++ if (ntfs_attr_record_resize(m, a, attr_rec_len)) {
++ ntfs_error(vol->sb, "Failed to restore attribute "
++ "record in error code path. Run "
++ "chkdsk to recover.");
++ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
++ } else /* if (success) */ {
++ if (ntfs_mapping_pairs_build(vol, (u8*)a +
++ le16_to_cpu(a->data.non_resident.
++ mapping_pairs_offset), attr_rec_len -
++ le16_to_cpu(a->data.non_resident.
++ mapping_pairs_offset), ni->runlist.rl,
++ vcn, highest_vcn, NULL)) {
++ ntfs_error(vol->sb, "Failed to restore "
++ "mapping pairs array in error "
++ "code path. Run chkdsk to "
++ "recover.");
++ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
++ }
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ }
++ }
++ /* Release the mft record and the attribute. */
++ if (status.mft_attr_mapped) {
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ }
++ /* Release the runlist lock. */
++ if (rl_write_locked)
++ up_write(&ni->runlist.lock);
++ else if (rl)
++ up_read(&ni->runlist.lock);
++ /*
++ * Zero out any newly allocated blocks to avoid exposing stale data.
++ * If BH_New is set, we know that the block was newly allocated above
++ * and that it has not been fully zeroed and marked dirty yet.
++ */
++ nr_pages = u;
++ u = 0;
++ end = bh_cpos << vol->cluster_size_bits;
++ do {
++ page = pages[u];
++ bh = head = page_buffers(page);
++ do {
++ if (u == nr_pages &&
++ ((s64)page->index << PAGE_CACHE_SHIFT) +
++ bh_offset(bh) >= end)
++ break;
++ if (!buffer_new(bh))
++ continue;
++ clear_buffer_new(bh);
++ if (!buffer_uptodate(bh)) {
++ if (PageUptodate(page))
++ set_buffer_uptodate(bh);
++ else {
++ u8 *kaddr = kmap_atomic(page, KM_USER0);
++ memset(kaddr + bh_offset(bh), 0,
++ blocksize);
++ kunmap_atomic(kaddr, KM_USER0);
++ flush_dcache_page(page);
++ set_buffer_uptodate(bh);
++ }
++ }
++ mark_buffer_dirty(bh);
++ } while ((bh = bh->b_this_page) != head);
++ } while (++u <= nr_pages);
++ ntfs_error(vol->sb, "Failed. Returning error code %i.", err);
++ return err;
++}
++
++/*
++ * Copy as much as we can into the pages and return the number of bytes which
++ * were sucessfully copied. If a fault is encountered then clear the pages
++ * out to (ofs + bytes) and return the number of bytes which were copied.
++ */
++static inline size_t ntfs_copy_from_user(struct page **pages,
++ unsigned nr_pages, unsigned ofs, const char __user *buf,
++ size_t bytes)
++{
++ struct page **last_page = pages + nr_pages;
++ char *kaddr;
++ size_t total = 0;
++ unsigned len;
++ int left;
++
++ do {
++ len = PAGE_CACHE_SIZE - ofs;
++ if (len > bytes)
++ len = bytes;
++ kaddr = kmap_atomic(*pages, KM_USER0);
++ left = __copy_from_user_inatomic(kaddr + ofs, buf, len);
++ kunmap_atomic(kaddr, KM_USER0);
++ if (unlikely(left)) {
++ /* Do it the slow way. */
++ kaddr = kmap(*pages);
++ left = __copy_from_user(kaddr + ofs, buf, len);
++ kunmap(*pages);
++ if (unlikely(left))
++ goto err_out;
++ }
++ total += len;
++ bytes -= len;
++ if (!bytes)
++ break;
++ buf += len;
++ ofs = 0;
++ } while (++pages < last_page);
++out:
++ return total;
++err_out:
++ total += len - left;
++ /* Zero the rest of the target like __copy_from_user(). */
++ while (++pages < last_page) {
++ bytes -= len;
++ if (!bytes)
++ break;
++ len = PAGE_CACHE_SIZE;
++ if (len > bytes)
++ len = bytes;
++ kaddr = kmap_atomic(*pages, KM_USER0);
++ memset(kaddr, 0, len);
++ kunmap_atomic(kaddr, KM_USER0);
++ }
++ goto out;
++}
++
++static size_t __ntfs_copy_from_user_iovec(char *vaddr,
++ const struct iovec *iov, size_t iov_ofs, size_t bytes)
++{
++ size_t total = 0;
++
++ while (1) {
++ const char __user *buf = iov->iov_base + iov_ofs;
++ unsigned len;
++ size_t left;
++
++ len = iov->iov_len - iov_ofs;
++ if (len > bytes)
++ len = bytes;
++ left = __copy_from_user_inatomic(vaddr, buf, len);
++ total += len;
++ bytes -= len;
++ vaddr += len;
++ if (unlikely(left)) {
++ /*
++ * Zero the rest of the target like __copy_from_user().
++ */
++ memset(vaddr, 0, bytes);
++ total -= left;
++ break;
++ }
++ if (!bytes)
++ break;
++ iov++;
++ iov_ofs = 0;
++ }
++ return total;
++}
++
++static inline void ntfs_set_next_iovec(const struct iovec **iovp,
++ size_t *iov_ofsp, size_t bytes)
++{
++ const struct iovec *iov = *iovp;
++ size_t iov_ofs = *iov_ofsp;
++
++ while (bytes) {
++ unsigned len;
++
++ len = iov->iov_len - iov_ofs;
++ if (len > bytes)
++ len = bytes;
++ bytes -= len;
++ iov_ofs += len;
++ if (iov->iov_len == iov_ofs) {
++ iov++;
++ iov_ofs = 0;
++ }
++ }
++ *iovp = iov;
++ *iov_ofsp = iov_ofs;
++}
++
++/*
++ * This has the same side-effects and return value as ntfs_copy_from_user().
++ * The difference is that on a fault we need to memset the remainder of the
++ * pages (out to offset + bytes), to emulate ntfs_copy_from_user()'s
++ * single-segment behaviour.
++ *
++ * We call the same helper (__ntfs_copy_from_user_iovec()) both when atomic and
++ * when not atomic. This is ok because __ntfs_copy_from_user_iovec() calls
++ * __copy_from_user_inatomic() and it is ok to call this when non-atomic. In
++ * fact, the only difference between __copy_from_user_inatomic() and
++ * __copy_from_user() is that the latter calls might_sleep(). And on many
++ * architectures __copy_from_user_inatomic() is just defined to
++ * __copy_from_user() so it makes no difference at all on those architectures.
++ */
++static inline size_t ntfs_copy_from_user_iovec(struct page **pages,
++ unsigned nr_pages, unsigned ofs, const struct iovec **iov,
++ size_t *iov_ofs, size_t bytes)
++{
++ struct page **last_page = pages + nr_pages;
++ char *kaddr;
++ size_t copied, len, total = 0;
++
++ do {
++ len = PAGE_CACHE_SIZE - ofs;
++ if (len > bytes)
++ len = bytes;
++ kaddr = kmap_atomic(*pages, KM_USER0);
++ copied = __ntfs_copy_from_user_iovec(kaddr + ofs,
++ *iov, *iov_ofs, len);
++ kunmap_atomic(kaddr, KM_USER0);
++ if (unlikely(copied != len)) {
++ /* Do it the slow way. */
++ kaddr = kmap(*pages);
++ copied = __ntfs_copy_from_user_iovec(kaddr + ofs,
++ *iov, *iov_ofs, len);
++ kunmap(*pages);
++ if (unlikely(copied != len))
++ goto err_out;
++ }
++ total += len;
++ bytes -= len;
++ if (!bytes)
++ break;
++ ntfs_set_next_iovec(iov, iov_ofs, len);
++ ofs = 0;
++ } while (++pages < last_page);
++out:
++ return total;
++err_out:
++ total += copied;
++ /* Zero the rest of the target like __copy_from_user(). */
++ while (++pages < last_page) {
++ bytes -= len;
++ if (!bytes)
++ break;
++ len = PAGE_CACHE_SIZE;
++ if (len > bytes)
++ len = bytes;
++ kaddr = kmap_atomic(*pages, KM_USER0);
++ memset(kaddr, 0, len);
++ kunmap_atomic(kaddr, KM_USER0);
++ }
++ goto out;
++}
++
++static inline void ntfs_flush_dcache_pages(struct page **pages,
++ unsigned nr_pages)
++{
++ BUG_ON(!nr_pages);
++ do {
++ /*
++ * Warning: Do not do the decrement at the same time as the
++ * call because flush_dcache_page() is a NULL macro on i386
++ * and hence the decrement never happens.
++ */
++ flush_dcache_page(pages[nr_pages]);
++ } while (--nr_pages > 0);
++}
++
++/**
++ * ntfs_commit_pages_after_non_resident_write - commit the received data
++ * @pages: array of destination pages
++ * @nr_pages: number of pages in @pages
++ * @pos: byte position in file at which the write begins
++ * @bytes: number of bytes to be written
++ *
++ * See description of ntfs_commit_pages_after_write(), below.
++ */
++static inline int ntfs_commit_pages_after_non_resident_write(
++ struct page **pages, const unsigned nr_pages,
++ s64 pos, size_t bytes)
++{
++ s64 end, initialized_size;
++ struct inode *vi;
++ ntfs_inode *ni, *base_ni;
++ struct buffer_head *bh, *head;
++ ntfs_attr_search_ctx *ctx;
++ MFT_RECORD *m;
++ ATTR_RECORD *a;
++ unsigned long flags;
++ unsigned blocksize, u;
++ int err;
++
++ vi = pages[0]->mapping->host;
++ ni = NTFS_I(vi);
++ blocksize = 1 << vi->i_blkbits;
++ end = pos + bytes;
++ u = 0;
++ do {
++ s64 bh_pos;
++ struct page *page;
++ BOOL partial;
++
++ page = pages[u];
++ bh_pos = (s64)page->index << PAGE_CACHE_SHIFT;
++ bh = head = page_buffers(page);
++ partial = FALSE;
++ do {
++ s64 bh_end;
++
++ bh_end = bh_pos + blocksize;
++ if (bh_end <= pos || bh_pos >= end) {
++ if (!buffer_uptodate(bh))
++ partial = TRUE;
++ } else {
++ set_buffer_uptodate(bh);
++ mark_buffer_dirty(bh);
++ }
++ } while (bh_pos += blocksize, (bh = bh->b_this_page) != head);
++ /*
++ * If all buffers are now uptodate but the page is not, set the
++ * page uptodate.
++ */
++ if (!partial && !PageUptodate(page))
++ SetPageUptodate(page);
++ } while (++u < nr_pages);
++ /*
++ * Finally, if we do not need to update initialized_size or i_size we
++ * are finished.
++ */
++ read_lock_irqsave(&ni->size_lock, flags);
++ initialized_size = ni->initialized_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (end <= initialized_size) {
++ ntfs_debug("Done.");
++ return 0;
++ }
++ /*
++ * Update initialized_size/i_size as appropriate, both in the inode and
++ * the mft record.
++ */
++ if (!NInoAttr(ni))
++ base_ni = ni;
++ else
++ base_ni = ni->ext.base_ntfs_ino;
++ /* Map, pin, and lock the mft record. */
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m)) {
++ err = PTR_ERR(m);
++ m = NULL;
++ ctx = NULL;
++ goto err_out;
++ }
++ BUG_ON(!NInoNonResident(ni));
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, 0, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ goto err_out;
++ }
++ a = ctx->attr;
++ BUG_ON(!a->non_resident);
++ write_lock_irqsave(&ni->size_lock, flags);
++ BUG_ON(end > ni->allocated_size);
++ ni->initialized_size = end;
++ a->data.non_resident.initialized_size = cpu_to_sle64(end);
++ if (end > i_size_read(vi)) {
++ i_size_write(vi, end);
++ a->data.non_resident.data_size =
++ a->data.non_resident.initialized_size;
++ }
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ /* Mark the mft record dirty, so it gets written back. */
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ ntfs_debug("Done.");
++ return 0;
++err_out:
++ if (ctx)
++ ntfs_attr_put_search_ctx(ctx);
++ if (m)
++ unmap_mft_record(base_ni);
++ ntfs_error(vi->i_sb, "Failed to update initialized_size/i_size (error "
++ "code %i).", err);
++ if (err != -ENOMEM) {
++ NVolSetErrors(ni->vol);
++ make_bad_inode(VFS_I(base_ni));
++ make_bad_inode(vi);
++ }
++ return err;
++}
++
++/**
++ * ntfs_commit_pages_after_write - commit the received data
++ * @pages: array of destination pages
++ * @nr_pages: number of pages in @pages
++ * @pos: byte position in file at which the write begins
++ * @bytes: number of bytes to be written
++ *
++ * This is called from ntfs_file_buffered_write() with i_sem held on the inode
++ * (@pages[0]->mapping->host). There are @nr_pages pages in @pages which are
++ * locked but not kmap()ped. The source data has already been copied into the
++ * @page. ntfs_prepare_pages_for_non_resident_write() has been called before
++ * the data was copied (for non-resident attributes only) and it returned
++ * success.
++ *
++ * Need to set uptodate and mark dirty all buffers within the boundary of the
++ * write. If all buffers in a page are uptodate we set the page uptodate, too.
++ *
++ * Setting the buffers dirty ensures that they get written out later when
++ * ntfs_writepage() is invoked by the VM.
++ *
++ * Finally, we need to update i_size and initialized_size as appropriate both
++ * in the inode and the mft record.
++ *
++ * This is modelled after fs/buffer.c::generic_commit_write(), which marks
++ * buffers uptodate and dirty, sets the page uptodate if all buffers in the
++ * page are uptodate, and updates i_size if the end of io is beyond i_size. In
++ * that case, it also marks the inode dirty.
++ *
++ * If things have gone as outlined in
++ * ntfs_prepare_pages_for_non_resident_write(), we do not need to do any page
++ * content modifications here for non-resident attributes. For resident
++ * attributes we need to do the uptodate bringing here which we combine with
++ * the copying into the mft record which means we save one atomic kmap.
++ *
++ * Return 0 on success or -errno on error.
++ */
++static int ntfs_commit_pages_after_write(struct page **pages,
++ const unsigned nr_pages, s64 pos, size_t bytes)
++{
++ s64 end, initialized_size;
++ loff_t i_size;
++ struct inode *vi;
++ ntfs_inode *ni, *base_ni;
++ struct page *page;
++ ntfs_attr_search_ctx *ctx;
++ MFT_RECORD *m;
++ ATTR_RECORD *a;
++ char *kattr, *kaddr;
++ unsigned long flags;
++ u32 attr_len;
++ int err;
++
++ BUG_ON(!nr_pages);
++ BUG_ON(!pages);
++ page = pages[0];
++ BUG_ON(!page);
++ vi = page->mapping->host;
++ ni = NTFS_I(vi);
++ ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, start page "
++ "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.",
++ vi->i_ino, ni->type, page->index, nr_pages,
++ (long long)pos, bytes);
++ if (NInoNonResident(ni))
++ return ntfs_commit_pages_after_non_resident_write(pages,
++ nr_pages, pos, bytes);
++ BUG_ON(nr_pages > 1);
++ /*
++ * Attribute is resident, implying it is not compressed, encrypted, or
++ * sparse.
++ */
++ if (!NInoAttr(ni))
++ base_ni = ni;
++ else
++ base_ni = ni->ext.base_ntfs_ino;
++ BUG_ON(NInoNonResident(ni));
++ /* Map, pin, and lock the mft record. */
++ m = map_mft_record(base_ni);
++ if (IS_ERR(m)) {
++ err = PTR_ERR(m);
++ m = NULL;
++ ctx = NULL;
++ goto err_out;
++ }
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
++ if (unlikely(!ctx)) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
++ CASE_SENSITIVE, 0, NULL, 0, ctx);
++ if (unlikely(err)) {
++ if (err == -ENOENT)
++ err = -EIO;
++ goto err_out;
++ }
++ a = ctx->attr;
++ BUG_ON(a->non_resident);
++ /* The total length of the attribute value. */
++ attr_len = le32_to_cpu(a->data.resident.value_length);
++ i_size = i_size_read(vi);
++ BUG_ON(attr_len != i_size);
++ BUG_ON(pos > attr_len);
++ end = pos + bytes;
++ BUG_ON(end > le32_to_cpu(a->length) -
++ le16_to_cpu(a->data.resident.value_offset));
++ kattr = (u8*)a + le16_to_cpu(a->data.resident.value_offset);
++ kaddr = kmap_atomic(page, KM_USER0);
++ /* Copy the received data from the page to the mft record. */
++ memcpy(kattr + pos, kaddr + pos, bytes);
++ /* Update the attribute length if necessary. */
++ if (end > attr_len) {
++ attr_len = end;
++ a->data.resident.value_length = cpu_to_le32(attr_len);
++ }
++ /*
++ * If the page is not uptodate, bring the out of bounds area(s)
++ * uptodate by copying data from the mft record to the page.
++ */
++ if (!PageUptodate(page)) {
++ if (pos > 0)
++ memcpy(kaddr, kattr, pos);
++ if (end < attr_len)
++ memcpy(kaddr + end, kattr + end, attr_len - end);
++ /* Zero the region outside the end of the attribute value. */
++ memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
++ flush_dcache_page(page);
++ SetPageUptodate(page);
++ }
++ kunmap_atomic(kaddr, KM_USER0);
++ /* Update initialized_size/i_size if necessary. */
++ read_lock_irqsave(&ni->size_lock, flags);
++ initialized_size = ni->initialized_size;
++ BUG_ON(end > ni->allocated_size);
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ BUG_ON(initialized_size != i_size);
++ if (end > initialized_size) {
++ unsigned long flags;
++
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->initialized_size = end;
++ i_size_write(vi, end);
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ }
++ /* Mark the mft record dirty, so it gets written back. */
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ ntfs_debug("Done.");
++ return 0;
++err_out:
++ if (err == -ENOMEM) {
++ ntfs_warning(vi->i_sb, "Error allocating memory required to "
++ "commit the write.");
++ if (PageUptodate(page)) {
++ ntfs_warning(vi->i_sb, "Page is uptodate, setting "
++ "dirty so the write will be retried "
++ "later on by the VM.");
++ /*
++ * Put the page on mapping->dirty_pages, but leave its
++ * buffers' dirty state as-is.
++ */
++ __set_page_dirty_nobuffers(page);
++ err = 0;
++ } else
++ ntfs_error(vi->i_sb, "Page is not uptodate. Written "
++ "data has been lost.");
++ } else {
++ ntfs_error(vi->i_sb, "Resident attribute commit write failed "
++ "with error %i.", err);
++ NVolSetErrors(ni->vol);
++ make_bad_inode(VFS_I(base_ni));
++ make_bad_inode(vi);
++ }
++ if (ctx)
++ ntfs_attr_put_search_ctx(ctx);
++ if (m)
++ unmap_mft_record(base_ni);
++ return err;
++}
++
++/**
++ * ntfs_file_buffered_write -
++ *
++ * Locking: The vfs is holding ->i_sem on the inode.
++ */
++static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
++ const struct iovec *iov, unsigned long nr_segs,
++ loff_t pos, loff_t *ppos, size_t count)
++{
++ struct file *file = iocb->ki_filp;
++ struct address_space *mapping = file->f_mapping;
++ struct inode *vi = mapping->host;
++ ntfs_inode *ni = NTFS_I(vi);
++ ntfs_volume *vol = ni->vol;
++ struct page *pages[NTFS_MAX_PAGES_PER_CLUSTER];
++ struct page *cached_page = NULL;
++ char __user *buf = NULL;
++ s64 end, ll;
++ VCN last_vcn;
++ LCN lcn;
++ unsigned long flags;
++ size_t bytes, iov_ofs = 0; /* Offset in the current iovec. */
++ ssize_t status, written;
++ unsigned nr_pages;
++ int err;
++ struct pagevec lru_pvec;
++
++ ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, "
++ "pos 0x%llx, count 0x%lx.",
++ vi->i_ino, (unsigned)le32_to_cpu(ni->type),
++ (unsigned long long)pos, (unsigned long)count);
++ if (unlikely(!count))
++ return 0;
++ BUG_ON(NInoMstProtected(ni));
++ /*
++ * If the attribute is not an index root and it is encrypted or
++ * compressed, we cannot write to it yet. Note we need to check for
++ * AT_INDEX_ALLOCATION since this is the type of both directory and
++ * index inodes.
++ */
++ if (ni->type != AT_INDEX_ALLOCATION) {
++ /* If file is encrypted, deny access, just like NT4. */
++ if (NInoEncrypted(ni)) {
++ /*
++ * Reminder for later: Encrypted files are _always_
++ * non-resident so that the content can always be
++ * encrypted.
++ */
++ ntfs_debug("Denying write access to encrypted file.");
++ return -EACCES;
++ }
++ if (NInoCompressed(ni)) {
++ /* Only unnamed $DATA attribute can be compressed. */
++ BUG_ON(ni->type != AT_DATA);
++ BUG_ON(ni->name_len);
++ /*
++ * Reminder for later: If resident, the data is not
++ * actually compressed. Only on the switch to non-
++ * resident does compression kick in. This is in
++ * contrast to encrypted files (see above).
++ */
++ ntfs_error(vi->i_sb, "Writing to compressed files is "
++ "not implemented yet. Sorry.");
++ return -EOPNOTSUPP;
++ }
++ }
++ /*
++ * If a previous ntfs_truncate() failed, repeat it and abort if it
++ * fails again.
++ */
++ if (unlikely(NInoTruncateFailed(ni))) {
++ down_write(&vi->i_alloc_sem);
++ err = ntfs_truncate(vi);
++ up_write(&vi->i_alloc_sem);
++ if (err || NInoTruncateFailed(ni)) {
++ if (!err)
++ err = -EIO;
++ ntfs_error(vol->sb, "Cannot perform write to inode "
++ "0x%lx, attribute type 0x%x, because "
++ "ntfs_truncate() failed (error code "
++ "%i).", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ return err;
++ }
++ }
++ /* The first byte after the write. */
++ end = pos + count;
++ /*
++ * If the write goes beyond the allocated size, extend the allocation
++ * to cover the whole of the write, rounded up to the nearest cluster.
++ */
++ read_lock_irqsave(&ni->size_lock, flags);
++ ll = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (end > ll) {
++ /* Extend the allocation without changing the data size. */
++ ll = ntfs_attr_extend_allocation(ni, end, -1, pos);
++ if (likely(ll >= 0)) {
++ BUG_ON(pos >= ll);
++ /* If the extension was partial truncate the write. */
++ if (end > ll) {
++ ntfs_debug("Truncating write to inode 0x%lx, "
++ "attribute type 0x%x, because "
++ "the allocation was only "
++ "partially extended.",
++ vi->i_ino, (unsigned)
++ le32_to_cpu(ni->type));
++ end = ll;
++ count = ll - pos;
++ }
++ } else {
++ err = ll;
++ read_lock_irqsave(&ni->size_lock, flags);
++ ll = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ /* Perform a partial write if possible or fail. */
++ if (pos < ll) {
++ ntfs_debug("Truncating write to inode 0x%lx, "
++ "attribute type 0x%x, because "
++ "extending the allocation "
++ "failed (error code %i).",
++ vi->i_ino, (unsigned)
++ le32_to_cpu(ni->type), err);
++ end = ll;
++ count = ll - pos;
++ } else {
++ ntfs_error(vol->sb, "Cannot perform write to "
++ "inode 0x%lx, attribute type "
++ "0x%x, because extending the "
++ "allocation failed (error "
++ "code %i).", vi->i_ino,
++ (unsigned)
++ le32_to_cpu(ni->type), err);
++ return err;
++ }
++ }
++ }
++ pagevec_init(&lru_pvec, 0);
++ written = 0;
++ /*
++ * If the write starts beyond the initialized size, extend it up to the
++ * beginning of the write and initialize all non-sparse space between
++ * the old initialized size and the new one. This automatically also
++ * increments the vfs inode->i_size to keep it above or equal to the
++ * initialized_size.
++ */
++ read_lock_irqsave(&ni->size_lock, flags);
++ ll = ni->initialized_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ if (pos > ll) {
++ err = ntfs_attr_extend_initialized(ni, pos, &cached_page,
++ &lru_pvec);
++ if (err < 0) {
++ ntfs_error(vol->sb, "Cannot perform write to inode "
++ "0x%lx, attribute type 0x%x, because "
++ "extending the initialized size "
++ "failed (error code %i).", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ status = err;
++ goto err_out;
++ }
++ }
++ /*
++ * Determine the number of pages per cluster for non-resident
++ * attributes.
++ */
++ nr_pages = 1;
++ if (vol->cluster_size > PAGE_CACHE_SIZE && NInoNonResident(ni))
++ nr_pages = vol->cluster_size >> PAGE_CACHE_SHIFT;
++ /* Finally, perform the actual write. */
++ last_vcn = -1;
++ if (likely(nr_segs == 1))
++ buf = iov->iov_base;
++ do {
++ VCN vcn;
++ pgoff_t idx, start_idx;
++ unsigned ofs, do_pages, u;
++ size_t copied;
++
++ start_idx = idx = pos >> PAGE_CACHE_SHIFT;
++ ofs = pos & ~PAGE_CACHE_MASK;
++ bytes = PAGE_CACHE_SIZE - ofs;
++ do_pages = 1;
++ if (nr_pages > 1) {
++ vcn = pos >> vol->cluster_size_bits;
++ if (vcn != last_vcn) {
++ last_vcn = vcn;
++ /*
++ * Get the lcn of the vcn the write is in. If
++ * it is a hole, need to lock down all pages in
++ * the cluster.
++ */
++ down_read(&ni->runlist.lock);
++ lcn = ntfs_attr_vcn_to_lcn_nolock(ni, pos >>
++ vol->cluster_size_bits, FALSE);
++ up_read(&ni->runlist.lock);
++ if (unlikely(lcn < LCN_HOLE)) {
++ status = -EIO;
++ if (lcn == LCN_ENOMEM)
++ status = -ENOMEM;
++ else
++ ntfs_error(vol->sb, "Cannot "
++ "perform write to "
++ "inode 0x%lx, "
++ "attribute type 0x%x, "
++ "because the attribute "
++ "is corrupt.",
++ vi->i_ino, (unsigned)
++ le32_to_cpu(ni->type));
++ break;
++ }
++ if (lcn == LCN_HOLE) {
++ start_idx = (pos & ~(s64)
++ vol->cluster_size_mask)
++ >> PAGE_CACHE_SHIFT;
++ bytes = vol->cluster_size - (pos &
++ vol->cluster_size_mask);
++ do_pages = nr_pages;
++ }
++ }
++ }
++ if (bytes > count)
++ bytes = count;
++ /*
++ * Bring in the user page(s) that we will copy from _first_.
++ * Otherwise there is a nasty deadlock on copying from the same
++ * page(s) as we are writing to, without it/them being marked
++ * up-to-date. Note, at present there is nothing to stop the
++ * pages being swapped out between us bringing them into memory
++ * and doing the actual copying.
++ */
++ if (likely(nr_segs == 1))
++ ntfs_fault_in_pages_readable(buf, bytes);
++ else
++ ntfs_fault_in_pages_readable_iovec(iov, iov_ofs, bytes);
++ /* Get and lock @do_pages starting at index @start_idx. */
++ status = __ntfs_grab_cache_pages(mapping, start_idx, do_pages,
++ pages, &cached_page, &lru_pvec);
++ if (unlikely(status))
++ break;
++ /*
++ * For non-resident attributes, we need to fill any holes with
++ * actual clusters and ensure all bufferes are mapped. We also
++ * need to bring uptodate any buffers that are only partially
++ * being written to.
++ */
++ if (NInoNonResident(ni)) {
++ status = ntfs_prepare_pages_for_non_resident_write(
++ pages, do_pages, pos, bytes);
++ if (unlikely(status)) {
++ loff_t i_size;
++
++ do {
++ unlock_page(pages[--do_pages]);
++ page_cache_release(pages[do_pages]);
++ } while (do_pages);
++ /*
++ * The write preparation may have instantiated
++ * allocated space outside i_size. Trim this
++ * off again. We can ignore any errors in this
++ * case as we will just be waisting a bit of
++ * allocated space, which is not a disaster.
++ */
++ i_size = i_size_read(vi);
++ if (pos + bytes > i_size)
++ vmtruncate(vi, i_size);
++ break;
++ }
++ }
++ u = (pos >> PAGE_CACHE_SHIFT) - pages[0]->index;
++ if (likely(nr_segs == 1)) {
++ copied = ntfs_copy_from_user(pages + u, do_pages - u,
++ ofs, buf, bytes);
++ buf += copied;
++ } else
++ copied = ntfs_copy_from_user_iovec(pages + u,
++ do_pages - u, ofs, &iov, &iov_ofs,
++ bytes);
++ ntfs_flush_dcache_pages(pages + u, do_pages - u);
++ status = ntfs_commit_pages_after_write(pages, do_pages, pos,
++ bytes);
++ if (likely(!status)) {
++ written += copied;
++ count -= copied;
++ pos += copied;
++ if (unlikely(copied != bytes))
++ status = -EFAULT;
++ }
++ do {
++ unlock_page(pages[--do_pages]);
++ mark_page_accessed(pages[do_pages]);
++ page_cache_release(pages[do_pages]);
++ } while (do_pages);
++ if (unlikely(status))
++ break;
++ balance_dirty_pages_ratelimited(mapping);
++ cond_resched();
++ } while (count);
++err_out:
++ *ppos = pos;
++ if (cached_page)
++ page_cache_release(cached_page);
++ /* For now, when the user asks for O_SYNC, we actually give O_DSYNC. */
++ if (likely(!status)) {
++ if (unlikely((file->f_flags & O_SYNC) || IS_SYNC(vi))) {
++ if (!mapping->a_ops->writepage || !is_sync_kiocb(iocb))
++ status = generic_osync_inode(vi, mapping,
++ OSYNC_METADATA|OSYNC_DATA);
++ }
++ }
++ pagevec_lru_add(&lru_pvec);
++ ntfs_debug("Done. Returning %s (written 0x%lx, status %li).",
++ written ? "written" : "status", (unsigned long)written,
++ (long)status);
++ return written ? written : status;
++}
++
++/**
++ * ntfs_file_aio_write_nolock -
++ */
++static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
++ const struct iovec *iov, unsigned long nr_segs, loff_t *ppos)
++{
++ struct file *file = iocb->ki_filp;
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
++ loff_t pos;
++ unsigned long seg;
++ size_t count; /* after file limit checks */
++ ssize_t written, err;
++
++ count = 0;
++ for (seg = 0; seg < nr_segs; seg++) {
++ const struct iovec *iv = &iov[seg];
++ /*
++ * If any segment has a negative length, or the cumulative
++ * length ever wraps negative then return -EINVAL.
++ */
++ count += iv->iov_len;
++ if (unlikely((ssize_t)(count|iv->iov_len) < 0))
++ return -EINVAL;
++ if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
++ continue;
++ if (!seg)
++ return -EFAULT;
++ nr_segs = seg;
++ count -= iv->iov_len; /* This segment is no good */
++ break;
++ }
++ pos = *ppos;
++ vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
++ /* We can write back this queue in page reclaim. */
++ current->backing_dev_info = mapping->backing_dev_info;
++ written = 0;
++ err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
++ if (err)
++ goto out;
++ if (!count)
++ goto out;
++ err = remove_suid(file->f_dentry);
++ if (err)
++ goto out;
++ inode_update_time(inode, 1);
++ written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
++ count);
++out:
++ current->backing_dev_info = NULL;
++ return written ? written : err;
++}
++
++/**
++ * ntfs_file_aio_write -
++ */
++static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const char __user *buf,
++ size_t count, loff_t pos)
++{
++ struct file *file = iocb->ki_filp;
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
++ ssize_t ret;
++ struct iovec local_iov = { .iov_base = (void __user *)buf,
++ .iov_len = count };
++
++ BUG_ON(iocb->ki_pos != pos);
++
++ down(&inode->i_sem);
++ ret = ntfs_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
++ up(&inode->i_sem);
++ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ int err = sync_page_range(inode, mapping, pos, ret);
++ if (err < 0)
++ ret = err;
++ }
++ return ret;
++}
++
++/**
++ * ntfs_file_writev -
++ *
++ * Basically the same as generic_file_writev() except that it ends up calling
++ * ntfs_file_aio_write_nolock() instead of __generic_file_aio_write_nolock().
++ */
++static ssize_t ntfs_file_writev(struct file *file, const struct iovec *iov,
++ unsigned long nr_segs, loff_t *ppos)
++{
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
++ struct kiocb kiocb;
++ ssize_t ret;
++
++ down(&inode->i_sem);
++ init_sync_kiocb(&kiocb, file);
++ ret = ntfs_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
++ if (ret == -EIOCBQUEUED)
++ ret = wait_on_sync_kiocb(&kiocb);
++ up(&inode->i_sem);
++ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ int err = sync_page_range(inode, mapping, *ppos - ret, ret);
++ if (err < 0)
++ ret = err;
++ }
++ return ret;
++}
++
++/**
++ * ntfs_file_write - simple wrapper for ntfs_file_writev()
++ */
++static ssize_t ntfs_file_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct iovec local_iov = { .iov_base = (void __user *)buf,
++ .iov_len = count };
++
++ return ntfs_file_writev(file, &local_iov, 1, ppos);
++}
++
++/**
+ * ntfs_file_fsync - sync a file to disk
+ * @filp: file to be synced
+ * @dentry: dentry describing the file to sync
+@@ -113,39 +2305,39 @@ static int ntfs_file_fsync(struct file *
+ #endif /* NTFS_RW */
+
+ struct file_operations ntfs_file_ops = {
+- .llseek = generic_file_llseek, /* Seek inside file. */
+- .read = generic_file_read, /* Read from file. */
+- .aio_read = generic_file_aio_read, /* Async read from file. */
+- .readv = generic_file_readv, /* Read from file. */
++ .llseek = generic_file_llseek, /* Seek inside file. */
++ .read = generic_file_read, /* Read from file. */
++ .aio_read = generic_file_aio_read, /* Async read from file. */
++ .readv = generic_file_readv, /* Read from file. */
+ #ifdef NTFS_RW
+- .write = generic_file_write, /* Write to file. */
+- .aio_write = generic_file_aio_write, /* Async write to file. */
+- .writev = generic_file_writev, /* Write to file. */
+- /*.release = ,*/ /* Last file is closed. See
+- fs/ext2/file.c::
+- ext2_release_file() for
+- how to use this to discard
+- preallocated space for
+- write opened files. */
+- .fsync = ntfs_file_fsync, /* Sync a file to disk. */
+- /*.aio_fsync = ,*/ /* Sync all outstanding async
+- i/o operations on a
+- kiocb. */
++ .write = ntfs_file_write, /* Write to file. */
++ .aio_write = ntfs_file_aio_write, /* Async write to file. */
++ .writev = ntfs_file_writev, /* Write to file. */
++ /*.release = ,*/ /* Last file is closed. See
++ fs/ext2/file.c::
++ ext2_release_file() for
++ how to use this to discard
++ preallocated space for
++ write opened files. */
++ .fsync = ntfs_file_fsync, /* Sync a file to disk. */
++ /*.aio_fsync = ,*/ /* Sync all outstanding async
++ i/o operations on a
++ kiocb. */
+ #endif /* NTFS_RW */
+- /*.ioctl = ,*/ /* Perform function on the
+- mounted filesystem. */
+- .mmap = generic_file_mmap, /* Mmap file. */
+- .open = ntfs_file_open, /* Open file. */
+- .sendfile = generic_file_sendfile, /* Zero-copy data send with
+- the data source being on
+- the ntfs partition. We
+- do not need to care about
+- the data destination. */
+- /*.sendpage = ,*/ /* Zero-copy data send with
+- the data destination being
+- on the ntfs partition. We
+- do not need to care about
+- the data source. */
++ /*.ioctl = ,*/ /* Perform function on the
++ mounted filesystem. */
++ .mmap = generic_file_mmap, /* Mmap file. */
++ .open = ntfs_file_open, /* Open file. */
++ .sendfile = generic_file_sendfile, /* Zero-copy data send with
++ the data source being on
++ the ntfs partition. We do
++ not need to care about the
++ data destination. */
++ /*.sendpage = ,*/ /* Zero-copy data send with
++ the data destination being
++ on the ntfs partition. We
++ do not need to care about
++ the data source. */
+ };
+
+ struct inode_operations ntfs_file_inode_ops = {
+diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
+--- a/fs/ntfs/inode.c
++++ b/fs/ntfs/inode.c
+@@ -30,6 +30,7 @@
+ #include "debug.h"
+ #include "inode.h"
+ #include "attrib.h"
++#include "lcnalloc.h"
+ #include "malloc.h"
+ #include "mft.h"
+ #include "time.h"
+@@ -2291,11 +2292,16 @@ int ntfs_show_options(struct seq_file *s
+
+ #ifdef NTFS_RW
+
++static const char *es = " Leaving inconsistent metadata. Unmount and run "
++ "chkdsk.";
++
+ /**
+ * ntfs_truncate - called when the i_size of an ntfs inode is changed
+ * @vi: inode for which the i_size was changed
+ *
+- * We do not support i_size changes yet.
++ * We only support i_size changes for normal files at present, i.e. not
++ * compressed and not encrypted. This is enforced in ntfs_setattr(), see
++ * below.
+ *
+ * The kernel guarantees that @vi is a regular file (S_ISREG() is true) and
+ * that the change is allowed.
+@@ -2306,80 +2312,499 @@ int ntfs_show_options(struct seq_file *s
+ * Returns 0 on success or -errno on error.
+ *
+ * Called with ->i_sem held. In all but one case ->i_alloc_sem is held for
+- * writing. The only case where ->i_alloc_sem is not held is
++ * writing. The only case in the kernel where ->i_alloc_sem is not held is
+ * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called
+- * with the current i_size as the offset which means that it is a noop as far
+- * as ntfs_truncate() is concerned.
++ * with the current i_size as the offset. The analogous place in NTFS is in
++ * fs/ntfs/file.c::ntfs_file_buffered_write() where we call vmtruncate() again
++ * without holding ->i_alloc_sem.
+ */
+ int ntfs_truncate(struct inode *vi)
+ {
+- ntfs_inode *ni = NTFS_I(vi);
++ s64 new_size, old_size, nr_freed, new_alloc_size, old_alloc_size;
++ VCN highest_vcn;
++ unsigned long flags;
++ ntfs_inode *base_ni, *ni = NTFS_I(vi);
+ ntfs_volume *vol = ni->vol;
+ ntfs_attr_search_ctx *ctx;
+ MFT_RECORD *m;
+ ATTR_RECORD *a;
+ const char *te = " Leaving file length out of sync with i_size.";
+- int err;
++ int err, mp_size, size_change, alloc_change;
++ u32 attr_len;
+
+ ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+ BUG_ON(NInoAttr(ni));
++ BUG_ON(S_ISDIR(vi->i_mode));
++ BUG_ON(NInoMstProtected(ni));
+ BUG_ON(ni->nr_extents < 0);
+- m = map_mft_record(ni);
++retry_truncate:
++ /*
++ * Lock the runlist for writing and map the mft record to ensure it is
++ * safe to mess with the attribute runlist and sizes.
++ */
++ down_write(&ni->runlist.lock);
++ if (!NInoAttr(ni))
++ base_ni = ni;
++ else
++ base_ni = ni->ext.base_ntfs_ino;
++ m = map_mft_record(base_ni);
+ if (IS_ERR(m)) {
+ err = PTR_ERR(m);
+ ntfs_error(vi->i_sb, "Failed to map mft record for inode 0x%lx "
+ "(error code %d).%s", vi->i_ino, err, te);
+ ctx = NULL;
+ m = NULL;
+- goto err_out;
++ goto old_bad_out;
+ }
+- ctx = ntfs_attr_get_search_ctx(ni, m);
++ ctx = ntfs_attr_get_search_ctx(base_ni, m);
+ if (unlikely(!ctx)) {
+ ntfs_error(vi->i_sb, "Failed to allocate a search context for "
+ "inode 0x%lx (not enough memory).%s",
+ vi->i_ino, te);
+ err = -ENOMEM;
+- goto err_out;
++ goto old_bad_out;
+ }
+ err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+ CASE_SENSITIVE, 0, NULL, 0, ctx);
+ if (unlikely(err)) {
+- if (err == -ENOENT)
++ if (err == -ENOENT) {
+ ntfs_error(vi->i_sb, "Open attribute is missing from "
+ "mft record. Inode 0x%lx is corrupt. "
+- "Run chkdsk.", vi->i_ino);
+- else
++ "Run chkdsk.%s", vi->i_ino, te);
++ err = -EIO;
++ } else
+ ntfs_error(vi->i_sb, "Failed to lookup attribute in "
+- "inode 0x%lx (error code %d).",
+- vi->i_ino, err);
+- goto err_out;
++ "inode 0x%lx (error code %d).%s",
++ vi->i_ino, err, te);
++ goto old_bad_out;
+ }
++ m = ctx->mrec;
+ a = ctx->attr;
+- /* If the size has not changed there is nothing to do. */
+- if (ntfs_attr_size(a) == i_size_read(vi))
+- goto done;
+- // TODO: Implement the truncate...
+- ntfs_error(vi->i_sb, "Inode size has changed but this is not "
+- "implemented yet. Resetting inode size to old value. "
+- " This is most likely a bug in the ntfs driver!");
+- i_size_write(vi, ntfs_attr_size(a));
+-done:
++ /*
++ * The i_size of the vfs inode is the new size for the attribute value.
++ */
++ new_size = i_size_read(vi);
++ /* The current size of the attribute value is the old size. */
++ old_size = ntfs_attr_size(a);
++ /* Calculate the new allocated size. */
++ if (NInoNonResident(ni))
++ new_alloc_size = (new_size + vol->cluster_size - 1) &
++ ~(s64)vol->cluster_size_mask;
++ else
++ new_alloc_size = (new_size + 7) & ~7;
++ /* The current allocated size is the old allocated size. */
++ read_lock_irqsave(&ni->size_lock, flags);
++ old_alloc_size = ni->allocated_size;
++ read_unlock_irqrestore(&ni->size_lock, flags);
++ /*
++ * The change in the file size. This will be 0 if no change, >0 if the
++ * size is growing, and <0 if the size is shrinking.
++ */
++ size_change = -1;
++ if (new_size - old_size >= 0) {
++ size_change = 1;
++ if (new_size == old_size)
++ size_change = 0;
++ }
++ /* As above for the allocated size. */
++ alloc_change = -1;
++ if (new_alloc_size - old_alloc_size >= 0) {
++ alloc_change = 1;
++ if (new_alloc_size == old_alloc_size)
++ alloc_change = 0;
++ }
++ /*
++ * If neither the size nor the allocation are being changed there is
++ * nothing to do.
++ */
++ if (!size_change && !alloc_change)
++ goto unm_done;
++ /* If the size is changing, check if new size is allowed in $AttrDef. */
++ if (size_change) {
++ err = ntfs_attr_size_bounds_check(vol, ni->type, new_size);
++ if (unlikely(err)) {
++ if (err == -ERANGE) {
++ ntfs_error(vol->sb, "Truncate would cause the "
++ "inode 0x%lx to %simum size "
++ "for its attribute type "
++ "(0x%x). Aborting truncate.",
++ vi->i_ino,
++ new_size > old_size ? "exceed "
++ "the max" : "go under the min",
++ le32_to_cpu(ni->type));
++ err = -EFBIG;
++ } else {
++ ntfs_error(vol->sb, "Inode 0x%lx has unknown "
++ "attribute type 0x%x. "
++ "Aborting truncate.",
++ vi->i_ino,
++ le32_to_cpu(ni->type));
++ err = -EIO;
++ }
++ /* Reset the vfs inode size to the old size. */
++ i_size_write(vi, old_size);
++ goto err_out;
++ }
++ }
++ if (NInoCompressed(ni) || NInoEncrypted(ni)) {
++ ntfs_warning(vi->i_sb, "Changes in inode size are not "
++ "supported yet for %s files, ignoring.",
++ NInoCompressed(ni) ? "compressed" :
++ "encrypted");
++ err = -EOPNOTSUPP;
++ goto bad_out;
++ }
++ if (a->non_resident)
++ goto do_non_resident_truncate;
++ BUG_ON(NInoNonResident(ni));
++ /* Resize the attribute record to best fit the new attribute size. */
++ if (new_size < vol->mft_record_size &&
++ !ntfs_resident_attr_value_resize(m, a, new_size)) {
++ unsigned long flags;
++
++ /* The resize succeeded! */
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ write_lock_irqsave(&ni->size_lock, flags);
++ /* Update the sizes in the ntfs inode and all is done. */
++ ni->allocated_size = le32_to_cpu(a->length) -
++ le16_to_cpu(a->data.resident.value_offset);
++ /*
++ * Note ntfs_resident_attr_value_resize() has already done any
++ * necessary data clearing in the attribute record. When the
++ * file is being shrunk vmtruncate() will already have cleared
++ * the top part of the last partial page, i.e. since this is
++ * the resident case this is the page with index 0. However,
++ * when the file is being expanded, the page cache page data
++ * between the old data_size, i.e. old_size, and the new_size
++ * has not been zeroed. Fortunately, we do not need to zero it
++ * either since on one hand it will either already be zero due
++ * to both readpage and writepage clearing partial page data
++ * beyond i_size in which case there is nothing to do or in the
++ * case of the file being mmap()ped at the same time, POSIX
++ * specifies that the behaviour is unspecified thus we do not
++ * have to do anything. This means that in our implementation
++ * in the rare case that the file is mmap()ped and a write
++ * occured into the mmap()ped region just beyond the file size
++ * and writepage has not yet been called to write out the page
++ * (which would clear the area beyond the file size) and we now
++ * extend the file size to incorporate this dirty region
++ * outside the file size, a write of the page would result in
++ * this data being written to disk instead of being cleared.
++ * Given both POSIX and the Linux mmap(2) man page specify that
++ * this corner case is undefined, we choose to leave it like
++ * that as this is much simpler for us as we cannot lock the
++ * relevant page now since we are holding too many ntfs locks
++ * which would result in a lock reversal deadlock.
++ */
++ ni->initialized_size = new_size;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ goto unm_done;
++ }
++ /* If the above resize failed, this must be an attribute extension. */
++ BUG_ON(size_change < 0);
++ /*
++ * We have to drop all the locks so we can call
++ * ntfs_attr_make_non_resident(). This could be optimised by try-
++ * locking the first page cache page and only if that fails dropping
++ * the locks, locking the page, and redoing all the locking and
++ * lookups. While this would be a huge optimisation, it is not worth
++ * it as this is definitely a slow code path as it only ever can happen
++ * once for any given file.
++ */
+ ntfs_attr_put_search_ctx(ctx);
+- unmap_mft_record(ni);
+- NInoClearTruncateFailed(ni);
+- ntfs_debug("Done.");
+- return 0;
+-err_out:
+- if (err != -ENOMEM) {
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++ /*
++ * Not enough space in the mft record, try to make the attribute
++ * non-resident and if successful restart the truncation process.
++ */
++ err = ntfs_attr_make_non_resident(ni, old_size);
++ if (likely(!err))
++ goto retry_truncate;
++ /*
++ * Could not make non-resident. If this is due to this not being
++ * permitted for this attribute type or there not being enough space,
++ * try to make other attributes non-resident. Otherwise fail.
++ */
++ if (unlikely(err != -EPERM && err != -ENOSPC)) {
++ ntfs_error(vol->sb, "Cannot truncate inode 0x%lx, attribute "
++ "type 0x%x, because the conversion from "
++ "resident to non-resident attribute failed "
++ "with error code %i.", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), err);
++ if (err != -ENOMEM)
++ err = -EIO;
++ goto conv_err_out;
++ }
++ /* TODO: Not implemented from here, abort. */
++ if (err == -ENOSPC)
++ ntfs_error(vol->sb, "Not enough space in the mft record/on "
++ "disk for the non-resident attribute value. "
++ "This case is not implemented yet.");
++ else /* if (err == -EPERM) */
++ ntfs_error(vol->sb, "This attribute type may not be "
++ "non-resident. This case is not implemented "
++ "yet.");
++ err = -EOPNOTSUPP;
++ goto conv_err_out;
++#if 0
++ // TODO: Attempt to make other attributes non-resident.
++ if (!err)
++ goto do_resident_extend;
++ /*
++ * Both the attribute list attribute and the standard information
++ * attribute must remain in the base inode. Thus, if this is one of
++ * these attributes, we have to try to move other attributes out into
++ * extent mft records instead.
++ */
++ if (ni->type == AT_ATTRIBUTE_LIST ||
++ ni->type == AT_STANDARD_INFORMATION) {
++ // TODO: Attempt to move other attributes into extent mft
++ // records.
++ err = -EOPNOTSUPP;
++ if (!err)
++ goto do_resident_extend;
++ goto err_out;
++ }
++ // TODO: Attempt to move this attribute to an extent mft record, but
++ // only if it is not already the only attribute in an mft record in
++ // which case there would be nothing to gain.
++ err = -EOPNOTSUPP;
++ if (!err)
++ goto do_resident_extend;
++ /* There is nothing we can do to make enough space. )-: */
++ goto err_out;
++#endif
++do_non_resident_truncate:
++ BUG_ON(!NInoNonResident(ni));
++ if (alloc_change < 0) {
++ highest_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn);
++ if (highest_vcn > 0 &&
++ old_alloc_size >> vol->cluster_size_bits >
++ highest_vcn + 1) {
++ /*
++ * This attribute has multiple extents. Not yet
++ * supported.
++ */
++ ntfs_error(vol->sb, "Cannot truncate inode 0x%lx, "
++ "attribute type 0x%x, because the "
++ "attribute is highly fragmented (it "
++ "consists of multiple extents) and "
++ "this case is not implemented yet.",
++ vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type));
++ err = -EOPNOTSUPP;
++ goto bad_out;
++ }
++ }
++ /*
++ * If the size is shrinking, need to reduce the initialized_size and
++ * the data_size before reducing the allocation.
++ */
++ if (size_change < 0) {
++ /*
++ * Make the valid size smaller (i_size is already up-to-date).
++ */
++ write_lock_irqsave(&ni->size_lock, flags);
++ if (new_size < ni->initialized_size) {
++ ni->initialized_size = new_size;
++ a->data.non_resident.initialized_size =
++ cpu_to_sle64(new_size);
++ }
++ a->data.non_resident.data_size = cpu_to_sle64(new_size);
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++ /* If the allocated size is not changing, we are done. */
++ if (!alloc_change)
++ goto unm_done;
++ /*
++ * If the size is shrinking it makes no sense for the
++ * allocation to be growing.
++ */
++ BUG_ON(alloc_change > 0);
++ } else /* if (size_change >= 0) */ {
++ /*
++ * The file size is growing or staying the same but the
++ * allocation can be shrinking, growing or staying the same.
++ */
++ if (alloc_change > 0) {
++ /*
++ * We need to extend the allocation and possibly update
++ * the data size. If we are updating the data size,
++ * since we are not touching the initialized_size we do
++ * not need to worry about the actual data on disk.
++ * And as far as the page cache is concerned, there
++ * will be no pages beyond the old data size and any
++ * partial region in the last page between the old and
++ * new data size (or the end of the page if the new
++ * data size is outside the page) does not need to be
++ * modified as explained above for the resident
++ * attribute truncate case. To do this, we simply drop
++ * the locks we hold and leave all the work to our
++ * friendly helper ntfs_attr_extend_allocation().
++ */
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++ err = ntfs_attr_extend_allocation(ni, new_size,
++ size_change > 0 ? new_size : -1, -1);
++ /*
++ * ntfs_attr_extend_allocation() will have done error
++ * output already.
++ */
++ goto done;
++ }
++ if (!alloc_change)
++ goto alloc_done;
++ }
++ /* alloc_change < 0 */
++ /* Free the clusters. */
++ nr_freed = ntfs_cluster_free(ni, new_alloc_size >>
++ vol->cluster_size_bits, -1, ctx);
++ m = ctx->mrec;
++ a = ctx->attr;
++ if (unlikely(nr_freed < 0)) {
++ ntfs_error(vol->sb, "Failed to release cluster(s) (error code "
++ "%lli). Unmount and run chkdsk to recover "
++ "the lost cluster(s).", (long long)nr_freed);
+ NVolSetErrors(vol);
++ nr_freed = 0;
++ }
++ /* Truncate the runlist. */
++ err = ntfs_rl_truncate_nolock(vol, &ni->runlist,
++ new_alloc_size >> vol->cluster_size_bits);
++ /*
++ * If the runlist truncation failed and/or the search context is no
++ * longer valid, we cannot resize the attribute record or build the
++ * mapping pairs array thus we mark the inode bad so that no access to
++ * the freed clusters can happen.
++ */
++ if (unlikely(err || IS_ERR(m))) {
++ ntfs_error(vol->sb, "Failed to %s (error code %li).%s",
++ IS_ERR(m) ?
++ "restore attribute search context" :
++ "truncate attribute runlist",
++ IS_ERR(m) ? PTR_ERR(m) : err, es);
++ err = -EIO;
++ goto bad_out;
++ }
++ /* Get the size for the shrunk mapping pairs array for the runlist. */
++ mp_size = ntfs_get_size_for_mapping_pairs(vol, ni->runlist.rl, 0, -1);
++ if (unlikely(mp_size <= 0)) {
++ ntfs_error(vol->sb, "Cannot shrink allocation of inode 0x%lx, "
++ "attribute type 0x%x, because determining the "
++ "size for the mapping pairs failed with error "
++ "code %i.%s", vi->i_ino,
++ (unsigned)le32_to_cpu(ni->type), mp_size, es);
++ err = -EIO;
++ goto bad_out;
++ }
++ /*
++ * Shrink the attribute record for the new mapping pairs array. Note,
++ * this cannot fail since we are making the attribute smaller thus by
++ * definition there is enough space to do so.
++ */
++ attr_len = le32_to_cpu(a->length);
++ err = ntfs_attr_record_resize(m, a, mp_size +
++ le16_to_cpu(a->data.non_resident.mapping_pairs_offset));
++ BUG_ON(err);
++ /*
++ * Generate the mapping pairs array directly into the attribute record.
++ */
++ err = ntfs_mapping_pairs_build(vol, (u8*)a +
++ le16_to_cpu(a->data.non_resident.mapping_pairs_offset),
++ mp_size, ni->runlist.rl, 0, -1, NULL);
++ if (unlikely(err)) {
++ ntfs_error(vol->sb, "Cannot shrink allocation of inode 0x%lx, "
++ "attribute type 0x%x, because building the "
++ "mapping pairs failed with error code %i.%s",
++ vi->i_ino, (unsigned)le32_to_cpu(ni->type),
++ err, es);
++ err = -EIO;
++ goto bad_out;
++ }
++ /* Update the allocated/compressed size as well as the highest vcn. */
++ a->data.non_resident.highest_vcn = cpu_to_sle64((new_alloc_size >>
++ vol->cluster_size_bits) - 1);
++ write_lock_irqsave(&ni->size_lock, flags);
++ ni->allocated_size = new_alloc_size;
++ a->data.non_resident.allocated_size = cpu_to_sle64(new_alloc_size);
++ if (NInoSparse(ni) || NInoCompressed(ni)) {
++ if (nr_freed) {
++ ni->itype.compressed.size -= nr_freed <<
++ vol->cluster_size_bits;
++ BUG_ON(ni->itype.compressed.size < 0);
++ a->data.non_resident.compressed_size = cpu_to_sle64(
++ ni->itype.compressed.size);
++ vi->i_blocks = ni->itype.compressed.size >> 9;
++ }
++ } else
++ vi->i_blocks = new_alloc_size >> 9;
++ write_unlock_irqrestore(&ni->size_lock, flags);
++ /*
++ * We have shrunk the allocation. If this is a shrinking truncate we
++ * have already dealt with the initialized_size and the data_size above
++ * and we are done. If the truncate is only changing the allocation
++ * and not the data_size, we are also done. If this is an extending
++ * truncate, need to extend the data_size now which is ensured by the
++ * fact that @size_change is positive.
++ */
++alloc_done:
++ /*
++ * If the size is growing, need to update it now. If it is shrinking,
++ * we have already updated it above (before the allocation change).
++ */
++ if (size_change > 0)
++ a->data.non_resident.data_size = cpu_to_sle64(new_size);
++ /* Ensure the modified mft record is written out. */
++ flush_dcache_mft_record_page(ctx->ntfs_ino);
++ mark_mft_record_dirty(ctx->ntfs_ino);
++unm_done:
++ ntfs_attr_put_search_ctx(ctx);
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++done:
++ /* Update the mtime and ctime on the base inode. */
++ inode_update_time(VFS_I(base_ni), 1);
++ if (likely(!err)) {
++ NInoClearTruncateFailed(ni);
++ ntfs_debug("Done.");
++ }
++ return err;
++old_bad_out:
++ old_size = -1;
++bad_out:
++ if (err != -ENOMEM && err != -EOPNOTSUPP) {
+ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
+ }
++ if (err != -EOPNOTSUPP)
++ NInoSetTruncateFailed(ni);
++ else if (old_size >= 0)
++ i_size_write(vi, old_size);
++err_out:
+ if (ctx)
+ ntfs_attr_put_search_ctx(ctx);
+ if (m)
+- unmap_mft_record(ni);
+- NInoSetTruncateFailed(ni);
++ unmap_mft_record(base_ni);
++ up_write(&ni->runlist.lock);
++out:
++ ntfs_debug("Failed. Returning error code %i.", err);
+ return err;
++conv_err_out:
++ if (err != -ENOMEM && err != -EOPNOTSUPP) {
++ make_bad_inode(vi);
++ make_bad_inode(VFS_I(base_ni));
++ NVolSetErrors(vol);
++ }
++ if (err != -EOPNOTSUPP)
++ NInoSetTruncateFailed(ni);
++ else
++ i_size_write(vi, old_size);
++ goto out;
+ }
+
+ /**
+@@ -2420,8 +2845,7 @@ int ntfs_setattr(struct dentry *dentry,
+
+ err = inode_change_ok(vi, attr);
+ if (err)
+- return err;
+-
++ goto out;
+ /* We do not support NTFS ACLs yet. */
+ if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) {
+ ntfs_warning(vi->i_sb, "Changes in user/group/mode are not "
+@@ -2429,14 +2853,22 @@ int ntfs_setattr(struct dentry *dentry,
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+-
+ if (ia_valid & ATTR_SIZE) {
+ if (attr->ia_size != i_size_read(vi)) {
+- ntfs_warning(vi->i_sb, "Changes in inode size are not "
+- "supported yet, ignoring.");
+- err = -EOPNOTSUPP;
+- // TODO: Implement...
+- // err = vmtruncate(vi, attr->ia_size);
++ ntfs_inode *ni = NTFS_I(vi);
++ /*
++ * FIXME: For now we do not support resizing of
++ * compressed or encrypted files yet.
++ */
++ if (NInoCompressed(ni) || NInoEncrypted(ni)) {
++ ntfs_warning(vi->i_sb, "Changes in inode size "
++ "are not supported yet for "
++ "%s files, ignoring.",
++ NInoCompressed(ni) ?
++ "compressed" : "encrypted");
++ err = -EOPNOTSUPP;
++ } else
++ err = vmtruncate(vi, attr->ia_size);
+ if (err || ia_valid == ATTR_SIZE)
+ goto out;
+ } else {
+diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h
+--- a/fs/ntfs/layout.h
++++ b/fs/ntfs/layout.h
+@@ -1021,10 +1021,17 @@ enum {
+ FILE_NAME_POSIX = 0x00,
+ /* This is the largest namespace. It is case sensitive and allows all
+ Unicode characters except for: '\0' and '/'. Beware that in
+- WinNT/2k files which eg have the same name except for their case
+- will not be distinguished by the standard utilities and thus a "del
+- filename" will delete both "filename" and "fileName" without
+- warning. */
++ WinNT/2k/2003 by default files which eg have the same name except
++ for their case will not be distinguished by the standard utilities
++ and thus a "del filename" will delete both "filename" and "fileName"
++ without warning. However if for example Services For Unix (SFU) are
++ installed and the case sensitive option was enabled at installation
++ time, then you can create/access/delete such files.
++ Note that even SFU places restrictions on the filenames beyond the
++ '\0' and '/' and in particular the following set of characters is
++ not allowed: '"', '/', '<', '>', '\'. All other characters,
++ including the ones no allowed in WIN32 namespace are allowed.
++ Tested with SFU 3.5 (this is now free) running on Windows XP. */
+ FILE_NAME_WIN32 = 0x01,
+ /* The standard WinNT/2k NTFS long filenames. Case insensitive. All
+ Unicode chars except: '\0', '"', '*', '/', ':', '<', '>', '?', '\',
+@@ -2367,7 +2374,9 @@ typedef struct {
+ * Extended attribute flags (8-bit).
+ */
+ enum {
+- NEED_EA = 0x80
++ NEED_EA = 0x80 /* If set the file to which the EA belongs
++ cannot be interpreted without understanding
++ the associates extended attributes. */
+ } __attribute__ ((__packed__));
+
+ typedef u8 EA_FLAGS;
+@@ -2375,20 +2384,20 @@ typedef u8 EA_FLAGS;
+ /*
+ * Attribute: Extended attribute (EA) (0xe0).
+ *
+- * NOTE: Always non-resident. (Is this true?)
++ * NOTE: Can be resident or non-resident.
+ *
+ * Like the attribute list and the index buffer list, the EA attribute value is
+ * a sequence of EA_ATTR variable length records.
+- *
+- * FIXME: It appears weird that the EA name is not unicode. Is it true?
+ */
+ typedef struct {
+ le32 next_entry_offset; /* Offset to the next EA_ATTR. */
+ EA_FLAGS flags; /* Flags describing the EA. */
+- u8 ea_name_length; /* Length of the name of the EA in bytes. */
++ u8 ea_name_length; /* Length of the name of the EA in bytes
++ excluding the '\0' byte terminator. */
+ le16 ea_value_length; /* Byte size of the EA's value. */
+- u8 ea_name[0]; /* Name of the EA. */
+- u8 ea_value[0]; /* The value of the EA. Immediately follows
++ u8 ea_name[0]; /* Name of the EA. Note this is ASCII, not
++ Unicode and it is zero terminated. */
++ u8 ea_value[0]; /* The value of the EA. Immediately follows
+ the name. */
+ } __attribute__ ((__packed__)) EA_ATTR;
+
+diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
+--- a/fs/ntfs/lcnalloc.c
++++ b/fs/ntfs/lcnalloc.c
+@@ -76,6 +76,7 @@ int ntfs_cluster_free_from_rl_nolock(ntf
+ * @count: number of clusters to allocate
+ * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none)
+ * @zone: zone from which to allocate the clusters
++ * @is_extension: if TRUE, this is an attribute extension
+ *
+ * Allocate @count clusters preferably starting at cluster @start_lcn or at the
+ * current allocator position if @start_lcn is -1, on the mounted ntfs volume
+@@ -86,6 +87,13 @@ int ntfs_cluster_free_from_rl_nolock(ntf
+ * @start_vcn specifies the vcn of the first allocated cluster. This makes
+ * merging the resulting runlist with the old runlist easier.
+ *
++ * If @is_extension is TRUE, the caller is allocating clusters to extend an
++ * attribute and if it is FALSE, the caller is allocating clusters to fill a
++ * hole in an attribute. Practically the difference is that if @is_extension
++ * is TRUE the returned runlist will be terminated with LCN_ENOENT and if
++ * @is_extension is FALSE the runlist will be terminated with
++ * LCN_RL_NOT_MAPPED.
++ *
+ * You need to check the return value with IS_ERR(). If this is false, the
+ * function was successful and the return value is a runlist describing the
+ * allocated cluster(s). If IS_ERR() is true, the function failed and
+@@ -137,7 +145,8 @@ int ntfs_cluster_free_from_rl_nolock(ntf
+ */
+ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
+ const s64 count, const LCN start_lcn,
+- const NTFS_CLUSTER_ALLOCATION_ZONES zone)
++ const NTFS_CLUSTER_ALLOCATION_ZONES zone,
++ const BOOL is_extension)
+ {
+ LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
+ LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
+@@ -310,7 +319,7 @@ runlist_element *ntfs_cluster_alloc(ntfs
+ continue;
+ }
+ bit = 1 << (lcn & 7);
+- ntfs_debug("bit %i.", bit);
++ ntfs_debug("bit 0x%x.", bit);
+ /* If the bit is already set, go onto the next one. */
+ if (*byte & bit) {
+ lcn++;
+@@ -729,7 +738,7 @@ out:
+ /* Add runlist terminator element. */
+ if (likely(rl)) {
+ rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
+- rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
++ rl[rlpos].lcn = is_extension ? LCN_ENOENT : LCN_RL_NOT_MAPPED;
+ rl[rlpos].length = 0;
+ }
+ if (likely(page && !IS_ERR(page))) {
+@@ -782,6 +791,7 @@ out:
+ * @ni: ntfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
+ * @count: number of clusters to free or -1 for all clusters
++ * @ctx: active attribute search context if present or NULL if not
+ * @is_rollback: true if this is a rollback operation
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+@@ -791,15 +801,39 @@ out:
+ * deallocated. Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
++ * If @ctx is specified, it is an active search context of @ni and its base mft
++ * record. This is needed when __ntfs_cluster_free() encounters unmapped
++ * runlist fragments and allows their mapping. If you do not have the mft
++ * record mapped, you can specify @ctx as NULL and __ntfs_cluster_free() will
++ * perform the necessary mapping and unmapping.
++ *
++ * Note, __ntfs_cluster_free() saves the state of @ctx on entry and restores it
++ * before returning. Thus, @ctx will be left pointing to the same attribute on
++ * return as on entry. However, the actual pointers in @ctx may point to
++ * different memory locations on return, so you must remember to reset any
++ * cached pointers from the @ctx, i.e. after the call to __ntfs_cluster_free(),
++ * you will probably want to do:
++ * m = ctx->mrec;
++ * a = ctx->attr;
++ * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
++ * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
++ *
+ * @is_rollback should always be FALSE, it is for internal use to rollback
+ * errors. You probably want to use ntfs_cluster_free() instead.
+ *
+- * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+- * has to deal with it later.
++ * Note, __ntfs_cluster_free() does not modify the runlist, so you have to
++ * remove from the runlist or mark sparse the freed runs later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
++ * WARNING: If @ctx is supplied, regardless of whether success or failure is
++ * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
++ * is no longer valid, i.e. you need to either call
++ * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
++ * In that case PTR_ERR(@ctx->mrec) will give you the error code for
++ * why the mapping of the old inode failed.
++ *
+ * Locking: - The runlist described by @ni must be locked for writing on entry
+ * and is locked on return. Note the runlist may be modified when
+ * needed runlist fragments need to be mapped.
+@@ -807,9 +841,13 @@ out:
+ * on return.
+ * - This function takes the volume lcn bitmap lock for writing and
+ * modifies the bitmap contents.
++ * - If @ctx is NULL, the base mft record of @ni must not be mapped on
++ * entry and it will be left unmapped on return.
++ * - If @ctx is not NULL, the base mft record must be mapped on entry
++ * and it will be left mapped on return.
+ */
+ s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
+- const BOOL is_rollback)
++ ntfs_attr_search_ctx *ctx, const BOOL is_rollback)
+ {
+ s64 delta, to_free, total_freed, real_freed;
+ ntfs_volume *vol;
+@@ -839,7 +877,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni,
+
+ total_freed = real_freed = 0;
+
+- rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, TRUE);
++ rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, ctx);
+ if (IS_ERR(rl)) {
+ if (!is_rollback)
+ ntfs_error(vol->sb, "Failed to find first runlist "
+@@ -893,7 +931,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni,
+
+ /* Attempt to map runlist. */
+ vcn = rl->vcn;
+- rl = ntfs_attr_find_vcn_nolock(ni, vcn, TRUE);
++ rl = ntfs_attr_find_vcn_nolock(ni, vcn, ctx);
+ if (IS_ERR(rl)) {
+ err = PTR_ERR(rl);
+ if (!is_rollback)
+@@ -961,7 +999,7 @@ err_out:
+ * If rollback fails, set the volume errors flag, emit an error
+ * message, and return the error code.
+ */
+- delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE);
++ delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, TRUE);
+ if (delta < 0) {
+ ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
+ "inconsistent metadata! Unmount and run "
+diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h
+--- a/fs/ntfs/lcnalloc.h
++++ b/fs/ntfs/lcnalloc.h
+@@ -27,6 +27,7 @@
+
+ #include <linux/fs.h>
+
++#include "attrib.h"
+ #include "types.h"
+ #include "inode.h"
+ #include "runlist.h"
+@@ -41,16 +42,18 @@ typedef enum {
+
+ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
+ const VCN start_vcn, const s64 count, const LCN start_lcn,
+- const NTFS_CLUSTER_ALLOCATION_ZONES zone);
++ const NTFS_CLUSTER_ALLOCATION_ZONES zone,
++ const BOOL is_extension);
+
+ extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
+- s64 count, const BOOL is_rollback);
++ s64 count, ntfs_attr_search_ctx *ctx, const BOOL is_rollback);
+
+ /**
+ * ntfs_cluster_free - free clusters on an ntfs volume
+ * @ni: ntfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
+ * @count: number of clusters to free or -1 for all clusters
++ * @ctx: active attribute search context if present or NULL if not
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the ntfs inode @ni.
+@@ -59,12 +62,36 @@ extern s64 __ntfs_cluster_free(ntfs_inod
+ * deallocated. Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
+- * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+- * has to deal with it later.
++ * If @ctx is specified, it is an active search context of @ni and its base mft
++ * record. This is needed when ntfs_cluster_free() encounters unmapped runlist
++ * fragments and allows their mapping. If you do not have the mft record
++ * mapped, you can specify @ctx as NULL and ntfs_cluster_free() will perform
++ * the necessary mapping and unmapping.
++ *
++ * Note, ntfs_cluster_free() saves the state of @ctx on entry and restores it
++ * before returning. Thus, @ctx will be left pointing to the same attribute on
++ * return as on entry. However, the actual pointers in @ctx may point to
++ * different memory locations on return, so you must remember to reset any
++ * cached pointers from the @ctx, i.e. after the call to ntfs_cluster_free(),
++ * you will probably want to do:
++ * m = ctx->mrec;
++ * a = ctx->attr;
++ * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
++ * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
++ *
++ * Note, ntfs_cluster_free() does not modify the runlist, so you have to remove
++ * from the runlist or mark sparse the freed runs later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
++ * WARNING: If @ctx is supplied, regardless of whether success or failure is
++ * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
++ * is no longer valid, i.e. you need to either call
++ * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
++ * In that case PTR_ERR(@ctx->mrec) will give you the error code for
++ * why the mapping of the old inode failed.
++ *
+ * Locking: - The runlist described by @ni must be locked for writing on entry
+ * and is locked on return. Note the runlist may be modified when
+ * needed runlist fragments need to be mapped.
+@@ -72,11 +99,15 @@ extern s64 __ntfs_cluster_free(ntfs_inod
+ * on return.
+ * - This function takes the volume lcn bitmap lock for writing and
+ * modifies the bitmap contents.
++ * - If @ctx is NULL, the base mft record of @ni must not be mapped on
++ * entry and it will be left unmapped on return.
++ * - If @ctx is not NULL, the base mft record must be mapped on entry
++ * and it will be left mapped on return.
+ */
+ static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
+- s64 count)
++ s64 count, ntfs_attr_search_ctx *ctx)
+ {
+- return __ntfs_cluster_free(ni, start_vcn, count, FALSE);
++ return __ntfs_cluster_free(ni, start_vcn, count, ctx, FALSE);
+ }
+
+ extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
+diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h
+--- a/fs/ntfs/malloc.h
++++ b/fs/ntfs/malloc.h
+@@ -39,8 +39,7 @@
+ * If there was insufficient memory to complete the request, return NULL.
+ * Depending on @gfp_mask the allocation may be guaranteed to succeed.
+ */
+-static inline void *__ntfs_malloc(unsigned long size,
+- gfp_t gfp_mask)
++static inline void *__ntfs_malloc(unsigned long size, gfp_t gfp_mask)
+ {
+ if (likely(size <= PAGE_SIZE)) {
+ BUG_ON(!size);
+diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
+--- a/fs/ntfs/mft.c
++++ b/fs/ntfs/mft.c
+@@ -49,7 +49,8 @@ static inline MFT_RECORD *map_mft_record
+ ntfs_volume *vol = ni->vol;
+ struct inode *mft_vi = vol->mft_ino;
+ struct page *page;
+- unsigned long index, ofs, end_index;
++ unsigned long index, end_index;
++ unsigned ofs;
+
+ BUG_ON(ni->page);
+ /*
+@@ -1308,7 +1309,7 @@ static int ntfs_mft_bitmap_extend_alloca
+ ll = mftbmp_ni->allocated_size;
+ read_unlock_irqrestore(&mftbmp_ni->size_lock, flags);
+ rl = ntfs_attr_find_vcn_nolock(mftbmp_ni,
+- (ll - 1) >> vol->cluster_size_bits, TRUE);
++ (ll - 1) >> vol->cluster_size_bits, NULL);
+ if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
+ up_write(&mftbmp_ni->runlist.lock);
+ ntfs_error(vol->sb, "Failed to determine last allocated "
+@@ -1354,7 +1355,8 @@ static int ntfs_mft_bitmap_extend_alloca
+ up_write(&vol->lcnbmp_lock);
+ ntfs_unmap_page(page);
+ /* Allocate a cluster from the DATA_ZONE. */
+- rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);
++ rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE,
++ TRUE);
+ if (IS_ERR(rl2)) {
+ up_write(&mftbmp_ni->runlist.lock);
+ ntfs_error(vol->sb, "Failed to allocate a cluster for "
+@@ -1738,7 +1740,7 @@ static int ntfs_mft_data_extend_allocati
+ ll = mft_ni->allocated_size;
+ read_unlock_irqrestore(&mft_ni->size_lock, flags);
+ rl = ntfs_attr_find_vcn_nolock(mft_ni,
+- (ll - 1) >> vol->cluster_size_bits, TRUE);
++ (ll - 1) >> vol->cluster_size_bits, NULL);
+ if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) {
+ up_write(&mft_ni->runlist.lock);
+ ntfs_error(vol->sb, "Failed to determine last allocated "
+@@ -1779,7 +1781,8 @@ static int ntfs_mft_data_extend_allocati
+ nr > min_nr ? "default" : "minimal", (long long)nr);
+ old_last_vcn = rl[1].vcn;
+ do {
+- rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE);
++ rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE,
++ TRUE);
+ if (likely(!IS_ERR(rl2)))
+ break;
+ if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) {
+@@ -1951,20 +1954,21 @@ restore_undo_alloc:
+ NVolSetErrors(vol);
+ return ret;
+ }
+- a = ctx->attr;
+- a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1);
++ ctx->attr->data.non_resident.highest_vcn =
++ cpu_to_sle64(old_last_vcn - 1);
+ undo_alloc:
+- if (ntfs_cluster_free(mft_ni, old_last_vcn, -1) < 0) {
++ if (ntfs_cluster_free(mft_ni, old_last_vcn, -1, ctx) < 0) {
+ ntfs_error(vol->sb, "Failed to free clusters from mft data "
+ "attribute.%s", es);
+ NVolSetErrors(vol);
+ }
++ a = ctx->attr;
+ if (ntfs_rl_truncate_nolock(vol, &mft_ni->runlist, old_last_vcn)) {
+ ntfs_error(vol->sb, "Failed to truncate mft data attribute "
+ "runlist.%s", es);
+ NVolSetErrors(vol);
+ }
+- if (mp_rebuilt) {
++ if (mp_rebuilt && !IS_ERR(ctx->mrec)) {
+ if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
+ a->data.non_resident.mapping_pairs_offset),
+ old_alen - le16_to_cpu(
+@@ -1981,6 +1985,10 @@ undo_alloc:
+ }
+ flush_dcache_mft_record_page(ctx->ntfs_ino);
+ mark_mft_record_dirty(ctx->ntfs_ino);
++ } else if (IS_ERR(ctx->mrec)) {
++ ntfs_error(vol->sb, "Failed to restore attribute search "
++ "context.%s", es);
++ NVolSetErrors(vol);
+ }
+ if (ctx)
+ ntfs_attr_put_search_ctx(ctx);
+diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
+--- a/fs/ntfs/super.c
++++ b/fs/ntfs/super.c
+@@ -1447,7 +1447,7 @@ not_enabled:
+ if (unlikely(i_size_read(tmp_ino) < sizeof(USN_HEADER))) {
+ ntfs_error(vol->sb, "Found corrupt $UsnJrnl/$DATA/$Max "
+ "attribute (size is 0x%llx but should be at "
+- "least 0x%x bytes).", i_size_read(tmp_ino),
++ "least 0x%zx bytes).", i_size_read(tmp_ino),
+ sizeof(USN_HEADER));
+ return FALSE;
+ }
+diff --git a/fs/open.c b/fs/open.c
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -739,7 +739,8 @@ asmlinkage long sys_fchown(unsigned int
+ }
+
+ 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 @@ static struct file *__dentry_open(struct
+ 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 @@ struct file *filp_open(const char * file
+ {
+ 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 @@ struct file *dentry_open(struct dentry *
+ 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
+--- a/fs/partitions/check.c
++++ b/fs/partitions/check.c
+@@ -192,6 +192,7 @@ check_partition(struct gendisk *hd, stru
+ 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 @@ part_attr_show(struct kobject * kobj, st
+ 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 @@ static ssize_t part_stat_read(struct hd_
+ 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 part_attribute part_attr_s
+ };
+
+ 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 @@ void del_gendisk(struct gendisk *disk)
+ 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
+--- a/fs/proc/array.c
++++ b/fs/proc/array.c
+@@ -438,7 +438,7 @@ static int do_task_stat(struct task_stru
+ 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
+--- a/fs/proc/generic.c
++++ b/fs/proc/generic.c
+@@ -533,7 +533,7 @@ static void proc_kill_inodes(struct proc
+ */
+ 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
+--- a/fs/proc/inode.c
++++ b/fs/proc/inode.c
+@@ -156,10 +156,13 @@ struct inode *proc_get_inode(struct supe
+
+ 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 @@ struct inode *proc_get_inode(struct supe
+ 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/proc_misc.c b/fs/proc/proc_misc.c
+--- a/fs/proc/proc_misc.c
++++ b/fs/proc/proc_misc.c
+@@ -629,12 +629,4 @@ void __init proc_misc_init(void)
+ if (entry)
+ entry->proc_fops = &proc_sysrq_trigger_operations;
+ #endif
+-#ifdef CONFIG_PPC32
+- {
+- extern struct file_operations ppc_htab_operations;
+- entry = create_proc_entry("ppc_htab", S_IRUGO|S_IWUSR, NULL);
+- if (entry)
+- entry->proc_fops = &ppc_htab_operations;
+- }
+-#endif
+ }
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+--- 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 @@ unsigned long task_vsize(struct mm_struc
+ 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 @@ static void smaps_pte_range(struct vm_ar
+ 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 @@ static void smaps_pte_range(struct vm_ar
+ 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 inline void smaps_pgd_range(struc
+ 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 @@ static struct numa_maps *get_numa_maps(c
+ 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 @@ static struct numa_maps *get_numa_maps(c
+ md->anon++;
+ md->node[page_to_nid(page)]++;
+ }
++ cond_resched();
+ }
+- spin_unlock(&mm->page_table_lock);
+ return md;
+ }
+
+@@ -469,7 +480,7 @@ static int show_numa_map(struct seq_file
+ 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
+--- a/fs/reiserfs/fix_node.c
++++ b/fs/reiserfs/fix_node.c
+@@ -2022,7 +2022,7 @@ static int get_neighbors(struct tree_bal
+ }
+
+ #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
+--- a/fs/reiserfs/inode.c
++++ b/fs/reiserfs/inode.c
+@@ -2842,7 +2842,7 @@ static int reiserfs_set_page_dirty(struc
+ * 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
+--- a/fs/reiserfs/super.c
++++ b/fs/reiserfs/super.c
+@@ -1024,12 +1024,8 @@ static int reiserfs_parse_options(struct
+ 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 @@ static int reiserfs_remount(struct super
+ 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 @@ static int reiserfs_fill_super(struct su
+ 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
+--- a/fs/reiserfs/xattr.c
++++ b/fs/reiserfs/xattr.c
+@@ -453,7 +453,7 @@ static struct page *reiserfs_get_page(st
+ 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
+--- a/fs/reiserfs/xattr_acl.c
++++ b/fs/reiserfs/xattr_acl.c
+@@ -296,8 +296,7 @@ reiserfs_set_acl(struct inode *inode, in
+ }
+ }
+
+- if (value)
+- kfree(value);
++ kfree(value);
+
+ if (!error) {
+ /* Release the old one */
+diff --git a/fs/super.c b/fs/super.c
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -513,7 +513,7 @@ static void mark_files_ro(struct super_b
+ 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
+--- a/fs/vfat/namei.c
++++ b/fs/vfat/namei.c
+@@ -621,8 +621,7 @@ static int vfat_build_slots(struct inode
+ }
+
+ /* 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 @@ static int vfat_rename(struct inode *old
+ {
+ 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 @@ static int vfat_rename(struct inode *old
+
+ 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 @@ error_inode:
+ 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
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -143,7 +143,7 @@ getxattr(struct dentry *d, char __user *
+ 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 @@ getxattr(struct dentry *d, char __user *
+ 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
+--- 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 @@ kmem_alloc(size_t size, gfp_t flags)
+ }
+
+ void *
+-kmem_zalloc(size_t size, gfp_t flags)
++kmem_zalloc(size_t size, unsigned int __nocast flags)
+ {
+ void *ptr;
+
+@@ -90,7 +90,7 @@ kmem_free(void *ptr, size_t size)
+
+ void *
+ kmem_realloc(void *ptr, size_t newsize, size_t oldsize,
+- gfp_t flags)
++ unsigned int __nocast flags)
+ {
+ void *new;
+
+@@ -105,11 +105,11 @@ kmem_realloc(void *ptr, size_t newsize,
+ }
+
+ 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 @@ kmem_zone_alloc(kmem_zone_t *zone, gfp_t
+ }
+
+ 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
+--- a/fs/xfs/linux-2.6/kmem.h
++++ b/fs/xfs/linux-2.6/kmem.h
+@@ -81,9 +81,9 @@ typedef unsigned long xfs_pflags_t;
+ *(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 @@ kmem_zone_destroy(kmem_zone_t *zone)
+ 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 @@ kmem_shake_deregister(kmem_shaker_t shri
+ }
+
+ 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
+--- a/fs/xfs/linux-2.6/xfs_aops.c
++++ b/fs/xfs/linux-2.6/xfs_aops.c
+@@ -1296,7 +1296,7 @@ linvfs_invalidate_page(
+ 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
+--- 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 @@ set_page_region(
+ 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 @@ test_page_region(
+ {
+ 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 @@ _pagebuf_lookup_pages(
+ 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_force_sleep;
+
+ 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
+--- 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
+--- 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
+--- a/include/asm-alpha/rwsem.h
++++ b/include/asm-alpha/rwsem.h
+@@ -262,5 +262,10 @@ static inline long rwsem_atomic_update(l
+ #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
+--- a/include/asm-alpha/semaphore.h
++++ b/include/asm-alpha/semaphore.h
+@@ -26,9 +26,6 @@ struct semaphore {
+ .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
+--- 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
+--- /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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- /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
+--- 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
+--- 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
+--- a/include/asm-arm/arch-ebsa285/memory.h
++++ b/include/asm-arm/arch-ebsa285/memory.h
+@@ -46,14 +46,14 @@ extern unsigned long __bus_to_virt(unsig
+ #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 @@ extern unsigned long __bus_to_virt(unsig
+ /*
+ * 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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/enp2611.h b/include/asm-arm/arch-ixp2000/enp2611.h
+--- a/include/asm-arm/arch-ixp2000/enp2611.h
++++ b/include/asm-arm/arch-ixp2000/enp2611.h
+@@ -21,8 +21,20 @@
+ #ifndef __ENP2611_H
+ #define __ENP2611_H
+
+-#define ENP2611_GPIO_SCL 0x07
+-#define ENP2611_GPIO_SDA 0x06
++#define ENP2611_CALEB_PHYS_BASE 0xc5000000
++#define ENP2611_CALEB_VIRT_BASE 0xfe000000
++#define ENP2611_CALEB_SIZE 0x00100000
++
++#define ENP2611_PM3386_0_PHYS_BASE 0xc6000000
++#define ENP2611_PM3386_0_VIRT_BASE 0xfe100000
++#define ENP2611_PM3386_0_SIZE 0x00100000
++
++#define ENP2611_PM3386_1_PHYS_BASE 0xc6400000
++#define ENP2611_PM3386_1_VIRT_BASE 0xfe200000
++#define ENP2611_PM3386_1_SIZE 0x00100000
++
++#define ENP2611_GPIO_SCL 7
++#define ENP2611_GPIO_SDA 6
+
+
+ #endif
+diff --git a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
+--- 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
+--- 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
+--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
++++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+@@ -59,14 +59,15 @@
+ #define IXP2000_CAP_SIZE 0x00100000
+
+ /*
+- * Addresses for specific on-chip peripherals
++ * Addresses for specific on-chip peripherals.
+ */
+ #define IXP2000_SLOWPORT_CSR_VIRT_BASE 0xfef80000
+ #define IXP2000_GLOBAL_REG_VIRT_BASE 0xfef04000
+ #define IXP2000_UART_PHYS_BASE 0xc0030000
+ #define IXP2000_UART_VIRT_BASE 0xfef30000
+ #define IXP2000_TIMER_VIRT_BASE 0xfef20000
+-#define IXP2000_GPIO_VIRT_BASE 0Xfef10000
++#define IXP2000_UENGINE_CSR_VIRT_BASE 0xfef18000
++#define IXP2000_GPIO_VIRT_BASE 0xfef10000
+
+ /*
+ * Devices outside of the 0xc0000000 -> 0xc0100000 range. The virtual
+@@ -252,7 +253,7 @@
+ #define IXP2000_PCI_XSCALE_INT_ENABLE IXP2000_PCI_CSR(0x15C)
+
+ #define IXP2000_PCICNTL_PNR (1<<17) /* PCI not Reset bit of PCI_CONTROL */
+-#define IXP2000_PCICNTL_PCF (1<<28) /* PCI Centrolfunction bit */
++#define IXP2000_PCICNTL_PCF (1<<28) /* PCI Central function bit */
+ #define IXP2000_XSCALE_INT (1<<1) /* Interrupt from XScale to PCI */
+
+ /* These are from the IRQ register in the PCI ISR register */
+@@ -392,4 +393,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
+--- 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
+--- a/include/asm-arm/arch-ixp2000/platform.h
++++ b/include/asm-arm/arch-ixp2000/platform.h
+@@ -15,40 +15,40 @@
+
+ #ifndef __ASSEMBLY__
+
++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;
++}
++
+ /*
+- * 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.
++ * 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.
+ */
+-#if defined(CONFIG_ARCH_ENP2611) || defined(CONFIG_ARCH_IXDP2400) || defined(CONFIG_ARCH_IXDP2401)
+-
+-#include <asm/system.h> /* Pickup local_irq_ functions */
+-
+-static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
++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);
+-}
+-#else
+-static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
+-{
+- *((volatile unsigned long *)reg) = val;
++ __asm__ __volatile__("mov %0, %0" : "+r" (dummy));
+ }
+-#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-ixp2000/system.h b/include/asm-arm/arch-ixp2000/system.h
+--- a/include/asm-arm/arch-ixp2000/system.h
++++ b/include/asm-arm/arch-ixp2000/system.h
+@@ -26,29 +26,24 @@ static inline void arch_reset(char mode)
+ * RedBoot bank.
+ */
+ if (machine_is_ixdp2401()) {
+- *IXDP2X01_CPLD_FLASH_REG = ((0 >> IXDP2X01_FLASH_WINDOW_BITS)
+- | IXDP2X01_CPLD_FLASH_INTERN);
+- *IXDP2X01_CPLD_RESET_REG = 0xffffffff;
++ ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
++ ((0 >> IXDP2X01_FLASH_WINDOW_BITS)
++ | IXDP2X01_CPLD_FLASH_INTERN));
++ ixp2000_reg_wrb(IXDP2X01_CPLD_RESET_REG, 0xffffffff);
+ }
+
+ /*
+ * On IXDP2801 we need to write this magic sequence to the CPLD
+ * to cause a complete reset of the CPU and all external devices
+- * and moves the flash bank register back to 0.
++ * and move the flash bank register back to 0.
+ */
+ if (machine_is_ixdp2801()) {
+ unsigned long reset_reg = *IXDP2X01_CPLD_RESET_REG;
++
+ reset_reg = 0x55AA0000 | (reset_reg & 0x0000FFFF);
+- *IXDP2X01_CPLD_RESET_REG = reset_reg;
+- mb();
+- *IXDP2X01_CPLD_RESET_REG = 0x80000000;
++ ixp2000_reg_write(IXDP2X01_CPLD_RESET_REG, reset_reg);
++ ixp2000_reg_wrb(IXDP2X01_CPLD_RESET_REG, 0x80000000);
+ }
+
+- /*
+- * We do a reset all if we are PCI master. We could be a slave and we
+- * don't want to do anything funky on the PCI bus.
+- */
+- if (*IXP2000_STRAP_OPTIONS & CFG_PCI_BOOT_HOST) {
+- *(IXP2000_RESET0) |= (RSTALL);
+- }
++ ixp2000_reg_wrb(IXP2000_RESET0, RSTALL);
+ }
+diff --git a/include/asm-arm/arch-ixp2000/uengine.h b/include/asm-arm/arch-ixp2000/uengine.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-ixp2000/uengine.h
+@@ -0,0 +1,62 @@
++/*
++ * Generic library functions for the microengines found on the Intel
++ * IXP2000 series of network processors.
++ *
++ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh at wantstofly.org>
++ * Dedicated to Marija Kulikova.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of the
++ * License, or (at your option) any later version.
++ */
++
++#ifndef __IXP2000_UENGINE_H
++#define __IXP2000_UENGINE_H
++
++extern u32 ixp2000_uengine_mask;
++
++struct ixp2000_uengine_code
++{
++ u32 cpu_model_bitmask;
++ u8 cpu_min_revision;
++ u8 cpu_max_revision;
++
++ u32 uengine_parameters;
++
++ struct ixp2000_reg_value {
++ int reg;
++ u32 value;
++ } *initial_reg_values;
++
++ int num_insns;
++ u8 *insns;
++};
++
++u32 ixp2000_uengine_csr_read(int uengine, int offset);
++void ixp2000_uengine_csr_write(int uengine, int offset, u32 value);
++void ixp2000_uengine_reset(u32 uengine_mask);
++void ixp2000_uengine_set_mode(int uengine, u32 mode);
++void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns);
++void ixp2000_uengine_init_context(int uengine, int context, int pc);
++void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask);
++void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask);
++int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c);
++
++#define IXP2000_UENGINE_8_CONTEXTS 0x00000000
++#define IXP2000_UENGINE_4_CONTEXTS 0x80000000
++#define IXP2000_UENGINE_PRN_UPDATE_EVERY 0x40000000
++#define IXP2000_UENGINE_PRN_UPDATE_ON_ACCESS 0x00000000
++#define IXP2000_UENGINE_NN_FROM_SELF 0x00100000
++#define IXP2000_UENGINE_NN_FROM_PREVIOUS 0x00000000
++#define IXP2000_UENGINE_ASSERT_EMPTY_AT_3 0x000c0000
++#define IXP2000_UENGINE_ASSERT_EMPTY_AT_2 0x00080000
++#define IXP2000_UENGINE_ASSERT_EMPTY_AT_1 0x00040000
++#define IXP2000_UENGINE_ASSERT_EMPTY_AT_0 0x00000000
++#define IXP2000_UENGINE_LM_ADDR1_GLOBAL 0x00020000
++#define IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT 0x00000000
++#define IXP2000_UENGINE_LM_ADDR0_GLOBAL 0x00010000
++#define IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT 0x00000000
++
++
++#endif
+diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
+--- a/include/asm-arm/arch-ixp4xx/io.h
++++ b/include/asm-arm/arch-ixp4xx/io.h
+@@ -113,7 +113,7 @@ __ixp4xx_writeb(u8 value, u32 addr)
+ }
+
+ 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 @@ __ixp4xx_writew(u16 value, u32 addr)
+ }
+
+ 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 @@ __ixp4xx_writel(u32 value, u32 addr)
+ }
+
+ 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
+--- 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_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_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_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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- /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
+--- 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
+--- 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
+--- 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-realview/debug-macro.S b/include/asm-arm/arch-realview/debug-macro.S
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/debug-macro.S
+@@ -0,0 +1,38 @@
++/* linux/include/asm-arm/arch-realview/debug-macro.S
++ *
++ * Debugging macro include header
++ *
++ * Copyright (C) 1994-1999 Russell King
++ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
++ *
++ * 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 <asm/hardware/amba_serial.h>
++
++ .macro addruart,rx
++ mrc p15, 0, \rx, c1, c0
++ tst \rx, #1 @ MMU enabled?
++ moveq \rx, #0x10000000
++ movne \rx, #0xf1000000 @ virtual base
++ orr \rx, \rx, #0x00009000
++ .endm
++
++ .macro senduart,rd,rx
++ strb \rd, [\rx, #UART01x_DR]
++ .endm
++
++ .macro waituart,rd,rx
++1001: ldr \rd, [\rx, #0x18] @ UARTFLG
++ tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full
++ bne 1001b
++ .endm
++
++ .macro busyuart,rd,rx
++1001: ldr \rd, [\rx, #0x18] @ UARTFLG
++ tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
++ bne 1001b
++ .endm
+diff --git a/include/asm-arm/arch-realview/dma.h b/include/asm-arm/arch-realview/dma.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/dma.h
+@@ -0,0 +1,27 @@
++/*
++ * linux/include/asm-arm/arch-realview/dma.h
++ *
++ * Copyright (C) 2003 ARM Limited.
++ * Copyright (C) 1997,1998 Russell King
++ *
++ * 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_ARCH_DMA_H
++#define __ASM_ARCH_DMA_H
++
++#define MAX_DMA_ADDRESS 0xffffffff
++#define MAX_DMA_CHANNELS 0
++
++#endif /* _ASM_ARCH_DMA_H */
+diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/entry-macro.S
+@@ -0,0 +1,49 @@
++/*
++ * include/asm-arm/arch-realview/entry-macro.S
++ *
++ * Low-level IRQ helper macros for RealView platforms
++ *
++ * 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 <asm/hardware/gic.h>
++
++ .macro disable_fiq
++ .endm
++
++ /*
++ * The interrupt numbering scheme is defined in the
++ * interrupt controller spec. To wit:
++ *
++ * Interrupts 0-15 are IPI
++ * 16-28 are reserved
++ * 29-31 are local. We allow 30 to be used for the watchdog.
++ * 32-1020 are global
++ * 1021-1022 are reserved
++ * 1023 is "spurious" (no interrupt)
++ *
++ * For now, we ignore all local interrupts so only return an interrupt if it's
++ * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
++ *
++ * A simple read from the controller will tell us the number of the highest
++ * priority enabled interrupt. We then just need to check whether it is in the
++ * valid range for an IRQ (30-1020 inclusive).
++ */
++
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++
++ ldr \base, =IO_ADDRESS(REALVIEW_GIC_CPU_BASE)
++ ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
++
++ ldr \tmp, =1021
++
++ bic \irqnr, \irqstat, #0x1c00
++
++ cmp \irqnr, #29
++ cmpcc \irqnr, \irqnr
++ cmpne \irqnr, \tmp
++ cmpcs \irqnr, \irqnr
++
++ .endm
+diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/hardware.h
+@@ -0,0 +1,31 @@
++/*
++ * linux/include/asm-arm/arch-realview/hardware.h
++ *
++ * This file contains the hardware definitions of the RealView boards.
++ *
++ * Copyright (C) 2003 ARM Limited.
++ *
++ * 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_ARCH_HARDWARE_H
++#define __ASM_ARCH_HARDWARE_H
++
++#include <asm/sizes.h>
++#include <asm/arch/platform.h>
++
++/* macro to get at IO space when running virtually */
++#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
++
++#endif
+diff --git a/include/asm-arm/arch-realview/io.h b/include/asm-arm/arch-realview/io.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/io.h
+@@ -0,0 +1,34 @@
++/*
++ * linux/include/asm-arm/arch-realview/io.h
++ *
++ * Copyright (C) 2003 ARM Limited
++ *
++ * 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_ARM_ARCH_IO_H
++#define __ASM_ARM_ARCH_IO_H
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++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)
++
++#endif
+diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/irqs.h
+@@ -0,0 +1,103 @@
++/*
++ * linux/include/asm-arm/arch-realview/irqs.h
++ *
++ * Copyright (C) 2003 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd.
++ *
++ * 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 <asm/arch/platform.h>
++
++/*
++ * IRQ interrupts definitions are the same the INT definitions
++ * held within platform.h
++ */
++#define IRQ_GIC_START 32
++#define IRQ_WDOGINT (IRQ_GIC_START + INT_WDOGINT)
++#define IRQ_SOFTINT (IRQ_GIC_START + INT_SOFTINT)
++#define IRQ_COMMRx (IRQ_GIC_START + INT_COMMRx)
++#define IRQ_COMMTx (IRQ_GIC_START + INT_COMMTx)
++#define IRQ_TIMERINT0_1 (IRQ_GIC_START + INT_TIMERINT0_1)
++#define IRQ_TIMERINT2_3 (IRQ_GIC_START + INT_TIMERINT2_3)
++#define IRQ_GPIOINT0 (IRQ_GIC_START + INT_GPIOINT0)
++#define IRQ_GPIOINT1 (IRQ_GIC_START + INT_GPIOINT1)
++#define IRQ_GPIOINT2 (IRQ_GIC_START + INT_GPIOINT2)
++#define IRQ_GPIOINT3 (IRQ_GIC_START + INT_GPIOINT3)
++#define IRQ_RTCINT (IRQ_GIC_START + INT_RTCINT)
++#define IRQ_SSPINT (IRQ_GIC_START + INT_SSPINT)
++#define IRQ_UARTINT0 (IRQ_GIC_START + INT_UARTINT0)
++#define IRQ_UARTINT1 (IRQ_GIC_START + INT_UARTINT1)
++#define IRQ_UARTINT2 (IRQ_GIC_START + INT_UARTINT2)
++#define IRQ_UART3 (IRQ_GIC_START + INT_UARTINT3)
++#define IRQ_SCIINT (IRQ_GIC_START + INT_SCIINT)
++#define IRQ_CLCDINT (IRQ_GIC_START + INT_CLCDINT)
++#define IRQ_DMAINT (IRQ_GIC_START + INT_DMAINT)
++#define IRQ_PWRFAILINT (IRQ_GIC_START + INT_PWRFAILINT)
++#define IRQ_MBXINT (IRQ_GIC_START + INT_MBXINT)
++#define IRQ_GNDINT (IRQ_GIC_START + INT_GNDINT)
++#define IRQ_MMCI0B (IRQ_GIC_START + INT_MMCI0B)
++#define IRQ_MMCI1B (IRQ_GIC_START + INT_MMCI1B)
++#define IRQ_KMI0 (IRQ_GIC_START + INT_KMI0)
++#define IRQ_KMI1 (IRQ_GIC_START + INT_KMI1)
++#define IRQ_SCI3 (IRQ_GIC_START + INT_SCI3)
++#define IRQ_CLCD (IRQ_GIC_START + INT_CLCD)
++#define IRQ_TOUCH (IRQ_GIC_START + INT_TOUCH)
++#define IRQ_KEYPAD (IRQ_GIC_START + INT_KEYPAD)
++#define IRQ_DoC (IRQ_GIC_START + INT_DoC)
++#define IRQ_MMCI0A (IRQ_GIC_START + INT_MMCI0A)
++#define IRQ_MMCI1A (IRQ_GIC_START + INT_MMCI1A)
++#define IRQ_AACI (IRQ_GIC_START + INT_AACI)
++#define IRQ_ETH (IRQ_GIC_START + INT_ETH)
++#define IRQ_USB (IRQ_GIC_START + INT_USB)
++
++#define IRQMASK_WDOGINT INTMASK_WDOGINT
++#define IRQMASK_SOFTINT INTMASK_SOFTINT
++#define IRQMASK_COMMRx INTMASK_COMMRx
++#define IRQMASK_COMMTx INTMASK_COMMTx
++#define IRQMASK_TIMERINT0_1 INTMASK_TIMERINT0_1
++#define IRQMASK_TIMERINT2_3 INTMASK_TIMERINT2_3
++#define IRQMASK_GPIOINT0 INTMASK_GPIOINT0
++#define IRQMASK_GPIOINT1 INTMASK_GPIOINT1
++#define IRQMASK_GPIOINT2 INTMASK_GPIOINT2
++#define IRQMASK_GPIOINT3 INTMASK_GPIOINT3
++#define IRQMASK_RTCINT INTMASK_RTCINT
++#define IRQMASK_SSPINT INTMASK_SSPINT
++#define IRQMASK_UARTINT0 INTMASK_UARTINT0
++#define IRQMASK_UARTINT1 INTMASK_UARTINT1
++#define IRQMASK_UARTINT2 INTMASK_UARTINT2
++#define IRQMASK_SCIINT INTMASK_SCIINT
++#define IRQMASK_CLCDINT INTMASK_CLCDINT
++#define IRQMASK_DMAINT INTMASK_DMAINT
++#define IRQMASK_PWRFAILINT INTMASK_PWRFAILINT
++#define IRQMASK_MBXINT INTMASK_MBXINT
++#define IRQMASK_GNDINT INTMASK_GNDINT
++#define IRQMASK_MMCI0B INTMASK_MMCI0B
++#define IRQMASK_MMCI1B INTMASK_MMCI1B
++#define IRQMASK_KMI0 INTMASK_KMI0
++#define IRQMASK_KMI1 INTMASK_KMI1
++#define IRQMASK_SCI3 INTMASK_SCI3
++#define IRQMASK_UART3 INTMASK_UART3
++#define IRQMASK_CLCD INTMASK_CLCD
++#define IRQMASK_TOUCH INTMASK_TOUCH
++#define IRQMASK_KEYPAD INTMASK_KEYPAD
++#define IRQMASK_DoC INTMASK_DoC
++#define IRQMASK_MMCI0A INTMASK_MMCI0A
++#define IRQMASK_MMCI1A INTMASK_MMCI1A
++#define IRQMASK_AACI INTMASK_AACI
++#define IRQMASK_ETH INTMASK_ETH
++#define IRQMASK_USB INTMASK_USB
++
++#define NR_IRQS (IRQ_GIC_START + 64)
+diff --git a/include/asm-arm/arch-realview/memory.h b/include/asm-arm/arch-realview/memory.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/memory.h
+@@ -0,0 +1,38 @@
++/*
++ * linux/include/asm-arm/arch-realview/memory.h
++ *
++ * Copyright (C) 2003 ARM Limited
++ *
++ * 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_ARCH_MEMORY_H
++#define __ASM_ARCH_MEMORY_H
++
++/*
++ * Physical DRAM offset.
++ */
++#define PHYS_OFFSET (0x00000000UL)
++
++/*
++ * Virtual view <-> DMA view memory address translations
++ * virt_to_bus: Used to translate the virtual address to an
++ * address suitable to be passed to set_dma_addr
++ * bus_to_virt: Used to convert an address for DMA operations
++ * to an address that the kernel can use.
++ */
++#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
++#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
++
++#endif
+diff --git a/include/asm-arm/arch-realview/param.h b/include/asm-arm/arch-realview/param.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/param.h
+@@ -0,0 +1,19 @@
++/*
++ * linux/include/asm-arm/arch-realview/param.h
++ *
++ * Copyright (C) 2002 ARM Limited
++ *
++ * 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
++ */
+diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/platform.h
+@@ -0,0 +1,395 @@
++/*
++ * linux/include/asm-arm/arch-realview/platform.h
++ *
++ * Copyright (c) ARM Limited 2003. 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 __address_h
++#define __address_h 1
++
++/*
++ * Memory definitions
++ */
++#define REALVIEW_BOOT_ROM_LO 0x30000000 /* DoC Base (64Mb)...*/
++#define REALVIEW_BOOT_ROM_HI 0x30000000
++#define REALVIEW_BOOT_ROM_BASE REALVIEW_BOOT_ROM_HI /* Normal position */
++#define REALVIEW_BOOT_ROM_SIZE SZ_64M
++
++#define REALVIEW_SSRAM_BASE /* REALVIEW_SSMC_BASE ? */
++#define REALVIEW_SSRAM_SIZE SZ_2M
++
++#define REALVIEW_FLASH_BASE 0x40000000
++#define REALVIEW_FLASH_SIZE SZ_64M
++
++/*
++ * SDRAM
++ */
++#define REALVIEW_SDRAM_BASE 0x00000000
++
++/*
++ * Logic expansion modules
++ *
++ */
++
++
++/* ------------------------------------------------------------------------
++ * RealView Registers
++ * ------------------------------------------------------------------------
++ *
++ */
++#define REALVIEW_SYS_ID_OFFSET 0x00
++#define REALVIEW_SYS_SW_OFFSET 0x04
++#define REALVIEW_SYS_LED_OFFSET 0x08
++#define REALVIEW_SYS_OSC0_OFFSET 0x0C
++
++#define REALVIEW_SYS_OSC1_OFFSET 0x10
++#define REALVIEW_SYS_OSC2_OFFSET 0x14
++#define REALVIEW_SYS_OSC3_OFFSET 0x18
++#define REALVIEW_SYS_OSC4_OFFSET 0x1C /* OSC1 for RealView/AB */
++
++#define REALVIEW_SYS_LOCK_OFFSET 0x20
++#define REALVIEW_SYS_100HZ_OFFSET 0x24
++#define REALVIEW_SYS_CFGDATA1_OFFSET 0x28
++#define REALVIEW_SYS_CFGDATA2_OFFSET 0x2C
++#define REALVIEW_SYS_FLAGS_OFFSET 0x30
++#define REALVIEW_SYS_FLAGSSET_OFFSET 0x30
++#define REALVIEW_SYS_FLAGSCLR_OFFSET 0x34
++#define REALVIEW_SYS_NVFLAGS_OFFSET 0x38
++#define REALVIEW_SYS_NVFLAGSSET_OFFSET 0x38
++#define REALVIEW_SYS_NVFLAGSCLR_OFFSET 0x3C
++#define REALVIEW_SYS_RESETCTL_OFFSET 0x40
++#define REALVIEW_SYS_PCICTL_OFFSET 0x44
++#define REALVIEW_SYS_MCI_OFFSET 0x48
++#define REALVIEW_SYS_FLASH_OFFSET 0x4C
++#define REALVIEW_SYS_CLCD_OFFSET 0x50
++#define REALVIEW_SYS_CLCDSER_OFFSET 0x54
++#define REALVIEW_SYS_BOOTCS_OFFSET 0x58
++#define REALVIEW_SYS_24MHz_OFFSET 0x5C
++#define REALVIEW_SYS_MISC_OFFSET 0x60
++#define REALVIEW_SYS_IOSEL_OFFSET 0x70
++#define REALVIEW_SYS_TEST_OSC0_OFFSET 0x80
++#define REALVIEW_SYS_TEST_OSC1_OFFSET 0x84
++#define REALVIEW_SYS_TEST_OSC2_OFFSET 0x88
++#define REALVIEW_SYS_TEST_OSC3_OFFSET 0x8C
++#define REALVIEW_SYS_TEST_OSC4_OFFSET 0x90
++
++#define REALVIEW_SYS_BASE 0x10000000
++#define REALVIEW_SYS_ID (REALVIEW_SYS_BASE + REALVIEW_SYS_ID_OFFSET)
++#define REALVIEW_SYS_SW (REALVIEW_SYS_BASE + REALVIEW_SYS_SW_OFFSET)
++#define REALVIEW_SYS_LED (REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET)
++#define REALVIEW_SYS_OSC0 (REALVIEW_SYS_BASE + REALVIEW_SYS_OSC0_OFFSET)
++#define REALVIEW_SYS_OSC1 (REALVIEW_SYS_BASE + REALVIEW_SYS_OSC1_OFFSET)
++
++#define REALVIEW_SYS_LOCK (REALVIEW_SYS_BASE + REALVIEW_SYS_LOCK_OFFSET)
++#define REALVIEW_SYS_100HZ (REALVIEW_SYS_BASE + REALVIEW_SYS_100HZ_OFFSET)
++#define REALVIEW_SYS_CFGDATA1 (REALVIEW_SYS_BASE + REALVIEW_SYS_CFGDATA1_OFFSET)
++#define REALVIEW_SYS_CFGDATA2 (REALVIEW_SYS_BASE + REALVIEW_SYS_CFGDATA2_OFFSET)
++#define REALVIEW_SYS_FLAGS (REALVIEW_SYS_BASE + REALVIEW_SYS_FLAGS_OFFSET)
++#define REALVIEW_SYS_FLAGSSET (REALVIEW_SYS_BASE + REALVIEW_SYS_FLAGSSET_OFFSET)
++#define REALVIEW_SYS_FLAGSCLR (REALVIEW_SYS_BASE + REALVIEW_SYS_FLAGSCLR_OFFSET)
++#define REALVIEW_SYS_NVFLAGS (REALVIEW_SYS_BASE + REALVIEW_SYS_NVFLAGS_OFFSET)
++#define REALVIEW_SYS_NVFLAGSSET (REALVIEW_SYS_BASE + REALVIEW_SYS_NVFLAGSSET_OFFSET)
++#define REALVIEW_SYS_NVFLAGSCLR (REALVIEW_SYS_BASE + REALVIEW_SYS_NVFLAGSCLR_OFFSET)
++#define REALVIEW_SYS_RESETCTL (REALVIEW_SYS_BASE + REALVIEW_SYS_RESETCTL_OFFSET)
++#define REALVIEW_SYS_PCICTL (REALVIEW_SYS_BASE + REALVIEW_SYS_PCICTL_OFFSET)
++#define REALVIEW_SYS_MCI (REALVIEW_SYS_BASE + REALVIEW_SYS_MCI_OFFSET)
++#define REALVIEW_SYS_FLASH (REALVIEW_SYS_BASE + REALVIEW_SYS_FLASH_OFFSET)
++#define REALVIEW_SYS_CLCD (REALVIEW_SYS_BASE + REALVIEW_SYS_CLCD_OFFSET)
++#define REALVIEW_SYS_CLCDSER (REALVIEW_SYS_BASE + REALVIEW_SYS_CLCDSER_OFFSET)
++#define REALVIEW_SYS_BOOTCS (REALVIEW_SYS_BASE + REALVIEW_SYS_BOOTCS_OFFSET)
++#define REALVIEW_SYS_24MHz (REALVIEW_SYS_BASE + REALVIEW_SYS_24MHz_OFFSET)
++#define REALVIEW_SYS_MISC (REALVIEW_SYS_BASE + REALVIEW_SYS_MISC_OFFSET)
++#define REALVIEW_SYS_IOSEL (REALVIEW_SYS_BASE + REALVIEW_SYS_IOSEL_OFFSET)
++#define REALVIEW_SYS_TEST_OSC0 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC0_OFFSET)
++#define REALVIEW_SYS_TEST_OSC1 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC1_OFFSET)
++#define REALVIEW_SYS_TEST_OSC2 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC2_OFFSET)
++#define REALVIEW_SYS_TEST_OSC3 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC3_OFFSET)
++#define REALVIEW_SYS_TEST_OSC4 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC4_OFFSET)
++
++/*
++ * Values for REALVIEW_SYS_RESET_CTRL
++ */
++#define REALVIEW_SYS_CTRL_RESET_CONFIGCLR 0x01
++#define REALVIEW_SYS_CTRL_RESET_CONFIGINIT 0x02
++#define REALVIEW_SYS_CTRL_RESET_DLLRESET 0x03
++#define REALVIEW_SYS_CTRL_RESET_PLLRESET 0x04
++#define REALVIEW_SYS_CTRL_RESET_POR 0x05
++#define REALVIEW_SYS_CTRL_RESET_DoC 0x06
++
++#define REALVIEW_SYS_CTRL_LED (1 << 0)
++
++
++/* ------------------------------------------------------------------------
++ * RealView control registers
++ * ------------------------------------------------------------------------
++ */
++
++/*
++ * REALVIEW_IDFIELD
++ *
++ * 31:24 = manufacturer (0x41 = ARM)
++ * 23:16 = architecture (0x08 = AHB system bus, ASB processor bus)
++ * 15:12 = FPGA (0x3 = XVC600 or XVC600E)
++ * 11:4 = build value
++ * 3:0 = revision number (0x1 = rev B (AHB))
++ */
++
++/*
++ * REALVIEW_SYS_LOCK
++ * control access to SYS_OSCx, SYS_CFGDATAx, SYS_RESETCTL,
++ * SYS_CLD, SYS_BOOTCS
++ */
++#define REALVIEW_SYS_LOCK_LOCKED (1 << 16)
++#define REALVIEW_SYS_LOCKVAL_MASK 0xFFFF /* write 0xA05F to enable write access */
++
++/*
++ * REALVIEW_SYS_FLASH
++ */
++#define REALVIEW_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */
++
++/*
++ * REALVIEW_INTREG
++ * - used to acknowledge and control MMCI and UART interrupts
++ */
++#define REALVIEW_INTREG_WPROT 0x00 /* MMC protection status (no interrupt generated) */
++#define REALVIEW_INTREG_RI0 0x01 /* Ring indicator UART0 is asserted, */
++#define REALVIEW_INTREG_CARDIN 0x08 /* MMCI card in detect */
++ /* write 1 to acknowledge and clear */
++#define REALVIEW_INTREG_RI1 0x02 /* Ring indicator UART1 is asserted, */
++#define REALVIEW_INTREG_CARDINSERT 0x03 /* Signal insertion of MMC card */
++
++/*
++ * REALVIEW peripheral addresses
++ */
++#define REALVIEW_SCTL_BASE 0x10001000 /* System controller */
++#define REALVIEW_I2C_BASE 0x10002000 /* I2C control */
++ /* Reserved 0x10003000 */
++#define REALVIEW_AACI_BASE 0x10004000 /* Audio */
++#define REALVIEW_MMCI0_BASE 0x10005000 /* MMC interface */
++#define REALVIEW_KMI0_BASE 0x10006000 /* KMI interface */
++#define REALVIEW_KMI1_BASE 0x10007000 /* KMI 2nd interface */
++#define REALVIEW_CHAR_LCD_BASE 0x10008000 /* Character LCD */
++#define REALVIEW_UART0_BASE 0x10009000 /* UART 0 */
++#define REALVIEW_UART1_BASE 0x1000A000 /* UART 1 */
++#define REALVIEW_UART2_BASE 0x1000B000 /* UART 2 */
++#define REALVIEW_UART3_BASE 0x1000C000 /* UART 3 */
++#define REALVIEW_SSP_BASE 0x1000D000 /* Synchronous Serial Port */
++#define REALVIEW_SCI_BASE 0x1000E000 /* Smart card controller */
++ /* Reserved 0x1000F000 */
++#define REALVIEW_WATCHDOG_BASE 0x10010000 /* watchdog interface */
++#define REALVIEW_TIMER0_1_BASE 0x10011000 /* Timer 0 and 1 */
++#define REALVIEW_TIMER2_3_BASE 0x10012000 /* Timer 2 and 3 */
++#define REALVIEW_GPIO0_BASE 0x10013000 /* GPIO port 0 */
++#define REALVIEW_GPIO1_BASE 0x10014000 /* GPIO port 1 */
++#define REALVIEW_GPIO2_BASE 0x10015000 /* GPIO port 2 */
++ /* Reserved 0x10016000 */
++#define REALVIEW_RTC_BASE 0x10017000 /* Real Time Clock */
++#define REALVIEW_DMC_BASE 0x10018000 /* DMC configuration */
++#define REALVIEW_PCI_CORE_BASE 0x10019000 /* PCI configuration */
++ /* Reserved 0x1001A000 - 0x1001FFFF */
++#define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */
++#define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */
++#define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
++#define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
++#define REALVIEW_SMC_BASE 0x10080000 /* SMC */
++ /* Reserved 0x10090000 - 0x100EFFFF */
++
++#define REALVIEW_ETH_BASE 0x4E000000 /* Ethernet */
++
++/* PCI space */
++#define REALVIEW_PCI_BASE 0x41000000 /* PCI Interface */
++#define REALVIEW_PCI_CFG_BASE 0x42000000
++#define REALVIEW_PCI_MEM_BASE0 0x44000000
++#define REALVIEW_PCI_MEM_BASE1 0x50000000
++#define REALVIEW_PCI_MEM_BASE2 0x60000000
++/* Sizes of above maps */
++#define REALVIEW_PCI_BASE_SIZE 0x01000000
++#define REALVIEW_PCI_CFG_BASE_SIZE 0x02000000
++#define REALVIEW_PCI_MEM_BASE0_SIZE 0x0c000000 /* 32Mb */
++#define REALVIEW_PCI_MEM_BASE1_SIZE 0x10000000 /* 256Mb */
++#define REALVIEW_PCI_MEM_BASE2_SIZE 0x10000000 /* 256Mb */
++
++#define REALVIEW_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */
++#define REALVIEW_LT_BASE 0x80000000 /* Logic Tile expansion */
++
++/*
++ * Disk on Chip
++ */
++#define REALVIEW_DOC_BASE 0x2C000000
++#define REALVIEW_DOC_SIZE (16 << 20)
++#define REALVIEW_DOC_PAGE_SIZE 512
++#define REALVIEW_DOC_TOTAL_PAGES (DOC_SIZE / PAGE_SIZE)
++
++#define ERASE_UNIT_PAGES 32
++#define START_PAGE 0x80
++
++/*
++ * LED settings, bits [7:0]
++ */
++#define REALVIEW_SYS_LED0 (1 << 0)
++#define REALVIEW_SYS_LED1 (1 << 1)
++#define REALVIEW_SYS_LED2 (1 << 2)
++#define REALVIEW_SYS_LED3 (1 << 3)
++#define REALVIEW_SYS_LED4 (1 << 4)
++#define REALVIEW_SYS_LED5 (1 << 5)
++#define REALVIEW_SYS_LED6 (1 << 6)
++#define REALVIEW_SYS_LED7 (1 << 7)
++
++#define ALL_LEDS 0xFF
++
++#define LED_BANK REALVIEW_SYS_LED
++
++/*
++ * Control registers
++ */
++#define REALVIEW_IDFIELD_OFFSET 0x0 /* RealView build information */
++#define REALVIEW_FLASHPROG_OFFSET 0x4 /* Flash devices */
++#define REALVIEW_INTREG_OFFSET 0x8 /* Interrupt control */
++#define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */
++
++/* ------------------------------------------------------------------------
++ * Interrupts - bit assignment (primary)
++ * ------------------------------------------------------------------------
++ */
++#define INT_WDOGINT 0 /* Watchdog timer */
++#define INT_SOFTINT 1 /* Software interrupt */
++#define INT_COMMRx 2 /* Debug Comm Rx interrupt */
++#define INT_COMMTx 3 /* Debug Comm Tx interrupt */
++#define INT_TIMERINT0_1 4 /* Timer 0 and 1 */
++#define INT_TIMERINT2_3 5 /* Timer 2 and 3 */
++#define INT_GPIOINT0 6 /* GPIO 0 */
++#define INT_GPIOINT1 7 /* GPIO 1 */
++#define INT_GPIOINT2 8 /* GPIO 2 */
++/* 9 reserved */
++#define INT_RTCINT 10 /* Real Time Clock */
++#define INT_SSPINT 11 /* Synchronous Serial Port */
++#define INT_UARTINT0 12 /* UART 0 on development chip */
++#define INT_UARTINT1 13 /* UART 1 on development chip */
++#define INT_UARTINT2 14 /* UART 2 on development chip */
++#define INT_UARTINT3 15 /* UART 3 on development chip */
++#define INT_SCIINT 16 /* Smart Card Interface */
++#define INT_MMCI0A 17 /* Multimedia Card 0A */
++#define INT_MMCI0B 18 /* Multimedia Card 0B */
++#define INT_AACI 19 /* Audio Codec */
++#define INT_KMI0 20 /* Keyboard/Mouse port 0 */
++#define INT_KMI1 21 /* Keyboard/Mouse port 1 */
++#define INT_CHARLCD 22 /* Character LCD */
++#define INT_CLCDINT 23 /* CLCD controller */
++#define INT_DMAINT 24 /* DMA controller */
++#define INT_PWRFAILINT 25 /* Power failure */
++#define INT_PISMO 26
++#define INT_DoC 27 /* Disk on Chip memory controller */
++#define INT_ETH 28 /* Ethernet controller */
++#define INT_USB 29 /* USB controller */
++#define INT_TSPENINT 30 /* Touchscreen pen */
++#define INT_TSKPADINT 31 /* Touchscreen keypad */
++
++/*
++ * Interrupt bit positions
++ *
++ */
++#define INTMASK_WDOGINT (1 << INT_WDOGINT)
++#define INTMASK_SOFTINT (1 << INT_SOFTINT)
++#define INTMASK_COMMRx (1 << INT_COMMRx)
++#define INTMASK_COMMTx (1 << INT_COMMTx)
++#define INTMASK_TIMERINT0_1 (1 << INT_TIMERINT0_1)
++#define INTMASK_TIMERINT2_3 (1 << INT_TIMERINT2_3)
++#define INTMASK_GPIOINT0 (1 << INT_GPIOINT0)
++#define INTMASK_GPIOINT1 (1 << INT_GPIOINT1)
++#define INTMASK_GPIOINT2 (1 << INT_GPIOINT2)
++#define INTMASK_RTCINT (1 << INT_RTCINT)
++#define INTMASK_SSPINT (1 << INT_SSPINT)
++#define INTMASK_UARTINT0 (1 << INT_UARTINT0)
++#define INTMASK_UARTINT1 (1 << INT_UARTINT1)
++#define INTMASK_UARTINT2 (1 << INT_UARTINT2)
++#define INTMASK_UARTINT3 (1 << INT_UARTINT3)
++#define INTMASK_SCIINT (1 << INT_SCIINT)
++#define INTMASK_MMCI0A (1 << INT_MMCI0A)
++#define INTMASK_MMCI0B (1 << INT_MMCI0B)
++#define INTMASK_AACI (1 << INT_AACI)
++#define INTMASK_KMI0 (1 << INT_KMI0)
++#define INTMASK_KMI1 (1 << INT_KMI1)
++#define INTMASK_CHARLCD (1 << INT_CHARLCD)
++#define INTMASK_CLCDINT (1 << INT_CLCDINT)
++#define INTMASK_DMAINT (1 << INT_DMAINT)
++#define INTMASK_PWRFAILINT (1 << INT_PWRFAILINT)
++#define INTMASK_PISMO (1 << INT_PISMO)
++#define INTMASK_DoC (1 << INT_DoC)
++#define INTMASK_ETH (1 << INT_ETH)
++#define INTMASK_USB (1 << INT_USB)
++#define INTMASK_TSPENINT (1 << INT_TSPENINT)
++#define INTMASK_TSKPADINT (1 << INT_TSKPADINT)
++
++#define MAXIRQNUM 31
++#define MAXFIQNUM 31
++#define MAXSWINUM 31
++
++/*
++ * Application Flash
++ *
++ */
++#define FLASH_BASE REALVIEW_FLASH_BASE
++#define FLASH_SIZE REALVIEW_FLASH_SIZE
++#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
++#define FLASH_BLOCK_SIZE SZ_128K
++
++/*
++ * Boot Flash
++ *
++ */
++#define EPROM_BASE REALVIEW_BOOT_ROM_HI
++#define EPROM_SIZE REALVIEW_BOOT_ROM_SIZE
++#define EPROM_END (EPROM_BASE + EPROM_SIZE - 1)
++
++/*
++ * Clean base - dummy
++ *
++ */
++#define CLEAN_BASE EPROM_BASE
++
++/*
++ * System controller bit assignment
++ */
++#define REALVIEW_REFCLK 0
++#define REALVIEW_TIMCLK 1
++
++#define REALVIEW_TIMER1_EnSel 15
++#define REALVIEW_TIMER2_EnSel 17
++#define REALVIEW_TIMER3_EnSel 19
++#define REALVIEW_TIMER4_EnSel 21
++
++
++#define MAX_TIMER 2
++#define MAX_PERIOD 699050
++#define TICKS_PER_uSEC 1
++
++/*
++ * These are useconds NOT ticks.
++ *
++ */
++#define mSEC_1 1000
++#define mSEC_5 (mSEC_1 * 5)
++#define mSEC_10 (mSEC_1 * 10)
++#define mSEC_25 (mSEC_1 * 25)
++#define SEC_1 (mSEC_1 * 1000)
++
++#define REALVIEW_CSR_BASE 0x10000000
++#define REALVIEW_CSR_SIZE 0x10000000
++
++#endif
++
++/* END */
+diff --git a/include/asm-arm/arch-realview/system.h b/include/asm-arm/arch-realview/system.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/system.h
+@@ -0,0 +1,51 @@
++/*
++ * linux/include/asm-arm/arch-realview/system.h
++ *
++ * Copyright (C) 2003 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * 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_ARCH_SYSTEM_H
++#define __ASM_ARCH_SYSTEM_H
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/arch/platform.h>
++
++static inline void arch_idle(void)
++{
++ /*
++ * This should do all the clock switching
++ * and wait for interrupt tricks
++ */
++ cpu_do_idle();
++}
++
++static inline void arch_reset(char mode)
++{
++ unsigned int hdr_ctrl = (IO_ADDRESS(REALVIEW_SYS_BASE) + REALVIEW_SYS_RESETCTL_OFFSET);
++ unsigned int val;
++
++ /*
++ * To reset, we hit the on-board reset register
++ * in the system FPGA
++ */
++ val = __raw_readl(hdr_ctrl);
++ val |= REALVIEW_SYS_CTRL_RESET_CONFIGCLR;
++ __raw_writel(val, hdr_ctrl);
++}
++
++#endif
+diff --git a/include/asm-arm/arch-realview/timex.h b/include/asm-arm/arch-realview/timex.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/timex.h
+@@ -0,0 +1,23 @@
++/*
++ * linux/include/asm-arm/arch-realview/timex.h
++ *
++ * RealView architecture timex specifications
++ *
++ * Copyright (C) 2003 ARM Limited
++ *
++ * 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 CLOCK_TICK_RATE (50000000 / 16)
+diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/uncompress.h
+@@ -0,0 +1,54 @@
++/*
++ * linux/include/asm-arm/arch-realview/uncompress.h
++ *
++ * Copyright (C) 2003 ARM Limited
++ *
++ * 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 <asm/hardware.h>
++
++#define AMBA_UART_DR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x00))
++#define AMBA_UART_LCRH (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x2c))
++#define AMBA_UART_CR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x30))
++#define AMBA_UART_FR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x18))
++
++/*
++ * This does not append a newline
++ */
++static void putstr(const char *s)
++{
++ while (*s) {
++ while (AMBA_UART_FR & (1 << 5))
++ barrier();
++
++ AMBA_UART_DR = *s;
++
++ if (*s == '\n') {
++ while (AMBA_UART_FR & (1 << 5))
++ barrier();
++
++ AMBA_UART_DR = '\r';
++ }
++ s++;
++ }
++ while (AMBA_UART_FR & (1 << 3))
++ barrier();
++}
++
++/*
++ * nothing to do
++ */
++#define arch_decomp_setup()
++#define arch_decomp_wdog()
+diff --git a/include/asm-arm/arch-realview/vmalloc.h b/include/asm-arm/arch-realview/vmalloc.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-arm/arch-realview/vmalloc.h
+@@ -0,0 +1,21 @@
++/*
++ * linux/include/asm-arm/arch-realview/vmalloc.h
++ *
++ * Copyright (C) 2003 ARM Limited
++ * Copyright (C) 2000 Russell King.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License 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 VMALLOC_END (PAGE_OFFSET + 0x18000000)
+diff --git a/include/asm-arm/arch-rpc/io.h b/include/asm-arm/arch-rpc/io.h
+--- 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
+--- 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
+--- 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 @@ struct s3c2410fb_mach_info {
+ 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
+--- 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
+--- 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
+--- 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-s3c2410/regs-iis.h b/include/asm-arm/arch-s3c2410/regs-iis.h
+--- a/include/asm-arm/arch-s3c2410/regs-iis.h
++++ b/include/asm-arm/arch-s3c2410/regs-iis.h
+@@ -55,6 +55,7 @@
+ #define S3C2410_IISMOD_16FS (0<<0)
+ #define S3C2410_IISMOD_32FS (1<<0)
+ #define S3C2410_IISMOD_48FS (2<<0)
++#define S3C2410_IISMOD_FS_MASK (3<<0)
+
+ #define S3C2410_IISPSR (0x08)
+ #define S3C2410_IISPSR_INTMASK (31<<5)
+diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
+--- 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
+--- 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
+--- 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
+--- 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 at 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
+--- 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
+--- 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
+--- 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
+--- a/include/asm-arm/dma-mapping.h
++++ b/include/asm-arm/dma-mapping.h
+@@ -70,7 +70,7 @@ static inline int dma_mapping_error(dma_
+ * 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 @@ int dma_mmap_coherent(struct device *dev
+ * 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/hardware/amba_clcd.h b/include/asm-arm/hardware/amba_clcd.h
+--- a/include/asm-arm/hardware/amba_clcd.h
++++ b/include/asm-arm/hardware/amba_clcd.h
+@@ -22,7 +22,7 @@
+ #define CLCD_UBAS 0x00000010
+ #define CLCD_LBAS 0x00000014
+
+-#ifndef CONFIG_ARCH_VERSATILE
++#if !defined(CONFIG_ARCH_VERSATILE) && !defined(CONFIG_ARCH_REALVIEW)
+ #define CLCD_IENB 0x00000018
+ #define CLCD_CNTL 0x0000001c
+ #else
+diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
+--- 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
+--- a/include/asm-arm/mach/arch.h
++++ b/include/asm-arm/mach/arch.h
+@@ -48,10 +48,11 @@ struct machine_desc {
+ * 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
+--- a/include/asm-arm/mach/flash.h
++++ b/include/asm-arm/mach/flash.h
+@@ -14,6 +14,7 @@ struct mtd_partition;
+
+ /*
+ * 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 mtd_partition;
+ */
+ 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
+--- 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 @@ struct meminfo;
+ #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
+--- 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
+--- a/include/asm-arm/pgtable.h
++++ b/include/asm-arm/pgtable.h
+@@ -397,9 +397,6 @@ static inline pte_t *pmd_page_kernel(pmd
+ #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
+--- a/include/asm-arm/semaphore.h
++++ b/include/asm-arm/semaphore.h
+@@ -24,8 +24,6 @@ struct semaphore {
+ .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
+--- 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 @@ DECLARE_PER_CPU(struct mmu_gather, mmu_g
+ 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 @@ tlb_gather_mmu(struct mm_struct *mm, uns
+ 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
+--- a/include/asm-arm/unistd.h
++++ b/include/asm-arm/unistd.h
+@@ -544,7 +544,6 @@ asmlinkage int sys_clone(unsigned long c
+ 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
+--- a/include/asm-arm26/pgtable.h
++++ b/include/asm-arm26/pgtable.h
+@@ -98,8 +98,6 @@ extern struct page *empty_zero_page;
+ #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
+--- a/include/asm-arm26/semaphore.h
++++ b/include/asm-arm26/semaphore.h
+@@ -25,9 +25,6 @@ struct semaphore {
+ .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
+--- 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 @@ tlb_gather_mmu(struct mm_struct *mm, uns
+ 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 @@ tlb_is_full_mm(struct mmu_gather *tlb)
+ } 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
+--- a/include/asm-arm26/unistd.h
++++ b/include/asm-arm26/unistd.h
+@@ -480,7 +480,6 @@ asmlinkage int sys_clone(unsigned long c
+ 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
+--- 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
+--- a/include/asm-cris/semaphore.h
++++ b/include/asm-cris/semaphore.h
+@@ -33,9 +33,6 @@ struct semaphore {
+ .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
+--- a/include/asm-cris/unistd.h
++++ b/include/asm-cris/unistd.h
+@@ -367,7 +367,6 @@ asmlinkage int sys_fork(long r10, long r
+ 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
+--- 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
+--- a/include/asm-frv/pci.h
++++ b/include/asm-frv/pci.h
+@@ -32,7 +32,7 @@ extern void pcibios_set_master(struct pc
+ 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
+--- a/include/asm-frv/pgtable.h
++++ b/include/asm-frv/pgtable.h
+@@ -436,8 +436,6 @@ static inline pte_t pte_modify(pte_t pte
+ 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
+--- a/include/asm-frv/semaphore.h
++++ b/include/asm-frv/semaphore.h
+@@ -47,9 +47,6 @@ struct semaphore {
+ #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
+--- 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
+--- 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
+--- 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
+--- 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 @@ DECLARE_PER_CPU(struct mmu_gather, mmu_g
+ 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_gather_mmu(struct mm_struct *mm, uns
+ tlb->nr = num_online_cpus() > 1 ? 0U : ~0U;
+
+ tlb->fullmm = full_mm_flush;
+- tlb->freed = 0;
+
+ return tlb;
+ }
+@@ -85,28 +81,17 @@ tlb_flush_mmu(struct mmu_gather *tlb, un
+
+ /* 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
+--- a/include/asm-h8300/semaphore.h
++++ b/include/asm-h8300/semaphore.h
+@@ -35,9 +35,6 @@ struct semaphore {
+ .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
+--- a/include/asm-h8300/unistd.h
++++ b/include/asm-h8300/unistd.h
+@@ -528,7 +528,6 @@ asmlinkage long sys_mmap2(unsigned long
+ 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/desc.h b/include/asm-i386/desc.h
+--- 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 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
+
+ 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_tss_desc(unsign
+
+ 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 write_ldt_entry(void
+
+ 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/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h
+--- a/include/asm-i386/mach-es7000/mach_mpparse.h
++++ b/include/asm-i386/mach-es7000/mach_mpparse.h
+@@ -16,7 +16,7 @@ static inline void mpc_oem_pci_bus(struc
+
+ 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
+--- a/include/asm-i386/mach-summit/mach_mpparse.h
++++ b/include/asm-i386/mach-summit/mach_mpparse.h
+@@ -22,7 +22,6 @@ static inline void mpc_oem_pci_bus(struc
+ {
+ }
+
+-extern int usb_early_handoff;
+ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid)
+ {
+@@ -32,7 +31,6 @@ static inline int mps_oem_check(struct m
+ || !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 @@ static inline int acpi_madt_oem_check(ch
+ || !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/mmzone.h b/include/asm-i386/mmzone.h
+--- a/include/asm-i386/mmzone.h
++++ b/include/asm-i386/mmzone.h
+@@ -88,12 +88,6 @@ static inline int pfn_to_nid(unsigned lo
+ __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
+--- 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
+--- a/include/asm-i386/pgtable-3level.h
++++ b/include/asm-i386/pgtable-3level.h
+@@ -74,11 +74,6 @@ static inline void set_pte(pte_t *ptep,
+ */
+ 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
+--- a/include/asm-i386/pgtable.h
++++ b/include/asm-i386/pgtable.h
+@@ -203,7 +203,8 @@ extern unsigned long pg0[];
+ #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 @@ static inline pte_t pte_modify(pte_t pte
+ 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 @@ static inline pte_t pte_modify(pte_t pte
+ #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
+--- a/include/asm-i386/rwsem.h
++++ b/include/asm-i386/rwsem.h
+@@ -284,5 +284,10 @@ LOCK_PREFIX "xadd %0,(%2)"
+ 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
+--- a/include/asm-i386/semaphore.h
++++ b/include/asm-i386/semaphore.h
+@@ -55,9 +55,6 @@ struct semaphore {
+ .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
+--- a/include/asm-i386/system.h
++++ b/include/asm-i386/system.h
+@@ -167,6 +167,8 @@ struct __xchg_dummy { unsigned long a[10
+ #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 @@ static inline void __set_64bit_var (unsi
+ __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 @@ static inline unsigned long __xchg(unsig
+
+ #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 @@ static inline unsigned long __cmpxchg(vo
+ 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 @@ static inline unsigned long __cmpxchg(vo
+ #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
+--- a/include/asm-i386/unistd.h
++++ b/include/asm-i386/unistd.h
+@@ -448,7 +448,6 @@ asmlinkage int sys_clone(struct pt_regs
+ 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
+--- a/include/asm-ia64/machvec.h
++++ b/include/asm-ia64/machvec.h
+@@ -26,7 +26,7 @@ typedef void ia64_mv_cpu_init_t (void);
+ 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 @@ typedef int ia64_mv_pci_legacy_write_t (
+
+ /* 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
+--- 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 @@ extern ia64_mv_dma_mapping_error sba_dma
+ * 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
+--- 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 @@ extern ia64_mv_dma_sync_sg_for_device h
+ #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
+--- 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 find_memory (void);
+ 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 @@ extern int filter_rsvd_memory (unsigned
+ #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
+--- 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 @@ static inline int pfn_to_nid(unsigned lo
+ #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 @@ static inline int pfn_to_nid(unsigned lo
+ # 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
+--- 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 @@ struct ia64_node_data {
+ */
+ #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
+--- a/include/asm-ia64/page.h
++++ b/include/asm-ia64/page.h
+@@ -102,15 +102,15 @@ do { \
+
+ #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
+--- a/include/asm-ia64/pgtable.h
++++ b/include/asm-ia64/pgtable.h
+@@ -236,9 +236,6 @@ ia64_phys_addr_valid (unsigned long addr
+ #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
+--- a/include/asm-ia64/rwsem.h
++++ b/include/asm-ia64/rwsem.h
+@@ -186,4 +186,9 @@ __downgrade_write (struct rw_semaphore *
+ #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
+--- a/include/asm-ia64/semaphore.h
++++ b/include/asm-ia64/semaphore.h
+@@ -24,8 +24,6 @@ struct semaphore {
+ .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
+--- 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 @@ DECLARE_PER_CPU(struct sn_hub_info_s, __
+
+
+ /*
+- * 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 @@ DECLARE_PER_CPU(short, __sn_cnodeid_to_n
+ #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
+--- 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 @@ extern void sn_dma_flush(unsigned long);
+ #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
+--- a/include/asm-ia64/sn/klconfig.h
++++ b/include/asm-ia64/sn/klconfig.h
+@@ -208,19 +208,6 @@ typedef struct lboard_s {
+ 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 @@ typedef struct klinfo_s {
+ } 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
+--- 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
+--- a/include/asm-ia64/sn/nodepda.h
++++ b/include/asm-ia64/sn/nodepda.h
+@@ -55,7 +55,6 @@ struct nodepda_s {
+ */
+ 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
+--- a/include/asm-ia64/sn/sn_cpuid.h
++++ b/include/asm-ia64/sn/sn_cpuid.h
+@@ -105,7 +105,6 @@ extern short physical_node_map[]; /* ind
+ #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 @@ extern short physical_node_map[]; /* ind
+ * 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
+--- 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 @@ ia64_sn_get_master_baseio_nasid(void)
+ 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 @@ sn_change_memprotect(u64 paddr, u64 len,
+ 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 @@ ia64_sn_sysctl_event_init(nasid_t nasid)
+ 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
+--- a/include/asm-ia64/sn/tioca_provider.h
++++ b/include/asm-ia64/sn/tioca_provider.h
+@@ -182,11 +182,11 @@ tioca_tlbflush(struct tioca_kernel *tioc
+ * 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 @@ tioca_tlbflush(struct tioca_kernel *tioc
+ * 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
+--- a/include/asm-ia64/sn/tiocx.h
++++ b/include/asm-ia64/sn/tiocx.h
+@@ -19,6 +19,7 @@ struct cx_id_s {
+
+ 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 @@ struct cx_drv {
+ 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
+--- 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 @@ enum xpc_retval {
+ 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 @@ typedef void (*xpc_notify_func)(enum xpc
+ *
+ * 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
+--- /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
+--- a/include/asm-ia64/tlb.h
++++ b/include/asm-ia64/tlb.h
+@@ -60,7 +60,6 @@ struct mmu_gather {
+ 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 @@ ia64_tlb_flush_mmu (struct mmu_gather *t
+ 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_gather_mmu (struct mm_struct *mm, un
+ */
+ 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 @@ tlb_finish_mmu (struct mmu_gather *tlb,
+
+ /* 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
+--- a/include/asm-ia64/unistd.h
++++ b/include/asm-ia64/unistd.h
+@@ -383,8 +383,6 @@ struct sigaction;
+ 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
+--- 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
+--- a/include/asm-m32r/mmzone.h
++++ b/include/asm-m32r/mmzone.h
+@@ -21,12 +21,6 @@ extern struct pglist_data *node_data[];
+ __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
+--- a/include/asm-m32r/pgtable.h
++++ b/include/asm-m32r/pgtable.h
+@@ -324,8 +324,6 @@ static inline pte_t pte_modify(pte_t pte
+ 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
+--- a/include/asm-m32r/semaphore.h
++++ b/include/asm-m32r/semaphore.h
+@@ -32,9 +32,6 @@ struct semaphore {
+ .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
+--- a/include/asm-m32r/thread_info.h
++++ b/include/asm-m32r/thread_info.h
+@@ -95,7 +95,7 @@ static inline struct thread_info *curren
+ }
+
+ /* 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
+--- a/include/asm-m32r/unistd.h
++++ b/include/asm-m32r/unistd.h
+@@ -452,7 +452,6 @@ asmlinkage int sys_clone(struct pt_regs
+ 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
+--- a/include/asm-m68k/semaphore.h
++++ b/include/asm-m68k/semaphore.h
+@@ -36,9 +36,6 @@ struct semaphore {
+ .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
+--- 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
+--- a/include/asm-m68k/unistd.h
++++ b/include/asm-m68k/unistd.h
+@@ -444,7 +444,6 @@ asmlinkage long sys_mmap2(
+ 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/anchor.h b/include/asm-m68knommu/anchor.h
+--- a/include/asm-m68knommu/anchor.h
++++ b/include/asm-m68knommu/anchor.h
+@@ -14,7 +14,7 @@
+ /*
+ * Define basic addressing info.
+ */
+-#if defined(CONFIG_MOTOROLA) && defined(CONFIG_M5407)
++#if defined(CONFIG_M5407C3)
+ #define COMEM_BASE 0xFFFF0000 /* Base of CO-MEM address space */
+ #define COMEM_IRQ 25 /* IRQ of anchor part */
+ #else
+@@ -96,7 +96,7 @@
+ * The PCI bus will be limited in what slots will actually be used.
+ * Define valid device numbers for different boards.
+ */
+-#if defined(CONFIG_MOTOROLA) && defined(CONFIG_M5407)
++#if defined(CONFIG_M5407C3)
+ #define COMEM_MINDEV 14 /* Minimum valid DEVICE */
+ #define COMEM_MAXDEV 14 /* Maximum valid DEVICE */
+ #define COMEM_BRIDGEDEV 15 /* Slot bridge is in */
+diff --git a/include/asm-m68knommu/asm-offsets.h b/include/asm-m68knommu/asm-offsets.h
+deleted file mode 100644
+--- a/include/asm-m68knommu/asm-offsets.h
++++ /dev/null
+@@ -1,49 +0,0 @@
+-#ifndef __ASM_OFFSETS_H__
+-#define __ASM_OFFSETS_H__
+-/*
+- * DO NOT MODIFY.
+- *
+- * This file was generated by arch/m68knommu/Makefile
+- *
+- */
+-
+-#define TASK_STATE 0 /* offsetof(struct task_struct, state) */
+-#define TASK_FLAGS 12 /* offsetof(struct task_struct, flags) */
+-#define TASK_PTRACE 16 /* offsetof(struct task_struct, ptrace) */
+-#define TASK_BLOCKED 922 /* offsetof(struct task_struct, blocked) */
+-#define TASK_THREAD 772 /* offsetof(struct task_struct, thread) */
+-#define TASK_THREAD_INFO 4 /* offsetof(struct task_struct, thread_info) */
+-#define TASK_MM 92 /* offsetof(struct task_struct, mm) */
+-#define TASK_ACTIVE_MM 96 /* offsetof(struct task_struct, active_mm) */
+-#define CPUSTAT_SOFTIRQ_PENDING 0 /* offsetof(irq_cpustat_t, __softirq_pending) */
+-#define THREAD_KSP 0 /* offsetof(struct thread_struct, ksp) */
+-#define THREAD_USP 4 /* offsetof(struct thread_struct, usp) */
+-#define THREAD_SR 8 /* offsetof(struct thread_struct, sr) */
+-#define THREAD_FS 10 /* offsetof(struct thread_struct, fs) */
+-#define THREAD_CRP 12 /* offsetof(struct thread_struct, crp) */
+-#define THREAD_ESP0 20 /* offsetof(struct thread_struct, esp0) */
+-#define THREAD_FPREG 24 /* offsetof(struct thread_struct, fp) */
+-#define THREAD_FPCNTL 120 /* offsetof(struct thread_struct, fpcntl) */
+-#define THREAD_FPSTATE 132 /* offsetof(struct thread_struct, fpstate) */
+-#define PT_D0 32 /* offsetof(struct pt_regs, d0) */
+-#define PT_ORIG_D0 36 /* offsetof(struct pt_regs, orig_d0) */
+-#define PT_D1 0 /* offsetof(struct pt_regs, d1) */
+-#define PT_D2 4 /* offsetof(struct pt_regs, d2) */
+-#define PT_D3 8 /* offsetof(struct pt_regs, d3) */
+-#define PT_D4 12 /* offsetof(struct pt_regs, d4) */
+-#define PT_D5 16 /* offsetof(struct pt_regs, d5) */
+-#define PT_A0 20 /* offsetof(struct pt_regs, a0) */
+-#define PT_A1 24 /* offsetof(struct pt_regs, a1) */
+-#define PT_A2 28 /* offsetof(struct pt_regs, a2) */
+-#define PT_PC 48 /* offsetof(struct pt_regs, pc) */
+-#define PT_SR 46 /* offsetof(struct pt_regs, sr) */
+-#define PT_VECTOR 52 /* offsetof(struct pt_regs, pc) + 4 */
+-#define STAT_IRQ 5140 /* offsetof(struct kernel_stat, irqs) */
+-#define SIGSEGV 11 /* SIGSEGV */
+-#define SEGV_MAPERR 196609 /* SEGV_MAPERR */
+-#define SIGTRAP 5 /* SIGTRAP */
+-#define TRAP_TRACE 196610 /* TRAP_TRACE */
+-#define PT_PTRACED 1 /* PT_PTRACED */
+-#define PT_DTRACE 2 /* PT_DTRACE */
+-
+-#endif
+diff --git a/include/asm-m68knommu/atomic.h b/include/asm-m68knommu/atomic.h
+--- a/include/asm-m68knommu/atomic.h
++++ b/include/asm-m68knommu/atomic.h
+@@ -100,7 +100,7 @@ static __inline__ void atomic_set_mask(u
+ #define smp_mb__before_atomic_inc() barrier()
+ #define smp_mb__after_atomic_inc() barrier()
+
+-extern __inline__ int atomic_add_return(int i, atomic_t * v)
++static inline int atomic_add_return(int i, atomic_t * v)
+ {
+ unsigned long temp, flags;
+
+@@ -115,7 +115,7 @@ extern __inline__ int atomic_add_return(
+
+ #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
+
+-extern __inline__ int atomic_sub_return(int i, atomic_t * v)
++static inline int atomic_sub_return(int i, atomic_t * v)
+ {
+ unsigned long temp, flags;
+
+diff --git a/include/asm-m68knommu/coldfire.h b/include/asm-m68knommu/coldfire.h
+--- a/include/asm-m68knommu/coldfire.h
++++ b/include/asm-m68knommu/coldfire.h
+@@ -20,9 +20,14 @@
+ */
+ #define MCF_MBAR 0x10000000
+ #define MCF_MBAR2 0x80000000
++#if defined(CONFIG_M520x)
++#define MCF_IPSBAR 0xFC000000
++#else
+ #define MCF_IPSBAR 0x40000000
++#endif
+
+-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
++#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
++ defined(CONFIG_M520x)
+ #undef MCF_MBAR
+ #define MCF_MBAR MCF_IPSBAR
+ #endif
+@@ -78,7 +83,8 @@
+ * One some ColdFire family members the bus clock (used by internal
+ * peripherals) is not the same as the CPU clock.
+ */
+-#if defined(CONFIG_M523x) || defined(CONFIG_M5249) || defined(CONFIG_M527x)
++#if defined(CONFIG_M523x) || defined(CONFIG_M5249) || defined(CONFIG_M527x) || \
++ defined(CONFIG_M520x)
+ #define MCF_BUSCLK (MCF_CLK / 2)
+ #else
+ #define MCF_BUSCLK MCF_CLK
+diff --git a/include/asm-m68knommu/delay.h b/include/asm-m68knommu/delay.h
+--- a/include/asm-m68knommu/delay.h
++++ b/include/asm-m68knommu/delay.h
+@@ -8,7 +8,7 @@
+
+ #include <asm/param.h>
+
+-extern __inline__ void __delay(unsigned long loops)
++static inline void __delay(unsigned long loops)
+ {
+ #if defined(CONFIG_COLDFIRE)
+ /* The coldfire runs this loop at significantly different speeds
+@@ -48,7 +48,7 @@ extern __inline__ void __delay(unsigned
+
+ extern unsigned long loops_per_jiffy;
+
+-extern __inline__ void _udelay(unsigned long usecs)
++static inline void _udelay(unsigned long usecs)
+ {
+ #if defined(CONFIG_M68328) || defined(CONFIG_M68EZ328) || \
+ defined(CONFIG_M68VZ328) || defined(CONFIG_M68360) || \
+diff --git a/include/asm-m68knommu/ide.h b/include/asm-m68knommu/ide.h
+deleted file mode 100644
+--- a/include/asm-m68knommu/ide.h
++++ /dev/null
+@@ -1,444 +0,0 @@
+-/****************************************************************************/
+-/*
+- * linux/include/asm-m68knommu/ide.h
+- *
+- * Copyright (C) 1994-1996 Linus Torvalds & authors
+- * Copyright (C) 2001 Lineo Inc., davidm at uclinux.org
+- */
+-/****************************************************************************/
+-#ifndef _M68KNOMMU_IDE_H
+-#define _M68KNOMMU_IDE_H
+-
+-#ifdef __KERNEL__
+-/****************************************************************************/
+-
+-#include <linux/config.h>
+-#include <linux/interrupt.h>
+-
+-#include <asm/setup.h>
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-
+-/****************************************************************************/
+-/*
+- * some coldfire specifics
+- */
+-
+-#ifdef CONFIG_COLDFIRE
+-#include <asm/coldfire.h>
+-#include <asm/mcfsim.h>
+-
+-/*
+- * Save some space, only have 1 interface
+- */
+-#define MAX_HWIFS 1 /* we only have one interface for now */
+-
+-#ifdef CONFIG_SECUREEDGEMP3
+-#define MCFSIM_LOCALCS MCFSIM_CSCR4
+-#else
+-#define MCFSIM_LOCALCS MCFSIM_CSCR6
+-#endif
+-
+-#endif /* CONFIG_COLDFIRE */
+-
+-/****************************************************************************/
+-/*
+- * Fix up things that may not have been provided
+- */
+-
+-#ifndef MAX_HWIFS
+-#define MAX_HWIFS 4 /* same as the other archs */
+-#endif
+-
+-#undef SUPPORT_SLOW_DATA_PORTS
+-#define SUPPORT_SLOW_DATA_PORTS 0
+-
+-#undef SUPPORT_VLB_SYNC
+-#define SUPPORT_VLB_SYNC 0
+-
+-/* this definition is used only on startup .. */
+-#undef HD_DATA
+-#define HD_DATA NULL
+-
+-#define DBGIDE(fmt,a...)
+-// #define DBGIDE(fmt,a...) printk(fmt, ##a)
+-#define IDE_INLINE __inline__
+-// #define IDE_INLINE
+-
+-/****************************************************************************/
+-
+-typedef union {
+- unsigned all : 8; /* all of the bits together */
+- struct {
+- unsigned bit7 : 1; /* always 1 */
+- unsigned lba : 1; /* using LBA instead of CHS */
+- unsigned bit5 : 1; /* always 1 */
+- unsigned unit : 1; /* drive select number, 0 or 1 */
+- unsigned head : 4; /* always zeros here */
+- } b;
+-} select_t;
+-
+-/*
+- * our list of ports/irq's for different boards
+- */
+-
+-static struct m68k_ide_defaults {
+- ide_ioreg_t base;
+- int irq;
+-} m68k_ide_defaults[MAX_HWIFS] = {
+-#if defined(CONFIG_SECUREEDGEMP3)
+- { ((ide_ioreg_t)0x30800000), 29 },
+-#elif defined(CONFIG_eLIA)
+- { ((ide_ioreg_t)0x30c00000), 29 },
+-#else
+- { ((ide_ioreg_t)0x0), 0 }
+-#endif
+-};
+-
+-/****************************************************************************/
+-
+-static IDE_INLINE int ide_default_irq(ide_ioreg_t base)
+-{
+- int i;
+-
+- for (i = 0; i < MAX_HWIFS; i++)
+- if (m68k_ide_defaults[i].base == base)
+- return(m68k_ide_defaults[i].irq);
+- return 0;
+-}
+-
+-static IDE_INLINE ide_ioreg_t ide_default_io_base(int index)
+-{
+- if (index >= 0 && index < MAX_HWIFS)
+- return(m68k_ide_defaults[index].base);
+- return 0;
+-}
+-
+-
+-/*
+- * Set up a hw structure for a specified data port, control port and IRQ.
+- * This should follow whatever the default interface uses.
+- */
+-static IDE_INLINE void ide_init_hwif_ports(
+- hw_regs_t *hw,
+- ide_ioreg_t data_port,
+- ide_ioreg_t ctrl_port,
+- int *irq)
+-{
+- ide_ioreg_t reg = data_port;
+- int i;
+-
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hw->io_ports[i] = reg;
+- reg += 1;
+- }
+- if (ctrl_port) {
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+- } else {
+- hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0xe;
+- }
+-}
+-
+-#define ide_init_default_irq(base) ide_default_irq(base)
+-
+-static IDE_INLINE int
+-ide_request_irq(
+- unsigned int irq,
+- void (*handler)(int, void *, struct pt_regs *),
+- unsigned long flags,
+- const char *device,
+- void *dev_id)
+-{
+-#ifdef CONFIG_COLDFIRE
+- mcf_autovector(irq);
+-#endif
+- return(request_irq(irq, handler, flags, device, dev_id));
+-}
+-
+-
+-static IDE_INLINE void
+-ide_free_irq(unsigned int irq, void *dev_id)
+-{
+- free_irq(irq, dev_id);
+-}
+-
+-
+-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)
+-{
+-}
+-
+-
+-static IDE_INLINE void
+-ide_release_region(ide_ioreg_t from, unsigned int extent)
+-{
+-}
+-
+-
+-static IDE_INLINE void
+-ide_fix_driveid(struct hd_driveid *id)
+-{
+-#ifdef CONFIG_COLDFIRE
+- int i, n;
+- unsigned short *wp = (unsigned short *) id;
+- int avoid[] = {49, 51, 52, 59, -1 }; /* do not swap these words */
+-
+- /* Need to byte swap shorts, but not char fields */
+- for (i = n = 0; i < sizeof(*id) / sizeof(*wp); i++, wp++) {
+- if (avoid[n] == i) {
+- n++;
+- continue;
+- }
+- *wp = ((*wp & 0xff) << 8) | ((*wp >> 8) & 0xff);
+- }
+- /* have to word swap the one 32 bit field */
+- id->lba_capacity = ((id->lba_capacity & 0xffff) << 16) |
+- ((id->lba_capacity >> 16) & 0xffff);
+-#endif
+-}
+-
+-
+-static IDE_INLINE void
+-ide_release_lock (int *ide_lock)
+-{
+-}
+-
+-
+-static IDE_INLINE void
+-ide_get_lock(
+- int *ide_lock,
+- void (*handler)(int, void *, struct pt_regs *),
+- void *data)
+-{
+-}
+-
+-
+-#define ide_ack_intr(hwif) \
+- ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
+-#define ide__sti() __sti()
+-
+-/****************************************************************************/
+-/*
+- * System specific IO requirements
+- */
+-
+-#ifdef CONFIG_COLDFIRE
+-
+-#ifdef CONFIG_SECUREEDGEMP3
+-
+-/* Replace standard IO functions for funky mapping of MP3 board */
+-#undef outb
+-#undef outb_p
+-#undef inb
+-#undef inb_p
+-
+-#define outb(v, a) ide_outb(v, (unsigned long) (a))
+-#define outb_p(v, a) ide_outb(v, (unsigned long) (a))
+-#define inb(a) ide_inb((unsigned long) (a))
+-#define inb_p(a) ide_inb((unsigned long) (a))
+-
+-#define ADDR8_PTR(addr) (((addr) & 0x1) ? (0x8000 + (addr) - 1) : (addr))
+-#define ADDR16_PTR(addr) (addr)
+-#define ADDR32_PTR(addr) (addr)
+-#define SWAP8(w) ((((w) & 0xffff) << 8) | (((w) & 0xffff) >> 8))
+-#define SWAP16(w) (w)
+-#define SWAP32(w) (w)
+-
+-
+-static IDE_INLINE void
+-ide_outb(unsigned int val, unsigned int addr)
+-{
+- volatile unsigned short *rp;
+-
+- DBGIDE("%s(val=%x,addr=%x)\n", __FUNCTION__, val, addr);
+- rp = (volatile unsigned short *) ADDR8_PTR(addr);
+- *rp = SWAP8(val);
+-}
+-
+-
+-static IDE_INLINE int
+-ide_inb(unsigned int addr)
+-{
+- volatile unsigned short *rp, val;
+-
+- DBGIDE("%s(addr=%x)\n", __FUNCTION__, addr);
+- rp = (volatile unsigned short *) ADDR8_PTR(addr);
+- val = *rp;
+- return(SWAP8(val));
+-}
+-
+-
+-static IDE_INLINE void
+-ide_outw(unsigned int val, unsigned int addr)
+-{
+- volatile unsigned short *rp;
+-
+- DBGIDE("%s(val=%x,addr=%x)\n", __FUNCTION__, val, addr);
+- rp = (volatile unsigned short *) ADDR16_PTR(addr);
+- *rp = SWAP16(val);
+-}
+-
+-static IDE_INLINE void
+-ide_outsw(unsigned int addr, const void *vbuf, unsigned long len)
+-{
+- volatile unsigned short *rp, val;
+- unsigned short *buf;
+-
+- DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
+- buf = (unsigned short *) vbuf;
+- rp = (volatile unsigned short *) ADDR16_PTR(addr);
+- for (; (len > 0); len--) {
+- val = *buf++;
+- *rp = SWAP16(val);
+- }
+-}
+-
+-static IDE_INLINE int
+-ide_inw(unsigned int addr)
+-{
+- volatile unsigned short *rp, val;
+-
+- DBGIDE("%s(addr=%x)\n", __FUNCTION__, addr);
+- rp = (volatile unsigned short *) ADDR16_PTR(addr);
+- val = *rp;
+- return(SWAP16(val));
+-}
+-
+-static IDE_INLINE void
+-ide_insw(unsigned int addr, void *vbuf, unsigned long len)
+-{
+- volatile unsigned short *rp;
+- unsigned short w, *buf;
+-
+- DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
+- buf = (unsigned short *) vbuf;
+- rp = (volatile unsigned short *) ADDR16_PTR(addr);
+- for (; (len > 0); len--) {
+- w = *rp;
+- *buf++ = SWAP16(w);
+- }
+-}
+-
+-static IDE_INLINE void
+-ide_insl(unsigned int addr, void *vbuf, unsigned long len)
+-{
+- volatile unsigned long *rp;
+- unsigned long w, *buf;
+-
+- DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
+- buf = (unsigned long *) vbuf;
+- rp = (volatile unsigned long *) ADDR32_PTR(addr);
+- for (; (len > 0); len--) {
+- w = *rp;
+- *buf++ = SWAP32(w);
+- }
+-}
+-
+-static IDE_INLINE void
+-ide_outsl(unsigned int addr, const void *vbuf, unsigned long len)
+-{
+- volatile unsigned long *rp, val;
+- unsigned long *buf;
+-
+- DBGIDE("%s(addr=%x,vbuf=%p,len=%x)\n", __FUNCTION__, addr, vbuf, len);
+- buf = (unsigned long *) vbuf;
+- rp = (volatile unsigned long *) ADDR32_PTR(addr);
+- for (; (len > 0); len--) {
+- val = *buf++;
+- *rp = SWAP32(val);
+- }
+-}
+-
+-#elif CONFIG_eLIA
+-
+-/* 8/16 bit acesses are controlled by flicking bits in the CS register */
+-#define ACCESS_MODE_16BIT() \
+- *((volatile unsigned short *) (MCF_MBAR + MCFSIM_LOCALCS)) = 0x0080
+-#define ACCESS_MODE_8BIT() \
+- *((volatile unsigned short *) (MCF_MBAR + MCFSIM_LOCALCS)) = 0x0040
+-
+-
+-static IDE_INLINE void
+-ide_outw(unsigned int val, unsigned int addr)
+-{
+- ACCESS_MODE_16BIT();
+- outw(val, addr);
+- ACCESS_MODE_8BIT();
+-}
+-
+-static IDE_INLINE void
+-ide_outsw(unsigned int addr, const void *vbuf, unsigned long len)
+-{
+- ACCESS_MODE_16BIT();
+- outsw(addr, vbuf, len);
+- ACCESS_MODE_8BIT();
+-}
+-
+-static IDE_INLINE int
+-ide_inw(unsigned int addr)
+-{
+- int ret;
+-
+- ACCESS_MODE_16BIT();
+- ret = inw(addr);
+- ACCESS_MODE_8BIT();
+- return(ret);
+-}
+-
+-static IDE_INLINE void
+-ide_insw(unsigned int addr, void *vbuf, unsigned long len)
+-{
+- ACCESS_MODE_16BIT();
+- insw(addr, vbuf, len);
+- ACCESS_MODE_8BIT();
+-}
+-
+-static IDE_INLINE void
+-ide_insl(unsigned int addr, void *vbuf, unsigned long len)
+-{
+- ACCESS_MODE_16BIT();
+- insl(addr, vbuf, len);
+- ACCESS_MODE_8BIT();
+-}
+-
+-static IDE_INLINE void
+-ide_outsl(unsigned int addr, const void *vbuf, unsigned long len)
+-{
+- ACCESS_MODE_16BIT();
+- outsl(addr, vbuf, len);
+- ACCESS_MODE_8BIT();
+-}
+-
+-#endif /* CONFIG_SECUREEDGEMP3 */
+-
+-#undef outw
+-#undef outw_p
+-#undef outsw
+-#undef inw
+-#undef inw_p
+-#undef insw
+-#undef insl
+-#undef outsl
+-
+-#define outw(v, a) ide_outw(v, (unsigned long) (a))
+-#define outw_p(v, a) ide_outw(v, (unsigned long) (a))
+-#define outsw(a, b, n) ide_outsw((unsigned long) (a), b, n)
+-#define inw(a) ide_inw((unsigned long) (a))
+-#define inw_p(a) ide_inw((unsigned long) (a))
+-#define insw(a, b, n) ide_insw((unsigned long) (a), b, n)
+-#define insl(a, b, n) ide_insl((unsigned long) (a), b, n)
+-#define outsl(a, b, n) ide_outsl((unsigned long) (a), b, n)
+-
+-#endif CONFIG_COLDFIRE
+-
+-/****************************************************************************/
+-#endif /* __KERNEL__ */
+-#endif /* _M68KNOMMU_IDE_H */
+-/****************************************************************************/
+diff --git a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
+--- a/include/asm-m68knommu/io.h
++++ b/include/asm-m68knommu/io.h
+@@ -147,19 +147,19 @@ static inline void io_insl(unsigned int
+ extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
+ extern void __iounmap(void *addr, unsigned long size);
+
+-extern inline void *ioremap(unsigned long physaddr, unsigned long size)
++static inline void *ioremap(unsigned long physaddr, unsigned long size)
+ {
+ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
+ }
+-extern inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
++static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
+ {
+ return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
+ }
+-extern inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
++static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
+ {
+ return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
+ }
+-extern inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
++static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
+ {
+ return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
+ }
+diff --git a/include/asm-m68knommu/m520xsim.h b/include/asm-m68knommu/m520xsim.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-m68knommu/m520xsim.h
+@@ -0,0 +1,54 @@
++/****************************************************************************/
++
++/*
++ * m520xsim.h -- ColdFire 5207/5208 System Integration Module support.
++ *
++ * (C) Copyright 2005, Intec Automation (mike at steroidmicros.com)
++ */
++
++/****************************************************************************/
++#ifndef m520xsim_h
++#define m520xsim_h
++/****************************************************************************/
++
++#include <linux/config.h>
++
++/*
++ * Define the 5282 SIM register set addresses.
++ */
++#define MCFICM_INTC0 0x48000 /* Base for Interrupt Ctrl 0 */
++#define MCFINTC_IPRH 0x00 /* Interrupt pending 32-63 */
++#define MCFINTC_IPRL 0x04 /* Interrupt pending 1-31 */
++#define MCFINTC_IMRH 0x08 /* Interrupt mask 32-63 */
++#define MCFINTC_IMRL 0x0c /* Interrupt mask 1-31 */
++#define MCFINTC_INTFRCH 0x10 /* Interrupt force 32-63 */
++#define MCFINTC_INTFRCL 0x14 /* Interrupt force 1-31 */
++#define MCFINTC_ICR0 0x40 /* Base ICR register */
++
++#define MCFINT_VECBASE 64
++#define MCFINT_UART0 26 /* Interrupt number for UART0 */
++#define MCFINT_UART1 27 /* Interrupt number for UART1 */
++#define MCFINT_UART2 28 /* Interrupt number for UART2 */
++#define MCFINT_QSPI 31 /* Interrupt number for QSPI */
++#define MCFINT_PIT1 4 /* Interrupt number for PIT1 (PIT0 in processor) */
++
++
++#define MCF_GPIO_PAR_UART (0xA4036)
++#define MCF_GPIO_PAR_FECI2C (0xA4033)
++#define MCF_GPIO_PAR_FEC (0xA4038)
++
++#define MCF_GPIO_PAR_UART_PAR_URXD0 (0x0001)
++#define MCF_GPIO_PAR_UART_PAR_UTXD0 (0x0002)
++
++#define MCF_GPIO_PAR_UART_PAR_URXD1 (0x0040)
++#define MCF_GPIO_PAR_UART_PAR_UTXD1 (0x0080)
++
++#define MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2 (0x02)
++#define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 (0x04)
++
++#define ICR_INTRCONF 0x05
++#define MCFPIT_IMR MCFINTC_IMRL
++#define MCFPIT_IMR_IBIT (1 << MCFINT_PIT1)
++
++/****************************************************************************/
++#endif /* m520xsim_h */
+diff --git a/include/asm-m68knommu/mcfcache.h b/include/asm-m68knommu/mcfcache.h
+--- a/include/asm-m68knommu/mcfcache.h
++++ b/include/asm-m68knommu/mcfcache.h
+@@ -117,6 +117,20 @@
+ .endm
+ #endif /* CONFIG_M5407 */
+
++#if defined(CONFIG_M520x)
++.macro CACHE_ENABLE
++ move.l #0x01000000,%d0 /* invalidate whole cache */
++ movec %d0,%CACR
++ nop
++ move.l #0x0000c000,%d0 /* set SDRAM cached (write-thru) */
++ movec %d0,%ACR0
++ move.l #0x00000000,%d0 /* no other regions cached */
++ movec %d0,%ACR1
++ move.l #0x80400000,%d0 /* enable 8K instruction cache */
++ movec %d0,%CACR
++ nop
++.endm
++#endif /* CONFIG_M520x */
+
+ /****************************************************************************/
+ #endif /* __M68KNOMMU_MCFCACHE_H */
+diff --git a/include/asm-m68knommu/mcfne.h b/include/asm-m68knommu/mcfne.h
+--- a/include/asm-m68knommu/mcfne.h
++++ b/include/asm-m68knommu/mcfne.h
+@@ -35,7 +35,7 @@
+ * Define the basic hardware resources of NE2000 boards.
+ */
+
+-#if defined(CONFIG_M5206) && defined(CONFIG_ARNEWSH)
++#if defined(CONFIG_ARN5206)
+ #define NE2000_ADDR 0x40000300
+ #define NE2000_ODDOFFSET 0x00010000
+ #define NE2000_IRQ_VECTOR 0xf0
+@@ -44,7 +44,7 @@
+ #define NE2000_BYTE volatile unsigned short
+ #endif
+
+-#if defined(CONFIG_M5206e) && defined(CONFIG_MOTOROLA)
++#if defined(CONFIG_M5206eC3)
+ #define NE2000_ADDR 0x40000300
+ #define NE2000_ODDOFFSET 0x00010000
+ #define NE2000_IRQ_VECTOR 0x1c
+@@ -61,7 +61,7 @@
+ #define NE2000_BYTE volatile unsigned char
+ #endif
+
+-#if defined(CONFIG_M5206e) && defined(CONFIG_CFV240)
++#if defined(CONFIG_CFV240)
+ #define NE2000_ADDR 0x40010000
+ #define NE2000_ADDR1 0x40010001
+ #define NE2000_ODDOFFSET 0x00000000
+@@ -72,7 +72,7 @@
+ #define NE2000_BYTE volatile unsigned char
+ #endif
+
+-#if defined(CONFIG_M5307) && defined(CONFIG_MOTOROLA)
++#if defined(CONFIG_M5307C3)
+ #define NE2000_ADDR 0x40000300
+ #define NE2000_ODDOFFSET 0x00010000
+ #define NE2000_IRQ_VECTOR 0x1b
+@@ -114,7 +114,7 @@
+ #define RSWAP(w) (((w) << 8) | ((w) >> 8))
+ #endif
+
+-#if defined(CONFIG_M5307) && defined(CONFIG_ARNEWSH)
++#if defined(CONFIG_ARN5307)
+ #define NE2000_ADDR 0xfe600300
+ #define NE2000_ODDOFFSET 0x00010000
+ #define NE2000_IRQ_VECTOR 0x1b
+@@ -123,7 +123,7 @@
+ #define NE2000_BYTE volatile unsigned short
+ #endif
+
+-#if defined(CONFIG_M5407)
++#if defined(CONFIG_M5407C3)
+ #define NE2000_ADDR 0x40000300
+ #define NE2000_ODDOFFSET 0x00010000
+ #define NE2000_IRQ_VECTOR 0x1b
+@@ -264,7 +264,7 @@ void ne2000_outsw(unsigned int addr, con
+ * Minor differences between the different board types.
+ */
+
+-#if defined(CONFIG_M5206) && defined(CONFIG_ARNEWSH)
++#if defined(CONFIG_ARN5206)
+ void ne2000_irqsetup(int irq)
+ {
+ volatile unsigned char *icrp;
+@@ -275,7 +275,7 @@ void ne2000_irqsetup(int irq)
+ }
+ #endif
+
+-#if defined(CONFIG_M5206e) && defined(CONFIG_MOTOROLA)
++#if defined(CONFIG_M5206eC3)
+ void ne2000_irqsetup(int irq)
+ {
+ volatile unsigned char *icrp;
+@@ -286,7 +286,7 @@ void ne2000_irqsetup(int irq)
+ }
+ #endif
+
+-#if defined(CONFIG_M5206e) && defined(CONFIG_CFV240)
++#if defined(CONFIG_CFV240)
+ void ne2000_irqsetup(int irq)
+ {
+ volatile unsigned char *icrp;
+diff --git a/include/asm-m68knommu/mcfpit.h b/include/asm-m68knommu/mcfpit.h
+--- a/include/asm-m68knommu/mcfpit.h
++++ b/include/asm-m68knommu/mcfpit.h
+@@ -14,13 +14,17 @@
+ #include <linux/config.h>
+
+ /*
+- * Get address specific defines for the 5270/5271 and 5280/5282.
++ * Get address specific defines for the 5270/5271, 5280/5282, and 5208.
+ */
++#if defined(CONFIG_M520x)
++#define MCFPIT_BASE1 0x00080000 /* Base address of TIMER1 */
++#define MCFPIT_BASE2 0x00084000 /* Base address of TIMER2 */
++#else
+ #define MCFPIT_BASE1 0x00150000 /* Base address of TIMER1 */
+ #define MCFPIT_BASE2 0x00160000 /* Base address of TIMER2 */
+ #define MCFPIT_BASE3 0x00170000 /* Base address of TIMER3 */
+ #define MCFPIT_BASE4 0x00180000 /* Base address of TIMER4 */
+-
++#endif
+
+ /*
+ * Define the PIT timer register set addresses.
+diff --git a/include/asm-m68knommu/mcfsim.h b/include/asm-m68knommu/mcfsim.h
+--- a/include/asm-m68knommu/mcfsim.h
++++ b/include/asm-m68knommu/mcfsim.h
+@@ -22,6 +22,8 @@
+ #include <asm/m5204sim.h>
+ #elif defined(CONFIG_M5206) || defined(CONFIG_M5206e)
+ #include <asm/m5206sim.h>
++#elif defined(CONFIG_M520x)
++#include <asm/m520xsim.h>
+ #elif defined(CONFIG_M523x)
+ #include <asm/m523xsim.h>
+ #elif defined(CONFIG_M5249)
+@@ -99,6 +101,19 @@
+ #define MCFSIM_IMR_MASKALL 0x3ffe /* All intr sources */
+ #endif
+
++/*
++ * PIT interrupt settings, if not found in mXXXXsim.h file.
++ */
++#ifndef ICR_INTRCONF
++#define ICR_INTRCONF 0x2b /* PIT1 level 5, priority 3 */
++#endif
++#ifndef MCFPIT_IMR
++#define MCFPIT_IMR MCFINTC_IMRH
++#endif
++#ifndef MCFPIT_IMR_IBIT
++#define MCFPIT_IMR_IBIT (1 << (MCFINT_PIT1 - 32))
++#endif
++
+
+ #ifndef __ASSEMBLY__
+ /*
+diff --git a/include/asm-m68knommu/mcfuart.h b/include/asm-m68knommu/mcfuart.h
+--- a/include/asm-m68knommu/mcfuart.h
++++ b/include/asm-m68knommu/mcfuart.h
+@@ -41,6 +41,10 @@
+ #define MCFUART_BASE1 0x1c0 /* Base address of UART1 */
+ #define MCFUART_BASE2 0x200 /* Base address of UART2 */
+ #endif
++#elif defined(CONFIG_M520x)
++#define MCFUART_BASE1 0x60000 /* Base address of UART1 */
++#define MCFUART_BASE2 0x64000 /* Base address of UART2 */
++#define MCFUART_BASE3 0x68000 /* Base address of UART2 */
+ #endif
+
+
+diff --git a/include/asm-m68knommu/mcfwdebug.h b/include/asm-m68knommu/mcfwdebug.h
+--- a/include/asm-m68knommu/mcfwdebug.h
++++ b/include/asm-m68knommu/mcfwdebug.h
+@@ -90,7 +90,7 @@
+ * that the debug module instructions (2 longs) must be long word aligned and
+ * some pointer fiddling is performed to ensure this.
+ */
+-extern inline void wdebug(int reg, unsigned long data) {
++static inline void wdebug(int reg, unsigned long data) {
+ unsigned short dbg_spc[6];
+ unsigned short *dbg;
+
+diff --git a/include/asm-m68knommu/mmu_context.h b/include/asm-m68knommu/mmu_context.h
+--- a/include/asm-m68knommu/mmu_context.h
++++ b/include/asm-m68knommu/mmu_context.h
+@@ -10,7 +10,7 @@ static inline void enter_lazy_tlb(struct
+ {
+ }
+
+-extern inline int
++static inline int
+ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+ {
+ // mm->context = virt_to_phys(mm->pgd);
+@@ -25,7 +25,7 @@ static inline void switch_mm(struct mm_s
+
+ #define deactivate_mm(tsk,mm) do { } while (0)
+
+-extern inline void activate_mm(struct mm_struct *prev_mm,
++static inline void activate_mm(struct mm_struct *prev_mm,
+ struct mm_struct *next_mm)
+ {
+ }
+diff --git a/include/asm-m68knommu/processor.h b/include/asm-m68knommu/processor.h
+--- a/include/asm-m68knommu/processor.h
++++ b/include/asm-m68knommu/processor.h
+@@ -21,7 +21,7 @@
+ #include <asm/ptrace.h>
+ #include <asm/current.h>
+
+-extern inline unsigned long rdusp(void)
++static inline unsigned long rdusp(void)
+ {
+ #ifdef CONFIG_COLDFIRE
+ extern unsigned int sw_usp;
+@@ -33,7 +33,7 @@ extern inline unsigned long rdusp(void)
+ #endif
+ }
+
+-extern inline void wrusp(unsigned long usp)
++static inline void wrusp(unsigned long usp)
+ {
+ #ifdef CONFIG_COLDFIRE
+ extern unsigned int sw_usp;
+diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
+--- a/include/asm-m68knommu/semaphore.h
++++ b/include/asm-m68knommu/semaphore.h
+@@ -35,16 +35,13 @@ struct semaphore {
+ .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)
+
+ #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+ #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+-extern inline void sema_init (struct semaphore *sem, int val)
++static inline void sema_init (struct semaphore *sem, int val)
+ {
+ *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+ }
+@@ -76,7 +73,7 @@ extern spinlock_t semaphore_wake_lock;
+ * "down_failed" is a special asm handler that calls the C
+ * routine that actually waits. See arch/m68k/lib/semaphore.S
+ */
+-extern inline void down(struct semaphore * sem)
++static inline void down(struct semaphore * sem)
+ {
+ might_sleep();
+ __asm__ __volatile__(
+@@ -91,7 +88,7 @@ extern inline void down(struct semaphore
+ : "cc", "%a0", "%a1", "memory");
+ }
+
+-extern inline int down_interruptible(struct semaphore * sem)
++static inline int down_interruptible(struct semaphore * sem)
+ {
+ int ret;
+
+@@ -110,7 +107,7 @@ extern inline int down_interruptible(str
+ return(ret);
+ }
+
+-extern inline int down_trylock(struct semaphore * sem)
++static inline int down_trylock(struct semaphore * sem)
+ {
+ register struct semaphore *sem1 __asm__ ("%a1") = sem;
+ register int result __asm__ ("%d0");
+@@ -138,7 +135,7 @@ extern inline int down_trylock(struct se
+ * The default case (no contention) will result in NO
+ * jumps for both down() and up().
+ */
+-extern inline void up(struct semaphore * sem)
++static inline void up(struct semaphore * sem)
+ {
+ __asm__ __volatile__(
+ "| atomic up operation\n\t"
+diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
+--- a/include/asm-m68knommu/system.h
++++ b/include/asm-m68knommu/system.h
+@@ -312,6 +312,19 @@ cmpxchg(volatile int *p, int old, int ne
+ moveb #0x80, (%a0); \
+ "); \
+ })
++#elif defined(CONFIG_M520x)
++ /*
++ * The MCF5208 has a bit (SOFTRST) in memory (Reset Control Register
++ * RCR), that when set, resets the MCF5208.
++ */
++#define HARD_RESET_NOW() \
++({ \
++ unsigned char volatile *reset; \
++ asm("move.w #0x2700, %sr"); \
++ reset = ((volatile unsigned short *)(MCF_IPSBAR + 0xA0000)); \
++ while(1) \
++ *reset |= 0x80; \
++})
+ #else
+ #define HARD_RESET_NOW() ({ \
+ asm(" \
+diff --git a/include/asm-m68knommu/tlbflush.h b/include/asm-m68knommu/tlbflush.h
+--- a/include/asm-m68knommu/tlbflush.h
++++ b/include/asm-m68knommu/tlbflush.h
+@@ -47,12 +47,12 @@ static inline void flush_tlb_range(struc
+ BUG();
+ }
+
+-extern inline void flush_tlb_kernel_page(unsigned long addr)
++static inline void flush_tlb_kernel_page(unsigned long addr)
+ {
+ BUG();
+ }
+
+-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
++static inline void flush_tlb_pgtables(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+ {
+ BUG();
+diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h
+--- a/include/asm-m68knommu/unistd.h
++++ b/include/asm-m68knommu/unistd.h
+@@ -504,7 +504,6 @@ asmlinkage long sys_mmap2(unsigned long
+ 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
+--- /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
+--- 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
+--- a/include/asm-mips/asm.h
++++ b/include/asm-mips/asm.h
+@@ -107,6 +107,7 @@ symbol = value
+ /*
+ * Print formatted string
+ */
++#ifdef CONFIG_PRINTK
+ #define PRINT(string) \
+ .set push; \
+ .set reorder; \
+@@ -114,6 +115,9 @@ symbol = value
+ 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
+--- a/include/asm-mips/atomic.h
++++ b/include/asm-mips/atomic.h
+@@ -62,20 +62,24 @@ static __inline__ void atomic_add(int i,
+ 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 @@ static __inline__ void atomic_sub(int i,
+ 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 @@ static __inline__ int atomic_add_return(
+ 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 @@ static __inline__ int atomic_add_return(
+ 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 @@ static __inline__ int atomic_sub_return(
+ 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 @@ static __inline__ int atomic_sub_return(
+ 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 @@ static __inline__ int atomic_sub_if_posi
+ 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 @@ static __inline__ int atomic_sub_if_posi
+ " 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 @@ static __inline__ int atomic_sub_if_posi
+ 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 @@ static __inline__ int atomic_sub_if_posi
+ " 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 @@ static __inline__ void atomic64_add(long
+ 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 @@ static __inline__ void atomic64_sub(long
+ 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 @@ static __inline__ long atomic64_add_retu
+ 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 @@ static __inline__ long atomic64_add_retu
+ 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 @@ static __inline__ long atomic64_sub_retu
+ 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 @@ static __inline__ long atomic64_sub_retu
+ 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 @@ static __inline__ long atomic64_sub_if_p
+ 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 @@ static __inline__ long atomic64_sub_if_p
+ " 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 @@ static __inline__ long atomic64_sub_if_p
+ 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 @@ static __inline__ long atomic64_sub_if_p
+ " 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
+--- 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 @@ static inline void set_bit(unsigned long
+
+ 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 @@ static inline void clear_bit(unsigned lo
+
+ 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 @@ static inline void change_bit(unsigned l
+ 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 @@ static inline void change_bit(unsigned l
+ 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 @@ static inline int test_and_set_bit(unsig
+ 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 @@ static inline int test_and_set_bit(unsig
+ 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 @@ static inline int test_and_clear_bit(uns
+ 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 @@ static inline int test_and_clear_bit(uns
+ 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 @@ static inline int test_and_change_bit(un
+ 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 @@ static inline int test_and_change_bit(un
+ 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 @@ static inline int test_bit(unsigned long
+ }
+
+ /*
+- * 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 @@ static inline unsigned long ffz(unsigned
+ 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)
++{
++ if (!word)
++ return 0;
++
++ return __ffs(word) + 1;
++}
++
++/*
++ * 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);
++}
++
++/*
++ * 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)
+ {
+- return ffz(~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.
++ * 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;
++}
+
+-#define fls(x) generic_fls(x)
+
+ /*
+ * find_next_zero_bit - find the first zero bit in a memory region
+@@ -704,17 +832,6 @@ static inline int sched_find_first_bit(c
+ }
+
+ /*
+- * 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- a/include/asm-mips/cacheflush.h
++++ b/include/asm-mips/cacheflush.h
+@@ -49,17 +49,29 @@ static inline void flush_dcache_page(str
+
+ 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 @@ extern void (*flush_data_cache_page)(uns
+ #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
+--- a/include/asm-mips/checksum.h
++++ b/include/asm-mips/checksum.h
+@@ -34,8 +34,9 @@ unsigned int csum_partial(const unsigned
+ * 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 @@ unsigned int csum_partial_copy_nocheck(c
+ 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 @@ static inline unsigned int csum_tcpudp_n
+ 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\t%0, %3\n\t"
+- "sltu\t$1, %0, %3\n\t"
+- "addu\t%0, $1\n\t"
+-
+- "addu\t%0, %4\n\t"
+- "sltu\t$1, %0, %4\n\t"
+- "addu\t%0, $1\n\t"
++ " addu %0, %2 \n"
++ " sltu $1, %0, %2 \n"
++ " addu %0, $1 \n"
++
++ " addu %0, %3 \n"
++ " sltu $1, %0, %3 \n"
++ " addu %0, $1 \n"
++
++ " 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 @@ static __inline__ unsigned short int csu
+ 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"
+-
+- "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"
+-
+- "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\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\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\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\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\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\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"
++ " .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 %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 %1, 4(%2) \n"
++ " addu %0, $1 \n"
++ " addu %0, %1 \n"
++ " sltu $1, %0, %1 \n"
++
++ " lw %1, 8(%2) \n"
++ " addu %0, $1 \n"
++ " addu %0, %1 \n"
++ " sltu $1, %0, %1 \n"
++
++ " lw %1, 12(%2) \n"
++ " addu %0, $1 \n"
++ " addu %0, %1 \n"
++ " sltu $1, %0, %1 \n"
++
++ " lw %1, 0(%3) \n"
++ " addu %0, $1 \n"
++ " addu %0, %1 \n"
++ " sltu $1, %0, %1 \n"
++
++ " lw %1, 4(%3) \n"
++ " addu %0, $1 \n"
++ " addu %0, %1 \n"
++ " sltu $1, %0, %1 \n"
++
++ " lw %1, 8(%3) \n"
++ " addu %0, $1 \n"
++ " addu %0, %1 \n"
++ " sltu $1, %0, %1 \n"
++
++ " 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
+--- 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 @@ do { \
+ 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
+--- /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
+--- a/include/asm-mips/compat.h
++++ b/include/asm-mips/compat.h
+@@ -15,10 +15,10 @@ typedef s32 compat_clock_t;
+ 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 @@ struct compat_stat {
+ 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
+--- 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
+--- 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 @@ struct cpuinfo_mips {
+ * 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
+--- 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 at 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
+--- a/include/asm-mips/dec/ecc.h
++++ b/include/asm-mips/dec/ecc.h
+@@ -49,7 +49,8 @@ struct pt_regs;
+
+ 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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 @@ extern int (*__pmax_close)(int);
+ * 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 _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(_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 __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
+--- /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
+--- 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_base_addr(in
+ */
+ 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
+--- 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 @@ static inline void __udelay(unsigned lon
+ __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
+--- 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
+--- /dev/null
++++ b/include/asm-mips/dsp.h
+@@ -0,0 +1,83 @@
++/*
++ * Copyright (C) 2005 Mips Technologies
++ * Author: Chris Dearman, chris at 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
+--- 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 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
+
+ #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
+--- 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
+--- 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 @@ struct flock {
+
+ #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
+--- a/include/asm-mips/fixmap.h
++++ b/include/asm-mips/fixmap.h
+@@ -107,4 +107,11 @@ static inline unsigned long virt_to_fix(
+ 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
+--- a/include/asm-mips/fpu.h
++++ b/include/asm-mips/fpu.h
+@@ -80,9 +80,14 @@ do { \
+
+ #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 void restore_fp(struct tas
+ 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
+--- 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
+--- 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 @@ futex_atomic_op_inuser (int encoded_op,
+
+ 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
+--- 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 @@ __asm__(
+ " .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 @@ __asm__(
+ ".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 @@ __asm__(
+ #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 @@ __asm__(
+ " \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 @@ __asm__(
+ #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 @@ __asm__(
+ #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
+--- a/include/asm-mips/highmem.h
++++ b/include/asm-mips/highmem.h
+@@ -75,6 +75,7 @@ static inline void *kmap_atomic(struct p
+ }
+
+ 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 *__kmap(struct page *page);
+ 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
+--- a/include/asm-mips/inst.h
++++ b/include/asm-mips/inst.h
+@@ -28,7 +28,7 @@ enum major_op {
+ 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 @@ enum rt_op {
+ 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
+--- 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 @@ static inline void local_irq_enable(void
+ * 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 @@ static inline void local_irq_disable(voi
+ }
+
+ __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 @@ __asm__ __volatile__( \
+ : "=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 @@ __asm__ __volatile__( \
+ : "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
+--- 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 @@ typedef struct inventory_s {
+ } 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
+--- 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 @@ extern unsigned long isa_slot_offset;
+ */
+ #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 @@ static inline void * __ioremap_mode(phys
+ */
+ 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 * __ioremap_mode(phys
+
+ 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 @@ static inline type pfx##read##bwlq(volat
+ 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 @@ static inline type pfx##read##bwlq(volat
+ ".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 @@ static inline void pfx##out##bwlq##p(typ
+ \
+ __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 @@ static inline type pfx##in##bwlq##p(unsi
+ 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 @@ static inline type pfx##in##bwlq##p(unsi
+ \
+ __BUILD_MEMORY_SINGLE(bus, bwlq, type, 1)
+
+-#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(bwlq, type) \
++#define BUILDIO_MEM(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 @@ static inline void writes##bwlq(volatile
+ volatile type *__addr = addr; \
+ \
+ while (count--) { \
+- __raw_write##bwlq(*__addr, mem); \
++ mem_write##bwlq(*__addr, mem); \
+ __addr++; \
+ } \
+ } \
+@@ -433,20 +476,20 @@ static inline void reads##bwlq(volatile
+ 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 @@ static inline void ins##bwlq(unsigned lo
+ volatile type *__addr = addr; \
+ \
+ while (count--) { \
+- *__addr = __raw_in##bwlq(port); \
++ *__addr = mem_in##bwlq(port); \
+ __addr++; \
+ } \
+ }
+@@ -470,15 +513,26 @@ __BUILD_IOPORT_STRING(bwlq, type)
+ 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
+--- a/include/asm-mips/irq.h
++++ b/include/asm-mips/irq.h
+@@ -24,11 +24,9 @@ static inline int irq_canonicalize(int i
+
+ 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
+--- a/include/asm-mips/jmr3927/jmr3927.h
++++ b/include/asm-mips/jmr3927/jmr3927.h
+@@ -202,20 +202,6 @@ static inline int jmr3927_have_isac(void
+ #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
+--- a/include/asm-mips/mach-au1x00/au1000.h
++++ b/include/asm-mips/mach-au1x00/au1000.h
+@@ -60,59 +60,36 @@ void static inline au_sync_delay(int ms)
+ 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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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_SDADDR0 0xB400000C
+-#define MEM_SDADDR1 0xB4000010
+-#define MEM_SDADDR2 0xB4000014
+-
+-#define MEM_SDREFCFG 0xB4000018
+-#define MEM_SDPRECMD 0xB400001C
+-#define MEM_SDAUTOREF 0xB4000020
+-
+-#define MEM_SDWRMD0 0xB4000024
+-#define MEM_SDWRMD1 0xB4000028
+-#define MEM_SDWRMD2 0xB400002C
++#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)
++
++/*
++ * 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_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)
++
++/*
++ * 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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ #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 @@ extern au1xxx_irq_map_t au1xxx_irq_map[]
+ _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 @@ struct cpu_spec {
+ 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
+--- /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
+--- 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 @@ typedef struct dbdma_global {
+
+ /* 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 @@ typedef struct au1xxx_dma_channel {
+ /* "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 @@ typedef struct au1xxx_ddma_desc {
+ 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 @@ typedef struct au1xxx_ddma_desc {
+ #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 @@ typedef struct au1xxx_ddma_desc {
+ #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 @@ typedef struct au1xxx_ddma_desc {
+ */
+ #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 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u
+
+ #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 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid,
+
+ /* 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 @@ u32 au1xxx_get_dma_residue(u32 chanid);
+ 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
+--- /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
+--- /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
+--- 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
+--- /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
+--- /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
+--- 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
+--- 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
+--- 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 @@ static __inline__ unsigned long ide_defa
+
+ /* 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
+-
+-#define __ide_mm_insw readsw
+-#define __ide_mm_insl readsl
+-#define __ide_mm_outsw writesw
+-#define __ide_mm_outsl writesl
++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));
++ }
++}
++
++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
+--- /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
+--- /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 at 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
+--- /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
+--- 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
+--- 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
+--- 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
+--- 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
+--- /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 at 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
+--- /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
+--- 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 @@ struct hub_data {
+ 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
+--- 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
+--- 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
+--- 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
+--- /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
+--- 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
+--- 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
+--- 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
+--- /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
+--- 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
+--- /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
+--- /dev/null
++++ b/include/asm-mips/mach-pnx8550/cm.h
+@@ -0,0 +1,43 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Clock module specific definitions
++ *
++ * Author: source at 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
+--- /dev/null
++++ b/include/asm-mips/mach-pnx8550/glb.h
+@@ -0,0 +1,86 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PNX8550 global definitions
++ *
++ * Author: source at 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
+--- /dev/null
++++ b/include/asm-mips/mach-pnx8550/int.h
+@@ -0,0 +1,140 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * Interrupt specific definitions
++ *
++ * Author: source at 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
+--- /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
+--- /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
+--- /dev/null
++++ b/include/asm-mips/mach-pnx8550/pci.h
+@@ -0,0 +1,185 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * PCI specific definitions
++ *
++ * Author: source at 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
+--- /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
+--- /dev/null
++++ b/include/asm-mips/mach-pnx8550/usb.h
+@@ -0,0 +1,32 @@
++/*
++ *
++ * BRIEF MODULE DESCRIPTION
++ * USB specific definitions
++ *
++ * Author: source at 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
+--- 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
+--- 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
+--- /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
+--- 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
+--- 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
+--- 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
+--- 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 at 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 at mips.com>
++ * Maciej W. Rozycki <macro at 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_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_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_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_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_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 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 @@ extern unsigned long _pcictrl_msc;
+ * 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 @@ extern unsigned long _pcictrl_msc;
+ #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
+--- /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
+--- /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
+--- /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
+--- 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 at mips.com and Carsten Langgaard, carstenl at 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 @@ do { \
+ 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 { \
+ do { \
+ __asm__ __volatile__( \
+ "ctc0\t%z0, " #register "\n\t" \
+- : : "Jr" ((unsigned int)value)); \
++ : : "Jr" ((unsigned int)(value))); \
+ } while (0)
+
+ /*
+@@ -769,12 +839,24 @@ do { \
+ #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 @@ do { \
+ #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 @@ do { \
+ #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 @@ do { \
+ : "=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(status)
+ __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
+--- a/include/asm-mips/mmu_context.h
++++ b/include/asm-mips/mmu_context.h
+@@ -30,7 +30,7 @@ extern unsigned long pgd_current[];
+
+ #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 @@ extern unsigned long pgd_current[];
+ #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
+--- 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
+--- a/include/asm-mips/module.h
++++ b/include/asm-mips/module.h
+@@ -14,15 +14,23 @@ struct mod_arch_specific {
+
+ 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 @@ typedef struct
+ #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 @@ typedef struct
+ #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 @@ search_module_dbetables(unsigned long ad
+ }
+ #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
+--- a/include/asm-mips/paccess.h
++++ b/include/asm-mips/paccess.h
+@@ -52,7 +52,7 @@ struct __large_pstruct { unsigned long b
+ })
+
+ #define __get_dbe_asm(insn) \
+-({ \
++{ \
+ __asm__ __volatile__( \
+ "1:\t" insn "\t%1,%2\n\t" \
+ "move\t%0,$0\n" \
+@@ -67,7 +67,7 @@ struct __large_pstruct { unsigned long b
+ ".previous" \
+ :"=r" (__gu_err), "=r" (__gu_val) \
+ :"o" (__mp(__gu_addr)), "i" (-EFAULT)); \
+-})
++}
+
+ extern void __get_dbe_unknown(void);
+
+@@ -90,7 +90,7 @@ extern void __get_dbe_unknown(void);
+ })
+
+ #define __put_dbe_asm(insn) \
+-({ \
++{ \
+ __asm__ __volatile__( \
+ "1:\t" insn "\t%1,%2\n\t" \
+ "move\t%0,$0\n" \
+@@ -104,7 +104,7 @@ extern void __get_dbe_unknown(void);
+ ".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
+--- a/include/asm-mips/page.h
++++ b/include/asm-mips/page.h
+@@ -87,22 +87,48 @@ static inline void copy_user_page(void *
+ typedef struct { unsigned long pte; } pte_t;
+ #define pte_val(x) ((x).pte)
+ #endif
++#define __pte(x) ((pte_t) { (x) } )
+
+-typedef struct { unsigned long pmd; } pmd_t;
+-typedef struct { unsigned long pgd; } pgd_t;
+-typedef struct { unsigned long pgprot; } pgprot_t;
++/*
++ * 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;
+ #define pmd_val(x) ((x).pmd)
+-#define pgd_val(x) ((x).pgd)
+-#define pgprot_val(x) ((x).pgprot)
++#define __pmd(x) ((pmd_t) { (x) } )
+
+-#define ptep_buddy(x) ((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
++#endif
+
+-#define __pte(x) ((pte_t) { (x) } )
+-#define __pmd(x) ((pmd_t) { (x) } )
++/*
++ * 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
+--- a/include/asm-mips/pci.h
++++ b/include/asm-mips/pci.h
+@@ -40,6 +40,11 @@ struct pci_controller {
+ 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 @@ static inline void pci_dma_burst_advice(
+
+ 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 @@ static inline void pcibios_add_platform_
+ /* 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
+--- a/include/asm-mips/pgalloc.h
++++ b/include/asm-mips/pgalloc.h
+@@ -26,10 +26,22 @@ static inline void pmd_populate(struct m
+ }
+
+ /*
++ * 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 @@ static inline void pte_free(struct page
+ #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
+--- 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 @@ extern int add_temporary_entry(unsigned
+ * 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 */
++/* PGDIR_SHIFT determines what a third-level page table entry can map */
+ #ifdef CONFIG_64BIT_PHYS_ADDR
+-#define PMD_SHIFT 21
++#define PGDIR_SHIFT 21
+ #else
+-#define PMD_SHIFT 22
++#define PGDIR_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
+ #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 @@ extern int add_temporary_entry(unsigned
+ #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 @@ static inline void pmd_clear(pmd_t *pmdp
+ 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 @@ pfn_pte(unsigned long pfn, pgprot_t prot
+ #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 @@ static inline pmd_t *pmd_offset(pgd_t *d
+ */
+ #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
+--- 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 @@ static inline void pmd_clear(pmd_t *pmdp
+ }
+
+ /*
+- * 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 pud_bad(pud_t pud)
++{
++ return pud_val(pud) & ~PAGE_MASK;
++}
+
+-static inline int pgd_present(pgd_t pgd)
++static inline int pud_present(pud_t pud)
+ {
+- return pgd_val(pgd) != (unsigned long) invalid_pmd_table;
++ return pud_val(pud) != (unsigned long) invalid_pmd_table;
+ }
+
+-static inline void pgd_clear(pgd_t *pgdp)
++static inline void pud_clear(pud_t *pudp)
+ {
+- pgd_val(*pgdp) = ((unsigned long) invalid_pmd_table);
++ pud_val(*pudp) = ((unsigned long) invalid_pmd_table);
+ }
+
+-#define pte_page(x) pfn_to_page((unsigned long)((pte_val(x) >> PAGE_SHIFT)))
++#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 @@ static inline void pgd_clear(pgd_t *pgdp
+ #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
+--- 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
+--- 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 @@ extern void paging_init(void);
+ * 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 @@ extern void paging_init(void);
+ #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 @@ static inline void pte_clear(struct mm_s
+ #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 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD
+ * 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 @@ static inline pgprot_t pgprot_noncached(
+ */
+ #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 @@ static inline void update_mmu_cache(stru
+ #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 @@ static inline int io_remap_pfn_range(str
+ 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
+--- a/include/asm-mips/processor.h
++++ b/include/asm-mips/processor.h
+@@ -96,12 +96,26 @@ union mips_fpu_union {
+ {{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 @@ struct thread_struct {
+ /* 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 @@ struct thread_struct {
+ 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 @@ struct thread_struct {
+ */ \
+ 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
+--- 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 @@ struct pt_regs {
+
+ /* 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 @@ struct pt_regs {
+ #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
+--- 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 flush_scache_line(uns
+ 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 @@ static inline void protected_flush_icach
+ * 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_d
+ 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 @@ static inline void invalidate_tcache_pag
+
+ #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 @@ static inline void invalidate_tcache_pag
+ " 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 @@ static inline void blast_scache16_page_i
+
+ #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 @@ static inline void blast_scache16_page_i
+ " 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 @@ static inline void blast_scache32_page_i
+
+ #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 @@ static inline void blast_scache32_page_i
+ " 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 @@ static inline void blast_scache64_page_i
+
+ #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 @@ static inline void blast_scache64_page_i
+ " 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
+--- 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
+--- /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
+--- a/include/asm-mips/semaphore.h
++++ b/include/asm-mips/semaphore.h
+@@ -45,9 +45,6 @@ struct semaphore {
+ .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
+--- 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
+--- a/include/asm-mips/sgi/hpc3.h
++++ b/include/asm-mips/sgi/hpc3.h
+@@ -128,26 +128,26 @@ struct hpc3_ethregs {
+ 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 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 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 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 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 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
+--- /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
+--- /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
+--- /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
+--- /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
+--- /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
+--- /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
+--- 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
+--- 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 unsigned long sb1250_gettimeoffse
+ 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 @@ extern void prom_printf(char *fmt, ...);
+
+ #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
+--- 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_112x_ALL 0x0000f00
+-#define SIBYTE_HDR_FMASK_112x_PASS1 0x0000100
++#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 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- a/include/asm-mips/sigcontext.h
++++ b/include/asm-mips/sigcontext.h
+@@ -27,14 +27,15 @@ struct sigcontext {
+ 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 @@ struct sigcontext {
+ * 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 @@ struct sigcontext {
+ #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
+--- 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
+--- a/include/asm-mips/signal.h
++++ b/include/asm-mips/signal.h
+@@ -98,12 +98,39 @@ typedef unsigned long old_sigset_t; /*
+ #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
+--- 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
+--- a/include/asm-mips/socket.h
++++ b/include/asm-mips/socket.h
+@@ -37,8 +37,6 @@ To add: #define SO_REUSEPORT 0x0200 /* A
+ #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 @@ To add: #define SO_REUSEPORT 0x0200 /* A
+ #define SCM_TIMESTAMP SO_TIMESTAMP
+
+ #define SO_PEERSEC 30
++#define SO_SNDBUFFORCE 31
++#define SO_RCVBUFFORCE 33
+
+ #ifdef __KERNEL__
+
+@@ -92,6 +92,7 @@ enum sock_type {
+ 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
+--- 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 @@ static inline unsigned int __raw_spin_tr
+ * 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 @@ static inline void __raw_write_lock(raw_
+ " 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 @@ static inline void __raw_write_lock(raw_
+ " 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 @@ static inline int __raw_write_trylock(ra
+ " 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
+--- 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
+--- 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 @@ extern asmlinkage void *resume(void *las
+
+ 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 @@ static inline unsigned long __xchg_u32(v
+ 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 @@ static inline unsigned long __xchg_u32(v
+ 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 @@ static inline __u64 __xchg_u64(volatile
+ 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 @@ static inline __u64 __xchg_u64(volatile
+ 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 @@ static inline __u64 __xchg_u64(volatile
+ #ifdef CONFIG_SMP
+ " sync \n"
+ #endif
++ " .set mips0 \n"
+ : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+ : "R" (*m), "Jr" (val)
+ : "memory");
+@@ -286,34 +297,41 @@ static inline unsigned long __cmpxchg_u3
+
+ 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 @@ static inline unsigned long __cmpxchg_u6
+
+ 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 @@ static inline unsigned long __cmpxchg_u6
+ " 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 @@ static inline unsigned long __cmpxchg(vo
+
+ #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);
+-
+-#define die(msg, regs) \
+- __die(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
+-#define die_if_kernel(msg, regs) \
+- __die_if_kernel(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
++extern NORET_TYPE void die(const char *, struct pt_regs *);
++
++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
+--- a/include/asm-mips/thread_info.h
++++ b/include/asm-mips/thread_info.h
+@@ -26,6 +26,7 @@ struct thread_info {
+ 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 @@ register struct thread_info *__current_t
+ #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 @@ register struct thread_info *__current_t
+ #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
+--- 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- /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 at 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
+--- 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; \
+- \
+- might_sleep(); \
+- __gu_addr = (long) (ptr); \
+- __gu_err = access_ok(VERIFY_READ, (void *) __gu_addr, size) \
+- ? 0 : -EFAULT; \
++ long __gu_err = -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 @@ struct __large_struct { unsigned long bu
+ " "__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 @@ struct __large_struct { unsigned long bu
+ " " __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 @@ extern void __get_user_unknown(void);
+ * 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 @@ extern void __get_user_unknown(void);
+
+ #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 @@ extern void __get_user_unknown(void);
+ " " __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 @@ extern void __get_user_unknown(void);
+ " " __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 @@ extern size_t __copy_user(void *__to, co
+
+ #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 @@ extern size_t __copy_user(void *__to, co
+ */
+ #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 @@ extern size_t __copy_user(void *__to, co
+ */
+ #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 @@ extern size_t __copy_user(void *__to, co
+ #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 @@ extern size_t __copy_user(void *__to, co
+ #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 @@ extern size_t __copy_user(void *__to, co
+ #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 @@ extern size_t __copy_user(void *__to, co
+
+ #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 @@ extern size_t __copy_user(void *__to, co
+ * 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 @@ __clear_user(void *addr, __kernel_size_t
+
+ #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 @@ __clear_user(void *addr, __kernel_size_t
+ * 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 @@ __strncpy_from_user(char *__to, const ch
+ * 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 @@ strncpy_from_user(char *__to, const char
+ }
+
+ /* 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 @@ static inline long __strlen_user(const c
+ * 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 @@ static inline long strlen_user(const cha
+ }
+
+ /* 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 @@ static inline long __strnlen_user(const
+ * 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
+--- 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 @@ asmlinkage long sys_mmap2(
+ 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
+--- 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
+--- 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
+--- 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
+--- 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 @@ static __inline__ unsigned long __ffs(un
+ 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 @@ static __inline__ int fls(int x)
+ * 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 fls(int x)
+ */
+ 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 @@ static inline int sched_find_first_bit(c
+ 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 @@ found_middle:
+
+ 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 @@ found_middle:
+ * 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
+
+-#endif /* __KERNEL__ */
++/* '3' is bits per byte */
++#define LE_BYTE_ADDR ((sizeof(unsigned long) - 1) << 3)
+
+-static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
+-{
+- __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
++#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)
+
+- return (ADDR[nr >> 3] >> (nr & 7)) & 1;
+-}
++#endif /* __KERNEL__ */
+
+-/*
+- * 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)
++
++/* include/linux/byteorder does not support "unsigned long" type */
++static inline unsigned long ext2_swabp(unsigned long * x)
++{
++#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
++}
+
+-extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
+- unsigned long size, unsigned long offset)
++static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+ {
+- unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+- unsigned int result = offset & ~31UL;
+- unsigned int tmp;
++ 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
+--- a/include/asm-parisc/cacheflush.h
++++ b/include/asm-parisc/cacheflush.h
+@@ -100,30 +100,34 @@ static inline void flush_cache_range(str
+
+ /* 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 */
++
++ /* Filter out coincidental file entries and swap entries */
++ if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
++ return 0;
+
+- /* 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;
++ 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 @@ flush_cache_page(struct vm_area_struct *
+ {
+ 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
+--- 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 @@ extern struct hppa_dma_ops *hppa_dma_ops
+
+ 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
+--- 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
+--- 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
+--- 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
+--- 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
+--- a/include/asm-parisc/mmzone.h
++++ b/include/asm-parisc/mmzone.h
+@@ -27,12 +27,6 @@ extern struct node_map_data node_data[];
+ })
+ #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
+--- 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 @@ struct parisc_driver {
+ #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
+--- a/include/asm-parisc/pci.h
++++ b/include/asm-parisc/pci.h
+@@ -69,7 +69,7 @@ struct pci_hba_data {
+ #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
+--- a/include/asm-parisc/pgtable.h
++++ b/include/asm-parisc/pgtable.h
+@@ -501,6 +501,8 @@ static inline void ptep_set_wrprotect(st
+ #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
+--- a/include/asm-parisc/processor.h
++++ b/include/asm-parisc/processor.h
+@@ -122,8 +122,27 @@ struct thread_struct {
+ };
+
+ /* 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
+--- 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
+--- a/include/asm-parisc/ptrace.h
++++ b/include/asm-parisc/ptrace.h
+@@ -49,7 +49,7 @@ struct pt_regs {
+ #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
+--- a/include/asm-parisc/semaphore.h
++++ b/include/asm-parisc/semaphore.h
+@@ -49,9 +49,6 @@ struct semaphore {
+ .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
+--- 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
+--- 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
+--- a/include/asm-parisc/system.h
++++ b/include/asm-parisc/system.h
+@@ -138,13 +138,7 @@ static inline void set_eiem(unsigned lon
+ #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 @@ static inline void set_eiem(unsigned lon
+ 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"
+
+-#ifdef CONFIG_SMP
+-# define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
+-#endif
++#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"
+
+-#define KERNEL_START (0x10100000 - 0x1000)
++#endif /*!CONFIG_PA20*/
+
+-/* 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)
++/* 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)
+ #define arch_align_stack(x) (x)
+
+ #endif
+diff --git a/include/asm-parisc/tlbflush.h b/include/asm-parisc/tlbflush.h
+--- 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 @@ static inline void flush_tlb_range(struc
+ {
+ 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
+--- a/include/asm-parisc/types.h
++++ b/include/asm-parisc/types.h
+@@ -33,8 +33,10 @@ typedef unsigned long long __u64;
+
+ #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
+--- 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 @@ int sys_clone(unsigned long clone_flags,
+ 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/a.out.h b/include/asm-powerpc/a.out.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/a.out.h
+@@ -0,0 +1,36 @@
++#ifndef _ASM_POWERPC_A_OUT_H
++#define _ASM_POWERPC_A_OUT_H
++
++struct exec
++{
++ unsigned long a_info; /* Use macros N_MAGIC, etc for access */
++ unsigned a_text; /* length of text, in bytes */
++ unsigned a_data; /* length of data, in bytes */
++ unsigned a_bss; /* length of uninitialized data area for file, in bytes */
++ unsigned a_syms; /* length of symbol table data in file, in bytes */
++ unsigned a_entry; /* start address */
++ unsigned a_trsize; /* length of relocation info for text, in bytes */
++ unsigned a_drsize; /* length of relocation info for data, in bytes */
++};
++
++#define N_TRSIZE(a) ((a).a_trsize)
++#define N_DRSIZE(a) ((a).a_drsize)
++#define N_SYMSIZE(a) ((a).a_syms)
++
++#ifdef __KERNEL__
++#ifdef __powerpc64__
++
++#define STACK_TOP_USER64 TASK_SIZE_USER64
++#define STACK_TOP_USER32 TASK_SIZE_USER32
++
++#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
++ STACK_TOP_USER32 : STACK_TOP_USER64)
++
++#else /* __powerpc64__ */
++
++#define STACK_TOP TASK_SIZE
++
++#endif /* __powerpc64__ */
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_POWERPC_A_OUT_H */
+diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/atomic.h
+@@ -0,0 +1,209 @@
++#ifndef _ASM_POWERPC_ATOMIC_H_
++#define _ASM_POWERPC_ATOMIC_H_
++
++/*
++ * PowerPC atomic operations
++ */
++
++typedef struct { volatile int counter; } atomic_t;
++
++#ifdef __KERNEL__
++#include <asm/synch.h>
++
++#define ATOMIC_INIT(i) { (i) }
++
++#define atomic_read(v) ((v)->counter)
++#define atomic_set(v,i) (((v)->counter) = (i))
++
++/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx.
++ * The old ATOMIC_SYNC_FIX covered some but not all of this.
++ */
++#ifdef CONFIG_IBM405_ERR77
++#define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";"
++#else
++#define PPC405_ERR77(ra,rb)
++#endif
++
++static __inline__ void atomic_add(int a, atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++"1: lwarx %0,0,%3 # atomic_add\n\
++ add %0,%2,%0\n"
++ PPC405_ERR77(0,%3)
++" stwcx. %0,0,%3 \n\
++ bne- 1b"
++ : "=&r" (t), "=m" (v->counter)
++ : "r" (a), "r" (&v->counter), "m" (v->counter)
++ : "cc");
++}
++
++static __inline__ int atomic_add_return(int a, atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++ EIEIO_ON_SMP
++"1: lwarx %0,0,%2 # atomic_add_return\n\
++ add %0,%1,%0\n"
++ PPC405_ERR77(0,%2)
++" stwcx. %0,0,%2 \n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ : "=&r" (t)
++ : "r" (a), "r" (&v->counter)
++ : "cc", "memory");
++
++ return t;
++}
++
++#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
++
++static __inline__ void atomic_sub(int a, atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++"1: lwarx %0,0,%3 # atomic_sub\n\
++ subf %0,%2,%0\n"
++ PPC405_ERR77(0,%3)
++" stwcx. %0,0,%3 \n\
++ bne- 1b"
++ : "=&r" (t), "=m" (v->counter)
++ : "r" (a), "r" (&v->counter), "m" (v->counter)
++ : "cc");
++}
++
++static __inline__ int atomic_sub_return(int a, atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++ EIEIO_ON_SMP
++"1: lwarx %0,0,%2 # atomic_sub_return\n\
++ subf %0,%1,%0\n"
++ PPC405_ERR77(0,%2)
++" stwcx. %0,0,%2 \n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ : "=&r" (t)
++ : "r" (a), "r" (&v->counter)
++ : "cc", "memory");
++
++ return t;
++}
++
++static __inline__ void atomic_inc(atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++"1: lwarx %0,0,%2 # atomic_inc\n\
++ addic %0,%0,1\n"
++ PPC405_ERR77(0,%2)
++" stwcx. %0,0,%2 \n\
++ bne- 1b"
++ : "=&r" (t), "=m" (v->counter)
++ : "r" (&v->counter), "m" (v->counter)
++ : "cc");
++}
++
++static __inline__ int atomic_inc_return(atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++ EIEIO_ON_SMP
++"1: lwarx %0,0,%1 # atomic_inc_return\n\
++ addic %0,%0,1\n"
++ PPC405_ERR77(0,%1)
++" stwcx. %0,0,%1 \n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ : "=&r" (t)
++ : "r" (&v->counter)
++ : "cc", "memory");
++
++ return t;
++}
++
++/*
++ * atomic_inc_and_test - increment and test
++ * @v: pointer of type atomic_t
++ *
++ * Atomically increments @v by 1
++ * and returns true if the result is zero, or false for all
++ * other cases.
++ */
++#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
++
++static __inline__ void atomic_dec(atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++"1: lwarx %0,0,%2 # atomic_dec\n\
++ addic %0,%0,-1\n"
++ PPC405_ERR77(0,%2)\
++" stwcx. %0,0,%2\n\
++ bne- 1b"
++ : "=&r" (t), "=m" (v->counter)
++ : "r" (&v->counter), "m" (v->counter)
++ : "cc");
++}
++
++static __inline__ int atomic_dec_return(atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++ EIEIO_ON_SMP
++"1: lwarx %0,0,%1 # atomic_dec_return\n\
++ addic %0,%0,-1\n"
++ PPC405_ERR77(0,%1)
++" stwcx. %0,0,%1\n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ : "=&r" (t)
++ : "r" (&v->counter)
++ : "cc", "memory");
++
++ return t;
++}
++
++#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
++#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
++
++/*
++ * Atomically test *v and decrement if it is greater than 0.
++ * The function returns the old value of *v minus 1.
++ */
++static __inline__ int atomic_dec_if_positive(atomic_t *v)
++{
++ int t;
++
++ __asm__ __volatile__(
++ EIEIO_ON_SMP
++"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\
++ addic. %0,%0,-1\n\
++ blt- 2f\n"
++ PPC405_ERR77(0,%1)
++" stwcx. %0,0,%1\n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ "\n\
++2:" : "=&r" (t)
++ : "r" (&v->counter)
++ : "cc", "memory");
++
++ return t;
++}
++
++#define smp_mb__before_atomic_dec() smp_mb()
++#define smp_mb__after_atomic_dec() smp_mb()
++#define smp_mb__before_atomic_inc() smp_mb()
++#define smp_mb__after_atomic_inc() smp_mb()
++
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_ATOMIC_H_ */
+diff --git a/include/asm-powerpc/auxvec.h b/include/asm-powerpc/auxvec.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/auxvec.h
+@@ -0,0 +1,21 @@
++#ifndef _ASM_POWERPC_AUXVEC_H
++#define _ASM_POWERPC_AUXVEC_H
++
++/*
++ * We need to put in some extra aux table entries to tell glibc what
++ * the cache block size is, so it can use the dcbz instruction safely.
++ */
++#define AT_DCACHEBSIZE 19
++#define AT_ICACHEBSIZE 20
++#define AT_UCACHEBSIZE 21
++/* A special ignored type value for PPC, for glibc compatibility. */
++#define AT_IGNOREPPC 22
++
++/* The vDSO location. We have to use the same value as x86 for glibc's
++ * sake :-)
++ */
++#ifdef __powerpc64__
++#define AT_SYSINFO_EHDR 33
++#endif
++
++#endif
+diff --git a/include/asm-powerpc/backlight.h b/include/asm-powerpc/backlight.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/backlight.h
+@@ -0,0 +1,31 @@
++/*
++ * Routines for handling backlight control on PowerBooks
++ *
++ * For now, implementation resides in
++ * arch/powerpc/platforms/powermac/pmac_support.c
++ *
++ */
++#ifndef __ASM_POWERPC_BACKLIGHT_H
++#define __ASM_POWERPC_BACKLIGHT_H
++#ifdef __KERNEL__
++
++/* Abstract values */
++#define BACKLIGHT_OFF 0
++#define BACKLIGHT_MIN 1
++#define BACKLIGHT_MAX 0xf
++
++struct backlight_controller {
++ int (*set_enable)(int enable, int level, void *data);
++ int (*set_level)(int level, void *data);
++};
++
++extern void register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type);
++extern void unregister_backlight_controller(struct backlight_controller *ctrler, void *data);
++
++extern int set_backlight_enable(int enable);
++extern int get_backlight_enable(void);
++extern int set_backlight_level(int level);
++extern int get_backlight_level(void);
++
++#endif /* __KERNEL__ */
++#endif
+diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/bug.h
+@@ -0,0 +1,81 @@
++#ifndef _ASM_POWERPC_BUG_H
++#define _ASM_POWERPC_BUG_H
++
++/*
++ * Define an illegal instr to trap on the bug.
++ * We don't use 0 because that marks the end of a function
++ * in the ELF ABI. That's "Boo Boo" in case you wonder...
++ */
++#define BUG_OPCODE .long 0x00b00b00 /* For asm */
++#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */
++
++#ifndef __ASSEMBLY__
++
++#ifdef __powerpc64__
++#define BUG_TABLE_ENTRY(label, line, file, func) \
++ ".llong " #label "\n .long " #line "\n .llong " #file ", " #func "\n"
++#define TRAP_OP(ra, rb) "1: tdnei " #ra ", " #rb "\n"
++#define DATA_TYPE long long
++#else
++#define BUG_TABLE_ENTRY(label, line, file, func) \
++ ".long " #label ", " #line ", " #file ", " #func "\n"
++#define TRAP_OP(ra, rb) "1: twnei " #ra ", " #rb "\n"
++#define DATA_TYPE int
++#endif /* __powerpc64__ */
++
++struct bug_entry {
++ unsigned long bug_addr;
++ int line;
++ const char *file;
++ const char *function;
++};
++
++struct bug_entry *find_bug(unsigned long bugaddr);
++
++/*
++ * If this bit is set in the line number it means that the trap
++ * is for WARN_ON rather than BUG or BUG_ON.
++ */
++#define BUG_WARNING_TRAP 0x1000000
++
++#ifdef CONFIG_BUG
++
++#define BUG() do { \
++ __asm__ __volatile__( \
++ "1: twi 31,0,0\n" \
++ ".section __bug_table,\"a\"\n\t" \
++ BUG_TABLE_ENTRY(1b,%0,%1,%2) \
++ ".previous" \
++ : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
++} while (0)
++
++#define BUG_ON(x) do { \
++ __asm__ __volatile__( \
++ TRAP_OP(%0,0) \
++ ".section __bug_table,\"a\"\n\t" \
++ BUG_TABLE_ENTRY(1b,%1,%2,%3) \
++ ".previous" \
++ : : "r" ((DATA_TYPE)(x)), "i" (__LINE__), \
++ "i" (__FILE__), "i" (__FUNCTION__)); \
++} while (0)
++
++#define WARN_ON(x) do { \
++ __asm__ __volatile__( \
++ TRAP_OP(%0,0) \
++ ".section __bug_table,\"a\"\n\t" \
++ BUG_TABLE_ENTRY(1b,%1,%2,%3) \
++ ".previous" \
++ : : "r" ((DATA_TYPE)(x)), \
++ "i" (__LINE__ + BUG_WARNING_TRAP), \
++ "i" (__FILE__), "i" (__FUNCTION__)); \
++} while (0)
++
++#define HAVE_ARCH_BUG
++#define HAVE_ARCH_BUG_ON
++#define HAVE_ARCH_WARN_ON
++#endif /* CONFIG_BUG */
++#endif /* __ASSEMBLY __ */
++
++#include <asm-generic/bug.h>
++
++#endif /* _ASM_POWERPC_BUG_H */
+diff --git a/include/asm-powerpc/byteorder.h b/include/asm-powerpc/byteorder.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/byteorder.h
+@@ -0,0 +1,89 @@
++#ifndef _ASM_POWERPC_BYTEORDER_H
++#define _ASM_POWERPC_BYTEORDER_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.
++ */
++
++#include <asm/types.h>
++#include <linux/compiler.h>
++
++#ifdef __GNUC__
++#ifdef __KERNEL__
++
++static __inline__ __u16 ld_le16(const volatile __u16 *addr)
++{
++ __u16 val;
++
++ __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
++ return val;
++}
++
++static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
++{
++ __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
++}
++
++static __inline__ __u32 ld_le32(const volatile __u32 *addr)
++{
++ __u32 val;
++
++ __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
++ return val;
++}
++
++static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
++{
++ __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
++}
++
++static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
++{
++ __u16 result;
++
++ __asm__("rlwimi %0,%1,8,16,23"
++ : "=r" (result)
++ : "r" (value), "0" (value >> 8));
++ return result;
++}
++
++static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
++{
++ __u32 result;
++
++ __asm__("rlwimi %0,%1,24,16,23\n\t"
++ "rlwimi %0,%1,8,8,15\n\t"
++ "rlwimi %0,%1,24,0,7"
++ : "=r" (result)
++ : "r" (value), "0" (value >> 24));
++ return result;
++}
++
++#define __arch__swab16(x) ___arch__swab16(x)
++#define __arch__swab32(x) ___arch__swab32(x)
++
++/* The same, but returns converted value from the location pointer by addr. */
++#define __arch__swab16p(addr) ld_le16(addr)
++#define __arch__swab32p(addr) ld_le32(addr)
++
++/* The same, but do the conversion in situ, ie. put the value back to addr. */
++#define __arch__swab16s(addr) st_le16(addr,*addr)
++#define __arch__swab32s(addr) st_le32(addr,*addr)
++
++#endif /* __KERNEL__ */
++
++#ifndef __STRICT_ANSI__
++#define __BYTEORDER_HAS_U64__
++#ifndef __powerpc64__
++#define __SWAB_64_THRU_32__
++#endif /* __powerpc64__ */
++#endif /* __STRICT_ANSI__ */
++
++#endif /* __GNUC__ */
++
++#include <linux/byteorder/big_endian.h>
++
++#endif /* _ASM_POWERPC_BYTEORDER_H */
+diff --git a/include/asm-powerpc/checksum.h b/include/asm-powerpc/checksum.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/checksum.h
+@@ -0,0 +1,132 @@
++#ifndef _ASM_POWERPC_CHECKSUM_H
++#define _ASM_POWERPC_CHECKSUM_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.
++ */
++
++/*
++ * This is a version of ip_compute_csum() optimized for IP headers,
++ * which always checksum on 4 octet boundaries. ihl is the number
++ * of 32-bit words and is always >= 5.
++ */
++extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
++
++/*
++ * computes the checksum of the TCP/UDP pseudo-header
++ * returns a 16-bit checksum, already complemented
++ */
++extern unsigned short csum_tcpudp_magic(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum);
++
++/*
++ * computes the checksum of a memory block at buff, length len,
++ * and adds in "sum" (32-bit)
++ *
++ * returns a 32-bit number suitable for feeding into itself
++ * or csum_tcpudp_magic
++ *
++ * this function must be called with even lengths, except
++ * for the last fragment, which may be odd
++ *
++ * it's best to have buff aligned on a 32-bit boundary
++ */
++extern unsigned int csum_partial(const unsigned char * buff, int len,
++ unsigned int sum);
++
++/*
++ * Computes the checksum of a memory block at src, length len,
++ * and adds in "sum" (32-bit), while copying the block to dst.
++ * If an access exception occurs on src or dst, it stores -EFAULT
++ * to *src_err or *dst_err respectively (if that pointer is not
++ * NULL), and, for an error on src, zeroes the rest of dst.
++ *
++ * Like csum_partial, this must be called with even lengths,
++ * except for the last fragment.
++ */
++extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
++ int len, unsigned int sum,
++ int *src_err, int *dst_err);
++/*
++ * the same as csum_partial, but copies from src to dst while it
++ * checksums.
++ */
++unsigned int csum_partial_copy_nocheck(const char *src,
++ char *dst,
++ int len,
++ unsigned int sum);
++
++#define csum_partial_copy_from_user(src, dst, len, sum, errp) \
++ csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
++
++#define csum_partial_copy_nocheck(src, dst, len, sum) \
++ csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
++
++
++/*
++ * turns a 32-bit partial checksum (e.g. from csum_partial) into a
++ * 1's complement 16-bit checksum.
++ */
++static inline unsigned int csum_fold(unsigned int sum)
++{
++ unsigned int tmp;
++
++ /* swap the two 16-bit halves of sum */
++ __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum));
++ /* if there is a carry from adding the two 16-bit halves,
++ it will carry from the lower half into the upper half,
++ giving us the correct sum in the upper half. */
++ sum = ~(sum + tmp) >> 16;
++ return sum;
++}
++
++/*
++ * this routine is used for miscellaneous IP-like checksums, mainly
++ * in icmp.c
++ */
++static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
++{
++ return csum_fold(csum_partial(buff, len, 0));
++}
++
++#ifdef __powerpc64__
++static inline u32 csum_tcpudp_nofold(u32 saddr,
++ u32 daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ unsigned long s = sum;
++
++ s += saddr;
++ s += daddr;
++ s += (proto << 16) + len;
++ s += (s >> 32);
++ return (u32) s;
++}
++#else
++static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ __asm__("\n\
++ addc %0,%0,%1 \n\
++ adde %0,%0,%2 \n\
++ adde %0,%0,%3 \n\
++ addze %0,%0 \n\
++ "
++ : "=r" (sum)
++ : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
++ return sum;
++}
++
++#endif
++#endif
+diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/cputable.h
+@@ -0,0 +1,427 @@
++#ifndef __ASM_POWERPC_CPUTABLE_H
++#define __ASM_POWERPC_CPUTABLE_H
++
++#include <linux/config.h>
++#include <asm/ppc_asm.h> /* for ASM_CONST */
++
++#define PPC_FEATURE_32 0x80000000
++#define PPC_FEATURE_64 0x40000000
++#define PPC_FEATURE_601_INSTR 0x20000000
++#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
++#define PPC_FEATURE_HAS_FPU 0x08000000
++#define PPC_FEATURE_HAS_MMU 0x04000000
++#define PPC_FEATURE_HAS_4xxMAC 0x02000000
++#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
++#define PPC_FEATURE_HAS_SPE 0x00800000
++#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000
++#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000
++#define PPC_FEATURE_NO_TB 0x00100000
++
++#ifdef __KERNEL__
++#ifndef __ASSEMBLY__
++
++/* This structure can grow, it's real size is used by head.S code
++ * via the mkdefs mechanism.
++ */
++struct cpu_spec;
++struct op_powerpc_model;
++
++typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
++
++struct cpu_spec {
++ /* CPU is matched via (PVR & pvr_mask) == pvr_value */
++ unsigned int pvr_mask;
++ unsigned int pvr_value;
++
++ char *cpu_name;
++ unsigned long cpu_features; /* Kernel features */
++ unsigned int cpu_user_features; /* Userland features */
++
++ /* cache line sizes */
++ unsigned int icache_bsize;
++ unsigned int dcache_bsize;
++
++ /* number of performance monitor counters */
++ unsigned int num_pmcs;
++
++ /* this is called to initialize various CPU bits like L1 cache,
++ * BHT, SPD, etc... from head.S before branching to identify_machine
++ */
++ cpu_setup_t cpu_setup;
++
++ /* Used by oprofile userspace to select the right counters */
++ char *oprofile_cpu_type;
++
++ /* Processor specific oprofile operations */
++ struct op_powerpc_model *oprofile_model;
++};
++
++extern struct cpu_spec *cur_cpu_spec;
++
++extern void identify_cpu(unsigned long offset, unsigned long cpu);
++extern void do_cpu_ftr_fixups(unsigned long offset);
++
++#endif /* __ASSEMBLY__ */
++
++/* CPU kernel features */
++
++/* Retain the 32b definitions all use bottom half of word */
++#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001)
++#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002)
++#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004)
++#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008)
++#define CPU_FTR_TAU ASM_CONST(0x0000000000000010)
++#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020)
++#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040)
++#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080)
++#define CPU_FTR_601 ASM_CONST(0x0000000000000100)
++#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200)
++#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400)
++#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800)
++#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000)
++#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000)
++#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000)
++#define CPU_FTR_NO_DPM ASM_CONST(0x0000000000008000)
++#define CPU_FTR_HAS_HIGH_BATS ASM_CONST(0x0000000000010000)
++#define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000)
++#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000)
++#define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000)
++
++#ifdef __powerpc64__
++/* Add the 64b processor unique features in the top half of the word */
++#define CPU_FTR_SLB ASM_CONST(0x0000000100000000)
++#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000)
++#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000)
++#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000)
++#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000)
++#define CPU_FTR_IABR ASM_CONST(0x0000002000000000)
++#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000)
++#define CPU_FTR_CTRL ASM_CONST(0x0000008000000000)
++#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
++#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
++#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
++#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
++#else
++/* ensure on 32b processors the flags are available for compiling but
++ * don't do anything */
++#define CPU_FTR_SLB ASM_CONST(0x0)
++#define CPU_FTR_16M_PAGE ASM_CONST(0x0)
++#define CPU_FTR_TLBIEL ASM_CONST(0x0)
++#define CPU_FTR_NOEXECUTE ASM_CONST(0x0)
++#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0)
++#define CPU_FTR_IABR ASM_CONST(0x0)
++#define CPU_FTR_MMCRA ASM_CONST(0x0)
++#define CPU_FTR_CTRL ASM_CONST(0x0)
++#define CPU_FTR_SMT ASM_CONST(0x0)
++#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0)
++#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0)
++#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0)
++#endif
++
++#ifndef __ASSEMBLY__
++
++#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \
++ CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \
++ CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL)
++
++/* iSeries doesn't support large pages */
++#ifdef CONFIG_PPC_ISERIES
++#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE)
++#else
++#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE)
++#endif /* CONFIG_PPC_ISERIES */
++
++/* We only set the altivec features if the kernel was compiled with altivec
++ * support
++ */
++#ifdef CONFIG_ALTIVEC
++#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC
++#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC
++#else
++#define CPU_FTR_ALTIVEC_COMP 0
++#define PPC_FEATURE_HAS_ALTIVEC_COMP 0
++#endif
++
++/* We need to mark all pages as being coherent if we're SMP or we
++ * have a 74[45]x and an MPC107 host bridge.
++ */
++#if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE)
++#define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT
++#else
++#define CPU_FTR_COMMON 0
++#endif
++
++/* The powersave features NAP & DOZE seems to confuse BDI when
++ debugging. So if a BDI is used, disable theses
++ */
++#ifndef CONFIG_BDI_SWITCH
++#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE
++#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP
++#else
++#define CPU_FTR_MAYBE_CAN_DOZE 0
++#define CPU_FTR_MAYBE_CAN_NAP 0
++#endif
++
++#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \
++ !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
++ !defined(CONFIG_BOOKE))
++
++enum {
++ CPU_FTRS_PPC601 = CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE,
++ CPU_FTRS_603 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP,
++ CPU_FTRS_604 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
++ CPU_FTRS_740_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
++ CPU_FTRS_740 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
++ CPU_FTRS_750 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
++ CPU_FTRS_750FX1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
++ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM,
++ CPU_FTRS_750FX2 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
++ CPU_FTR_NO_DPM,
++ CPU_FTRS_750FX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
++ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
++ CPU_FTRS_750GX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
++ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
++ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
++ CPU_FTRS_7400_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
++ CPU_FTR_MAYBE_CAN_NAP,
++ CPU_FTRS_7400 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
++ CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
++ CPU_FTR_MAYBE_CAN_NAP,
++ CPU_FTRS_7450_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NEED_COHERENT,
++ CPU_FTRS_7450_21 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
++ CPU_FTR_NEED_COHERENT,
++ CPU_FTRS_7450_23 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT,
++ CPU_FTRS_7455_1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS |
++ CPU_FTR_NEED_COHERENT,
++ CPU_FTRS_7455_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
++ CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS,
++ CPU_FTRS_7455 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
++ CPU_FTR_NEED_COHERENT,
++ CPU_FTRS_7447_10 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
++ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
++ CPU_FTRS_7447 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
++ CPU_FTR_NEED_COHERENT,
++ CPU_FTRS_7447A = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB |
++ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
++ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
++ CPU_FTR_NEED_COHERENT,
++ CPU_FTRS_82XX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB,
++ CPU_FTRS_G2_LE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
++ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
++ CPU_FTRS_E300 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
++ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
++ CPU_FTRS_CLASSIC32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
++ CPU_FTRS_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
++ CPU_FTRS_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
++ CPU_FTRS_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
++ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP |
++ CPU_FTR_MAYBE_CAN_NAP,
++ CPU_FTRS_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
++ CPU_FTRS_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
++ CPU_FTRS_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
++ CPU_FTRS_E200 = CPU_FTR_USE_TB,
++ CPU_FTRS_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
++ CPU_FTRS_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_BIG_PHYS,
++ CPU_FTRS_GENERIC_32 = CPU_FTR_COMMON,
++#ifdef __powerpc64__
++ CPU_FTRS_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
++ CPU_FTRS_RS64 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
++ CPU_FTR_MMCRA | CPU_FTR_CTRL,
++ CPU_FTRS_POWER4 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
++ CPU_FTRS_PPC970 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
++ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
++ CPU_FTRS_POWER5 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
++ CPU_FTR_MMCRA | CPU_FTR_SMT |
++ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
++ CPU_FTR_MMCRA_SIHV,
++ CPU_FTRS_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
++ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT,
++ CPU_FTRS_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
++ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2,
++#endif
++
++ CPU_FTRS_POSSIBLE =
++#if CLASSIC_PPC
++ CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
++ CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
++ CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX |
++ CPU_FTRS_7400_NOTAU | CPU_FTRS_7400 | CPU_FTRS_7450_20 |
++ CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 |
++ CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 |
++ CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX |
++ CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_CLASSIC32 |
++#else
++ CPU_FTRS_GENERIC_32 |
++#endif
++#ifdef CONFIG_PPC64BRIDGE
++ CPU_FTRS_POWER3_32 |
++#endif
++#ifdef CONFIG_POWER4
++ CPU_FTRS_POWER4_32 | CPU_FTRS_970_32 |
++#endif
++#ifdef CONFIG_8xx
++ CPU_FTRS_8XX |
++#endif
++#ifdef CONFIG_40x
++ CPU_FTRS_40X |
++#endif
++#ifdef CONFIG_44x
++ CPU_FTRS_44X |
++#endif
++#ifdef CONFIG_E200
++ CPU_FTRS_E200 |
++#endif
++#ifdef CONFIG_E500
++ CPU_FTRS_E500 | CPU_FTRS_E500_2 |
++#endif
++#ifdef __powerpc64__
++ CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |
++ CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL |
++#endif
++ 0,
++
++ CPU_FTRS_ALWAYS =
++#if CLASSIC_PPC
++ CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
++ CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
++ CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX &
++ CPU_FTRS_7400_NOTAU & CPU_FTRS_7400 & CPU_FTRS_7450_20 &
++ CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 &
++ CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 &
++ CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX &
++ CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_CLASSIC32 &
++#else
++ CPU_FTRS_GENERIC_32 &
++#endif
++#ifdef CONFIG_PPC64BRIDGE
++ CPU_FTRS_POWER3_32 &
++#endif
++#ifdef CONFIG_POWER4
++ CPU_FTRS_POWER4_32 & CPU_FTRS_970_32 &
++#endif
++#ifdef CONFIG_8xx
++ CPU_FTRS_8XX &
++#endif
++#ifdef CONFIG_40x
++ CPU_FTRS_40X &
++#endif
++#ifdef CONFIG_44x
++ CPU_FTRS_44X &
++#endif
++#ifdef CONFIG_E200
++ CPU_FTRS_E200 &
++#endif
++#ifdef CONFIG_E500
++ CPU_FTRS_E500 & CPU_FTRS_E500_2 &
++#endif
++#ifdef __powerpc64__
++ CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &
++ CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL &
++#endif
++ CPU_FTRS_POSSIBLE,
++};
++
++static inline int cpu_has_feature(unsigned long feature)
++{
++ return (CPU_FTRS_ALWAYS & feature) ||
++ (CPU_FTRS_POSSIBLE
++ & cur_cpu_spec->cpu_features
++ & feature);
++}
++
++#endif /* !__ASSEMBLY__ */
++
++#ifdef __ASSEMBLY__
++
++#define BEGIN_FTR_SECTION 98:
++
++#ifndef __powerpc64__
++#define END_FTR_SECTION(msk, val) \
++99: \
++ .section __ftr_fixup,"a"; \
++ .align 2; \
++ .long msk; \
++ .long val; \
++ .long 98b; \
++ .long 99b; \
++ .previous
++#else /* __powerpc64__ */
++#define END_FTR_SECTION(msk, val) \
++99: \
++ .section __ftr_fixup,"a"; \
++ .align 3; \
++ .llong msk; \
++ .llong val; \
++ .llong 98b; \
++ .llong 99b; \
++ .previous
++#endif /* __powerpc64__ */
++
++#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk))
++#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0)
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++#endif /* __ASM_POWERPC_CPUTABLE_H */
+diff --git a/include/asm-powerpc/dbdma.h b/include/asm-powerpc/dbdma.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/dbdma.h
+@@ -0,0 +1,102 @@
++/*
++ * Definitions for using the Apple Descriptor-Based DMA controller
++ * in Power Macintosh computers.
++ *
++ * Copyright (C) 1996 Paul Mackerras.
++ */
++
++#ifdef __KERNEL__
++#ifndef _ASM_DBDMA_H_
++#define _ASM_DBDMA_H_
++/*
++ * DBDMA control/status registers. All little-endian.
++ */
++struct dbdma_regs {
++ unsigned int control; /* lets you change bits in status */
++ unsigned int status; /* DMA and device status bits (see below) */
++ unsigned int cmdptr_hi; /* upper 32 bits of command address */
++ unsigned int cmdptr; /* (lower 32 bits of) command address (phys) */
++ unsigned int intr_sel; /* select interrupt condition bit */
++ unsigned int br_sel; /* select branch condition bit */
++ unsigned int wait_sel; /* select wait condition bit */
++ unsigned int xfer_mode;
++ unsigned int data2ptr_hi;
++ unsigned int data2ptr;
++ unsigned int res1;
++ unsigned int address_hi;
++ unsigned int br_addr_hi;
++ unsigned int res2[3];
++};
++
++/* Bits in control and status registers */
++#define RUN 0x8000
++#define PAUSE 0x4000
++#define FLUSH 0x2000
++#define WAKE 0x1000
++#define DEAD 0x0800
++#define ACTIVE 0x0400
++#define BT 0x0100
++#define DEVSTAT 0x00ff
++
++/*
++ * DBDMA command structure. These fields are all little-endian!
++ */
++struct dbdma_cmd {
++ unsigned short req_count; /* requested byte transfer count */
++ unsigned short command; /* command word (has bit-fields) */
++ unsigned int phy_addr; /* physical data address */
++ unsigned int cmd_dep; /* command-dependent field */
++ unsigned short res_count; /* residual count after completion */
++ unsigned short xfer_status; /* transfer status */
++};
++
++/* DBDMA command values in command field */
++#define OUTPUT_MORE 0 /* transfer memory data to stream */
++#define OUTPUT_LAST 0x1000 /* ditto followed by end marker */
++#define INPUT_MORE 0x2000 /* transfer stream data to memory */
++#define INPUT_LAST 0x3000 /* ditto, expect end marker */
++#define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */
++#define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */
++#define DBDMA_NOP 0x6000 /* do nothing */
++#define DBDMA_STOP 0x7000 /* suspend processing */
++
++/* Key values in command field */
++#define KEY_STREAM0 0 /* usual data stream */
++#define KEY_STREAM1 0x100 /* control/status stream */
++#define KEY_STREAM2 0x200 /* device-dependent stream */
++#define KEY_STREAM3 0x300 /* device-dependent stream */
++#define KEY_REGS 0x500 /* device register space */
++#define KEY_SYSTEM 0x600 /* system memory-mapped space */
++#define KEY_DEVICE 0x700 /* device memory-mapped space */
++
++/* Interrupt control values in command field */
++#define INTR_NEVER 0 /* don't interrupt */
++#define INTR_IFSET 0x10 /* intr if condition bit is 1 */
++#define INTR_IFCLR 0x20 /* intr if condition bit is 0 */
++#define INTR_ALWAYS 0x30 /* always interrupt */
++
++/* Branch control values in command field */
++#define BR_NEVER 0 /* don't branch */
++#define BR_IFSET 0x4 /* branch if condition bit is 1 */
++#define BR_IFCLR 0x8 /* branch if condition bit is 0 */
++#define BR_ALWAYS 0xc /* always branch */
++
++/* Wait control values in command field */
++#define WAIT_NEVER 0 /* don't wait */
++#define WAIT_IFSET 1 /* wait if condition bit is 1 */
++#define WAIT_IFCLR 2 /* wait if condition bit is 0 */
++#define WAIT_ALWAYS 3 /* always wait */
++
++/* Align an address for a DBDMA command structure */
++#define DBDMA_ALIGN(x) (((unsigned long)(x) + sizeof(struct dbdma_cmd) - 1) \
++ & -sizeof(struct dbdma_cmd))
++
++/* Useful macros */
++#define DBDMA_DO_STOP(regs) do { \
++ out_le32(&((regs)->control), (RUN|FLUSH)<<16); \
++ while(in_le32(&((regs)->status)) & (ACTIVE|FLUSH)) \
++ ; \
++} while(0)
++
++#endif /* _ASM_DBDMA_H_ */
++#endif /* __KERNEL__ */
+diff --git a/include/asm-powerpc/dma.h b/include/asm-powerpc/dma.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/dma.h
+@@ -0,0 +1,390 @@
++#ifndef _ASM_POWERPC_DMA_H
++#define _ASM_POWERPC_DMA_H
++
++/*
++ * Defines for using and allocating dma channels.
++ * Written by Hennus Bergman, 1992.
++ * High DMA channel support & info by Hannu Savolainen
++ * and John Boyd, Nov. 1992.
++ * Changes for ppc sound by Christoph Nadig
++ */
++
++/*
++ * Note: Adapted for PowerPC by Gary Thomas
++ * Modified by Cort Dougan <cort at cs.nmt.edu>
++ *
++ * None of this really applies for Power Macintoshes. There is
++ * basically just enough here to get kernel/dma.c to compile.
++ *
++ * There may be some comments or restrictions made here which are
++ * not valid for the PReP platform. Take what you read
++ * with a grain of salt.
++ */
++
++#include <linux/config.h>
++#include <asm/io.h>
++#include <linux/spinlock.h>
++#include <asm/system.h>
++
++#ifndef MAX_DMA_CHANNELS
++#define MAX_DMA_CHANNELS 8
++#endif
++
++/* The maximum address that we can perform a DMA transfer to on this platform */
++/* Doesn't really apply... */
++#define MAX_DMA_ADDRESS (~0UL)
++
++#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)
++
++#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
++#define dma_outb outb_p
++#else
++#define dma_outb outb
++#endif
++
++#define dma_inb inb
++
++/*
++ * NOTES about DMA transfers:
++ *
++ * controller 1: channels 0-3, byte operations, ports 00-1F
++ * controller 2: channels 4-7, word operations, ports C0-DF
++ *
++ * - ALL registers are 8 bits only, regardless of transfer size
++ * - channel 4 is not used - cascades 1 into 2.
++ * - channels 0-3 are byte - addresses/counts are for physical bytes
++ * - channels 5-7 are word - addresses/counts are for physical words
++ * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
++ * - transfer count loaded to registers is 1 less than actual count
++ * - controller 2 offsets are all even (2x offsets for controller 1)
++ * - page registers for 5-7 don't use data bit 0, represent 128K pages
++ * - page registers for 0-3 use bit 0, represent 64K pages
++ *
++ * On PReP, DMA transfers are limited to the lower 16MB of _physical_ memory.
++ * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing.
++ * Note that addresses loaded into registers must be _physical_ addresses,
++ * not logical addresses (which may differ if paging is active).
++ *
++ * Address mapping for channels 0-3:
++ *
++ * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses)
++ * | ... | | ... | | ... |
++ * | ... | | ... | | ... |
++ * | ... | | ... | | ... |
++ * P7 ... P0 A7 ... A0 A7 ... A0
++ * | Page | Addr MSB | Addr LSB | (DMA registers)
++ *
++ * Address mapping for channels 5-7:
++ *
++ * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses)
++ * | ... | \ \ ... \ \ \ ... \ \
++ * | ... | \ \ ... \ \ \ ... \ (not used)
++ * | ... | \ \ ... \ \ \ ... \
++ * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0
++ * | Page | Addr MSB | Addr LSB | (DMA registers)
++ *
++ * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
++ * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
++ * the hardware level, so odd-byte transfers aren't possible).
++ *
++ * Transfer count (_not # bytes_) is limited to 64K, represented as actual
++ * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more,
++ * and up to 128K bytes may be transferred on channels 5-7 in one operation.
++ *
++ */
++
++/* see prep_setup_arch() for detailed informations */
++#if defined(CONFIG_SOUND_CS4232) && defined(CONFIG_PPC_PREP)
++extern long ppc_cs4232_dma, ppc_cs4232_dma2;
++#define SND_DMA1 ppc_cs4232_dma
++#define SND_DMA2 ppc_cs4232_dma2
++#else
++#define SND_DMA1 -1
++#define SND_DMA2 -1
++#endif
++
++/* 8237 DMA controllers */
++#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
++#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
++
++/* DMA controller registers */
++#define DMA1_CMD_REG 0x08 /* command register (w) */
++#define DMA1_STAT_REG 0x08 /* status register (r) */
++#define DMA1_REQ_REG 0x09 /* request register (w) */
++#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
++#define DMA1_MODE_REG 0x0B /* mode register (w) */
++#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
++#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
++#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
++#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
++#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
++
++#define DMA2_CMD_REG 0xD0 /* command register (w) */
++#define DMA2_STAT_REG 0xD0 /* status register (r) */
++#define DMA2_REQ_REG 0xD2 /* request register (w) */
++#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
++#define DMA2_MODE_REG 0xD6 /* mode register (w) */
++#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
++#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
++#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
++#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
++#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
++
++#define DMA_ADDR_0 0x00 /* DMA address registers */
++#define DMA_ADDR_1 0x02
++#define DMA_ADDR_2 0x04
++#define DMA_ADDR_3 0x06
++#define DMA_ADDR_4 0xC0
++#define DMA_ADDR_5 0xC4
++#define DMA_ADDR_6 0xC8
++#define DMA_ADDR_7 0xCC
++
++#define DMA_CNT_0 0x01 /* DMA count registers */
++#define DMA_CNT_1 0x03
++#define DMA_CNT_2 0x05
++#define DMA_CNT_3 0x07
++#define DMA_CNT_4 0xC2
++#define DMA_CNT_5 0xC6
++#define DMA_CNT_6 0xCA
++#define DMA_CNT_7 0xCE
++
++#define DMA_LO_PAGE_0 0x87 /* DMA page registers */
++#define DMA_LO_PAGE_1 0x83
++#define DMA_LO_PAGE_2 0x81
++#define DMA_LO_PAGE_3 0x82
++#define DMA_LO_PAGE_5 0x8B
++#define DMA_LO_PAGE_6 0x89
++#define DMA_LO_PAGE_7 0x8A
++
++#define DMA_HI_PAGE_0 0x487 /* DMA page registers */
++#define DMA_HI_PAGE_1 0x483
++#define DMA_HI_PAGE_2 0x481
++#define DMA_HI_PAGE_3 0x482
++#define DMA_HI_PAGE_5 0x48B
++#define DMA_HI_PAGE_6 0x489
++#define DMA_HI_PAGE_7 0x48A
++
++#define DMA1_EXT_REG 0x40B
++#define DMA2_EXT_REG 0x4D6
++
++#ifndef __powerpc64__
++ /* in arch/ppc/kernel/setup.c -- Cort */
++ extern unsigned int DMA_MODE_WRITE;
++ extern unsigned int DMA_MODE_READ;
++ extern unsigned long ISA_DMA_THRESHOLD;
++#else
++ #define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
++ #define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
++#endif
++
++#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
++
++#define DMA_AUTOINIT 0x10
++
++extern spinlock_t dma_spin_lock;
++
++static __inline__ unsigned long claim_dma_lock(void)
++{
++ unsigned long flags;
++ spin_lock_irqsave(&dma_spin_lock, flags);
++ return flags;
++}
++
++static __inline__ void release_dma_lock(unsigned long flags)
++{
++ spin_unlock_irqrestore(&dma_spin_lock, flags);
++}
++
++/* enable/disable a specific DMA channel */
++static __inline__ void enable_dma(unsigned int dmanr)
++{
++ unsigned char ucDmaCmd = 0x00;
++
++ if (dmanr != 4) {
++ dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */
++ dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */
++ }
++ if (dmanr <= 3) {
++ dma_outb(dmanr, DMA1_MASK_REG);
++ dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */
++ } else {
++ dma_outb(dmanr & 3, DMA2_MASK_REG);
++ }
++}
++
++static __inline__ void disable_dma(unsigned int dmanr)
++{
++ if (dmanr <= 3)
++ dma_outb(dmanr | 4, DMA1_MASK_REG);
++ else
++ dma_outb((dmanr & 3) | 4, DMA2_MASK_REG);
++}
++
++/* Clear the 'DMA Pointer Flip Flop'.
++ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
++ * Use this once to initialize the FF to a known state.
++ * After that, keep track of it. :-)
++ * --- In order to do that, the DMA routines below should ---
++ * --- only be used while interrupts are disabled! ---
++ */
++static __inline__ void clear_dma_ff(unsigned int dmanr)
++{
++ if (dmanr <= 3)
++ dma_outb(0, DMA1_CLEAR_FF_REG);
++ else
++ dma_outb(0, DMA2_CLEAR_FF_REG);
++}
++
++/* set mode (above) for a specific DMA channel */
++static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
++{
++ if (dmanr <= 3)
++ dma_outb(mode | dmanr, DMA1_MODE_REG);
++ else
++ dma_outb(mode | (dmanr & 3), DMA2_MODE_REG);
++}
++
++/* Set only the page register bits of the transfer address.
++ * This is used for successive transfers when we know the contents of
++ * the lower 16 bits of the DMA current address register, but a 64k boundary
++ * may have been crossed.
++ */
++static __inline__ void set_dma_page(unsigned int dmanr, int pagenr)
++{
++ switch (dmanr) {
++ case 0:
++ dma_outb(pagenr, DMA_LO_PAGE_0);
++ dma_outb(pagenr >> 8, DMA_HI_PAGE_0);
++ break;
++ case 1:
++ dma_outb(pagenr, DMA_LO_PAGE_1);
++ dma_outb(pagenr >> 8, DMA_HI_PAGE_1);
++ break;
++ case 2:
++ dma_outb(pagenr, DMA_LO_PAGE_2);
++ dma_outb(pagenr >> 8, DMA_HI_PAGE_2);
++ break;
++ case 3:
++ dma_outb(pagenr, DMA_LO_PAGE_3);
++ dma_outb(pagenr >> 8, DMA_HI_PAGE_3);
++ break;
++ case 5:
++ if (SND_DMA1 == 5 || SND_DMA2 == 5)
++ dma_outb(pagenr, DMA_LO_PAGE_5);
++ else
++ dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
++ dma_outb(pagenr >> 8, DMA_HI_PAGE_5);
++ break;
++ case 6:
++ if (SND_DMA1 == 6 || SND_DMA2 == 6)
++ dma_outb(pagenr, DMA_LO_PAGE_6);
++ else
++ dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
++ dma_outb(pagenr >> 8, DMA_HI_PAGE_6);
++ break;
++ case 7:
++ if (SND_DMA1 == 7 || SND_DMA2 == 7)
++ dma_outb(pagenr, DMA_LO_PAGE_7);
++ else
++ dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
++ dma_outb(pagenr >> 8, DMA_HI_PAGE_7);
++ break;
++ }
++}
++
++/* Set transfer address & page bits for specific DMA channel.
++ * Assumes dma flipflop is clear.
++ */
++static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys)
++{
++ if (dmanr <= 3) {
++ dma_outb(phys & 0xff,
++ ((dmanr & 3) << 1) + IO_DMA1_BASE);
++ dma_outb((phys >> 8) & 0xff,
++ ((dmanr & 3) << 1) + IO_DMA1_BASE);
++ } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
++ dma_outb(phys & 0xff,
++ ((dmanr & 3) << 2) + IO_DMA2_BASE);
++ dma_outb((phys >> 8) & 0xff,
++ ((dmanr & 3) << 2) + IO_DMA2_BASE);
++ dma_outb((dmanr & 3), DMA2_EXT_REG);
++ } else {
++ dma_outb((phys >> 1) & 0xff,
++ ((dmanr & 3) << 2) + IO_DMA2_BASE);
++ dma_outb((phys >> 9) & 0xff,
++ ((dmanr & 3) << 2) + IO_DMA2_BASE);
++ }
++ set_dma_page(dmanr, phys >> 16);
++}
++
++
++/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
++ * a specific DMA channel.
++ * You must ensure the parameters are valid.
++ * NOTE: from a manual: "the number of transfers is one more
++ * than the initial word count"! This is taken into account.
++ * Assumes dma flip-flop is clear.
++ * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
++ */
++static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
++{
++ count--;
++ if (dmanr <= 3) {
++ dma_outb(count & 0xff,
++ ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
++ dma_outb((count >> 8) & 0xff,
++ ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
++ } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
++ dma_outb(count & 0xff,
++ ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++ dma_outb((count >> 8) & 0xff,
++ ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++ } else {
++ dma_outb((count >> 1) & 0xff,
++ ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++ dma_outb((count >> 9) & 0xff,
++ ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++ }
++}
++
++
++/* Get DMA residue count. After a DMA transfer, this
++ * should return zero. Reading this while a DMA transfer is
++ * still in progress will return unpredictable results.
++ * If called before the channel has been used, it may return 1.
++ * Otherwise, it returns the number of _bytes_ left to transfer.
++ *
++ * Assumes DMA flip-flop is clear.
++ */
++static __inline__ int get_dma_residue(unsigned int dmanr)
++{
++ unsigned int io_port = (dmanr <= 3)
++ ? ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE
++ : ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE;
++
++ /* using short to get 16-bit wrap around */
++ unsigned short count;
++
++ count = 1 + dma_inb(io_port);
++ count += dma_inb(io_port) << 8;
++
++ return (dmanr <= 3 || dmanr == SND_DMA1 || dmanr == SND_DMA2)
++ ? count : (count << 1);
++}
++
++/* These are in kernel/dma.c: */
++
++/* reserve a DMA channel */
++extern int request_dma(unsigned int dmanr, const char *device_id);
++/* release it again */
++extern void free_dma(unsigned int dmanr);
++
++#ifdef CONFIG_PCI
++extern int isa_dma_bridge_buggy;
++#else
++#define isa_dma_bridge_buggy (0)
++#endif
++
++#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */
++
++#endif /* _ASM_POWERPC_DMA_H */
+diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/elf.h
+@@ -0,0 +1,411 @@
++#ifndef _ASM_POWERPC_ELF_H
++#define _ASM_POWERPC_ELF_H
++
++#include <asm/types.h>
++#include <asm/ptrace.h>
++#include <asm/cputable.h>
++#include <asm/auxvec.h>
++#include <asm/page.h>
++
++/* PowerPC relocations defined by the ABIs */
++#define R_PPC_NONE 0
++#define R_PPC_ADDR32 1 /* 32bit absolute address */
++#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
++#define R_PPC_ADDR16 3 /* 16bit absolute address */
++#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
++#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
++#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
++#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
++#define R_PPC_ADDR14_BRTAKEN 8
++#define R_PPC_ADDR14_BRNTAKEN 9
++#define R_PPC_REL24 10 /* PC relative 26 bit */
++#define R_PPC_REL14 11 /* PC relative 16 bit */
++#define R_PPC_REL14_BRTAKEN 12
++#define R_PPC_REL14_BRNTAKEN 13
++#define R_PPC_GOT16 14
++#define R_PPC_GOT16_LO 15
++#define R_PPC_GOT16_HI 16
++#define R_PPC_GOT16_HA 17
++#define R_PPC_PLTREL24 18
++#define R_PPC_COPY 19
++#define R_PPC_GLOB_DAT 20
++#define R_PPC_JMP_SLOT 21
++#define R_PPC_RELATIVE 22
++#define R_PPC_LOCAL24PC 23
++#define R_PPC_UADDR32 24
++#define R_PPC_UADDR16 25
++#define R_PPC_REL32 26
++#define R_PPC_PLT32 27
++#define R_PPC_PLTREL32 28
++#define R_PPC_PLT16_LO 29
++#define R_PPC_PLT16_HI 30
++#define R_PPC_PLT16_HA 31
++#define R_PPC_SDAREL16 32
++#define R_PPC_SECTOFF 33
++#define R_PPC_SECTOFF_LO 34
++#define R_PPC_SECTOFF_HI 35
++#define R_PPC_SECTOFF_HA 36
++
++/* PowerPC relocations defined for the TLS access ABI. */
++#define R_PPC_TLS 67 /* none (sym+add)@tls */
++#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
++#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
++#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */
++#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */
++#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */
++#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
++#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
++#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */
++#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */
++#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */
++#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
++#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */
++#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */
++#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */
++#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */
++#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */
++#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */
++#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */
++#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */
++#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got at tprel */
++#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got at tprel@l */
++#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */
++#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */
++#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got at dtprel */
++#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got at dtprel@l */
++#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got at dtprel@h */
++#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got at dtprel@ha */
++
++/* keep this the last entry. */
++#define R_PPC_NUM 95
++
++/*
++ * ELF register definitions..
++ *
++ * 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 <asm/ptrace.h>
++
++#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
++#define ELF_NFPREG 33 /* includes fpscr */
++
++typedef unsigned long elf_greg_t64;
++typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
++
++typedef unsigned int elf_greg_t32;
++typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
++
++/*
++ * ELF_ARCH, CLASS, and DATA are used to set parameters in the core dumps.
++ */
++#ifdef __powerpc64__
++# define ELF_NVRREG32 33 /* includes vscr & vrsave stuffed together */
++# define ELF_NVRREG 34 /* includes vscr & vrsave in split vectors */
++# define ELF_GREG_TYPE elf_greg_t64
++#else
++# define ELF_NEVRREG 34 /* includes acc (as 2) */
++# define ELF_NVRREG 33 /* includes vscr */
++# define ELF_GREG_TYPE elf_greg_t32
++# define ELF_ARCH EM_PPC
++# define ELF_CLASS ELFCLASS32
++# define ELF_DATA ELFDATA2MSB
++#endif /* __powerpc64__ */
++
++#ifndef ELF_ARCH
++# define ELF_ARCH EM_PPC64
++# define ELF_CLASS ELFCLASS64
++# define ELF_DATA ELFDATA2MSB
++ typedef elf_greg_t64 elf_greg_t;
++ typedef elf_gregset_t64 elf_gregset_t;
++# define elf_addr_t unsigned long
++#else
++ /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */
++ typedef elf_greg_t32 elf_greg_t;
++ typedef elf_gregset_t32 elf_gregset_t;
++# define elf_addr_t u32
++#endif /* ELF_ARCH */
++
++/* Floating point registers */
++typedef double elf_fpreg_t;
++typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
++
++/* Altivec registers */
++/*
++ * The entries with indexes 0-31 contain the corresponding vector registers.
++ * The entry with index 32 contains the vscr as the last word (offset 12)
++ * within the quadword. This allows the vscr to be stored as either a
++ * quadword (since it must be copied via a vector register to/from storage)
++ * or as a word.
++ *
++ * 64-bit kernel notes: The entry at index 33 contains the vrsave as the first
++ * word (offset 0) within the quadword.
++ *
++ * This definition of the VMX state is compatible with the current PPC32
++ * ptrace interface. This allows signal handling and ptrace to use the same
++ * structures. This also simplifies the implementation of a bi-arch
++ * (combined (32- and 64-bit) gdb.
++ *
++ * Note that it's _not_ compatible with 32 bits ucontext which stuffs the
++ * vrsave along with vscr and so only uses 33 vectors for the register set
++ */
++typedef __vector128 elf_vrreg_t;
++typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG];
++#ifdef __powerpc64__
++typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
++#endif
++
++/*
++ * This is used to ensure we don't load something for the wrong architecture.
++ */
++#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE PAGE_SIZE
++
++/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
++ use of this is to invoke "./ld.so someprog" to test out a new version of
++ the loader. We need to make sure that it is out of the way of the program
++ that it will "exec", and that there is sufficient room for the brk. */
++
++#define ELF_ET_DYN_BASE (0x08000000)
++
++#ifdef __KERNEL__
++
++/* Common routine for both 32-bit and 64-bit processes */
++static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs,
++ struct pt_regs *regs)
++{
++ int i;
++ int gprs = sizeof(struct pt_regs)/sizeof(ELF_GREG_TYPE);
++
++ if (gprs > ELF_NGREG)
++ gprs = ELF_NGREG;
++
++ for (i=0; i < gprs; i++)
++ elf_regs[i] = (elf_greg_t)((ELF_GREG_TYPE *)regs)[i];
++
++ memset((char *)(elf_regs) + sizeof(struct pt_regs), 0, \
++ sizeof(elf_gregset_t) - sizeof(struct pt_regs));
++
++}
++#define ELF_CORE_COPY_REGS(gregs, regs) ppc_elf_core_copy_regs(gregs, regs);
++
++static inline int dump_task_regs(struct task_struct *tsk,
++ elf_gregset_t *elf_regs)
++{
++ struct pt_regs *regs = tsk->thread.regs;
++ if (regs)
++ ppc_elf_core_copy_regs(*elf_regs, regs);
++
++ return 1;
++}
++#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
++
++extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
++#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
++
++#endif /* __KERNEL__ */
++
++/* ELF_HWCAP yields a mask that user programs can use to figure out what
++ instruction set this cpu supports. This could be done in userspace,
++ but it's not easy, and we've already done it here. */
++# define ELF_HWCAP (cur_cpu_spec->cpu_user_features)
++#ifdef __powerpc64__
++# define ELF_PLAT_INIT(_r, load_addr) do { \
++ _r->gpr[2] = load_addr; \
++} while (0)
++#endif /* __powerpc64__ */
++
++/* This yields a string that ld.so will use to load implementation
++ specific libraries for optimization. This is more specific in
++ intent than poking at uname or /proc/cpuinfo.
++
++ For the moment, we have only optimizations for the Intel generations,
++ but that could change... */
++
++#define ELF_PLATFORM (NULL)
++
++#ifdef __KERNEL__
++
++#ifdef __powerpc64__
++# define SET_PERSONALITY(ex, ibcs2) \
++do { \
++ unsigned long new_flags = 0; \
++ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
++ new_flags = _TIF_32BIT; \
++ if ((current_thread_info()->flags & _TIF_32BIT) \
++ != new_flags) \
++ set_thread_flag(TIF_ABI_PENDING); \
++ else \
++ clear_thread_flag(TIF_ABI_PENDING); \
++ if (personality(current->personality) != PER_LINUX32) \
++ set_personality(PER_LINUX); \
++} while (0)
++/*
++ * An executable for which elf_read_implies_exec() returns TRUE will
++ * have the READ_IMPLIES_EXEC personality flag set automatically. This
++ * is only required to work around bugs in old 32bit toolchains. Since
++ * the 64bit ABI has never had these issues dont enable the workaround
++ * even if we have an executable stack.
++ */
++# define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
++ (exec_stk != EXSTACK_DISABLE_X) : 0)
++#else
++# define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
++#endif /* __powerpc64__ */
++
++#endif /* __KERNEL__ */
++
++extern int dcache_bsize;
++extern int icache_bsize;
++extern int ucache_bsize;
++
++#ifdef __powerpc64__
++struct linux_binprm;
++#define ARCH_HAS_SETUP_ADDITIONAL_PAGES /* vDSO has arch_setup_additional_pages */
++extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack);
++#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b);
++#else
++#define VDSO_AUX_ENT(a,b)
++#endif /* __powerpc64__ */
++
++/*
++ * The requirements here are:
++ * - keep the final alignment of sp (sp & 0xf)
++ * - make sure the 32-bit value at the first 16 byte aligned position of
++ * AUXV is greater than 16 for glibc compatibility.
++ * AT_IGNOREPPC is used for that.
++ * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
++ * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
++ */
++#define ARCH_DLINFO \
++do { \
++ /* Handle glibc compatibility. */ \
++ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
++ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
++ /* Cache size items */ \
++ NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
++ NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
++ NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
++ VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base) \
++} while (0)
++
++/* PowerPC64 relocations defined by the ABIs */
++#define R_PPC64_NONE R_PPC_NONE
++#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */
++#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */
++#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */
++#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */
++#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */
++#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
++#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */
++#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
++#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
++#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */
++#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */
++#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
++#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
++#define R_PPC64_GOT16 R_PPC_GOT16
++#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
++#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
++#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
++
++#define R_PPC64_COPY R_PPC_COPY
++#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
++#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
++#define R_PPC64_RELATIVE R_PPC_RELATIVE
++
++#define R_PPC64_UADDR32 R_PPC_UADDR32
++#define R_PPC64_UADDR16 R_PPC_UADDR16
++#define R_PPC64_REL32 R_PPC_REL32
++#define R_PPC64_PLT32 R_PPC_PLT32
++#define R_PPC64_PLTREL32 R_PPC_PLTREL32
++#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
++#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
++#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
++
++#define R_PPC64_SECTOFF R_PPC_SECTOFF
++#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
++#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
++#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
++#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */
++#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */
++#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */
++#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */
++#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */
++#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */
++#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */
++#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */
++#define R_PPC64_PLT64 45 /* doubleword64 L + A. */
++#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */
++#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */
++#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */
++#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */
++#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */
++#define R_PPC64_TOC 51 /* doubleword64 .TOC. */
++#define R_PPC64_PLTGOT16 52 /* half16* M + A. */
++#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */
++#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */
++#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */
++
++#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */
++#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */
++#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */
++#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */
++#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */
++#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */
++#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */
++#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */
++#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */
++#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */
++#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */
++
++/* PowerPC64 relocations defined for the TLS access ABI. */
++#define R_PPC64_TLS 67 /* none (sym+add)@tls */
++#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
++#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
++#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */
++#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */
++#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */
++#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
++#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
++#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */
++#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */
++#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */
++#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
++#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */
++#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */
++#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */
++#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */
++#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */
++#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */
++#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */
++#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */
++#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got at tprel */
++#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got at tprel@l */
++#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */
++#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */
++#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got at dtprel */
++#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got at dtprel@l */
++#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got at dtprel@h */
++#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got at dtprel@ha */
++#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
++#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel at l */
++#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel at higher */
++#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel at highera */
++#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel at highest */
++#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel at highesta */
++#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
++#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel at l */
++#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel at higher */
++#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel at highera */
++#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel at highest */
++#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel at highesta */
++
++/* Keep this the last entry. */
++#define R_PPC64_NUM 107
++
++#endif /* _ASM_POWERPC_ELF_H */
+diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/firmware.h
+@@ -0,0 +1,97 @@
++/*
++ * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * Modifications for ppc64:
++ * Copyright (C) 2003 Dave Engebretsen <engebret at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++#ifndef __ASM_POWERPC_FIRMWARE_H
++#define __ASM_POWERPC_FIRMWARE_H
++
++#ifdef __KERNEL__
++
++#ifndef __ASSEMBLY__
++
++/* firmware feature bitmask values */
++#define FIRMWARE_MAX_FEATURES 63
++
++#define FW_FEATURE_PFT (1UL<<0)
++#define FW_FEATURE_TCE (1UL<<1)
++#define FW_FEATURE_SPRG0 (1UL<<2)
++#define FW_FEATURE_DABR (1UL<<3)
++#define FW_FEATURE_COPY (1UL<<4)
++#define FW_FEATURE_ASR (1UL<<5)
++#define FW_FEATURE_DEBUG (1UL<<6)
++#define FW_FEATURE_TERM (1UL<<7)
++#define FW_FEATURE_PERF (1UL<<8)
++#define FW_FEATURE_DUMP (1UL<<9)
++#define FW_FEATURE_INTERRUPT (1UL<<10)
++#define FW_FEATURE_MIGRATE (1UL<<11)
++#define FW_FEATURE_PERFMON (1UL<<12)
++#define FW_FEATURE_CRQ (1UL<<13)
++#define FW_FEATURE_VIO (1UL<<14)
++#define FW_FEATURE_RDMA (1UL<<15)
++#define FW_FEATURE_LLAN (1UL<<16)
++#define FW_FEATURE_BULK (1UL<<17)
++#define FW_FEATURE_XDABR (1UL<<18)
++#define FW_FEATURE_MULTITCE (1UL<<19)
++#define FW_FEATURE_SPLPAR (1UL<<20)
++#define FW_FEATURE_ISERIES (1UL<<21)
++
++enum {
++ FW_FEATURE_PSERIES_POSSIBLE = FW_FEATURE_PFT | FW_FEATURE_TCE |
++ FW_FEATURE_SPRG0 | FW_FEATURE_DABR | FW_FEATURE_COPY |
++ FW_FEATURE_ASR | FW_FEATURE_DEBUG | FW_FEATURE_TERM |
++ FW_FEATURE_PERF | FW_FEATURE_DUMP | FW_FEATURE_INTERRUPT |
++ FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
++ FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
++ FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
++ FW_FEATURE_SPLPAR,
++ FW_FEATURE_PSERIES_ALWAYS = 0,
++ FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES,
++ FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES,
++ FW_FEATURE_POSSIBLE =
++#ifdef CONFIG_PPC_PSERIES
++ FW_FEATURE_PSERIES_POSSIBLE |
++#endif
++#ifdef CONFIG_PPC_ISERIES
++ FW_FEATURE_ISERIES_POSSIBLE |
++#endif
++ 0,
++ FW_FEATURE_ALWAYS =
++#ifdef CONFIG_PPC_PSERIES
++ FW_FEATURE_PSERIES_ALWAYS &
++#endif
++#ifdef CONFIG_PPC_ISERIES
++ FW_FEATURE_ISERIES_ALWAYS &
++#endif
++ FW_FEATURE_POSSIBLE,
++};
++
++/* This is used to identify firmware features which are available
++ * to the kernel.
++ */
++extern unsigned long ppc64_firmware_features;
++
++static inline unsigned long firmware_has_feature(unsigned long feature)
++{
++ return (FW_FEATURE_ALWAYS & feature) ||
++ (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
++}
++
++#ifdef CONFIG_PPC_PSERIES
++typedef struct {
++ unsigned long val;
++ char * name;
++} firmware_feature_t;
++
++extern firmware_feature_t firmware_features_table[];
++#endif
++
++#endif /* __ASSEMBLY__ */
++#endif /* __KERNEL__ */
++#endif /* __ASM_POWERPC_FIRMWARE_H */
+diff --git a/include/asm-powerpc/grackle.h b/include/asm-powerpc/grackle.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/grackle.h
+@@ -0,0 +1,7 @@
++/*
++ * Functions for setting up and using a MPC106 northbridge
++ */
++
++#include <asm/pci-bridge.h>
++
++extern void setup_grackle(struct pci_controller *hose);
+diff --git a/include/asm-powerpc/hardirq.h b/include/asm-powerpc/hardirq.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/hardirq.h
+@@ -0,0 +1,27 @@
++#ifndef _ASM_POWERPC_HARDIRQ_H
++#define _ASM_POWERPC_HARDIRQ_H
++
++#include <asm/irq.h>
++#include <asm/bug.h>
++
++/* The __last_jiffy_stamp field is needed to ensure that no decrementer
++ * interrupt is lost on SMP machines. Since on most CPUs it is in the same
++ * cache line as local_irq_count, it is cheap to access and is also used on UP
++ * for uniformity.
++ */
++typedef struct {
++ unsigned int __softirq_pending; /* set_bit is used on this */
++ unsigned int __last_jiffy_stamp;
++} ____cacheline_aligned irq_cpustat_t;
++
++#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
++
++#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp)
++
++static inline void ack_bad_irq(int irq)
++{
++ printk(KERN_CRIT "illegal vector %d received!\n", irq);
++ BUG();
++}
++
++#endif /* _ASM_POWERPC_HARDIRQ_H */
+diff --git a/include/asm-powerpc/heathrow.h b/include/asm-powerpc/heathrow.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/heathrow.h
+@@ -0,0 +1,62 @@
++/*
++ * heathrow.h: definitions for using the "Heathrow" I/O controller chip.
++ *
++ * Grabbed from Open Firmware definitions on a PowerBook G3 Series
++ *
++ * Copyright (C) 1997 Paul Mackerras.
++ */
++
++/* Front light color on Yikes/B&W G3. 32 bits */
++#define HEATHROW_FRONT_LIGHT 0x32 /* (set to 0 or 0xffffffff) */
++
++/* Brightness/contrast (gossamer iMac ?). 8 bits */
++#define HEATHROW_BRIGHTNESS_CNTL 0x32
++#define HEATHROW_CONTRAST_CNTL 0x33
++
++/* offset from ohare base for feature control register */
++#define HEATHROW_MBCR 0x34 /* Media bay control */
++#define HEATHROW_FCR 0x38 /* Feature control */
++#define HEATHROW_AUX_CNTL_REG 0x3c /* Aux control */
++
++/*
++ * Bits in feature control register.
++ * Bits postfixed with a _N are in inverse logic
++ */
++#define HRW_SCC_TRANS_EN_N 0x00000001 /* Also controls modem power */
++#define HRW_BAY_POWER_N 0x00000002
++#define HRW_BAY_PCI_ENABLE 0x00000004
++#define HRW_BAY_IDE_ENABLE 0x00000008
++#define HRW_BAY_FLOPPY_ENABLE 0x00000010
++#define HRW_IDE0_ENABLE 0x00000020
++#define HRW_IDE0_RESET_N 0x00000040
++#define HRW_BAY_DEV_MASK 0x0000001c
++#define HRW_BAY_RESET_N 0x00000080
++#define HRW_IOBUS_ENABLE 0x00000100 /* Internal IDE ? */
++#define HRW_SCC_ENABLE 0x00000200
++#define HRW_MESH_ENABLE 0x00000400
++#define HRW_SWIM_ENABLE 0x00000800
++#define HRW_SOUND_POWER_N 0x00001000
++#define HRW_SOUND_CLK_ENABLE 0x00002000
++#define HRW_SCCA_IO 0x00004000
++#define HRW_SCCB_IO 0x00008000
++#define HRW_PORT_OR_DESK_VIA_N 0x00010000 /* This one is 0 on PowerBook */
++#define HRW_PWM_MON_ID_N 0x00020000 /* ??? (0) */
++#define HRW_HOOK_MB_CNT_N 0x00040000 /* ??? (0) */
++#define HRW_SWIM_CLONE_FLOPPY 0x00080000 /* ??? (0) */
++#define HRW_AUD_RUN22 0x00100000 /* ??? (1) */
++#define HRW_SCSI_LINK_MODE 0x00200000 /* Read ??? (1) */
++#define HRW_ARB_BYPASS 0x00400000 /* Disable internal PCI arbitrer */
++#define HRW_IDE1_RESET_N 0x00800000 /* Media bay */
++#define HRW_SLOW_SCC_PCLK 0x01000000 /* ??? (0) */
++#define HRW_RESET_SCC 0x02000000
++#define HRW_MFDC_CELL_ENABLE 0x04000000 /* ??? (0) */
++#define HRW_USE_MFDC 0x08000000 /* ??? (0) */
++#define HRW_BMAC_IO_ENABLE 0x60000000 /* two bits, not documented in OF */
++#define HRW_BMAC_RESET 0x80000000 /* not documented in OF */
++
++/* We OR those features at boot on desktop G3s */
++#define HRW_DEFAULTS (HRW_SCCA_IO | HRW_SCCB_IO | HRW_SCC_ENABLE)
++
++/* Looks like Heathrow has some sort of GPIOs as well... */
++#define HRW_GPIO_MODEM_RESET 0x6d
++
+diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/hw_irq.h
+@@ -0,0 +1,114 @@
++/*
++ * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
++ */
++#ifndef _ASM_POWERPC_HW_IRQ_H
++#define _ASM_POWERPC_HW_IRQ_H
++
++#ifdef __KERNEL__
++
++#include <linux/config.h>
++#include <linux/errno.h>
++#include <asm/ptrace.h>
++#include <asm/processor.h>
++
++extern void timer_interrupt(struct pt_regs *);
++extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
++
++#ifdef CONFIG_PPC_ISERIES
++
++extern unsigned long local_get_flags(void);
++extern unsigned long local_irq_disable(void);
++extern void local_irq_restore(unsigned long);
++
++#define local_irq_enable() local_irq_restore(1)
++#define local_save_flags(flags) ((flags) = local_get_flags())
++#define local_irq_save(flags) ((flags) = local_irq_disable())
++
++#define irqs_disabled() (local_get_flags() == 0)
++
++#else
++
++#if defined(CONFIG_BOOKE)
++#define SET_MSR_EE(x) mtmsr(x)
++#define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
++#elif defined(__powerpc64__)
++#define SET_MSR_EE(x) __mtmsrd(x, 1)
++#define local_irq_restore(flags) do { \
++ __asm__ __volatile__("": : :"memory"); \
++ __mtmsrd((flags), 1); \
++} while(0)
++#else
++#define SET_MSR_EE(x) mtmsr(x)
++#define local_irq_restore(flags) mtmsr(flags)
++#endif
++
++static inline void local_irq_disable(void)
++{
++#ifdef CONFIG_BOOKE
++ __asm__ __volatile__("wrteei 0": : :"memory");
++#else
++ unsigned long msr;
++ __asm__ __volatile__("": : :"memory");
++ msr = mfmsr();
++ SET_MSR_EE(msr & ~MSR_EE);
++#endif
++}
++
++static inline void local_irq_enable(void)
++{
++#ifdef CONFIG_BOOKE
++ __asm__ __volatile__("wrteei 1": : :"memory");
++#else
++ unsigned long msr;
++ __asm__ __volatile__("": : :"memory");
++ msr = mfmsr();
++ SET_MSR_EE(msr | MSR_EE);
++#endif
++}
++
++static inline void local_irq_save_ptr(unsigned long *flags)
++{
++ unsigned long msr;
++ msr = mfmsr();
++ *flags = msr;
++#ifdef CONFIG_BOOKE
++ __asm__ __volatile__("wrteei 0": : :"memory");
++#else
++ SET_MSR_EE(msr & ~MSR_EE);
++#endif
++ __asm__ __volatile__("": : :"memory");
++}
++
++#define local_save_flags(flags) ((flags) = mfmsr())
++#define local_irq_save(flags) local_irq_save_ptr(&flags)
++#define irqs_disabled() ((mfmsr() & MSR_EE) == 0)
++
++#endif /* CONFIG_PPC_ISERIES */
++
++#define mask_irq(irq) \
++ ({ \
++ irq_desc_t *desc = get_irq_desc(irq); \
++ if (desc->handler && desc->handler->disable) \
++ desc->handler->disable(irq); \
++ })
++#define unmask_irq(irq) \
++ ({ \
++ irq_desc_t *desc = get_irq_desc(irq); \
++ if (desc->handler && desc->handler->enable) \
++ desc->handler->enable(irq); \
++ })
++#define ack_irq(irq) \
++ ({ \
++ irq_desc_t *desc = get_irq_desc(irq); \
++ if (desc->handler && desc->handler->ack) \
++ desc->handler->ack(irq); \
++ })
++
++/* Should we handle this via lost interrupts and IPIs or should we don't care like
++ * we do now ? --BenH.
++ */
++struct hw_interrupt_type;
++static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
++
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_HW_IRQ_H */
+diff --git a/include/asm-powerpc/i8259.h b/include/asm-powerpc/i8259.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/i8259.h
+@@ -0,0 +1,12 @@
++#ifndef _ASM_POWERPC_I8259_H
++#define _ASM_POWERPC_I8259_H
++
++#include <linux/irq.h>
++
++extern struct hw_interrupt_type i8259_pic;
++
++extern void i8259_init(unsigned long intack_addr, int offset);
++extern int i8259_irq(struct pt_regs *regs);
++extern int i8259_irq_cascade(struct pt_regs *regs, void *unused);
++
++#endif /* _ASM_POWERPC_I8259_H */
+diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/iommu.h
+@@ -0,0 +1,113 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
++ * Rewrite, cleanup:
++ * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _ASM_IOMMU_H
++#define _ASM_IOMMU_H
++
++#include <linux/config.h>
++#include <asm/types.h>
++#include <linux/spinlock.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++
++/*
++ * IOMAP_MAX_ORDER defines the largest contiguous block
++ * of dma space we can get. IOMAP_MAX_ORDER = 13
++ * allows up to 2**12 pages (4096 * 4096) = 16 MB
++ */
++#define IOMAP_MAX_ORDER 13
++
++struct iommu_table {
++ unsigned long it_busno; /* Bus number this table belongs to */
++ unsigned long it_size; /* Size of iommu table in entries */
++ unsigned long it_offset; /* Offset into global table */
++ unsigned long it_base; /* mapped address of tce table */
++ unsigned long it_index; /* which iommu table this is */
++ unsigned long it_type; /* type: PCI or Virtual Bus */
++ unsigned long it_blocksize; /* Entries in each block (cacheline) */
++ unsigned long it_hint; /* Hint for next alloc */
++ unsigned long it_largehint; /* Hint for large allocs */
++ unsigned long it_halfpoint; /* Breaking point for small/large allocs */
++ spinlock_t it_lock; /* Protects it_map */
++ unsigned long *it_map; /* A simple allocation bitmap for now */
++};
++
++struct scatterlist;
++struct device_node;
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++
++/* Walks all buses and creates iommu tables */
++extern void iommu_setup_pSeries(void);
++extern void iommu_setup_u3(void);
++
++/* Frees table for an individual device node */
++extern void iommu_free_table(struct device_node *dn);
++
++#endif /* CONFIG_PPC_MULTIPLATFORM */
++
++#ifdef CONFIG_PPC_PSERIES
++
++/* Creates table for an individual device node */
++extern void iommu_devnode_init_pSeries(struct device_node *dn);
++
++#endif /* CONFIG_PPC_PSERIES */
++
++#ifdef CONFIG_PPC_ISERIES
++
++/* Creates table for an individual device node */
++extern void iommu_devnode_init_iSeries(struct device_node *dn);
++
++#endif /* CONFIG_PPC_ISERIES */
++
++/* Initializes an iommu_table based in values set in the passed-in
++ * structure
++ */
++extern struct iommu_table *iommu_init_table(struct iommu_table * tbl);
++
++extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
++ struct scatterlist *sglist, int nelems,
++ enum dma_data_direction direction);
++extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
++ int nelems, enum dma_data_direction direction);
++
++extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
++ dma_addr_t *dma_handle, gfp_t flag);
++extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
++ void *vaddr, dma_addr_t dma_handle);
++extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
++ size_t size, enum dma_data_direction direction);
++extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
++ size_t size, enum dma_data_direction direction);
++
++extern void iommu_init_early_pSeries(void);
++extern void iommu_init_early_iSeries(void);
++extern void iommu_init_early_u3(void);
++
++#ifdef CONFIG_PCI
++extern void pci_iommu_init(void);
++extern void pci_direct_iommu_init(void);
++#else
++static inline void pci_iommu_init(void) { }
++#endif
++
++extern void alloc_u3_dart_table(void);
++
++#endif /* _ASM_IOMMU_H */
+diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/irq.h
+@@ -0,0 +1,504 @@
++#ifdef __KERNEL__
++#ifndef _ASM_POWERPC_IRQ_H
++#define _ASM_POWERPC_IRQ_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.
++ */
++
++#include <linux/config.h>
++#include <linux/threads.h>
++
++#include <asm/types.h>
++#include <asm/atomic.h>
++
++/* this number is used when no interrupt has been assigned */
++#define NO_IRQ (-1)
++
++/*
++ * These constants are used for passing information about interrupt
++ * signal polarity and level/edge sensing to the low-level PIC chip
++ * drivers.
++ */
++#define IRQ_SENSE_MASK 0x1
++#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */
++#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */
++
++#define IRQ_POLARITY_MASK 0x2
++#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */
++#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */
++
++/*
++ * IRQ line status macro IRQ_PER_CPU is used
++ */
++#define ARCH_HAS_IRQ_PER_CPU
++
++#define get_irq_desc(irq) (&irq_desc[(irq)])
++
++/* Define a way to iterate across irqs. */
++#define for_each_irq(i) \
++ for ((i) = 0; (i) < NR_IRQS; ++(i))
++
++#ifdef CONFIG_PPC64
++
++/*
++ * Maximum number of interrupt sources that we can handle.
++ */
++#define NR_IRQS 512
++
++/* Interrupt numbers are virtual in case they are sparsely
++ * distributed by the hardware.
++ */
++extern unsigned int virt_irq_to_real_map[NR_IRQS];
++
++/* Create a mapping for a real_irq if it doesn't already exist.
++ * Return the virtual irq as a convenience.
++ */
++int virt_irq_create_mapping(unsigned int real_irq);
++void virt_irq_init(void);
++
++static inline unsigned int virt_irq_to_real(unsigned int virt_irq)
++{
++ return virt_irq_to_real_map[virt_irq];
++}
++
++extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq);
++
++/*
++ * List of interrupt controllers.
++ */
++#define IC_INVALID 0
++#define IC_OPEN_PIC 1
++#define IC_PPC_XIC 2
++#define IC_BPA_IIC 3
++#define IC_ISERIES 4
++
++extern u64 ppc64_interrupt_controller;
++
++#else /* 32-bit */
++
++#if defined(CONFIG_40x)
++#include <asm/ibm4xx.h>
++
++#ifndef NR_BOARD_IRQS
++#define NR_BOARD_IRQS 0
++#endif
++
++#ifndef UIC_WIDTH /* Number of interrupts per device */
++#define UIC_WIDTH 32
++#endif
++
++#ifndef NR_UICS /* number of UIC devices */
++#define NR_UICS 1
++#endif
++
++#if defined (CONFIG_403)
++/*
++ * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
++ * 32 possible interrupts, a majority of which are not implemented on
++ * all cores. There are six configurable, external interrupt pins and
++ * there are eight internal interrupts for the on-chip serial port
++ * (SPU), DMA controller, and JTAG controller.
++ *
++ */
++
++#define NR_AIC_IRQS 32
++#define NR_IRQS (NR_AIC_IRQS + NR_BOARD_IRQS)
++
++#elif !defined (CONFIG_403)
++
++/*
++ * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32
++ * possible interrupts as well. There are seven, configurable external
++ * interrupt pins and there are 17 internal interrupts for the on-chip
++ * serial port, DMA controller, on-chip Ethernet controller, PCI, etc.
++ *
++ */
++
++
++#define NR_UIC_IRQS UIC_WIDTH
++#define NR_IRQS ((NR_UIC_IRQS * NR_UICS) + NR_BOARD_IRQS)
++#endif
++
++#elif defined(CONFIG_44x)
++#include <asm/ibm44x.h>
++
++#define NR_UIC_IRQS 32
++#define NR_IRQS ((NR_UIC_IRQS * NR_UICS) + NR_BOARD_IRQS)
++
++#elif defined(CONFIG_8xx)
++
++/* Now include the board configuration specific associations.
++*/
++#include <asm/mpc8xx.h>
++
++/* The MPC8xx cores have 16 possible interrupts. There are eight
++ * possible level sensitive interrupts assigned and generated internally
++ * from such devices as CPM, PCMCIA, RTC, PIT, TimeBase and Decrementer.
++ * There are eight external interrupts (IRQs) that can be configured
++ * as either level or edge sensitive.
++ *
++ * On some implementations, there is also the possibility of an 8259
++ * through the PCI and PCI-ISA bridges.
++ *
++ * We are "flattening" the interrupt vectors of the cascaded CPM
++ * and 8259 interrupt controllers so that we can uniquely identify
++ * any interrupt source with a single integer.
++ */
++#define NR_SIU_INTS 16
++#define NR_CPM_INTS 32
++#ifndef NR_8259_INTS
++#define NR_8259_INTS 0
++#endif
++
++#define SIU_IRQ_OFFSET 0
++#define CPM_IRQ_OFFSET (SIU_IRQ_OFFSET + NR_SIU_INTS)
++#define I8259_IRQ_OFFSET (CPM_IRQ_OFFSET + NR_CPM_INTS)
++
++#define NR_IRQS (NR_SIU_INTS + NR_CPM_INTS + NR_8259_INTS)
++
++/* These values must be zero-based and map 1:1 with the SIU configuration.
++ * They are used throughout the 8xx I/O subsystem to generate
++ * interrupt masks, flags, and other control patterns. This is why the
++ * current kernel assumption of the 8259 as the base controller is such
++ * a pain in the butt.
++ */
++#define SIU_IRQ0 (0) /* Highest priority */
++#define SIU_LEVEL0 (1)
++#define SIU_IRQ1 (2)
++#define SIU_LEVEL1 (3)
++#define SIU_IRQ2 (4)
++#define SIU_LEVEL2 (5)
++#define SIU_IRQ3 (6)
++#define SIU_LEVEL3 (7)
++#define SIU_IRQ4 (8)
++#define SIU_LEVEL4 (9)
++#define SIU_IRQ5 (10)
++#define SIU_LEVEL5 (11)
++#define SIU_IRQ6 (12)
++#define SIU_LEVEL6 (13)
++#define SIU_IRQ7 (14)
++#define SIU_LEVEL7 (15)
++
++#define MPC8xx_INT_FEC1 SIU_LEVEL1
++#define MPC8xx_INT_FEC2 SIU_LEVEL3
++
++#define MPC8xx_INT_SCC1 (CPM_IRQ_OFFSET + CPMVEC_SCC1)
++#define MPC8xx_INT_SCC2 (CPM_IRQ_OFFSET + CPMVEC_SCC2)
++#define MPC8xx_INT_SCC3 (CPM_IRQ_OFFSET + CPMVEC_SCC3)
++#define MPC8xx_INT_SCC4 (CPM_IRQ_OFFSET + CPMVEC_SCC4)
++#define MPC8xx_INT_SMC1 (CPM_IRQ_OFFSET + CPMVEC_SMC1)
++#define MPC8xx_INT_SMC2 (CPM_IRQ_OFFSET + CPMVEC_SMC2)
++
++/* The internal interrupts we can configure as we see fit.
++ * My personal preference is CPM at level 2, which puts it above the
++ * MBX PCI/ISA/IDE interrupts.
++ */
++#ifndef PIT_INTERRUPT
++#define PIT_INTERRUPT SIU_LEVEL0
++#endif
++#ifndef CPM_INTERRUPT
++#define CPM_INTERRUPT SIU_LEVEL2
++#endif
++#ifndef PCMCIA_INTERRUPT
++#define PCMCIA_INTERRUPT SIU_LEVEL6
++#endif
++#ifndef DEC_INTERRUPT
++#define DEC_INTERRUPT SIU_LEVEL7
++#endif
++
++/* Some internal interrupt registers use an 8-bit mask for the interrupt
++ * level instead of a number.
++ */
++#define mk_int_int_mask(IL) (1 << (7 - (IL/2)))
++
++#elif defined(CONFIG_83xx)
++#include <asm/mpc83xx.h>
++
++#define NR_IRQS (NR_IPIC_INTS)
++
++#elif defined(CONFIG_85xx)
++/* Now include the board configuration specific associations.
++*/
++#include <asm/mpc85xx.h>
++
++/* The MPC8548 openpic has 48 internal interrupts and 12 external
++ * interrupts.
++ *
++ * We are "flattening" the interrupt vectors of the cascaded CPM
++ * so that we can uniquely identify any interrupt source with a
++ * single integer.
++ */
++#define NR_CPM_INTS 64
++#define NR_EPIC_INTS 60
++#ifndef NR_8259_INTS
++#define NR_8259_INTS 0
++#endif
++#define NUM_8259_INTERRUPTS NR_8259_INTS
++
++#ifndef CPM_IRQ_OFFSET
++#define CPM_IRQ_OFFSET 0
++#endif
++
++#define NR_IRQS (NR_EPIC_INTS + NR_CPM_INTS + NR_8259_INTS)
++
++/* Internal IRQs on MPC85xx OpenPIC */
++
++#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
++#ifdef CONFIG_CPM2
++#define MPC85xx_OPENPIC_IRQ_OFFSET (CPM_IRQ_OFFSET + NR_CPM_INTS)
++#else
++#define MPC85xx_OPENPIC_IRQ_OFFSET 0
++#endif
++#endif
++
++/* Not all of these exist on all MPC85xx implementations */
++#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC3_TX (15 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC3_RX (16 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC3_ERROR (17 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC4_TX (21 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC4_RX (22 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC4_ERROR (23 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
++
++/* The 12 external interrupt lines */
++#define MPC85xx_IRQ_EXT0 (48 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT1 (49 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT2 (50 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT3 (51 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT4 (52 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT5 (53 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT6 (54 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT7 (55 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT8 (56 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT9 (57 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT10 (58 + MPC85xx_OPENPIC_IRQ_OFFSET)
++#define MPC85xx_IRQ_EXT11 (59 + MPC85xx_OPENPIC_IRQ_OFFSET)
++
++/* CPM related interrupts */
++#define SIU_INT_ERROR ((uint)0x00+CPM_IRQ_OFFSET)
++#define SIU_INT_I2C ((uint)0x01+CPM_IRQ_OFFSET)
++#define SIU_INT_SPI ((uint)0x02+CPM_IRQ_OFFSET)
++#define SIU_INT_RISC ((uint)0x03+CPM_IRQ_OFFSET)
++#define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET)
++#define SIU_INT_SMC2 ((uint)0x05+CPM_IRQ_OFFSET)
++#define SIU_INT_USB ((uint)0x0b+CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER1 ((uint)0x0c+CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER2 ((uint)0x0d+CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER3 ((uint)0x0e+CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER4 ((uint)0x0f+CPM_IRQ_OFFSET)
++#define SIU_INT_FCC1 ((uint)0x20+CPM_IRQ_OFFSET)
++#define SIU_INT_FCC2 ((uint)0x21+CPM_IRQ_OFFSET)
++#define SIU_INT_FCC3 ((uint)0x22+CPM_IRQ_OFFSET)
++#define SIU_INT_MCC1 ((uint)0x24+CPM_IRQ_OFFSET)
++#define SIU_INT_MCC2 ((uint)0x25+CPM_IRQ_OFFSET)
++#define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET)
++#define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET)
++#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
++#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
++#define SIU_INT_PC15 ((uint)0x30+CPM_IRQ_OFFSET)
++#define SIU_INT_PC14 ((uint)0x31+CPM_IRQ_OFFSET)
++#define SIU_INT_PC13 ((uint)0x32+CPM_IRQ_OFFSET)
++#define SIU_INT_PC12 ((uint)0x33+CPM_IRQ_OFFSET)
++#define SIU_INT_PC11 ((uint)0x34+CPM_IRQ_OFFSET)
++#define SIU_INT_PC10 ((uint)0x35+CPM_IRQ_OFFSET)
++#define SIU_INT_PC9 ((uint)0x36+CPM_IRQ_OFFSET)
++#define SIU_INT_PC8 ((uint)0x37+CPM_IRQ_OFFSET)
++#define SIU_INT_PC7 ((uint)0x38+CPM_IRQ_OFFSET)
++#define SIU_INT_PC6 ((uint)0x39+CPM_IRQ_OFFSET)
++#define SIU_INT_PC5 ((uint)0x3a+CPM_IRQ_OFFSET)
++#define SIU_INT_PC4 ((uint)0x3b+CPM_IRQ_OFFSET)
++#define SIU_INT_PC3 ((uint)0x3c+CPM_IRQ_OFFSET)
++#define SIU_INT_PC2 ((uint)0x3d+CPM_IRQ_OFFSET)
++#define SIU_INT_PC1 ((uint)0x3e+CPM_IRQ_OFFSET)
++#define SIU_INT_PC0 ((uint)0x3f+CPM_IRQ_OFFSET)
++
++#else /* CONFIG_40x + CONFIG_8xx */
++/*
++ * this is the # irq's for all ppc arch's (pmac/chrp/prep)
++ * so it is the max of them all
++ */
++#define NR_IRQS 256
++#define __DO_IRQ_CANON 1
++
++#ifndef CONFIG_8260
++
++#define NUM_8259_INTERRUPTS 16
++
++#else /* CONFIG_8260 */
++
++/* The 8260 has an internal interrupt controller with a maximum of
++ * 64 IRQs. We will use NR_IRQs from above since it is large enough.
++ * Don't be confused by the 8260 documentation where they list an
++ * "interrupt number" and "interrupt vector". We are only interested
++ * in the interrupt vector. There are "reserved" holes where the
++ * vector number increases, but the interrupt number in the table does not.
++ * (Document errata updates have fixed this...make sure you have up to
++ * date processor documentation -- Dan).
++ */
++
++#ifndef CPM_IRQ_OFFSET
++#define CPM_IRQ_OFFSET 0
++#endif
++
++#define NR_CPM_INTS 64
++
++#define SIU_INT_ERROR ((uint)0x00 + CPM_IRQ_OFFSET)
++#define SIU_INT_I2C ((uint)0x01 + CPM_IRQ_OFFSET)
++#define SIU_INT_SPI ((uint)0x02 + CPM_IRQ_OFFSET)
++#define SIU_INT_RISC ((uint)0x03 + CPM_IRQ_OFFSET)
++#define SIU_INT_SMC1 ((uint)0x04 + CPM_IRQ_OFFSET)
++#define SIU_INT_SMC2 ((uint)0x05 + CPM_IRQ_OFFSET)
++#define SIU_INT_IDMA1 ((uint)0x06 + CPM_IRQ_OFFSET)
++#define SIU_INT_IDMA2 ((uint)0x07 + CPM_IRQ_OFFSET)
++#define SIU_INT_IDMA3 ((uint)0x08 + CPM_IRQ_OFFSET)
++#define SIU_INT_IDMA4 ((uint)0x09 + CPM_IRQ_OFFSET)
++#define SIU_INT_SDMA ((uint)0x0a + CPM_IRQ_OFFSET)
++#define SIU_INT_USB ((uint)0x0b + CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER1 ((uint)0x0c + CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER2 ((uint)0x0d + CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER3 ((uint)0x0e + CPM_IRQ_OFFSET)
++#define SIU_INT_TIMER4 ((uint)0x0f + CPM_IRQ_OFFSET)
++#define SIU_INT_TMCNT ((uint)0x10 + CPM_IRQ_OFFSET)
++#define SIU_INT_PIT ((uint)0x11 + CPM_IRQ_OFFSET)
++#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
++#define SIU_INT_IRQ2 ((uint)0x14 + CPM_IRQ_OFFSET)
++#define SIU_INT_IRQ3 ((uint)0x15 + CPM_IRQ_OFFSET)
++#define SIU_INT_IRQ4 ((uint)0x16 + CPM_IRQ_OFFSET)
++#define SIU_INT_IRQ5 ((uint)0x17 + CPM_IRQ_OFFSET)
++#define SIU_INT_IRQ6 ((uint)0x18 + CPM_IRQ_OFFSET)
++#define SIU_INT_IRQ7 ((uint)0x19 + CPM_IRQ_OFFSET)
++#define SIU_INT_FCC1 ((uint)0x20 + CPM_IRQ_OFFSET)
++#define SIU_INT_FCC2 ((uint)0x21 + CPM_IRQ_OFFSET)
++#define SIU_INT_FCC3 ((uint)0x22 + CPM_IRQ_OFFSET)
++#define SIU_INT_MCC1 ((uint)0x24 + CPM_IRQ_OFFSET)
++#define SIU_INT_MCC2 ((uint)0x25 + CPM_IRQ_OFFSET)
++#define SIU_INT_SCC1 ((uint)0x28 + CPM_IRQ_OFFSET)
++#define SIU_INT_SCC2 ((uint)0x29 + CPM_IRQ_OFFSET)
++#define SIU_INT_SCC3 ((uint)0x2a + CPM_IRQ_OFFSET)
++#define SIU_INT_SCC4 ((uint)0x2b + CPM_IRQ_OFFSET)
++#define SIU_INT_PC15 ((uint)0x30 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC14 ((uint)0x31 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC13 ((uint)0x32 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC12 ((uint)0x33 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC11 ((uint)0x34 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC10 ((uint)0x35 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC9 ((uint)0x36 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC8 ((uint)0x37 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC7 ((uint)0x38 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC6 ((uint)0x39 + CPM_IRQ_OFFSET)
++#define SIU_INT_PC5 ((uint)0x3a + CPM_IRQ_OFFSET)
++#define SIU_INT_PC4 ((uint)0x3b + CPM_IRQ_OFFSET)
++#define SIU_INT_PC3 ((uint)0x3c + CPM_IRQ_OFFSET)
++#define SIU_INT_PC2 ((uint)0x3d + CPM_IRQ_OFFSET)
++#define SIU_INT_PC1 ((uint)0x3e + CPM_IRQ_OFFSET)
++#define SIU_INT_PC0 ((uint)0x3f + CPM_IRQ_OFFSET)
++
++#endif /* CONFIG_8260 */
++
++#endif
++
++#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
++/* pedantic: these are long because they are used with set_bit --RR */
++extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
++extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
++extern atomic_t ppc_n_lost_interrupts;
++
++#define virt_irq_create_mapping(x) (x)
++
++#endif
++
++/*
++ * Because many systems have two overlapping names spaces for
++ * interrupts (ISA and XICS for example), and the ISA interrupts
++ * have historically not been easy to renumber, we allow ISA
++ * interrupts to take values 0 - 15, and shift up the remaining
++ * interrupts by 0x10.
++ */
++#define NUM_ISA_INTERRUPTS 0x10
++extern int __irq_offset_value;
++
++static inline int irq_offset_up(int irq)
++{
++ return(irq + __irq_offset_value);
++}
++
++static inline int irq_offset_down(int irq)
++{
++ return(irq - __irq_offset_value);
++}
++
++static inline int irq_offset_value(void)
++{
++ return __irq_offset_value;
++}
++
++#ifdef __DO_IRQ_CANON
++extern int ppc_do_canonicalize_irqs;
++#else
++#define ppc_do_canonicalize_irqs 0
++#endif
++
++static __inline__ int irq_canonicalize(int irq)
++{
++ if (ppc_do_canonicalize_irqs && irq == 2)
++ irq = 9;
++ return irq;
++}
++
++extern int distribute_irqs;
++
++struct irqaction;
++struct pt_regs;
++
++#ifdef CONFIG_IRQSTACKS
++/*
++ * Per-cpu stacks for handling hard and soft interrupts.
++ */
++extern struct thread_info *hardirq_ctx[NR_CPUS];
++extern struct thread_info *softirq_ctx[NR_CPUS];
++
++extern void irq_ctx_init(void);
++extern void call_do_softirq(struct thread_info *tp);
++extern int call_handle_IRQ_event(int irq, struct pt_regs *regs,
++ struct irqaction *action, struct thread_info *tp);
++
++#define __ARCH_HAS_DO_SOFTIRQ
++
++#else
++#define irq_ctx_init()
++
++#endif /* CONFIG_IRQSTACKS */
++
++extern void do_IRQ(struct pt_regs *regs);
++
++#endif /* _ASM_IRQ_H */
++#endif /* __KERNEL__ */
+diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/kdebug.h
+@@ -0,0 +1,42 @@
++#ifndef _ASM_POWERPC_KDEBUG_H
++#define _ASM_POWERPC_KDEBUG_H
++
++/* nearly identical to x86_64/i386 code */
++
++#include <linux/notifier.h>
++
++struct pt_regs;
++
++struct die_args {
++ struct pt_regs *regs;
++ const char *str;
++ long err;
++ int trapnr;
++ int signr;
++};
++
++/*
++ Note - you should never unregister because that can race with NMIs.
++ If you really want to do it first unregister - then synchronize_sched -
++ then free.
++ */
++int register_die_notifier(struct notifier_block *nb);
++extern struct notifier_block *powerpc_die_chain;
++
++/* Grossly misnamed. */
++enum die_val {
++ DIE_OOPS = 1,
++ DIE_IABR_MATCH,
++ DIE_DABR_MATCH,
++ DIE_BPT,
++ DIE_SSTEP,
++ DIE_PAGE_FAULT,
++};
++
++static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
++{
++ struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
++ return notifier_call_chain(&powerpc_die_chain, val, &args);
++}
++
++#endif /* _ASM_POWERPC_KDEBUG_H */
+diff --git a/include/asm-powerpc/keylargo.h b/include/asm-powerpc/keylargo.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/keylargo.h
+@@ -0,0 +1,248 @@
++/*
++ * keylargo.h: definitions for using the "KeyLargo" I/O controller chip.
++ *
++ */
++
++/* "Pangea" chipset has keylargo device-id 0x25 while core99
++ * has device-id 0x22. The rev. of the pangea one is 0, so we
++ * fake an artificial rev. in keylargo_rev by oring 0x100
++ */
++#define KL_PANGEA_REV 0x100
++
++/* offset from base for feature control registers */
++#define KEYLARGO_MBCR 0x34 /* KL Only, Media bay control/status */
++#define KEYLARGO_FCR0 0x38
++#define KEYLARGO_FCR1 0x3c
++#define KEYLARGO_FCR2 0x40
++#define KEYLARGO_FCR3 0x44
++#define KEYLARGO_FCR4 0x48
++#define KEYLARGO_FCR5 0x4c /* Pangea only */
++
++/* K2 aditional FCRs */
++#define K2_FCR6 0x34
++#define K2_FCR7 0x30
++#define K2_FCR8 0x2c
++#define K2_FCR9 0x28
++#define K2_FCR10 0x24
++
++/* GPIO registers */
++#define KEYLARGO_GPIO_LEVELS0 0x50
++#define KEYLARGO_GPIO_LEVELS1 0x54
++#define KEYLARGO_GPIO_EXTINT_0 0x58
++#define KEYLARGO_GPIO_EXTINT_CNT 18
++#define KEYLARGO_GPIO_0 0x6A
++#define KEYLARGO_GPIO_CNT 17
++#define KEYLARGO_GPIO_EXTINT_DUAL_EDGE 0x80
++#define KEYLARGO_GPIO_OUTPUT_ENABLE 0x04
++#define KEYLARGO_GPIO_OUTOUT_DATA 0x01
++#define KEYLARGO_GPIO_INPUT_DATA 0x02
++
++/* K2 does only extint GPIOs and does 51 of them */
++#define K2_GPIO_EXTINT_0 0x58
++#define K2_GPIO_EXTINT_CNT 51
++
++/* Specific GPIO regs */
++
++#define KL_GPIO_MODEM_RESET (KEYLARGO_GPIO_0+0x03)
++#define KL_GPIO_MODEM_POWER (KEYLARGO_GPIO_0+0x02) /* Pangea */
++
++#define KL_GPIO_SOUND_POWER (KEYLARGO_GPIO_0+0x05)
++
++/* Hrm... this one is only to be used on Pismo. It seeem to also
++ * control the timebase enable on other machines. Still to be
++ * experimented... --BenH.
++ */
++#define KL_GPIO_FW_CABLE_POWER (KEYLARGO_GPIO_0+0x09)
++#define KL_GPIO_TB_ENABLE (KEYLARGO_GPIO_0+0x09)
++
++#define KL_GPIO_ETH_PHY_RESET (KEYLARGO_GPIO_0+0x10)
++
++#define KL_GPIO_EXTINT_CPU1 (KEYLARGO_GPIO_0+0x0a)
++#define KL_GPIO_EXTINT_CPU1_ASSERT 0x04
++#define KL_GPIO_EXTINT_CPU1_RELEASE 0x38
++
++#define KL_GPIO_RESET_CPU0 (KEYLARGO_GPIO_EXTINT_0+0x03)
++#define KL_GPIO_RESET_CPU1 (KEYLARGO_GPIO_EXTINT_0+0x04)
++#define KL_GPIO_RESET_CPU2 (KEYLARGO_GPIO_EXTINT_0+0x0f)
++#define KL_GPIO_RESET_CPU3 (KEYLARGO_GPIO_EXTINT_0+0x10)
++
++#define KL_GPIO_PMU_MESSAGE_IRQ (KEYLARGO_GPIO_EXTINT_0+0x09)
++#define KL_GPIO_PMU_MESSAGE_BIT KEYLARGO_GPIO_INPUT_DATA
++
++#define KL_GPIO_MEDIABAY_IRQ (KEYLARGO_GPIO_EXTINT_0+0x0e)
++
++#define KL_GPIO_AIRPORT_0 (KEYLARGO_GPIO_EXTINT_0+0x0a)
++#define KL_GPIO_AIRPORT_1 (KEYLARGO_GPIO_EXTINT_0+0x0d)
++#define KL_GPIO_AIRPORT_2 (KEYLARGO_GPIO_0+0x0d)
++#define KL_GPIO_AIRPORT_3 (KEYLARGO_GPIO_0+0x0e)
++#define KL_GPIO_AIRPORT_4 (KEYLARGO_GPIO_0+0x0f)
++
++/*
++ * Bits in feature control register. Those bits different for K2 are
++ * listed separately
++ */
++#define KL_MBCR_MB0_PCI_ENABLE 0x00000800 /* exist ? */
++#define KL_MBCR_MB0_IDE_ENABLE 0x00001000
++#define KL_MBCR_MB0_FLOPPY_ENABLE 0x00002000 /* exist ? */
++#define KL_MBCR_MB0_SOUND_ENABLE 0x00004000 /* hrm... */
++#define KL_MBCR_MB0_DEV_MASK 0x00007800
++#define KL_MBCR_MB0_DEV_POWER 0x00000400
++#define KL_MBCR_MB0_DEV_RESET 0x00000200
++#define KL_MBCR_MB0_ENABLE 0x00000100
++#define KL_MBCR_MB1_PCI_ENABLE 0x08000000 /* exist ? */
++#define KL_MBCR_MB1_IDE_ENABLE 0x10000000
++#define KL_MBCR_MB1_FLOPPY_ENABLE 0x20000000 /* exist ? */
++#define KL_MBCR_MB1_SOUND_ENABLE 0x40000000 /* hrm... */
++#define KL_MBCR_MB1_DEV_MASK 0x78000000
++#define KL_MBCR_MB1_DEV_POWER 0x04000000
++#define KL_MBCR_MB1_DEV_RESET 0x02000000
++#define KL_MBCR_MB1_ENABLE 0x01000000
++
++#define KL0_SCC_B_INTF_ENABLE 0x00000001 /* (KL Only) */
++#define KL0_SCC_A_INTF_ENABLE 0x00000002
++#define KL0_SCC_SLOWPCLK 0x00000004
++#define KL0_SCC_RESET 0x00000008
++#define KL0_SCCA_ENABLE 0x00000010
++#define KL0_SCCB_ENABLE 0x00000020
++#define KL0_SCC_CELL_ENABLE 0x00000040
++#define KL0_IRDA_HIGH_BAND 0x00000100 /* (KL Only) */
++#define KL0_IRDA_SOURCE2_SEL 0x00000200 /* (KL Only) */
++#define KL0_IRDA_SOURCE1_SEL 0x00000400 /* (KL Only) */
++#define KL0_PG_USB0_PMI_ENABLE 0x00000400 /* (Pangea/Intrepid Only) */
++#define KL0_IRDA_RESET 0x00000800 /* (KL Only) */
++#define KL0_PG_USB0_REF_SUSPEND_SEL 0x00000800 /* (Pangea/Intrepid Only) */
++#define KL0_IRDA_DEFAULT1 0x00001000 /* (KL Only) */
++#define KL0_PG_USB0_REF_SUSPEND 0x00001000 /* (Pangea/Intrepid Only) */
++#define KL0_IRDA_DEFAULT0 0x00002000 /* (KL Only) */
++#define KL0_PG_USB0_PAD_SUSPEND 0x00002000 /* (Pangea/Intrepid Only) */
++#define KL0_IRDA_FAST_CONNECT 0x00004000 /* (KL Only) */
++#define KL0_PG_USB1_PMI_ENABLE 0x00004000 /* (Pangea/Intrepid Only) */
++#define KL0_IRDA_ENABLE 0x00008000 /* (KL Only) */
++#define KL0_PG_USB1_REF_SUSPEND_SEL 0x00008000 /* (Pangea/Intrepid Only) */
++#define KL0_IRDA_CLK32_ENABLE 0x00010000 /* (KL Only) */
++#define KL0_PG_USB1_REF_SUSPEND 0x00010000 /* (Pangea/Intrepid Only) */
++#define KL0_IRDA_CLK19_ENABLE 0x00020000 /* (KL Only) */
++#define KL0_PG_USB1_PAD_SUSPEND 0x00020000 /* (Pangea/Intrepid Only) */
++#define KL0_USB0_PAD_SUSPEND0 0x00040000
++#define KL0_USB0_PAD_SUSPEND1 0x00080000
++#define KL0_USB0_CELL_ENABLE 0x00100000
++#define KL0_USB1_PAD_SUSPEND0 0x00400000
++#define KL0_USB1_PAD_SUSPEND1 0x00800000
++#define KL0_USB1_CELL_ENABLE 0x01000000
++#define KL0_USB_REF_SUSPEND 0x10000000 /* (KL Only) */
++
++#define KL0_SERIAL_ENABLE (KL0_SCC_B_INTF_ENABLE | \
++ KL0_SCC_SLOWPCLK | \
++ KL0_SCC_CELL_ENABLE | KL0_SCCA_ENABLE)
++
++#define KL1_USB2_PMI_ENABLE 0x00000001 /* Intrepid only */
++#define KL1_AUDIO_SEL_22MCLK 0x00000002 /* KL/Pangea only */
++#define KL1_USB2_REF_SUSPEND_SEL 0x00000002 /* Intrepid only */
++#define KL1_USB2_REF_SUSPEND 0x00000004 /* Intrepid only */
++#define KL1_AUDIO_CLK_ENABLE_BIT 0x00000008 /* KL/Pangea only */
++#define KL1_USB2_PAD_SUSPEND_SEL 0x00000008 /* Intrepid only */
++#define KL1_USB2_PAD_SUSPEND0 0x00000010 /* Intrepid only */
++#define KL1_AUDIO_CLK_OUT_ENABLE 0x00000020 /* KL/Pangea only */
++#define KL1_USB2_PAD_SUSPEND1 0x00000020 /* Intrepid only */
++#define KL1_AUDIO_CELL_ENABLE 0x00000040 /* KL/Pangea only */
++#define KL1_USB2_CELL_ENABLE 0x00000040 /* Intrepid only */
++#define KL1_AUDIO_CHOOSE 0x00000080 /* KL/Pangea only */
++#define KL1_I2S0_CHOOSE 0x00000200 /* KL Only */
++#define KL1_I2S0_CELL_ENABLE 0x00000400
++#define KL1_I2S0_CLK_ENABLE_BIT 0x00001000
++#define KL1_I2S0_ENABLE 0x00002000
++#define KL1_I2S1_CELL_ENABLE 0x00020000
++#define KL1_I2S1_CLK_ENABLE_BIT 0x00080000
++#define KL1_I2S1_ENABLE 0x00100000
++#define KL1_EIDE0_ENABLE 0x00800000 /* KL/Intrepid Only */
++#define KL1_EIDE0_RESET_N 0x01000000 /* KL/Intrepid Only */
++#define KL1_EIDE1_ENABLE 0x04000000 /* KL Only */
++#define KL1_EIDE1_RESET_N 0x08000000 /* KL Only */
++#define KL1_UIDE_ENABLE 0x20000000 /* KL/Pangea Only */
++#define KL1_UIDE_RESET_N 0x40000000 /* KL/Pangea Only */
++
++#define KL2_IOBUS_ENABLE 0x00000002
++#define KL2_SLEEP_STATE_BIT 0x00000100 /* KL Only */
++#define KL2_PG_STOP_ALL_CLOCKS 0x00000100 /* Pangea Only */
++#define KL2_MPIC_ENABLE 0x00020000
++#define KL2_CARDSLOT_RESET 0x00040000 /* Pangea/Intrepid Only */
++#define KL2_ALT_DATA_OUT 0x02000000 /* KL Only ??? */
++#define KL2_MEM_IS_BIG 0x04000000
++#define KL2_CARDSEL_16 0x08000000
++
++#define KL3_SHUTDOWN_PLL_TOTAL 0x00000001 /* KL/Pangea only */
++#define KL3_SHUTDOWN_PLLKW6 0x00000002 /* KL/Pangea only */
++#define KL3_IT_SHUTDOWN_PLL3 0x00000002 /* Intrepid only */
++#define KL3_SHUTDOWN_PLLKW4 0x00000004 /* KL/Pangea only */
++#define KL3_IT_SHUTDOWN_PLL2 0x00000004 /* Intrepid only */
++#define KL3_SHUTDOWN_PLLKW35 0x00000008 /* KL/Pangea only */
++#define KL3_IT_SHUTDOWN_PLL1 0x00000008 /* Intrepid only */
++#define KL3_SHUTDOWN_PLLKW12 0x00000010 /* KL Only */
++#define KL3_IT_ENABLE_PLL3_SHUTDOWN 0x00000010 /* Intrepid only */
++#define KL3_PLL_RESET 0x00000020 /* KL/Pangea only */
++#define KL3_IT_ENABLE_PLL2_SHUTDOWN 0x00000020 /* Intrepid only */
++#define KL3_IT_ENABLE_PLL1_SHUTDOWN 0x00000010 /* Intrepid only */
++#define KL3_SHUTDOWN_PLL2X 0x00000080 /* KL Only */
++#define KL3_CLK66_ENABLE 0x00000100 /* KL Only */
++#define KL3_CLK49_ENABLE 0x00000200
++#define KL3_CLK45_ENABLE 0x00000400
++#define KL3_CLK31_ENABLE 0x00000800 /* KL/Pangea only */
++#define KL3_TIMER_CLK18_ENABLE 0x00001000
++#define KL3_I2S1_CLK18_ENABLE 0x00002000
++#define KL3_I2S0_CLK18_ENABLE 0x00004000
++#define KL3_VIA_CLK16_ENABLE 0x00008000 /* KL/Pangea only */
++#define KL3_IT_VIA_CLK32_ENABLE 0x00008000 /* Intrepid only */
++#define KL3_STOPPING33_ENABLED 0x00080000 /* KL Only */
++#define KL3_PG_PLL_ENABLE_TEST 0x00080000 /* Pangea Only */
++
++/* Intrepid USB bus 2, port 0,1 */
++#define KL3_IT_PORT_WAKEUP_ENABLE(p) (0x00080000 << ((p)<<3))
++#define KL3_IT_PORT_RESUME_WAKE_EN(p) (0x00040000 << ((p)<<3))
++#define KL3_IT_PORT_CONNECT_WAKE_EN(p) (0x00020000 << ((p)<<3))
++#define KL3_IT_PORT_DISCONNECT_WAKE_EN(p) (0x00010000 << ((p)<<3))
++#define KL3_IT_PORT_RESUME_STAT(p) (0x00300000 << ((p)<<3))
++#define KL3_IT_PORT_CONNECT_STAT(p) (0x00200000 << ((p)<<3))
++#define KL3_IT_PORT_DISCONNECT_STAT(p) (0x00100000 << ((p)<<3))
++
++/* Port 0,1 : bus 0, port 2,3 : bus 1 */
++#define KL4_PORT_WAKEUP_ENABLE(p) (0x00000008 << ((p)<<3))
++#define KL4_PORT_RESUME_WAKE_EN(p) (0x00000004 << ((p)<<3))
++#define KL4_PORT_CONNECT_WAKE_EN(p) (0x00000002 << ((p)<<3))
++#define KL4_PORT_DISCONNECT_WAKE_EN(p) (0x00000001 << ((p)<<3))
++#define KL4_PORT_RESUME_STAT(p) (0x00000040 << ((p)<<3))
++#define KL4_PORT_CONNECT_STAT(p) (0x00000020 << ((p)<<3))
++#define KL4_PORT_DISCONNECT_STAT(p) (0x00000010 << ((p)<<3))
++
++/* Pangea and Intrepid only */
++#define KL5_VIA_USE_CLK31 0000000001 /* Pangea Only */
++#define KL5_SCC_USE_CLK31 0x00000002 /* Pangea Only */
++#define KL5_PWM_CLK32_EN 0x00000004
++#define KL5_CLK3_68_EN 0x00000010
++#define KL5_CLK32_EN 0x00000020
++
++
++/* K2 definitions */
++#define K2_FCR0_USB0_SWRESET 0x00200000
++#define K2_FCR0_USB1_SWRESET 0x02000000
++#define K2_FCR0_RING_PME_DISABLE 0x08000000
++
++#define K2_FCR1_PCI1_BUS_RESET_N 0x00000010
++#define K2_FCR1_PCI1_SLEEP_RESET_EN 0x00000020
++#define K2_FCR1_I2S0_CELL_ENABLE 0x00000400
++#define K2_FCR1_I2S0_RESET 0x00000800
++#define K2_FCR1_I2S0_CLK_ENABLE_BIT 0x00001000
++#define K2_FCR1_I2S0_ENABLE 0x00002000
++
++#define K2_FCR1_PCI1_CLK_ENABLE 0x00004000
++#define K2_FCR1_FW_CLK_ENABLE 0x00008000
++#define K2_FCR1_FW_RESET_N 0x00010000
++#define K2_FCR1_GMAC_CLK_ENABLE 0x00400000
++#define K2_FCR1_GMAC_POWER_DOWN 0x00800000
++#define K2_FCR1_GMAC_RESET_N 0x01000000
++#define K2_FCR1_SATA_CLK_ENABLE 0x02000000
++#define K2_FCR1_SATA_POWER_DOWN 0x04000000
++#define K2_FCR1_SATA_RESET_N 0x08000000
++#define K2_FCR1_UATA_CLK_ENABLE 0x10000000
++#define K2_FCR1_UATA_RESET_N 0x40000000
++#define K2_FCR1_UATA_CHOOSE_CLK66 0x80000000
++
+diff --git a/include/asm-powerpc/kmap_types.h b/include/asm-powerpc/kmap_types.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/kmap_types.h
+@@ -0,0 +1,33 @@
++#ifndef _ASM_POWERPC_KMAP_TYPES_H
++#define _ASM_POWERPC_KMAP_TYPES_H
++
++#ifdef __KERNEL__
++
++/*
++ * 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.
++ */
++
++enum km_type {
++ KM_BOUNCE_READ,
++ KM_SKB_SUNRPC_DATA,
++ KM_SKB_DATA_SOFTIRQ,
++ KM_USER0,
++ KM_USER1,
++ KM_BIO_SRC_IRQ,
++ KM_BIO_DST_IRQ,
++ KM_PTE0,
++ KM_PTE1,
++ KM_IRQ0,
++ KM_IRQ1,
++ KM_SOFTIRQ0,
++ KM_SOFTIRQ1,
++ KM_PPC_SYNC_PAGE,
++ KM_PPC_SYNC_ICACHE,
++ KM_TYPE_NR
++};
++
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_KMAP_TYPES_H */
+diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/kprobes.h
+@@ -0,0 +1,66 @@
++#ifndef _ASM_POWERPC_KPROBES_H
++#define _ASM_POWERPC_KPROBES_H
++/*
++ * Kernel Probes (KProbes)
++ *
++ * 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, 2002, 2004
++ *
++ * 2002-Oct Created by Vamsi Krishna S <vamsi_krishna at in.ibm.com> Kernel
++ * Probes initial implementation ( includes suggestions from
++ * Rusty Russell).
++ * 2004-Nov Modified for PPC64 by Ananth N Mavinakayanahalli
++ * <ananth at in.ibm.com>
++ */
++#include <linux/types.h>
++#include <linux/ptrace.h>
++
++struct pt_regs;
++
++typedef unsigned int kprobe_opcode_t;
++#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
++#define MAX_INSN_SIZE 1
++
++#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
++#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088)
++#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000)
++#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
++
++#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry)
++
++#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
++ IS_TWI(instr) || IS_TDI(instr))
++
++#define ARCH_SUPPORTS_KRETPROBES
++void kretprobe_trampoline(void);
++
++/* Architecture specific copy of original instruction */
++struct arch_specific_insn {
++ /* copy of original instruction */
++ kprobe_opcode_t *insn;
++};
++
++#ifdef CONFIG_KPROBES
++extern int kprobe_exceptions_notify(struct notifier_block *self,
++ unsigned long val, void *data);
++#else /* !CONFIG_KPROBES */
++static inline int kprobe_exceptions_notify(struct notifier_block *self,
++ unsigned long val, void *data)
++{
++ return 0;
++}
++#endif
++#endif /* _ASM_POWERPC_KPROBES_H */
+diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/lmb.h
+@@ -0,0 +1,81 @@
++#ifndef _PPC64_LMB_H
++#define _PPC64_LMB_H
++
++/*
++ * Definitions for talking to the Open Firmware PROM on
++ * Power Macintosh computers.
++ *
++ * Copyright (C) 2001 Peter Bergner, IBM Corp.
++ *
++ * 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 <asm/prom.h>
++
++#define MAX_LMB_REGIONS 128
++
++#define LMB_ALLOC_ANYWHERE 0
++
++struct lmb_property {
++ unsigned long base;
++ unsigned long size;
++};
++
++struct lmb_region {
++ unsigned long cnt;
++ unsigned long size;
++ struct lmb_property region[MAX_LMB_REGIONS+1];
++};
++
++struct lmb {
++ unsigned long debug;
++ unsigned long rmo_size;
++ struct lmb_region memory;
++ struct lmb_region reserved;
++};
++
++extern struct lmb lmb;
++
++extern void __init lmb_init(void);
++extern void __init lmb_analyze(void);
++extern long __init lmb_add(unsigned long, unsigned long);
++extern long __init lmb_reserve(unsigned long, unsigned long);
++extern unsigned long __init lmb_alloc(unsigned long, unsigned long);
++extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long,
++ unsigned long);
++extern unsigned long __init lmb_phys_mem_size(void);
++extern unsigned long __init lmb_end_of_DRAM(void);
++extern unsigned long __init lmb_abs_to_phys(unsigned long);
++extern void __init lmb_enforce_memory_limit(unsigned long);
++
++extern void lmb_dump_all(void);
++
++extern unsigned long io_hole_start;
++
++static inline unsigned long
++lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
++{
++ return type->region[region_nr].size;
++}
++static inline unsigned long
++lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
++{
++ return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
++}
++static inline unsigned long
++lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
++{
++ return type->region[region_nr].base >> PAGE_SHIFT;
++}
++static inline unsigned long
++lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
++{
++ return lmb_start_pfn(type, region_nr) +
++ lmb_size_pages(type, region_nr);
++}
++
++#endif /* _PPC64_LMB_H */
+diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/machdep.h
+@@ -0,0 +1,284 @@
++#ifndef _ASM_POWERPC_MACHDEP_H
++#define _ASM_POWERPC_MACHDEP_H
++#ifdef __KERNEL__
++
++/*
++ * 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/seq_file.h>
++#include <linux/init.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/setup.h>
++
++/* We export this macro for external modules like Alsa to know if
++ * ppc_md.feature_call is implemented or not
++ */
++#define CONFIG_PPC_HAS_FEATURE_CALLS
++
++struct pt_regs;
++struct pci_bus;
++struct device_node;
++struct iommu_table;
++struct rtc_time;
++struct file;
++
++#ifdef CONFIG_SMP
++struct smp_ops_t {
++ void (*message_pass)(int target, int msg);
++ int (*probe)(void);
++ void (*kick_cpu)(int nr);
++ void (*setup_cpu)(int nr);
++ void (*take_timebase)(void);
++ void (*give_timebase)(void);
++ int (*cpu_enable)(unsigned int nr);
++ int (*cpu_disable)(void);
++ void (*cpu_die)(unsigned int nr);
++ int (*cpu_bootable)(unsigned int nr);
++};
++#endif
++
++struct machdep_calls {
++#ifdef CONFIG_PPC64
++ void (*hpte_invalidate)(unsigned long slot,
++ unsigned long va,
++ int large,
++ int local);
++ long (*hpte_updatepp)(unsigned long slot,
++ unsigned long newpp,
++ unsigned long va,
++ int large,
++ int local);
++ void (*hpte_updateboltedpp)(unsigned long newpp,
++ unsigned long ea);
++ long (*hpte_insert)(unsigned long hpte_group,
++ unsigned long va,
++ unsigned long prpn,
++ unsigned long vflags,
++ unsigned long rflags);
++ long (*hpte_remove)(unsigned long hpte_group);
++ void (*flush_hash_range)(unsigned long number, int local);
++
++ /* special for kexec, to be called in real mode, linar mapping is
++ * destroyed as well */
++ void (*hpte_clear_all)(void);
++
++ void (*tce_build)(struct iommu_table * tbl,
++ long index,
++ long npages,
++ unsigned long uaddr,
++ enum dma_data_direction direction);
++ void (*tce_free)(struct iommu_table *tbl,
++ long index,
++ long npages);
++ void (*tce_flush)(struct iommu_table *tbl);
++ void (*iommu_dev_setup)(struct pci_dev *dev);
++ void (*iommu_bus_setup)(struct pci_bus *bus);
++ void (*irq_bus_setup)(struct pci_bus *bus);
++#endif
++
++ int (*probe)(int platform);
++ void (*setup_arch)(void);
++ void (*init_early)(void);
++ /* Optional, may be NULL. */
++ void (*show_cpuinfo)(struct seq_file *m);
++ void (*show_percpuinfo)(struct seq_file *m, int i);
++
++ void (*init_IRQ)(void);
++ int (*get_irq)(struct pt_regs *);
++ void (*cpu_irq_down)(int secondary);
++
++ /* PCI stuff */
++ /* Called after scanning the bus, before allocating resources */
++ void (*pcibios_fixup)(void);
++ int (*pci_probe_mode)(struct pci_bus *);
++
++ void (*restart)(char *cmd);
++ void (*power_off)(void);
++ void (*halt)(void);
++ void (*panic)(char *str);
++ void (*cpu_die)(void);
++
++ long (*time_init)(void); /* Optional, may be NULL */
++
++ int (*set_rtc_time)(struct rtc_time *);
++ void (*get_rtc_time)(struct rtc_time *);
++ unsigned long (*get_boot_time)(void);
++ unsigned char (*rtc_read_val)(int addr);
++ void (*rtc_write_val)(int addr, unsigned char val);
++
++ void (*calibrate_decr)(void);
++
++ void (*progress)(char *, unsigned short);
++
++ /* Interface for platform error logging */
++ void (*log_error)(char *buf, unsigned int err_type, int fatal);
++
++ unsigned char (*nvram_read_val)(int addr);
++ void (*nvram_write_val)(int addr, unsigned char val);
++ ssize_t (*nvram_write)(char *buf, size_t count, loff_t *index);
++ ssize_t (*nvram_read)(char *buf, size_t count, loff_t *index);
++ ssize_t (*nvram_size)(void);
++ void (*nvram_sync)(void);
++
++ /* Exception handlers */
++ void (*system_reset_exception)(struct pt_regs *regs);
++ int (*machine_check_exception)(struct pt_regs *regs);
++
++ /* Motherboard/chipset features. This is a kind of general purpose
++ * hook used to control some machine specific features (like reset
++ * lines, chip power control, etc...).
++ */
++ long (*feature_call)(unsigned int feature, ...);
++
++ /* Check availability of legacy devices like i8042 */
++ int (*check_legacy_ioport)(unsigned int baseport);
++
++ /* Get legacy PCI/IDE interrupt mapping */
++ int (*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel);
++
++ /* Get access protection for /dev/mem */
++ pgprot_t (*phys_mem_access_prot)(struct file *file,
++ unsigned long pfn,
++ unsigned long size,
++ pgprot_t vma_prot);
++
++ /* Idle loop for this platform, leave empty for default idle loop */
++ void (*idle_loop)(void);
++
++ /* Function to enable performance monitor counters for this
++ platform, called once per cpu. */
++ void (*enable_pmcs)(void);
++
++#ifdef CONFIG_PPC32 /* XXX for now */
++ /* A general init function, called by ppc_init in init/main.c.
++ May be NULL. */
++ void (*init)(void);
++
++ void (*idle)(void);
++ void (*power_save)(void);
++
++ void (*heartbeat)(void);
++ unsigned long heartbeat_reset;
++ unsigned long heartbeat_count;
++
++ void (*setup_io_mappings)(void);
++
++ void (*early_serial_map)(void);
++ void (*kgdb_map_scc)(void);
++
++ /*
++ * optional PCI "hooks"
++ */
++
++ /* Called after PPC generic resource fixup to perform
++ machine specific fixups */
++ void (*pcibios_fixup_resources)(struct pci_dev *);
++
++ /* Called for each PCI bus in the system when it's probed */
++ void (*pcibios_fixup_bus)(struct pci_bus *);
++
++ /* Called when pci_enable_device() is called (initial=0) or
++ * when a device with no assigned resource is found (initial=1).
++ * Returns 0 to allow assignment/enabling of the device. */
++ int (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
++
++ /* For interrupt routing */
++ unsigned char (*pci_swizzle)(struct pci_dev *, unsigned char *);
++ int (*pci_map_irq)(struct pci_dev *, unsigned char, unsigned char);
++
++ /* Called in indirect_* to avoid touching devices */
++ int (*pci_exclude_device)(unsigned char, unsigned char);
++
++ /* Called at then very end of pcibios_init() */
++ void (*pcibios_after_init)(void);
++
++ /* this is for modules, since _machine can be a define -- Cort */
++ int ppc_machine;
++
++#ifdef CONFIG_KEXEC
++ /* Called to shutdown machine specific hardware not already controlled
++ * by other drivers.
++ * XXX Should we move this one out of kexec scope?
++ */
++ void (*machine_shutdown)(void);
++
++ /* Called to do the minimal shutdown needed to run a kexec'd kernel
++ * to run successfully.
++ * XXX Should we move this one out of kexec scope?
++ */
++ void (*machine_crash_shutdown)(void);
++
++ /* Called to do what every setup is needed on image and the
++ * reboot code buffer. Returns 0 on success.
++ * Provide your own (maybe dummy) implementation if your platform
++ * claims to support kexec.
++ */
++ int (*machine_kexec_prepare)(struct kimage *image);
++
++ /* Called to handle any machine specific cleanup on image */
++ void (*machine_kexec_cleanup)(struct kimage *image);
++
++ /* Called to perform the _real_ kexec.
++ * Do NOT allocate memory or fail here. We are past the point of
++ * no return.
++ */
++ void (*machine_kexec)(struct kimage *image);
++#endif /* CONFIG_KEXEC */
++#endif /* CONFIG_PPC32 */
++};
++
++extern void default_idle(void);
++extern void native_idle(void);
++
++extern struct machdep_calls ppc_md;
++extern char cmd_line[COMMAND_LINE_SIZE];
++
++#ifdef CONFIG_PPC_PMAC
++/*
++ * Power macintoshes have either a CUDA, PMU or SMU controlling
++ * system reset, power, NVRAM, RTC.
++ */
++typedef enum sys_ctrler_kind {
++ SYS_CTRLER_UNKNOWN = 0,
++ SYS_CTRLER_CUDA = 1,
++ SYS_CTRLER_PMU = 2,
++ SYS_CTRLER_SMU = 3,
++} sys_ctrler_t;
++extern sys_ctrler_t sys_ctrler;
++
++#endif /* CONFIG_PPC_PMAC */
++
++extern void setup_pci_ptrs(void);
++
++#ifdef CONFIG_SMP
++/* Poor default implementations */
++extern void __devinit smp_generic_give_timebase(void);
++extern void __devinit smp_generic_take_timebase(void);
++#endif /* CONFIG_SMP */
++
++
++/* Functions to produce codes on the leds.
++ * The SRC code should be unique for the message category and should
++ * be limited to the lower 24 bits (the upper 8 are set by these funcs),
++ * and (for boot & dump) should be sorted numerically in the order
++ * the events occur.
++ */
++/* Print a boot progress message. */
++void ppc64_boot_msg(unsigned int src, const char *msg);
++/* Print a termination message (print only -- does not stop the kernel) */
++void ppc64_terminate_msg(unsigned int src, const char *msg);
++
++static inline void log_error(char *buf, unsigned int err_type, int fatal)
++{
++ if (ppc_md.log_error)
++ ppc_md.log_error(buf, err_type, fatal);
++}
++
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_MACHDEP_H */
+diff --git a/include/asm-powerpc/macio.h b/include/asm-powerpc/macio.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/macio.h
+@@ -0,0 +1,140 @@
++#ifndef __MACIO_ASIC_H__
++#define __MACIO_ASIC_H__
++
++#include <asm/of_device.h>
++
++extern struct bus_type macio_bus_type;
++
++/* MacIO device driver is defined later */
++struct macio_driver;
++struct macio_chip;
++
++#define MACIO_DEV_COUNT_RESOURCES 8
++#define MACIO_DEV_COUNT_IRQS 8
++
++/*
++ * the macio_bus structure is used to describe a "virtual" bus
++ * within a MacIO ASIC. It's typically provided by a macio_pci_asic
++ * PCI device, but could be provided differently as well (nubus
++ * machines using a fake OF tree).
++ *
++ * The pdev field can be NULL on non-PCI machines
++ */
++struct macio_bus
++{
++ struct macio_chip *chip; /* macio_chip (private use) */
++ int index; /* macio chip index in system */
++#ifdef CONFIG_PCI
++ struct pci_dev *pdev; /* PCI device hosting this bus */
++#endif
++};
++
++/*
++ * the macio_dev structure is used to describe a device
++ * within an Apple MacIO ASIC.
++ */
++struct macio_dev
++{
++ struct macio_bus *bus; /* macio bus this device is on */
++ struct macio_dev *media_bay; /* Device is part of a media bay */
++ struct of_device ofdev;
++ int n_resources;
++ struct resource resource[MACIO_DEV_COUNT_RESOURCES];
++ int n_interrupts;
++ struct resource interrupt[MACIO_DEV_COUNT_IRQS];
++};
++#define to_macio_device(d) container_of(d, struct macio_dev, ofdev.dev)
++#define of_to_macio_device(d) container_of(d, struct macio_dev, ofdev)
++
++extern struct macio_dev *macio_dev_get(struct macio_dev *dev);
++extern void macio_dev_put(struct macio_dev *dev);
++
++/*
++ * Accessors to resources & interrupts and other device
++ * fields
++ */
++
++static inline int macio_resource_count(struct macio_dev *dev)
++{
++ return dev->n_resources;
++}
++
++static inline unsigned long macio_resource_start(struct macio_dev *dev, int resource_no)
++{
++ return dev->resource[resource_no].start;
++}
++
++static inline unsigned long macio_resource_end(struct macio_dev *dev, int resource_no)
++{
++ return dev->resource[resource_no].end;
++}
++
++static inline unsigned long macio_resource_len(struct macio_dev *dev, int resource_no)
++{
++ struct resource *res = &dev->resource[resource_no];
++ if (res->start == 0 || res->end == 0 || res->end < res->start)
++ return 0;
++ return res->end - res->start + 1;
++}
++
++extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name);
++extern void macio_release_resource(struct macio_dev *dev, int resource_no);
++extern int macio_request_resources(struct macio_dev *dev, const char *name);
++extern void macio_release_resources(struct macio_dev *dev);
++
++static inline int macio_irq_count(struct macio_dev *dev)
++{
++ return dev->n_interrupts;
++}
++
++static inline int macio_irq(struct macio_dev *dev, int irq_no)
++{
++ return dev->interrupt[irq_no].start;
++}
++
++static inline void macio_set_drvdata(struct macio_dev *dev, void *data)
++{
++ dev_set_drvdata(&dev->ofdev.dev, data);
++}
++
++static inline void* macio_get_drvdata(struct macio_dev *dev)
++{
++ return dev_get_drvdata(&dev->ofdev.dev);
++}
++
++static inline struct device_node *macio_get_of_node(struct macio_dev *mdev)
++{
++ return mdev->ofdev.node;
++}
++
++#ifdef CONFIG_PCI
++static inline struct pci_dev *macio_get_pci_dev(struct macio_dev *mdev)
++{
++ return mdev->bus->pdev;
++}
++#endif
++
++/*
++ * A driver for a mac-io chip based device
++ */
++struct macio_driver
++{
++ char *name;
++ struct of_device_id *match_table;
++ struct module *owner;
++
++ int (*probe)(struct macio_dev* dev, const struct of_device_id *match);
++ int (*remove)(struct macio_dev* dev);
++
++ int (*suspend)(struct macio_dev* dev, pm_message_t state);
++ int (*resume)(struct macio_dev* dev);
++ int (*shutdown)(struct macio_dev* dev);
++
++ struct device_driver driver;
++};
++#define to_macio_driver(drv) container_of(drv,struct macio_driver, driver)
++
++extern int macio_register_driver(struct macio_driver *);
++extern void macio_unregister_driver(struct macio_driver *);
++
++#endif /* __MACIO_ASIC_H__ */
+diff --git a/include/asm-powerpc/mediabay.h b/include/asm-powerpc/mediabay.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/mediabay.h
+@@ -0,0 +1,31 @@
++/*
++ * mediabay.h: definitions for using the media bay
++ * on PowerBook 3400 and similar computers.
++ *
++ * Copyright (C) 1997 Paul Mackerras.
++ */
++#ifndef _PPC_MEDIABAY_H
++#define _PPC_MEDIABAY_H
++
++#ifdef __KERNEL__
++
++#define MB_FD 0 /* media bay contains floppy drive (automatic eject ?) */
++#define MB_FD1 1 /* media bay contains floppy drive (manual eject ?) */
++#define MB_SOUND 2 /* sound device ? */
++#define MB_CD 3 /* media bay contains ATA drive such as CD or ZIP */
++#define MB_PCI 5 /* media bay contains a PCI device */
++#define MB_POWER 6 /* media bay contains a Power device (???) */
++#define MB_NO 7 /* media bay contains nothing */
++
++int check_media_bay(struct device_node *which_bay, int what);
++int check_media_bay_by_base(unsigned long base, int what);
++
++/* Number of bays in the machine or 0 */
++extern int media_bay_count;
++
++/* called by pmac-ide.c to register IDE controller for media bay */
++extern int media_bay_set_ide_infos(struct device_node* which_bay,
++ unsigned long base, int irq, int index);
++
++#endif /* __KERNEL__ */
++#endif /* _PPC_MEDIABAY_H */
+diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/mpic.h
+@@ -0,0 +1,287 @@
++#ifndef _ASM_POWERPC_MPIC_H
++#define _ASM_POWERPC_MPIC_H
++
++#include <linux/irq.h>
++
++/*
++ * Global registers
++ */
++
++#define MPIC_GREG_BASE 0x01000
++
++#define MPIC_GREG_FEATURE_0 0x00000
++#define MPIC_GREG_FEATURE_LAST_SRC_MASK 0x07ff0000
++#define MPIC_GREG_FEATURE_LAST_SRC_SHIFT 16
++#define MPIC_GREG_FEATURE_LAST_CPU_MASK 0x00001f00
++#define MPIC_GREG_FEATURE_LAST_CPU_SHIFT 8
++#define MPIC_GREG_FEATURE_VERSION_MASK 0xff
++#define MPIC_GREG_FEATURE_1 0x00010
++#define MPIC_GREG_GLOBAL_CONF_0 0x00020
++#define MPIC_GREG_GCONF_RESET 0x80000000
++#define MPIC_GREG_GCONF_8259_PTHROU_DIS 0x20000000
++#define MPIC_GREG_GCONF_BASE_MASK 0x000fffff
++#define MPIC_GREG_GLOBAL_CONF_1 0x00030
++#define MPIC_GREG_VENDOR_0 0x00040
++#define MPIC_GREG_VENDOR_1 0x00050
++#define MPIC_GREG_VENDOR_2 0x00060
++#define MPIC_GREG_VENDOR_3 0x00070
++#define MPIC_GREG_VENDOR_ID 0x00080
++#define MPIC_GREG_VENDOR_ID_STEPPING_MASK 0x00ff0000
++#define MPIC_GREG_VENDOR_ID_STEPPING_SHIFT 16
++#define MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
++#define MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT 8
++#define MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
++#define MPIC_GREG_PROCESSOR_INIT 0x00090
++#define MPIC_GREG_IPI_VECTOR_PRI_0 0x000a0
++#define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0
++#define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0
++#define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0
++#define MPIC_GREG_SPURIOUS 0x000e0
++#define MPIC_GREG_TIMER_FREQ 0x000f0
++
++/*
++ *
++ * Timer registers
++ */
++#define MPIC_TIMER_BASE 0x01100
++#define MPIC_TIMER_STRIDE 0x40
++
++#define MPIC_TIMER_CURRENT_CNT 0x00000
++#define MPIC_TIMER_BASE_CNT 0x00010
++#define MPIC_TIMER_VECTOR_PRI 0x00020
++#define MPIC_TIMER_DESTINATION 0x00030
++
++/*
++ * Per-Processor registers
++ */
++
++#define MPIC_CPU_THISBASE 0x00000
++#define MPIC_CPU_BASE 0x20000
++#define MPIC_CPU_STRIDE 0x01000
++
++#define MPIC_CPU_IPI_DISPATCH_0 0x00040
++#define MPIC_CPU_IPI_DISPATCH_1 0x00050
++#define MPIC_CPU_IPI_DISPATCH_2 0x00060
++#define MPIC_CPU_IPI_DISPATCH_3 0x00070
++#define MPIC_CPU_CURRENT_TASK_PRI 0x00080
++#define MPIC_CPU_TASKPRI_MASK 0x0000000f
++#define MPIC_CPU_WHOAMI 0x00090
++#define MPIC_CPU_WHOAMI_MASK 0x0000001f
++#define MPIC_CPU_INTACK 0x000a0
++#define MPIC_CPU_EOI 0x000b0
++
++/*
++ * Per-source registers
++ */
++
++#define MPIC_IRQ_BASE 0x10000
++#define MPIC_IRQ_STRIDE 0x00020
++#define MPIC_IRQ_VECTOR_PRI 0x00000
++#define MPIC_VECPRI_MASK 0x80000000
++#define MPIC_VECPRI_ACTIVITY 0x40000000 /* Read Only */
++#define MPIC_VECPRI_PRIORITY_MASK 0x000f0000
++#define MPIC_VECPRI_PRIORITY_SHIFT 16
++#define MPIC_VECPRI_VECTOR_MASK 0x000007ff
++#define MPIC_VECPRI_POLARITY_POSITIVE 0x00800000
++#define MPIC_VECPRI_POLARITY_NEGATIVE 0x00000000
++#define MPIC_VECPRI_POLARITY_MASK 0x00800000
++#define MPIC_VECPRI_SENSE_LEVEL 0x00400000
++#define MPIC_VECPRI_SENSE_EDGE 0x00000000
++#define MPIC_VECPRI_SENSE_MASK 0x00400000
++#define MPIC_IRQ_DESTINATION 0x00010
++
++#define MPIC_MAX_IRQ_SOURCES 2048
++#define MPIC_MAX_CPUS 32
++#define MPIC_MAX_ISU 32
++
++/*
++ * Special vector numbers (internal use only)
++ */
++#define MPIC_VEC_SPURRIOUS 255
++#define MPIC_VEC_IPI_3 254
++#define MPIC_VEC_IPI_2 253
++#define MPIC_VEC_IPI_1 252
++#define MPIC_VEC_IPI_0 251
++
++/* unused */
++#define MPIC_VEC_TIMER_3 250
++#define MPIC_VEC_TIMER_2 249
++#define MPIC_VEC_TIMER_1 248
++#define MPIC_VEC_TIMER_0 247
++
++/* Type definition of the cascade handler */
++typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
++
++#ifdef CONFIG_MPIC_BROKEN_U3
++/* Fixup table entry */
++struct mpic_irq_fixup
++{
++ u8 __iomem *base;
++ unsigned int irq;
++};
++#endif /* CONFIG_MPIC_BROKEN_U3 */
++
++
++/* The instance data of a given MPIC */
++struct mpic
++{
++ /* The "linux" controller struct */
++ hw_irq_controller hc_irq;
++#ifdef CONFIG_SMP
++ hw_irq_controller hc_ipi;
++#endif
++ const char *name;
++ /* Flags */
++ unsigned int flags;
++ /* How many irq sources in a given ISU */
++ unsigned int isu_size;
++ unsigned int isu_shift;
++ unsigned int isu_mask;
++ /* Offset of irq vector numbers */
++ unsigned int irq_offset;
++ unsigned int irq_count;
++ /* Offset of ipi vector numbers */
++ unsigned int ipi_offset;
++ /* Number of sources */
++ unsigned int num_sources;
++ /* Number of CPUs */
++ unsigned int num_cpus;
++ /* cascade handler */
++ mpic_cascade_t cascade;
++ void *cascade_data;
++ unsigned int cascade_vec;
++ /* senses array */
++ unsigned char *senses;
++ unsigned int senses_count;
++
++#ifdef CONFIG_MPIC_BROKEN_U3
++ /* The fixup table */
++ struct mpic_irq_fixup *fixups;
++ spinlock_t fixup_lock;
++#endif
++
++ /* The various ioremap'ed bases */
++ volatile u32 __iomem *gregs;
++ volatile u32 __iomem *tmregs;
++ volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS];
++ volatile u32 __iomem *isus[MPIC_MAX_ISU];
++
++ /* link */
++ struct mpic *next;
++};
++
++/* This is the primary controller, only that one has IPIs and
++ * has afinity control. A non-primary MPIC always uses CPU0
++ * registers only
++ */
++#define MPIC_PRIMARY 0x00000001
++/* Set this for a big-endian MPIC */
++#define MPIC_BIG_ENDIAN 0x00000002
++/* Broken U3 MPIC */
++#define MPIC_BROKEN_U3 0x00000004
++/* Broken IPI registers (autodetected) */
++#define MPIC_BROKEN_IPI 0x00000008
++/* MPIC wants a reset */
++#define MPIC_WANTS_RESET 0x00000010
++
++/* Allocate the controller structure and setup the linux irq descs
++ * for the range if interrupts passed in. No HW initialization is
++ * actually performed.
++ *
++ * @phys_addr: physial base address of the MPIC
++ * @flags: flags, see constants above
++ * @isu_size: number of interrupts in an ISU. Use 0 to use a
++ * standard ISU-less setup (aka powermac)
++ * @irq_offset: first irq number to assign to this mpic
++ * @irq_count: number of irqs to use with this mpic IRQ sources. Pass 0
++ * to match the number of sources
++ * @ipi_offset: first irq number to assign to this mpic IPI sources,
++ * used only on primary mpic
++ * @senses: array of sense values
++ * @senses_num: number of entries in the array
++ *
++ * Note about the sense array. If none is passed, all interrupts are
++ * setup to be level negative unless MPIC_BROKEN_U3 is set in which
++ * case they are edge positive (and the array is ignored anyway).
++ * The values in the array start at the first source of the MPIC,
++ * that is senses[0] correspond to linux irq "irq_offset".
++ */
++extern struct mpic *mpic_alloc(unsigned long phys_addr,
++ unsigned int flags,
++ unsigned int isu_size,
++ unsigned int irq_offset,
++ unsigned int irq_count,
++ unsigned int ipi_offset,
++ unsigned char *senses,
++ unsigned int senses_num,
++ const char *name);
++
++/* Assign ISUs, to call before mpic_init()
++ *
++ * @mpic: controller structure as returned by mpic_alloc()
++ * @isu_num: ISU number
++ * @phys_addr: physical address of the ISU
++ */
++extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
++ unsigned long phys_addr);
++
++/* Initialize the controller. After this has been called, none of the above
++ * should be called again for this mpic
++ */
++extern void mpic_init(struct mpic *mpic);
++
++/* Setup a cascade. Currently, only one cascade is supported this
++ * way, though you can always do a normal request_irq() and add
++ * other cascades this way. You should call this _after_ having
++ * added all the ISUs
++ *
++ * @irq_no: "linux" irq number of the cascade (that is offset'ed vector)
++ * @handler: cascade handler function
++ */
++extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
++ void *data);
++
++/*
++ * All of the following functions must only be used after the
++ * ISUs have been assigned and the controller fully initialized
++ * with mpic_init()
++ */
++
++
++/* Change/Read the priority of an interrupt. Default is 8 for irqs and
++ * 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the
++ * IPI number is then the offset'ed (linux irq number mapped to the IPI)
++ */
++extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri);
++extern unsigned int mpic_irq_get_priority(unsigned int irq);
++
++/* Setup a non-boot CPU */
++extern void mpic_setup_this_cpu(void);
++
++/* Clean up for kexec (or cpu offline or ...) */
++extern void mpic_teardown_this_cpu(int secondary);
++
++/* Get the current cpu priority for this cpu (0..15) */
++extern int mpic_cpu_get_priority(void);
++
++/* Set the current cpu priority for this cpu */
++extern void mpic_cpu_set_priority(int prio);
++
++/* Request IPIs on primary mpic */
++extern void mpic_request_ipis(void);
++
++/* Send an IPI (non offseted number 0..3) */
++extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
++
++/* Send a message (IPI) to a given target (cpu number or MSG_*) */
++void smp_mpic_message_pass(int target, int msg);
++
++/* Fetch interrupt from a given mpic */
++extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
++/* This one gets to the primary mpic */
++extern int mpic_get_irq(struct pt_regs *regs);
++
++/* global mpic for pSeries */
++extern struct mpic *pSeries_mpic;
++
++#endif /* _ASM_POWERPC_MPIC_H */
+diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/of_device.h
+@@ -0,0 +1,64 @@
++#ifndef _ASM_POWERPC_OF_DEVICE_H
++#define _ASM_POWERPC_OF_DEVICE_H
++
++#include <linux/device.h>
++#include <linux/mod_devicetable.h>
++#include <asm/prom.h>
++
++/*
++ * The of_platform_bus_type is a bus type used by drivers that do not
++ * attach to a macio or similar bus but still use OF probing
++ * mecanism
++ */
++extern struct bus_type of_platform_bus_type;
++
++/*
++ * The of_device is a kind of "base class" that is a superset of
++ * struct device for use by devices attached to an OF node and
++ * probed using OF properties
++ */
++struct of_device
++{
++ struct device_node *node; /* OF device node */
++ u64 dma_mask; /* DMA mask */
++ struct device dev; /* Generic device interface */
++};
++#define to_of_device(d) container_of(d, struct of_device, dev)
++
++extern const struct of_device_id *of_match_device(
++ const struct of_device_id *matches, const struct of_device *dev);
++
++extern struct of_device *of_dev_get(struct of_device *dev);
++extern void of_dev_put(struct of_device *dev);
++
++/*
++ * An of_platform_driver driver is attached to a basic of_device on
++ * the "platform bus" (of_platform_bus_type)
++ */
++struct of_platform_driver
++{
++ char *name;
++ struct of_device_id *match_table;
++ struct module *owner;
++
++ int (*probe)(struct of_device* dev, const struct of_device_id *match);
++ int (*remove)(struct of_device* dev);
++
++ int (*suspend)(struct of_device* dev, pm_message_t state);
++ int (*resume)(struct of_device* dev);
++ int (*shutdown)(struct of_device* dev);
++
++ struct device_driver driver;
++};
++#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
++
++extern int of_register_driver(struct of_platform_driver *drv);
++extern void of_unregister_driver(struct of_platform_driver *drv);
++extern int of_device_register(struct of_device *ofdev);
++extern void of_device_unregister(struct of_device *ofdev);
++extern struct of_device *of_platform_device_create(struct device_node *np,
++ const char *bus_id,
++ struct device *parent);
++extern void of_release_dev(struct device *dev);
++
++#endif /* _ASM_POWERPC_OF_DEVICE_H */
+diff --git a/include/asm-powerpc/ohare.h b/include/asm-powerpc/ohare.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/ohare.h
+@@ -0,0 +1,48 @@
++/*
++ * ohare.h: definitions for using the "O'Hare" I/O controller chip.
++ *
++ * Copyright (C) 1997 Paul Mackerras.
++ *
++ * BenH: Changed to match those of heathrow (but not all of them). Please
++ * check if I didn't break anything (especially the media bay).
++ */
++
++/* offset from ohare base for feature control register */
++#define OHARE_MBCR 0x34
++#define OHARE_FCR 0x38
++
++/*
++ * Bits in feature control register.
++ * These were mostly derived by experiment on a powerbook 3400
++ * and may differ for other machines.
++ */
++#define OH_SCC_RESET 1
++#define OH_BAY_POWER_N 2 /* a guess */
++#define OH_BAY_PCI_ENABLE 4 /* a guess */
++#define OH_BAY_IDE_ENABLE 8
++#define OH_BAY_FLOPPY_ENABLE 0x10
++#define OH_IDE0_ENABLE 0x20
++#define OH_IDE0_RESET_N 0x40 /* a guess */
++#define OH_BAY_DEV_MASK 0x1c
++#define OH_BAY_RESET_N 0x80
++#define OH_IOBUS_ENABLE 0x100 /* IOBUS seems to be IDE */
++#define OH_SCC_ENABLE 0x200
++#define OH_MESH_ENABLE 0x400
++#define OH_FLOPPY_ENABLE 0x800
++#define OH_SCCA_IO 0x4000
++#define OH_SCCB_IO 0x8000
++#define OH_VIA_ENABLE 0x10000 /* Is apparently wrong, to be verified */
++#define OH_IDE1_RESET_N 0x800000
++
++/*
++ * Bits to set in the feature control register on PowerBooks.
++ */
++#define PBOOK_FEATURES (OH_IDE_ENABLE | OH_SCC_ENABLE | \
++ OH_MESH_ENABLE | OH_SCCA_IO | OH_SCCB_IO)
++
++/*
++ * A magic value to put into the feature control register of the
++ * "ohare" I/O controller on Starmaxes to enable the IDE CD interface.
++ * Contributed by Harry Eaton.
++ */
++#define STARMAX_FEATURES 0xbeff7a
+diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/oprofile_impl.h
+@@ -0,0 +1,123 @@
++/*
++ * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * Based on alpha version.
++ *
++ * 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_POWERPC_OPROFILE_IMPL_H
++#define _ASM_POWERPC_OPROFILE_IMPL_H
++
++#define OP_MAX_COUNTER 8
++
++/* Per-counter configuration as set via oprofilefs. */
++struct op_counter_config {
++#ifdef __powerpc64__
++ unsigned long valid;
++#endif
++ unsigned long enabled;
++ unsigned long event;
++ unsigned long count;
++ unsigned long kernel;
++#ifdef __powerpc64__
++ /* We dont support per counter user/kernel selection */
++#endif
++ unsigned long user;
++ unsigned long unit_mask;
++};
++
++/* System-wide configuration as set via oprofilefs. */
++struct op_system_config {
++#ifdef __powerpc64__
++ unsigned long mmcr0;
++ unsigned long mmcr1;
++ unsigned long mmcra;
++#endif
++ unsigned long enable_kernel;
++ unsigned long enable_user;
++#ifdef __powerpc64__
++ unsigned long backtrace_spinlocks;
++#endif
++};
++
++/* Per-arch configuration */
++struct op_powerpc_model {
++ void (*reg_setup) (struct op_counter_config *,
++ struct op_system_config *,
++ int num_counters);
++#ifdef __powerpc64__
++ void (*cpu_setup) (void *);
++#endif
++ void (*start) (struct op_counter_config *);
++ void (*stop) (void);
++ void (*handle_interrupt) (struct pt_regs *,
++ struct op_counter_config *);
++ int num_counters;
++};
++
++#ifdef __powerpc64__
++extern struct op_powerpc_model op_model_rs64;
++extern struct op_powerpc_model op_model_power4;
++
++static inline unsigned int ctr_read(unsigned int i)
++{
++ switch(i) {
++ case 0:
++ return mfspr(SPRN_PMC1);
++ case 1:
++ return mfspr(SPRN_PMC2);
++ case 2:
++ return mfspr(SPRN_PMC3);
++ case 3:
++ return mfspr(SPRN_PMC4);
++ case 4:
++ return mfspr(SPRN_PMC5);
++ case 5:
++ return mfspr(SPRN_PMC6);
++ case 6:
++ return mfspr(SPRN_PMC7);
++ case 7:
++ return mfspr(SPRN_PMC8);
++ default:
++ return 0;
++ }
++}
++
++static inline void ctr_write(unsigned int i, unsigned int val)
++{
++ switch(i) {
++ case 0:
++ mtspr(SPRN_PMC1, val);
++ break;
++ case 1:
++ mtspr(SPRN_PMC2, val);
++ break;
++ case 2:
++ mtspr(SPRN_PMC3, val);
++ break;
++ case 3:
++ mtspr(SPRN_PMC4, val);
++ break;
++ case 4:
++ mtspr(SPRN_PMC5, val);
++ break;
++ case 5:
++ mtspr(SPRN_PMC6, val);
++ break;
++ case 6:
++ mtspr(SPRN_PMC7, val);
++ break;
++ case 7:
++ mtspr(SPRN_PMC8, val);
++ break;
++ default:
++ break;
++ }
++}
++#endif /* __powerpc64__ */
++
++#endif /* _ASM_POWERPC_OPROFILE_IMPL_H */
+diff --git a/include/asm-powerpc/pSeries_reconfig.h b/include/asm-powerpc/pSeries_reconfig.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/pSeries_reconfig.h
+@@ -0,0 +1,25 @@
++#ifndef _PPC64_PSERIES_RECONFIG_H
++#define _PPC64_PSERIES_RECONFIG_H
++
++#include <linux/notifier.h>
++
++/*
++ * Use this API if your code needs to know about OF device nodes being
++ * added or removed on pSeries systems.
++ */
++
++#define PSERIES_RECONFIG_ADD 0x0001
++#define PSERIES_RECONFIG_REMOVE 0x0002
++
++#ifdef CONFIG_PPC_PSERIES
++extern int pSeries_reconfig_notifier_register(struct notifier_block *);
++extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
++#else /* !CONFIG_PPC_PSERIES */
++static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
++{
++ return 0;
++}
++static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
++#endif /* CONFIG_PPC_PSERIES */
++
++#endif /* _PPC64_PSERIES_RECONFIG_H */
+diff --git a/include/asm-powerpc/parport.h b/include/asm-powerpc/parport.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/parport.h
+@@ -0,0 +1,18 @@
++/*
++ * parport.h: platform-specific PC-style parport initialisation
++ *
++ * Copyright (C) 1999, 2000 Tim Waugh <tim at cyberelk.demon.co.uk>
++ *
++ * This file should only be included by drivers/parport/parport_pc.c.
++ */
++
++#ifndef _ASM_POWERPC_PARPORT_H
++#define _ASM_POWERPC_PARPORT_H
++
++static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
++static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
++{
++ return parport_pc_find_isa_ports (autoirq, autodma);
++}
++
++#endif /* !(_ASM_POWERPC_PARPORT_H) */
+diff --git a/include/asm-powerpc/pmac_feature.h b/include/asm-powerpc/pmac_feature.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/pmac_feature.h
+@@ -0,0 +1,380 @@
++/*
++ * Definition of platform feature hooks for PowerMacs
++ *
++ * 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 Paul Mackerras &
++ * Ben. Herrenschmidt.
++ *
++ *
++ * Note: I removed media-bay details from the feature stuff, I believe it's
++ * not worth it, the media-bay driver can directly use the mac-io
++ * ASIC registers.
++ *
++ * Implementation note: Currently, none of these functions will block.
++ * However, they may internally protect themselves with a spinlock
++ * for way too long. Be prepared for at least some of these to block
++ * in the future.
++ *
++ * Unless specifically defined, the result code is assumed to be an
++ * error when negative, 0 is the default success result. Some functions
++ * may return additional positive result values.
++ *
++ * To keep implementation simple, all feature calls are assumed to have
++ * the prototype parameters (struct device_node* node, int value).
++ * When either is not used, pass 0.
++ */
++
++#ifdef __KERNEL__
++#ifndef __PPC_ASM_PMAC_FEATURE_H
++#define __PPC_ASM_PMAC_FEATURE_H
++
++#include <asm/macio.h>
++#include <asm/machdep.h>
++
++/*
++ * Known Mac motherboard models
++ *
++ * Please, report any error here to benh at kernel.crashing.org, thanks !
++ *
++ * Note that I don't fully maintain this list for Core99 & MacRISC2
++ * and I'm considering removing all NewWorld entries from it and
++ * entirely rely on the model string.
++ */
++
++/* PowerSurge are the first generation of PCI Pmacs. This include
++ * all of the Grand-Central based machines. We currently don't
++ * differenciate most of them.
++ */
++#define PMAC_TYPE_PSURGE 0x10 /* PowerSurge */
++#define PMAC_TYPE_ANS 0x11 /* Apple Network Server */
++
++/* Here is the infamous serie of OHare based machines
++ */
++#define PMAC_TYPE_COMET 0x20 /* Beleived to be PowerBook 2400 */
++#define PMAC_TYPE_HOOPER 0x21 /* Beleived to be PowerBook 3400 */
++#define PMAC_TYPE_KANGA 0x22 /* PowerBook 3500 (first G3) */
++#define PMAC_TYPE_ALCHEMY 0x23 /* Alchemy motherboard base */
++#define PMAC_TYPE_GAZELLE 0x24 /* Spartacus, some 5xxx/6xxx */
++#define PMAC_TYPE_UNKNOWN_OHARE 0x2f /* Unknown, but OHare based */
++
++/* Here are the Heathrow based machines
++ * FIXME: Differenciate wallstreet,mainstreet,wallstreetII
++ */
++#define PMAC_TYPE_GOSSAMER 0x30 /* Gossamer motherboard */
++#define PMAC_TYPE_SILK 0x31 /* Desktop PowerMac G3 */
++#define PMAC_TYPE_WALLSTREET 0x32 /* Wallstreet/Mainstreet PowerBook*/
++#define PMAC_TYPE_UNKNOWN_HEATHROW 0x3f /* Unknown but heathrow based */
++
++/* Here are newworld machines based on Paddington (heathrow derivative)
++ */
++#define PMAC_TYPE_101_PBOOK 0x40 /* 101 PowerBook (aka Lombard) */
++#define PMAC_TYPE_ORIG_IMAC 0x41 /* First generation iMac */
++#define PMAC_TYPE_YOSEMITE 0x42 /* B&W G3 */
++#define PMAC_TYPE_YIKES 0x43 /* Yikes G4 (PCI graphics) */
++#define PMAC_TYPE_UNKNOWN_PADDINGTON 0x4f /* Unknown but paddington based */
++
++/* Core99 machines based on UniNorth 1.0 and 1.5
++ *
++ * Note: A single entry here may cover several actual models according
++ * to the device-tree. (Sawtooth is most tower G4s, FW_IMAC is most
++ * FireWire based iMacs, etc...). Those machines are too similar to be
++ * distinguished here, when they need to be differencied, use the
++ * device-tree "model" or "compatible" property.
++ */
++#define PMAC_TYPE_ORIG_IBOOK 0x40 /* First iBook model (no firewire) */
++#define PMAC_TYPE_SAWTOOTH 0x41 /* Desktop G4s */
++#define PMAC_TYPE_FW_IMAC 0x42 /* FireWire iMacs (except Pangea based) */
++#define PMAC_TYPE_FW_IBOOK 0x43 /* FireWire iBooks (except iBook2) */
++#define PMAC_TYPE_CUBE 0x44 /* Cube PowerMac */
++#define PMAC_TYPE_QUICKSILVER 0x45 /* QuickSilver G4s */
++#define PMAC_TYPE_PISMO 0x46 /* Pismo PowerBook */
++#define PMAC_TYPE_TITANIUM 0x47 /* Titanium PowerBook */
++#define PMAC_TYPE_TITANIUM2 0x48 /* Titanium II PowerBook (no L3, M6) */
++#define PMAC_TYPE_TITANIUM3 0x49 /* Titanium III PowerBook (with L3 & M7) */
++#define PMAC_TYPE_TITANIUM4 0x50 /* Titanium IV PowerBook (with L3 & M9) */
++#define PMAC_TYPE_EMAC 0x50 /* eMac */
++#define PMAC_TYPE_UNKNOWN_CORE99 0x5f
++
++/* MacRisc2 with UniNorth 2.0 */
++#define PMAC_TYPE_RACKMAC 0x80 /* XServe */
++#define PMAC_TYPE_WINDTUNNEL 0x81
++
++/* MacRISC2 machines based on the Pangea chipset
++ */
++#define PMAC_TYPE_PANGEA_IMAC 0x100 /* Flower Power iMac */
++#define PMAC_TYPE_IBOOK2 0x101 /* iBook2 (polycarbonate) */
++#define PMAC_TYPE_FLAT_PANEL_IMAC 0x102 /* Flat panel iMac */
++#define PMAC_TYPE_UNKNOWN_PANGEA 0x10f
++
++/* MacRISC2 machines based on the Intrepid chipset
++ */
++#define PMAC_TYPE_UNKNOWN_INTREPID 0x11f /* Generic */
++
++/* MacRISC4 / G5 machines. We don't have per-machine selection here anymore,
++ * but rather machine families
++ */
++#define PMAC_TYPE_POWERMAC_G5 0x150 /* U3 & U3H based */
++#define PMAC_TYPE_POWERMAC_G5_U3L 0x151 /* U3L based desktop */
++#define PMAC_TYPE_IMAC_G5 0x152 /* iMac G5 */
++#define PMAC_TYPE_XSERVE_G5 0x153 /* Xserve G5 */
++#define PMAC_TYPE_UNKNOWN_K2 0x19f /* Any other K2 based */
++
++/*
++ * Motherboard flags
++ */
++
++#define PMAC_MB_CAN_SLEEP 0x00000001
++#define PMAC_MB_HAS_FW_POWER 0x00000002
++#define PMAC_MB_OLD_CORE99 0x00000004
++#define PMAC_MB_MOBILE 0x00000008
++#define PMAC_MB_MAY_SLEEP 0x00000010
++
++/*
++ * Feature calls supported on pmac
++ *
++ */
++
++/*
++ * Use this inline wrapper
++ */
++struct device_node;
++
++static inline long pmac_call_feature(int selector, struct device_node* node,
++ long param, long value)
++{
++ if (!ppc_md.feature_call)
++ return -ENODEV;
++ return ppc_md.feature_call(selector, node, param, value);
++}
++
++/* PMAC_FTR_SERIAL_ENABLE (struct device_node* node, int param, int value)
++ * enable/disable an SCC side. Pass the node corresponding to the
++ * channel side as a parameter.
++ * param is the type of port
++ * if param is ored with PMAC_SCC_FLAG_XMON, then the SCC is locked enabled
++ * for use by xmon.
++ */
++#define PMAC_FTR_SCC_ENABLE PMAC_FTR_DEF(0)
++ #define PMAC_SCC_ASYNC 0
++ #define PMAC_SCC_IRDA 1
++ #define PMAC_SCC_I2S1 2
++ #define PMAC_SCC_FLAG_XMON 0x00001000
++
++/* PMAC_FTR_MODEM_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable the internal modem.
++ */
++#define PMAC_FTR_MODEM_ENABLE PMAC_FTR_DEF(1)
++
++/* PMAC_FTR_SWIM3_ENABLE (struct device_node* node, 0,int value)
++ * enable/disable the swim3 (floppy) cell of a mac-io ASIC
++ */
++#define PMAC_FTR_SWIM3_ENABLE PMAC_FTR_DEF(2)
++
++/* PMAC_FTR_MESH_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable the mesh (scsi) cell of a mac-io ASIC
++ */
++#define PMAC_FTR_MESH_ENABLE PMAC_FTR_DEF(3)
++
++/* PMAC_FTR_IDE_ENABLE (struct device_node* node, int busID, int value)
++ * enable/disable an IDE port of a mac-io ASIC
++ * pass the busID parameter
++ */
++#define PMAC_FTR_IDE_ENABLE PMAC_FTR_DEF(4)
++
++/* PMAC_FTR_IDE_RESET (struct device_node* node, int busID, int value)
++ * assert(1)/release(0) an IDE reset line (mac-io IDE only)
++ */
++#define PMAC_FTR_IDE_RESET PMAC_FTR_DEF(5)
++
++/* PMAC_FTR_BMAC_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable the bmac (ethernet) cell of a mac-io ASIC, also drive
++ * it's reset line
++ */
++#define PMAC_FTR_BMAC_ENABLE PMAC_FTR_DEF(6)
++
++/* PMAC_FTR_GMAC_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable the gmac (ethernet) cell of an uninorth ASIC. This
++ * control the cell's clock.
++ */
++#define PMAC_FTR_GMAC_ENABLE PMAC_FTR_DEF(7)
++
++/* PMAC_FTR_GMAC_PHY_RESET (struct device_node* node, 0, 0)
++ * Perform a HW reset of the PHY connected to a gmac controller.
++ * Pass the gmac device node, not the PHY node.
++ */
++#define PMAC_FTR_GMAC_PHY_RESET PMAC_FTR_DEF(8)
++
++/* PMAC_FTR_SOUND_CHIP_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable the sound chip, whatever it is and provided it can
++ * acually be controlled
++ */
++#define PMAC_FTR_SOUND_CHIP_ENABLE PMAC_FTR_DEF(9)
++
++/* -- add various tweaks related to sound routing -- */
++
++/* PMAC_FTR_AIRPORT_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable the airport card
++ */
++#define PMAC_FTR_AIRPORT_ENABLE PMAC_FTR_DEF(10)
++
++/* PMAC_FTR_RESET_CPU (NULL, int cpu_nr, 0)
++ * toggle the reset line of a CPU on an uninorth-based SMP machine
++ */
++#define PMAC_FTR_RESET_CPU PMAC_FTR_DEF(11)
++
++/* PMAC_FTR_USB_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable an USB cell, along with the power of the USB "pad"
++ * on keylargo based machines
++ */
++#define PMAC_FTR_USB_ENABLE PMAC_FTR_DEF(12)
++
++/* PMAC_FTR_1394_ENABLE (struct device_node* node, 0, int value)
++ * enable/disable the firewire cell of an uninorth ASIC.
++ */
++#define PMAC_FTR_1394_ENABLE PMAC_FTR_DEF(13)
++
++/* PMAC_FTR_1394_CABLE_POWER (struct device_node* node, 0, int value)
++ * enable/disable the firewire cable power supply of the uninorth
++ * firewire cell
++ */
++#define PMAC_FTR_1394_CABLE_POWER PMAC_FTR_DEF(14)
++
++/* PMAC_FTR_SLEEP_STATE (struct device_node* node, 0, int value)
++ * set the sleep state of the motherboard.
++ *
++ * Pass -1 as value to query for sleep capability
++ * Pass 1 to set IOs to sleep
++ * Pass 0 to set IOs to wake
++ */
++#define PMAC_FTR_SLEEP_STATE PMAC_FTR_DEF(15)
++
++/* PMAC_FTR_GET_MB_INFO (NULL, selector, 0)
++ *
++ * returns some motherboard infos.
++ * selector: 0 - model id
++ * 1 - model flags (capabilities)
++ * 2 - model name (cast to const char *)
++ */
++#define PMAC_FTR_GET_MB_INFO PMAC_FTR_DEF(16)
++#define PMAC_MB_INFO_MODEL 0
++#define PMAC_MB_INFO_FLAGS 1
++#define PMAC_MB_INFO_NAME 2
++
++/* PMAC_FTR_READ_GPIO (NULL, int index, 0)
++ *
++ * read a GPIO from a mac-io controller of type KeyLargo or Pangea.
++ * the value returned is a byte (positive), or a negative error code
++ */
++#define PMAC_FTR_READ_GPIO PMAC_FTR_DEF(17)
++
++/* PMAC_FTR_WRITE_GPIO (NULL, int index, int value)
++ *
++ * write a GPIO of a mac-io controller of type KeyLargo or Pangea.
++ */
++#define PMAC_FTR_WRITE_GPIO PMAC_FTR_DEF(18)
++
++/* PMAC_FTR_ENABLE_MPIC
++ *
++ * Enable the MPIC cell
++ */
++#define PMAC_FTR_ENABLE_MPIC PMAC_FTR_DEF(19)
++
++/* PMAC_FTR_AACK_DELAY_ENABLE (NULL, int enable, 0)
++ *
++ * Enable/disable the AACK delay on the northbridge for systems using DFS
++ */
++#define PMAC_FTR_AACK_DELAY_ENABLE PMAC_FTR_DEF(20)
++
++/* PMAC_FTR_DEVICE_CAN_WAKE
++ *
++ * Used by video drivers to inform system that they can actually perform
++ * wakeup from sleep
++ */
++#define PMAC_FTR_DEVICE_CAN_WAKE PMAC_FTR_DEF(22)
++
++
++/* Don't use those directly, they are for the sake of pmac_setup.c */
++extern long pmac_do_feature_call(unsigned int selector, ...);
++extern void pmac_feature_init(void);
++
++/* Video suspend tweak */
++extern void pmac_set_early_video_resume(void (*proc)(void *data), void *data);
++extern void pmac_call_early_video_resume(void);
++
++#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
++
++/* The AGP driver registers itself here */
++extern void pmac_register_agp_pm(struct pci_dev *bridge,
++ int (*suspend)(struct pci_dev *bridge),
++ int (*resume)(struct pci_dev *bridge));
++
++/* Those are meant to be used by video drivers to deal with AGP
++ * suspend resume properly
++ */
++extern void pmac_suspend_agp_for_card(struct pci_dev *dev);
++extern void pmac_resume_agp_for_card(struct pci_dev *dev);
++
++/* Used by the via-pmu driver for suspend/resume
++ */
++extern void pmac_tweak_clock_spreading(int enable);
++
++/*
++ * The part below is for use by macio_asic.c only, do not rely
++ * on the data structures or constants below in a normal driver
++ *
++ */
++
++#define MAX_MACIO_CHIPS 2
++
++enum {
++ macio_unknown = 0,
++ macio_grand_central,
++ macio_ohare,
++ macio_ohareII,
++ macio_heathrow,
++ macio_gatwick,
++ macio_paddington,
++ macio_keylargo,
++ macio_pangea,
++ macio_intrepid,
++ macio_keylargo2,
++};
++
++struct macio_chip
++{
++ struct device_node *of_node;
++ int type;
++ const char *name;
++ int rev;
++ volatile u32 __iomem *base;
++ unsigned long flags;
++
++ /* For use by macio_asic PCI driver */
++ struct macio_bus lbus;
++};
++
++extern struct macio_chip macio_chips[MAX_MACIO_CHIPS];
++
++#define MACIO_FLAG_SCCA_ON 0x00000001
++#define MACIO_FLAG_SCCB_ON 0x00000002
++#define MACIO_FLAG_SCC_LOCKED 0x00000004
++#define MACIO_FLAG_AIRPORT_ON 0x00000010
++#define MACIO_FLAG_FW_SUPPORTED 0x00000020
++
++extern struct macio_chip* macio_find(struct device_node* child, int type);
++
++#define MACIO_FCR32(macio, r) ((macio)->base + ((r) >> 2))
++#define MACIO_FCR8(macio, r) (((volatile u8 __iomem *)((macio)->base)) + (r))
++
++#define MACIO_IN32(r) (in_le32(MACIO_FCR32(macio,r)))
++#define MACIO_OUT32(r,v) (out_le32(MACIO_FCR32(macio,r), (v)))
++#define MACIO_BIS(r,v) (MACIO_OUT32((r), MACIO_IN32(r) | (v)))
++#define MACIO_BIC(r,v) (MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
++#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r)))
++#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v)))
++
++#endif /* __PPC_ASM_PMAC_FEATURE_H */
++#endif /* __KERNEL__ */
+diff --git a/include/asm-powerpc/pmac_low_i2c.h b/include/asm-powerpc/pmac_low_i2c.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/pmac_low_i2c.h
+@@ -0,0 +1,43 @@
++/*
++ * include/asm-ppc/pmac_low_i2c.h
++ *
++ * Copyright (C) 2003 Ben. Herrenschmidt (benh at kernel.crashing.org)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++#ifndef __PMAC_LOW_I2C_H__
++#define __PMAC_LOW_I2C_H__
++
++/* i2c mode (based on the platform functions format) */
++enum {
++ pmac_low_i2c_mode_dumb = 1,
++ pmac_low_i2c_mode_std = 2,
++ pmac_low_i2c_mode_stdsub = 3,
++ pmac_low_i2c_mode_combined = 4,
++};
++
++/* RW bit in address */
++enum {
++ pmac_low_i2c_read = 0x01,
++ pmac_low_i2c_write = 0x00
++};
++
++/* Init, called early during boot */
++extern void pmac_init_low_i2c(void);
++
++/* Locking functions exposed to i2c-keywest */
++int pmac_low_i2c_lock(struct device_node *np);
++int pmac_low_i2c_unlock(struct device_node *np);
++
++/* Access functions for platform code */
++int pmac_low_i2c_open(struct device_node *np, int channel);
++int pmac_low_i2c_close(struct device_node *np);
++int pmac_low_i2c_setmode(struct device_node *np, int mode);
++int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len);
++
++
++#endif /* __PMAC_LOW_I2C_H__ */
+diff --git a/include/asm-powerpc/pmc.h b/include/asm-powerpc/pmc.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/pmc.h
+@@ -0,0 +1,46 @@
++/*
++ * pmc.h
++ * Copyright (C) 2004 David Gibson, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _POWERPC_PMC_H
++#define _POWERPC_PMC_H
++
++#include <asm/ptrace.h>
++
++typedef void (*perf_irq_t)(struct pt_regs *);
++
++int reserve_pmc_hardware(perf_irq_t new_perf_irq);
++void release_pmc_hardware(void);
++
++#ifdef CONFIG_PPC64
++void power4_enable_pmcs(void);
++#endif
++
++#ifdef CONFIG_FSL_BOOKE
++void init_pmc_stop(int ctr);
++void set_pmc_event(int ctr, int event);
++void set_pmc_user_kernel(int ctr, int user, int kernel);
++void set_pmc_marked(int ctr, int mark0, int mark1);
++void pmc_start_ctr(int ctr, int enable);
++void pmc_start_ctrs(int enable);
++void pmc_stop_ctrs(void);
++void dump_pmcs(void);
++
++extern struct op_powerpc_model op_model_fsl_booke;
++#endif
++
++#endif /* _POWERPC_PMC_H */
+diff --git a/include/asm-powerpc/posix_types.h b/include/asm-powerpc/posix_types.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/posix_types.h
+@@ -0,0 +1,129 @@
++#ifndef _ASM_POWERPC_POSIX_TYPES_H
++#define _ASM_POWERPC_POSIX_TYPES_H
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned long __kernel_ino_t;
++typedef unsigned int __kernel_mode_t;
++typedef long __kernel_off_t;
++typedef int __kernel_pid_t;
++typedef unsigned int __kernel_uid_t;
++typedef unsigned int __kernel_gid_t;
++typedef long __kernel_ptrdiff_t;
++typedef long __kernel_time_t;
++typedef long __kernel_clock_t;
++typedef int __kernel_timer_t;
++typedef int __kernel_clockid_t;
++typedef long __kernel_suseconds_t;
++typedef int __kernel_daddr_t;
++typedef char * __kernel_caddr_t;
++typedef unsigned short __kernel_uid16_t;
++typedef unsigned short __kernel_gid16_t;
++typedef unsigned int __kernel_uid32_t;
++typedef unsigned int __kernel_gid32_t;
++typedef unsigned int __kernel_old_uid_t;
++typedef unsigned int __kernel_old_gid_t;
++
++#ifdef __powerpc64__
++typedef unsigned long __kernel_nlink_t;
++typedef int __kernel_ipc_pid_t;
++typedef unsigned long __kernel_size_t;
++typedef long __kernel_ssize_t;
++typedef unsigned long __kernel_old_dev_t;
++#else
++typedef unsigned short __kernel_nlink_t;
++typedef short __kernel_ipc_pid_t;
++typedef unsigned int __kernel_size_t;
++typedef int __kernel_ssize_t;
++typedef unsigned int __kernel_old_dev_t;
++#endif
++
++#ifdef __powerpc64__
++typedef long long __kernel_loff_t;
++#else
++#ifdef __GNUC__
++typedef long long __kernel_loff_t;
++#endif
++#endif
++
++typedef struct {
++ int val[2];
++} __kernel_fsid_t;
++
++#ifndef __GNUC__
++
++#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
++#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
++#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
++#define __FD_ZERO(set) \
++ ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
++
++#else /* __GNUC__ */
++
++#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
++ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
++/* With GNU C, use inline functions instead so args are evaluated only once: */
++
++#undef __FD_SET
++static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
++{
++ unsigned long _tmp = fd / __NFDBITS;
++ unsigned long _rem = fd % __NFDBITS;
++ fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
++}
++
++#undef __FD_CLR
++static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
++{
++ unsigned long _tmp = fd / __NFDBITS;
++ unsigned long _rem = fd % __NFDBITS;
++ fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
++}
++
++#undef __FD_ISSET
++static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
++{
++ unsigned long _tmp = fd / __NFDBITS;
++ unsigned long _rem = fd % __NFDBITS;
++ return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
++}
++
++/*
++ * This will unroll the loop for the normal constant case (8 ints,
++ * for a 256-bit fd_set)
++ */
++#undef __FD_ZERO
++static __inline__ void __FD_ZERO(__kernel_fd_set *p)
++{
++ unsigned long *tmp = (unsigned long *)p->fds_bits;
++ int i;
++
++ if (__builtin_constant_p(__FDSET_LONGS)) {
++ switch (__FDSET_LONGS) {
++ case 16:
++ tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
++ tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
++
++ case 8:
++ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
++
++ case 4:
++ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++ return;
++ }
++ }
++ i = __FDSET_LONGS;
++ while (i) {
++ i--;
++ *tmp = 0;
++ tmp++;
++ }
++}
++
++#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
++#endif /* __GNUC__ */
++#endif /* _ASM_POWERPC_POSIX_TYPES_H */
+diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/ppc-pci.h
+@@ -0,0 +1,54 @@
++/*
++ * c 2001 PPC 64 Team, IBM Corp
++ *
++ * 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_POWERPC_PPC_PCI_H
++#define _ASM_POWERPC_PPC_PCI_H
++
++#include <linux/pci.h>
++#include <asm/pci-bridge.h>
++
++extern unsigned long isa_io_base;
++
++extern void pci_setup_pci_controller(struct pci_controller *hose);
++extern void pci_setup_phb_io(struct pci_controller *hose, int primary);
++extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary);
++
++
++extern struct list_head hose_list;
++extern int global_phb_number;
++
++extern unsigned long find_and_init_phbs(void);
++
++extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */
++
++/* PCI device_node operations */
++struct device_node;
++typedef void *(*traverse_func)(struct device_node *me, void *data);
++void *traverse_pci_devices(struct device_node *start, traverse_func pre,
++ void *data);
++
++void pci_devs_phb_init(void);
++void pci_devs_phb_init_dynamic(struct pci_controller *phb);
++
++/* PCI address cache management routines */
++void pci_addr_cache_insert_device(struct pci_dev *dev);
++void pci_addr_cache_remove_device(struct pci_dev *dev);
++
++/* From rtas_pci.h */
++void init_pci_config_tokens (void);
++unsigned long get_phb_buid (struct device_node *);
++
++/* From pSeries_pci.h */
++extern void pSeries_final_fixup(void);
++extern void pSeries_irq_bus_setup(struct pci_bus *bus);
++
++extern unsigned long pci_probe_only;
++extern unsigned long pci_assign_all_buses;
++extern int pci_read_irq_line(struct pci_dev *pci_dev);
++
++#endif /* _ASM_POWERPC_PPC_PCI_H */
+diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/ppc_asm.h
+@@ -0,0 +1,511 @@
++/*
++ * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
++ */
++#ifndef _ASM_POWERPC_PPC_ASM_H
++#define _ASM_POWERPC_PPC_ASM_H
++
++#include <linux/stringify.h>
++#include <linux/config.h>
++
++#ifdef __ASSEMBLY__
++
++/*
++ * Macros for storing registers into and loading registers from
++ * exception frames.
++ */
++#ifdef __powerpc64__
++#define SAVE_GPR(n, base) std n,GPR0+8*(n)(base)
++#define REST_GPR(n, base) ld n,GPR0+8*(n)(base)
++#define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, base)
++#define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, base)
++#else
++#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
++#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
++#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \
++ SAVE_10GPRS(22, base)
++#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); \
++ REST_10GPRS(22, base)
++#endif
++
++
++#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
++#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
++#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
++#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
++#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
++#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
++#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
++#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
++
++#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base)
++#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
++#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
++#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
++#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
++#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
++#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base)
++#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
++#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
++#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
++#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
++#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
++
++#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base
++#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
++#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base)
++#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base)
++#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base)
++#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base)
++#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base
++#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
++#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base)
++#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base)
++#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
++#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
++
++#define SAVE_EVR(n,s,base) evmergehi s,s,n; stw s,THREAD_EVR0+4*(n)(base)
++#define SAVE_2EVRS(n,s,base) SAVE_EVR(n,s,base); SAVE_EVR(n+1,s,base)
++#define SAVE_4EVRS(n,s,base) SAVE_2EVRS(n,s,base); SAVE_2EVRS(n+2,s,base)
++#define SAVE_8EVRS(n,s,base) SAVE_4EVRS(n,s,base); SAVE_4EVRS(n+4,s,base)
++#define SAVE_16EVRS(n,s,base) SAVE_8EVRS(n,s,base); SAVE_8EVRS(n+8,s,base)
++#define SAVE_32EVRS(n,s,base) SAVE_16EVRS(n,s,base); SAVE_16EVRS(n+16,s,base)
++#define REST_EVR(n,s,base) lwz s,THREAD_EVR0+4*(n)(base); evmergelo n,s,n
++#define REST_2EVRS(n,s,base) REST_EVR(n,s,base); REST_EVR(n+1,s,base)
++#define REST_4EVRS(n,s,base) REST_2EVRS(n,s,base); REST_2EVRS(n+2,s,base)
++#define REST_8EVRS(n,s,base) REST_4EVRS(n,s,base); REST_4EVRS(n+4,s,base)
++#define REST_16EVRS(n,s,base) REST_8EVRS(n,s,base); REST_8EVRS(n+8,s,base)
++#define REST_32EVRS(n,s,base) REST_16EVRS(n,s,base); REST_16EVRS(n+16,s,base)
++
++/* Macros to adjust thread priority for hardware multithreading */
++#define HMT_VERY_LOW or 31,31,31 # very low priority
++#define HMT_LOW or 1,1,1
++#define HMT_MEDIUM_LOW or 6,6,6 # medium low priority
++#define HMT_MEDIUM or 2,2,2
++#define HMT_MEDIUM_HIGH or 5,5,5 # medium high priority
++#define HMT_HIGH or 3,3,3
++
++/* handle instructions that older assemblers may not know */
++#define RFCI .long 0x4c000066 /* rfci instruction */
++#define RFDI .long 0x4c00004e /* rfdi instruction */
++#define RFMCI .long 0x4c00004c /* rfmci instruction */
++
++#ifdef CONFIG_PPC64
++
++#define XGLUE(a,b) a##b
++#define GLUE(a,b) XGLUE(a,b)
++
++#define _GLOBAL(name) \
++ .section ".text"; \
++ .align 2 ; \
++ .globl name; \
++ .globl GLUE(.,name); \
++ .section ".opd","aw"; \
++name: \
++ .quad GLUE(.,name); \
++ .quad .TOC. at tocbase; \
++ .quad 0; \
++ .previous; \
++ .type GLUE(.,name), at function; \
++GLUE(.,name):
++
++#define _KPROBE(name) \
++ .section ".kprobes.text","a"; \
++ .align 2 ; \
++ .globl name; \
++ .globl GLUE(.,name); \
++ .section ".opd","aw"; \
++name: \
++ .quad GLUE(.,name); \
++ .quad .TOC. at tocbase; \
++ .quad 0; \
++ .previous; \
++ .type GLUE(.,name), at function; \
++GLUE(.,name):
++
++#define _STATIC(name) \
++ .section ".text"; \
++ .align 2 ; \
++ .section ".opd","aw"; \
++name: \
++ .quad GLUE(.,name); \
++ .quad .TOC. at tocbase; \
++ .quad 0; \
++ .previous; \
++ .type GLUE(.,name), at function; \
++GLUE(.,name):
++
++#else /* 32-bit */
++
++#define _GLOBAL(n) \
++ .text; \
++ .stabs __stringify(n:F-1),N_FUN,0,0,n;\
++ .globl n; \
++n:
++
++#define _KPROBE(n) \
++ .section ".kprobes.text","a"; \
++ .globl n; \
++n:
++
++#endif
++
++/*
++ * LOADADDR( rn, name )
++ * loads the address of 'name' into 'rn'
++ *
++ * LOADBASE( rn, name )
++ * loads the address (possibly without the low 16 bits) of 'name' into 'rn'
++ * suitable for base+disp addressing
++ */
++#ifdef __powerpc64__
++#define LOADADDR(rn,name) \
++ lis rn,name##@highest; \
++ ori rn,rn,name##@higher; \
++ rldicr rn,rn,32,31; \
++ oris rn,rn,name##@h; \
++ ori rn,rn,name##@l
++
++#define LOADBASE(rn,name) \
++ ld rn,name at got(r2)
++
++#define OFF(name) 0
++
++#define SET_REG_TO_CONST(reg, value) \
++ lis reg,(((value)>>48)&0xFFFF); \
++ ori reg,reg,(((value)>>32)&0xFFFF); \
++ rldicr reg,reg,32,31; \
++ oris reg,reg,(((value)>>16)&0xFFFF); \
++ ori reg,reg,((value)&0xFFFF);
++
++#define SET_REG_TO_LABEL(reg, label) \
++ lis reg,(label)@highest; \
++ ori reg,reg,(label)@higher; \
++ rldicr reg,reg,32,31; \
++ oris reg,reg,(label)@h; \
++ ori reg,reg,(label)@l;
++
++/* operations for longs and pointers */
++#define LDL ld
++#define STL std
++#define CMPI cmpdi
++#define SZL 8
++
++/* offsets for stack frame layout */
++#define LRSAVE 16
++
++#else /* 32-bit */
++#define LOADADDR(rn,name) \
++ lis rn,name at ha; \
++ addi rn,rn,name at l
++
++#define LOADBASE(rn,name) \
++ lis rn,name at ha
++
++#define OFF(name) name at l
++
++/* operations for longs and pointers */
++#define LDL lwz
++#define STL stw
++#define CMPI cmpwi
++#define SZL 4
++
++/* offsets for stack frame layout */
++#define LRSAVE 4
++
++#endif
++
++/* various errata or part fixups */
++#ifdef CONFIG_PPC601_SYNC_FIX
++#define SYNC \
++BEGIN_FTR_SECTION \
++ sync; \
++ isync; \
++END_FTR_SECTION_IFSET(CPU_FTR_601)
++#define SYNC_601 \
++BEGIN_FTR_SECTION \
++ sync; \
++END_FTR_SECTION_IFSET(CPU_FTR_601)
++#define ISYNC_601 \
++BEGIN_FTR_SECTION \
++ isync; \
++END_FTR_SECTION_IFSET(CPU_FTR_601)
++#else
++#define SYNC
++#define SYNC_601
++#define ISYNC_601
++#endif
++
++
++#ifndef CONFIG_SMP
++#define TLBSYNC
++#else /* CONFIG_SMP */
++/* tlbsync is not implemented on 601 */
++#define TLBSYNC \
++BEGIN_FTR_SECTION \
++ tlbsync; \
++ sync; \
++END_FTR_SECTION_IFCLR(CPU_FTR_601)
++#endif
++
++
++/*
++ * This instruction is not implemented on the PPC 603 or 601; however, on
++ * the 403GCX and 405GP tlbia IS defined and tlbie is not.
++ * All of these instructions exist in the 8xx, they have magical powers,
++ * and they must be used.
++ */
++
++#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
++#define tlbia \
++ li r4,1024; \
++ mtctr r4; \
++ lis r4,KERNELBASE at h; \
++0: tlbie r4; \
++ addi r4,r4,0x1000; \
++ bdnz 0b
++#endif
++
++
++#ifdef CONFIG_IBM405_ERR77
++#define PPC405_ERR77(ra,rb) dcbt ra, rb;
++#define PPC405_ERR77_SYNC sync;
++#else
++#define PPC405_ERR77(ra,rb)
++#define PPC405_ERR77_SYNC
++#endif
++
++
++#ifdef CONFIG_IBM440EP_ERR42
++#define PPC440EP_ERR42 isync
++#else
++#define PPC440EP_ERR42
++#endif
++
++
++#if defined(CONFIG_BOOKE)
++#define toreal(rd)
++#define fromreal(rd)
++
++#define tophys(rd,rs) \
++ addis rd,rs,0
++
++#define tovirt(rd,rs) \
++ addis rd,rs,0
++
++#elif defined(CONFIG_PPC64)
++#define toreal(rd) /* we can access c000... in real mode */
++#define fromreal(rd)
++
++#define tophys(rd,rs) \
++ clrldi rd,rs,2
++
++#define tovirt(rd,rs) \
++ rotldi rd,rs,16; \
++ ori rd,rd,((KERNELBASE>>48)&0xFFFF);\
++ rotldi rd,rd,48
++#else
++/*
++ * On APUS (Amiga PowerPC cpu upgrade board), we don't know the
++ * physical base address of RAM at compile time.
++ */
++#define toreal(rd) tophys(rd,rd)
++#define fromreal(rd) tovirt(rd,rd)
++
++#define tophys(rd,rs) \
++0: addis rd,rs,-KERNELBASE at h; \
++ .section ".vtop_fixup","aw"; \
++ .align 1; \
++ .long 0b; \
++ .previous
++
++#define tovirt(rd,rs) \
++0: addis rd,rs,KERNELBASE at h; \
++ .section ".ptov_fixup","aw"; \
++ .align 1; \
++ .long 0b; \
++ .previous
++#endif
++
++#ifdef CONFIG_PPC64
++#define RFI rfid
++#define MTMSRD(r) mtmsrd r
++
++#else
++#define FIX_SRR1(ra, rb)
++#ifndef CONFIG_40x
++#define RFI rfi
++#else
++#define RFI rfi; b . /* Prevent prefetch past rfi */
++#endif
++#define MTMSRD(r) mtmsr r
++#define CLR_TOP32(r)
++#endif
++
++/* The boring bits... */
++
++/* Condition Register Bit Fields */
++
++#define cr0 0
++#define cr1 1
++#define cr2 2
++#define cr3 3
++#define cr4 4
++#define cr5 5
++#define cr6 6
++#define cr7 7
++
++
++/* General Purpose Registers (GPRs) */
++
++#define r0 0
++#define r1 1
++#define r2 2
++#define r3 3
++#define r4 4
++#define r5 5
++#define r6 6
++#define r7 7
++#define r8 8
++#define r9 9
++#define r10 10
++#define r11 11
++#define r12 12
++#define r13 13
++#define r14 14
++#define r15 15
++#define r16 16
++#define r17 17
++#define r18 18
++#define r19 19
++#define r20 20
++#define r21 21
++#define r22 22
++#define r23 23
++#define r24 24
++#define r25 25
++#define r26 26
++#define r27 27
++#define r28 28
++#define r29 29
++#define r30 30
++#define r31 31
++
++
++/* Floating Point Registers (FPRs) */
++
++#define fr0 0
++#define fr1 1
++#define fr2 2
++#define fr3 3
++#define fr4 4
++#define fr5 5
++#define fr6 6
++#define fr7 7
++#define fr8 8
++#define fr9 9
++#define fr10 10
++#define fr11 11
++#define fr12 12
++#define fr13 13
++#define fr14 14
++#define fr15 15
++#define fr16 16
++#define fr17 17
++#define fr18 18
++#define fr19 19
++#define fr20 20
++#define fr21 21
++#define fr22 22
++#define fr23 23
++#define fr24 24
++#define fr25 25
++#define fr26 26
++#define fr27 27
++#define fr28 28
++#define fr29 29
++#define fr30 30
++#define fr31 31
++
++/* AltiVec Registers (VPRs) */
++
++#define vr0 0
++#define vr1 1
++#define vr2 2
++#define vr3 3
++#define vr4 4
++#define vr5 5
++#define vr6 6
++#define vr7 7
++#define vr8 8
++#define vr9 9
++#define vr10 10
++#define vr11 11
++#define vr12 12
++#define vr13 13
++#define vr14 14
++#define vr15 15
++#define vr16 16
++#define vr17 17
++#define vr18 18
++#define vr19 19
++#define vr20 20
++#define vr21 21
++#define vr22 22
++#define vr23 23
++#define vr24 24
++#define vr25 25
++#define vr26 26
++#define vr27 27
++#define vr28 28
++#define vr29 29
++#define vr30 30
++#define vr31 31
++
++/* SPE Registers (EVPRs) */
++
++#define evr0 0
++#define evr1 1
++#define evr2 2
++#define evr3 3
++#define evr4 4
++#define evr5 5
++#define evr6 6
++#define evr7 7
++#define evr8 8
++#define evr9 9
++#define evr10 10
++#define evr11 11
++#define evr12 12
++#define evr13 13
++#define evr14 14
++#define evr15 15
++#define evr16 16
++#define evr17 17
++#define evr18 18
++#define evr19 19
++#define evr20 20
++#define evr21 21
++#define evr22 22
++#define evr23 23
++#define evr24 24
++#define evr25 25
++#define evr26 26
++#define evr27 27
++#define evr28 28
++#define evr29 29
++#define evr30 30
++#define evr31 31
++
++/* some stab codes */
++#define N_FUN 36
++#define N_RSYM 64
++#define N_SLINE 68
++#define N_SO 100
++
++#define ASM_CONST(x) x
++#else
++ #define __ASM_CONST(x) x##UL
++ #define ASM_CONST(x) __ASM_CONST(x)
++#endif /* __ASSEMBLY__ */
++
++#endif /* _ASM_POWERPC_PPC_ASM_H */
+diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/processor.h
+@@ -0,0 +1,281 @@
++#ifndef _ASM_POWERPC_PROCESSOR_H
++#define _ASM_POWERPC_PROCESSOR_H
++
++/*
++ * Copyright (C) 2001 PPC 64 Team, IBM Corp
++ *
++ * 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/reg.h>
++
++#ifndef __ASSEMBLY__
++#include <linux/compiler.h>
++#include <asm/ptrace.h>
++#include <asm/types.h>
++#ifdef CONFIG_PPC64
++#include <asm/systemcfg.h>
++#endif
++
++#ifdef CONFIG_PPC32
++/* 32-bit platform types */
++/* We only need to define a new _MACH_xxx for machines which are part of
++ * a configuration which supports more than one type of different machine.
++ * This is currently limited to CONFIG_PPC_MULTIPLATFORM and CHRP/PReP/PMac.
++ * -- Tom
++ */
++#define _MACH_prep 0x00000001
++#define _MACH_Pmac 0x00000002 /* pmac or pmac clone (non-chrp) */
++#define _MACH_chrp 0x00000004 /* chrp machine */
++
++/* see residual.h for these */
++#define _PREP_Motorola 0x01 /* motorola prep */
++#define _PREP_Firm 0x02 /* firmworks prep */
++#define _PREP_IBM 0x00 /* ibm prep */
++#define _PREP_Bull 0x03 /* bull prep */
++
++/* these are arbitrary */
++#define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */
++#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
++#define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */
++
++#ifdef CONFIG_PPC_MULTIPLATFORM
++extern int _machine;
++
++/* what kind of prep workstation we are */
++extern int _prep_type;
++extern int _chrp_type;
++
++/*
++ * This is used to identify the board type from a given PReP board
++ * vendor. Board revision is also made available.
++ */
++extern unsigned char ucSystemType;
++extern unsigned char ucBoardRev;
++extern unsigned char ucBoardRevMaj, ucBoardRevMin;
++#else
++#define _machine 0
++#endif /* CONFIG_PPC_MULTIPLATFORM */
++#endif /* CONFIG_PPC32 */
++
++#ifdef CONFIG_PPC64
++/* Platforms supported by PPC64 */
++#define PLATFORM_PSERIES 0x0100
++#define PLATFORM_PSERIES_LPAR 0x0101
++#define PLATFORM_ISERIES_LPAR 0x0201
++#define PLATFORM_LPAR 0x0001
++#define PLATFORM_POWERMAC 0x0400
++#define PLATFORM_MAPLE 0x0500
++#define PLATFORM_BPA 0x1000
++
++/* Compatibility with drivers coming from PPC32 world */
++#define _machine (systemcfg->platform)
++#define _MACH_Pmac PLATFORM_POWERMAC
++#endif
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ __label__ _l; _l: &&_l;})
++
++/* Macros for adjusting thread priority (hardware multi-threading) */
++#define HMT_very_low() asm volatile("or 31,31,31 # very low priority")
++#define HMT_low() asm volatile("or 1,1,1 # low priority")
++#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority")
++#define HMT_medium() asm volatile("or 2,2,2 # medium priority")
++#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority")
++#define HMT_high() asm volatile("or 3,3,3 # high priority")
++
++#ifdef __KERNEL__
++
++extern int have_of;
++
++struct task_struct;
++void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
++void release_thread(struct task_struct *);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++extern void prepare_to_copy(struct task_struct *tsk);
++
++/* Create a new kernel thread. */
++extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
++
++/* Lazy FPU handling on uni-processor */
++extern struct task_struct *last_task_used_math;
++extern struct task_struct *last_task_used_altivec;
++extern struct task_struct *last_task_used_spe;
++
++#ifdef CONFIG_PPC32
++#define TASK_SIZE (CONFIG_TASK_SIZE)
++
++/* This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
++#endif
++
++#ifdef CONFIG_PPC64
++/* 64-bit user address space is 44-bits (16TB user VM) */
++#define TASK_SIZE_USER64 (0x0000100000000000UL)
++
++/*
++ * 32-bit user address space is 4GB - 1 page
++ * (this 1 page is needed so referencing of 0xFFFFFFFF generates EFAULT
++ */
++#define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE))
++
++#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
++ TASK_SIZE_USER32 : TASK_SIZE_USER64)
++
++/* This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
++#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))
++
++#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)) ? \
++ TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
++#endif
++
++typedef struct {
++ unsigned long seg;
++} mm_segment_t;
++
++struct thread_struct {
++ unsigned long ksp; /* Kernel stack pointer */
++#ifdef CONFIG_PPC64
++ unsigned long ksp_vsid;
++#endif
++ struct pt_regs *regs; /* Pointer to saved register state */
++ mm_segment_t fs; /* for get_fs() validation */
++#ifdef CONFIG_PPC32
++ void *pgdir; /* root of page-table tree */
++ signed long last_syscall;
++#endif
++#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
++ unsigned long dbcr0; /* debug control register values */
++ unsigned long dbcr1;
++#endif
++ double fpr[32]; /* Complete floating point set */
++ struct { /* fpr ... fpscr must be contiguous */
++
++ unsigned int pad;
++ unsigned int val; /* Floating point status */
++ } fpscr;
++ int fpexc_mode; /* floating-point exception mode */
++#ifdef CONFIG_PPC64
++ unsigned long start_tb; /* Start purr when proc switched in */
++ unsigned long accum_tb; /* Total accumilated purr for process */
++ unsigned long vdso_base; /* base of the vDSO library */
++#endif
++ unsigned long dabr; /* Data address breakpoint register */
++#ifdef CONFIG_ALTIVEC
++ /* Complete AltiVec register set */
++ vector128 vr[32] __attribute((aligned(16)));
++ /* AltiVec status */
++ vector128 vscr __attribute((aligned(16)));
++ unsigned long vrsave;
++ int used_vr; /* set if process has used altivec */
++#endif /* CONFIG_ALTIVEC */
++#ifdef CONFIG_SPE
++ unsigned long evr[32]; /* upper 32-bits of SPE regs */
++ u64 acc; /* Accumulator */
++ unsigned long spefscr; /* SPE & eFP status */
++ int used_spe; /* set if process has used spe */
++#endif /* CONFIG_SPE */
++};
++
++#define ARCH_MIN_TASKALIGN 16
++
++#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
++
++
++#ifdef CONFIG_PPC32
++#define INIT_THREAD { \
++ .ksp = INIT_SP, \
++ .fs = KERNEL_DS, \
++ .pgdir = swapper_pg_dir, \
++ .fpexc_mode = MSR_FE0 | MSR_FE1, \
++}
++#else
++#define INIT_THREAD { \
++ .ksp = INIT_SP, \
++ .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
++ .fs = KERNEL_DS, \
++ .fpr = {0}, \
++ .fpscr = { .val = 0, }, \
++ .fpexc_mode = MSR_FE0|MSR_FE1, \
++}
++#endif
++
++/*
++ * Return saved PC of a blocked thread. For now, this is the "user" PC
++ */
++#define thread_saved_pc(tsk) \
++ ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
++
++unsigned long get_wchan(struct task_struct *p);
++
++#define KSTK_EIP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
++#define KSTK_ESP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0)
++
++/* Get/set floating-point exception mode */
++#define GET_FPEXC_CTL(tsk, adr) get_fpexc_mode((tsk), (adr))
++#define SET_FPEXC_CTL(tsk, val) set_fpexc_mode((tsk), (val))
++
++extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr);
++extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val);
++
++static inline unsigned int __unpack_fe01(unsigned long msr_bits)
++{
++ return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
++}
++
++static inline unsigned long __pack_fe01(unsigned int fpmode)
++{
++ return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1);
++}
++
++#ifdef CONFIG_PPC64
++#define cpu_relax() do { HMT_low(); HMT_medium(); barrier(); } while (0)
++#else
++#define cpu_relax() barrier()
++#endif
++
++/*
++ * Prefetch macros.
++ */
++#define ARCH_HAS_PREFETCH
++#define ARCH_HAS_PREFETCHW
++#define ARCH_HAS_SPINLOCK_PREFETCH
++
++static inline void prefetch(const void *x)
++{
++ if (unlikely(!x))
++ return;
++
++ __asm__ __volatile__ ("dcbt 0,%0" : : "r" (x));
++}
++
++static inline void prefetchw(const void *x)
++{
++ if (unlikely(!x))
++ return;
++
++ __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x));
++}
++
++#define spin_lock_prefetch(x) prefetchw(x)
++
++#ifdef CONFIG_PPC64
++#define HAVE_ARCH_PICK_MMAP_LAYOUT
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* __ASSEMBLY__ */
++#endif /* _ASM_POWERPC_PROCESSOR_H */
+diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/prom.h
+@@ -0,0 +1,219 @@
++#ifndef _POWERPC_PROM_H
++#define _POWERPC_PROM_H
++#ifdef __KERNEL__
++
++/*
++ * Definitions for talking to the Open Firmware PROM on
++ * Power Macintosh computers.
++ *
++ * Copyright (C) 1996-2005 Paul Mackerras.
++ *
++ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
++ *
++ * 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/types.h>
++#include <linux/proc_fs.h>
++#include <asm/atomic.h>
++
++/* Definitions used by the flattened device tree */
++#define OF_DT_HEADER 0xd00dfeed /* marker */
++#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
++#define OF_DT_END_NODE 0x2 /* End node */
++#define OF_DT_PROP 0x3 /* Property: name off, size,
++ * content */
++#define OF_DT_NOP 0x4 /* nop */
++#define OF_DT_END 0x9
++
++#define OF_DT_VERSION 0x10
++
++/*
++ * This is what gets passed to the kernel by prom_init or kexec
++ *
++ * The dt struct contains the device tree structure, full pathes and
++ * property contents. The dt strings contain a separate block with just
++ * the strings for the property names, and is fully page aligned and
++ * self contained in a page, so that it can be kept around by the kernel,
++ * each property name appears only once in this page (cheap compression)
++ *
++ * the mem_rsvmap contains a map of reserved ranges of physical memory,
++ * passing it here instead of in the device-tree itself greatly simplifies
++ * the job of everybody. It's just a list of u64 pairs (base/size) that
++ * ends when size is 0
++ */
++struct boot_param_header
++{
++ u32 magic; /* magic word OF_DT_HEADER */
++ u32 totalsize; /* total size of DT block */
++ u32 off_dt_struct; /* offset to structure */
++ u32 off_dt_strings; /* offset to strings */
++ u32 off_mem_rsvmap; /* offset to memory reserve map */
++ u32 version; /* format version */
++ u32 last_comp_version; /* last compatible version */
++ /* version 2 fields below */
++ u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
++ /* version 3 fields below */
++ u32 dt_strings_size; /* size of the DT strings block */
++};
++
++
++
++typedef u32 phandle;
++typedef u32 ihandle;
++
++struct address_range {
++ unsigned long space;
++ unsigned long address;
++ unsigned long size;
++};
++
++struct interrupt_info {
++ int line;
++ int sense; /* +ve/-ve logic, edge or level, etc. */
++};
++
++struct pci_address {
++ u32 a_hi;
++ u32 a_mid;
++ u32 a_lo;
++};
++
++struct isa_address {
++ u32 a_hi;
++ u32 a_lo;
++};
++
++struct isa_range {
++ struct isa_address isa_addr;
++ struct pci_address pci_addr;
++ unsigned int size;
++};
++
++struct reg_property {
++ unsigned long address;
++ unsigned long size;
++};
++
++struct reg_property32 {
++ unsigned int address;
++ unsigned int size;
++};
++
++struct reg_property64 {
++ u64 address;
++ u64 size;
++};
++
++struct property {
++ char *name;
++ int length;
++ unsigned char *value;
++ struct property *next;
++};
++
++struct device_node {
++ char *name;
++ char *type;
++ phandle node;
++ phandle linux_phandle;
++ int n_addrs;
++ struct address_range *addrs;
++ int n_intrs;
++ struct interrupt_info *intrs;
++ char *full_name;
++
++ struct property *properties;
++ struct device_node *parent;
++ struct device_node *child;
++ struct device_node *sibling;
++ struct device_node *next; /* next device of same type */
++ struct device_node *allnext; /* next in list of all nodes */
++ struct proc_dir_entry *pde; /* this node's proc directory */
++ struct kref kref;
++ unsigned long _flags;
++ void *data;
++};
++
++extern struct device_node *of_chosen;
++
++/* flag descriptions */
++#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
++
++#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
++#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
++
++#define HAVE_ARCH_DEVTREE_FIXUPS
++
++static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
++{
++ dn->pde = de;
++}
++
++
++/* OBSOLETE: Old style node lookup */
++extern struct device_node *find_devices(const char *name);
++extern struct device_node *find_type_devices(const char *type);
++extern struct device_node *find_path_device(const char *path);
++extern struct device_node *find_compatible_devices(const char *type,
++ const char *compat);
++extern struct device_node *find_all_nodes(void);
++
++/* New style node lookup */
++extern struct device_node *of_find_node_by_name(struct device_node *from,
++ const char *name);
++extern struct device_node *of_find_node_by_type(struct device_node *from,
++ const char *type);
++extern struct device_node *of_find_compatible_node(struct device_node *from,
++ const char *type, const char *compat);
++extern struct device_node *of_find_node_by_path(const char *path);
++extern struct device_node *of_find_node_by_phandle(phandle handle);
++extern struct device_node *of_find_all_nodes(struct device_node *prev);
++extern struct device_node *of_get_parent(const struct device_node *node);
++extern struct device_node *of_get_next_child(const struct device_node *node,
++ struct device_node *prev);
++extern struct device_node *of_node_get(struct device_node *node);
++extern void of_node_put(struct device_node *node);
++
++/* For updating the device tree at runtime */
++extern void of_attach_node(struct device_node *);
++extern void of_detach_node(const struct device_node *);
++
++/* Other Prototypes */
++extern void finish_device_tree(void);
++extern void unflatten_device_tree(void);
++extern void early_init_devtree(void *);
++extern int device_is_compatible(struct device_node *device, const char *);
++extern int machine_is_compatible(const char *compat);
++extern unsigned char *get_property(struct device_node *node, const char *name,
++ int *lenp);
++extern void print_properties(struct device_node *node);
++extern int prom_n_addr_cells(struct device_node* np);
++extern int prom_n_size_cells(struct device_node* np);
++extern int prom_n_intr_cells(struct device_node* np);
++extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
++extern void prom_add_property(struct device_node* np, struct property* prop);
++
++#ifdef CONFIG_PPC32
++/*
++ * PCI <-> OF matching functions
++ * (XXX should these be here?)
++ */
++struct pci_bus;
++struct pci_dev;
++extern int pci_device_from_OF_node(struct device_node *node,
++ u8* bus, u8* devfn);
++extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
++extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
++extern void pci_create_OF_bus_map(void);
++#endif
++
++extern struct resource *request_OF_resource(struct device_node* node,
++ int index, const char* name_postfix);
++extern int release_OF_resource(struct device_node* node, int index);
++
++#endif /* __KERNEL__ */
++#endif /* _POWERPC_PROM_H */
+diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/reg.h
+@@ -0,0 +1,613 @@
++/*
++ * Contains the definition of registers common to all PowerPC variants.
++ * If a register definition has been changed in a different PowerPC
++ * variant, we will case it in #ifndef XXX ... #endif, and have the
++ * number used in the Programming Environments Manual For 32-Bit
++ * Implementations of the PowerPC Architecture (a.k.a. Green Book) here.
++ */
++
++#ifndef _ASM_POWERPC_REG_H
++#define _ASM_POWERPC_REG_H
++#ifdef __KERNEL__
++
++#include <linux/stringify.h>
++#include <asm/cputable.h>
++
++/* Pickup Book E specific registers. */
++#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
++#include <asm/reg_booke.h>
++#endif
++
++#define MSR_SF_LG 63 /* Enable 64 bit mode */
++#define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */
++#define MSR_HV_LG 60 /* Hypervisor state */
++#define MSR_VEC_LG 25 /* Enable AltiVec */
++#define MSR_POW_LG 18 /* Enable Power Management */
++#define MSR_WE_LG 18 /* Wait State Enable */
++#define MSR_TGPR_LG 17 /* TLB Update registers in use */
++#define MSR_CE_LG 17 /* Critical Interrupt Enable */
++#define MSR_ILE_LG 16 /* Interrupt Little Endian */
++#define MSR_EE_LG 15 /* External Interrupt Enable */
++#define MSR_PR_LG 14 /* Problem State / Privilege Level */
++#define MSR_FP_LG 13 /* Floating Point enable */
++#define MSR_ME_LG 12 /* Machine Check Enable */
++#define MSR_FE0_LG 11 /* Floating Exception mode 0 */
++#define MSR_SE_LG 10 /* Single Step */
++#define MSR_BE_LG 9 /* Branch Trace */
++#define MSR_DE_LG 9 /* Debug Exception Enable */
++#define MSR_FE1_LG 8 /* Floating Exception mode 1 */
++#define MSR_IP_LG 6 /* Exception prefix 0x000/0xFFF */
++#define MSR_IR_LG 5 /* Instruction Relocate */
++#define MSR_DR_LG 4 /* Data Relocate */
++#define MSR_PE_LG 3 /* Protection Enable */
++#define MSR_PX_LG 2 /* Protection Exclusive Mode */
++#define MSR_PMM_LG 2 /* Performance monitor */
++#define MSR_RI_LG 1 /* Recoverable Exception */
++#define MSR_LE_LG 0 /* Little Endian */
++
++#ifdef __ASSEMBLY__
++#define __MASK(X) (1<<(X))
++#else
++#define __MASK(X) (1UL<<(X))
++#endif
++
++#ifdef CONFIG_PPC64
++#define MSR_SF __MASK(MSR_SF_LG) /* Enable 64 bit mode */
++#define MSR_ISF __MASK(MSR_ISF_LG) /* Interrupt 64b mode valid on 630 */
++#define MSR_HV __MASK(MSR_HV_LG) /* Hypervisor state */
++#else
++/* so tests for these bits fail on 32-bit */
++#define MSR_SF 0
++#define MSR_ISF 0
++#define MSR_HV 0
++#endif
++
++#define MSR_VEC __MASK(MSR_VEC_LG) /* Enable AltiVec */
++#define MSR_POW __MASK(MSR_POW_LG) /* Enable Power Management */
++#define MSR_WE __MASK(MSR_WE_LG) /* Wait State Enable */
++#define MSR_TGPR __MASK(MSR_TGPR_LG) /* TLB Update registers in use */
++#define MSR_CE __MASK(MSR_CE_LG) /* Critical Interrupt Enable */
++#define MSR_ILE __MASK(MSR_ILE_LG) /* Interrupt Little Endian */
++#define MSR_EE __MASK(MSR_EE_LG) /* External Interrupt Enable */
++#define MSR_PR __MASK(MSR_PR_LG) /* Problem State / Privilege Level */
++#define MSR_FP __MASK(MSR_FP_LG) /* Floating Point enable */
++#define MSR_ME __MASK(MSR_ME_LG) /* Machine Check Enable */
++#define MSR_FE0 __MASK(MSR_FE0_LG) /* Floating Exception mode 0 */
++#define MSR_SE __MASK(MSR_SE_LG) /* Single Step */
++#define MSR_BE __MASK(MSR_BE_LG) /* Branch Trace */
++#define MSR_DE __MASK(MSR_DE_LG) /* Debug Exception Enable */
++#define MSR_FE1 __MASK(MSR_FE1_LG) /* Floating Exception mode 1 */
++#define MSR_IP __MASK(MSR_IP_LG) /* Exception prefix 0x000/0xFFF */
++#define MSR_IR __MASK(MSR_IR_LG) /* Instruction Relocate */
++#define MSR_DR __MASK(MSR_DR_LG) /* Data Relocate */
++#define MSR_PE __MASK(MSR_PE_LG) /* Protection Enable */
++#define MSR_PX __MASK(MSR_PX_LG) /* Protection Exclusive Mode */
++#ifndef MSR_PMM
++#define MSR_PMM __MASK(MSR_PMM_LG) /* Performance monitor */
++#endif
++#define MSR_RI __MASK(MSR_RI_LG) /* Recoverable Exception */
++#define MSR_LE __MASK(MSR_LE_LG) /* Little Endian */
++
++#ifdef CONFIG_PPC64
++#define MSR_ MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF
++#define MSR_KERNEL MSR_ | MSR_SF | MSR_HV
++
++#define MSR_USER32 MSR_ | MSR_PR | MSR_EE
++#define MSR_USER64 MSR_USER32 | MSR_SF
++
++#else /* 32-bit */
++/* Default MSR for kernel mode. */
++#ifndef MSR_KERNEL /* reg_booke.h also defines this */
++#ifdef CONFIG_APUS_FAST_EXCEPT
++#define MSR_KERNEL (MSR_ME|MSR_IP|MSR_RI|MSR_IR|MSR_DR)
++#else
++#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR)
++#endif
++#endif
++
++#define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE)
++#endif
++
++/* Floating Point Status and Control Register (FPSCR) Fields */
++#define FPSCR_FX 0x80000000 /* FPU exception summary */
++#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */
++#define FPSCR_VX 0x20000000 /* Invalid operation summary */
++#define FPSCR_OX 0x10000000 /* Overflow exception summary */
++#define FPSCR_UX 0x08000000 /* Underflow exception summary */
++#define FPSCR_ZX 0x04000000 /* Zero-divide exception summary */
++#define FPSCR_XX 0x02000000 /* Inexact exception summary */
++#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */
++#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */
++#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */
++#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */
++#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */
++#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */
++#define FPSCR_FR 0x00040000 /* Fraction rounded */
++#define FPSCR_FI 0x00020000 /* Fraction inexact */
++#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */
++#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */
++#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */
++#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */
++#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */
++#define FPSCR_VE 0x00000080 /* Invalid op exception enable */
++#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */
++#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */
++#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */
++#define FPSCR_XE 0x00000008 /* FP inexact exception enable */
++#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */
++#define FPSCR_RN 0x00000003 /* FPU rounding control */
++
++/* Special Purpose Registers (SPRNs)*/
++#define SPRN_CTR 0x009 /* Count Register */
++#define SPRN_CTRLF 0x088
++#define SPRN_CTRLT 0x098
++#define CTRL_RUNLATCH 0x1
++#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
++#define DABR_TRANSLATION (1UL << 2)
++#define SPRN_DAR 0x013 /* Data Address Register */
++#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
++#define DSISR_NOHPTE 0x40000000 /* no translation found */
++#define DSISR_PROTFAULT 0x08000000 /* protection fault */
++#define DSISR_ISSTORE 0x02000000 /* access was a store */
++#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
++#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */
++#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
++#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
++#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */
++#define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */
++#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
++#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
++#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
++#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */
++#define SPRN_DBAT1U 0x21A /* Data BAT 1 Upper Register */
++#define SPRN_DBAT2L 0x21D /* Data BAT 2 Lower Register */
++#define SPRN_DBAT2U 0x21C /* Data BAT 2 Upper Register */
++#define SPRN_DBAT3L 0x21F /* Data BAT 3 Lower Register */
++#define SPRN_DBAT3U 0x21E /* Data BAT 3 Upper Register */
++#define SPRN_DBAT4L 0x239 /* Data BAT 4 Lower Register */
++#define SPRN_DBAT4U 0x238 /* Data BAT 4 Upper Register */
++#define SPRN_DBAT5L 0x23B /* Data BAT 5 Lower Register */
++#define SPRN_DBAT5U 0x23A /* Data BAT 5 Upper Register */
++#define SPRN_DBAT6L 0x23D /* Data BAT 6 Lower Register */
++#define SPRN_DBAT6U 0x23C /* Data BAT 6 Upper Register */
++#define SPRN_DBAT7L 0x23F /* Data BAT 7 Lower Register */
++#define SPRN_DBAT7U 0x23E /* Data BAT 7 Upper Register */
++
++#define SPRN_DEC 0x016 /* Decrement Register */
++#define SPRN_DER 0x095 /* Debug Enable Regsiter */
++#define DER_RSTE 0x40000000 /* Reset Interrupt */
++#define DER_CHSTPE 0x20000000 /* Check Stop */
++#define DER_MCIE 0x10000000 /* Machine Check Interrupt */
++#define DER_EXTIE 0x02000000 /* External Interrupt */
++#define DER_ALIE 0x01000000 /* Alignment Interrupt */
++#define DER_PRIE 0x00800000 /* Program Interrupt */
++#define DER_FPUVIE 0x00400000 /* FP Unavailable Interrupt */
++#define DER_DECIE 0x00200000 /* Decrementer Interrupt */
++#define DER_SYSIE 0x00040000 /* System Call Interrupt */
++#define DER_TRE 0x00020000 /* Trace Interrupt */
++#define DER_SEIE 0x00004000 /* FP SW Emulation Interrupt */
++#define DER_ITLBMSE 0x00002000 /* Imp. Spec. Instruction TLB Miss */
++#define DER_ITLBERE 0x00001000 /* Imp. Spec. Instruction TLB Error */
++#define DER_DTLBMSE 0x00000800 /* Imp. Spec. Data TLB Miss */
++#define DER_DTLBERE 0x00000400 /* Imp. Spec. Data TLB Error */
++#define DER_LBRKE 0x00000008 /* Load/Store Breakpoint Interrupt */
++#define DER_IBRKE 0x00000004 /* Instruction Breakpoint Interrupt */
++#define DER_EBRKE 0x00000002 /* External Breakpoint Interrupt */
++#define DER_DPIE 0x00000001 /* Dev. Port Nonmaskable Request */
++#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
++#define SPRN_EAR 0x11A /* External Address Register */
++#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
++#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
++#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
++#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
++#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
++#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
++#define HID0_SBCLK (1<<27)
++#define HID0_EICE (1<<26)
++#define HID0_TBEN (1<<26) /* Timebase enable - 745x */
++#define HID0_ECLK (1<<25)
++#define HID0_PAR (1<<24)
++#define HID0_STEN (1<<24) /* Software table search enable - 745x */
++#define HID0_HIGH_BAT (1<<23) /* Enable high BATs - 7455 */
++#define HID0_DOZE (1<<23)
++#define HID0_NAP (1<<22)
++#define HID0_SLEEP (1<<21)
++#define HID0_DPM (1<<20)
++#define HID0_BHTCLR (1<<18) /* Clear branch history table - 7450 */
++#define HID0_XAEN (1<<17) /* Extended addressing enable - 7450 */
++#define HID0_NHR (1<<16) /* Not hard reset (software bit-7450)*/
++#define HID0_ICE (1<<15) /* Instruction Cache Enable */
++#define HID0_DCE (1<<14) /* Data Cache Enable */
++#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
++#define HID0_DLOCK (1<<12) /* Data Cache Lock */
++#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
++#define HID0_DCI (1<<10) /* Data Cache Invalidate */
++#define HID0_SPD (1<<9) /* Speculative disable */
++#define HID0_DAPUEN (1<<8) /* Debug APU enable */
++#define HID0_SGE (1<<7) /* Store Gathering Enable */
++#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
++#define HID0_DFCA (1<<6) /* Data Cache Flush Assist */
++#define HID0_LRSTK (1<<4) /* Link register stack - 745x */
++#define HID0_BTIC (1<<5) /* Branch Target Instr Cache Enable */
++#define HID0_ABE (1<<3) /* Address Broadcast Enable */
++#define HID0_FOLD (1<<3) /* Branch Folding enable - 745x */
++#define HID0_BHTE (1<<2) /* Branch History Table Enable */
++#define HID0_BTCD (1<<1) /* Branch target cache disable */
++#define HID0_NOPDST (1<<1) /* No-op dst, dstt, etc. instr. */
++#define HID0_NOPTI (1<<0) /* No-op dcbt and dcbst instr. */
++
++#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
++#define HID1_EMCP (1<<31) /* 7450 Machine Check Pin Enable */
++#define HID1_DFS (1<<22) /* 7447A Dynamic Frequency Scaling */
++#define HID1_PC0 (1<<16) /* 7450 PLL_CFG[0] */
++#define HID1_PC1 (1<<15) /* 7450 PLL_CFG[1] */
++#define HID1_PC2 (1<<14) /* 7450 PLL_CFG[2] */
++#define HID1_PC3 (1<<13) /* 7450 PLL_CFG[3] */
++#define HID1_SYNCBE (1<<11) /* 7450 ABE for sync, eieio */
++#define HID1_ABE (1<<10) /* 7450 Address Broadcast Enable */
++#define HID1_PS (1<<16) /* 750FX PLL selection */
++#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
++#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
++#define SPRN_HID4 0x3F4 /* 970 HID4 */
++#define SPRN_HID5 0x3F6 /* 970 HID5 */
++#define SPRN_HID6 0x3F9 /* BE HID 6 */
++#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */
++#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */
++#define SPRN_TSCR 0x399 /* Thread switch control on BE */
++#define SPRN_TTR 0x39A /* Thread switch timeout on BE */
++#define TSCR_DEC_ENABLE 0x200000 /* Decrementer Interrupt */
++#define TSCR_EE_ENABLE 0x100000 /* External Interrupt */
++#define TSCR_EE_BOOST 0x080000 /* External Interrupt Boost */
++#define SPRN_TSC 0x3FD /* Thread switch control on others */
++#define SPRN_TST 0x3FC /* Thread switch timeout on others */
++#if !defined(SPRN_IAC1) && !defined(SPRN_IAC2)
++#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
++#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
++#endif
++#define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */
++#define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */
++#define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */
++#define SPRN_IBAT1U 0x212 /* Instruction BAT 1 Upper Register */
++#define SPRN_IBAT2L 0x215 /* Instruction BAT 2 Lower Register */
++#define SPRN_IBAT2U 0x214 /* Instruction BAT 2 Upper Register */
++#define SPRN_IBAT3L 0x217 /* Instruction BAT 3 Lower Register */
++#define SPRN_IBAT3U 0x216 /* Instruction BAT 3 Upper Register */
++#define SPRN_IBAT4L 0x231 /* Instruction BAT 4 Lower Register */
++#define SPRN_IBAT4U 0x230 /* Instruction BAT 4 Upper Register */
++#define SPRN_IBAT5L 0x233 /* Instruction BAT 5 Lower Register */
++#define SPRN_IBAT5U 0x232 /* Instruction BAT 5 Upper Register */
++#define SPRN_IBAT6L 0x235 /* Instruction BAT 6 Lower Register */
++#define SPRN_IBAT6U 0x234 /* Instruction BAT 6 Upper Register */
++#define SPRN_IBAT7L 0x237 /* Instruction BAT 7 Lower Register */
++#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */
++#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
++#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
++#define SPRN_ICTRL 0x3F3 /* 1011 7450 icache and interrupt ctrl */
++#define ICTRL_EICE 0x08000000 /* enable icache parity errs */
++#define ICTRL_EDC 0x04000000 /* enable dcache parity errs */
++#define ICTRL_EICP 0x00000100 /* enable icache par. check */
++#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
++#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
++#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
++#define SPRN_L2CR2 0x3f8
++#define L2CR_L2E 0x80000000 /* L2 enable */
++#define L2CR_L2PE 0x40000000 /* L2 parity enable */
++#define L2CR_L2SIZ_MASK 0x30000000 /* L2 size mask */
++#define L2CR_L2SIZ_256KB 0x10000000 /* L2 size 256KB */
++#define L2CR_L2SIZ_512KB 0x20000000 /* L2 size 512KB */
++#define L2CR_L2SIZ_1MB 0x30000000 /* L2 size 1MB */
++#define L2CR_L2CLK_MASK 0x0e000000 /* L2 clock mask */
++#define L2CR_L2CLK_DISABLED 0x00000000 /* L2 clock disabled */
++#define L2CR_L2CLK_DIV1 0x02000000 /* L2 clock / 1 */
++#define L2CR_L2CLK_DIV1_5 0x04000000 /* L2 clock / 1.5 */
++#define L2CR_L2CLK_DIV2 0x08000000 /* L2 clock / 2 */
++#define L2CR_L2CLK_DIV2_5 0x0a000000 /* L2 clock / 2.5 */
++#define L2CR_L2CLK_DIV3 0x0c000000 /* L2 clock / 3 */
++#define L2CR_L2RAM_MASK 0x01800000 /* L2 RAM type mask */
++#define L2CR_L2RAM_FLOW 0x00000000 /* L2 RAM flow through */
++#define L2CR_L2RAM_PIPE 0x01000000 /* L2 RAM pipelined */
++#define L2CR_L2RAM_PIPE_LW 0x01800000 /* L2 RAM pipelined latewr */
++#define L2CR_L2DO 0x00400000 /* L2 data only */
++#define L2CR_L2I 0x00200000 /* L2 global invalidate */
++#define L2CR_L2CTL 0x00100000 /* L2 RAM control */
++#define L2CR_L2WT 0x00080000 /* L2 write-through */
++#define L2CR_L2TS 0x00040000 /* L2 test support */
++#define L2CR_L2OH_MASK 0x00030000 /* L2 output hold mask */
++#define L2CR_L2OH_0_5 0x00000000 /* L2 output hold 0.5 ns */
++#define L2CR_L2OH_1_0 0x00010000 /* L2 output hold 1.0 ns */
++#define L2CR_L2SL 0x00008000 /* L2 DLL slow */
++#define L2CR_L2DF 0x00004000 /* L2 differential clock */
++#define L2CR_L2BYP 0x00002000 /* L2 DLL bypass */
++#define L2CR_L2IP 0x00000001 /* L2 GI in progress */
++#define L2CR_L2IO_745x 0x00100000 /* L2 instr. only (745x) */
++#define L2CR_L2DO_745x 0x00010000 /* L2 data only (745x) */
++#define L2CR_L2REP_745x 0x00001000 /* L2 repl. algorithm (745x) */
++#define L2CR_L2HWF_745x 0x00000800 /* L2 hardware flush (745x) */
++#define SPRN_L3CR 0x3FA /* Level 3 Cache Control Regsiter */
++#define L3CR_L3E 0x80000000 /* L3 enable */
++#define L3CR_L3PE 0x40000000 /* L3 data parity enable */
++#define L3CR_L3APE 0x20000000 /* L3 addr parity enable */
++#define L3CR_L3SIZ 0x10000000 /* L3 size */
++#define L3CR_L3CLKEN 0x08000000 /* L3 clock enable */
++#define L3CR_L3RES 0x04000000 /* L3 special reserved bit */
++#define L3CR_L3CLKDIV 0x03800000 /* L3 clock divisor */
++#define L3CR_L3IO 0x00400000 /* L3 instruction only */
++#define L3CR_L3SPO 0x00040000 /* L3 sample point override */
++#define L3CR_L3CKSP 0x00030000 /* L3 clock sample point */
++#define L3CR_L3PSP 0x0000e000 /* L3 P-clock sample point */
++#define L3CR_L3REP 0x00001000 /* L3 replacement algorithm */
++#define L3CR_L3HWF 0x00000800 /* L3 hardware flush */
++#define L3CR_L3I 0x00000400 /* L3 global invalidate */
++#define L3CR_L3RT 0x00000300 /* L3 SRAM type */
++#define L3CR_L3NIRCA 0x00000080 /* L3 non-integer ratio clock adj. */
++#define L3CR_L3DO 0x00000040 /* L3 data only mode */
++#define L3CR_PMEN 0x00000004 /* L3 private memory enable */
++#define L3CR_PMSIZ 0x00000001 /* L3 private memory size */
++
++#define SPRN_MSSCR0 0x3f6 /* Memory Subsystem Control Register 0 */
++#define SPRN_MSSSR0 0x3f7 /* Memory Subsystem Status Register 1 */
++#define SPRN_LDSTCR 0x3f8 /* Load/Store control register */
++#define SPRN_LDSTDB 0x3f4 /* */
++#define SPRN_LR 0x008 /* Link Register */
++#ifndef SPRN_PIR
++#define SPRN_PIR 0x3FF /* Processor Identification Register */
++#endif
++#define SPRN_PTEHI 0x3D5 /* 981 7450 PTE HI word (S/W TLB load) */
++#define SPRN_PTELO 0x3D6 /* 982 7450 PTE LO word (S/W TLB load) */
++#define SPRN_PURR 0x135 /* Processor Utilization of Resources Reg */
++#define SPRN_PVR 0x11F /* Processor Version Register */
++#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
++#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
++#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
++#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
++#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
++#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
++#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
++#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
++#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
++#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
++#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
++#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
++#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
++#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
++#ifndef SPRN_SVR
++#define SPRN_SVR 0x11E /* System Version Register */
++#endif
++#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
++/* these bits were defined in inverted endian sense originally, ugh, confusing */
++#define THRM1_TIN (1 << 31)
++#define THRM1_TIV (1 << 30)
++#define THRM1_THRES(x) ((x&0x7f)<<23)
++#define THRM3_SITV(x) ((x&0x3fff)<<1)
++#define THRM1_TID (1<<2)
++#define THRM1_TIE (1<<1)
++#define THRM1_V (1<<0)
++#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
++#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
++#define THRM3_E (1<<0)
++#define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */
++#define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */
++#define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */
++#define SPRN_UPMC1 0x3A9 /* User Performance Counter Register 1 */
++#define SPRN_UPMC2 0x3AA /* User Performance Counter Register 2 */
++#define SPRN_UPMC3 0x3AD /* User Performance Counter Register 3 */
++#define SPRN_UPMC4 0x3AE /* User Performance Counter Register 4 */
++#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
++#define SPRN_VRSAVE 0x100 /* Vector Register Save Register */
++#define SPRN_XER 0x001 /* Fixed Point Exception Register */
++
++/* Performance monitor SPRs */
++#ifdef CONFIG_PPC64
++#define SPRN_MMCR0 795
++#define MMCR0_FC 0x80000000UL /* freeze counters */
++#define MMCR0_FCS 0x40000000UL /* freeze in supervisor state */
++#define MMCR0_KERNEL_DISABLE MMCR0_FCS
++#define MMCR0_FCP 0x20000000UL /* freeze in problem state */
++#define MMCR0_PROBLEM_DISABLE MMCR0_FCP
++#define MMCR0_FCM1 0x10000000UL /* freeze counters while MSR mark = 1 */
++#define MMCR0_FCM0 0x08000000UL /* freeze counters while MSR mark = 0 */
++#define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */
++#define MMCR0_FCECE 0x02000000UL /* freeze ctrs on enabled cond or event */
++#define MMCR0_TBEE 0x00400000UL /* time base exception enable */
++#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/
++#define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/
++#define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */
++#define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */
++#define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */
++#define MMCR0_FCTI 0x00000008UL /* freeze counters in tags inactive mode */
++#define MMCR0_FCTA 0x00000004UL /* freeze counters in tags active mode */
++#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
++#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
++#define SPRN_MMCR1 798
++#define SPRN_MMCRA 0x312
++#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */
++#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */
++#define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
++#define SPRN_PMC1 787
++#define SPRN_PMC2 788
++#define SPRN_PMC3 789
++#define SPRN_PMC4 790
++#define SPRN_PMC5 791
++#define SPRN_PMC6 792
++#define SPRN_PMC7 793
++#define SPRN_PMC8 794
++#define SPRN_SIAR 780
++#define SPRN_SDAR 781
++
++#else /* 32-bit */
++#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */
++#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */
++#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */
++#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */
++#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */
++#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */
++
++/* Bit definitions for MMCR0 and PMC1 / PMC2. */
++#define MMCR0_PMC1_CYCLES (1 << 7)
++#define MMCR0_PMC1_ICACHEMISS (5 << 7)
++#define MMCR0_PMC1_DTLB (6 << 7)
++#define MMCR0_PMC2_DCACHEMISS 0x6
++#define MMCR0_PMC2_CYCLES 0x1
++#define MMCR0_PMC2_ITLB 0x7
++#define MMCR0_PMC2_LOADMISSTIME 0x5
++#define MMCR0_PMXE (1 << 26)
++#endif
++
++/* Processor Version Register (PVR) field extraction */
++
++#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
++#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
++
++#define __is_processor(pv) (PVR_VER(mfspr(SPRN_PVR)) == (pv))
++
++/*
++ * IBM has further subdivided the standard PowerPC 16-bit version and
++ * revision subfields of the PVR for the PowerPC 403s into the following:
++ */
++
++#define PVR_FAM(pvr) (((pvr) >> 20) & 0xFFF) /* Family field */
++#define PVR_MEM(pvr) (((pvr) >> 16) & 0xF) /* Member field */
++#define PVR_CORE(pvr) (((pvr) >> 12) & 0xF) /* Core field */
++#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */
++#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
++#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
++
++/* Processor Version Numbers */
++
++#define PVR_403GA 0x00200000
++#define PVR_403GB 0x00200100
++#define PVR_403GC 0x00200200
++#define PVR_403GCX 0x00201400
++#define PVR_405GP 0x40110000
++#define PVR_STB03XXX 0x40310000
++#define PVR_NP405H 0x41410000
++#define PVR_NP405L 0x41610000
++#define PVR_601 0x00010000
++#define PVR_602 0x00050000
++#define PVR_603 0x00030000
++#define PVR_603e 0x00060000
++#define PVR_603ev 0x00070000
++#define PVR_603r 0x00071000
++#define PVR_604 0x00040000
++#define PVR_604e 0x00090000
++#define PVR_604r 0x000A0000
++#define PVR_620 0x00140000
++#define PVR_740 0x00080000
++#define PVR_750 PVR_740
++#define PVR_740P 0x10080000
++#define PVR_750P PVR_740P
++#define PVR_7400 0x000C0000
++#define PVR_7410 0x800C0000
++#define PVR_7450 0x80000000
++#define PVR_8540 0x80200000
++#define PVR_8560 0x80200000
++/*
++ * For the 8xx processors, all of them report the same PVR family for
++ * the PowerPC core. The various versions of these processors must be
++ * differentiated by the version number in the Communication Processor
++ * Module (CPM).
++ */
++#define PVR_821 0x00500000
++#define PVR_823 PVR_821
++#define PVR_850 PVR_821
++#define PVR_860 PVR_821
++#define PVR_8240 0x00810100
++#define PVR_8245 0x80811014
++#define PVR_8260 PVR_8240
++
++/* 64-bit processors */
++/* XXX the prefix should be PVR_, we'll do a global sweep to fix it one day */
++#define PV_NORTHSTAR 0x0033
++#define PV_PULSAR 0x0034
++#define PV_POWER4 0x0035
++#define PV_ICESTAR 0x0036
++#define PV_SSTAR 0x0037
++#define PV_POWER4p 0x0038
++#define PV_970 0x0039
++#define PV_POWER5 0x003A
++#define PV_POWER5p 0x003B
++#define PV_970FX 0x003C
++#define PV_630 0x0040
++#define PV_630p 0x0041
++#define PV_970MP 0x0044
++#define PV_BE 0x0070
++
++/*
++ * Number of entries in the SLB. If this ever changes we should handle
++ * it with a use a cpu feature fixup.
++ */
++#define SLB_NUM_ENTRIES 64
++
++/* Macros for setting and retrieving special purpose registers */
++#ifndef __ASSEMBLY__
++#define mfmsr() ({unsigned long rval; \
++ asm volatile("mfmsr %0" : "=r" (rval)); rval;})
++#ifdef CONFIG_PPC64
++#define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \
++ : : "r" (v))
++#define mtmsrd(v) __mtmsrd((v), 0)
++#define mtmsr(v) mtmsrd(v)
++#else
++#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
++#endif
++
++#define mfspr(rn) ({unsigned long rval; \
++ asm volatile("mfspr %0," __stringify(rn) \
++ : "=r" (rval)); rval;})
++#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
++
++#define mftb() ({unsigned long rval; \
++ asm volatile("mftb %0" : "=r" (rval)); rval;})
++#define mftbl() ({unsigned long rval; \
++ asm volatile("mftbl %0" : "=r" (rval)); rval;})
++
++#define mttbl(v) asm volatile("mttbl %0":: "r"(v))
++#define mttbu(v) asm volatile("mttbu %0":: "r"(v))
++
++#ifdef CONFIG_PPC32
++#define mfsrin(v) ({unsigned int rval; \
++ asm volatile("mfsrin %0,%1" : "=r" (rval) : "r" (v)); \
++ rval;})
++#endif
++
++#define proc_trap() asm volatile("trap")
++
++#ifdef CONFIG_PPC64
++static inline void ppc64_runlatch_on(void)
++{
++ unsigned long ctrl;
++
++ if (cpu_has_feature(CPU_FTR_CTRL)) {
++ ctrl = mfspr(SPRN_CTRLF);
++ ctrl |= CTRL_RUNLATCH;
++ mtspr(SPRN_CTRLT, ctrl);
++ }
++}
++
++static inline void ppc64_runlatch_off(void)
++{
++ unsigned long ctrl;
++
++ if (cpu_has_feature(CPU_FTR_CTRL)) {
++ ctrl = mfspr(SPRN_CTRLF);
++ ctrl &= ~CTRL_RUNLATCH;
++ mtspr(SPRN_CTRLT, ctrl);
++ }
++}
++#endif
++
++#define __get_SP() ({unsigned long sp; \
++ asm volatile("mr %0,1": "=r" (sp)); sp;})
++
++#else /* __ASSEMBLY__ */
++
++#define RUNLATCH_ON(REG) \
++BEGIN_FTR_SECTION \
++ mfspr (REG),SPRN_CTRLF; \
++ ori (REG),(REG),CTRL_RUNLATCH; \
++ mtspr SPRN_CTRLT,(REG); \
++END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
++
++#endif /* __ASSEMBLY__ */
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_REG_H */
+diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/rtas.h
+@@ -0,0 +1,249 @@
++#ifndef _POWERPC_RTAS_H
++#define _POWERPC_RTAS_H
++
++#include <linux/spinlock.h>
++#include <asm/page.h>
++
++/*
++ * Definitions for talking to the RTAS on CHRP machines.
++ *
++ * Copyright (C) 2001 Peter Bergner
++ * Copyright (C) 2001 PPC 64 Team, IBM Corp
++ *
++ * 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.
++ */
++
++#define RTAS_UNKNOWN_SERVICE (-1)
++#define RTAS_INSTANTIATE_MAX (1UL<<30) /* Don't instantiate rtas at/above this value */
++
++/* Buffer size for ppc_rtas system call. */
++#define RTAS_RMOBUF_MAX (64 * 1024)
++
++/* RTAS return status codes */
++#define RTAS_BUSY -2 /* RTAS Busy */
++#define RTAS_EXTENDED_DELAY_MIN 9900
++#define RTAS_EXTENDED_DELAY_MAX 9905
++
++/*
++ * In general to call RTAS use rtas_token("string") to lookup
++ * an RTAS token for the given string (e.g. "event-scan").
++ * To actually perform the call use
++ * ret = rtas_call(token, n_in, n_out, ...)
++ * Where n_in is the number of input parameters and
++ * n_out is the number of output parameters
++ *
++ * If the "string" is invalid on this system, RTAS_UNKNOWN_SERVICE
++ * will be returned as a token. rtas_call() does look for this
++ * token and error out gracefully so rtas_call(rtas_token("str"), ...)
++ * may be safely used for one-shot calls to RTAS.
++ *
++ */
++
++typedef u32 rtas_arg_t;
++
++struct rtas_args {
++ u32 token;
++ u32 nargs;
++ u32 nret;
++ rtas_arg_t args[16];
++ rtas_arg_t *rets; /* Pointer to return values in args[]. */
++};
++
++extern struct rtas_args rtas_stop_self_args;
++
++struct rtas_t {
++ unsigned long entry; /* physical address pointer */
++ unsigned long base; /* physical address pointer */
++ unsigned long size;
++ spinlock_t lock;
++ struct rtas_args args;
++ struct device_node *dev; /* virtual address pointer */
++};
++
++/* RTAS event classes */
++#define RTAS_INTERNAL_ERROR 0x80000000 /* set bit 0 */
++#define RTAS_EPOW_WARNING 0x40000000 /* set bit 1 */
++#define RTAS_POWERMGM_EVENTS 0x20000000 /* set bit 2 */
++#define RTAS_HOTPLUG_EVENTS 0x10000000 /* set bit 3 */
++#define RTAS_EVENT_SCAN_ALL_EVENTS 0xf0000000
++
++/* RTAS event severity */
++#define RTAS_SEVERITY_FATAL 0x5
++#define RTAS_SEVERITY_ERROR 0x4
++#define RTAS_SEVERITY_ERROR_SYNC 0x3
++#define RTAS_SEVERITY_WARNING 0x2
++#define RTAS_SEVERITY_EVENT 0x1
++#define RTAS_SEVERITY_NO_ERROR 0x0
++
++/* RTAS event disposition */
++#define RTAS_DISP_FULLY_RECOVERED 0x0
++#define RTAS_DISP_LIMITED_RECOVERY 0x1
++#define RTAS_DISP_NOT_RECOVERED 0x2
++
++/* RTAS event initiator */
++#define RTAS_INITIATOR_UNKNOWN 0x0
++#define RTAS_INITIATOR_CPU 0x1
++#define RTAS_INITIATOR_PCI 0x2
++#define RTAS_INITIATOR_ISA 0x3
++#define RTAS_INITIATOR_MEMORY 0x4
++#define RTAS_INITIATOR_POWERMGM 0x5
++
++/* RTAS event target */
++#define RTAS_TARGET_UNKNOWN 0x0
++#define RTAS_TARGET_CPU 0x1
++#define RTAS_TARGET_PCI 0x2
++#define RTAS_TARGET_ISA 0x3
++#define RTAS_TARGET_MEMORY 0x4
++#define RTAS_TARGET_POWERMGM 0x5
++
++/* RTAS event type */
++#define RTAS_TYPE_RETRY 0x01
++#define RTAS_TYPE_TCE_ERR 0x02
++#define RTAS_TYPE_INTERN_DEV_FAIL 0x03
++#define RTAS_TYPE_TIMEOUT 0x04
++#define RTAS_TYPE_DATA_PARITY 0x05
++#define RTAS_TYPE_ADDR_PARITY 0x06
++#define RTAS_TYPE_CACHE_PARITY 0x07
++#define RTAS_TYPE_ADDR_INVALID 0x08
++#define RTAS_TYPE_ECC_UNCORR 0x09
++#define RTAS_TYPE_ECC_CORR 0x0a
++#define RTAS_TYPE_EPOW 0x40
++#define RTAS_TYPE_PLATFORM 0xE0
++#define RTAS_TYPE_IO 0xE1
++#define RTAS_TYPE_INFO 0xE2
++#define RTAS_TYPE_DEALLOC 0xE3
++#define RTAS_TYPE_DUMP 0xE4
++/* I don't add PowerMGM events right now, this is a different topic */
++#define RTAS_TYPE_PMGM_POWER_SW_ON 0x60
++#define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61
++#define RTAS_TYPE_PMGM_LID_OPEN 0x62
++#define RTAS_TYPE_PMGM_LID_CLOSE 0x63
++#define RTAS_TYPE_PMGM_SLEEP_BTN 0x64
++#define RTAS_TYPE_PMGM_WAKE_BTN 0x65
++#define RTAS_TYPE_PMGM_BATTERY_WARN 0x66
++#define RTAS_TYPE_PMGM_BATTERY_CRIT 0x67
++#define RTAS_TYPE_PMGM_SWITCH_TO_BAT 0x68
++#define RTAS_TYPE_PMGM_SWITCH_TO_AC 0x69
++#define RTAS_TYPE_PMGM_KBD_OR_MOUSE 0x6a
++#define RTAS_TYPE_PMGM_ENCLOS_OPEN 0x6b
++#define RTAS_TYPE_PMGM_ENCLOS_CLOSED 0x6c
++#define RTAS_TYPE_PMGM_RING_INDICATE 0x6d
++#define RTAS_TYPE_PMGM_LAN_ATTENTION 0x6e
++#define RTAS_TYPE_PMGM_TIME_ALARM 0x6f
++#define RTAS_TYPE_PMGM_CONFIG_CHANGE 0x70
++#define RTAS_TYPE_PMGM_SERVICE_PROC 0x71
++
++struct rtas_error_log {
++ unsigned long version:8; /* Architectural version */
++ unsigned long severity:3; /* Severity level of error */
++ unsigned long disposition:2; /* Degree of recovery */
++ unsigned long extended:1; /* extended log present? */
++ unsigned long /* reserved */ :2; /* Reserved for future use */
++ unsigned long initiator:4; /* Initiator of event */
++ unsigned long target:4; /* Target of failed operation */
++ unsigned long type:8; /* General event or error*/
++ unsigned long extended_log_length:32; /* length in bytes */
++ unsigned char buffer[1];
++};
++
++struct flash_block {
++ char *data;
++ unsigned long length;
++};
++
++/* This struct is very similar but not identical to
++ * that needed by the rtas flash update.
++ * All we need to do for rtas is rewrite num_blocks
++ * into a version/length and translate the pointers
++ * to absolute.
++ */
++#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block))
++struct flash_block_list {
++ unsigned long num_blocks;
++ struct flash_block_list *next;
++ struct flash_block blocks[FLASH_BLOCKS_PER_NODE];
++};
++struct flash_block_list_header { /* just the header of flash_block_list */
++ unsigned long num_blocks;
++ struct flash_block_list *next;
++};
++extern struct flash_block_list_header rtas_firmware_flash_list;
++
++extern struct rtas_t rtas;
++
++extern void enter_rtas(unsigned long);
++extern int rtas_token(const char *service);
++extern int rtas_call(int token, int, int, int *, ...);
++extern void call_rtas_display_status(unsigned char);
++extern void rtas_restart(char *cmd);
++extern void rtas_power_off(void);
++extern void rtas_halt(void);
++extern void rtas_os_term(char *str);
++extern int rtas_get_sensor(int sensor, int index, int *state);
++extern int rtas_get_power_level(int powerdomain, int *level);
++extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
++extern int rtas_set_indicator(int indicator, int index, int new_value);
++extern void rtas_progress(char *s, unsigned short hex);
++extern void rtas_initialize(void);
++
++struct rtc_time;
++extern unsigned long rtas_get_boot_time(void);
++extern void rtas_get_rtc_time(struct rtc_time *rtc_time);
++extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
++
++/* Given an RTAS status code of 9900..9905 compute the hinted delay */
++unsigned int rtas_extended_busy_delay_time(int status);
++static inline int rtas_is_extended_busy(int status)
++{
++ return status >= 9900 && status <= 9909;
++}
++
++extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
++
++/* Error types logged. */
++#define ERR_FLAG_ALREADY_LOGGED 0x0
++#define ERR_FLAG_BOOT 0x1 /* log was pulled from NVRAM on boot */
++#define ERR_TYPE_RTAS_LOG 0x2 /* from rtas event-scan */
++#define ERR_TYPE_KERNEL_PANIC 0x4 /* from panic() */
++
++/* All the types and not flags */
++#define ERR_TYPE_MASK (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
++
++#define RTAS_DEBUG KERN_DEBUG "RTAS: "
++
++#define RTAS_ERROR_LOG_MAX 2048
++
++/*
++ * Return the firmware-specified size of the error log buffer
++ * for all rtas calls that require an error buffer argument.
++ * This includes 'check-exception' and 'rtas-last-error'.
++ */
++extern int rtas_get_error_log_max(void);
++
++/* Event Scan Parameters */
++#define EVENT_SCAN_ALL_EVENTS 0xf0000000
++#define SURVEILLANCE_TOKEN 9000
++#define LOG_NUMBER 64 /* must be a power of two */
++#define LOG_NUMBER_MASK (LOG_NUMBER-1)
++
++/* Some RTAS ops require a data buffer and that buffer must be < 4G.
++ * Rather than having a memory allocator, just use this buffer
++ * (get the lock first), make the RTAS call. Copy the data instead
++ * of holding the buffer for long.
++ */
++
++#define RTAS_DATA_BUF_SIZE 4096
++extern spinlock_t rtas_data_buf_lock;
++extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
++
++extern void rtas_stop_self(void);
++
++/* RMO buffer reserved for user-space RTAS use */
++extern unsigned long rtas_rmo_buf;
++
++#define GLOBAL_INTERRUPT_QUEUE 9005
++
++#endif /* _POWERPC_RTAS_H */
+diff --git a/include/asm-powerpc/rtc.h b/include/asm-powerpc/rtc.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/rtc.h
+@@ -0,0 +1,78 @@
++/*
++ * Real-time clock definitions and interfaces
++ *
++ * Author: Tom Rini <trini at mvista.com>
++ *
++ * 2002 (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.
++ *
++ * Based on:
++ * include/asm-m68k/rtc.h
++ *
++ * Copyright Richard Zidlicky
++ * implementation details for genrtc/q40rtc driver
++ *
++ * And the old drivers/macintosh/rtc.c which was heavily based on:
++ * Linux/SPARC Real Time Clock Driver
++ * Copyright (C) 1996 Thomas K. Dyas (tdyas at eden.rutgers.edu)
++ *
++ * With additional work by Paul Mackerras and Franz Sirl.
++ */
++
++#ifndef __ASM_POWERPC_RTC_H__
++#define __ASM_POWERPC_RTC_H__
++
++#ifdef __KERNEL__
++
++#include <linux/rtc.h>
++
++#include <asm/machdep.h>
++#include <asm/time.h>
++
++#define RTC_PIE 0x40 /* periodic interrupt enable */
++#define RTC_AIE 0x20 /* alarm interrupt enable */
++#define RTC_UIE 0x10 /* update-finished interrupt enable */
++
++/* some dummy definitions */
++#define RTC_BATT_BAD 0x100 /* battery bad */
++#define RTC_SQWE 0x08 /* enable square-wave output */
++#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
++#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 */
++
++static inline unsigned int get_rtc_time(struct rtc_time *time)
++{
++ if (ppc_md.get_rtc_time)
++ ppc_md.get_rtc_time(time);
++ return RTC_24H;
++}
++
++/* Set the current date and time in the real time clock. */
++static inline int set_rtc_time(struct rtc_time *time)
++{
++ if (ppc_md.set_rtc_time)
++ return ppc_md.set_rtc_time(time);
++ return -EINVAL;
++}
++
++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 /* __KERNEL__ */
++#endif /* __ASM_POWERPC_RTC_H__ */
+diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/rwsem.h
+@@ -0,0 +1,168 @@
++#ifndef _ASM_POWERPC_RWSEM_H
++#define _ASM_POWERPC_RWSEM_H
++
++#ifdef __KERNEL__
++
++/*
++ * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff
++ * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h
++ * by Paul Mackerras <paulus at samba.org>.
++ */
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++
++/*
++ * the semaphore definition
++ */
++struct rw_semaphore {
++ /* XXX this should be able to be an atomic_t -- paulus */
++ signed int count;
++#define RWSEM_UNLOCKED_VALUE 0x00000000
++#define RWSEM_ACTIVE_BIAS 0x00000001
++#define RWSEM_ACTIVE_MASK 0x0000ffff
++#define RWSEM_WAITING_BIAS (-0x00010000)
++#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
++#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
++ spinlock_t wait_lock;
++ struct list_head wait_list;
++#if RWSEM_DEBUG
++ int debug;
++#endif
++};
++
++/*
++ * initialisation
++ */
++#if RWSEM_DEBUG
++#define __RWSEM_DEBUG_INIT , 0
++#else
++#define __RWSEM_DEBUG_INIT /* */
++#endif
++
++#define __RWSEM_INITIALIZER(name) \
++ { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
++ LIST_HEAD_INIT((name).wait_list) \
++ __RWSEM_DEBUG_INIT }
++
++#define DECLARE_RWSEM(name) \
++ struct rw_semaphore name = __RWSEM_INITIALIZER(name)
++
++extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
++extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
++extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
++extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
++
++static inline void init_rwsem(struct rw_semaphore *sem)
++{
++ sem->count = RWSEM_UNLOCKED_VALUE;
++ spin_lock_init(&sem->wait_lock);
++ INIT_LIST_HEAD(&sem->wait_list);
++#if RWSEM_DEBUG
++ sem->debug = 0;
++#endif
++}
++
++/*
++ * lock for reading
++ */
++static inline void __down_read(struct rw_semaphore *sem)
++{
++ if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0))
++ rwsem_down_read_failed(sem);
++}
++
++static inline int __down_read_trylock(struct rw_semaphore *sem)
++{
++ int tmp;
++
++ while ((tmp = sem->count) >= 0) {
++ if (tmp == cmpxchg(&sem->count, tmp,
++ tmp + RWSEM_ACTIVE_READ_BIAS)) {
++ return 1;
++ }
++ }
++ return 0;
++}
++
++/*
++ * lock for writing
++ */
++static inline void __down_write(struct rw_semaphore *sem)
++{
++ int tmp;
++
++ tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
++ (atomic_t *)(&sem->count));
++ if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
++ rwsem_down_write_failed(sem);
++}
++
++static inline int __down_write_trylock(struct rw_semaphore *sem)
++{
++ int tmp;
++
++ tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
++ RWSEM_ACTIVE_WRITE_BIAS);
++ return tmp == RWSEM_UNLOCKED_VALUE;
++}
++
++/*
++ * unlock after reading
++ */
++static inline void __up_read(struct rw_semaphore *sem)
++{
++ int tmp;
++
++ tmp = atomic_dec_return((atomic_t *)(&sem->count));
++ if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
++ rwsem_wake(sem);
++}
++
++/*
++ * unlock after writing
++ */
++static inline void __up_write(struct rw_semaphore *sem)
++{
++ if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
++ (atomic_t *)(&sem->count)) < 0))
++ rwsem_wake(sem);
++}
++
++/*
++ * implement atomic add functionality
++ */
++static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
++{
++ atomic_add(delta, (atomic_t *)(&sem->count));
++}
++
++/*
++ * downgrade write lock to read lock
++ */
++static inline void __downgrade_write(struct rw_semaphore *sem)
++{
++ int tmp;
++
++ tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
++ if (tmp < 0)
++ rwsem_downgrade_wake(sem);
++}
++
++/*
++ * implement exchange and add functionality
++ */
++static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
++{
++ 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/scatterlist.h b/include/asm-powerpc/scatterlist.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/scatterlist.h
+@@ -0,0 +1,45 @@
++#ifndef _ASM_POWERPC_SCATTERLIST_H
++#define _ASM_POWERPC_SCATTERLIST_H
++/*
++ * Copyright (C) 2001 PPC64 Team, IBM Corp
++ *
++ * 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.
++ */
++
++#ifdef __KERNEL__
++#include <linux/types.h>
++#include <asm/dma.h>
++
++struct scatterlist {
++ struct page *page;
++ unsigned int offset;
++ unsigned int length;
++
++ /* For TCE support */
++ dma_addr_t dma_address;
++ u32 dma_length;
++};
++
++/*
++ * These macros should be used after a dma_map_sg call has been done
++ * to get bus addresses of each of the SG entries and their lengths.
++ * You should only work with the number of sg entries pci_map_sg
++ * returns, or alternatively stop on the first sg_dma_len(sg) which
++ * is 0.
++ */
++#define sg_dma_address(sg) ((sg)->dma_address)
++#ifdef __powerpc64__
++#define sg_dma_len(sg) ((sg)->dma_length)
++#else
++#define sg_dma_len(sg) ((sg)->length)
++#endif
++
++#ifdef __powerpc64__
++#define ISA_DMA_THRESHOLD (~0UL)
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_SCATTERLIST_H */
+diff --git a/include/asm-powerpc/seccomp.h b/include/asm-powerpc/seccomp.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/seccomp.h
+@@ -0,0 +1,16 @@
++#ifndef _ASM_POWERPC_SECCOMP_H
++
++#include <linux/thread_info.h>
++#include <linux/unistd.h>
++
++#define __NR_seccomp_read __NR_read
++#define __NR_seccomp_write __NR_write
++#define __NR_seccomp_exit __NR_exit
++#define __NR_seccomp_sigreturn __NR_rt_sigreturn
++
++#define __NR_seccomp_read_32 __NR_read
++#define __NR_seccomp_write_32 __NR_write
++#define __NR_seccomp_exit_32 __NR_exit
++#define __NR_seccomp_sigreturn_32 __NR_sigreturn
++
++#endif /* _ASM_POWERPC_SECCOMP_H */
+diff --git a/include/asm-powerpc/sections.h b/include/asm-powerpc/sections.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/sections.h
+@@ -0,0 +1,20 @@
++#ifndef _ASM_POWERPC_SECTIONS_H
++#define _ASM_POWERPC_SECTIONS_H
++
++#include <asm-generic/sections.h>
++
++#ifdef __powerpc64__
++
++extern char _end[];
++
++static inline int in_kernel_text(unsigned long addr)
++{
++ if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end)
++ return 1;
++
++ return 0;
++}
++
++#endif
++
++#endif /* _ASM_POWERPC_SECTIONS_H */
+diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/semaphore.h
+@@ -0,0 +1,95 @@
++#ifndef _ASM_POWERPC_SEMAPHORE_H
++#define _ASM_POWERPC_SEMAPHORE_H
++
++/*
++ * Remove spinlock-based RW semaphores; RW semaphore definitions are
++ * now in rwsem.h and we use the generic lib/rwsem.c implementation.
++ * Rework semaphores to use atomic_dec_if_positive.
++ * -- Paul Mackerras (paulus at samba.org)
++ */
++
++#ifdef __KERNEL__
++
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <linux/wait.h>
++#include <linux/rwsem.h>
++
++struct semaphore {
++ /*
++ * Note that any negative value of count is equivalent to 0,
++ * but additionally indicates that some process(es) might be
++ * sleeping on `wait'.
++ */
++ atomic_t count;
++ wait_queue_head_t wait;
++};
++
++#define __SEMAPHORE_INITIALIZER(name, n) \
++{ \
++ .count = ATOMIC_INIT(n), \
++ .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
++}
++
++#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
++ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
++
++#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
++#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
++
++static inline void sema_init (struct semaphore *sem, int val)
++{
++ atomic_set(&sem->count, val);
++ init_waitqueue_head(&sem->wait);
++}
++
++static inline void init_MUTEX (struct semaphore *sem)
++{
++ sema_init(sem, 1);
++}
++
++static inline void init_MUTEX_LOCKED (struct semaphore *sem)
++{
++ sema_init(sem, 0);
++}
++
++extern void __down(struct semaphore * sem);
++extern int __down_interruptible(struct semaphore * sem);
++extern void __up(struct semaphore * sem);
++
++static inline void down(struct semaphore * sem)
++{
++ might_sleep();
++
++ /*
++ * Try to get the semaphore, take the slow path if we fail.
++ */
++ if (unlikely(atomic_dec_return(&sem->count) < 0))
++ __down(sem);
++}
++
++static inline int down_interruptible(struct semaphore * sem)
++{
++ int ret = 0;
++
++ might_sleep();
++
++ if (unlikely(atomic_dec_return(&sem->count) < 0))
++ ret = __down_interruptible(sem);
++ return ret;
++}
++
++static inline int down_trylock(struct semaphore * sem)
++{
++ return atomic_dec_if_positive(&sem->count) < 0;
++}
++
++static inline void up(struct semaphore * sem)
++{
++ if (unlikely(atomic_inc_return(&sem->count) <= 0))
++ __up(sem);
++}
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_POWERPC_SEMAPHORE_H */
+diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/smu.h
+@@ -0,0 +1,379 @@
++#ifndef _SMU_H
++#define _SMU_H
++
++/*
++ * Definitions for talking to the SMU chip in newer G5 PowerMacs
++ */
++
++#include <linux/config.h>
++#include <linux/list.h>
++
++/*
++ * Known SMU commands
++ *
++ * Most of what is below comes from looking at the Open Firmware driver,
++ * though this is still incomplete and could use better documentation here
++ * or there...
++ */
++
++
++/*
++ * Partition info commands
++ *
++ * I do not know what those are for at this point
++ */
++#define SMU_CMD_PARTITION_COMMAND 0x3e
++
++
++/*
++ * Fan control
++ *
++ * This is a "mux" for fan control commands, first byte is the
++ * "sub" command.
++ */
++#define SMU_CMD_FAN_COMMAND 0x4a
++
++
++/*
++ * Battery access
++ *
++ * Same command number as the PMU, could it be same syntax ?
++ */
++#define SMU_CMD_BATTERY_COMMAND 0x6f
++#define SMU_CMD_GET_BATTERY_INFO 0x00
++
++/*
++ * Real time clock control
++ *
++ * This is a "mux", first data byte contains the "sub" command.
++ * The "RTC" part of the SMU controls the date, time, powerup
++ * timer, but also a PRAM
++ *
++ * Dates are in BCD format on 7 bytes:
++ * [sec] [min] [hour] [weekday] [month day] [month] [year]
++ * with month being 1 based and year minus 100
++ */
++#define SMU_CMD_RTC_COMMAND 0x8e
++#define SMU_CMD_RTC_SET_PWRUP_TIMER 0x00 /* i: 7 bytes date */
++#define SMU_CMD_RTC_GET_PWRUP_TIMER 0x01 /* o: 7 bytes date */
++#define SMU_CMD_RTC_STOP_PWRUP_TIMER 0x02
++#define SMU_CMD_RTC_SET_PRAM_BYTE_ACC 0x20 /* i: 1 byte (address?) */
++#define SMU_CMD_RTC_SET_PRAM_AUTOINC 0x21 /* i: 1 byte (data?) */
++#define SMU_CMD_RTC_SET_PRAM_LO_BYTES 0x22 /* i: 10 bytes */
++#define SMU_CMD_RTC_SET_PRAM_HI_BYTES 0x23 /* i: 10 bytes */
++#define SMU_CMD_RTC_GET_PRAM_BYTE 0x28 /* i: 1 bytes (address?) */
++#define SMU_CMD_RTC_GET_PRAM_LO_BYTES 0x29 /* o: 10 bytes */
++#define SMU_CMD_RTC_GET_PRAM_HI_BYTES 0x2a /* o: 10 bytes */
++#define SMU_CMD_RTC_SET_DATETIME 0x80 /* i: 7 bytes date */
++#define SMU_CMD_RTC_GET_DATETIME 0x81 /* o: 7 bytes date */
++
++ /*
++ * i2c commands
++ *
++ * To issue an i2c command, first is to send a parameter block to the
++ * the SMU. This is a command of type 0x9a with 9 bytes of header
++ * eventually followed by data for a write:
++ *
++ * 0: bus number (from device-tree usually, SMU has lots of busses !)
++ * 1: transfer type/format (see below)
++ * 2: device address. For combined and combined4 type transfers, this
++ * is the "write" version of the address (bit 0x01 cleared)
++ * 3: subaddress length (0..3)
++ * 4: subaddress byte 0 (or only byte for subaddress length 1)
++ * 5: subaddress byte 1
++ * 6: subaddress byte 2
++ * 7: combined address (device address for combined mode data phase)
++ * 8: data length
++ *
++ * The transfer types are the same good old Apple ones it seems,
++ * that is:
++ * - 0x00: Simple transfer
++ * - 0x01: Subaddress transfer (addr write + data tx, no restart)
++ * - 0x02: Combined transfer (addr write + restart + data tx)
++ *
++ * This is then followed by actual data for a write.
++ *
++ * At this point, the OF driver seems to have a limitation on transfer
++ * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know
++ * wether this is just an OF limit due to some temporary buffer size
++ * or if this is an SMU imposed limit. This driver has the same limitation
++ * for now as I use a 0x10 bytes temporary buffer as well
++ *
++ * Once that is completed, a response is expected from the SMU. This is
++ * obtained via a command of type 0x9a with a length of 1 byte containing
++ * 0 as the data byte. OF also fills the rest of the data buffer with 0xff's
++ * though I can't tell yet if this is actually necessary. Once this command
++ * is complete, at this point, all I can tell is what OF does. OF tests
++ * byte 0 of the reply:
++ * - on read, 0xfe or 0xfc : bus is busy, wait (see below) or nak ?
++ * - on read, 0x00 or 0x01 : reply is in buffer (after the byte 0)
++ * - on write, < 0 -> failure (immediate exit)
++ * - else, OF just exists (without error, weird)
++ *
++ * So on read, there is this wait-for-busy thing when getting a 0xfc or
++ * 0xfe result. OF does a loop of up to 64 retries, waiting 20ms and
++ * doing the above again until either the retries expire or the result
++ * is no longer 0xfe or 0xfc
++ *
++ * The Darwin I2C driver is less subtle though. On any non-success status
++ * from the response command, it waits 5ms and tries again up to 20 times,
++ * it doesn't differenciate between fatal errors or "busy" status.
++ *
++ * This driver provides an asynchronous paramblock based i2c command
++ * interface to be used either directly by low level code or by a higher
++ * level driver interfacing to the linux i2c layer. The current
++ * implementation of this relies on working timers & timer interrupts
++ * though, so be careful of calling context for now. This may be "fixed"
++ * in the future by adding a polling facility.
++ */
++#define SMU_CMD_I2C_COMMAND 0x9a
++ /* transfer types */
++#define SMU_I2C_TRANSFER_SIMPLE 0x00
++#define SMU_I2C_TRANSFER_STDSUB 0x01
++#define SMU_I2C_TRANSFER_COMBINED 0x02
++
++/*
++ * Power supply control
++ *
++ * The "sub" command is an ASCII string in the data, the
++ * data lenght is that of the string.
++ *
++ * The VSLEW command can be used to get or set the voltage slewing.
++ * - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
++ * reply at data offset 6, 7 and 8.
++ * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is
++ * used to set the voltage slewing point. The SMU replies with "DONE"
++ * I yet have to figure out their exact meaning of those 3 bytes in
++ * both cases.
++ *
++ */
++#define SMU_CMD_POWER_COMMAND 0xaa
++#define SMU_CMD_POWER_RESTART "RESTART"
++#define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN"
++#define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW"
++
++/* Misc commands
++ *
++ * This command seem to be a grab bag of various things
++ */
++#define SMU_CMD_MISC_df_COMMAND 0xdf
++#define SMU_CMD_MISC_df_SET_DISPLAY_LIT 0x02 /* i: 1 byte */
++#define SMU_CMD_MISC_df_NMI_OPTION 0x04
++
++/*
++ * Version info commands
++ *
++ * I haven't quite tried to figure out how these work
++ */
++#define SMU_CMD_VERSION_COMMAND 0xea
++
++
++/*
++ * Misc commands
++ *
++ * This command seem to be a grab bag of various things
++ */
++#define SMU_CMD_MISC_ee_COMMAND 0xee
++#define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02
++#define SMU_CMD_MISC_ee_LEDS_CTRL 0x04 /* i: 00 (00,01) [00] */
++#define SMU_CMD_MISC_ee_GET_DATA 0x05 /* i: 00 , o: ?? */
++
++
++
++/*
++ * - Kernel side interface -
++ */
++
++#ifdef __KERNEL__
++
++/*
++ * Asynchronous SMU commands
++ *
++ * Fill up this structure and submit it via smu_queue_command(),
++ * and get notified by the optional done() callback, or because
++ * status becomes != 1
++ */
++
++struct smu_cmd;
++
++struct smu_cmd
++{
++ /* public */
++ u8 cmd; /* command */
++ int data_len; /* data len */
++ int reply_len; /* reply len */
++ void *data_buf; /* data buffer */
++ void *reply_buf; /* reply buffer */
++ int status; /* command status */
++ void (*done)(struct smu_cmd *cmd, void *misc);
++ void *misc;
++
++ /* private */
++ struct list_head link;
++};
++
++/*
++ * Queues an SMU command, all fields have to be initialized
++ */
++extern int smu_queue_cmd(struct smu_cmd *cmd);
++
++/*
++ * Simple command wrapper. This structure embeds a small buffer
++ * to ease sending simple SMU commands from the stack
++ */
++struct smu_simple_cmd
++{
++ struct smu_cmd cmd;
++ u8 buffer[16];
++};
++
++/*
++ * Queues a simple command. All fields will be initialized by that
++ * function
++ */
++extern int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
++ unsigned int data_len,
++ void (*done)(struct smu_cmd *cmd, void *misc),
++ void *misc,
++ ...);
++
++/*
++ * Completion helper. Pass it to smu_queue_simple or as 'done'
++ * member to smu_queue_cmd, it will call complete() on the struct
++ * completion passed in the "misc" argument
++ */
++extern void smu_done_complete(struct smu_cmd *cmd, void *misc);
++
++/*
++ * Synchronous helpers. Will spin-wait for completion of a command
++ */
++extern void smu_spinwait_cmd(struct smu_cmd *cmd);
++
++static inline void smu_spinwait_simple(struct smu_simple_cmd *scmd)
++{
++ smu_spinwait_cmd(&scmd->cmd);
++}
++
++/*
++ * Poll routine to call if blocked with irqs off
++ */
++extern void smu_poll(void);
++
++
++/*
++ * Init routine, presence check....
++ */
++extern int smu_init(void);
++extern int smu_present(void);
++struct of_device;
++extern struct of_device *smu_get_ofdev(void);
++
++
++/*
++ * Common command wrappers
++ */
++extern void smu_shutdown(void);
++extern void smu_restart(void);
++struct rtc_time;
++extern int smu_get_rtc_time(struct rtc_time *time, int spinwait);
++extern int smu_set_rtc_time(struct rtc_time *time, int spinwait);
++
++/*
++ * SMU command buffer absolute address, exported by pmac_setup,
++ * this is allocated very early during boot.
++ */
++extern unsigned long smu_cmdbuf_abs;
++
++
++/*
++ * Kenrel asynchronous i2c interface
++ */
++
++/* SMU i2c header, exactly matches i2c header on wire */
++struct smu_i2c_param
++{
++ u8 bus; /* SMU bus ID (from device tree) */
++ u8 type; /* i2c transfer type */
++ u8 devaddr; /* device address (includes direction) */
++ u8 sublen; /* subaddress length */
++ u8 subaddr[3]; /* subaddress */
++ u8 caddr; /* combined address, filled by SMU driver */
++ u8 datalen; /* length of transfer */
++ u8 data[7]; /* data */
++};
++
++#define SMU_I2C_READ_MAX 0x0d
++#define SMU_I2C_WRITE_MAX 0x05
++
++struct smu_i2c_cmd
++{
++ /* public */
++ struct smu_i2c_param info;
++ void (*done)(struct smu_i2c_cmd *cmd, void *misc);
++ void *misc;
++ int status; /* 1 = pending, 0 = ok, <0 = fail */
++
++ /* private */
++ struct smu_cmd scmd;
++ int read;
++ int stage;
++ int retries;
++ u8 pdata[0x10];
++ struct list_head link;
++};
++
++/*
++ * Call this to queue an i2c command to the SMU. You must fill info,
++ * including info.data for a write, done and misc.
++ * For now, no polling interface is provided so you have to use completion
++ * callback.
++ */
++extern int smu_queue_i2c(struct smu_i2c_cmd *cmd);
++
++
++#endif /* __KERNEL__ */
++
++/*
++ * - Userland interface -
++ */
++
++/*
++ * A given instance of the device can be configured for 2 different
++ * things at the moment:
++ *
++ * - sending SMU commands (default at open() time)
++ * - receiving SMU events (not yet implemented)
++ *
++ * Commands are written with write() of a command block. They can be
++ * "driver" commands (for example to switch to event reception mode)
++ * or real SMU commands. They are made of a header followed by command
++ * data if any.
++ *
++ * For SMU commands (not for driver commands), you can then read() back
++ * a reply. The reader will be blocked or not depending on how the device
++ * file is opened. poll() isn't implemented yet. The reply will consist
++ * of a header as well, followed by the reply data if any. You should
++ * always provide a buffer large enough for the maximum reply data, I
++ * recommand one page.
++ *
++ * It is illegal to send SMU commands through a file descriptor configured
++ * for events reception
++ *
++ */
++struct smu_user_cmd_hdr
++{
++ __u32 cmdtype;
++#define SMU_CMDTYPE_SMU 0 /* SMU command */
++#define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */
++
++ __u8 cmd; /* SMU command byte */
++ __u32 data_len; /* Lenght of data following */
++};
++
++struct smu_user_reply_hdr
++{
++ __u32 status; /* Command status */
++ __u32 reply_len; /* Lenght of data follwing */
++};
++
++#endif /* _SMU_H */
+diff --git a/include/asm-powerpc/spinlock_types.h b/include/asm-powerpc/spinlock_types.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/spinlock_types.h
+@@ -0,0 +1,20 @@
++#ifndef _ASM_POWERPC_SPINLOCK_TYPES_H
++#define _ASM_POWERPC_SPINLOCK_TYPES_H
++
++#ifndef __LINUX_SPINLOCK_TYPES_H
++# error "please don't include this file directly"
++#endif
++
++typedef struct {
++ volatile unsigned int slock;
++} raw_spinlock_t;
++
++#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
++
++typedef struct {
++ volatile signed int lock;
++} raw_rwlock_t;
++
++#define __RAW_RW_LOCK_UNLOCKED { 0 }
++
++#endif
+diff --git a/include/asm-powerpc/sstep.h b/include/asm-powerpc/sstep.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/sstep.h
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (C) 2004 Paul Mackerras <paulus at au.ibm.com>, IBM
++ *
++ * 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.
++ */
++
++struct pt_regs;
++
++/*
++ * We don't allow single-stepping an mtmsrd that would clear
++ * MSR_RI, since that would make the exception unrecoverable.
++ * Since we need to single-step to proceed from a breakpoint,
++ * we don't allow putting a breakpoint on an mtmsrd instruction.
++ * Similarly we don't allow breakpoints on rfid instructions.
++ * These macros tell us if an instruction is a mtmsrd or rfid.
++ * Note that IS_MTMSRD returns true for both an mtmsr (32-bit)
++ * and an mtmsrd (64-bit).
++ */
++#define IS_MTMSRD(instr) (((instr) & 0xfc0007be) == 0x7c000124)
++#define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024)
++
++/* Emulate instructions that cause a transfer of control. */
++extern int emulate_step(struct pt_regs *regs, unsigned int instr);
+diff --git a/include/asm-powerpc/statfs.h b/include/asm-powerpc/statfs.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/statfs.h
+@@ -0,0 +1,60 @@
++#ifndef _ASM_POWERPC_STATFS_H
++#define _ASM_POWERPC_STATFS_H
++
++/* For ppc32 we just use the generic definitions, not so simple on ppc64 */
++
++#ifndef __powerpc64__
++#include <asm-generic/statfs.h>
++#else
++
++#ifndef __KERNEL_STRICT_NAMES
++#include <linux/types.h>
++typedef __kernel_fsid_t fsid_t;
++#endif
++
++/*
++ * We're already 64-bit, so duplicate the definition
++ */
++struct statfs {
++ long f_type;
++ long f_bsize;
++ long f_blocks;
++ long f_bfree;
++ long f_bavail;
++ long f_files;
++ long f_ffree;
++ __kernel_fsid_t f_fsid;
++ long f_namelen;
++ long f_frsize;
++ long f_spare[5];
++};
++
++struct statfs64 {
++ long f_type;
++ long f_bsize;
++ long f_blocks;
++ long f_bfree;
++ long f_bavail;
++ long f_files;
++ long f_ffree;
++ __kernel_fsid_t f_fsid;
++ long f_namelen;
++ long f_frsize;
++ long f_spare[5];
++};
++
++struct compat_statfs64 {
++ __u32 f_type;
++ __u32 f_bsize;
++ __u64 f_blocks;
++ __u64 f_bfree;
++ __u64 f_bavail;
++ __u64 f_files;
++ __u64 f_ffree;
++ __kernel_fsid_t f_fsid;
++ __u32 f_namelen;
++ __u32 f_frsize;
++ __u32 f_spare[5];
++};
++#endif /* ! __powerpc64__ */
++#endif
+diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/synch.h
+@@ -0,0 +1,51 @@
++#ifndef _ASM_POWERPC_SYNCH_H
++#define _ASM_POWERPC_SYNCH_H
++
++#include <linux/config.h>
++
++#ifdef __powerpc64__
++#define __SUBARCH_HAS_LWSYNC
++#endif
++
++#ifdef __SUBARCH_HAS_LWSYNC
++# define LWSYNC lwsync
++#else
++# define LWSYNC sync
++#endif
++
++
++/*
++ * Arguably the bitops and *xchg operations don't imply any memory barrier
++ * or SMP ordering, but in fact a lot of drivers expect them to imply
++ * both, since they do on x86 cpus.
++ */
++#ifdef CONFIG_SMP
++#define EIEIO_ON_SMP "eieio\n"
++#define ISYNC_ON_SMP "\n\tisync"
++#define SYNC_ON_SMP __stringify(LWSYNC) "\n"
++#else
++#define EIEIO_ON_SMP
++#define ISYNC_ON_SMP
++#define SYNC_ON_SMP
++#endif
++
++static inline void eieio(void)
++{
++ __asm__ __volatile__ ("eieio" : : : "memory");
++}
++
++static inline void isync(void)
++{
++ __asm__ __volatile__ ("isync" : : : "memory");
++}
++
++#ifdef CONFIG_SMP
++#define eieio_on_smp() eieio()
++#define isync_on_smp() isync()
++#else
++#define eieio_on_smp() __asm__ __volatile__("": : :"memory")
++#define isync_on_smp() __asm__ __volatile__("": : :"memory")
++#endif
++
++#endif /* _ASM_POWERPC_SYNCH_H */
++
+diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/system.h
+@@ -0,0 +1,363 @@
++/*
++ * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
++ */
++#ifndef _ASM_POWERPC_SYSTEM_H
++#define _ASM_POWERPC_SYSTEM_H
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++
++#include <asm/hw_irq.h>
++#include <asm/ppc_asm.h>
++#include <asm/atomic.h>
++
++/*
++ * Memory barrier.
++ * The sync instruction guarantees that all memory accesses initiated
++ * by this processor have been performed (with respect to all other
++ * mechanisms that access memory). The eieio instruction is a barrier
++ * providing an ordering (separately) for (a) cacheable stores and (b)
++ * loads and stores to non-cacheable memory (e.g. I/O devices).
++ *
++ * mb() prevents loads and stores being reordered across this point.
++ * rmb() prevents loads being reordered across this point.
++ * wmb() prevents stores being reordered across this point.
++ * read_barrier_depends() prevents data-dependent loads being reordered
++ * across this point (nop on PPC).
++ *
++ * We have to use the sync instructions for mb(), since lwsync doesn't
++ * order loads with respect to previous stores. Lwsync is fine for
++ * rmb(), though. Note that lwsync is interpreted as sync by
++ * 32-bit and older 64-bit CPUs.
++ *
++ * For wmb(), we use sync since wmb is used in drivers to order
++ * stores to system memory with respect to writes to the device.
++ * However, smp_wmb() can be a lighter-weight eieio barrier on
++ * SMP since it is only used to order updates to system memory.
++ */
++#define mb() __asm__ __volatile__ ("sync" : : : "memory")
++#define rmb() __asm__ __volatile__ ("lwsync" : : : "memory")
++#define wmb() __asm__ __volatile__ ("sync" : : : "memory")
++#define read_barrier_depends() do { } while(0)
++
++#define set_mb(var, value) do { var = value; mb(); } while (0)
++#define set_wmb(var, value) do { var = value; wmb(); } while (0)
++
++#ifdef CONFIG_SMP
++#define smp_mb() mb()
++#define smp_rmb() rmb()
++#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory")
++#define smp_read_barrier_depends() read_barrier_depends()
++#else
++#define smp_mb() barrier()
++#define smp_rmb() barrier()
++#define smp_wmb() barrier()
++#define smp_read_barrier_depends() do { } while(0)
++#endif /* CONFIG_SMP */
++
++#ifdef __KERNEL__
++struct task_struct;
++struct pt_regs;
++
++#ifdef CONFIG_DEBUGGER
++
++extern int (*__debugger)(struct pt_regs *regs);
++extern int (*__debugger_ipi)(struct pt_regs *regs);
++extern int (*__debugger_bpt)(struct pt_regs *regs);
++extern int (*__debugger_sstep)(struct pt_regs *regs);
++extern int (*__debugger_iabr_match)(struct pt_regs *regs);
++extern int (*__debugger_dabr_match)(struct pt_regs *regs);
++extern int (*__debugger_fault_handler)(struct pt_regs *regs);
++
++#define DEBUGGER_BOILERPLATE(__NAME) \
++static inline int __NAME(struct pt_regs *regs) \
++{ \
++ if (unlikely(__ ## __NAME)) \
++ return __ ## __NAME(regs); \
++ return 0; \
++}
++
++DEBUGGER_BOILERPLATE(debugger)
++DEBUGGER_BOILERPLATE(debugger_ipi)
++DEBUGGER_BOILERPLATE(debugger_bpt)
++DEBUGGER_BOILERPLATE(debugger_sstep)
++DEBUGGER_BOILERPLATE(debugger_iabr_match)
++DEBUGGER_BOILERPLATE(debugger_dabr_match)
++DEBUGGER_BOILERPLATE(debugger_fault_handler)
++
++#ifdef CONFIG_XMON
++extern void xmon_init(int enable);
++#endif
++
++#else
++static inline int debugger(struct pt_regs *regs) { return 0; }
++static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
++static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
++static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
++static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
++static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
++static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
++#endif
++
++extern int set_dabr(unsigned long dabr);
++extern void print_backtrace(unsigned long *);
++extern void show_regs(struct pt_regs * regs);
++extern void flush_instruction_cache(void);
++extern void hard_reset_now(void);
++extern void poweroff_now(void);
++
++#ifdef CONFIG_6xx
++extern long _get_L2CR(void);
++extern long _get_L3CR(void);
++extern void _set_L2CR(unsigned long);
++extern void _set_L3CR(unsigned long);
++#else
++#define _get_L2CR() 0L
++#define _get_L3CR() 0L
++#define _set_L2CR(val) do { } while(0)
++#define _set_L3CR(val) do { } while(0)
++#endif
++
++extern void via_cuda_init(void);
++extern void read_rtc_time(void);
++extern void pmac_find_display(void);
++extern void giveup_fpu(struct task_struct *);
++extern void disable_kernel_fp(void);
++extern void enable_kernel_fp(void);
++extern void flush_fp_to_thread(struct task_struct *);
++extern void enable_kernel_altivec(void);
++extern void giveup_altivec(struct task_struct *);
++extern void load_up_altivec(struct task_struct *);
++extern int emulate_altivec(struct pt_regs *);
++extern void giveup_spe(struct task_struct *);
++extern void load_up_spe(struct task_struct *);
++extern int fix_alignment(struct pt_regs *);
++extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
++extern void cvt_df(double *from, float *to, struct thread_struct *thread);
++
++#ifdef CONFIG_ALTIVEC
++extern void flush_altivec_to_thread(struct task_struct *);
++#else
++static inline void flush_altivec_to_thread(struct task_struct *t)
++{
++}
++#endif
++
++#ifdef CONFIG_SPE
++extern void flush_spe_to_thread(struct task_struct *);
++#else
++static inline void flush_spe_to_thread(struct task_struct *t)
++{
++}
++#endif
++
++extern int call_rtas(const char *, int, int, unsigned long *, ...);
++extern void cacheable_memzero(void *p, unsigned int nb);
++extern void *cacheable_memcpy(void *, const void *, unsigned int);
++extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
++extern void bad_page_fault(struct pt_regs *, unsigned long, int);
++extern int die(const char *, struct pt_regs *, long);
++extern void _exception(int, struct pt_regs *, int, unsigned long);
++#ifdef CONFIG_BOOKE_WDT
++extern u32 booke_wdt_enabled;
++extern u32 booke_wdt_period;
++#endif /* CONFIG_BOOKE_WDT */
++
++/* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */
++extern unsigned char e2a(unsigned char);
++
++struct device_node;
++extern void note_scsi_host(struct device_node *, void *);
++
++extern struct task_struct *__switch_to(struct task_struct *,
++ struct task_struct *);
++#define switch_to(prev, next, last) ((last) = __switch_to((prev), (next)))
++
++struct thread_struct;
++extern struct task_struct *_switch(struct thread_struct *prev,
++ struct thread_struct *next);
++
++extern unsigned int rtas_data;
++extern int mem_init_done; /* set on boot once kmalloc can be called */
++extern unsigned long memory_limit;
++
++extern int powersave_nap; /* set if nap mode can be used in idle loop */
++
++/*
++ * Atomic exchange
++ *
++ * Changes the memory location '*ptr' to be val and returns
++ * the previous value stored there.
++ */
++static __inline__ unsigned long
++__xchg_u32(volatile void *p, unsigned long val)
++{
++ unsigned long prev;
++
++ __asm__ __volatile__(
++ EIEIO_ON_SMP
++"1: lwarx %0,0,%2 \n"
++ PPC405_ERR77(0,%2)
++" stwcx. %3,0,%2 \n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ : "=&r" (prev), "=m" (*(volatile unsigned int *)p)
++ : "r" (p), "r" (val), "m" (*(volatile unsigned int *)p)
++ : "cc", "memory");
++
++ return prev;
++}
++
++#ifdef CONFIG_PPC64
++static __inline__ unsigned long
++__xchg_u64(volatile void *p, unsigned long val)
++{
++ unsigned long prev;
++
++ __asm__ __volatile__(
++ EIEIO_ON_SMP
++"1: ldarx %0,0,%2 \n"
++ PPC405_ERR77(0,%2)
++" stdcx. %3,0,%2 \n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ : "=&r" (prev), "=m" (*(volatile unsigned long *)p)
++ : "r" (p), "r" (val), "m" (*(volatile unsigned long *)p)
++ : "cc", "memory");
++
++ return prev;
++}
++#endif
++
++/*
++ * This function doesn't exist, so you'll get a linker error
++ * if something tries to do an invalid xchg().
++ */
++extern void __xchg_called_with_bad_pointer(void);
++
++static __inline__ unsigned long
++__xchg(volatile void *ptr, unsigned long x, unsigned int size)
++{
++ switch (size) {
++ case 4:
++ return __xchg_u32(ptr, x);
++#ifdef CONFIG_PPC64
++ case 8:
++ return __xchg_u64(ptr, x);
++#endif
++ }
++ __xchg_called_with_bad_pointer();
++ return x;
++}
++
++#define xchg(ptr,x) \
++ ({ \
++ __typeof__(*(ptr)) _x_ = (x); \
++ (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
++ })
++
++#define tas(ptr) (xchg((ptr),1))
++
++/*
++ * Compare and exchange - if *p == old, set it to new,
++ * and return the old value of *p.
++ */
++#define __HAVE_ARCH_CMPXCHG 1
++
++static __inline__ unsigned long
++__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
++{
++ unsigned int prev;
++
++ __asm__ __volatile__ (
++ EIEIO_ON_SMP
++"1: lwarx %0,0,%2 # __cmpxchg_u32\n\
++ cmpw 0,%0,%3\n\
++ bne- 2f\n"
++ PPC405_ERR77(0,%2)
++" stwcx. %4,0,%2\n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ "\n\
++2:"
++ : "=&r" (prev), "=m" (*p)
++ : "r" (p), "r" (old), "r" (new), "m" (*p)
++ : "cc", "memory");
++
++ return prev;
++}
++
++#ifdef CONFIG_PPC64
++static __inline__ unsigned long
++__cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new)
++{
++ unsigned long prev;
++
++ __asm__ __volatile__ (
++ EIEIO_ON_SMP
++"1: ldarx %0,0,%2 # __cmpxchg_u64\n\
++ cmpd 0,%0,%3\n\
++ bne- 2f\n\
++ stdcx. %4,0,%2\n\
++ bne- 1b"
++ ISYNC_ON_SMP
++ "\n\
++2:"
++ : "=&r" (prev), "=m" (*p)
++ : "r" (p), "r" (old), "r" (new), "m" (*p)
++ : "cc", "memory");
++
++ return prev;
++}
++#endif
++
++/* This function doesn't exist, so you'll get a linker error
++ if something tries to do an invalid cmpxchg(). */
++extern void __cmpxchg_called_with_bad_pointer(void);
++
++static __inline__ unsigned long
++__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
++ unsigned int size)
++{
++ switch (size) {
++ case 4:
++ return __cmpxchg_u32(ptr, old, new);
++#ifdef CONFIG_PPC64
++ case 8:
++ return __cmpxchg_u64(ptr, old, new);
++#endif
++ }
++ __cmpxchg_called_with_bad_pointer();
++ return old;
++}
++
++#define cmpxchg(ptr,o,n) \
++ ({ \
++ __typeof__(*(ptr)) _o_ = (o); \
++ __typeof__(*(ptr)) _n_ = (n); \
++ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
++ (unsigned long)_n_, sizeof(*(ptr))); \
++ })
++
++#ifdef CONFIG_PPC64
++/*
++ * We handle most unaligned accesses in hardware. On the other hand
++ * unaligned DMA can be very expensive on some ppc64 IO chips (it does
++ * powers of 2 writes until it reaches sufficient alignment).
++ *
++ * Based on this we disable the IP header alignment in network drivers.
++ */
++#define NET_IP_ALIGN 0
++#endif
++
++#define arch_align_stack(x) (x)
++
++/* Used in very early kernel initialization. */
++extern unsigned long reloc_offset(void);
++extern unsigned long add_reloc_offset(unsigned long);
++extern void reloc_got2(unsigned long);
++
++#define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x)))
++
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_SYSTEM_H */
+diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/thread_info.h
+@@ -0,0 +1,142 @@
++/* thread_info.h: PowerPC low-level thread information
++ * adapted from the i386 version by Paul Mackerras
++ *
++ * Copyright (C) 2002 David Howells (dhowells at redhat.com)
++ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
++ */
++
++#ifndef _ASM_POWERPC_THREAD_INFO_H
++#define _ASM_POWERPC_THREAD_INFO_H
++
++#ifdef __KERNEL__
++
++/* We have 8k stacks on ppc32 and 16k on ppc64 */
++
++#ifdef CONFIG_PPC64
++#define THREAD_SHIFT 14
++#else
++#define THREAD_SHIFT 13
++#endif
++
++#define THREAD_SIZE (1 << THREAD_SHIFT)
++
++#ifndef __ASSEMBLY__
++#include <linux/config.h>
++#include <linux/cache.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <linux/stringify.h>
++
++/*
++ * low level task data.
++ */
++struct thread_info {
++ struct task_struct *task; /* main task structure */
++ struct exec_domain *exec_domain; /* execution domain */
++ int cpu; /* cpu we're on */
++ int preempt_count; /* 0 => preemptable,
++ <0 => BUG */
++ struct restart_block restart_block;
++ /* set by force_successful_syscall_return */
++ unsigned char syscall_noerror;
++ /* low level flags - has atomic operations done on it */
++ unsigned long flags ____cacheline_aligned_in_smp;
++};
++
++/*
++ * macros/functions for gaining access to the thread information structure
++ *
++ * preempt_count needs to be 1 initially, until the scheduler is functional.
++ */
++#define INIT_THREAD_INFO(tsk) \
++{ \
++ .task = &tsk, \
++ .exec_domain = &default_exec_domain, \
++ .cpu = 0, \
++ .preempt_count = 1, \
++ .restart_block = { \
++ .fn = do_no_restart_syscall, \
++ }, \
++ .flags = 0, \
++}
++
++#define init_thread_info (init_thread_union.thread_info)
++#define init_stack (init_thread_union.stack)
++
++/* thread information allocation */
++
++#ifdef CONFIG_DEBUG_STACK_USAGE
++#define THREAD_INFO_GFP GFP_KERNEL | __GFP_ZERO
++#else
++#define THREAD_INFO_GFP GFP_KERNEL
++#endif
++
++#if THREAD_SHIFT >= PAGE_SHIFT
++
++#define THREAD_ORDER (THREAD_SHIFT - PAGE_SHIFT)
++
++#define alloc_thread_info(tsk) \
++ ((struct thread_info *)__get_free_pages(THREAD_INFO_GFP, THREAD_ORDER))
++#define free_thread_info(ti) free_pages((unsigned long)ti, THREAD_ORDER)
++
++#else /* THREAD_SHIFT < PAGE_SHIFT */
++
++#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, THREAD_INFO_GFP)
++#define free_thread_info(ti) kfree(ti)
++
++#endif /* THREAD_SHIFT < PAGE_SHIFT */
++
++#define get_thread_info(ti) get_task_struct((ti)->task)
++#define put_thread_info(ti) put_task_struct((ti)->task)
++
++/* how to get the thread information struct from C */
++static inline struct thread_info *current_thread_info(void)
++{
++ register unsigned long sp asm("r1");
++
++ /* gcc4, at least, is smart enough to turn this into a single
++ * rlwinm for ppc32 and clrrdi for ppc64 */
++ return (struct thread_info *)(sp & ~(THREAD_SIZE-1));
++}
++
++#endif /* __ASSEMBLY__ */
++
++#define PREEMPT_ACTIVE 0x10000000
++
++/*
++ * thread information flag bit numbers
++ */
++#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
++#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
++#define TIF_SIGPENDING 2 /* signal pending */
++#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
++#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
++ TIF_NEED_RESCHED */
++#define TIF_32BIT 5 /* 32 bit binary */
++/* #define SPARE 6 */
++#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */
++#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
++#define TIF_SINGLESTEP 9 /* singlestepping active */
++#define TIF_MEMDIE 10
++#define TIF_SECCOMP 11 /* secure computing */
++
++/* as above, but as bit values */
++#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
++#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
++#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
++#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
++#define _TIF_32BIT (1<<TIF_32BIT)
++/* #define _SPARE (1<<SPARE) */
++#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
++#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
++#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
++#define _TIF_SECCOMP (1<<TIF_SECCOMP)
++#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
++
++#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
++ _TIF_NEED_RESCHED)
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_POWERPC_THREAD_INFO_H */
+diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/time.h
+@@ -0,0 +1,226 @@
++/*
++ * Common time prototypes and such for all ppc machines.
++ *
++ * Written by Cort Dougan (cort at cs.nmt.edu) to merge
++ * Paul Mackerras' version and mine for PReP and Pmac.
++ *
++ * 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 __POWERPC_TIME_H
++#define __POWERPC_TIME_H
++
++#ifdef __KERNEL__
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/percpu.h>
++
++#include <asm/processor.h>
++#ifdef CONFIG_PPC64
++#include <asm/paca.h>
++#include <asm/iSeries/HvCall.h>
++#endif
++
++/* time.c */
++extern unsigned long tb_ticks_per_jiffy;
++extern unsigned long tb_ticks_per_usec;
++extern unsigned long tb_ticks_per_sec;
++extern u64 tb_to_xs;
++extern unsigned tb_to_us;
++extern unsigned long tb_last_stamp;
++extern u64 tb_last_jiffy;
++
++DECLARE_PER_CPU(unsigned long, last_jiffy);
++
++struct rtc_time;
++extern void to_tm(int tim, struct rtc_time * tm);
++extern time_t last_rtc_update;
++
++extern void generic_calibrate_decr(void);
++extern void wakeup_decrementer(void);
++
++/* Some sane defaults: 125 MHz timebase, 1GHz processor */
++extern unsigned long ppc_proc_freq;
++#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
++extern unsigned long ppc_tb_freq;
++#define DEFAULT_TB_FREQ 125000000UL
++
++/*
++ * By putting all of this stuff into a single struct we
++ * reduce the number of cache lines touched by do_gettimeofday.
++ * Both by collecting all of the data in one cache line and
++ * by touching only one TOC entry on ppc64.
++ */
++struct gettimeofday_vars {
++ u64 tb_to_xs;
++ u64 stamp_xsec;
++ u64 tb_orig_stamp;
++};
++
++struct gettimeofday_struct {
++ unsigned long tb_ticks_per_sec;
++ struct gettimeofday_vars vars[2];
++ struct gettimeofday_vars * volatile varp;
++ unsigned var_idx;
++ unsigned tb_to_us;
++};
++
++struct div_result {
++ u64 result_high;
++ u64 result_low;
++};
++
++/* Accessor functions for the timebase (RTC on 601) registers. */
++/* If one day CONFIG_POWER is added just define __USE_RTC as 1 */
++#ifdef CONFIG_6xx
++#define __USE_RTC() (!cpu_has_feature(CPU_FTR_USE_TB))
++#else
++#define __USE_RTC() 0
++#endif
++
++/* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */
++static inline unsigned long get_tbl(void)
++{
++ unsigned long tbl;
++
++#if defined(CONFIG_403GCX)
++ asm volatile("mfspr %0, 0x3dd" : "=r" (tbl));
++#else
++ asm volatile("mftb %0" : "=r" (tbl));
++#endif
++ return tbl;
++}
++
++static inline unsigned int get_tbu(void)
++{
++ unsigned int tbu;
++
++#if defined(CONFIG_403GCX)
++ asm volatile("mfspr %0, 0x3dc" : "=r" (tbu));
++#else
++ asm volatile("mftbu %0" : "=r" (tbu));
++#endif
++ return tbu;
++}
++
++static inline unsigned int get_rtcl(void)
++{
++ unsigned int rtcl;
++
++ asm volatile("mfrtcl %0" : "=r" (rtcl));
++ return rtcl;
++}
++
++static inline u64 get_rtc(void)
++{
++ unsigned int hi, lo, hi2;
++
++ do {
++ asm volatile("mfrtcu %0; mfrtcl %1; mfrtcu %2"
++ : "=r" (hi), "=r" (lo), "=r" (hi2));
++ } while (hi2 != hi);
++ return (u64)hi * 1000000000 + lo;
++}
++
++#ifdef CONFIG_PPC64
++static inline u64 get_tb(void)
++{
++ return mftb();
++}
++#else
++static inline u64 get_tb(void)
++{
++ unsigned int tbhi, tblo, tbhi2;
++
++ do {
++ tbhi = get_tbu();
++ tblo = get_tbl();
++ tbhi2 = get_tbu();
++ } while (tbhi != tbhi2);
++
++ return ((u64)tbhi << 32) | tblo;
++}
++#endif
++
++static inline void set_tb(unsigned int upper, unsigned int lower)
++{
++ mtspr(SPRN_TBWL, 0);
++ mtspr(SPRN_TBWU, upper);
++ mtspr(SPRN_TBWL, lower);
++}
++
++/* Accessor functions for the decrementer register.
++ * The 4xx doesn't even have a decrementer. I tried to use the
++ * generic timer interrupt code, which seems OK, with the 4xx PIT
++ * in auto-reload mode. The problem is PIT stops counting when it
++ * hits zero. If it would wrap, we could use it just like a decrementer.
++ */
++static inline unsigned int get_dec(void)
++{
++#if defined(CONFIG_40x)
++ return (mfspr(SPRN_PIT));
++#else
++ return (mfspr(SPRN_DEC));
++#endif
++}
++
++static inline void set_dec(int val)
++{
++#if defined(CONFIG_40x)
++ return; /* Have to let it auto-reload */
++#elif defined(CONFIG_8xx_CPU6)
++ set_dec_cpu6(val);
++#else
++#ifdef CONFIG_PPC_ISERIES
++ struct paca_struct *lpaca = get_paca();
++ int cur_dec;
++
++ if (lpaca->lppaca.shared_proc) {
++ lpaca->lppaca.virtual_decr = val;
++ cur_dec = get_dec();
++ if (cur_dec > val)
++ HvCall_setVirtualDecr();
++ } else
++#endif
++ mtspr(SPRN_DEC, val);
++#endif /* not 40x or 8xx_CPU6 */
++}
++
++static inline unsigned long tb_ticks_since(unsigned long tstamp)
++{
++ if (__USE_RTC()) {
++ int delta = get_rtcl() - (unsigned int) tstamp;
++ return delta < 0 ? delta + 1000000000 : delta;
++ }
++ return get_tbl() - tstamp;
++}
++
++#define mulhwu(x,y) \
++({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
++
++#ifdef CONFIG_PPC64
++#define mulhdu(x,y) \
++({unsigned long z; asm ("mulhdu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
++#else
++extern u64 mulhdu(u64, u64);
++#endif
++
++extern void smp_space_timers(unsigned int);
++
++extern unsigned mulhwu_scale_factor(unsigned, unsigned);
++extern void div128_by_32(u64 dividend_high, u64 dividend_low,
++ unsigned divisor, struct div_result *dr);
++
++/* Used to store Processor Utilization register (purr) values */
++
++struct cpu_usage {
++ u64 current_tb; /* Holds the current purr register values */
++};
++
++DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
++
++#endif /* __KERNEL__ */
++#endif /* __PPC64_TIME_H */
+diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/types.h
+@@ -0,0 +1,110 @@
++#ifndef _ASM_POWERPC_TYPES_H
++#define _ASM_POWERPC_TYPES_H
++
++#ifndef __ASSEMBLY__
++
++/*
++ * This file is never included by application software unless
++ * explicitly requested (e.g., via linux/types.h) in which case the
++ * application is Linux specific so (user-) name space pollution is
++ * not a major issue. However, for interoperability, libraries still
++ * need to be careful to avoid a name clashes.
++ *
++ * 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.
++ */
++
++#ifdef __powerpc64__
++typedef unsigned int umode_t;
++#else
++typedef unsigned short umode_t;
++#endif
++
++/*
++ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
++ * header files exported to user space
++ */
++
++typedef __signed__ char __s8;
++typedef unsigned char __u8;
++
++typedef __signed__ short __s16;
++typedef unsigned short __u16;
++
++typedef __signed__ int __s32;
++typedef unsigned int __u32;
++
++#ifdef __powerpc64__
++typedef __signed__ long __s64;
++typedef unsigned long __u64;
++#else
++#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
++typedef __signed__ long long __s64;
++typedef unsigned long long __u64;
++#endif
++#endif /* __powerpc64__ */
++
++typedef struct {
++ __u32 u[4];
++} __attribute((aligned(16))) __vector128;
++
++#endif /* __ASSEMBLY__ */
++
++#ifdef __KERNEL__
++/*
++ * These aren't exported outside the kernel to avoid name space clashes
++ */
++#ifdef __powerpc64__
++#define BITS_PER_LONG 64
++#else
++#define BITS_PER_LONG 32
++#endif
++
++#ifndef __ASSEMBLY__
++
++#include <linux/config.h>
++
++typedef signed char s8;
++typedef unsigned char u8;
++
++typedef signed short s16;
++typedef unsigned short u16;
++
++typedef signed int s32;
++typedef unsigned int u32;
++
++#ifdef __powerpc64__
++typedef signed long s64;
++typedef unsigned long u64;
++#else
++typedef signed long long s64;
++typedef unsigned long long u64;
++#endif
++
++typedef __vector128 vector128;
++
++#ifdef __powerpc64__
++typedef u64 dma_addr_t;
++#else
++typedef u32 dma_addr_t;
++#endif
++typedef u64 dma64_addr_t;
++
++typedef struct {
++ unsigned long entry;
++ unsigned long toc;
++ unsigned long env;
++} func_descr_t;
++
++#ifdef CONFIG_LBD
++typedef u64 sector_t;
++#define HAVE_SECTOR_T
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_POWERPC_TYPES_H */
+diff --git a/include/asm-powerpc/uninorth.h b/include/asm-powerpc/uninorth.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/uninorth.h
+@@ -0,0 +1,229 @@
++/*
++ * uninorth.h: definitions for using the "UniNorth" host bridge chip
++ * from Apple. This chip is used on "Core99" machines
++ * This also includes U2 used on more recent MacRISC2/3
++ * machines and U3 (G5)
++ *
++ */
++#ifdef __KERNEL__
++#ifndef __ASM_UNINORTH_H__
++#define __ASM_UNINORTH_H__
++
++/*
++ * Uni-N and U3 config space reg. definitions
++ *
++ * (Little endian)
++ */
++
++/* Address ranges selection. This one should work with Bandit too */
++/* Not U3 */
++#define UNI_N_ADDR_SELECT 0x48
++#define UNI_N_ADDR_COARSE_MASK 0xffff0000 /* 256Mb regions at *0000000 */
++#define UNI_N_ADDR_FINE_MASK 0x0000ffff /* 16Mb regions at f*000000 */
++
++/* AGP registers */
++/* Not U3 */
++#define UNI_N_CFG_GART_BASE 0x8c
++#define UNI_N_CFG_AGP_BASE 0x90
++#define UNI_N_CFG_GART_CTRL 0x94
++#define UNI_N_CFG_INTERNAL_STATUS 0x98
++#define UNI_N_CFG_GART_DUMMY_PAGE 0xa4
++
++/* UNI_N_CFG_GART_CTRL bits definitions */
++#define UNI_N_CFG_GART_INVAL 0x00000001
++#define UNI_N_CFG_GART_ENABLE 0x00000100
++#define UNI_N_CFG_GART_2xRESET 0x00010000
++#define UNI_N_CFG_GART_DISSBADET 0x00020000
++/* The following seems to only be used only on U3 <j.glisse at gmail.com> */
++#define U3_N_CFG_GART_SYNCMODE 0x00040000
++#define U3_N_CFG_GART_PERFRD 0x00080000
++#define U3_N_CFG_GART_B2BGNT 0x00200000
++#define U3_N_CFG_GART_FASTDDR 0x00400000
++
++/* My understanding of UniNorth AGP as of UniNorth rev 1.0x,
++ * revision 1.5 (x4 AGP) may need further changes.
++ *
++ * AGP_BASE register contains the base address of the AGP aperture on
++ * the AGP bus. It doesn't seem to be visible to the CPU as of UniNorth 1.x,
++ * even if decoding of this address range is enabled in the address select
++ * register. Apparently, the only supported bases are 256Mb multiples
++ * (high 4 bits of that register).
++ *
++ * GART_BASE register appear to contain the physical address of the GART
++ * in system memory in the high address bits (page aligned), and the
++ * GART size in the low order bits (number of GART pages)
++ *
++ * The GART format itself is one 32bits word per physical memory page.
++ * This word contains, in little-endian format (!!!), the physical address
++ * of the page in the high bits, and what appears to be an "enable" bit
++ * in the LSB bit (0) that must be set to 1 when the entry is valid.
++ *
++ * Obviously, the GART is not cache coherent and so any change to it
++ * must be flushed to memory (or maybe just make the GART space non
++ * cachable). AGP memory itself doens't seem to be cache coherent neither.
++ *
++ * In order to invalidate the GART (which is probably necessary to inval
++ * the bridge internal TLBs), the following sequence has to be written,
++ * in order, to the GART_CTRL register:
++ *
++ * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL
++ * UNI_N_CFG_GART_ENABLE
++ * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET
++ * UNI_N_CFG_GART_ENABLE
++ *
++ * As far as AGP "features" are concerned, it looks like fast write may
++ * not be supported but this has to be confirmed.
++ *
++ * Turning on AGP seem to require a double invalidate operation, one before
++ * setting the AGP command register, on after.
++ *
++ * Turning off AGP seems to require the following sequence: first wait
++ * for the AGP to be idle by reading the internal status register, then
++ * write in that order to the GART_CTRL register:
++ *
++ * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL
++ * 0
++ * UNI_N_CFG_GART_2xRESET
++ * 0
++ */
++
++/*
++ * Uni-N memory mapped reg. definitions
++ *
++ * Those registers are Big-Endian !!
++ *
++ * Their meaning come from either Darwin and/or from experiments I made with
++ * the bootrom, I'm not sure about their exact meaning yet
++ *
++ */
++
++/* Version of the UniNorth chip */
++#define UNI_N_VERSION 0x0000 /* Known versions: 3,7 and 8 */
++
++#define UNI_N_VERSION_107 0x0003 /* 1.0.7 */
++#define UNI_N_VERSION_10A 0x0007 /* 1.0.10 */
++#define UNI_N_VERSION_150 0x0011 /* 1.5 */
++#define UNI_N_VERSION_200 0x0024 /* 2.0 */
++#define UNI_N_VERSION_PANGEA 0x00C0 /* Integrated U1 + K */
++#define UNI_N_VERSION_INTREPID 0x00D2 /* Integrated U2 + K */
++#define UNI_N_VERSION_300 0x0030 /* 3.0 (U3 on G5) */
++
++/* This register is used to enable/disable various clocks */
++#define UNI_N_CLOCK_CNTL 0x0020
++#define UNI_N_CLOCK_CNTL_PCI 0x00000001 /* PCI2 clock control */
++#define UNI_N_CLOCK_CNTL_GMAC 0x00000002 /* GMAC clock control */
++#define UNI_N_CLOCK_CNTL_FW 0x00000004 /* FireWire clock control */
++#define UNI_N_CLOCK_CNTL_ATA100 0x00000010 /* ATA-100 clock control (U2) */
++
++/* Power Management control */
++#define UNI_N_POWER_MGT 0x0030
++#define UNI_N_POWER_MGT_NORMAL 0x00
++#define UNI_N_POWER_MGT_IDLE2 0x01
++#define UNI_N_POWER_MGT_SLEEP 0x02
++
++/* This register is configured by Darwin depending on the UniN
++ * revision
++ */
++#define UNI_N_ARB_CTRL 0x0040
++#define UNI_N_ARB_CTRL_QACK_DELAY_SHIFT 15
++#define UNI_N_ARB_CTRL_QACK_DELAY_MASK 0x0e1f8000
++#define UNI_N_ARB_CTRL_QACK_DELAY 0x30
++#define UNI_N_ARB_CTRL_QACK_DELAY105 0x00
++
++/* This one _might_ return the CPU number of the CPU reading it;
++ * the bootROM decides whether to boot or to sleep/spinloop depending
++ * on this register beeing 0 or not
++ */
++#define UNI_N_CPU_NUMBER 0x0050
++
++/* This register appear to be read by the bootROM to decide what
++ * to do on a non-recoverable reset (powerup or wakeup)
++ */
++#define UNI_N_HWINIT_STATE 0x0070
++#define UNI_N_HWINIT_STATE_SLEEPING 0x01
++#define UNI_N_HWINIT_STATE_RUNNING 0x02
++/* This last bit appear to be used by the bootROM to know the second
++ * CPU has started and will enter it's sleep loop with IP=0
++ */
++#define UNI_N_HWINIT_STATE_CPU1_FLAG 0x10000000
++
++/* This register controls AACK delay, which is set when 2004 iBook/PowerBook
++ * is in low speed mode.
++ */
++#define UNI_N_AACK_DELAY 0x0100
++#define UNI_N_AACK_DELAY_ENABLE 0x00000001
++
++/* Clock status for Intrepid */
++#define UNI_N_CLOCK_STOP_STATUS0 0x0150
++#define UNI_N_CLOCK_STOPPED_EXTAGP 0x00200000
++#define UNI_N_CLOCK_STOPPED_AGPDEL 0x00100000
++#define UNI_N_CLOCK_STOPPED_I2S0_45_49 0x00080000
++#define UNI_N_CLOCK_STOPPED_I2S0_18 0x00040000
++#define UNI_N_CLOCK_STOPPED_I2S1_45_49 0x00020000
++#define UNI_N_CLOCK_STOPPED_I2S1_18 0x00010000
++#define UNI_N_CLOCK_STOPPED_TIMER 0x00008000
++#define UNI_N_CLOCK_STOPPED_SCC_RTCLK18 0x00004000
++#define UNI_N_CLOCK_STOPPED_SCC_RTCLK32 0x00002000
++#define UNI_N_CLOCK_STOPPED_SCC_VIA32 0x00001000
++#define UNI_N_CLOCK_STOPPED_SCC_SLOT0 0x00000800
++#define UNI_N_CLOCK_STOPPED_SCC_SLOT1 0x00000400
++#define UNI_N_CLOCK_STOPPED_SCC_SLOT2 0x00000200
++#define UNI_N_CLOCK_STOPPED_PCI_FBCLKO 0x00000100
++#define UNI_N_CLOCK_STOPPED_VEO0 0x00000080
++#define UNI_N_CLOCK_STOPPED_VEO1 0x00000040
++#define UNI_N_CLOCK_STOPPED_USB0 0x00000020
++#define UNI_N_CLOCK_STOPPED_USB1 0x00000010
++#define UNI_N_CLOCK_STOPPED_USB2 0x00000008
++#define UNI_N_CLOCK_STOPPED_32 0x00000004
++#define UNI_N_CLOCK_STOPPED_45 0x00000002
++#define UNI_N_CLOCK_STOPPED_49 0x00000001
++
++#define UNI_N_CLOCK_STOP_STATUS1 0x0160
++#define UNI_N_CLOCK_STOPPED_PLL4REF 0x00080000
++#define UNI_N_CLOCK_STOPPED_CPUDEL 0x00040000
++#define UNI_N_CLOCK_STOPPED_CPU 0x00020000
++#define UNI_N_CLOCK_STOPPED_BUF_REFCKO 0x00010000
++#define UNI_N_CLOCK_STOPPED_PCI2 0x00008000
++#define UNI_N_CLOCK_STOPPED_FW 0x00004000
++#define UNI_N_CLOCK_STOPPED_GB 0x00002000
++#define UNI_N_CLOCK_STOPPED_ATA66 0x00001000
++#define UNI_N_CLOCK_STOPPED_ATA100 0x00000800
++#define UNI_N_CLOCK_STOPPED_MAX 0x00000400
++#define UNI_N_CLOCK_STOPPED_PCI1 0x00000200
++#define UNI_N_CLOCK_STOPPED_KLPCI 0x00000100
++#define UNI_N_CLOCK_STOPPED_USB0PCI 0x00000080
++#define UNI_N_CLOCK_STOPPED_USB1PCI 0x00000040
++#define UNI_N_CLOCK_STOPPED_USB2PCI 0x00000020
++#define UNI_N_CLOCK_STOPPED_7PCI1 0x00000008
++#define UNI_N_CLOCK_STOPPED_AGP 0x00000004
++#define UNI_N_CLOCK_STOPPED_PCI0 0x00000002
++#define UNI_N_CLOCK_STOPPED_18 0x00000001
++
++/* Intrepid registe to OF do-platform-clockspreading */
++#define UNI_N_CLOCK_SPREADING 0x190
++
++/* Uninorth 1.5 rev. has additional perf. monitor registers at 0xf00-0xf50 */
++
++
++/*
++ * U3 specific registers
++ */
++
++
++/* U3 Toggle */
++#define U3_TOGGLE_REG 0x00e0
++#define U3_PMC_START_STOP 0x0001
++#define U3_MPIC_RESET 0x0002
++#define U3_MPIC_OUTPUT_ENABLE 0x0004
++
++/* U3 API PHY Config 1 */
++#define U3_API_PHY_CONFIG_1 0x23030
++
++/* U3 HyperTransport registers */
++#define U3_HT_CONFIG_BASE 0x70000
++#define U3_HT_LINK_COMMAND 0x100
++#define U3_HT_LINK_CONFIG 0x110
++#define U3_HT_LINK_FREQ 0x120
++
++#endif /* __ASM_UNINORTH_H__ */
++#endif /* __KERNEL__ */
+diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/unistd.h
+@@ -0,0 +1,509 @@
++#ifndef _ASM_PPC_UNISTD_H_
++#define _ASM_PPC_UNISTD_H_
++
++/*
++ * This file contains the system call numbers.
++ *
++ * 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.
++ */
++
++#define __NR_restart_syscall 0
++#define __NR_exit 1
++#define __NR_fork 2
++#define __NR_read 3
++#define __NR_write 4
++#define __NR_open 5
++#define __NR_close 6
++#define __NR_waitpid 7
++#define __NR_creat 8
++#define __NR_link 9
++#define __NR_unlink 10
++#define __NR_execve 11
++#define __NR_chdir 12
++#define __NR_time 13
++#define __NR_mknod 14
++#define __NR_chmod 15
++#define __NR_lchown 16
++#define __NR_break 17
++#define __NR_oldstat 18
++#define __NR_lseek 19
++#define __NR_getpid 20
++#define __NR_mount 21
++#define __NR_umount 22
++#define __NR_setuid 23
++#define __NR_getuid 24
++#define __NR_stime 25
++#define __NR_ptrace 26
++#define __NR_alarm 27
++#define __NR_oldfstat 28
++#define __NR_pause 29
++#define __NR_utime 30
++#define __NR_stty 31
++#define __NR_gtty 32
++#define __NR_access 33
++#define __NR_nice 34
++#define __NR_ftime 35
++#define __NR_sync 36
++#define __NR_kill 37
++#define __NR_rename 38
++#define __NR_mkdir 39
++#define __NR_rmdir 40
++#define __NR_dup 41
++#define __NR_pipe 42
++#define __NR_times 43
++#define __NR_prof 44
++#define __NR_brk 45
++#define __NR_setgid 46
++#define __NR_getgid 47
++#define __NR_signal 48
++#define __NR_geteuid 49
++#define __NR_getegid 50
++#define __NR_acct 51
++#define __NR_umount2 52
++#define __NR_lock 53
++#define __NR_ioctl 54
++#define __NR_fcntl 55
++#define __NR_mpx 56
++#define __NR_setpgid 57
++#define __NR_ulimit 58
++#define __NR_oldolduname 59
++#define __NR_umask 60
++#define __NR_chroot 61
++#define __NR_ustat 62
++#define __NR_dup2 63
++#define __NR_getppid 64
++#define __NR_getpgrp 65
++#define __NR_setsid 66
++#define __NR_sigaction 67
++#define __NR_sgetmask 68
++#define __NR_ssetmask 69
++#define __NR_setreuid 70
++#define __NR_setregid 71
++#define __NR_sigsuspend 72
++#define __NR_sigpending 73
++#define __NR_sethostname 74
++#define __NR_setrlimit 75
++#define __NR_getrlimit 76
++#define __NR_getrusage 77
++#define __NR_gettimeofday 78
++#define __NR_settimeofday 79
++#define __NR_getgroups 80
++#define __NR_setgroups 81
++#define __NR_select 82
++#define __NR_symlink 83
++#define __NR_oldlstat 84
++#define __NR_readlink 85
++#define __NR_uselib 86
++#define __NR_swapon 87
++#define __NR_reboot 88
++#define __NR_readdir 89
++#define __NR_mmap 90
++#define __NR_munmap 91
++#define __NR_truncate 92
++#define __NR_ftruncate 93
++#define __NR_fchmod 94
++#define __NR_fchown 95
++#define __NR_getpriority 96
++#define __NR_setpriority 97
++#define __NR_profil 98
++#define __NR_statfs 99
++#define __NR_fstatfs 100
++#define __NR_ioperm 101
++#define __NR_socketcall 102
++#define __NR_syslog 103
++#define __NR_setitimer 104
++#define __NR_getitimer 105
++#define __NR_stat 106
++#define __NR_lstat 107
++#define __NR_fstat 108
++#define __NR_olduname 109
++#define __NR_iopl 110
++#define __NR_vhangup 111
++#define __NR_idle 112
++#define __NR_vm86 113
++#define __NR_wait4 114
++#define __NR_swapoff 115
++#define __NR_sysinfo 116
++#define __NR_ipc 117
++#define __NR_fsync 118
++#define __NR_sigreturn 119
++#define __NR_clone 120
++#define __NR_setdomainname 121
++#define __NR_uname 122
++#define __NR_modify_ldt 123
++#define __NR_adjtimex 124
++#define __NR_mprotect 125
++#define __NR_sigprocmask 126
++#define __NR_create_module 127
++#define __NR_init_module 128
++#define __NR_delete_module 129
++#define __NR_get_kernel_syms 130
++#define __NR_quotactl 131
++#define __NR_getpgid 132
++#define __NR_fchdir 133
++#define __NR_bdflush 134
++#define __NR_sysfs 135
++#define __NR_personality 136
++#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
++#define __NR_setfsuid 138
++#define __NR_setfsgid 139
++#define __NR__llseek 140
++#define __NR_getdents 141
++#define __NR__newselect 142
++#define __NR_flock 143
++#define __NR_msync 144
++#define __NR_readv 145
++#define __NR_writev 146
++#define __NR_getsid 147
++#define __NR_fdatasync 148
++#define __NR__sysctl 149
++#define __NR_mlock 150
++#define __NR_munlock 151
++#define __NR_mlockall 152
++#define __NR_munlockall 153
++#define __NR_sched_setparam 154
++#define __NR_sched_getparam 155
++#define __NR_sched_setscheduler 156
++#define __NR_sched_getscheduler 157
++#define __NR_sched_yield 158
++#define __NR_sched_get_priority_max 159
++#define __NR_sched_get_priority_min 160
++#define __NR_sched_rr_get_interval 161
++#define __NR_nanosleep 162
++#define __NR_mremap 163
++#define __NR_setresuid 164
++#define __NR_getresuid 165
++#define __NR_query_module 166
++#define __NR_poll 167
++#define __NR_nfsservctl 168
++#define __NR_setresgid 169
++#define __NR_getresgid 170
++#define __NR_prctl 171
++#define __NR_rt_sigreturn 172
++#define __NR_rt_sigaction 173
++#define __NR_rt_sigprocmask 174
++#define __NR_rt_sigpending 175
++#define __NR_rt_sigtimedwait 176
++#define __NR_rt_sigqueueinfo 177
++#define __NR_rt_sigsuspend 178
++#define __NR_pread64 179
++#define __NR_pwrite64 180
++#define __NR_chown 181
++#define __NR_getcwd 182
++#define __NR_capget 183
++#define __NR_capset 184
++#define __NR_sigaltstack 185
++#define __NR_sendfile 186
++#define __NR_getpmsg 187 /* some people actually want streams */
++#define __NR_putpmsg 188 /* some people actually want streams */
++#define __NR_vfork 189
++#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
++#define __NR_readahead 191
++#ifndef __powerpc64__ /* these are 32-bit only */
++#define __NR_mmap2 192
++#define __NR_truncate64 193
++#define __NR_ftruncate64 194
++#define __NR_stat64 195
++#define __NR_lstat64 196
++#define __NR_fstat64 197
++#endif
++#define __NR_pciconfig_read 198
++#define __NR_pciconfig_write 199
++#define __NR_pciconfig_iobase 200
++#define __NR_multiplexer 201
++#define __NR_getdents64 202
++#define __NR_pivot_root 203
++#ifndef __powerpc64__
++#define __NR_fcntl64 204
++#endif
++#define __NR_madvise 205
++#define __NR_mincore 206
++#define __NR_gettid 207
++#define __NR_tkill 208
++#define __NR_setxattr 209
++#define __NR_lsetxattr 210
++#define __NR_fsetxattr 211
++#define __NR_getxattr 212
++#define __NR_lgetxattr 213
++#define __NR_fgetxattr 214
++#define __NR_listxattr 215
++#define __NR_llistxattr 216
++#define __NR_flistxattr 217
++#define __NR_removexattr 218
++#define __NR_lremovexattr 219
++#define __NR_fremovexattr 220
++#define __NR_futex 221
++#define __NR_sched_setaffinity 222
++#define __NR_sched_getaffinity 223
++/* 224 currently unused */
++#define __NR_tuxcall 225
++#ifndef __powerpc64__
++#define __NR_sendfile64 226
++#endif
++#define __NR_io_setup 227
++#define __NR_io_destroy 228
++#define __NR_io_getevents 229
++#define __NR_io_submit 230
++#define __NR_io_cancel 231
++#define __NR_set_tid_address 232
++#define __NR_fadvise64 233
++#define __NR_exit_group 234
++#define __NR_lookup_dcookie 235
++#define __NR_epoll_create 236
++#define __NR_epoll_ctl 237
++#define __NR_epoll_wait 238
++#define __NR_remap_file_pages 239
++#define __NR_timer_create 240
++#define __NR_timer_settime 241
++#define __NR_timer_gettime 242
++#define __NR_timer_getoverrun 243
++#define __NR_timer_delete 244
++#define __NR_clock_settime 245
++#define __NR_clock_gettime 246
++#define __NR_clock_getres 247
++#define __NR_clock_nanosleep 248
++#define __NR_swapcontext 249
++#define __NR_tgkill 250
++#define __NR_utimes 251
++#define __NR_statfs64 252
++#define __NR_fstatfs64 253
++#ifndef __powerpc64__
++#define __NR_fadvise64_64 254
++#endif
++#define __NR_rtas 255
++#define __NR_sys_debug_setcontext 256
++/* Number 257 is reserved for vserver */
++/* 258 currently unused */
++#define __NR_mbind 259
++#define __NR_get_mempolicy 260
++#define __NR_set_mempolicy 261
++#define __NR_mq_open 262
++#define __NR_mq_unlink 263
++#define __NR_mq_timedsend 264
++#define __NR_mq_timedreceive 265
++#define __NR_mq_notify 266
++#define __NR_mq_getsetattr 267
++#define __NR_kexec_load 268
++#define __NR_add_key 269
++#define __NR_request_key 270
++#define __NR_keyctl 271
++#define __NR_waitid 272
++#define __NR_ioprio_set 273
++#define __NR_ioprio_get 274
++#define __NR_inotify_init 275
++#define __NR_inotify_add_watch 276
++#define __NR_inotify_rm_watch 277
++
++#define __NR_syscalls 278
++
++#ifdef __KERNEL__
++#define __NR__exit __NR_exit
++#define NR_syscalls __NR_syscalls
++#endif
++
++#ifndef __ASSEMBLY__
++
++/* On powerpc a system call basically clobbers the same registers like a
++ * function call, with the exception of LR (which is needed for the
++ * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
++ * an error return status).
++ */
++
++#define __syscall_nr(nr, type, name, args...) \
++ unsigned long __sc_ret, __sc_err; \
++ { \
++ register unsigned long __sc_0 __asm__ ("r0"); \
++ register unsigned long __sc_3 __asm__ ("r3"); \
++ register unsigned long __sc_4 __asm__ ("r4"); \
++ register unsigned long __sc_5 __asm__ ("r5"); \
++ register unsigned long __sc_6 __asm__ ("r6"); \
++ register unsigned long __sc_7 __asm__ ("r7"); \
++ register unsigned long __sc_8 __asm__ ("r8"); \
++ \
++ __sc_loadargs_##nr(name, args); \
++ __asm__ __volatile__ \
++ ("sc \n\t" \
++ "mfcr %0 " \
++ : "=&r" (__sc_0), \
++ "=&r" (__sc_3), "=&r" (__sc_4), \
++ "=&r" (__sc_5), "=&r" (__sc_6), \
++ "=&r" (__sc_7), "=&r" (__sc_8) \
++ : __sc_asm_input_##nr \
++ : "cr0", "ctr", "memory", \
++ "r9", "r10","r11", "r12"); \
++ __sc_ret = __sc_3; \
++ __sc_err = __sc_0; \
++ } \
++ if (__sc_err & 0x10000000) \
++ { \
++ errno = __sc_ret; \
++ __sc_ret = -1; \
++ } \
++ return (type) __sc_ret
++
++#define __sc_loadargs_0(name, dummy...) \
++ __sc_0 = __NR_##name
++#define __sc_loadargs_1(name, arg1) \
++ __sc_loadargs_0(name); \
++ __sc_3 = (unsigned long) (arg1)
++#define __sc_loadargs_2(name, arg1, arg2) \
++ __sc_loadargs_1(name, arg1); \
++ __sc_4 = (unsigned long) (arg2)
++#define __sc_loadargs_3(name, arg1, arg2, arg3) \
++ __sc_loadargs_2(name, arg1, arg2); \
++ __sc_5 = (unsigned long) (arg3)
++#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \
++ __sc_loadargs_3(name, arg1, arg2, arg3); \
++ __sc_6 = (unsigned long) (arg4)
++#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \
++ __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \
++ __sc_7 = (unsigned long) (arg5)
++#define __sc_loadargs_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
++ __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5); \
++ __sc_8 = (unsigned long) (arg6)
++
++#define __sc_asm_input_0 "0" (__sc_0)
++#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
++#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
++#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
++#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
++#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
++#define __sc_asm_input_6 __sc_asm_input_5, "6" (__sc_8)
++
++#define _syscall0(type,name) \
++type name(void) \
++{ \
++ __syscall_nr(0, type, name); \
++}
++
++#define _syscall1(type,name,type1,arg1) \
++type name(type1 arg1) \
++{ \
++ __syscall_nr(1, type, name, arg1); \
++}
++
++#define _syscall2(type,name,type1,arg1,type2,arg2) \
++type name(type1 arg1, type2 arg2) \
++{ \
++ __syscall_nr(2, type, name, arg1, arg2); \
++}
++
++#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
++type name(type1 arg1, type2 arg2, type3 arg3) \
++{ \
++ __syscall_nr(3, type, name, arg1, arg2, arg3); \
++}
++
++#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
++{ \
++ __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \
++}
++
++#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
++{ \
++ __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \
++}
++#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
++type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
++{ \
++ __syscall_nr(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \
++}
++
++#ifdef __KERNEL__
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/compiler.h>
++#include <linux/linkage.h>
++
++#define __ARCH_WANT_IPC_PARSE_VERSION
++#define __ARCH_WANT_OLD_READDIR
++#define __ARCH_WANT_STAT64
++#define __ARCH_WANT_SYS_ALARM
++#define __ARCH_WANT_SYS_GETHOSTNAME
++#define __ARCH_WANT_SYS_PAUSE
++#define __ARCH_WANT_SYS_SGETMASK
++#define __ARCH_WANT_SYS_SIGNAL
++#define __ARCH_WANT_SYS_TIME
++#define __ARCH_WANT_SYS_UTIME
++#define __ARCH_WANT_SYS_WAITPID
++#define __ARCH_WANT_SYS_SOCKETCALL
++#define __ARCH_WANT_SYS_FADVISE64
++#define __ARCH_WANT_SYS_GETPGRP
++#define __ARCH_WANT_SYS_LLSEEK
++#define __ARCH_WANT_SYS_NICE
++#define __ARCH_WANT_SYS_OLD_GETRLIMIT
++#define __ARCH_WANT_SYS_OLDUMOUNT
++#define __ARCH_WANT_SYS_SIGPENDING
++#define __ARCH_WANT_SYS_SIGPROCMASK
++#define __ARCH_WANT_SYS_RT_SIGACTION
++#ifdef CONFIG_PPC32
++#define __ARCH_WANT_OLD_STAT
++#endif
++#ifdef CONFIG_PPC64
++#define __ARCH_WANT_COMPAT_SYS_TIME
++#endif
++
++/*
++ * System call prototypes.
++ */
++#ifdef __KERNEL_SYSCALLS__
++extern pid_t setsid(void);
++extern int write(int fd, const char *buf, off_t count);
++extern int read(int fd, char *buf, off_t count);
++extern off_t lseek(int fd, off_t offset, int count);
++extern int dup(int fd);
++extern int execve(const char *file, char **argv, char **envp);
++extern int open(const char *file, int flag, int mode);
++extern int close(int fd);
++extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
++#endif /* __KERNEL_SYSCALLS__ */
++
++/*
++ * Functions that implement syscalls.
++ */
++unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot,
++ unsigned long flags, unsigned long fd, off_t offset);
++unsigned long sys_mmap2(unsigned long addr, size_t len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, unsigned long pgoff);
++struct pt_regs;
++int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
++ unsigned long a3, unsigned long a4, unsigned long a5,
++ struct pt_regs *regs);
++int sys_clone(unsigned long clone_flags, unsigned long usp,
++ int __user *parent_tidp, void __user *child_threadptr,
++ int __user *child_tidp, int p6, struct pt_regs *regs);
++int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5, unsigned long p6,
++ struct pt_regs *regs);
++int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
++ unsigned long p4, unsigned long p5, unsigned long p6,
++ struct pt_regs *regs);
++int sys_pipe(int __user *fildes);
++struct sigaction;
++long sys_rt_sigaction(int sig, const struct sigaction __user *act,
++ struct sigaction __user *oact, size_t sigsetsize);
++
++/*
++ * "Conditional" syscalls
++ *
++ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
++ * but it doesn't work on all toolchains, so we just do it by hand
++ */
++#ifdef CONFIG_PPC32
++#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
++#else
++#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall")
++#endif
++
++#endif /* __KERNEL__ */
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* _ASM_PPC_UNISTD_H_ */
+diff --git a/include/asm-powerpc/vga.h b/include/asm-powerpc/vga.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/vga.h
+@@ -0,0 +1,54 @@
++#ifndef _ASM_POWERPC_VGA_H_
++#define _ASM_POWERPC_VGA_H_
++
++#ifdef __KERNEL__
++
++/*
++ * Access to VGA videoram
++ *
++ * (c) 1998 Martin Mares <mj at ucw.cz>
++ */
++
++
++#include <asm/io.h>
++
++#include <linux/config.h>
++
++#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
++
++#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)
++{
++ st_le16(addr, val);
++}
++
++static inline u16 scr_readw(volatile const u16 *addr)
++{
++ return ld_le16(addr);
++}
++
++#define VT_BUF_HAVE_MEMCPYW
++#define scr_memcpyw memcpy
++
++#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */
++
++extern unsigned long vgacon_remap_base;
++
++#ifdef __powerpc64__
++#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0))
++#else
++#define VGA_MAP_MEM(x) (x + vgacon_remap_base)
++#endif
++
++#define vga_readb(x) (*(x))
++#define vga_writeb(x,y) (*(y) = (x))
++
++#endif /* __KERNEL__ */
++#endif /* _ASM_POWERPC_VGA_H_ */
+diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/vio.h
+@@ -0,0 +1,106 @@
++/*
++ * IBM PowerPC Virtual I/O Infrastructure Support.
++ *
++ * Copyright (c) 2003 IBM Corp.
++ * Dave Engebretsen engebret at us.ibm.com
++ * Santiago Leon santil at us.ibm.com
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#ifndef _ASM_POWERPC_VIO_H
++#define _ASM_POWERPC_VIO_H
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/mod_devicetable.h>
++
++#include <asm/hvcall.h>
++#include <asm/scatterlist.h>
++
++/*
++ * Architecture-specific constants for drivers to
++ * extract attributes of the device using vio_get_attribute()
++ */
++#define VETH_MAC_ADDR "local-mac-address"
++#define VETH_MCAST_FILTER_SIZE "ibm,mac-address-filters"
++
++/* End architecture-specific constants */
++
++#define h_vio_signal(ua, mode) \
++ plpar_hcall_norets(H_VIO_SIGNAL, ua, mode)
++
++#define VIO_IRQ_DISABLE 0UL
++#define VIO_IRQ_ENABLE 1UL
++
++struct iommu_table;
++
++/*
++ * The vio_dev structure is used to describe virtual I/O devices.
++ */
++struct vio_dev {
++ struct iommu_table *iommu_table; /* vio_map_* uses this */
++ char *name;
++ char *type;
++ uint32_t unit_address;
++ unsigned int irq;
++ struct device dev;
++};
++
++struct vio_driver {
++ struct list_head node;
++ const struct vio_device_id *id_table;
++ int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
++ int (*remove)(struct vio_dev *dev);
++ void (*shutdown)(struct vio_dev *dev);
++ unsigned long driver_data;
++ struct device_driver driver;
++};
++
++struct vio_bus_ops {
++ int (*match)(const struct vio_device_id *id, const struct vio_dev *dev);
++ void (*unregister_device)(struct vio_dev *);
++ void (*release_device)(struct device *);
++};
++
++extern struct dma_mapping_ops vio_dma_ops;
++extern struct bus_type vio_bus_type;
++extern struct vio_dev vio_bus_device;
++
++extern int vio_register_driver(struct vio_driver *drv);
++extern void vio_unregister_driver(struct vio_driver *drv);
++
++extern struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev);
++extern void __devinit vio_unregister_device(struct vio_dev *dev);
++
++extern int vio_bus_init(struct vio_bus_ops *);
++
++#ifdef CONFIG_PPC_PSERIES
++struct device_node;
++
++extern struct vio_dev * __devinit vio_register_device_node(
++ struct device_node *node_vdev);
++extern struct vio_dev *vio_find_node(struct device_node *vnode);
++extern const void *vio_get_attribute(struct vio_dev *vdev, void *which,
++ int *length);
++extern int vio_enable_interrupts(struct vio_dev *dev);
++extern int vio_disable_interrupts(struct vio_dev *dev);
++#endif
++
++static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
++{
++ return container_of(drv, struct vio_driver, driver);
++}
++
++static inline struct vio_dev *to_vio_dev(struct device *dev)
++{
++ return container_of(dev, struct vio_dev, dev);
++}
++
++#endif /* _ASM_POWERPC_VIO_H */
+diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-powerpc/xmon.h
+@@ -0,0 +1,12 @@
++#ifndef __PPC_XMON_H
++#define __PPC_XMON_H
++#ifdef __KERNEL__
++
++struct pt_regs;
++
++extern int xmon(struct pt_regs *excp);
++extern void xmon_printf(const char *fmt, ...);
++extern void xmon_init(int);
++
++#endif
++#endif
+diff --git a/include/asm-ppc/a.out.h b/include/asm-ppc/a.out.h
+deleted file mode 100644
+--- a/include/asm-ppc/a.out.h
++++ /dev/null
+@@ -1,26 +0,0 @@
+-#ifndef __PPC_A_OUT_H__
+-#define __PPC_A_OUT_H__
+-
+-/* grabbed from the intel stuff */
+-#define STACK_TOP TASK_SIZE
+-
+-
+-struct exec
+-{
+- unsigned long a_info; /* Use macros N_MAGIC, etc for access */
+- unsigned a_text; /* length of text, in bytes */
+- unsigned a_data; /* length of data, in bytes */
+- unsigned a_bss; /* length of uninitialized data area for file, in bytes */
+- unsigned a_syms; /* length of symbol table data in file, in bytes */
+- unsigned a_entry; /* start address */
+- unsigned a_trsize; /* length of relocation info for text, in bytes */
+- unsigned a_drsize; /* length of relocation info for data, in bytes */
+-};
+-
+-
+-#define N_TRSIZE(a) ((a).a_trsize)
+-#define N_DRSIZE(a) ((a).a_drsize)
+-#define N_SYMSIZE(a) ((a).a_syms)
+-
+-
+-#endif
+diff --git a/include/asm-ppc/atomic.h b/include/asm-ppc/atomic.h
+deleted file mode 100644
+--- a/include/asm-ppc/atomic.h
++++ /dev/null
+@@ -1,214 +0,0 @@
+-/*
+- * PowerPC atomic operations
+- */
+-
+-#ifndef _ASM_PPC_ATOMIC_H_
+-#define _ASM_PPC_ATOMIC_H_
+-
+-typedef struct { volatile int counter; } atomic_t;
+-
+-#ifdef __KERNEL__
+-
+-#define ATOMIC_INIT(i) { (i) }
+-
+-#define atomic_read(v) ((v)->counter)
+-#define atomic_set(v,i) (((v)->counter) = (i))
+-
+-extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
+-
+-#ifdef CONFIG_SMP
+-#define SMP_SYNC "sync"
+-#define SMP_ISYNC "\n\tisync"
+-#else
+-#define SMP_SYNC ""
+-#define SMP_ISYNC
+-#endif
+-
+-/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx.
+- * The old ATOMIC_SYNC_FIX covered some but not all of this.
+- */
+-#ifdef CONFIG_IBM405_ERR77
+-#define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";"
+-#else
+-#define PPC405_ERR77(ra,rb)
+-#endif
+-
+-static __inline__ void atomic_add(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%3 # atomic_add\n\
+- add %0,%2,%0\n"
+- PPC405_ERR77(0,%3)
+-" stwcx. %0,0,%3 \n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (a), "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_add_return(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%2 # atomic_add_return\n\
+- add %0,%1,%0\n"
+- PPC405_ERR77(0,%2)
+-" stwcx. %0,0,%2 \n\
+- bne- 1b"
+- SMP_ISYNC
+- : "=&r" (t)
+- : "r" (a), "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
+-
+-static __inline__ void atomic_sub(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%3 # atomic_sub\n\
+- subf %0,%2,%0\n"
+- PPC405_ERR77(0,%3)
+-" stwcx. %0,0,%3 \n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (a), "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_sub_return(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%2 # atomic_sub_return\n\
+- subf %0,%1,%0\n"
+- PPC405_ERR77(0,%2)
+-" stwcx. %0,0,%2 \n\
+- bne- 1b"
+- SMP_ISYNC
+- : "=&r" (t)
+- : "r" (a), "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-static __inline__ void atomic_inc(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%2 # atomic_inc\n\
+- addic %0,%0,1\n"
+- PPC405_ERR77(0,%2)
+-" stwcx. %0,0,%2 \n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_inc_return(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%1 # atomic_inc_return\n\
+- addic %0,%0,1\n"
+- PPC405_ERR77(0,%1)
+-" stwcx. %0,0,%1 \n\
+- bne- 1b"
+- SMP_ISYNC
+- : "=&r" (t)
+- : "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-/*
+- * atomic_inc_and_test - increment and test
+- * @v: pointer of type atomic_t
+- *
+- * Atomically increments @v by 1
+- * and returns true if the result is zero, or false for all
+- * other cases.
+- */
+-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+-
+-static __inline__ void atomic_dec(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%2 # atomic_dec\n\
+- addic %0,%0,-1\n"
+- PPC405_ERR77(0,%2)\
+-" stwcx. %0,0,%2\n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_dec_return(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%1 # atomic_dec_return\n\
+- addic %0,%0,-1\n"
+- PPC405_ERR77(0,%1)
+-" stwcx. %0,0,%1\n\
+- bne- 1b"
+- SMP_ISYNC
+- : "=&r" (t)
+- : "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
+-#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
+-
+-/*
+- * Atomically test *v and decrement if it is greater than 0.
+- * The function returns the old value of *v minus 1.
+- */
+-static __inline__ int atomic_dec_if_positive(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\
+- addic. %0,%0,-1\n\
+- blt- 2f\n"
+- PPC405_ERR77(0,%1)
+-" stwcx. %0,0,%1\n\
+- bne- 1b"
+- SMP_ISYNC
+- "\n\
+-2:" : "=&r" (t)
+- : "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-#define __MB __asm__ __volatile__ (SMP_SYNC : : : "memory")
+-#define smp_mb__before_atomic_dec() __MB
+-#define smp_mb__after_atomic_dec() __MB
+-#define smp_mb__before_atomic_inc() __MB
+-#define smp_mb__after_atomic_inc() __MB
+-
+-#endif /* __KERNEL__ */
+-#endif /* _ASM_PPC_ATOMIC_H_ */
+diff --git a/include/asm-ppc/auxvec.h b/include/asm-ppc/auxvec.h
+deleted file mode 100644
+--- a/include/asm-ppc/auxvec.h
++++ /dev/null
+@@ -1,14 +0,0 @@
+-#ifndef __PPC_AUXVEC_H
+-#define __PPC_AUXVEC_H
+-
+-/*
+- * We need to put in some extra aux table entries to tell glibc what
+- * the cache block size is, so it can use the dcbz instruction safely.
+- */
+-#define AT_DCACHEBSIZE 19
+-#define AT_ICACHEBSIZE 20
+-#define AT_UCACHEBSIZE 21
+-/* A special ignored type value for PPC, for glibc compatibility. */
+-#define AT_IGNOREPPC 22
+-
+-#endif
+diff --git a/include/asm-ppc/backlight.h b/include/asm-ppc/backlight.h
+deleted file mode 100644
+--- a/include/asm-ppc/backlight.h
++++ /dev/null
+@@ -1,30 +0,0 @@
+-/*
+- * Routines for handling backlight control on PowerBooks
+- *
+- * For now, implementation resides in arch/ppc/kernel/pmac_support.c
+- *
+- */
+-#ifdef __KERNEL__
+-#ifndef __ASM_PPC_BACKLIGHT_H
+-#define __ASM_PPC_BACKLIGHT_H
+-
+-/* Abstract values */
+-#define BACKLIGHT_OFF 0
+-#define BACKLIGHT_MIN 1
+-#define BACKLIGHT_MAX 0xf
+-
+-struct backlight_controller {
+- int (*set_enable)(int enable, int level, void *data);
+- int (*set_level)(int level, void *data);
+-};
+-
+-extern void register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type);
+-extern void unregister_backlight_controller(struct backlight_controller *ctrler, void *data);
+-
+-extern int set_backlight_enable(int enable);
+-extern int get_backlight_enable(void);
+-extern int set_backlight_level(int level);
+-extern int get_backlight_level(void);
+-
+-#endif
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/bug.h b/include/asm-ppc/bug.h
+deleted file mode 100644
+--- a/include/asm-ppc/bug.h
++++ /dev/null
+@@ -1,58 +0,0 @@
+-#ifndef _PPC_BUG_H
+-#define _PPC_BUG_H
+-
+-struct bug_entry {
+- unsigned long bug_addr;
+- int line;
+- const char *file;
+- const char *function;
+-};
+-
+-/*
+- * If this bit is set in the line number it means that the trap
+- * is for WARN_ON rather than BUG or BUG_ON.
+- */
+-#define BUG_WARNING_TRAP 0x1000000
+-
+-#ifdef CONFIG_BUG
+-#define BUG() do { \
+- __asm__ __volatile__( \
+- "1: twi 31,0,0\n" \
+- ".section __bug_table,\"a\"\n\t" \
+- " .long 1b,%0,%1,%2\n" \
+- ".previous" \
+- : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
+-} while (0)
+-
+-#define BUG_ON(x) do { \
+- if (!__builtin_constant_p(x) || (x)) { \
+- __asm__ __volatile__( \
+- "1: twnei %0,0\n" \
+- ".section __bug_table,\"a\"\n\t" \
+- " .long 1b,%1,%2,%3\n" \
+- ".previous" \
+- : : "r" (x), "i" (__LINE__), "i" (__FILE__), \
+- "i" (__FUNCTION__)); \
+- } \
+-} while (0)
+-
+-#define WARN_ON(x) do { \
+- if (!__builtin_constant_p(x) || (x)) { \
+- __asm__ __volatile__( \
+- "1: twnei %0,0\n" \
+- ".section __bug_table,\"a\"\n\t" \
+- " .long 1b,%1,%2,%3\n" \
+- ".previous" \
+- : : "r" (x), "i" (__LINE__ + BUG_WARNING_TRAP), \
+- "i" (__FILE__), "i" (__FUNCTION__)); \
+- } \
+-} while (0)
+-
+-#define HAVE_ARCH_BUG
+-#define HAVE_ARCH_BUG_ON
+-#define HAVE_ARCH_WARN_ON
+-#endif
+-
+-#include <asm-generic/bug.h>
+-
+-#endif
+diff --git a/include/asm-ppc/byteorder.h b/include/asm-ppc/byteorder.h
+deleted file mode 100644
+--- a/include/asm-ppc/byteorder.h
++++ /dev/null
+@@ -1,76 +0,0 @@
+-#ifndef _PPC_BYTEORDER_H
+-#define _PPC_BYTEORDER_H
+-
+-#include <asm/types.h>
+-#include <linux/compiler.h>
+-
+-#ifdef __GNUC__
+-#ifdef __KERNEL__
+-
+-extern __inline__ unsigned ld_le16(const volatile unsigned short *addr)
+-{
+- unsigned val;
+-
+- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+- return val;
+-}
+-
+-extern __inline__ void st_le16(volatile unsigned short *addr, const unsigned val)
+-{
+- __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+-}
+-
+-extern __inline__ unsigned ld_le32(const volatile unsigned *addr)
+-{
+- unsigned val;
+-
+- __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+- return val;
+-}
+-
+-extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val)
+-{
+- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+-}
+-
+-static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
+-{
+- __u16 result;
+-
+- __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result) : "0" (value >> 8), "r" (value));
+- return result;
+-}
+-
+-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
+-{
+- __u32 result;
+-
+- __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result) : "0" (value>>24), "r" (value));
+- __asm__("rlwimi %0,%2,8,8,15" : "=&r" (result) : "0" (result), "r" (value));
+- __asm__("rlwimi %0,%2,24,0,7" : "=&r" (result) : "0" (result), "r" (value));
+-
+- return result;
+-}
+-#define __arch__swab32(x) ___arch__swab32(x)
+-#define __arch__swab16(x) ___arch__swab16(x)
+-
+-/* The same, but returns converted value from the location pointer by addr. */
+-#define __arch__swab16p(addr) ld_le16(addr)
+-#define __arch__swab32p(addr) ld_le32(addr)
+-
+-/* The same, but do the conversion in situ, ie. put the value back to addr. */
+-#define __arch__swab16s(addr) st_le16(addr,*addr)
+-#define __arch__swab32s(addr) st_le32(addr,*addr)
+-
+-#endif /* __KERNEL__ */
+-
+-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+-# define __BYTEORDER_HAS_U64__
+-# define __SWAB_64_THRU_32__
+-#endif
+-
+-#endif /* __GNUC__ */
+-
+-#include <linux/byteorder/big_endian.h>
+-
+-#endif /* _PPC_BYTEORDER_H */
+diff --git a/include/asm-ppc/cache.h b/include/asm-ppc/cache.h
+--- a/include/asm-ppc/cache.h
++++ b/include/asm-ppc/cache.h
+@@ -9,21 +9,18 @@
+
+ /* bytes per L1 cache line */
+ #if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
+-#define L1_CACHE_LINE_SIZE 16
+-#define LG_L1_CACHE_LINE_SIZE 4
++#define L1_CACHE_SHIFT 4
+ #define MAX_COPY_PREFETCH 1
+ #elif defined(CONFIG_PPC64BRIDGE)
+-#define L1_CACHE_LINE_SIZE 128
+-#define LG_L1_CACHE_LINE_SIZE 7
++#define L1_CACHE_SHIFT 7
+ #define MAX_COPY_PREFETCH 1
+ #else
+-#define L1_CACHE_LINE_SIZE 32
+-#define LG_L1_CACHE_LINE_SIZE 5
++#define L1_CACHE_SHIFT 5
+ #define MAX_COPY_PREFETCH 4
+ #endif
+
+-#define L1_CACHE_BYTES L1_CACHE_LINE_SIZE
+-#define L1_CACHE_SHIFT LG_L1_CACHE_LINE_SIZE
++#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
++
+ #define SMP_CACHE_BYTES L1_CACHE_BYTES
+ #define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */
+
+diff --git a/include/asm-ppc/checksum.h b/include/asm-ppc/checksum.h
+deleted file mode 100644
+--- a/include/asm-ppc/checksum.h
++++ /dev/null
+@@ -1,107 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _PPC_CHECKSUM_H
+-#define _PPC_CHECKSUM_H
+-
+-
+-/*
+- * computes the checksum of a memory block at buff, length len,
+- * and adds in "sum" (32-bit)
+- *
+- * returns a 32-bit number suitable for feeding into itself
+- * or csum_tcpudp_magic
+- *
+- * this function must be called with even lengths, except
+- * for the last fragment, which may be odd
+- *
+- * it's best to have buff aligned on a 32-bit boundary
+- */
+-extern unsigned int csum_partial(const unsigned char * buff, int len,
+- unsigned int sum);
+-
+-/*
+- * Computes the checksum of a memory block at src, length len,
+- * and adds in "sum" (32-bit), while copying the block to dst.
+- * If an access exception occurs on src or dst, it stores -EFAULT
+- * to *src_err or *dst_err respectively (if that pointer is not
+- * NULL), and, for an error on src, zeroes the rest of dst.
+- *
+- * Like csum_partial, this must be called with even lengths,
+- * except for the last fragment.
+- */
+-extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
+- int len, unsigned int sum,
+- int *src_err, int *dst_err);
+-
+-#define csum_partial_copy_from_user(src, dst, len, sum, errp) \
+- csum_partial_copy_generic((__force void *)(src), (dst), (len), (sum), (errp), NULL)
+-
+-/* FIXME: this needs to be written to really do no check -- Cort */
+-#define csum_partial_copy_nocheck(src, dst, len, sum) \
+- csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
+-
+-/*
+- * turns a 32-bit partial checksum (e.g. from csum_partial) into a
+- * 1's complement 16-bit checksum.
+- */
+-static inline unsigned int csum_fold(unsigned int sum)
+-{
+- unsigned int tmp;
+-
+- /* swap the two 16-bit halves of sum */
+- __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum));
+- /* if there is a carry from adding the two 16-bit halves,
+- it will carry from the lower half into the upper half,
+- giving us the correct sum in the upper half. */
+- sum = ~(sum + tmp) >> 16;
+- return sum;
+-}
+-
+-/*
+- * this routine is used for miscellaneous IP-like checksums, mainly
+- * in icmp.c
+- */
+-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+-{
+- return csum_fold(csum_partial(buff, len, 0));
+-}
+-
+-/*
+- * FIXME: I swiped this one from the sparc and made minor modifications.
+- * It may not be correct. -- Cort
+- */
+-static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+- unsigned long daddr,
+- unsigned short len,
+- unsigned short proto,
+- unsigned int sum)
+-{
+- __asm__("\n\
+- addc %0,%0,%1 \n\
+- adde %0,%0,%2 \n\
+- adde %0,%0,%3 \n\
+- addze %0,%0 \n\
+- "
+- : "=r" (sum)
+- : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
+- return sum;
+-}
+-
+-/*
+- * This is a version of ip_compute_csum() optimized for IP headers,
+- * which always checksum on 4 octet boundaries. ihl is the number
+- * of 32-bit words and is always >= 5.
+- */
+-extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+-
+-/*
+- * computes the checksum of the TCP/UDP pseudo-header
+- * returns a 16-bit checksum, already complemented
+- */
+-extern unsigned short csum_tcpudp_magic(unsigned long saddr,
+- unsigned long daddr,
+- unsigned short len,
+- unsigned short proto,
+- unsigned int sum);
+-
+-#endif
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
+--- a/include/asm-ppc/cpm2.h
++++ b/include/asm-ppc/cpm2.h
+@@ -1087,6 +1087,9 @@ typedef struct im_idma {
+ #define SCCR_PCIDF_MSK 0x00000078 /* PCI division factor */
+ #define SCCR_PCIDF_SHIFT 3
+
++#ifndef CPM_IMMR_OFFSET
++#define CPM_IMMR_OFFSET 0x101a8
++#endif
+
+ #endif /* __CPM2__ */
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/cputable.h b/include/asm-ppc/cputable.h
+deleted file mode 100644
+--- a/include/asm-ppc/cputable.h
++++ /dev/null
+@@ -1,129 +0,0 @@
+-/*
+- * include/asm-ppc/cputable.h
+- *
+- * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#ifndef __ASM_PPC_CPUTABLE_H
+-#define __ASM_PPC_CPUTABLE_H
+-
+-/* Exposed to userland CPU features */
+-#define PPC_FEATURE_32 0x80000000
+-#define PPC_FEATURE_64 0x40000000
+-#define PPC_FEATURE_601_INSTR 0x20000000
+-#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
+-#define PPC_FEATURE_HAS_FPU 0x08000000
+-#define PPC_FEATURE_HAS_MMU 0x04000000
+-#define PPC_FEATURE_HAS_4xxMAC 0x02000000
+-#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
+-#define PPC_FEATURE_HAS_SPE 0x00800000
+-#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000
+-#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000
+-#define PPC_FEATURE_NO_TB 0x00100000
+-
+-#ifdef __KERNEL__
+-
+-#ifndef __ASSEMBLY__
+-
+-/* This structure can grow, it's real size is used by head.S code
+- * via the mkdefs mecanism.
+- */
+-struct cpu_spec;
+-
+-typedef void (*cpu_setup_t)(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
+-
+-struct cpu_spec {
+- /* CPU is matched via (PVR & pvr_mask) == pvr_value */
+- unsigned int pvr_mask;
+- unsigned int pvr_value;
+-
+- char *cpu_name;
+- unsigned int cpu_features; /* Kernel features */
+- unsigned int cpu_user_features; /* Userland features */
+-
+- /* cache line sizes */
+- unsigned int icache_bsize;
+- unsigned int dcache_bsize;
+-
+- /* number of performance monitor counters */
+- unsigned int num_pmcs;
+-
+- /* this is called to initialize various CPU bits like L1 cache,
+- * BHT, SPD, etc... from head.S before branching to identify_machine
+- */
+- cpu_setup_t cpu_setup;
+-};
+-
+-extern struct cpu_spec cpu_specs[];
+-extern struct cpu_spec *cur_cpu_spec[];
+-
+-static inline unsigned int cpu_has_feature(unsigned int feature)
+-{
+- return cur_cpu_spec[0]->cpu_features & feature;
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-/* CPU kernel features */
+-#define CPU_FTR_SPLIT_ID_CACHE 0x00000001
+-#define CPU_FTR_L2CR 0x00000002
+-#define CPU_FTR_SPEC7450 0x00000004
+-#define CPU_FTR_ALTIVEC 0x00000008
+-#define CPU_FTR_TAU 0x00000010
+-#define CPU_FTR_CAN_DOZE 0x00000020
+-#define CPU_FTR_USE_TB 0x00000040
+-#define CPU_FTR_604_PERF_MON 0x00000080
+-#define CPU_FTR_601 0x00000100
+-#define CPU_FTR_HPTE_TABLE 0x00000200
+-#define CPU_FTR_CAN_NAP 0x00000400
+-#define CPU_FTR_L3CR 0x00000800
+-#define CPU_FTR_L3_DISABLE_NAP 0x00001000
+-#define CPU_FTR_NAP_DISABLE_L2_PR 0x00002000
+-#define CPU_FTR_DUAL_PLL_750FX 0x00004000
+-#define CPU_FTR_NO_DPM 0x00008000
+-#define CPU_FTR_HAS_HIGH_BATS 0x00010000
+-#define CPU_FTR_NEED_COHERENT 0x00020000
+-#define CPU_FTR_NO_BTIC 0x00040000
+-#define CPU_FTR_BIG_PHYS 0x00080000
+-
+-#ifdef __ASSEMBLY__
+-
+-#define BEGIN_FTR_SECTION 98:
+-
+-#define END_FTR_SECTION(msk, val) \
+-99: \
+- .section __ftr_fixup,"a"; \
+- .align 2; \
+- .long msk; \
+- .long val; \
+- .long 98b; \
+- .long 99b; \
+- .previous
+-
+-#else
+-
+-#define BEGIN_FTR_SECTION "98:\n"
+-#define END_FTR_SECTION(msk, val) \
+-"99:\n" \
+-" .section __ftr_fixup,\"a\";\n" \
+-" .align 2;\n" \
+-" .long "#msk";\n" \
+-" .long "#val";\n" \
+-" .long 98b;\n" \
+-" .long 99b;\n" \
+-" .previous\n"
+-
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk))
+-#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0)
+-
+-#endif /* __ASM_PPC_CPUTABLE_H */
+-#endif /* __KERNEL__ */
+-
+diff --git a/include/asm-ppc/dbdma.h b/include/asm-ppc/dbdma.h
+deleted file mode 100644
+--- a/include/asm-ppc/dbdma.h
++++ /dev/null
+@@ -1,102 +0,0 @@
+-/*
+- * Definitions for using the Apple Descriptor-Based DMA controller
+- * in Power Macintosh computers.
+- *
+- * Copyright (C) 1996 Paul Mackerras.
+- */
+-
+-#ifdef __KERNEL__
+-#ifndef _ASM_DBDMA_H_
+-#define _ASM_DBDMA_H_
+-/*
+- * DBDMA control/status registers. All little-endian.
+- */
+-struct dbdma_regs {
+- unsigned int control; /* lets you change bits in status */
+- unsigned int status; /* DMA and device status bits (see below) */
+- unsigned int cmdptr_hi; /* upper 32 bits of command address */
+- unsigned int cmdptr; /* (lower 32 bits of) command address (phys) */
+- unsigned int intr_sel; /* select interrupt condition bit */
+- unsigned int br_sel; /* select branch condition bit */
+- unsigned int wait_sel; /* select wait condition bit */
+- unsigned int xfer_mode;
+- unsigned int data2ptr_hi;
+- unsigned int data2ptr;
+- unsigned int res1;
+- unsigned int address_hi;
+- unsigned int br_addr_hi;
+- unsigned int res2[3];
+-};
+-
+-/* Bits in control and status registers */
+-#define RUN 0x8000
+-#define PAUSE 0x4000
+-#define FLUSH 0x2000
+-#define WAKE 0x1000
+-#define DEAD 0x0800
+-#define ACTIVE 0x0400
+-#define BT 0x0100
+-#define DEVSTAT 0x00ff
+-
+-/*
+- * DBDMA command structure. These fields are all little-endian!
+- */
+-struct dbdma_cmd {
+- unsigned short req_count; /* requested byte transfer count */
+- unsigned short command; /* command word (has bit-fields) */
+- unsigned int phy_addr; /* physical data address */
+- unsigned int cmd_dep; /* command-dependent field */
+- unsigned short res_count; /* residual count after completion */
+- unsigned short xfer_status; /* transfer status */
+-};
+-
+-/* DBDMA command values in command field */
+-#define OUTPUT_MORE 0 /* transfer memory data to stream */
+-#define OUTPUT_LAST 0x1000 /* ditto followed by end marker */
+-#define INPUT_MORE 0x2000 /* transfer stream data to memory */
+-#define INPUT_LAST 0x3000 /* ditto, expect end marker */
+-#define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */
+-#define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */
+-#define DBDMA_NOP 0x6000 /* do nothing */
+-#define DBDMA_STOP 0x7000 /* suspend processing */
+-
+-/* Key values in command field */
+-#define KEY_STREAM0 0 /* usual data stream */
+-#define KEY_STREAM1 0x100 /* control/status stream */
+-#define KEY_STREAM2 0x200 /* device-dependent stream */
+-#define KEY_STREAM3 0x300 /* device-dependent stream */
+-#define KEY_REGS 0x500 /* device register space */
+-#define KEY_SYSTEM 0x600 /* system memory-mapped space */
+-#define KEY_DEVICE 0x700 /* device memory-mapped space */
+-
+-/* Interrupt control values in command field */
+-#define INTR_NEVER 0 /* don't interrupt */
+-#define INTR_IFSET 0x10 /* intr if condition bit is 1 */
+-#define INTR_IFCLR 0x20 /* intr if condition bit is 0 */
+-#define INTR_ALWAYS 0x30 /* always interrupt */
+-
+-/* Branch control values in command field */
+-#define BR_NEVER 0 /* don't branch */
+-#define BR_IFSET 0x4 /* branch if condition bit is 1 */
+-#define BR_IFCLR 0x8 /* branch if condition bit is 0 */
+-#define BR_ALWAYS 0xc /* always branch */
+-
+-/* Wait control values in command field */
+-#define WAIT_NEVER 0 /* don't wait */
+-#define WAIT_IFSET 1 /* wait if condition bit is 1 */
+-#define WAIT_IFCLR 2 /* wait if condition bit is 0 */
+-#define WAIT_ALWAYS 3 /* always wait */
+-
+-/* Align an address for a DBDMA command structure */
+-#define DBDMA_ALIGN(x) (((unsigned long)(x) + sizeof(struct dbdma_cmd) - 1) \
+- & -sizeof(struct dbdma_cmd))
+-
+-/* Useful macros */
+-#define DBDMA_DO_STOP(regs) do { \
+- out_le32(&((regs)->control), (RUN|FLUSH)<<16); \
+- while(in_le32(&((regs)->status)) & (ACTIVE|FLUSH)) \
+- ; \
+-} while(0)
+-
+-#endif /* _ASM_DBDMA_H_ */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h
+--- 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-ppc/dma.h b/include/asm-ppc/dma.h
+deleted file mode 100644
+--- a/include/asm-ppc/dma.h
++++ /dev/null
+@@ -1,371 +0,0 @@
+-/*
+- * include/asm-ppc/dma.h: Defines for using and allocating dma channels.
+- * Written by Hennus Bergman, 1992.
+- * High DMA channel support & info by Hannu Savolainen
+- * and John Boyd, Nov. 1992.
+- * Changes for ppc sound by Christoph Nadig
+- */
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/config.h>
+-#include <asm/io.h>
+-#include <linux/spinlock.h>
+-#include <asm/system.h>
+-
+-/*
+- * Note: Adapted for PowerPC by Gary Thomas
+- * Modified by Cort Dougan <cort at cs.nmt.edu>
+- *
+- * None of this really applies for Power Macintoshes. There is
+- * basically just enough here to get kernel/dma.c to compile.
+- *
+- * There may be some comments or restrictions made here which are
+- * not valid for the PReP platform. Take what you read
+- * with a grain of salt.
+- */
+-
+-#ifndef _ASM_DMA_H
+-#define _ASM_DMA_H
+-
+-#ifndef MAX_DMA_CHANNELS
+-#define MAX_DMA_CHANNELS 8
+-#endif
+-
+-/* The maximum address that we can perform a DMA transfer to on this platform */
+-/* Doesn't really apply... */
+-#define MAX_DMA_ADDRESS 0xFFFFFFFF
+-
+-/* in arch/ppc/kernel/setup.c -- Cort */
+-extern unsigned long DMA_MODE_WRITE, DMA_MODE_READ;
+-extern unsigned long ISA_DMA_THRESHOLD;
+-
+-#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+-#define dma_outb outb_p
+-#else
+-#define dma_outb outb
+-#endif
+-
+-#define dma_inb inb
+-
+-/*
+- * NOTES about DMA transfers:
+- *
+- * controller 1: channels 0-3, byte operations, ports 00-1F
+- * controller 2: channels 4-7, word operations, ports C0-DF
+- *
+- * - ALL registers are 8 bits only, regardless of transfer size
+- * - channel 4 is not used - cascades 1 into 2.
+- * - channels 0-3 are byte - addresses/counts are for physical bytes
+- * - channels 5-7 are word - addresses/counts are for physical words
+- * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
+- * - transfer count loaded to registers is 1 less than actual count
+- * - controller 2 offsets are all even (2x offsets for controller 1)
+- * - page registers for 5-7 don't use data bit 0, represent 128K pages
+- * - page registers for 0-3 use bit 0, represent 64K pages
+- *
+- * On PReP, DMA transfers are limited to the lower 16MB of _physical_ memory.
+- * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing.
+- * Note that addresses loaded into registers must be _physical_ addresses,
+- * not logical addresses (which may differ if paging is active).
+- *
+- * Address mapping for channels 0-3:
+- *
+- * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses)
+- * | ... | | ... | | ... |
+- * | ... | | ... | | ... |
+- * | ... | | ... | | ... |
+- * P7 ... P0 A7 ... A0 A7 ... A0
+- * | Page | Addr MSB | Addr LSB | (DMA registers)
+- *
+- * Address mapping for channels 5-7:
+- *
+- * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses)
+- * | ... | \ \ ... \ \ \ ... \ \
+- * | ... | \ \ ... \ \ \ ... \ (not used)
+- * | ... | \ \ ... \ \ \ ... \
+- * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0
+- * | Page | Addr MSB | Addr LSB | (DMA registers)
+- *
+- * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
+- * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
+- * the hardware level, so odd-byte transfers aren't possible).
+- *
+- * Transfer count (_not # bytes_) is limited to 64K, represented as actual
+- * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more,
+- * and up to 128K bytes may be transferred on channels 5-7 in one operation.
+- *
+- */
+-
+-/* see prep_setup_arch() for detailed informations */
+-#if defined(CONFIG_SOUND_CS4232) && defined(CONFIG_PPC_PREP)
+-extern long ppc_cs4232_dma, ppc_cs4232_dma2;
+-#define SND_DMA1 ppc_cs4232_dma
+-#define SND_DMA2 ppc_cs4232_dma2
+-#else
+-#define SND_DMA1 -1
+-#define SND_DMA2 -1
+-#endif
+-
+-/* 8237 DMA controllers */
+-#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
+-#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
+-
+-/* DMA controller registers */
+-#define DMA1_CMD_REG 0x08 /* command register (w) */
+-#define DMA1_STAT_REG 0x08 /* status register (r) */
+-#define DMA1_REQ_REG 0x09 /* request register (w) */
+-#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+-#define DMA1_MODE_REG 0x0B /* mode register (w) */
+-#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+-#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+-#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+-#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+-#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+-
+-#define DMA2_CMD_REG 0xD0 /* command register (w) */
+-#define DMA2_STAT_REG 0xD0 /* status register (r) */
+-#define DMA2_REQ_REG 0xD2 /* request register (w) */
+-#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+-#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+-#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+-#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+-#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+-#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+-#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+-
+-#define DMA_ADDR_0 0x00 /* DMA address registers */
+-#define DMA_ADDR_1 0x02
+-#define DMA_ADDR_2 0x04
+-#define DMA_ADDR_3 0x06
+-#define DMA_ADDR_4 0xC0
+-#define DMA_ADDR_5 0xC4
+-#define DMA_ADDR_6 0xC8
+-#define DMA_ADDR_7 0xCC
+-
+-#define DMA_CNT_0 0x01 /* DMA count registers */
+-#define DMA_CNT_1 0x03
+-#define DMA_CNT_2 0x05
+-#define DMA_CNT_3 0x07
+-#define DMA_CNT_4 0xC2
+-#define DMA_CNT_5 0xC6
+-#define DMA_CNT_6 0xCA
+-#define DMA_CNT_7 0xCE
+-
+-#define DMA_LO_PAGE_0 0x87 /* DMA page registers */
+-#define DMA_LO_PAGE_1 0x83
+-#define DMA_LO_PAGE_2 0x81
+-#define DMA_LO_PAGE_3 0x82
+-#define DMA_LO_PAGE_5 0x8B
+-#define DMA_LO_PAGE_6 0x89
+-#define DMA_LO_PAGE_7 0x8A
+-
+-#define DMA_HI_PAGE_0 0x487 /* DMA page registers */
+-#define DMA_HI_PAGE_1 0x483
+-#define DMA_HI_PAGE_2 0x481
+-#define DMA_HI_PAGE_3 0x482
+-#define DMA_HI_PAGE_5 0x48B
+-#define DMA_HI_PAGE_6 0x489
+-#define DMA_HI_PAGE_7 0x48A
+-
+-#define DMA1_EXT_REG 0x40B
+-#define DMA2_EXT_REG 0x4D6
+-
+-#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
+-#define DMA_AUTOINIT 0x10
+-
+-extern spinlock_t dma_spin_lock;
+-
+-static __inline__ unsigned long claim_dma_lock(void)
+-{
+- unsigned long flags;
+- spin_lock_irqsave(&dma_spin_lock, flags);
+- return flags;
+-}
+-
+-static __inline__ void release_dma_lock(unsigned long flags)
+-{
+- spin_unlock_irqrestore(&dma_spin_lock, flags);
+-}
+-
+-/* enable/disable a specific DMA channel */
+-static __inline__ void enable_dma(unsigned int dmanr)
+-{
+- unsigned char ucDmaCmd = 0x00;
+-
+- if (dmanr != 4) {
+- dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */
+- dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */
+- }
+- if (dmanr <= 3) {
+- dma_outb(dmanr, DMA1_MASK_REG);
+- dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */
+- } else
+- dma_outb(dmanr & 3, DMA2_MASK_REG);
+-}
+-
+-static __inline__ void disable_dma(unsigned int dmanr)
+-{
+- if (dmanr <= 3)
+- dma_outb(dmanr | 4, DMA1_MASK_REG);
+- else
+- dma_outb((dmanr & 3) | 4, DMA2_MASK_REG);
+-}
+-
+-/* Clear the 'DMA Pointer Flip Flop'.
+- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+- * Use this once to initialize the FF to a known state.
+- * After that, keep track of it. :-)
+- * --- In order to do that, the DMA routines below should ---
+- * --- only be used while interrupts are disabled! ---
+- */
+-static __inline__ void clear_dma_ff(unsigned int dmanr)
+-{
+- if (dmanr <= 3)
+- dma_outb(0, DMA1_CLEAR_FF_REG);
+- else
+- dma_outb(0, DMA2_CLEAR_FF_REG);
+-}
+-
+-/* set mode (above) for a specific DMA channel */
+-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+-{
+- if (dmanr <= 3)
+- dma_outb(mode | dmanr, DMA1_MODE_REG);
+- else
+- dma_outb(mode | (dmanr & 3), DMA2_MODE_REG);
+-}
+-
+-/* Set only the page register bits of the transfer address.
+- * This is used for successive transfers when we know the contents of
+- * the lower 16 bits of the DMA current address register, but a 64k boundary
+- * may have been crossed.
+- */
+-static __inline__ void set_dma_page(unsigned int dmanr, int pagenr)
+-{
+- switch (dmanr) {
+- case 0:
+- dma_outb(pagenr, DMA_LO_PAGE_0);
+- dma_outb(pagenr >> 8, DMA_HI_PAGE_0);
+- break;
+- case 1:
+- dma_outb(pagenr, DMA_LO_PAGE_1);
+- dma_outb(pagenr >> 8, DMA_HI_PAGE_1);
+- break;
+- case 2:
+- dma_outb(pagenr, DMA_LO_PAGE_2);
+- dma_outb(pagenr >> 8, DMA_HI_PAGE_2);
+- break;
+- case 3:
+- dma_outb(pagenr, DMA_LO_PAGE_3);
+- dma_outb(pagenr >> 8, DMA_HI_PAGE_3);
+- break;
+- case 5:
+- if (SND_DMA1 == 5 || SND_DMA2 == 5)
+- dma_outb(pagenr, DMA_LO_PAGE_5);
+- else
+- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
+- dma_outb(pagenr >> 8, DMA_HI_PAGE_5);
+- break;
+- case 6:
+- if (SND_DMA1 == 6 || SND_DMA2 == 6)
+- dma_outb(pagenr, DMA_LO_PAGE_6);
+- else
+- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
+- dma_outb(pagenr >> 8, DMA_HI_PAGE_6);
+- break;
+- case 7:
+- if (SND_DMA1 == 7 || SND_DMA2 == 7)
+- dma_outb(pagenr, DMA_LO_PAGE_7);
+- else
+- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
+- dma_outb(pagenr >> 8, DMA_HI_PAGE_7);
+- break;
+- }
+-}
+-
+-/* Set transfer address & page bits for specific DMA channel.
+- * Assumes dma flipflop is clear.
+- */
+-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys)
+-{
+- if (dmanr <= 3) {
+- dma_outb(phys & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
+- dma_outb((phys >> 8) & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
+- } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
+- dma_outb(phys & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+- dma_outb((phys >> 8) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+- dma_outb((dmanr & 3), DMA2_EXT_REG);
+- } else {
+- dma_outb((phys >> 1) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+- dma_outb((phys >> 9) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+- }
+- set_dma_page(dmanr, phys >> 16);
+-}
+-
+-/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
+- * a specific DMA channel.
+- * You must ensure the parameters are valid.
+- * NOTE: from a manual: "the number of transfers is one more
+- * than the initial word count"! This is taken into account.
+- * Assumes dma flip-flop is clear.
+- * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+- */
+-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+-{
+- count--;
+- if (dmanr <= 3) {
+- dma_outb(count & 0xff, ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
+- dma_outb((count >> 8) & 0xff, ((dmanr & 3) << 1) + 1 +
+- IO_DMA1_BASE);
+- } else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
+- dma_outb(count & 0xff, ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
+- dma_outb((count >> 8) & 0xff, ((dmanr & 3) << 2) + 2 +
+- IO_DMA2_BASE);
+- } else {
+- dma_outb((count >> 1) & 0xff, ((dmanr & 3) << 2) + 2 +
+- IO_DMA2_BASE);
+- dma_outb((count >> 9) & 0xff, ((dmanr & 3) << 2) + 2 +
+- IO_DMA2_BASE);
+- }
+-}
+-
+-/* Get DMA residue count. After a DMA transfer, this
+- * should return zero. Reading this while a DMA transfer is
+- * still in progress will return unpredictable results.
+- * If called before the channel has been used, it may return 1.
+- * Otherwise, it returns the number of _bytes_ left to transfer.
+- *
+- * Assumes DMA flip-flop is clear.
+- */
+-static __inline__ int get_dma_residue(unsigned int dmanr)
+-{
+- unsigned int io_port = (dmanr <= 3) ?
+- ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE
+- : ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE;
+-
+- /* using short to get 16-bit wrap around */
+- unsigned short count;
+-
+- count = 1 + dma_inb(io_port);
+- count += dma_inb(io_port) << 8;
+-
+- return (dmanr <= 3 || dmanr == SND_DMA1 || dmanr == SND_DMA2)
+- ? count : (count << 1);
+-
+-}
+-
+-/* These are in kernel/dma.c: */
+-
+-/* reserve a DMA channel */
+-extern int request_dma(unsigned int dmanr, const char *device_id);
+-/* release it again */
+-extern void free_dma(unsigned int dmanr);
+-
+-#ifdef CONFIG_PCI
+-extern int isa_dma_bridge_buggy;
+-#else
+-#define isa_dma_bridge_buggy (0)
+-#endif
+-#endif /* _ASM_DMA_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/elf.h b/include/asm-ppc/elf.h
+deleted file mode 100644
+--- a/include/asm-ppc/elf.h
++++ /dev/null
+@@ -1,151 +0,0 @@
+-#ifndef __PPC_ELF_H
+-#define __PPC_ELF_H
+-
+-/*
+- * ELF register definitions..
+- */
+-#include <asm/types.h>
+-#include <asm/ptrace.h>
+-#include <asm/cputable.h>
+-#include <asm/auxvec.h>
+-
+-/* PowerPC relocations defined by the ABIs */
+-#define R_PPC_NONE 0
+-#define R_PPC_ADDR32 1 /* 32bit absolute address */
+-#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+-#define R_PPC_ADDR16 3 /* 16bit absolute address */
+-#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+-#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+-#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+-#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+-#define R_PPC_ADDR14_BRTAKEN 8
+-#define R_PPC_ADDR14_BRNTAKEN 9
+-#define R_PPC_REL24 10 /* PC relative 26 bit */
+-#define R_PPC_REL14 11 /* PC relative 16 bit */
+-#define R_PPC_REL14_BRTAKEN 12
+-#define R_PPC_REL14_BRNTAKEN 13
+-#define R_PPC_GOT16 14
+-#define R_PPC_GOT16_LO 15
+-#define R_PPC_GOT16_HI 16
+-#define R_PPC_GOT16_HA 17
+-#define R_PPC_PLTREL24 18
+-#define R_PPC_COPY 19
+-#define R_PPC_GLOB_DAT 20
+-#define R_PPC_JMP_SLOT 21
+-#define R_PPC_RELATIVE 22
+-#define R_PPC_LOCAL24PC 23
+-#define R_PPC_UADDR32 24
+-#define R_PPC_UADDR16 25
+-#define R_PPC_REL32 26
+-#define R_PPC_PLT32 27
+-#define R_PPC_PLTREL32 28
+-#define R_PPC_PLT16_LO 29
+-#define R_PPC_PLT16_HI 30
+-#define R_PPC_PLT16_HA 31
+-#define R_PPC_SDAREL16 32
+-#define R_PPC_SECTOFF 33
+-#define R_PPC_SECTOFF_LO 34
+-#define R_PPC_SECTOFF_HI 35
+-#define R_PPC_SECTOFF_HA 36
+-/* Keep this the last entry. */
+-#define R_PPC_NUM 37
+-
+-#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
+-#define ELF_NFPREG 33 /* includes fpscr */
+-#define ELF_NVRREG 33 /* includes vscr */
+-#define ELF_NEVRREG 34 /* includes acc (as 2) */
+-
+-/*
+- * These are used to set parameters in the core dumps.
+- */
+-#define ELF_ARCH EM_PPC
+-#define ELF_CLASS ELFCLASS32
+-#define ELF_DATA ELFDATA2MSB
+-
+-/* General registers */
+-typedef unsigned long elf_greg_t;
+-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+-
+-/* Floating point registers */
+-typedef double elf_fpreg_t;
+-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+-
+-/* Altivec registers */
+-typedef __vector128 elf_vrreg_t;
+-typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG];
+-
+-#ifdef __KERNEL__
+-
+-struct task_struct;
+-
+-/*
+- * This is used to ensure we don't load something for the wrong architecture.
+- */
+-
+-#define elf_check_arch(x) ((x)->e_machine == EM_PPC)
+-
+-/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+- use of this is to invoke "./ld.so someprog" to test out a new version of
+- the loader. We need to make sure that it is out of the way of the program
+- that it will "exec", and that there is sufficient room for the brk. */
+-
+-#define ELF_ET_DYN_BASE (0x08000000)
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 4096
+-
+-#define ELF_CORE_COPY_REGS(gregs, regs) \
+- memcpy((gregs), (regs), sizeof(struct pt_regs)); \
+- memset((char *)(gregs) + sizeof(struct pt_regs), 0, \
+- sizeof(elf_gregset_t) - sizeof(struct pt_regs));
+-
+-#define ELF_CORE_COPY_TASK_REGS(t, elfregs) \
+- ((t)->thread.regs? \
+- ({ ELF_CORE_COPY_REGS((elfregs), (t)->thread.regs); 1; }): 0)
+-
+-extern int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpu);
+-#define ELF_CORE_COPY_FPREGS(t, fpu) dump_task_fpu((t), (fpu))
+-
+-/* This yields a mask that user programs can use to figure out what
+- instruction set this cpu supports. This could be done in userspace,
+- but it's not easy, and we've already done it here. */
+-
+-#define ELF_HWCAP (cur_cpu_spec[0]->cpu_user_features)
+-
+-/* This yields a string that ld.so will use to load implementation
+- specific libraries for optimization. This is more specific in
+- intent than poking at uname or /proc/cpuinfo.
+-
+- For the moment, we have only optimizations for the Intel generations,
+- but that could change... */
+-
+-#define ELF_PLATFORM (NULL)
+-
+-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+-
+-extern int dcache_bsize;
+-extern int icache_bsize;
+-extern int ucache_bsize;
+-
+-/*
+- * The requirements here are:
+- * - keep the final alignment of sp (sp & 0xf)
+- * - make sure the 32-bit value at the first 16 byte aligned position of
+- * AUXV is greater than 16 for glibc compatibility.
+- * AT_IGNOREPPC is used for that.
+- * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+- * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+- */
+-#define ARCH_DLINFO \
+-do { \
+- /* Handle glibc compatibility. */ \
+- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+- /* Cache size items */ \
+- NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
+- NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
+- NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
+- } while (0)
+-
+-#endif /* __KERNEL__ */
+-#endif
+diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h
+deleted file mode 100644
+--- a/include/asm-ppc/hardirq.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef __ASM_HARDIRQ_H
+-#define __ASM_HARDIRQ_H
+-
+-#include <linux/config.h>
+-#include <linux/cache.h>
+-#include <linux/smp_lock.h>
+-#include <asm/irq.h>
+-
+-/* The __last_jiffy_stamp field is needed to ensure that no decrementer
+- * interrupt is lost on SMP machines. Since on most CPUs it is in the same
+- * cache line as local_irq_count, it is cheap to access and is also used on UP
+- * for uniformity.
+- */
+-typedef struct {
+- unsigned long __softirq_pending; /* set_bit is used on this */
+- unsigned int __last_jiffy_stamp;
+-} ____cacheline_aligned irq_cpustat_t;
+-
+-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+-
+-#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp)
+-
+-static inline void ack_bad_irq(int irq)
+-{
+- printk(KERN_CRIT "illegal vector %d received!\n", irq);
+- BUG();
+-}
+-
+-#endif /* __ASM_HARDIRQ_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/heathrow.h b/include/asm-ppc/heathrow.h
+deleted file mode 100644
+--- a/include/asm-ppc/heathrow.h
++++ /dev/null
+@@ -1,62 +0,0 @@
+-/*
+- * heathrow.h: definitions for using the "Heathrow" I/O controller chip.
+- *
+- * Grabbed from Open Firmware definitions on a PowerBook G3 Series
+- *
+- * Copyright (C) 1997 Paul Mackerras.
+- */
+-
+-/* Front light color on Yikes/B&W G3. 32 bits */
+-#define HEATHROW_FRONT_LIGHT 0x32 /* (set to 0 or 0xffffffff) */
+-
+-/* Brightness/contrast (gossamer iMac ?). 8 bits */
+-#define HEATHROW_BRIGHTNESS_CNTL 0x32
+-#define HEATHROW_CONTRAST_CNTL 0x33
+-
+-/* offset from ohare base for feature control register */
+-#define HEATHROW_MBCR 0x34 /* Media bay control */
+-#define HEATHROW_FCR 0x38 /* Feature control */
+-#define HEATHROW_AUX_CNTL_REG 0x3c /* Aux control */
+-
+-/*
+- * Bits in feature control register.
+- * Bits postfixed with a _N are in inverse logic
+- */
+-#define HRW_SCC_TRANS_EN_N 0x00000001 /* Also controls modem power */
+-#define HRW_BAY_POWER_N 0x00000002
+-#define HRW_BAY_PCI_ENABLE 0x00000004
+-#define HRW_BAY_IDE_ENABLE 0x00000008
+-#define HRW_BAY_FLOPPY_ENABLE 0x00000010
+-#define HRW_IDE0_ENABLE 0x00000020
+-#define HRW_IDE0_RESET_N 0x00000040
+-#define HRW_BAY_DEV_MASK 0x0000001c
+-#define HRW_BAY_RESET_N 0x00000080
+-#define HRW_IOBUS_ENABLE 0x00000100 /* Internal IDE ? */
+-#define HRW_SCC_ENABLE 0x00000200
+-#define HRW_MESH_ENABLE 0x00000400
+-#define HRW_SWIM_ENABLE 0x00000800
+-#define HRW_SOUND_POWER_N 0x00001000
+-#define HRW_SOUND_CLK_ENABLE 0x00002000
+-#define HRW_SCCA_IO 0x00004000
+-#define HRW_SCCB_IO 0x00008000
+-#define HRW_PORT_OR_DESK_VIA_N 0x00010000 /* This one is 0 on PowerBook */
+-#define HRW_PWM_MON_ID_N 0x00020000 /* ??? (0) */
+-#define HRW_HOOK_MB_CNT_N 0x00040000 /* ??? (0) */
+-#define HRW_SWIM_CLONE_FLOPPY 0x00080000 /* ??? (0) */
+-#define HRW_AUD_RUN22 0x00100000 /* ??? (1) */
+-#define HRW_SCSI_LINK_MODE 0x00200000 /* Read ??? (1) */
+-#define HRW_ARB_BYPASS 0x00400000 /* Disable internal PCI arbitrer */
+-#define HRW_IDE1_RESET_N 0x00800000 /* Media bay */
+-#define HRW_SLOW_SCC_PCLK 0x01000000 /* ??? (0) */
+-#define HRW_RESET_SCC 0x02000000
+-#define HRW_MFDC_CELL_ENABLE 0x04000000 /* ??? (0) */
+-#define HRW_USE_MFDC 0x08000000 /* ??? (0) */
+-#define HRW_BMAC_IO_ENABLE 0x60000000 /* two bits, not documented in OF */
+-#define HRW_BMAC_RESET 0x80000000 /* not documented in OF */
+-
+-/* We OR those features at boot on desktop G3s */
+-#define HRW_DEFAULTS (HRW_SCCA_IO | HRW_SCCB_IO | HRW_SCC_ENABLE)
+-
+-/* Looks like Heathrow has some sort of GPIOs as well... */
+-#define HRW_GPIO_MODEM_RESET 0x6d
+-
+diff --git a/include/asm-ppc/hw_irq.h b/include/asm-ppc/hw_irq.h
+deleted file mode 100644
+--- a/include/asm-ppc/hw_irq.h
++++ /dev/null
+@@ -1,74 +0,0 @@
+-/*
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- */
+-#ifdef __KERNEL__
+-#ifndef _PPC_HW_IRQ_H
+-#define _PPC_HW_IRQ_H
+-
+-#include <asm/ptrace.h>
+-#include <asm/reg.h>
+-
+-extern void timer_interrupt(struct pt_regs *);
+-
+-#define INLINE_IRQS
+-
+-#define irqs_disabled() ((mfmsr() & MSR_EE) == 0)
+-
+-#ifdef INLINE_IRQS
+-
+-static inline void local_irq_disable(void)
+-{
+- unsigned long msr;
+- msr = mfmsr();
+- mtmsr(msr & ~MSR_EE);
+- __asm__ __volatile__("": : :"memory");
+-}
+-
+-static inline void local_irq_enable(void)
+-{
+- unsigned long msr;
+- __asm__ __volatile__("": : :"memory");
+- msr = mfmsr();
+- mtmsr(msr | MSR_EE);
+-}
+-
+-static inline void local_irq_save_ptr(unsigned long *flags)
+-{
+- unsigned long msr;
+- msr = mfmsr();
+- *flags = msr;
+- mtmsr(msr & ~MSR_EE);
+- __asm__ __volatile__("": : :"memory");
+-}
+-
+-#define local_save_flags(flags) ((flags) = mfmsr())
+-#define local_irq_save(flags) local_irq_save_ptr(&flags)
+-#define local_irq_restore(flags) mtmsr(flags)
+-
+-#else
+-
+-extern void local_irq_enable(void);
+-extern void local_irq_disable(void);
+-extern void local_irq_restore(unsigned long);
+-extern void local_save_flags_ptr(unsigned long *);
+-
+-#define local_save_flags(flags) local_save_flags_ptr(&flags)
+-#define local_irq_save(flags) ({local_save_flags(flags);local_irq_disable();})
+-
+-#endif
+-
+-extern void do_lost_interrupts(unsigned long);
+-
+-#define mask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->disable) irq_desc[irq].handler->disable(irq);})
+-#define unmask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->enable) irq_desc[irq].handler->enable(irq);})
+-#define ack_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->ack) irq_desc[irq].handler->ack(irq);})
+-
+-/* Should we handle this via lost interrupts and IPIs or should we don't care like
+- * we do now ? --BenH.
+- */
+-struct hw_interrupt_type;
+-static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
+-
+-
+-#endif /* _PPC_HW_IRQ_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/i8259.h b/include/asm-ppc/i8259.h
+deleted file mode 100644
+--- a/include/asm-ppc/i8259.h
++++ /dev/null
+@@ -1,11 +0,0 @@
+-#ifndef _PPC_KERNEL_i8259_H
+-#define _PPC_KERNEL_i8259_H
+-
+-#include <linux/irq.h>
+-
+-extern struct hw_interrupt_type i8259_pic;
+-
+-extern void i8259_init(long intack_addr);
+-extern int i8259_irq(struct pt_regs *regs);
+-
+-#endif /* _PPC_KERNEL_i8259_H */
+diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
+--- a/include/asm-ppc/io.h
++++ b/include/asm-ppc/io.h
+@@ -8,6 +8,7 @@
+
+ #include <asm/page.h>
+ #include <asm/byteorder.h>
++#include <asm/synch.h>
+ #include <asm/mmu.h>
+
+ #define SIO_CONFIG_RA 0x398
+@@ -440,16 +441,6 @@ extern inline void * phys_to_virt(unsign
+ #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+ #define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET)
+
+-/*
+- * Enforce In-order Execution of I/O:
+- * Acts as a barrier to ensure all previous I/O accesses have
+- * completed before any further ones are issued.
+- */
+-extern inline void eieio(void)
+-{
+- __asm__ __volatile__ ("eieio" : : : "memory");
+-}
+-
+ /* Enforce in-order execution of data I/O.
+ * No distinction between read/write on PPC; use eieio for all three.
+ */
+diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
+deleted file mode 100644
+--- a/include/asm-ppc/irq.h
++++ /dev/null
+@@ -1,418 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_IRQ_H
+-#define _ASM_IRQ_H
+-
+-#include <linux/config.h>
+-#include <asm/machdep.h> /* ppc_md */
+-#include <asm/atomic.h>
+-
+-/*
+- * These constants are used for passing information about interrupt
+- * signal polarity and level/edge sensing to the low-level PIC chip
+- * drivers.
+- */
+-#define IRQ_SENSE_MASK 0x1
+-#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */
+-#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */
+-
+-#define IRQ_POLARITY_MASK 0x2
+-#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */
+-#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */
+-
+-/*
+- * IRQ line status macro IRQ_PER_CPU is used
+- */
+-#define ARCH_HAS_IRQ_PER_CPU
+-
+-#if defined(CONFIG_40x)
+-#include <asm/ibm4xx.h>
+-
+-#ifndef NR_BOARD_IRQS
+-#define NR_BOARD_IRQS 0
+-#endif
+-
+-#ifndef UIC_WIDTH /* Number of interrupts per device */
+-#define UIC_WIDTH 32
+-#endif
+-
+-#ifndef NR_UICS /* number of UIC devices */
+-#define NR_UICS 1
+-#endif
+-
+-#if defined (CONFIG_403)
+-/*
+- * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
+- * 32 possible interrupts, a majority of which are not implemented on
+- * all cores. There are six configurable, external interrupt pins and
+- * there are eight internal interrupts for the on-chip serial port
+- * (SPU), DMA controller, and JTAG controller.
+- *
+- */
+-
+-#define NR_AIC_IRQS 32
+-#define NR_IRQS (NR_AIC_IRQS + NR_BOARD_IRQS)
+-
+-#elif !defined (CONFIG_403)
+-
+-/*
+- * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32
+- * possible interrupts as well. There are seven, configurable external
+- * interrupt pins and there are 17 internal interrupts for the on-chip
+- * serial port, DMA controller, on-chip Ethernet controller, PCI, etc.
+- *
+- */
+-
+-
+-#define NR_UIC_IRQS UIC_WIDTH
+-#define NR_IRQS ((NR_UIC_IRQS * NR_UICS) + NR_BOARD_IRQS)
+-#endif
+-static __inline__ int
+-irq_canonicalize(int irq)
+-{
+- return (irq);
+-}
+-
+-#elif defined(CONFIG_44x)
+-#include <asm/ibm44x.h>
+-
+-#define NR_UIC_IRQS 32
+-#define NR_IRQS ((NR_UIC_IRQS * NR_UICS) + NR_BOARD_IRQS)
+-
+-static __inline__ int
+-irq_canonicalize(int irq)
+-{
+- return (irq);
+-}
+-
+-#elif defined(CONFIG_8xx)
+-
+-/* Now include the board configuration specific associations.
+-*/
+-#include <asm/mpc8xx.h>
+-
+-/* The MPC8xx cores have 16 possible interrupts. There are eight
+- * possible level sensitive interrupts assigned and generated internally
+- * from such devices as CPM, PCMCIA, RTC, PIT, TimeBase and Decrementer.
+- * There are eight external interrupts (IRQs) that can be configured
+- * as either level or edge sensitive.
+- *
+- * On some implementations, there is also the possibility of an 8259
+- * through the PCI and PCI-ISA bridges.
+- *
+- * We are "flattening" the interrupt vectors of the cascaded CPM
+- * and 8259 interrupt controllers so that we can uniquely identify
+- * any interrupt source with a single integer.
+- */
+-#define NR_SIU_INTS 16
+-#define NR_CPM_INTS 32
+-#ifndef NR_8259_INTS
+-#define NR_8259_INTS 0
+-#endif
+-
+-#define SIU_IRQ_OFFSET 0
+-#define CPM_IRQ_OFFSET (SIU_IRQ_OFFSET + NR_SIU_INTS)
+-#define I8259_IRQ_OFFSET (CPM_IRQ_OFFSET + NR_CPM_INTS)
+-
+-#define NR_IRQS (NR_SIU_INTS + NR_CPM_INTS + NR_8259_INTS)
+-
+-/* These values must be zero-based and map 1:1 with the SIU configuration.
+- * They are used throughout the 8xx I/O subsystem to generate
+- * interrupt masks, flags, and other control patterns. This is why the
+- * current kernel assumption of the 8259 as the base controller is such
+- * a pain in the butt.
+- */
+-#define SIU_IRQ0 (0) /* Highest priority */
+-#define SIU_LEVEL0 (1)
+-#define SIU_IRQ1 (2)
+-#define SIU_LEVEL1 (3)
+-#define SIU_IRQ2 (4)
+-#define SIU_LEVEL2 (5)
+-#define SIU_IRQ3 (6)
+-#define SIU_LEVEL3 (7)
+-#define SIU_IRQ4 (8)
+-#define SIU_LEVEL4 (9)
+-#define SIU_IRQ5 (10)
+-#define SIU_LEVEL5 (11)
+-#define SIU_IRQ6 (12)
+-#define SIU_LEVEL6 (13)
+-#define SIU_IRQ7 (14)
+-#define SIU_LEVEL7 (15)
+-
+-#define MPC8xx_INT_FEC1 SIU_LEVEL1
+-#define MPC8xx_INT_FEC2 SIU_LEVEL3
+-
+-#define MPC8xx_INT_SCC1 (CPM_IRQ_OFFSET + CPMVEC_SCC1)
+-#define MPC8xx_INT_SCC2 (CPM_IRQ_OFFSET + CPMVEC_SCC2)
+-#define MPC8xx_INT_SCC3 (CPM_IRQ_OFFSET + CPMVEC_SCC3)
+-#define MPC8xx_INT_SCC4 (CPM_IRQ_OFFSET + CPMVEC_SCC4)
+-#define MPC8xx_INT_SMC1 (CPM_IRQ_OFFSET + CPMVEC_SMC1)
+-#define MPC8xx_INT_SMC2 (CPM_IRQ_OFFSET + CPMVEC_SMC2)
+-
+-/* The internal interrupts we can configure as we see fit.
+- * My personal preference is CPM at level 2, which puts it above the
+- * MBX PCI/ISA/IDE interrupts.
+- */
+-#ifndef PIT_INTERRUPT
+-#define PIT_INTERRUPT SIU_LEVEL0
+-#endif
+-#ifndef CPM_INTERRUPT
+-#define CPM_INTERRUPT SIU_LEVEL2
+-#endif
+-#ifndef PCMCIA_INTERRUPT
+-#define PCMCIA_INTERRUPT SIU_LEVEL6
+-#endif
+-#ifndef DEC_INTERRUPT
+-#define DEC_INTERRUPT SIU_LEVEL7
+-#endif
+-
+-/* Some internal interrupt registers use an 8-bit mask for the interrupt
+- * level instead of a number.
+- */
+-#define mk_int_int_mask(IL) (1 << (7 - (IL/2)))
+-
+-/* always the same on 8xx -- Cort */
+-static __inline__ int irq_canonicalize(int irq)
+-{
+- return irq;
+-}
+-
+-#elif defined(CONFIG_83xx)
+-#include <asm/mpc83xx.h>
+-
+-static __inline__ int irq_canonicalize(int irq)
+-{
+- return irq;
+-}
+-
+-#define NR_IRQS (NR_IPIC_INTS)
+-
+-#elif defined(CONFIG_85xx)
+-/* Now include the board configuration specific associations.
+-*/
+-#include <asm/mpc85xx.h>
+-
+-/* The MPC8548 openpic has 48 internal interrupts and 12 external
+- * interrupts.
+- *
+- * We are "flattening" the interrupt vectors of the cascaded CPM
+- * so that we can uniquely identify any interrupt source with a
+- * single integer.
+- */
+-#define NR_CPM_INTS 64
+-#define NR_EPIC_INTS 60
+-#ifndef NR_8259_INTS
+-#define NR_8259_INTS 0
+-#endif
+-#define NUM_8259_INTERRUPTS NR_8259_INTS
+-
+-#ifndef CPM_IRQ_OFFSET
+-#define CPM_IRQ_OFFSET 0
+-#endif
+-
+-#define NR_IRQS (NR_EPIC_INTS + NR_CPM_INTS + NR_8259_INTS)
+-
+-/* Internal IRQs on MPC85xx OpenPIC */
+-
+-#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
+-#ifdef CONFIG_CPM2
+-#define MPC85xx_OPENPIC_IRQ_OFFSET (CPM_IRQ_OFFSET + NR_CPM_INTS)
+-#else
+-#define MPC85xx_OPENPIC_IRQ_OFFSET 0
+-#endif
+-#endif
+-
+-/* Not all of these exist on all MPC85xx implementations */
+-#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC3_TX (15 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC3_RX (16 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC3_ERROR (17 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC4_TX (21 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC4_RX (22 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC4_ERROR (23 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-
+-/* The 12 external interrupt lines */
+-#define MPC85xx_IRQ_EXT0 (48 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT1 (49 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT2 (50 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT3 (51 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT4 (52 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT5 (53 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT6 (54 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT7 (55 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT8 (56 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT9 (57 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT10 (58 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-#define MPC85xx_IRQ_EXT11 (59 + MPC85xx_OPENPIC_IRQ_OFFSET)
+-
+-/* CPM related interrupts */
+-#define SIU_INT_ERROR ((uint)0x00+CPM_IRQ_OFFSET)
+-#define SIU_INT_I2C ((uint)0x01+CPM_IRQ_OFFSET)
+-#define SIU_INT_SPI ((uint)0x02+CPM_IRQ_OFFSET)
+-#define SIU_INT_RISC ((uint)0x03+CPM_IRQ_OFFSET)
+-#define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET)
+-#define SIU_INT_SMC2 ((uint)0x05+CPM_IRQ_OFFSET)
+-#define SIU_INT_USB ((uint)0x0b+CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER1 ((uint)0x0c+CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER2 ((uint)0x0d+CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER3 ((uint)0x0e+CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER4 ((uint)0x0f+CPM_IRQ_OFFSET)
+-#define SIU_INT_FCC1 ((uint)0x20+CPM_IRQ_OFFSET)
+-#define SIU_INT_FCC2 ((uint)0x21+CPM_IRQ_OFFSET)
+-#define SIU_INT_FCC3 ((uint)0x22+CPM_IRQ_OFFSET)
+-#define SIU_INT_MCC1 ((uint)0x24+CPM_IRQ_OFFSET)
+-#define SIU_INT_MCC2 ((uint)0x25+CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC15 ((uint)0x30+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC14 ((uint)0x31+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC13 ((uint)0x32+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC12 ((uint)0x33+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC11 ((uint)0x34+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC10 ((uint)0x35+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC9 ((uint)0x36+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC8 ((uint)0x37+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC7 ((uint)0x38+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC6 ((uint)0x39+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC5 ((uint)0x3a+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC4 ((uint)0x3b+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC3 ((uint)0x3c+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC2 ((uint)0x3d+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC1 ((uint)0x3e+CPM_IRQ_OFFSET)
+-#define SIU_INT_PC0 ((uint)0x3f+CPM_IRQ_OFFSET)
+-
+-static __inline__ int irq_canonicalize(int irq)
+-{
+- return irq;
+-}
+-
+-#else /* CONFIG_40x + CONFIG_8xx */
+-/*
+- * this is the # irq's for all ppc arch's (pmac/chrp/prep)
+- * so it is the max of them all
+- */
+-#define NR_IRQS 256
+-
+-#ifndef CONFIG_8260
+-
+-#define NUM_8259_INTERRUPTS 16
+-
+-#else /* CONFIG_8260 */
+-
+-/* The 8260 has an internal interrupt controller with a maximum of
+- * 64 IRQs. We will use NR_IRQs from above since it is large enough.
+- * Don't be confused by the 8260 documentation where they list an
+- * "interrupt number" and "interrupt vector". We are only interested
+- * in the interrupt vector. There are "reserved" holes where the
+- * vector number increases, but the interrupt number in the table does not.
+- * (Document errata updates have fixed this...make sure you have up to
+- * date processor documentation -- Dan).
+- */
+-
+-#ifndef CPM_IRQ_OFFSET
+-#define CPM_IRQ_OFFSET 0
+-#endif
+-
+-#define NR_CPM_INTS 64
+-
+-#define SIU_INT_ERROR ((uint)0x00 + CPM_IRQ_OFFSET)
+-#define SIU_INT_I2C ((uint)0x01 + CPM_IRQ_OFFSET)
+-#define SIU_INT_SPI ((uint)0x02 + CPM_IRQ_OFFSET)
+-#define SIU_INT_RISC ((uint)0x03 + CPM_IRQ_OFFSET)
+-#define SIU_INT_SMC1 ((uint)0x04 + CPM_IRQ_OFFSET)
+-#define SIU_INT_SMC2 ((uint)0x05 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IDMA1 ((uint)0x06 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IDMA2 ((uint)0x07 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IDMA3 ((uint)0x08 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IDMA4 ((uint)0x09 + CPM_IRQ_OFFSET)
+-#define SIU_INT_SDMA ((uint)0x0a + CPM_IRQ_OFFSET)
+-#define SIU_INT_USB ((uint)0x0b + CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER1 ((uint)0x0c + CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER2 ((uint)0x0d + CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER3 ((uint)0x0e + CPM_IRQ_OFFSET)
+-#define SIU_INT_TIMER4 ((uint)0x0f + CPM_IRQ_OFFSET)
+-#define SIU_INT_TMCNT ((uint)0x10 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PIT ((uint)0x11 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IRQ2 ((uint)0x14 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IRQ3 ((uint)0x15 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IRQ4 ((uint)0x16 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IRQ5 ((uint)0x17 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IRQ6 ((uint)0x18 + CPM_IRQ_OFFSET)
+-#define SIU_INT_IRQ7 ((uint)0x19 + CPM_IRQ_OFFSET)
+-#define SIU_INT_FCC1 ((uint)0x20 + CPM_IRQ_OFFSET)
+-#define SIU_INT_FCC2 ((uint)0x21 + CPM_IRQ_OFFSET)
+-#define SIU_INT_FCC3 ((uint)0x22 + CPM_IRQ_OFFSET)
+-#define SIU_INT_MCC1 ((uint)0x24 + CPM_IRQ_OFFSET)
+-#define SIU_INT_MCC2 ((uint)0x25 + CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC1 ((uint)0x28 + CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC2 ((uint)0x29 + CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC3 ((uint)0x2a + CPM_IRQ_OFFSET)
+-#define SIU_INT_SCC4 ((uint)0x2b + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC15 ((uint)0x30 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC14 ((uint)0x31 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC13 ((uint)0x32 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC12 ((uint)0x33 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC11 ((uint)0x34 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC10 ((uint)0x35 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC9 ((uint)0x36 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC8 ((uint)0x37 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC7 ((uint)0x38 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC6 ((uint)0x39 + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC5 ((uint)0x3a + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC4 ((uint)0x3b + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC3 ((uint)0x3c + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC2 ((uint)0x3d + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC1 ((uint)0x3e + CPM_IRQ_OFFSET)
+-#define SIU_INT_PC0 ((uint)0x3f + CPM_IRQ_OFFSET)
+-
+-#endif /* CONFIG_8260 */
+-
+-/*
+- * This gets called from serial.c, which is now used on
+- * powermacs as well as prep/chrp boxes.
+- * Prep and chrp both have cascaded 8259 PICs.
+- */
+-static __inline__ int irq_canonicalize(int irq)
+-{
+- if (ppc_md.irq_canonicalize)
+- return ppc_md.irq_canonicalize(irq);
+- return irq;
+-}
+-
+-#endif
+-
+-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+-/* pedantic: these are long because they are used with set_bit --RR */
+-extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+-extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
+-extern atomic_t ppc_n_lost_interrupts;
+-
+-#endif /* _ASM_IRQ_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/keylargo.h b/include/asm-ppc/keylargo.h
+deleted file mode 100644
+--- a/include/asm-ppc/keylargo.h
++++ /dev/null
+@@ -1,248 +0,0 @@
+-/*
+- * keylargo.h: definitions for using the "KeyLargo" I/O controller chip.
+- *
+- */
+-
+-/* "Pangea" chipset has keylargo device-id 0x25 while core99
+- * has device-id 0x22. The rev. of the pangea one is 0, so we
+- * fake an artificial rev. in keylargo_rev by oring 0x100
+- */
+-#define KL_PANGEA_REV 0x100
+-
+-/* offset from base for feature control registers */
+-#define KEYLARGO_MBCR 0x34 /* KL Only, Media bay control/status */
+-#define KEYLARGO_FCR0 0x38
+-#define KEYLARGO_FCR1 0x3c
+-#define KEYLARGO_FCR2 0x40
+-#define KEYLARGO_FCR3 0x44
+-#define KEYLARGO_FCR4 0x48
+-#define KEYLARGO_FCR5 0x4c /* Pangea only */
+-
+-/* K2 aditional FCRs */
+-#define K2_FCR6 0x34
+-#define K2_FCR7 0x30
+-#define K2_FCR8 0x2c
+-#define K2_FCR9 0x28
+-#define K2_FCR10 0x24
+-
+-/* GPIO registers */
+-#define KEYLARGO_GPIO_LEVELS0 0x50
+-#define KEYLARGO_GPIO_LEVELS1 0x54
+-#define KEYLARGO_GPIO_EXTINT_0 0x58
+-#define KEYLARGO_GPIO_EXTINT_CNT 18
+-#define KEYLARGO_GPIO_0 0x6A
+-#define KEYLARGO_GPIO_CNT 17
+-#define KEYLARGO_GPIO_EXTINT_DUAL_EDGE 0x80
+-#define KEYLARGO_GPIO_OUTPUT_ENABLE 0x04
+-#define KEYLARGO_GPIO_OUTOUT_DATA 0x01
+-#define KEYLARGO_GPIO_INPUT_DATA 0x02
+-
+-/* K2 does only extint GPIOs and does 51 of them */
+-#define K2_GPIO_EXTINT_0 0x58
+-#define K2_GPIO_EXTINT_CNT 51
+-
+-/* Specific GPIO regs */
+-
+-#define KL_GPIO_MODEM_RESET (KEYLARGO_GPIO_0+0x03)
+-#define KL_GPIO_MODEM_POWER (KEYLARGO_GPIO_0+0x02) /* Pangea */
+-
+-#define KL_GPIO_SOUND_POWER (KEYLARGO_GPIO_0+0x05)
+-
+-/* Hrm... this one is only to be used on Pismo. It seeem to also
+- * control the timebase enable on other machines. Still to be
+- * experimented... --BenH.
+- */
+-#define KL_GPIO_FW_CABLE_POWER (KEYLARGO_GPIO_0+0x09)
+-#define KL_GPIO_TB_ENABLE (KEYLARGO_GPIO_0+0x09)
+-
+-#define KL_GPIO_ETH_PHY_RESET (KEYLARGO_GPIO_0+0x10)
+-
+-#define KL_GPIO_EXTINT_CPU1 (KEYLARGO_GPIO_0+0x0a)
+-#define KL_GPIO_EXTINT_CPU1_ASSERT 0x04
+-#define KL_GPIO_EXTINT_CPU1_RELEASE 0x38
+-
+-#define KL_GPIO_RESET_CPU0 (KEYLARGO_GPIO_EXTINT_0+0x03)
+-#define KL_GPIO_RESET_CPU1 (KEYLARGO_GPIO_EXTINT_0+0x04)
+-#define KL_GPIO_RESET_CPU2 (KEYLARGO_GPIO_EXTINT_0+0x0f)
+-#define KL_GPIO_RESET_CPU3 (KEYLARGO_GPIO_EXTINT_0+0x10)
+-
+-#define KL_GPIO_PMU_MESSAGE_IRQ (KEYLARGO_GPIO_EXTINT_0+0x09)
+-#define KL_GPIO_PMU_MESSAGE_BIT KEYLARGO_GPIO_INPUT_DATA
+-
+-#define KL_GPIO_MEDIABAY_IRQ (KEYLARGO_GPIO_EXTINT_0+0x0e)
+-
+-#define KL_GPIO_AIRPORT_0 (KEYLARGO_GPIO_EXTINT_0+0x0a)
+-#define KL_GPIO_AIRPORT_1 (KEYLARGO_GPIO_EXTINT_0+0x0d)
+-#define KL_GPIO_AIRPORT_2 (KEYLARGO_GPIO_0+0x0d)
+-#define KL_GPIO_AIRPORT_3 (KEYLARGO_GPIO_0+0x0e)
+-#define KL_GPIO_AIRPORT_4 (KEYLARGO_GPIO_0+0x0f)
+-
+-/*
+- * Bits in feature control register. Those bits different for K2 are
+- * listed separately
+- */
+-#define KL_MBCR_MB0_PCI_ENABLE 0x00000800 /* exist ? */
+-#define KL_MBCR_MB0_IDE_ENABLE 0x00001000
+-#define KL_MBCR_MB0_FLOPPY_ENABLE 0x00002000 /* exist ? */
+-#define KL_MBCR_MB0_SOUND_ENABLE 0x00004000 /* hrm... */
+-#define KL_MBCR_MB0_DEV_MASK 0x00007800
+-#define KL_MBCR_MB0_DEV_POWER 0x00000400
+-#define KL_MBCR_MB0_DEV_RESET 0x00000200
+-#define KL_MBCR_MB0_ENABLE 0x00000100
+-#define KL_MBCR_MB1_PCI_ENABLE 0x08000000 /* exist ? */
+-#define KL_MBCR_MB1_IDE_ENABLE 0x10000000
+-#define KL_MBCR_MB1_FLOPPY_ENABLE 0x20000000 /* exist ? */
+-#define KL_MBCR_MB1_SOUND_ENABLE 0x40000000 /* hrm... */
+-#define KL_MBCR_MB1_DEV_MASK 0x78000000
+-#define KL_MBCR_MB1_DEV_POWER 0x04000000
+-#define KL_MBCR_MB1_DEV_RESET 0x02000000
+-#define KL_MBCR_MB1_ENABLE 0x01000000
+-
+-#define KL0_SCC_B_INTF_ENABLE 0x00000001 /* (KL Only) */
+-#define KL0_SCC_A_INTF_ENABLE 0x00000002
+-#define KL0_SCC_SLOWPCLK 0x00000004
+-#define KL0_SCC_RESET 0x00000008
+-#define KL0_SCCA_ENABLE 0x00000010
+-#define KL0_SCCB_ENABLE 0x00000020
+-#define KL0_SCC_CELL_ENABLE 0x00000040
+-#define KL0_IRDA_HIGH_BAND 0x00000100 /* (KL Only) */
+-#define KL0_IRDA_SOURCE2_SEL 0x00000200 /* (KL Only) */
+-#define KL0_IRDA_SOURCE1_SEL 0x00000400 /* (KL Only) */
+-#define KL0_PG_USB0_PMI_ENABLE 0x00000400 /* (Pangea/Intrepid Only) */
+-#define KL0_IRDA_RESET 0x00000800 /* (KL Only) */
+-#define KL0_PG_USB0_REF_SUSPEND_SEL 0x00000800 /* (Pangea/Intrepid Only) */
+-#define KL0_IRDA_DEFAULT1 0x00001000 /* (KL Only) */
+-#define KL0_PG_USB0_REF_SUSPEND 0x00001000 /* (Pangea/Intrepid Only) */
+-#define KL0_IRDA_DEFAULT0 0x00002000 /* (KL Only) */
+-#define KL0_PG_USB0_PAD_SUSPEND 0x00002000 /* (Pangea/Intrepid Only) */
+-#define KL0_IRDA_FAST_CONNECT 0x00004000 /* (KL Only) */
+-#define KL0_PG_USB1_PMI_ENABLE 0x00004000 /* (Pangea/Intrepid Only) */
+-#define KL0_IRDA_ENABLE 0x00008000 /* (KL Only) */
+-#define KL0_PG_USB1_REF_SUSPEND_SEL 0x00008000 /* (Pangea/Intrepid Only) */
+-#define KL0_IRDA_CLK32_ENABLE 0x00010000 /* (KL Only) */
+-#define KL0_PG_USB1_REF_SUSPEND 0x00010000 /* (Pangea/Intrepid Only) */
+-#define KL0_IRDA_CLK19_ENABLE 0x00020000 /* (KL Only) */
+-#define KL0_PG_USB1_PAD_SUSPEND 0x00020000 /* (Pangea/Intrepid Only) */
+-#define KL0_USB0_PAD_SUSPEND0 0x00040000
+-#define KL0_USB0_PAD_SUSPEND1 0x00080000
+-#define KL0_USB0_CELL_ENABLE 0x00100000
+-#define KL0_USB1_PAD_SUSPEND0 0x00400000
+-#define KL0_USB1_PAD_SUSPEND1 0x00800000
+-#define KL0_USB1_CELL_ENABLE 0x01000000
+-#define KL0_USB_REF_SUSPEND 0x10000000 /* (KL Only) */
+-
+-#define KL0_SERIAL_ENABLE (KL0_SCC_B_INTF_ENABLE | \
+- KL0_SCC_SLOWPCLK | \
+- KL0_SCC_CELL_ENABLE | KL0_SCCA_ENABLE)
+-
+-#define KL1_USB2_PMI_ENABLE 0x00000001 /* Intrepid only */
+-#define KL1_AUDIO_SEL_22MCLK 0x00000002 /* KL/Pangea only */
+-#define KL1_USB2_REF_SUSPEND_SEL 0x00000002 /* Intrepid only */
+-#define KL1_USB2_REF_SUSPEND 0x00000004 /* Intrepid only */
+-#define KL1_AUDIO_CLK_ENABLE_BIT 0x00000008 /* KL/Pangea only */
+-#define KL1_USB2_PAD_SUSPEND_SEL 0x00000008 /* Intrepid only */
+-#define KL1_USB2_PAD_SUSPEND0 0x00000010 /* Intrepid only */
+-#define KL1_AUDIO_CLK_OUT_ENABLE 0x00000020 /* KL/Pangea only */
+-#define KL1_USB2_PAD_SUSPEND1 0x00000020 /* Intrepid only */
+-#define KL1_AUDIO_CELL_ENABLE 0x00000040 /* KL/Pangea only */
+-#define KL1_USB2_CELL_ENABLE 0x00000040 /* Intrepid only */
+-#define KL1_AUDIO_CHOOSE 0x00000080 /* KL/Pangea only */
+-#define KL1_I2S0_CHOOSE 0x00000200 /* KL Only */
+-#define KL1_I2S0_CELL_ENABLE 0x00000400
+-#define KL1_I2S0_CLK_ENABLE_BIT 0x00001000
+-#define KL1_I2S0_ENABLE 0x00002000
+-#define KL1_I2S1_CELL_ENABLE 0x00020000
+-#define KL1_I2S1_CLK_ENABLE_BIT 0x00080000
+-#define KL1_I2S1_ENABLE 0x00100000
+-#define KL1_EIDE0_ENABLE 0x00800000 /* KL/Intrepid Only */
+-#define KL1_EIDE0_RESET_N 0x01000000 /* KL/Intrepid Only */
+-#define KL1_EIDE1_ENABLE 0x04000000 /* KL Only */
+-#define KL1_EIDE1_RESET_N 0x08000000 /* KL Only */
+-#define KL1_UIDE_ENABLE 0x20000000 /* KL/Pangea Only */
+-#define KL1_UIDE_RESET_N 0x40000000 /* KL/Pangea Only */
+-
+-#define KL2_IOBUS_ENABLE 0x00000002
+-#define KL2_SLEEP_STATE_BIT 0x00000100 /* KL Only */
+-#define KL2_PG_STOP_ALL_CLOCKS 0x00000100 /* Pangea Only */
+-#define KL2_MPIC_ENABLE 0x00020000
+-#define KL2_CARDSLOT_RESET 0x00040000 /* Pangea/Intrepid Only */
+-#define KL2_ALT_DATA_OUT 0x02000000 /* KL Only ??? */
+-#define KL2_MEM_IS_BIG 0x04000000
+-#define KL2_CARDSEL_16 0x08000000
+-
+-#define KL3_SHUTDOWN_PLL_TOTAL 0x00000001 /* KL/Pangea only */
+-#define KL3_SHUTDOWN_PLLKW6 0x00000002 /* KL/Pangea only */
+-#define KL3_IT_SHUTDOWN_PLL3 0x00000002 /* Intrepid only */
+-#define KL3_SHUTDOWN_PLLKW4 0x00000004 /* KL/Pangea only */
+-#define KL3_IT_SHUTDOWN_PLL2 0x00000004 /* Intrepid only */
+-#define KL3_SHUTDOWN_PLLKW35 0x00000008 /* KL/Pangea only */
+-#define KL3_IT_SHUTDOWN_PLL1 0x00000008 /* Intrepid only */
+-#define KL3_SHUTDOWN_PLLKW12 0x00000010 /* KL Only */
+-#define KL3_IT_ENABLE_PLL3_SHUTDOWN 0x00000010 /* Intrepid only */
+-#define KL3_PLL_RESET 0x00000020 /* KL/Pangea only */
+-#define KL3_IT_ENABLE_PLL2_SHUTDOWN 0x00000020 /* Intrepid only */
+-#define KL3_IT_ENABLE_PLL1_SHUTDOWN 0x00000010 /* Intrepid only */
+-#define KL3_SHUTDOWN_PLL2X 0x00000080 /* KL Only */
+-#define KL3_CLK66_ENABLE 0x00000100 /* KL Only */
+-#define KL3_CLK49_ENABLE 0x00000200
+-#define KL3_CLK45_ENABLE 0x00000400
+-#define KL3_CLK31_ENABLE 0x00000800 /* KL/Pangea only */
+-#define KL3_TIMER_CLK18_ENABLE 0x00001000
+-#define KL3_I2S1_CLK18_ENABLE 0x00002000
+-#define KL3_I2S0_CLK18_ENABLE 0x00004000
+-#define KL3_VIA_CLK16_ENABLE 0x00008000 /* KL/Pangea only */
+-#define KL3_IT_VIA_CLK32_ENABLE 0x00008000 /* Intrepid only */
+-#define KL3_STOPPING33_ENABLED 0x00080000 /* KL Only */
+-#define KL3_PG_PLL_ENABLE_TEST 0x00080000 /* Pangea Only */
+-
+-/* Intrepid USB bus 2, port 0,1 */
+-#define KL3_IT_PORT_WAKEUP_ENABLE(p) (0x00080000 << ((p)<<3))
+-#define KL3_IT_PORT_RESUME_WAKE_EN(p) (0x00040000 << ((p)<<3))
+-#define KL3_IT_PORT_CONNECT_WAKE_EN(p) (0x00020000 << ((p)<<3))
+-#define KL3_IT_PORT_DISCONNECT_WAKE_EN(p) (0x00010000 << ((p)<<3))
+-#define KL3_IT_PORT_RESUME_STAT(p) (0x00300000 << ((p)<<3))
+-#define KL3_IT_PORT_CONNECT_STAT(p) (0x00200000 << ((p)<<3))
+-#define KL3_IT_PORT_DISCONNECT_STAT(p) (0x00100000 << ((p)<<3))
+-
+-/* Port 0,1 : bus 0, port 2,3 : bus 1 */
+-#define KL4_PORT_WAKEUP_ENABLE(p) (0x00000008 << ((p)<<3))
+-#define KL4_PORT_RESUME_WAKE_EN(p) (0x00000004 << ((p)<<3))
+-#define KL4_PORT_CONNECT_WAKE_EN(p) (0x00000002 << ((p)<<3))
+-#define KL4_PORT_DISCONNECT_WAKE_EN(p) (0x00000001 << ((p)<<3))
+-#define KL4_PORT_RESUME_STAT(p) (0x00000040 << ((p)<<3))
+-#define KL4_PORT_CONNECT_STAT(p) (0x00000020 << ((p)<<3))
+-#define KL4_PORT_DISCONNECT_STAT(p) (0x00000010 << ((p)<<3))
+-
+-/* Pangea and Intrepid only */
+-#define KL5_VIA_USE_CLK31 0000000001 /* Pangea Only */
+-#define KL5_SCC_USE_CLK31 0x00000002 /* Pangea Only */
+-#define KL5_PWM_CLK32_EN 0x00000004
+-#define KL5_CLK3_68_EN 0x00000010
+-#define KL5_CLK32_EN 0x00000020
+-
+-
+-/* K2 definitions */
+-#define K2_FCR0_USB0_SWRESET 0x00200000
+-#define K2_FCR0_USB1_SWRESET 0x02000000
+-#define K2_FCR0_RING_PME_DISABLE 0x08000000
+-
+-#define K2_FCR1_PCI1_BUS_RESET_N 0x00000010
+-#define K2_FCR1_PCI1_SLEEP_RESET_EN 0x00000020
+-#define K2_FCR1_I2S0_CELL_ENABLE 0x00000400
+-#define K2_FCR1_I2S0_RESET 0x00000800
+-#define K2_FCR1_I2S0_CLK_ENABLE_BIT 0x00001000
+-#define K2_FCR1_I2S0_ENABLE 0x00002000
+-
+-#define K2_FCR1_PCI1_CLK_ENABLE 0x00004000
+-#define K2_FCR1_FW_CLK_ENABLE 0x00008000
+-#define K2_FCR1_FW_RESET_N 0x00010000
+-#define K2_FCR1_GMAC_CLK_ENABLE 0x00400000
+-#define K2_FCR1_GMAC_POWER_DOWN 0x00800000
+-#define K2_FCR1_GMAC_RESET_N 0x01000000
+-#define K2_FCR1_SATA_CLK_ENABLE 0x02000000
+-#define K2_FCR1_SATA_POWER_DOWN 0x04000000
+-#define K2_FCR1_SATA_RESET_N 0x08000000
+-#define K2_FCR1_UATA_CLK_ENABLE 0x10000000
+-#define K2_FCR1_UATA_RESET_N 0x40000000
+-#define K2_FCR1_UATA_CHOOSE_CLK66 0x80000000
+-
+diff --git a/include/asm-ppc/kmap_types.h b/include/asm-ppc/kmap_types.h
+deleted file mode 100644
+--- a/include/asm-ppc/kmap_types.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_KMAP_TYPES_H
+-#define _ASM_KMAP_TYPES_H
+-
+-enum km_type {
+- KM_BOUNCE_READ,
+- KM_SKB_SUNRPC_DATA,
+- KM_SKB_DATA_SOFTIRQ,
+- KM_USER0,
+- KM_USER1,
+- KM_BIO_SRC_IRQ,
+- KM_BIO_DST_IRQ,
+- KM_PTE0,
+- KM_PTE1,
+- KM_IRQ0,
+- KM_IRQ1,
+- KM_SOFTIRQ0,
+- KM_SOFTIRQ1,
+- KM_PPC_SYNC_PAGE,
+- KM_PPC_SYNC_ICACHE,
+- KM_TYPE_NR
+-};
+-
+-#endif
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
+--- a/include/asm-ppc/machdep.h
++++ b/include/asm-ppc/machdep.h
+@@ -98,7 +98,7 @@ struct machdep_calls {
+
+ /* Get access protection for /dev/mem */
+ pgprot_t (*phys_mem_access_prot)(struct file *file,
+- unsigned long offset,
++ unsigned long pfn,
+ unsigned long size,
+ pgprot_t vma_prot);
+
+@@ -167,7 +167,7 @@ extern sys_ctrler_t sys_ctrler;
+
+ #ifdef CONFIG_SMP
+ struct smp_ops_t {
+- void (*message_pass)(int target, int msg, unsigned long data, int wait);
++ void (*message_pass)(int target, int msg);
+ int (*probe)(void);
+ void (*kick_cpu)(int nr);
+ void (*setup_cpu)(int nr);
+diff --git a/include/asm-ppc/macio.h b/include/asm-ppc/macio.h
+deleted file mode 100644
+--- a/include/asm-ppc/macio.h
++++ /dev/null
+@@ -1,140 +0,0 @@
+-#ifndef __MACIO_ASIC_H__
+-#define __MACIO_ASIC_H__
+-
+-#include <asm/of_device.h>
+-
+-extern struct bus_type macio_bus_type;
+-
+-/* MacIO device driver is defined later */
+-struct macio_driver;
+-struct macio_chip;
+-
+-#define MACIO_DEV_COUNT_RESOURCES 8
+-#define MACIO_DEV_COUNT_IRQS 8
+-
+-/*
+- * the macio_bus structure is used to describe a "virtual" bus
+- * within a MacIO ASIC. It's typically provided by a macio_pci_asic
+- * PCI device, but could be provided differently as well (nubus
+- * machines using a fake OF tree).
+- *
+- * The pdev field can be NULL on non-PCI machines
+- */
+-struct macio_bus
+-{
+- struct macio_chip *chip; /* macio_chip (private use) */
+- int index; /* macio chip index in system */
+-#ifdef CONFIG_PCI
+- struct pci_dev *pdev; /* PCI device hosting this bus */
+-#endif
+-};
+-
+-/*
+- * the macio_dev structure is used to describe a device
+- * within an Apple MacIO ASIC.
+- */
+-struct macio_dev
+-{
+- struct macio_bus *bus; /* macio bus this device is on */
+- struct macio_dev *media_bay; /* Device is part of a media bay */
+- struct of_device ofdev;
+- int n_resources;
+- struct resource resource[MACIO_DEV_COUNT_RESOURCES];
+- int n_interrupts;
+- struct resource interrupt[MACIO_DEV_COUNT_IRQS];
+-};
+-#define to_macio_device(d) container_of(d, struct macio_dev, ofdev.dev)
+-#define of_to_macio_device(d) container_of(d, struct macio_dev, ofdev)
+-
+-extern struct macio_dev *macio_dev_get(struct macio_dev *dev);
+-extern void macio_dev_put(struct macio_dev *dev);
+-
+-/*
+- * Accessors to resources & interrupts and other device
+- * fields
+- */
+-
+-static inline int macio_resource_count(struct macio_dev *dev)
+-{
+- return dev->n_resources;
+-}
+-
+-static inline unsigned long macio_resource_start(struct macio_dev *dev, int resource_no)
+-{
+- return dev->resource[resource_no].start;
+-}
+-
+-static inline unsigned long macio_resource_end(struct macio_dev *dev, int resource_no)
+-{
+- return dev->resource[resource_no].end;
+-}
+-
+-static inline unsigned long macio_resource_len(struct macio_dev *dev, int resource_no)
+-{
+- struct resource *res = &dev->resource[resource_no];
+- if (res->start == 0 || res->end == 0 || res->end < res->start)
+- return 0;
+- return res->end - res->start + 1;
+-}
+-
+-extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name);
+-extern void macio_release_resource(struct macio_dev *dev, int resource_no);
+-extern int macio_request_resources(struct macio_dev *dev, const char *name);
+-extern void macio_release_resources(struct macio_dev *dev);
+-
+-static inline int macio_irq_count(struct macio_dev *dev)
+-{
+- return dev->n_interrupts;
+-}
+-
+-static inline int macio_irq(struct macio_dev *dev, int irq_no)
+-{
+- return dev->interrupt[irq_no].start;
+-}
+-
+-static inline void macio_set_drvdata(struct macio_dev *dev, void *data)
+-{
+- dev_set_drvdata(&dev->ofdev.dev, data);
+-}
+-
+-static inline void* macio_get_drvdata(struct macio_dev *dev)
+-{
+- return dev_get_drvdata(&dev->ofdev.dev);
+-}
+-
+-static inline struct device_node *macio_get_of_node(struct macio_dev *mdev)
+-{
+- return mdev->ofdev.node;
+-}
+-
+-#ifdef CONFIG_PCI
+-static inline struct pci_dev *macio_get_pci_dev(struct macio_dev *mdev)
+-{
+- return mdev->bus->pdev;
+-}
+-#endif
+-
+-/*
+- * A driver for a mac-io chip based device
+- */
+-struct macio_driver
+-{
+- char *name;
+- struct of_device_id *match_table;
+- struct module *owner;
+-
+- int (*probe)(struct macio_dev* dev, const struct of_device_id *match);
+- int (*remove)(struct macio_dev* dev);
+-
+- int (*suspend)(struct macio_dev* dev, pm_message_t state);
+- int (*resume)(struct macio_dev* dev);
+- int (*shutdown)(struct macio_dev* dev);
+-
+- struct device_driver driver;
+-};
+-#define to_macio_driver(drv) container_of(drv,struct macio_driver, driver)
+-
+-extern int macio_register_driver(struct macio_driver *);
+-extern void macio_unregister_driver(struct macio_driver *);
+-
+-#endif /* __MACIO_ASIC_H__ */
+diff --git a/include/asm-ppc/mediabay.h b/include/asm-ppc/mediabay.h
+deleted file mode 100644
+--- a/include/asm-ppc/mediabay.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * mediabay.h: definitions for using the media bay
+- * on PowerBook 3400 and similar computers.
+- *
+- * Copyright (C) 1997 Paul Mackerras.
+- */
+-#ifndef _PPC_MEDIABAY_H
+-#define _PPC_MEDIABAY_H
+-
+-#ifdef __KERNEL__
+-
+-#define MB_FD 0 /* media bay contains floppy drive (automatic eject ?) */
+-#define MB_FD1 1 /* media bay contains floppy drive (manual eject ?) */
+-#define MB_SOUND 2 /* sound device ? */
+-#define MB_CD 3 /* media bay contains ATA drive such as CD or ZIP */
+-#define MB_PCI 5 /* media bay contains a PCI device */
+-#define MB_POWER 6 /* media bay contains a Power device (???) */
+-#define MB_NO 7 /* media bay contains nothing */
+-
+-int check_media_bay(struct device_node *which_bay, int what);
+-int check_media_bay_by_base(unsigned long base, int what);
+-
+-/* Number of bays in the machine or 0 */
+-extern int media_bay_count;
+-
+-/* called by pmac-ide.c to register IDE controller for media bay */
+-extern int media_bay_set_ide_infos(struct device_node* which_bay,
+- unsigned long base, int irq, int index);
+-
+-#endif /* __KERNEL__ */
+-#endif /* _PPC_MEDIABAY_H */
+diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
+--- a/include/asm-ppc/mmu_context.h
++++ b/include/asm-ppc/mmu_context.h
+@@ -164,13 +164,11 @@ static inline void switch_mm(struct mm_s
+ struct task_struct *tsk)
+ {
+ #ifdef CONFIG_ALTIVEC
+- asm volatile (
+- BEGIN_FTR_SECTION
+- "dssall;\n"
++ if (cpu_has_feature(CPU_FTR_ALTIVEC))
++ asm volatile ("dssall;\n"
+ #ifndef CONFIG_POWER4
+ "sync;\n" /* G4 needs a sync here, G5 apparently not */
+ #endif
+- END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ : : );
+ #endif /* CONFIG_ALTIVEC */
+
+diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
+--- a/include/asm-ppc/mpc8260.h
++++ b/include/asm-ppc/mpc8260.h
+@@ -92,6 +92,10 @@ enum ppc_sys_devices {
+ extern unsigned char __res[];
+ #endif
+
++#ifndef BOARD_CHIP_NAME
++#define BOARD_CHIP_NAME ""
++#endif
++
+ #endif /* CONFIG_8260 */
+ #endif /* !__ASM_PPC_MPC8260_H__ */
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
+--- a/include/asm-ppc/mpc85xx.h
++++ b/include/asm-ppc/mpc85xx.h
+@@ -67,6 +67,8 @@ extern unsigned char __res[];
+ #define MPC85xx_DMA3_SIZE (0x00080)
+ #define MPC85xx_ENET1_OFFSET (0x24000)
+ #define MPC85xx_ENET1_SIZE (0x01000)
++#define MPC85xx_MIIM_OFFSET (0x24520)
++#define MPC85xx_MIIM_SIZE (0x00018)
+ #define MPC85xx_ENET2_OFFSET (0x25000)
+ #define MPC85xx_ENET2_SIZE (0x01000)
+ #define MPC85xx_ENET3_OFFSET (0x26000)
+@@ -132,6 +134,7 @@ enum ppc_sys_devices {
+ MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4,
+ MPC85xx_IIC2,
++ MPC85xx_MDIO,
+ };
+
+ /* Internal interrupts are all Level Sensitive, and Positive Polarity */
+diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
+--- a/include/asm-ppc/mpc8xx.h
++++ b/include/asm-ppc/mpc8xx.h
+@@ -113,6 +113,10 @@ enum ppc_sys_devices {
+ MPC8xx_CPM_USB,
+ };
+
++#ifndef BOARD_CHIP_NAME
++#define BOARD_CHIP_NAME ""
++#endif
++
+ #endif /* !__ASSEMBLY__ */
+ #endif /* CONFIG_8xx */
+ #endif /* __CONFIG_8xx_DEFS */
+diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h
+--- a/include/asm-ppc/mv64x60.h
++++ b/include/asm-ppc/mv64x60.h
+@@ -27,6 +27,8 @@
+ #include <asm/pci-bridge.h>
+ #include <asm/mv64x60_defs.h>
+
++struct platform_device;
++
+ extern u8 mv64x60_pci_exclude_bridge;
+
+ extern spinlock_t mv64x60_lock;
+diff --git a/include/asm-ppc/of_device.h b/include/asm-ppc/of_device.h
+deleted file mode 100644
+--- a/include/asm-ppc/of_device.h
++++ /dev/null
+@@ -1,65 +0,0 @@
+-#ifndef __OF_DEVICE_H__
+-#define __OF_DEVICE_H__
+-
+-#include <linux/device.h>
+-#include <linux/mod_devicetable.h>
+-#include <asm/prom.h>
+-
+-/*
+- * The of_platform_bus_type is a bus type used by drivers that do not
+- * attach to a macio or similar bus but still use OF probing
+- * mecanism
+- */
+-extern struct bus_type of_platform_bus_type;
+-
+-/*
+- * The of_device is a kind of "base class" that is a superset of
+- * struct device for use by devices attached to an OF node and
+- * probed using OF properties
+- */
+-struct of_device
+-{
+- struct device_node *node; /* OF device node */
+- u64 dma_mask; /* DMA mask */
+- struct device dev; /* Generic device interface */
+-};
+-#define to_of_device(d) container_of(d, struct of_device, dev)
+-
+-extern const struct of_device_id *of_match_device(
+- const struct of_device_id *matches, const struct of_device *dev);
+-
+-extern struct of_device *of_dev_get(struct of_device *dev);
+-extern void of_dev_put(struct of_device *dev);
+-
+-/*
+- * An of_platform_driver driver is attached to a basic of_device on
+- * the "platform bus" (of_platform_bus_type)
+- */
+-struct of_platform_driver
+-{
+- char *name;
+- struct of_device_id *match_table;
+- struct module *owner;
+-
+- int (*probe)(struct of_device* dev, const struct of_device_id *match);
+- int (*remove)(struct of_device* dev);
+-
+- int (*suspend)(struct of_device* dev, pm_message_t state);
+- int (*resume)(struct of_device* dev);
+- int (*shutdown)(struct of_device* dev);
+-
+- struct device_driver driver;
+-};
+-#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
+-
+-extern int of_register_driver(struct of_platform_driver *drv);
+-extern void of_unregister_driver(struct of_platform_driver *drv);
+-extern int of_device_register(struct of_device *ofdev);
+-extern void of_device_unregister(struct of_device *ofdev);
+-extern struct of_device *of_platform_device_create(struct device_node *np,
+- const char *bus_id,
+- struct device *parent);
+-extern void of_release_dev(struct device *dev);
+-
+-#endif /* __OF_DEVICE_H__ */
+-
+diff --git a/include/asm-ppc/ohare.h b/include/asm-ppc/ohare.h
+deleted file mode 100644
+--- a/include/asm-ppc/ohare.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/*
+- * ohare.h: definitions for using the "O'Hare" I/O controller chip.
+- *
+- * Copyright (C) 1997 Paul Mackerras.
+- *
+- * BenH: Changed to match those of heathrow (but not all of them). Please
+- * check if I didn't break anything (especially the media bay).
+- */
+-
+-/* offset from ohare base for feature control register */
+-#define OHARE_MBCR 0x34
+-#define OHARE_FCR 0x38
+-
+-/*
+- * Bits in feature control register.
+- * These were mostly derived by experiment on a powerbook 3400
+- * and may differ for other machines.
+- */
+-#define OH_SCC_RESET 1
+-#define OH_BAY_POWER_N 2 /* a guess */
+-#define OH_BAY_PCI_ENABLE 4 /* a guess */
+-#define OH_BAY_IDE_ENABLE 8
+-#define OH_BAY_FLOPPY_ENABLE 0x10
+-#define OH_IDE0_ENABLE 0x20
+-#define OH_IDE0_RESET_N 0x40 /* a guess */
+-#define OH_BAY_DEV_MASK 0x1c
+-#define OH_BAY_RESET_N 0x80
+-#define OH_IOBUS_ENABLE 0x100 /* IOBUS seems to be IDE */
+-#define OH_SCC_ENABLE 0x200
+-#define OH_MESH_ENABLE 0x400
+-#define OH_FLOPPY_ENABLE 0x800
+-#define OH_SCCA_IO 0x4000
+-#define OH_SCCB_IO 0x8000
+-#define OH_VIA_ENABLE 0x10000 /* Is apparently wrong, to be verified */
+-#define OH_IDE1_RESET_N 0x800000
+-
+-/*
+- * Bits to set in the feature control register on PowerBooks.
+- */
+-#define PBOOK_FEATURES (OH_IDE_ENABLE | OH_SCC_ENABLE | \
+- OH_MESH_ENABLE | OH_SCCA_IO | OH_SCCB_IO)
+-
+-/*
+- * A magic value to put into the feature control register of the
+- * "ohare" I/O controller on Starmaxes to enable the IDE CD interface.
+- * Contributed by Harry Eaton.
+- */
+-#define STARMAX_FEATURES 0xbeff7a
+diff --git a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h
+--- a/include/asm-ppc/open_pic.h
++++ b/include/asm-ppc/open_pic.h
+@@ -58,8 +58,7 @@ extern int openpic_get_irq(struct pt_reg
+ extern void openpic_reset_processor_phys(u_int cpumask);
+ extern void openpic_setup_ISU(int isu_num, unsigned long addr);
+ extern void openpic_cause_IPI(u_int ipi, cpumask_t cpumask);
+-extern void smp_openpic_message_pass(int target, int msg, unsigned long data,
+- int wait);
++extern void smp_openpic_message_pass(int target, int msg);
+ extern void openpic_set_k2_cascade(int irq);
+ extern void openpic_set_priority(u_int pri);
+ extern u_int openpic_get_priority(void);
+diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h
+--- a/include/asm-ppc/page.h
++++ b/include/asm-ppc/page.h
+@@ -34,6 +34,17 @@ typedef unsigned long pte_basic_t;
+ #define PTE_FMT "%.8lx"
+ #endif
+
++/* align addr on a size boundary - adjust address up/down if needed */
++#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
++#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
++
++/* align addr on a size boundary - adjust address up if needed */
++#define _ALIGN(addr,size) _ALIGN_UP(addr,size)
++
++/* to align the pointer to the (next) page boundary */
++#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
++
++
+ #undef STRICT_MM_TYPECHECKS
+
+ #ifdef STRICT_MM_TYPECHECKS
+@@ -76,13 +87,6 @@ typedef unsigned long pgprot_t;
+
+ #endif
+
+-
+-/* align addr on a size boundary - adjust address up if needed -- Cort */
+-#define _ALIGN(addr,size) (((addr)+(size)-1)&(~((size)-1)))
+-
+-/* to align the pointer to the (next) page boundary */
+-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+-
+ struct page;
+ extern void clear_pages(void *page, int order);
+ static inline void clear_page(void *page) { clear_pages(page, 0); }
+diff --git a/include/asm-ppc/parport.h b/include/asm-ppc/parport.h
+deleted file mode 100644
+--- a/include/asm-ppc/parport.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/*
+- * parport.h: platform-specific PC-style parport initialisation
+- *
+- * Copyright (C) 1999, 2000 Tim Waugh <tim at cyberelk.demon.co.uk>
+- *
+- * This file should only be included by drivers/parport/parport_pc.c.
+- */
+-
+-#ifndef _ASM_PPC_PARPORT_H
+-#define _ASM_PPC_PARPORT_H
+-
+-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
+-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+-{
+- return parport_pc_find_isa_ports (autoirq, autodma);
+-}
+-
+-#endif /* !(_ASM_PPC_PARPORT_H) */
+diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
+--- a/include/asm-ppc/pci-bridge.h
++++ b/include/asm-ppc/pci-bridge.h
+@@ -79,6 +79,11 @@ struct pci_controller {
+ struct resource mem_space;
+ };
+
++static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
++{
++ return bus->sysdata;
++}
++
+ /* These are used for config access before all the PCI probing
+ has been done. */
+ int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
+--- a/include/asm-ppc/pci.h
++++ b/include/asm-ppc/pci.h
+@@ -24,9 +24,9 @@ struct pci_dev;
+ * Set this to 1 if you want the kernel to re-assign all PCI
+ * bus numbers
+ */
+-extern int pci_assign_all_busses;
++extern int pci_assign_all_buses;
+
+-#define pcibios_assign_all_busses() (pci_assign_all_busses)
++#define pcibios_assign_all_busses() (pci_assign_all_buses)
+ #define pcibios_scan_all_fns(a, b) 0
+
+ #define PCIBIOS_MIN_IO 0x1000
+@@ -126,7 +126,7 @@ extern void pcibios_add_platform_entries
+
+ struct file;
+ extern pgprot_t pci_phys_mem_access_prot(struct file *file,
+- unsigned long offset,
++ unsigned long pfn,
+ unsigned long size,
+ pgprot_t prot);
+
+diff --git a/include/asm-ppc/perfmon.h b/include/asm-ppc/perfmon.h
+deleted file mode 100644
+--- a/include/asm-ppc/perfmon.h
++++ /dev/null
+@@ -1,22 +0,0 @@
+-#ifndef __PERFMON_H
+-#define __PERFMON_H
+-
+-extern void (*perf_irq)(struct pt_regs *);
+-
+-int request_perfmon_irq(void (*handler)(struct pt_regs *));
+-void free_perfmon_irq(void);
+-
+-#ifdef CONFIG_FSL_BOOKE
+-void init_pmc_stop(int ctr);
+-void set_pmc_event(int ctr, int event);
+-void set_pmc_user_kernel(int ctr, int user, int kernel);
+-void set_pmc_marked(int ctr, int mark0, int mark1);
+-void pmc_start_ctr(int ctr, int enable);
+-void pmc_start_ctrs(int enable);
+-void pmc_stop_ctrs(void);
+-void dump_pmcs(void);
+-
+-extern struct op_ppc32_model op_model_fsl_booke;
+-#endif
+-
+-#endif /* __PERFMON_H */
+diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
+--- a/include/asm-ppc/pgtable.h
++++ b/include/asm-ppc/pgtable.h
+@@ -705,7 +705,7 @@ static inline void __ptep_set_access_fla
+ #define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+
+ struct file;
+-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
++extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ unsigned long size, pgprot_t vma_prot);
+ #define __HAVE_PHYS_MEM_ACCESS_PROT
+
+diff --git a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h
+deleted file mode 100644
+--- a/include/asm-ppc/pmac_feature.h
++++ /dev/null
+@@ -1,380 +0,0 @@
+-/*
+- * Definition of platform feature hooks for PowerMacs
+- *
+- * 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 Paul Mackerras &
+- * Ben. Herrenschmidt.
+- *
+- *
+- * Note: I removed media-bay details from the feature stuff, I believe it's
+- * not worth it, the media-bay driver can directly use the mac-io
+- * ASIC registers.
+- *
+- * Implementation note: Currently, none of these functions will block.
+- * However, they may internally protect themselves with a spinlock
+- * for way too long. Be prepared for at least some of these to block
+- * in the future.
+- *
+- * Unless specifically defined, the result code is assumed to be an
+- * error when negative, 0 is the default success result. Some functions
+- * may return additional positive result values.
+- *
+- * To keep implementation simple, all feature calls are assumed to have
+- * the prototype parameters (struct device_node* node, int value).
+- * When either is not used, pass 0.
+- */
+-
+-#ifdef __KERNEL__
+-#ifndef __PPC_ASM_PMAC_FEATURE_H
+-#define __PPC_ASM_PMAC_FEATURE_H
+-
+-#include <asm/macio.h>
+-#include <asm/machdep.h>
+-
+-/*
+- * Known Mac motherboard models
+- *
+- * Please, report any error here to benh at kernel.crashing.org, thanks !
+- *
+- * Note that I don't fully maintain this list for Core99 & MacRISC2
+- * and I'm considering removing all NewWorld entries from it and
+- * entirely rely on the model string.
+- */
+-
+-/* PowerSurge are the first generation of PCI Pmacs. This include
+- * all of the Grand-Central based machines. We currently don't
+- * differenciate most of them.
+- */
+-#define PMAC_TYPE_PSURGE 0x10 /* PowerSurge */
+-#define PMAC_TYPE_ANS 0x11 /* Apple Network Server */
+-
+-/* Here is the infamous serie of OHare based machines
+- */
+-#define PMAC_TYPE_COMET 0x20 /* Beleived to be PowerBook 2400 */
+-#define PMAC_TYPE_HOOPER 0x21 /* Beleived to be PowerBook 3400 */
+-#define PMAC_TYPE_KANGA 0x22 /* PowerBook 3500 (first G3) */
+-#define PMAC_TYPE_ALCHEMY 0x23 /* Alchemy motherboard base */
+-#define PMAC_TYPE_GAZELLE 0x24 /* Spartacus, some 5xxx/6xxx */
+-#define PMAC_TYPE_UNKNOWN_OHARE 0x2f /* Unknown, but OHare based */
+-
+-/* Here are the Heathrow based machines
+- * FIXME: Differenciate wallstreet,mainstreet,wallstreetII
+- */
+-#define PMAC_TYPE_GOSSAMER 0x30 /* Gossamer motherboard */
+-#define PMAC_TYPE_SILK 0x31 /* Desktop PowerMac G3 */
+-#define PMAC_TYPE_WALLSTREET 0x32 /* Wallstreet/Mainstreet PowerBook*/
+-#define PMAC_TYPE_UNKNOWN_HEATHROW 0x3f /* Unknown but heathrow based */
+-
+-/* Here are newworld machines based on Paddington (heathrow derivative)
+- */
+-#define PMAC_TYPE_101_PBOOK 0x40 /* 101 PowerBook (aka Lombard) */
+-#define PMAC_TYPE_ORIG_IMAC 0x41 /* First generation iMac */
+-#define PMAC_TYPE_YOSEMITE 0x42 /* B&W G3 */
+-#define PMAC_TYPE_YIKES 0x43 /* Yikes G4 (PCI graphics) */
+-#define PMAC_TYPE_UNKNOWN_PADDINGTON 0x4f /* Unknown but paddington based */
+-
+-/* Core99 machines based on UniNorth 1.0 and 1.5
+- *
+- * Note: A single entry here may cover several actual models according
+- * to the device-tree. (Sawtooth is most tower G4s, FW_IMAC is most
+- * FireWire based iMacs, etc...). Those machines are too similar to be
+- * distinguished here, when they need to be differencied, use the
+- * device-tree "model" or "compatible" property.
+- */
+-#define PMAC_TYPE_ORIG_IBOOK 0x40 /* First iBook model (no firewire) */
+-#define PMAC_TYPE_SAWTOOTH 0x41 /* Desktop G4s */
+-#define PMAC_TYPE_FW_IMAC 0x42 /* FireWire iMacs (except Pangea based) */
+-#define PMAC_TYPE_FW_IBOOK 0x43 /* FireWire iBooks (except iBook2) */
+-#define PMAC_TYPE_CUBE 0x44 /* Cube PowerMac */
+-#define PMAC_TYPE_QUICKSILVER 0x45 /* QuickSilver G4s */
+-#define PMAC_TYPE_PISMO 0x46 /* Pismo PowerBook */
+-#define PMAC_TYPE_TITANIUM 0x47 /* Titanium PowerBook */
+-#define PMAC_TYPE_TITANIUM2 0x48 /* Titanium II PowerBook (no L3, M6) */
+-#define PMAC_TYPE_TITANIUM3 0x49 /* Titanium III PowerBook (with L3 & M7) */
+-#define PMAC_TYPE_TITANIUM4 0x50 /* Titanium IV PowerBook (with L3 & M9) */
+-#define PMAC_TYPE_EMAC 0x50 /* eMac */
+-#define PMAC_TYPE_UNKNOWN_CORE99 0x5f
+-
+-/* MacRisc2 with UniNorth 2.0 */
+-#define PMAC_TYPE_RACKMAC 0x80 /* XServe */
+-#define PMAC_TYPE_WINDTUNNEL 0x81
+-
+-/* MacRISC2 machines based on the Pangea chipset
+- */
+-#define PMAC_TYPE_PANGEA_IMAC 0x100 /* Flower Power iMac */
+-#define PMAC_TYPE_IBOOK2 0x101 /* iBook2 (polycarbonate) */
+-#define PMAC_TYPE_FLAT_PANEL_IMAC 0x102 /* Flat panel iMac */
+-#define PMAC_TYPE_UNKNOWN_PANGEA 0x10f
+-
+-/* MacRISC2 machines based on the Intrepid chipset
+- */
+-#define PMAC_TYPE_UNKNOWN_INTREPID 0x11f /* Generic */
+-
+-/* MacRISC4 / G5 machines. We don't have per-machine selection here anymore,
+- * but rather machine families
+- */
+-#define PMAC_TYPE_POWERMAC_G5 0x150 /* U3 & U3H based */
+-#define PMAC_TYPE_POWERMAC_G5_U3L 0x151 /* U3L based desktop */
+-#define PMAC_TYPE_IMAC_G5 0x152 /* iMac G5 */
+-#define PMAC_TYPE_XSERVE_G5 0x153 /* Xserve G5 */
+-#define PMAC_TYPE_UNKNOWN_K2 0x19f /* Any other K2 based */
+-
+-/*
+- * Motherboard flags
+- */
+-
+-#define PMAC_MB_CAN_SLEEP 0x00000001
+-#define PMAC_MB_HAS_FW_POWER 0x00000002
+-#define PMAC_MB_OLD_CORE99 0x00000004
+-#define PMAC_MB_MOBILE 0x00000008
+-#define PMAC_MB_MAY_SLEEP 0x00000010
+-
+-/*
+- * Feature calls supported on pmac
+- *
+- */
+-
+-/*
+- * Use this inline wrapper
+- */
+-struct device_node;
+-
+-static inline long pmac_call_feature(int selector, struct device_node* node,
+- long param, long value)
+-{
+- if (!ppc_md.feature_call)
+- return -ENODEV;
+- return ppc_md.feature_call(selector, node, param, value);
+-}
+-
+-/* PMAC_FTR_SERIAL_ENABLE (struct device_node* node, int param, int value)
+- * enable/disable an SCC side. Pass the node corresponding to the
+- * channel side as a parameter.
+- * param is the type of port
+- * if param is ored with PMAC_SCC_FLAG_XMON, then the SCC is locked enabled
+- * for use by xmon.
+- */
+-#define PMAC_FTR_SCC_ENABLE PMAC_FTR_DEF(0)
+- #define PMAC_SCC_ASYNC 0
+- #define PMAC_SCC_IRDA 1
+- #define PMAC_SCC_I2S1 2
+- #define PMAC_SCC_FLAG_XMON 0x00001000
+-
+-/* PMAC_FTR_MODEM_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable the internal modem.
+- */
+-#define PMAC_FTR_MODEM_ENABLE PMAC_FTR_DEF(1)
+-
+-/* PMAC_FTR_SWIM3_ENABLE (struct device_node* node, 0,int value)
+- * enable/disable the swim3 (floppy) cell of a mac-io ASIC
+- */
+-#define PMAC_FTR_SWIM3_ENABLE PMAC_FTR_DEF(2)
+-
+-/* PMAC_FTR_MESH_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable the mesh (scsi) cell of a mac-io ASIC
+- */
+-#define PMAC_FTR_MESH_ENABLE PMAC_FTR_DEF(3)
+-
+-/* PMAC_FTR_IDE_ENABLE (struct device_node* node, int busID, int value)
+- * enable/disable an IDE port of a mac-io ASIC
+- * pass the busID parameter
+- */
+-#define PMAC_FTR_IDE_ENABLE PMAC_FTR_DEF(4)
+-
+-/* PMAC_FTR_IDE_RESET (struct device_node* node, int busID, int value)
+- * assert(1)/release(0) an IDE reset line (mac-io IDE only)
+- */
+-#define PMAC_FTR_IDE_RESET PMAC_FTR_DEF(5)
+-
+-/* PMAC_FTR_BMAC_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable the bmac (ethernet) cell of a mac-io ASIC, also drive
+- * it's reset line
+- */
+-#define PMAC_FTR_BMAC_ENABLE PMAC_FTR_DEF(6)
+-
+-/* PMAC_FTR_GMAC_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable the gmac (ethernet) cell of an uninorth ASIC. This
+- * control the cell's clock.
+- */
+-#define PMAC_FTR_GMAC_ENABLE PMAC_FTR_DEF(7)
+-
+-/* PMAC_FTR_GMAC_PHY_RESET (struct device_node* node, 0, 0)
+- * Perform a HW reset of the PHY connected to a gmac controller.
+- * Pass the gmac device node, not the PHY node.
+- */
+-#define PMAC_FTR_GMAC_PHY_RESET PMAC_FTR_DEF(8)
+-
+-/* PMAC_FTR_SOUND_CHIP_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable the sound chip, whatever it is and provided it can
+- * acually be controlled
+- */
+-#define PMAC_FTR_SOUND_CHIP_ENABLE PMAC_FTR_DEF(9)
+-
+-/* -- add various tweaks related to sound routing -- */
+-
+-/* PMAC_FTR_AIRPORT_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable the airport card
+- */
+-#define PMAC_FTR_AIRPORT_ENABLE PMAC_FTR_DEF(10)
+-
+-/* PMAC_FTR_RESET_CPU (NULL, int cpu_nr, 0)
+- * toggle the reset line of a CPU on an uninorth-based SMP machine
+- */
+-#define PMAC_FTR_RESET_CPU PMAC_FTR_DEF(11)
+-
+-/* PMAC_FTR_USB_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable an USB cell, along with the power of the USB "pad"
+- * on keylargo based machines
+- */
+-#define PMAC_FTR_USB_ENABLE PMAC_FTR_DEF(12)
+-
+-/* PMAC_FTR_1394_ENABLE (struct device_node* node, 0, int value)
+- * enable/disable the firewire cell of an uninorth ASIC.
+- */
+-#define PMAC_FTR_1394_ENABLE PMAC_FTR_DEF(13)
+-
+-/* PMAC_FTR_1394_CABLE_POWER (struct device_node* node, 0, int value)
+- * enable/disable the firewire cable power supply of the uninorth
+- * firewire cell
+- */
+-#define PMAC_FTR_1394_CABLE_POWER PMAC_FTR_DEF(14)
+-
+-/* PMAC_FTR_SLEEP_STATE (struct device_node* node, 0, int value)
+- * set the sleep state of the motherboard.
+- *
+- * Pass -1 as value to query for sleep capability
+- * Pass 1 to set IOs to sleep
+- * Pass 0 to set IOs to wake
+- */
+-#define PMAC_FTR_SLEEP_STATE PMAC_FTR_DEF(15)
+-
+-/* PMAC_FTR_GET_MB_INFO (NULL, selector, 0)
+- *
+- * returns some motherboard infos.
+- * selector: 0 - model id
+- * 1 - model flags (capabilities)
+- * 2 - model name (cast to const char *)
+- */
+-#define PMAC_FTR_GET_MB_INFO PMAC_FTR_DEF(16)
+-#define PMAC_MB_INFO_MODEL 0
+-#define PMAC_MB_INFO_FLAGS 1
+-#define PMAC_MB_INFO_NAME 2
+-
+-/* PMAC_FTR_READ_GPIO (NULL, int index, 0)
+- *
+- * read a GPIO from a mac-io controller of type KeyLargo or Pangea.
+- * the value returned is a byte (positive), or a negative error code
+- */
+-#define PMAC_FTR_READ_GPIO PMAC_FTR_DEF(17)
+-
+-/* PMAC_FTR_WRITE_GPIO (NULL, int index, int value)
+- *
+- * write a GPIO of a mac-io controller of type KeyLargo or Pangea.
+- */
+-#define PMAC_FTR_WRITE_GPIO PMAC_FTR_DEF(18)
+-
+-/* PMAC_FTR_ENABLE_MPIC
+- *
+- * Enable the MPIC cell
+- */
+-#define PMAC_FTR_ENABLE_MPIC PMAC_FTR_DEF(19)
+-
+-/* PMAC_FTR_AACK_DELAY_ENABLE (NULL, int enable, 0)
+- *
+- * Enable/disable the AACK delay on the northbridge for systems using DFS
+- */
+-#define PMAC_FTR_AACK_DELAY_ENABLE PMAC_FTR_DEF(20)
+-
+-/* PMAC_FTR_DEVICE_CAN_WAKE
+- *
+- * Used by video drivers to inform system that they can actually perform
+- * wakeup from sleep
+- */
+-#define PMAC_FTR_DEVICE_CAN_WAKE PMAC_FTR_DEF(22)
+-
+-
+-/* Don't use those directly, they are for the sake of pmac_setup.c */
+-extern long pmac_do_feature_call(unsigned int selector, ...);
+-extern void pmac_feature_init(void);
+-
+-/* Video suspend tweak */
+-extern void pmac_set_early_video_resume(void (*proc)(void *data), void *data);
+-extern void pmac_call_early_video_resume(void);
+-
+-#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
+-
+-/* The AGP driver registers itself here */
+-extern void pmac_register_agp_pm(struct pci_dev *bridge,
+- int (*suspend)(struct pci_dev *bridge),
+- int (*resume)(struct pci_dev *bridge));
+-
+-/* Those are meant to be used by video drivers to deal with AGP
+- * suspend resume properly
+- */
+-extern void pmac_suspend_agp_for_card(struct pci_dev *dev);
+-extern void pmac_resume_agp_for_card(struct pci_dev *dev);
+-
+-/* Used by the via-pmu driver for suspend/resume
+- */
+-extern void pmac_tweak_clock_spreading(int enable);
+-
+-/*
+- * The part below is for use by macio_asic.c only, do not rely
+- * on the data structures or constants below in a normal driver
+- *
+- */
+-
+-#define MAX_MACIO_CHIPS 2
+-
+-enum {
+- macio_unknown = 0,
+- macio_grand_central,
+- macio_ohare,
+- macio_ohareII,
+- macio_heathrow,
+- macio_gatwick,
+- macio_paddington,
+- macio_keylargo,
+- macio_pangea,
+- macio_intrepid,
+- macio_keylargo2,
+-};
+-
+-struct macio_chip
+-{
+- struct device_node *of_node;
+- int type;
+- const char *name;
+- int rev;
+- volatile u32 __iomem *base;
+- unsigned long flags;
+-
+- /* For use by macio_asic PCI driver */
+- struct macio_bus lbus;
+-};
+-
+-extern struct macio_chip macio_chips[MAX_MACIO_CHIPS];
+-
+-#define MACIO_FLAG_SCCA_ON 0x00000001
+-#define MACIO_FLAG_SCCB_ON 0x00000002
+-#define MACIO_FLAG_SCC_LOCKED 0x00000004
+-#define MACIO_FLAG_AIRPORT_ON 0x00000010
+-#define MACIO_FLAG_FW_SUPPORTED 0x00000020
+-
+-extern struct macio_chip* macio_find(struct device_node* child, int type);
+-
+-#define MACIO_FCR32(macio, r) ((macio)->base + ((r) >> 2))
+-#define MACIO_FCR8(macio, r) (((volatile u8 __iomem *)((macio)->base)) + (r))
+-
+-#define MACIO_IN32(r) (in_le32(MACIO_FCR32(macio,r)))
+-#define MACIO_OUT32(r,v) (out_le32(MACIO_FCR32(macio,r), (v)))
+-#define MACIO_BIS(r,v) (MACIO_OUT32((r), MACIO_IN32(r) | (v)))
+-#define MACIO_BIC(r,v) (MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
+-#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r)))
+-#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v)))
+-
+-#endif /* __PPC_ASM_PMAC_FEATURE_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/pmac_low_i2c.h b/include/asm-ppc/pmac_low_i2c.h
+deleted file mode 100644
+--- a/include/asm-ppc/pmac_low_i2c.h
++++ /dev/null
+@@ -1,43 +0,0 @@
+-/*
+- * include/asm-ppc/pmac_low_i2c.h
+- *
+- * Copyright (C) 2003 Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- */
+-#ifndef __PMAC_LOW_I2C_H__
+-#define __PMAC_LOW_I2C_H__
+-
+-/* i2c mode (based on the platform functions format) */
+-enum {
+- pmac_low_i2c_mode_dumb = 1,
+- pmac_low_i2c_mode_std = 2,
+- pmac_low_i2c_mode_stdsub = 3,
+- pmac_low_i2c_mode_combined = 4,
+-};
+-
+-/* RW bit in address */
+-enum {
+- pmac_low_i2c_read = 0x01,
+- pmac_low_i2c_write = 0x00
+-};
+-
+-/* Init, called early during boot */
+-extern void pmac_init_low_i2c(void);
+-
+-/* Locking functions exposed to i2c-keywest */
+-int pmac_low_i2c_lock(struct device_node *np);
+-int pmac_low_i2c_unlock(struct device_node *np);
+-
+-/* Access functions for platform code */
+-int pmac_low_i2c_open(struct device_node *np, int channel);
+-int pmac_low_i2c_close(struct device_node *np);
+-int pmac_low_i2c_setmode(struct device_node *np, int mode);
+-int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len);
+-
+-
+-#endif /* __PMAC_LOW_I2C_H__ */
+diff --git a/include/asm-ppc/posix_types.h b/include/asm-ppc/posix_types.h
+deleted file mode 100644
+--- a/include/asm-ppc/posix_types.h
++++ /dev/null
+@@ -1,111 +0,0 @@
+-#ifndef _PPC_POSIX_TYPES_H
+-#define _PPC_POSIX_TYPES_H
+-
+-/*
+- * This file is generally used by user-level software, so you need to
+- * be a little careful about namespace pollution etc. Also, we cannot
+- * assume GCC is being used.
+- */
+-
+-typedef unsigned long __kernel_ino_t;
+-typedef unsigned int __kernel_mode_t;
+-typedef unsigned short __kernel_nlink_t;
+-typedef long __kernel_off_t;
+-typedef int __kernel_pid_t;
+-typedef unsigned int __kernel_uid_t;
+-typedef unsigned int __kernel_gid_t;
+-typedef unsigned int __kernel_size_t;
+-typedef int __kernel_ssize_t;
+-typedef long __kernel_ptrdiff_t;
+-typedef long __kernel_time_t;
+-typedef long __kernel_suseconds_t;
+-typedef long __kernel_clock_t;
+-typedef int __kernel_timer_t;
+-typedef int __kernel_clockid_t;
+-typedef int __kernel_daddr_t;
+-typedef char * __kernel_caddr_t;
+-typedef short __kernel_ipc_pid_t;
+-typedef unsigned short __kernel_uid16_t;
+-typedef unsigned short __kernel_gid16_t;
+-typedef unsigned int __kernel_uid32_t;
+-typedef unsigned int __kernel_gid32_t;
+-
+-typedef unsigned int __kernel_old_uid_t;
+-typedef unsigned int __kernel_old_gid_t;
+-typedef unsigned int __kernel_old_dev_t;
+-
+-#ifdef __GNUC__
+-typedef long long __kernel_loff_t;
+-#endif
+-
+-typedef struct {
+- int val[2];
+-} __kernel_fsid_t;
+-
+-#ifndef __GNUC__
+-
+-#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+-#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+-#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+-#define __FD_ZERO(set) \
+- ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+-
+-#else /* __GNUC__ */
+-
+-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
+- || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+-/* With GNU C, use inline functions instead so args are evaluated only once: */
+-
+-#undef __FD_SET
+-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+-{
+- unsigned long _tmp = fd / __NFDBITS;
+- unsigned long _rem = fd % __NFDBITS;
+- fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+-}
+-
+-#undef __FD_CLR
+-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+-{
+- unsigned long _tmp = fd / __NFDBITS;
+- unsigned long _rem = fd % __NFDBITS;
+- fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+-}
+-
+-#undef __FD_ISSET
+-static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
+-{
+- unsigned long _tmp = fd / __NFDBITS;
+- unsigned long _rem = fd % __NFDBITS;
+- return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+-}
+-
+-/*
+- * This will unroll the loop for the normal constant case (8 ints,
+- * for a 256-bit fd_set)
+- */
+-#undef __FD_ZERO
+-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+-{
+- unsigned int *tmp = (unsigned int *)p->fds_bits;
+- int i;
+-
+- if (__builtin_constant_p(__FDSET_LONGS)) {
+- switch (__FDSET_LONGS) {
+- case 8:
+- tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+- tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+- return;
+- }
+- }
+- i = __FDSET_LONGS;
+- while (i) {
+- i--;
+- *tmp = 0;
+- tmp++;
+- }
+-}
+-
+-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+-#endif /* __GNUC__ */
+-#endif /* _PPC_POSIX_TYPES_H */
+diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h
+deleted file mode 100644
+--- a/include/asm-ppc/ppc_asm.h
++++ /dev/null
+@@ -1,350 +0,0 @@
+-/*
+- * include/asm-ppc/ppc_asm.h
+- *
+- * Definitions used by various bits of low-level assembly code on PowerPC.
+- *
+- * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
+- *
+- * 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>
+-
+-/*
+- * Macros for storing registers into and loading registers from
+- * exception frames.
+- */
+-#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
+-#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+-#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+-#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+-#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+-#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
+-#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+-#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+-#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+-#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+-
+-#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \
+- SAVE_10GPRS(22, base)
+-#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); \
+- REST_10GPRS(22, base)
+-
+-#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base)
+-#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
+-#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
+-#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
+-#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
+-#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
+-#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base)
+-#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
+-#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
+-#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
+-#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
+-#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
+-
+-#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base
+-#define SAVE_2VR(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
+-#define SAVE_4VR(n,b,base) SAVE_2VR(n,b,base); SAVE_2VR(n+2,b,base)
+-#define SAVE_8VR(n,b,base) SAVE_4VR(n,b,base); SAVE_4VR(n+4,b,base)
+-#define SAVE_16VR(n,b,base) SAVE_8VR(n,b,base); SAVE_8VR(n+8,b,base)
+-#define SAVE_32VR(n,b,base) SAVE_16VR(n,b,base); SAVE_16VR(n+16,b,base)
+-#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base
+-#define REST_2VR(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
+-#define REST_4VR(n,b,base) REST_2VR(n,b,base); REST_2VR(n+2,b,base)
+-#define REST_8VR(n,b,base) REST_4VR(n,b,base); REST_4VR(n+4,b,base)
+-#define REST_16VR(n,b,base) REST_8VR(n,b,base); REST_8VR(n+8,b,base)
+-#define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base)
+-
+-#define SAVE_EVR(n,s,base) evmergehi s,s,n; stw s,THREAD_EVR0+4*(n)(base)
+-#define SAVE_2EVR(n,s,base) SAVE_EVR(n,s,base); SAVE_EVR(n+1,s,base)
+-#define SAVE_4EVR(n,s,base) SAVE_2EVR(n,s,base); SAVE_2EVR(n+2,s,base)
+-#define SAVE_8EVR(n,s,base) SAVE_4EVR(n,s,base); SAVE_4EVR(n+4,s,base)
+-#define SAVE_16EVR(n,s,base) SAVE_8EVR(n,s,base); SAVE_8EVR(n+8,s,base)
+-#define SAVE_32EVR(n,s,base) SAVE_16EVR(n,s,base); SAVE_16EVR(n+16,s,base)
+-
+-#define REST_EVR(n,s,base) lwz s,THREAD_EVR0+4*(n)(base); evmergelo n,s,n
+-#define REST_2EVR(n,s,base) REST_EVR(n,s,base); REST_EVR(n+1,s,base)
+-#define REST_4EVR(n,s,base) REST_2EVR(n,s,base); REST_2EVR(n+2,s,base)
+-#define REST_8EVR(n,s,base) REST_4EVR(n,s,base); REST_4EVR(n+4,s,base)
+-#define REST_16EVR(n,s,base) REST_8EVR(n,s,base); REST_8EVR(n+8,s,base)
+-#define REST_32EVR(n,s,base) REST_16EVR(n,s,base); REST_16EVR(n+16,s,base)
+-
+-#ifdef CONFIG_PPC601_SYNC_FIX
+-#define SYNC \
+-BEGIN_FTR_SECTION \
+- sync; \
+- isync; \
+-END_FTR_SECTION_IFSET(CPU_FTR_601)
+-#define SYNC_601 \
+-BEGIN_FTR_SECTION \
+- sync; \
+-END_FTR_SECTION_IFSET(CPU_FTR_601)
+-#define ISYNC_601 \
+-BEGIN_FTR_SECTION \
+- isync; \
+-END_FTR_SECTION_IFSET(CPU_FTR_601)
+-#else
+-#define SYNC
+-#define SYNC_601
+-#define ISYNC_601
+-#endif
+-
+-#ifndef CONFIG_SMP
+-#define TLBSYNC
+-#else /* CONFIG_SMP */
+-/* tlbsync is not implemented on 601 */
+-#define TLBSYNC \
+-BEGIN_FTR_SECTION \
+- tlbsync; \
+- sync; \
+-END_FTR_SECTION_IFCLR(CPU_FTR_601)
+-#endif
+-
+-/*
+- * This instruction is not implemented on the PPC 603 or 601; however, on
+- * the 403GCX and 405GP tlbia IS defined and tlbie is not.
+- * All of these instructions exist in the 8xx, they have magical powers,
+- * and they must be used.
+- */
+-
+-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+-#define tlbia \
+- li r4,1024; \
+- mtctr r4; \
+- lis r4,KERNELBASE at h; \
+-0: tlbie r4; \
+- addi r4,r4,0x1000; \
+- bdnz 0b
+-#endif
+-
+-#ifdef CONFIG_BOOKE
+-#define tophys(rd,rs) \
+- addis rd,rs,0
+-
+-#define tovirt(rd,rs) \
+- addis rd,rs,0
+-
+-#else /* CONFIG_BOOKE */
+-/*
+- * On APUS (Amiga PowerPC cpu upgrade board), we don't know the
+- * physical base address of RAM at compile time.
+- */
+-#define tophys(rd,rs) \
+-0: addis rd,rs,-KERNELBASE at h; \
+- .section ".vtop_fixup","aw"; \
+- .align 1; \
+- .long 0b; \
+- .previous
+-
+-#define tovirt(rd,rs) \
+-0: addis rd,rs,KERNELBASE at h; \
+- .section ".ptov_fixup","aw"; \
+- .align 1; \
+- .long 0b; \
+- .previous
+-#endif /* CONFIG_BOOKE */
+-
+-/*
+- * On 64-bit cpus, we use the rfid instruction instead of rfi, but
+- * we then have to make sure we preserve the top 32 bits except for
+- * the 64-bit mode bit, which we clear.
+- */
+-#ifdef CONFIG_PPC64BRIDGE
+-#define FIX_SRR1(ra, rb) \
+- mr rb,ra; \
+- mfmsr ra; \
+- clrldi ra,ra,1; /* turn off 64-bit mode */ \
+- rldimi ra,rb,0,32
+-#define RFI .long 0x4c000024 /* rfid instruction */
+-#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* mtmsrd */
+-#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */
+-
+-#else
+-#define FIX_SRR1(ra, rb)
+-#ifndef CONFIG_40x
+-#define RFI rfi
+-#else
+-#define RFI rfi; b . /* Prevent prefetch past rfi */
+-#endif
+-#define MTMSRD(r) mtmsr r
+-#define CLR_TOP32(r)
+-#endif /* CONFIG_PPC64BRIDGE */
+-
+-#define RFCI .long 0x4c000066 /* rfci instruction */
+-#define RFDI .long 0x4c00004e /* rfdi instruction */
+-#define RFMCI .long 0x4c00004c /* rfmci instruction */
+-
+-#ifdef CONFIG_IBM405_ERR77
+-#define PPC405_ERR77(ra,rb) dcbt ra, rb;
+-#define PPC405_ERR77_SYNC sync;
+-#else
+-#define PPC405_ERR77(ra,rb)
+-#define PPC405_ERR77_SYNC
+-#endif
+-
+-#ifdef CONFIG_IBM440EP_ERR42
+-#define PPC440EP_ERR42 isync
+-#else
+-#define PPC440EP_ERR42
+-#endif
+-
+-/* The boring bits... */
+-
+-/* Condition Register Bit Fields */
+-
+-#define cr0 0
+-#define cr1 1
+-#define cr2 2
+-#define cr3 3
+-#define cr4 4
+-#define cr5 5
+-#define cr6 6
+-#define cr7 7
+-
+-
+-/* General Purpose Registers (GPRs) */
+-
+-#define r0 0
+-#define r1 1
+-#define r2 2
+-#define r3 3
+-#define r4 4
+-#define r5 5
+-#define r6 6
+-#define r7 7
+-#define r8 8
+-#define r9 9
+-#define r10 10
+-#define r11 11
+-#define r12 12
+-#define r13 13
+-#define r14 14
+-#define r15 15
+-#define r16 16
+-#define r17 17
+-#define r18 18
+-#define r19 19
+-#define r20 20
+-#define r21 21
+-#define r22 22
+-#define r23 23
+-#define r24 24
+-#define r25 25
+-#define r26 26
+-#define r27 27
+-#define r28 28
+-#define r29 29
+-#define r30 30
+-#define r31 31
+-
+-
+-/* Floating Point Registers (FPRs) */
+-
+-#define fr0 0
+-#define fr1 1
+-#define fr2 2
+-#define fr3 3
+-#define fr4 4
+-#define fr5 5
+-#define fr6 6
+-#define fr7 7
+-#define fr8 8
+-#define fr9 9
+-#define fr10 10
+-#define fr11 11
+-#define fr12 12
+-#define fr13 13
+-#define fr14 14
+-#define fr15 15
+-#define fr16 16
+-#define fr17 17
+-#define fr18 18
+-#define fr19 19
+-#define fr20 20
+-#define fr21 21
+-#define fr22 22
+-#define fr23 23
+-#define fr24 24
+-#define fr25 25
+-#define fr26 26
+-#define fr27 27
+-#define fr28 28
+-#define fr29 29
+-#define fr30 30
+-#define fr31 31
+-
+-#define vr0 0
+-#define vr1 1
+-#define vr2 2
+-#define vr3 3
+-#define vr4 4
+-#define vr5 5
+-#define vr6 6
+-#define vr7 7
+-#define vr8 8
+-#define vr9 9
+-#define vr10 10
+-#define vr11 11
+-#define vr12 12
+-#define vr13 13
+-#define vr14 14
+-#define vr15 15
+-#define vr16 16
+-#define vr17 17
+-#define vr18 18
+-#define vr19 19
+-#define vr20 20
+-#define vr21 21
+-#define vr22 22
+-#define vr23 23
+-#define vr24 24
+-#define vr25 25
+-#define vr26 26
+-#define vr27 27
+-#define vr28 28
+-#define vr29 29
+-#define vr30 30
+-#define vr31 31
+-
+-#define evr0 0
+-#define evr1 1
+-#define evr2 2
+-#define evr3 3
+-#define evr4 4
+-#define evr5 5
+-#define evr6 6
+-#define evr7 7
+-#define evr8 8
+-#define evr9 9
+-#define evr10 10
+-#define evr11 11
+-#define evr12 12
+-#define evr13 13
+-#define evr14 14
+-#define evr15 15
+-#define evr16 16
+-#define evr17 17
+-#define evr18 18
+-#define evr19 19
+-#define evr20 20
+-#define evr21 21
+-#define evr22 22
+-#define evr23 23
+-#define evr24 24
+-#define evr25 25
+-#define evr26 26
+-#define evr27 27
+-#define evr28 28
+-#define evr29 29
+-#define evr30 30
+-#define evr31 31
+-
+-/* some stab codes */
+-#define N_FUN 36
+-#define N_RSYM 64
+-#define N_SLINE 68
+-#define N_SO 100
+diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
+--- a/include/asm-ppc/ppc_sys.h
++++ b/include/asm-ppc/ppc_sys.h
+@@ -18,7 +18,7 @@
+ #define __ASM_PPC_SYS_H
+
+ #include <linux/init.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/types.h>
+
+ #if defined(CONFIG_8260)
+diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
+deleted file mode 100644
+--- a/include/asm-ppc/processor.h
++++ /dev/null
+@@ -1,201 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef __ASM_PPC_PROCESSOR_H
+-#define __ASM_PPC_PROCESSOR_H
+-
+-/*
+- * Default implementation of macro that returns current
+- * instruction pointer ("program counter").
+- */
+-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+-
+-#include <linux/config.h>
+-#include <linux/stringify.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/types.h>
+-#include <asm/mpc8xx.h>
+-#include <asm/reg.h>
+-
+-/* We only need to define a new _MACH_xxx for machines which are part of
+- * a configuration which supports more than one type of different machine.
+- * This is currently limited to CONFIG_PPC_MULTIPLATFORM and CHRP/PReP/PMac.
+- * -- Tom
+- */
+-#define _MACH_prep 0x00000001
+-#define _MACH_Pmac 0x00000002 /* pmac or pmac clone (non-chrp) */
+-#define _MACH_chrp 0x00000004 /* chrp machine */
+-
+-/* see residual.h for these */
+-#define _PREP_Motorola 0x01 /* motorola prep */
+-#define _PREP_Firm 0x02 /* firmworks prep */
+-#define _PREP_IBM 0x00 /* ibm prep */
+-#define _PREP_Bull 0x03 /* bull prep */
+-
+-/* these are arbitrary */
+-#define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */
+-#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
+-#define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */
+-
+-#define _GLOBAL(n)\
+- .stabs __stringify(n:F-1),N_FUN,0,0,n;\
+- .globl n;\
+-n:
+-
+-/*
+- * this is the minimum allowable io space due to the location
+- * of the io areas on prep (first one at 0x80000000) but
+- * as soon as I get around to remapping the io areas with the BATs
+- * to match the mac we can raise this. -- Cort
+- */
+-#define TASK_SIZE (CONFIG_TASK_SIZE)
+-
+-#ifndef __ASSEMBLY__
+-#ifdef CONFIG_PPC_MULTIPLATFORM
+-extern int _machine;
+-
+-/* what kind of prep workstation we are */
+-extern int _prep_type;
+-extern int _chrp_type;
+-
+-/*
+- * This is used to identify the board type from a given PReP board
+- * vendor. Board revision is also made available.
+- */
+-extern unsigned char ucSystemType;
+-extern unsigned char ucBoardRev;
+-extern unsigned char ucBoardRevMaj, ucBoardRevMin;
+-#else
+-#define _machine 0
+-#endif /* CONFIG_PPC_MULTIPLATFORM */
+-
+-struct task_struct;
+-void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
+-void release_thread(struct task_struct *);
+-
+-/* Prepare to copy thread state - unlazy all lazy status */
+-extern void prepare_to_copy(struct task_struct *tsk);
+-
+-/*
+- * Create a new kernel thread.
+- */
+-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+-
+-/* Lazy FPU handling on uni-processor */
+-extern struct task_struct *last_task_used_math;
+-extern struct task_struct *last_task_used_altivec;
+-extern struct task_struct *last_task_used_spe;
+-
+-/* This decides where the kernel will search for a free chunk of vm
+- * space during mmap's.
+- */
+-#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
+-
+-typedef struct {
+- unsigned long seg;
+-} mm_segment_t;
+-
+-struct thread_struct {
+- unsigned long ksp; /* Kernel stack pointer */
+- struct pt_regs *regs; /* Pointer to saved register state */
+- mm_segment_t fs; /* for get_fs() validation */
+- void *pgdir; /* root of page-table tree */
+- int fpexc_mode; /* floating-point exception mode */
+- signed long last_syscall;
+-#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
+- unsigned long dbcr0; /* debug control register values */
+- unsigned long dbcr1;
+-#endif
+- double fpr[32]; /* Complete floating point set */
+- unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */
+- unsigned long fpscr; /* Floating point status */
+-#ifdef CONFIG_ALTIVEC
+- /* Complete AltiVec register set */
+- vector128 vr[32] __attribute((aligned(16)));
+- /* AltiVec status */
+- vector128 vscr __attribute((aligned(16)));
+- unsigned long vrsave;
+- int used_vr; /* set if process has used altivec */
+-#endif /* CONFIG_ALTIVEC */
+-#ifdef CONFIG_SPE
+- unsigned long evr[32]; /* upper 32-bits of SPE regs */
+- u64 acc; /* Accumulator */
+- unsigned long spefscr; /* SPE & eFP status */
+- int used_spe; /* set if process has used spe */
+-#endif /* CONFIG_SPE */
+-};
+-
+-#define ARCH_MIN_TASKALIGN 16
+-
+-#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
+-
+-#define INIT_THREAD { \
+- .ksp = INIT_SP, \
+- .fs = KERNEL_DS, \
+- .pgdir = swapper_pg_dir, \
+- .fpexc_mode = MSR_FE0 | MSR_FE1, \
+-}
+-
+-/*
+- * Return saved PC of a blocked thread. For now, this is the "user" PC
+- */
+-#define thread_saved_pc(tsk) \
+- ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
+-
+-unsigned long get_wchan(struct task_struct *p);
+-
+-#define KSTK_EIP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
+-#define KSTK_ESP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0)
+-
+-/* Get/set floating-point exception mode */
+-#define GET_FPEXC_CTL(tsk, adr) get_fpexc_mode((tsk), (adr))
+-#define SET_FPEXC_CTL(tsk, val) set_fpexc_mode((tsk), (val))
+-
+-extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr);
+-extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val);
+-
+-static inline unsigned int __unpack_fe01(unsigned int msr_bits)
+-{
+- return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
+-}
+-
+-static inline unsigned int __pack_fe01(unsigned int fpmode)
+-{
+- return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1);
+-}
+-
+-/* in process.c - for early bootup debug -- Cort */
+-int ll_printk(const char *, ...);
+-void ll_puts(const char *);
+-
+-/* In misc.c */
+-void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+-
+-#define have_of (_machine == _MACH_chrp || _machine == _MACH_Pmac)
+-
+-#define cpu_relax() barrier()
+-
+-/*
+- * Prefetch macros.
+- */
+-#define ARCH_HAS_PREFETCH
+-#define ARCH_HAS_PREFETCHW
+-#define ARCH_HAS_SPINLOCK_PREFETCH
+-
+-extern inline void prefetch(const void *x)
+-{
+- __asm__ __volatile__ ("dcbt 0,%0" : : "r" (x));
+-}
+-
+-extern inline void prefetchw(const void *x)
+-{
+- __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x));
+-}
+-
+-#define spin_lock_prefetch(x) prefetchw(x)
+-
+-extern int emulate_altivec(struct pt_regs *regs);
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#endif /* __ASM_PPC_PROCESSOR_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h
+--- a/include/asm-ppc/ptrace.h
++++ b/include/asm-ppc/ptrace.h
+@@ -57,7 +57,7 @@ extern unsigned long profile_pc(struct p
+
+ #define force_successful_syscall_return() \
+ do { \
+- current_thread_info()->local_flags |= _TIFL_FORCE_NOERROR; \
++ current_thread_info()->syscall_noerror = 1; \
+ } while(0)
+
+ /*
+diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
+deleted file mode 100644
+--- a/include/asm-ppc/reg.h
++++ /dev/null
+@@ -1,440 +0,0 @@
+-/*
+- * Contains the definition of registers common to all PowerPC variants.
+- * If a register definition has been changed in a different PowerPC
+- * variant, we will case it in #ifndef XXX ... #endif, and have the
+- * number used in the Programming Environments Manual For 32-Bit
+- * Implementations of the PowerPC Architecture (a.k.a. Green Book) here.
+- */
+-
+-#ifdef __KERNEL__
+-#ifndef __ASM_PPC_REGS_H__
+-#define __ASM_PPC_REGS_H__
+-
+-#include <linux/stringify.h>
+-
+-/* Pickup Book E specific registers. */
+-#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+-#include <asm/reg_booke.h>
+-#endif
+-
+-/* Machine State Register (MSR) Fields */
+-#define MSR_SF (1<<63)
+-#define MSR_ISF (1<<61)
+-#define MSR_VEC (1<<25) /* Enable AltiVec */
+-#define MSR_POW (1<<18) /* Enable Power Management */
+-#define MSR_WE (1<<18) /* Wait State Enable */
+-#define MSR_TGPR (1<<17) /* TLB Update registers in use */
+-#define MSR_CE (1<<17) /* Critical Interrupt Enable */
+-#define MSR_ILE (1<<16) /* Interrupt Little Endian */
+-#define MSR_EE (1<<15) /* External Interrupt Enable */
+-#define MSR_PR (1<<14) /* Problem State / Privilege Level */
+-#define MSR_FP (1<<13) /* Floating Point enable */
+-#define MSR_ME (1<<12) /* Machine Check Enable */
+-#define MSR_FE0 (1<<11) /* Floating Exception mode 0 */
+-#define MSR_SE (1<<10) /* Single Step */
+-#define MSR_BE (1<<9) /* Branch Trace */
+-#define MSR_DE (1<<9) /* Debug Exception Enable */
+-#define MSR_FE1 (1<<8) /* Floating Exception mode 1 */
+-#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
+-#define MSR_IR (1<<5) /* Instruction Relocate */
+-#define MSR_DR (1<<4) /* Data Relocate */
+-#define MSR_PE (1<<3) /* Protection Enable */
+-#define MSR_PX (1<<2) /* Protection Exclusive Mode */
+-#define MSR_RI (1<<1) /* Recoverable Exception */
+-#define MSR_LE (1<<0) /* Little Endian */
+-
+-/* Default MSR for kernel mode. */
+-#ifdef CONFIG_APUS_FAST_EXCEPT
+-#define MSR_KERNEL (MSR_ME|MSR_IP|MSR_RI|MSR_IR|MSR_DR)
+-#endif
+-
+-#ifndef MSR_KERNEL
+-#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR)
+-#endif
+-
+-#define MSR_USER (MSR_KERNEL|MSR_PR|MSR_EE)
+-
+-/* Floating Point Status and Control Register (FPSCR) Fields */
+-#define FPSCR_FX 0x80000000 /* FPU exception summary */
+-#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */
+-#define FPSCR_VX 0x20000000 /* Invalid operation summary */
+-#define FPSCR_OX 0x10000000 /* Overflow exception summary */
+-#define FPSCR_UX 0x08000000 /* Underflow exception summary */
+-#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */
+-#define FPSCR_XX 0x02000000 /* Inexact exception summary */
+-#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */
+-#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */
+-#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */
+-#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */
+-#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */
+-#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */
+-#define FPSCR_FR 0x00040000 /* Fraction rounded */
+-#define FPSCR_FI 0x00020000 /* Fraction inexact */
+-#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */
+-#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */
+-#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */
+-#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */
+-#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */
+-#define FPSCR_VE 0x00000080 /* Invalid op exception enable */
+-#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */
+-#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */
+-#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */
+-#define FPSCR_XE 0x00000008 /* FP inexact exception enable */
+-#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */
+-#define FPSCR_RN 0x00000003 /* FPU rounding control */
+-
+-/* Special Purpose Registers (SPRNs)*/
+-#define SPRN_CTR 0x009 /* Count Register */
+-#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+-#define SPRN_DAR 0x013 /* Data Address Register */
+-#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
+-#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
+-#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */
+-#define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */
+-#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
+-#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
+-#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
+-#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */
+-#define SPRN_DBAT1U 0x21A /* Data BAT 1 Upper Register */
+-#define SPRN_DBAT2L 0x21D /* Data BAT 2 Lower Register */
+-#define SPRN_DBAT2U 0x21C /* Data BAT 2 Upper Register */
+-#define SPRN_DBAT3L 0x21F /* Data BAT 3 Lower Register */
+-#define SPRN_DBAT3U 0x21E /* Data BAT 3 Upper Register */
+-#define SPRN_DBAT4L 0x239 /* Data BAT 4 Lower Register */
+-#define SPRN_DBAT4U 0x238 /* Data BAT 4 Upper Register */
+-#define SPRN_DBAT5L 0x23B /* Data BAT 5 Lower Register */
+-#define SPRN_DBAT5U 0x23A /* Data BAT 5 Upper Register */
+-#define SPRN_DBAT6L 0x23D /* Data BAT 6 Lower Register */
+-#define SPRN_DBAT6U 0x23C /* Data BAT 6 Upper Register */
+-#define SPRN_DBAT7L 0x23F /* Data BAT 7 Lower Register */
+-#define SPRN_DBAT7U 0x23E /* Data BAT 7 Upper Register */
+-
+-#define SPRN_DEC 0x016 /* Decrement Register */
+-#define SPRN_DER 0x095 /* Debug Enable Regsiter */
+-#define DER_RSTE 0x40000000 /* Reset Interrupt */
+-#define DER_CHSTPE 0x20000000 /* Check Stop */
+-#define DER_MCIE 0x10000000 /* Machine Check Interrupt */
+-#define DER_EXTIE 0x02000000 /* External Interrupt */
+-#define DER_ALIE 0x01000000 /* Alignment Interrupt */
+-#define DER_PRIE 0x00800000 /* Program Interrupt */
+-#define DER_FPUVIE 0x00400000 /* FP Unavailable Interrupt */
+-#define DER_DECIE 0x00200000 /* Decrementer Interrupt */
+-#define DER_SYSIE 0x00040000 /* System Call Interrupt */
+-#define DER_TRE 0x00020000 /* Trace Interrupt */
+-#define DER_SEIE 0x00004000 /* FP SW Emulation Interrupt */
+-#define DER_ITLBMSE 0x00002000 /* Imp. Spec. Instruction TLB Miss */
+-#define DER_ITLBERE 0x00001000 /* Imp. Spec. Instruction TLB Error */
+-#define DER_DTLBMSE 0x00000800 /* Imp. Spec. Data TLB Miss */
+-#define DER_DTLBERE 0x00000400 /* Imp. Spec. Data TLB Error */
+-#define DER_LBRKE 0x00000008 /* Load/Store Breakpoint Interrupt */
+-#define DER_IBRKE 0x00000004 /* Instruction Breakpoint Interrupt */
+-#define DER_EBRKE 0x00000002 /* External Breakpoint Interrupt */
+-#define DER_DPIE 0x00000001 /* Dev. Port Nonmaskable Request */
+-#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
+-#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+-#define SPRN_EAR 0x11A /* External Address Register */
+-#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
+-#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
+-#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
+-#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
+-#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
+-#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
+-#define HID0_SBCLK (1<<27)
+-#define HID0_EICE (1<<26)
+-#define HID0_TBEN (1<<26) /* Timebase enable - 745x */
+-#define HID0_ECLK (1<<25)
+-#define HID0_PAR (1<<24)
+-#define HID0_STEN (1<<24) /* Software table search enable - 745x */
+-#define HID0_HIGH_BAT (1<<23) /* Enable high BATs - 7455 */
+-#define HID0_DOZE (1<<23)
+-#define HID0_NAP (1<<22)
+-#define HID0_SLEEP (1<<21)
+-#define HID0_DPM (1<<20)
+-#define HID0_BHTCLR (1<<18) /* Clear branch history table - 7450 */
+-#define HID0_XAEN (1<<17) /* Extended addressing enable - 7450 */
+-#define HID0_NHR (1<<16) /* Not hard reset (software bit-7450)*/
+-#define HID0_ICE (1<<15) /* Instruction Cache Enable */
+-#define HID0_DCE (1<<14) /* Data Cache Enable */
+-#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
+-#define HID0_DLOCK (1<<12) /* Data Cache Lock */
+-#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
+-#define HID0_DCI (1<<10) /* Data Cache Invalidate */
+-#define HID0_SPD (1<<9) /* Speculative disable */
+-#define HID0_DAPUEN (1<<8) /* Debug APU enable */
+-#define HID0_SGE (1<<7) /* Store Gathering Enable */
+-#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
+-#define HID0_DFCA (1<<6) /* Data Cache Flush Assist */
+-#define HID0_LRSTK (1<<4) /* Link register stack - 745x */
+-#define HID0_BTIC (1<<5) /* Branch Target Instr Cache Enable */
+-#define HID0_ABE (1<<3) /* Address Broadcast Enable */
+-#define HID0_FOLD (1<<3) /* Branch Folding enable - 745x */
+-#define HID0_BHTE (1<<2) /* Branch History Table Enable */
+-#define HID0_BTCD (1<<1) /* Branch target cache disable */
+-#define HID0_NOPDST (1<<1) /* No-op dst, dstt, etc. instr. */
+-#define HID0_NOPTI (1<<0) /* No-op dcbt and dcbst instr. */
+-
+-#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+-#define HID1_EMCP (1<<31) /* 7450 Machine Check Pin Enable */
+-#define HID1_DFS (1<<22) /* 7447A Dynamic Frequency Scaling */
+-#define HID1_PC0 (1<<16) /* 7450 PLL_CFG[0] */
+-#define HID1_PC1 (1<<15) /* 7450 PLL_CFG[1] */
+-#define HID1_PC2 (1<<14) /* 7450 PLL_CFG[2] */
+-#define HID1_PC3 (1<<13) /* 7450 PLL_CFG[3] */
+-#define HID1_SYNCBE (1<<11) /* 7450 ABE for sync, eieio */
+-#define HID1_ABE (1<<10) /* 7450 Address Broadcast Enable */
+-#define HID1_PS (1<<16) /* 750FX PLL selection */
+-#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
+-#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+-#define SPRN_HID4 0x3F4 /* 970 HID4 */
+-#define SPRN_HID5 0x3F6 /* 970 HID5 */
+-#if !defined(SPRN_IAC1) && !defined(SPRN_IAC2)
+-#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
+-#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
+-#endif
+-#define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */
+-#define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */
+-#define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */
+-#define SPRN_IBAT1U 0x212 /* Instruction BAT 1 Upper Register */
+-#define SPRN_IBAT2L 0x215 /* Instruction BAT 2 Lower Register */
+-#define SPRN_IBAT2U 0x214 /* Instruction BAT 2 Upper Register */
+-#define SPRN_IBAT3L 0x217 /* Instruction BAT 3 Lower Register */
+-#define SPRN_IBAT3U 0x216 /* Instruction BAT 3 Upper Register */
+-#define SPRN_IBAT4L 0x231 /* Instruction BAT 4 Lower Register */
+-#define SPRN_IBAT4U 0x230 /* Instruction BAT 4 Upper Register */
+-#define SPRN_IBAT5L 0x233 /* Instruction BAT 5 Lower Register */
+-#define SPRN_IBAT5U 0x232 /* Instruction BAT 5 Upper Register */
+-#define SPRN_IBAT6L 0x235 /* Instruction BAT 6 Lower Register */
+-#define SPRN_IBAT6U 0x234 /* Instruction BAT 6 Upper Register */
+-#define SPRN_IBAT7L 0x237 /* Instruction BAT 7 Lower Register */
+-#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */
+-#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
+-#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
+-#define SPRN_ICTRL 0x3F3 /* 1011 7450 icache and interrupt ctrl */
+-#define ICTRL_EICE 0x08000000 /* enable icache parity errs */
+-#define ICTRL_EDC 0x04000000 /* enable dcache parity errs */
+-#define ICTRL_EICP 0x00000100 /* enable icache par. check */
+-#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
+-#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
+-#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
+-#define SPRN_L2CR2 0x3f8
+-#define L2CR_L2E 0x80000000 /* L2 enable */
+-#define L2CR_L2PE 0x40000000 /* L2 parity enable */
+-#define L2CR_L2SIZ_MASK 0x30000000 /* L2 size mask */
+-#define L2CR_L2SIZ_256KB 0x10000000 /* L2 size 256KB */
+-#define L2CR_L2SIZ_512KB 0x20000000 /* L2 size 512KB */
+-#define L2CR_L2SIZ_1MB 0x30000000 /* L2 size 1MB */
+-#define L2CR_L2CLK_MASK 0x0e000000 /* L2 clock mask */
+-#define L2CR_L2CLK_DISABLED 0x00000000 /* L2 clock disabled */
+-#define L2CR_L2CLK_DIV1 0x02000000 /* L2 clock / 1 */
+-#define L2CR_L2CLK_DIV1_5 0x04000000 /* L2 clock / 1.5 */
+-#define L2CR_L2CLK_DIV2 0x08000000 /* L2 clock / 2 */
+-#define L2CR_L2CLK_DIV2_5 0x0a000000 /* L2 clock / 2.5 */
+-#define L2CR_L2CLK_DIV3 0x0c000000 /* L2 clock / 3 */
+-#define L2CR_L2RAM_MASK 0x01800000 /* L2 RAM type mask */
+-#define L2CR_L2RAM_FLOW 0x00000000 /* L2 RAM flow through */
+-#define L2CR_L2RAM_PIPE 0x01000000 /* L2 RAM pipelined */
+-#define L2CR_L2RAM_PIPE_LW 0x01800000 /* L2 RAM pipelined latewr */
+-#define L2CR_L2DO 0x00400000 /* L2 data only */
+-#define L2CR_L2I 0x00200000 /* L2 global invalidate */
+-#define L2CR_L2CTL 0x00100000 /* L2 RAM control */
+-#define L2CR_L2WT 0x00080000 /* L2 write-through */
+-#define L2CR_L2TS 0x00040000 /* L2 test support */
+-#define L2CR_L2OH_MASK 0x00030000 /* L2 output hold mask */
+-#define L2CR_L2OH_0_5 0x00000000 /* L2 output hold 0.5 ns */
+-#define L2CR_L2OH_1_0 0x00010000 /* L2 output hold 1.0 ns */
+-#define L2CR_L2SL 0x00008000 /* L2 DLL slow */
+-#define L2CR_L2DF 0x00004000 /* L2 differential clock */
+-#define L2CR_L2BYP 0x00002000 /* L2 DLL bypass */
+-#define L2CR_L2IP 0x00000001 /* L2 GI in progress */
+-#define L2CR_L2IO_745x 0x00100000 /* L2 instr. only (745x) */
+-#define L2CR_L2DO_745x 0x00010000 /* L2 data only (745x) */
+-#define L2CR_L2REP_745x 0x00001000 /* L2 repl. algorithm (745x) */
+-#define L2CR_L2HWF_745x 0x00000800 /* L2 hardware flush (745x) */
+-#define SPRN_L3CR 0x3FA /* Level 3 Cache Control Regsiter */
+-#define L3CR_L3E 0x80000000 /* L3 enable */
+-#define L3CR_L3PE 0x40000000 /* L3 data parity enable */
+-#define L3CR_L3APE 0x20000000 /* L3 addr parity enable */
+-#define L3CR_L3SIZ 0x10000000 /* L3 size */
+-#define L3CR_L3CLKEN 0x08000000 /* L3 clock enable */
+-#define L3CR_L3RES 0x04000000 /* L3 special reserved bit */
+-#define L3CR_L3CLKDIV 0x03800000 /* L3 clock divisor */
+-#define L3CR_L3IO 0x00400000 /* L3 instruction only */
+-#define L3CR_L3SPO 0x00040000 /* L3 sample point override */
+-#define L3CR_L3CKSP 0x00030000 /* L3 clock sample point */
+-#define L3CR_L3PSP 0x0000e000 /* L3 P-clock sample point */
+-#define L3CR_L3REP 0x00001000 /* L3 replacement algorithm */
+-#define L3CR_L3HWF 0x00000800 /* L3 hardware flush */
+-#define L3CR_L3I 0x00000400 /* L3 global invalidate */
+-#define L3CR_L3RT 0x00000300 /* L3 SRAM type */
+-#define L3CR_L3NIRCA 0x00000080 /* L3 non-integer ratio clock adj. */
+-#define L3CR_L3DO 0x00000040 /* L3 data only mode */
+-#define L3CR_PMEN 0x00000004 /* L3 private memory enable */
+-#define L3CR_PMSIZ 0x00000001 /* L3 private memory size */
+-#define SPRN_MSSCR0 0x3f6 /* Memory Subsystem Control Register 0 */
+-#define SPRN_MSSSR0 0x3f7 /* Memory Subsystem Status Register 1 */
+-#define SPRN_LDSTCR 0x3f8 /* Load/Store control register */
+-#define SPRN_LDSTDB 0x3f4 /* */
+-#define SPRN_LR 0x008 /* Link Register */
+-#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */
+-#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */
+-#ifndef SPRN_PIR
+-#define SPRN_PIR 0x3FF /* Processor Identification Register */
+-#endif
+-#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */
+-#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */
+-#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */
+-#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */
+-#define SPRN_PTEHI 0x3D5 /* 981 7450 PTE HI word (S/W TLB load) */
+-#define SPRN_PTELO 0x3D6 /* 982 7450 PTE LO word (S/W TLB load) */
+-#define SPRN_PVR 0x11F /* Processor Version Register */
+-#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
+-#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
+-#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
+-#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
+-#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
+-#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
+-#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
+-#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
+-#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
+-#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
+-#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
+-#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
+-#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
+-#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+-#ifndef SPRN_SVR
+-#define SPRN_SVR 0x11E /* System Version Register */
+-#endif
+-#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
+-/* these bits were defined in inverted endian sense originally, ugh, confusing */
+-#define THRM1_TIN (1 << 31)
+-#define THRM1_TIV (1 << 30)
+-#define THRM1_THRES(x) ((x&0x7f)<<23)
+-#define THRM3_SITV(x) ((x&0x3fff)<<1)
+-#define THRM1_TID (1<<2)
+-#define THRM1_TIE (1<<1)
+-#define THRM1_V (1<<0)
+-#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
+-#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
+-#define THRM3_E (1<<0)
+-#define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */
+-#define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */
+-#define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */
+-#define SPRN_UPMC1 0x3A9 /* User Performance Counter Register 1 */
+-#define SPRN_UPMC2 0x3AA /* User Performance Counter Register 2 */
+-#define SPRN_UPMC3 0x3AD /* User Performance Counter Register 3 */
+-#define SPRN_UPMC4 0x3AE /* User Performance Counter Register 4 */
+-#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
+-#define SPRN_VRSAVE 0x100 /* Vector Register Save Register */
+-#define SPRN_XER 0x001 /* Fixed Point Exception Register */
+-
+-/* Bit definitions for MMCR0 and PMC1 / PMC2. */
+-#define MMCR0_PMC1_CYCLES (1 << 7)
+-#define MMCR0_PMC1_ICACHEMISS (5 << 7)
+-#define MMCR0_PMC1_DTLB (6 << 7)
+-#define MMCR0_PMC2_DCACHEMISS 0x6
+-#define MMCR0_PMC2_CYCLES 0x1
+-#define MMCR0_PMC2_ITLB 0x7
+-#define MMCR0_PMC2_LOADMISSTIME 0x5
+-#define MMCR0_PMXE (1 << 26)
+-
+-/* Processor Version Register */
+-
+-/* Processor Version Register (PVR) field extraction */
+-
+-#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+-#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+-
+-/*
+- * IBM has further subdivided the standard PowerPC 16-bit version and
+- * revision subfields of the PVR for the PowerPC 403s into the following:
+- */
+-
+-#define PVR_FAM(pvr) (((pvr) >> 20) & 0xFFF) /* Family field */
+-#define PVR_MEM(pvr) (((pvr) >> 16) & 0xF) /* Member field */
+-#define PVR_CORE(pvr) (((pvr) >> 12) & 0xF) /* Core field */
+-#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */
+-#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
+-#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
+-
+-/* Processor Version Numbers */
+-
+-#define PVR_403GA 0x00200000
+-#define PVR_403GB 0x00200100
+-#define PVR_403GC 0x00200200
+-#define PVR_403GCX 0x00201400
+-#define PVR_405GP 0x40110000
+-#define PVR_STB03XXX 0x40310000
+-#define PVR_NP405H 0x41410000
+-#define PVR_NP405L 0x41610000
+-#define PVR_601 0x00010000
+-#define PVR_602 0x00050000
+-#define PVR_603 0x00030000
+-#define PVR_603e 0x00060000
+-#define PVR_603ev 0x00070000
+-#define PVR_603r 0x00071000
+-#define PVR_604 0x00040000
+-#define PVR_604e 0x00090000
+-#define PVR_604r 0x000A0000
+-#define PVR_620 0x00140000
+-#define PVR_740 0x00080000
+-#define PVR_750 PVR_740
+-#define PVR_740P 0x10080000
+-#define PVR_750P PVR_740P
+-#define PVR_7400 0x000C0000
+-#define PVR_7410 0x800C0000
+-#define PVR_7450 0x80000000
+-#define PVR_8540 0x80200000
+-#define PVR_8560 0x80200000
+-/*
+- * For the 8xx processors, all of them report the same PVR family for
+- * the PowerPC core. The various versions of these processors must be
+- * differentiated by the version number in the Communication Processor
+- * Module (CPM).
+- */
+-#define PVR_821 0x00500000
+-#define PVR_823 PVR_821
+-#define PVR_850 PVR_821
+-#define PVR_860 PVR_821
+-#define PVR_8240 0x00810100
+-#define PVR_8245 0x80811014
+-#define PVR_8260 PVR_8240
+-
+-#if 0
+-/* Segment Registers */
+-#define SR0 0
+-#define SR1 1
+-#define SR2 2
+-#define SR3 3
+-#define SR4 4
+-#define SR5 5
+-#define SR6 6
+-#define SR7 7
+-#define SR8 8
+-#define SR9 9
+-#define SR10 10
+-#define SR11 11
+-#define SR12 12
+-#define SR13 13
+-#define SR14 14
+-#define SR15 15
+-#endif
+-
+-/* Macros for setting and retrieving special purpose registers */
+-#ifndef __ASSEMBLY__
+-#define mfmsr() ({unsigned int rval; \
+- asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+-#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
+-
+-#define mfspr(rn) ({unsigned int rval; \
+- asm volatile("mfspr %0," __stringify(rn) \
+- : "=r" (rval)); rval;})
+-#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
+-
+-#define mfsrin(v) ({unsigned int rval; \
+- asm volatile("mfsrin %0,%1" : "=r" (rval) : "r" (v)); \
+- rval;})
+-
+-#define proc_trap() asm volatile("trap")
+-#endif /* __ASSEMBLY__ */
+-#endif /* __ASM_PPC_REGS_H__ */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/rwsem.h b/include/asm-ppc/rwsem.h
+deleted file mode 100644
+--- a/include/asm-ppc/rwsem.h
++++ /dev/null
+@@ -1,172 +0,0 @@
+-/*
+- * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff
+- * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h
+- * by Paul Mackerras <paulus at samba.org>.
+- */
+-
+-#ifndef _PPC_RWSEM_H
+-#define _PPC_RWSEM_H
+-
+-#ifdef __KERNEL__
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-
+-/*
+- * the semaphore definition
+- */
+-struct rw_semaphore {
+- /* XXX this should be able to be an atomic_t -- paulus */
+- signed long count;
+-#define RWSEM_UNLOCKED_VALUE 0x00000000
+-#define RWSEM_ACTIVE_BIAS 0x00000001
+-#define RWSEM_ACTIVE_MASK 0x0000ffff
+-#define RWSEM_WAITING_BIAS (-0x00010000)
+-#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
+-#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+- spinlock_t wait_lock;
+- struct list_head wait_list;
+-#if RWSEM_DEBUG
+- int debug;
+-#endif
+-};
+-
+-/*
+- * initialisation
+- */
+-#if RWSEM_DEBUG
+-#define __RWSEM_DEBUG_INIT , 0
+-#else
+-#define __RWSEM_DEBUG_INIT /* */
+-#endif
+-
+-#define __RWSEM_INITIALIZER(name) \
+- { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+- LIST_HEAD_INIT((name).wait_list) \
+- __RWSEM_DEBUG_INIT }
+-
+-#define DECLARE_RWSEM(name) \
+- struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+-
+-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+-
+-static inline void init_rwsem(struct rw_semaphore *sem)
+-{
+- sem->count = RWSEM_UNLOCKED_VALUE;
+- spin_lock_init(&sem->wait_lock);
+- INIT_LIST_HEAD(&sem->wait_list);
+-#if RWSEM_DEBUG
+- sem->debug = 0;
+-#endif
+-}
+-
+-/*
+- * lock for reading
+- */
+-static inline void __down_read(struct rw_semaphore *sem)
+-{
+- if (atomic_inc_return((atomic_t *)(&sem->count)) > 0)
+- smp_wmb();
+- else
+- rwsem_down_read_failed(sem);
+-}
+-
+-static inline int __down_read_trylock(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- while ((tmp = sem->count) >= 0) {
+- if (tmp == cmpxchg(&sem->count, tmp,
+- tmp + RWSEM_ACTIVE_READ_BIAS)) {
+- smp_wmb();
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+-/*
+- * lock for writing
+- */
+-static inline void __down_write(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+- (atomic_t *)(&sem->count));
+- if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
+- smp_wmb();
+- else
+- rwsem_down_write_failed(sem);
+-}
+-
+-static inline int __down_write_trylock(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+- RWSEM_ACTIVE_WRITE_BIAS);
+- smp_wmb();
+- return tmp == RWSEM_UNLOCKED_VALUE;
+-}
+-
+-/*
+- * unlock after reading
+- */
+-static inline void __up_read(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- smp_wmb();
+- tmp = atomic_dec_return((atomic_t *)(&sem->count));
+- if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
+- rwsem_wake(sem);
+-}
+-
+-/*
+- * unlock after writing
+- */
+-static inline void __up_write(struct rw_semaphore *sem)
+-{
+- smp_wmb();
+- if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+- (atomic_t *)(&sem->count)) < 0)
+- rwsem_wake(sem);
+-}
+-
+-/*
+- * implement atomic add functionality
+- */
+-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+-{
+- atomic_add(delta, (atomic_t *)(&sem->count));
+-}
+-
+-/*
+- * downgrade write lock to read lock
+- */
+-static inline void __downgrade_write(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- smp_wmb();
+- tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+- if (tmp < 0)
+- rwsem_downgrade_wake(sem);
+-}
+-
+-/*
+- * implement exchange and add functionality
+- */
+-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+-{
+- smp_mb();
+- return atomic_add_return(delta, (atomic_t *)(&sem->count));
+-}
+-
+-#endif /* __KERNEL__ */
+-#endif /* _PPC_RWSEM_XADD_H */
+diff --git a/include/asm-ppc/scatterlist.h b/include/asm-ppc/scatterlist.h
+deleted file mode 100644
+--- a/include/asm-ppc/scatterlist.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _PPC_SCATTERLIST_H
+-#define _PPC_SCATTERLIST_H
+-
+-#include <asm/dma.h>
+-
+-struct scatterlist {
+- struct page *page;
+- unsigned int offset;
+- dma_addr_t dma_address;
+- unsigned int length;
+-};
+-
+-/*
+- * These macros should be used after a pci_map_sg call has been done
+- * to get bus addresses of each of the SG entries and their lengths.
+- * You should only work with the number of sg entries pci_map_sg
+- * returns, or alternatively stop on the first sg_dma_len(sg) which
+- * is 0.
+- */
+-#define sg_dma_address(sg) ((sg)->dma_address)
+-#define sg_dma_len(sg) ((sg)->length)
+-
+-#endif /* !(_PPC_SCATTERLIST_H) */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/seccomp.h b/include/asm-ppc/seccomp.h
+deleted file mode 100644
+--- a/include/asm-ppc/seccomp.h
++++ /dev/null
+@@ -1,10 +0,0 @@
+-#ifndef _ASM_SECCOMP_H
+-
+-#include <linux/unistd.h>
+-
+-#define __NR_seccomp_read __NR_read
+-#define __NR_seccomp_write __NR_write
+-#define __NR_seccomp_exit __NR_exit
+-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+-
+-#endif /* _ASM_SECCOMP_H */
+diff --git a/include/asm-ppc/sections.h b/include/asm-ppc/sections.h
+deleted file mode 100644
+--- a/include/asm-ppc/sections.h
++++ /dev/null
+@@ -1,33 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _PPC_SECTIONS_H
+-#define _PPC_SECTIONS_H
+-
+-#include <asm-generic/sections.h>
+-
+-#define __pmac __attribute__ ((__section__ (".pmac.text")))
+-#define __pmacdata __attribute__ ((__section__ (".pmac.data")))
+-#define __pmacfunc(__argpmac) \
+- __argpmac __pmac; \
+- __argpmac
+-
+-#define __prep __attribute__ ((__section__ (".prep.text")))
+-#define __prepdata __attribute__ ((__section__ (".prep.data")))
+-#define __prepfunc(__argprep) \
+- __argprep __prep; \
+- __argprep
+-
+-#define __chrp __attribute__ ((__section__ (".chrp.text")))
+-#define __chrpdata __attribute__ ((__section__ (".chrp.data")))
+-#define __chrpfunc(__argchrp) \
+- __argchrp __chrp; \
+- __argchrp
+-
+-/* this is actually just common chrp/pmac code, not OF code -- Cort */
+-#define __openfirmware __attribute__ ((__section__ (".openfirmware.text")))
+-#define __openfirmwaredata __attribute__ ((__section__ (".openfirmware.data")))
+-#define __openfirmwarefunc(__argopenfirmware) \
+- __argopenfirmware __openfirmware; \
+- __argopenfirmware
+-
+-#endif /* _PPC_SECTIONS_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/semaphore.h b/include/asm-ppc/semaphore.h
+deleted file mode 100644
+--- a/include/asm-ppc/semaphore.h
++++ /dev/null
+@@ -1,111 +0,0 @@
+-#ifndef _PPC_SEMAPHORE_H
+-#define _PPC_SEMAPHORE_H
+-
+-/*
+- * Swiped from asm-sparc/semaphore.h and modified
+- * -- Cort (cort at cs.nmt.edu)
+- *
+- * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h
+- * -- Ani Joshi (ajoshi at unixbox.com)
+- *
+- * Remove spinlock-based RW semaphores; RW semaphore definitions are
+- * now in rwsem.h and we use the generic lib/rwsem.c implementation.
+- * Rework semaphores to use atomic_dec_if_positive.
+- * -- Paul Mackerras (paulus at samba.org)
+- */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- /*
+- * Note that any negative value of count is equivalent to 0,
+- * but additionally indicates that some process(es) might be
+- * sleeping on `wait'.
+- */
+- atomic_t count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .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)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-extern inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+-
+- /*
+- * Try to get the semaphore, take the slow path if we fail.
+- */
+- if (atomic_dec_return(&sem->count) < 0)
+- __down(sem);
+- smp_wmb();
+-}
+-
+-extern inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+-
+- if (atomic_dec_return(&sem->count) < 0)
+- ret = __down_interruptible(sem);
+- smp_wmb();
+- return ret;
+-}
+-
+-extern inline int down_trylock(struct semaphore * sem)
+-{
+- int ret;
+-
+- ret = atomic_dec_if_positive(&sem->count) < 0;
+- smp_wmb();
+- return ret;
+-}
+-
+-extern inline void up(struct semaphore * sem)
+-{
+- smp_wmb();
+- if (atomic_inc_return(&sem->count) <= 0)
+- __up(sem);
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* !(_PPC_SEMAPHORE_H) */
+diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h
+--- a/include/asm-ppc/smp.h
++++ b/include/asm-ppc/smp.h
+@@ -35,6 +35,7 @@ extern cpumask_t cpu_possible_map;
+ extern unsigned long smp_proc_in_lock[];
+ extern volatile unsigned long cpu_callin_map[];
+ extern int smp_tb_synchronized;
++extern struct smp_ops_t *smp_ops;
+
+ extern void smp_send_tlb_invalidate(int);
+ extern void smp_send_xmon_break(int cpu);
+@@ -45,32 +46,31 @@ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ extern void cpu_die(void) __attribute__((noreturn));
+
+-#define NO_PROC_ID 0xFF /* No processor magic marker */
+-#define PROC_CHANGE_PENALTY 20
+-
+ #define raw_smp_processor_id() (current_thread_info()->cpu)
+
+ extern int __cpu_up(unsigned int cpu);
+
+ extern int smp_hw_index[];
+-#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()])
+-
+-struct klock_info_struct {
+- unsigned long kernel_flag;
+- unsigned char akp;
+-};
+-
+-extern struct klock_info_struct klock_info;
+-#define KLOCK_HELD 0xffffffff
+-#define KLOCK_CLEAR 0x0
+-
++#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()])
++#define get_hard_smp_processor_id(cpu) (smp_hw_index[(cpu)])
++#define set_hard_smp_processor_id(cpu, phys)\
++ (smp_hw_index[(cpu)] = (phys))
++
+ #endif /* __ASSEMBLY__ */
+
+ #else /* !(CONFIG_SMP) */
+
+ static inline void cpu_die(void) { }
++#define get_hard_smp_processor_id(cpu) 0
++#define set_hard_smp_processor_id(cpu, phys)
++#define hard_smp_processor_id() 0
+
+ #endif /* !(CONFIG_SMP) */
+
++#ifndef __ASSEMBLY__
++extern int boot_cpuid;
++extern int boot_cpuid_phys;
++#endif
++
+ #endif /* !(_PPC_SMP_H) */
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/spinlock.h b/include/asm-ppc/spinlock.h
+--- a/include/asm-ppc/spinlock.h
++++ b/include/asm-ppc/spinlock.h
+@@ -9,7 +9,7 @@
+ * (the type definitions are in asm/raw_spinlock_types.h)
+ */
+
+-#define __raw_spin_is_locked(x) ((x)->lock != 0)
++#define __raw_spin_is_locked(x) ((x)->slock != 0)
+ #define __raw_spin_unlock_wait(lock) \
+ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+ #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+@@ -31,17 +31,17 @@ static inline void __raw_spin_lock(raw_s
+ bne- 2b\n\
+ isync"
+ : "=&r"(tmp)
+- : "r"(&lock->lock), "r"(1)
++ : "r"(&lock->slock), "r"(1)
+ : "cr0", "memory");
+ }
+
+ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+ {
+ __asm__ __volatile__("eieio # __raw_spin_unlock": : :"memory");
+- lock->lock = 0;
++ lock->slock = 0;
+ }
+
+-#define __raw_spin_trylock(l) (!test_and_set_bit(0,&(l)->lock))
++#define __raw_spin_trylock(l) (!test_and_set_bit(0,(volatile unsigned long *)(&(l)->slock)))
+
+ /*
+ * Read-write spinlocks, allowing multiple readers
+diff --git a/include/asm-ppc/spinlock_types.h b/include/asm-ppc/spinlock_types.h
+deleted file mode 100644
+--- a/include/asm-ppc/spinlock_types.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#ifndef __ASM_SPINLOCK_TYPES_H
+-#define __ASM_SPINLOCK_TYPES_H
+-
+-#ifndef __LINUX_SPINLOCK_TYPES_H
+-# error "please don't include this file directly"
+-#endif
+-
+-typedef struct {
+- volatile unsigned long lock;
+-} raw_spinlock_t;
+-
+-#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+-
+-typedef struct {
+- volatile signed int lock;
+-} raw_rwlock_t;
+-
+-#define __RAW_RW_LOCK_UNLOCKED { 0 }
+-
+-#endif
+diff --git a/include/asm-ppc/statfs.h b/include/asm-ppc/statfs.h
+deleted file mode 100644
+--- a/include/asm-ppc/statfs.h
++++ /dev/null
+@@ -1,8 +0,0 @@
+-#ifndef _PPC_STATFS_H
+-#define _PPC_STATFS_H
+-
+-#include <asm-generic/statfs.h>
+-#endif
+-
+-
+-
+diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h
+--- a/include/asm-ppc/system.h
++++ b/include/asm-ppc/system.h
+@@ -70,25 +70,47 @@ extern void _set_L3CR(unsigned long);
+ #endif
+ extern void via_cuda_init(void);
+ extern void pmac_nvram_init(void);
++extern void chrp_nvram_init(void);
+ extern void read_rtc_time(void);
+ extern void pmac_find_display(void);
+ extern void giveup_fpu(struct task_struct *);
+ extern void enable_kernel_fp(void);
++extern void flush_fp_to_thread(struct task_struct *);
+ extern void enable_kernel_altivec(void);
+ extern void giveup_altivec(struct task_struct *);
+ extern void load_up_altivec(struct task_struct *);
++extern int emulate_altivec(struct pt_regs *);
+ extern void giveup_spe(struct task_struct *);
+ extern void load_up_spe(struct task_struct *);
+ extern int fix_alignment(struct pt_regs *);
+-extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
+-extern void cvt_df(double *from, float *to, unsigned long *fpscr);
++extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
++extern void cvt_df(double *from, float *to, struct thread_struct *thread);
++
++#ifdef CONFIG_ALTIVEC
++extern void flush_altivec_to_thread(struct task_struct *);
++#else
++static inline void flush_altivec_to_thread(struct task_struct *t)
++{
++}
++#endif
++
++#ifdef CONFIG_SPE
++extern void flush_spe_to_thread(struct task_struct *);
++#else
++static inline void flush_spe_to_thread(struct task_struct *t)
++{
++}
++#endif
++
+ extern int call_rtas(const char *, int, int, unsigned long *, ...);
+ extern void cacheable_memzero(void *p, unsigned int nb);
+ extern void *cacheable_memcpy(void *, const void *, unsigned int);
+ extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
+ extern void bad_page_fault(struct pt_regs *, unsigned long, int);
+-extern void die(const char *, struct pt_regs *, long);
++extern int die(const char *, struct pt_regs *, long);
+ extern void _exception(int, struct pt_regs *, int, unsigned long);
++void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
++
+ #ifdef CONFIG_BOOKE_WDT
+ extern u32 booke_wdt_enabled;
+ extern u32 booke_wdt_period;
+diff --git a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
+deleted file mode 100644
+--- a/include/asm-ppc/thread_info.h
++++ /dev/null
+@@ -1,107 +0,0 @@
+-/* thread_info.h: PPC low-level thread information
+- * adapted from the i386 version by Paul Mackerras
+- *
+- * Copyright (C) 2002 David Howells (dhowells at redhat.com)
+- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+- */
+-
+-#ifndef _ASM_THREAD_INFO_H
+-#define _ASM_THREAD_INFO_H
+-
+-#ifdef __KERNEL__
+-#ifndef __ASSEMBLY__
+-/*
+- * low level task data.
+- * If you change this, change the TI_* offsets below to match.
+- */
+-struct thread_info {
+- struct task_struct *task; /* main task structure */
+- struct exec_domain *exec_domain; /* execution domain */
+- unsigned long flags; /* low level flags */
+- unsigned long local_flags; /* non-racy flags */
+- int cpu; /* cpu we're on */
+- int preempt_count; /* 0 => preemptable,
+- <0 => BUG */
+- struct restart_block restart_block;
+-};
+-
+-#define INIT_THREAD_INFO(tsk) \
+-{ \
+- .task = &tsk, \
+- .exec_domain = &default_exec_domain, \
+- .flags = 0, \
+- .local_flags = 0, \
+- .cpu = 0, \
+- .preempt_count = 1, \
+- .restart_block = { \
+- .fn = do_no_restart_syscall, \
+- }, \
+-}
+-
+-#define init_thread_info (init_thread_union.thread_info)
+-#define init_stack (init_thread_union.stack)
+-
+-/*
+- * macros/functions for gaining access to the thread information structure
+- */
+-
+-/* how to get the thread information struct from C */
+-static inline struct thread_info *current_thread_info(void)
+-{
+- struct thread_info *ti;
+- __asm__("rlwinm %0,1,0,0,18" : "=r"(ti));
+- return ti;
+-}
+-
+-/* thread information allocation */
+-#define alloc_thread_info(tsk) ((struct thread_info *) \
+- __get_free_pages(GFP_KERNEL, 1))
+-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+-#define get_thread_info(ti) get_task_struct((ti)->task)
+-#define put_thread_info(ti) put_task_struct((ti)->task)
+-#endif /* __ASSEMBLY__ */
+-
+-/*
+- * Size of kernel stack for each process.
+- */
+-#define THREAD_SIZE 8192 /* 2 pages */
+-
+-#define PREEMPT_ACTIVE 0x10000000
+-
+-/*
+- * thread information flag bit numbers
+- */
+-#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+-#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+-#define TIF_SIGPENDING 2 /* signal pending */
+-#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+-#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
+- TIF_NEED_RESCHED */
+-#define TIF_MEMDIE 5
+-#define TIF_SYSCALL_AUDIT 6 /* syscall auditing active */
+-#define TIF_SECCOMP 7 /* secure computing */
+-
+-/* as above, but as bit values */
+-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+-#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+-#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+-#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+-#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+-
+-#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
+-
+-/*
+- * Non racy (local) flags bit numbers
+- */
+-#define TIFL_FORCE_NOERROR 0 /* don't return error from current
+- syscall even if result < 0 */
+-
+-/* as above, but as bit values */
+-#define _TIFL_FORCE_NOERROR (1<<TIFL_FORCE_NOERROR)
+-
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _ASM_THREAD_INFO_H */
+diff --git a/include/asm-ppc/types.h b/include/asm-ppc/types.h
+deleted file mode 100644
+--- a/include/asm-ppc/types.h
++++ /dev/null
+@@ -1,69 +0,0 @@
+-#ifndef _PPC_TYPES_H
+-#define _PPC_TYPES_H
+-
+-#ifndef __ASSEMBLY__
+-
+-typedef __signed__ char __s8;
+-typedef unsigned char __u8;
+-
+-typedef __signed__ short __s16;
+-typedef unsigned short __u16;
+-
+-typedef __signed__ int __s32;
+-typedef unsigned int __u32;
+-
+-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+-typedef __signed__ long long __s64;
+-typedef unsigned long long __u64;
+-#endif
+-
+-typedef struct {
+- __u32 u[4];
+-} __vector128;
+-
+-/*
+- * XXX allowed outside of __KERNEL__ for now, until glibc gets
+- * a proper set of asm headers of its own. -- paulus
+- */
+-typedef unsigned short umode_t;
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#ifdef __KERNEL__
+-/*
+- * These aren't exported outside the kernel to avoid name space clashes
+- */
+-#define BITS_PER_LONG 32
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/config.h>
+-
+-typedef signed char s8;
+-typedef unsigned char u8;
+-
+-typedef signed short s16;
+-typedef unsigned short u16;
+-
+-typedef signed int s32;
+-typedef unsigned int u32;
+-
+-typedef signed long long s64;
+-typedef unsigned long long u64;
+-
+-typedef __vector128 vector128;
+-
+-/* DMA addresses are 32-bits wide */
+-typedef u32 dma_addr_t;
+-typedef u64 dma64_addr_t;
+-
+-#ifdef CONFIG_LBD
+-typedef u64 sector_t;
+-#define HAVE_SECTOR_T
+-#endif
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif /* __KERNEL__ */
+-
+-#endif
+diff --git a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h
+deleted file mode 100644
+--- a/include/asm-ppc/uninorth.h
++++ /dev/null
+@@ -1,229 +0,0 @@
+-/*
+- * uninorth.h: definitions for using the "UniNorth" host bridge chip
+- * from Apple. This chip is used on "Core99" machines
+- * This also includes U2 used on more recent MacRISC2/3
+- * machines and U3 (G5)
+- *
+- */
+-#ifdef __KERNEL__
+-#ifndef __ASM_UNINORTH_H__
+-#define __ASM_UNINORTH_H__
+-
+-/*
+- * Uni-N and U3 config space reg. definitions
+- *
+- * (Little endian)
+- */
+-
+-/* Address ranges selection. This one should work with Bandit too */
+-/* Not U3 */
+-#define UNI_N_ADDR_SELECT 0x48
+-#define UNI_N_ADDR_COARSE_MASK 0xffff0000 /* 256Mb regions at *0000000 */
+-#define UNI_N_ADDR_FINE_MASK 0x0000ffff /* 16Mb regions at f*000000 */
+-
+-/* AGP registers */
+-/* Not U3 */
+-#define UNI_N_CFG_GART_BASE 0x8c
+-#define UNI_N_CFG_AGP_BASE 0x90
+-#define UNI_N_CFG_GART_CTRL 0x94
+-#define UNI_N_CFG_INTERNAL_STATUS 0x98
+-#define UNI_N_CFG_GART_DUMMY_PAGE 0xa4
+-
+-/* UNI_N_CFG_GART_CTRL bits definitions */
+-#define UNI_N_CFG_GART_INVAL 0x00000001
+-#define UNI_N_CFG_GART_ENABLE 0x00000100
+-#define UNI_N_CFG_GART_2xRESET 0x00010000
+-#define UNI_N_CFG_GART_DISSBADET 0x00020000
+-/* The following seems to only be used only on U3 <j.glisse at gmail.com> */
+-#define U3_N_CFG_GART_SYNCMODE 0x00040000
+-#define U3_N_CFG_GART_PERFRD 0x00080000
+-#define U3_N_CFG_GART_B2BGNT 0x00200000
+-#define U3_N_CFG_GART_FASTDDR 0x00400000
+-
+-/* My understanding of UniNorth AGP as of UniNorth rev 1.0x,
+- * revision 1.5 (x4 AGP) may need further changes.
+- *
+- * AGP_BASE register contains the base address of the AGP aperture on
+- * the AGP bus. It doesn't seem to be visible to the CPU as of UniNorth 1.x,
+- * even if decoding of this address range is enabled in the address select
+- * register. Apparently, the only supported bases are 256Mb multiples
+- * (high 4 bits of that register).
+- *
+- * GART_BASE register appear to contain the physical address of the GART
+- * in system memory in the high address bits (page aligned), and the
+- * GART size in the low order bits (number of GART pages)
+- *
+- * The GART format itself is one 32bits word per physical memory page.
+- * This word contains, in little-endian format (!!!), the physical address
+- * of the page in the high bits, and what appears to be an "enable" bit
+- * in the LSB bit (0) that must be set to 1 when the entry is valid.
+- *
+- * Obviously, the GART is not cache coherent and so any change to it
+- * must be flushed to memory (or maybe just make the GART space non
+- * cachable). AGP memory itself doens't seem to be cache coherent neither.
+- *
+- * In order to invalidate the GART (which is probably necessary to inval
+- * the bridge internal TLBs), the following sequence has to be written,
+- * in order, to the GART_CTRL register:
+- *
+- * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL
+- * UNI_N_CFG_GART_ENABLE
+- * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET
+- * UNI_N_CFG_GART_ENABLE
+- *
+- * As far as AGP "features" are concerned, it looks like fast write may
+- * not be supported but this has to be confirmed.
+- *
+- * Turning on AGP seem to require a double invalidate operation, one before
+- * setting the AGP command register, on after.
+- *
+- * Turning off AGP seems to require the following sequence: first wait
+- * for the AGP to be idle by reading the internal status register, then
+- * write in that order to the GART_CTRL register:
+- *
+- * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL
+- * 0
+- * UNI_N_CFG_GART_2xRESET
+- * 0
+- */
+-
+-/*
+- * Uni-N memory mapped reg. definitions
+- *
+- * Those registers are Big-Endian !!
+- *
+- * Their meaning come from either Darwin and/or from experiments I made with
+- * the bootrom, I'm not sure about their exact meaning yet
+- *
+- */
+-
+-/* Version of the UniNorth chip */
+-#define UNI_N_VERSION 0x0000 /* Known versions: 3,7 and 8 */
+-
+-#define UNI_N_VERSION_107 0x0003 /* 1.0.7 */
+-#define UNI_N_VERSION_10A 0x0007 /* 1.0.10 */
+-#define UNI_N_VERSION_150 0x0011 /* 1.5 */
+-#define UNI_N_VERSION_200 0x0024 /* 2.0 */
+-#define UNI_N_VERSION_PANGEA 0x00C0 /* Integrated U1 + K */
+-#define UNI_N_VERSION_INTREPID 0x00D2 /* Integrated U2 + K */
+-#define UNI_N_VERSION_300 0x0030 /* 3.0 (U3 on G5) */
+-
+-/* This register is used to enable/disable various clocks */
+-#define UNI_N_CLOCK_CNTL 0x0020
+-#define UNI_N_CLOCK_CNTL_PCI 0x00000001 /* PCI2 clock control */
+-#define UNI_N_CLOCK_CNTL_GMAC 0x00000002 /* GMAC clock control */
+-#define UNI_N_CLOCK_CNTL_FW 0x00000004 /* FireWire clock control */
+-#define UNI_N_CLOCK_CNTL_ATA100 0x00000010 /* ATA-100 clock control (U2) */
+-
+-/* Power Management control */
+-#define UNI_N_POWER_MGT 0x0030
+-#define UNI_N_POWER_MGT_NORMAL 0x00
+-#define UNI_N_POWER_MGT_IDLE2 0x01
+-#define UNI_N_POWER_MGT_SLEEP 0x02
+-
+-/* This register is configured by Darwin depending on the UniN
+- * revision
+- */
+-#define UNI_N_ARB_CTRL 0x0040
+-#define UNI_N_ARB_CTRL_QACK_DELAY_SHIFT 15
+-#define UNI_N_ARB_CTRL_QACK_DELAY_MASK 0x0e1f8000
+-#define UNI_N_ARB_CTRL_QACK_DELAY 0x30
+-#define UNI_N_ARB_CTRL_QACK_DELAY105 0x00
+-
+-/* This one _might_ return the CPU number of the CPU reading it;
+- * the bootROM decides whether to boot or to sleep/spinloop depending
+- * on this register beeing 0 or not
+- */
+-#define UNI_N_CPU_NUMBER 0x0050
+-
+-/* This register appear to be read by the bootROM to decide what
+- * to do on a non-recoverable reset (powerup or wakeup)
+- */
+-#define UNI_N_HWINIT_STATE 0x0070
+-#define UNI_N_HWINIT_STATE_SLEEPING 0x01
+-#define UNI_N_HWINIT_STATE_RUNNING 0x02
+-/* This last bit appear to be used by the bootROM to know the second
+- * CPU has started and will enter it's sleep loop with IP=0
+- */
+-#define UNI_N_HWINIT_STATE_CPU1_FLAG 0x10000000
+-
+-/* This register controls AACK delay, which is set when 2004 iBook/PowerBook
+- * is in low speed mode.
+- */
+-#define UNI_N_AACK_DELAY 0x0100
+-#define UNI_N_AACK_DELAY_ENABLE 0x00000001
+-
+-/* Clock status for Intrepid */
+-#define UNI_N_CLOCK_STOP_STATUS0 0x0150
+-#define UNI_N_CLOCK_STOPPED_EXTAGP 0x00200000
+-#define UNI_N_CLOCK_STOPPED_AGPDEL 0x00100000
+-#define UNI_N_CLOCK_STOPPED_I2S0_45_49 0x00080000
+-#define UNI_N_CLOCK_STOPPED_I2S0_18 0x00040000
+-#define UNI_N_CLOCK_STOPPED_I2S1_45_49 0x00020000
+-#define UNI_N_CLOCK_STOPPED_I2S1_18 0x00010000
+-#define UNI_N_CLOCK_STOPPED_TIMER 0x00008000
+-#define UNI_N_CLOCK_STOPPED_SCC_RTCLK18 0x00004000
+-#define UNI_N_CLOCK_STOPPED_SCC_RTCLK32 0x00002000
+-#define UNI_N_CLOCK_STOPPED_SCC_VIA32 0x00001000
+-#define UNI_N_CLOCK_STOPPED_SCC_SLOT0 0x00000800
+-#define UNI_N_CLOCK_STOPPED_SCC_SLOT1 0x00000400
+-#define UNI_N_CLOCK_STOPPED_SCC_SLOT2 0x00000200
+-#define UNI_N_CLOCK_STOPPED_PCI_FBCLKO 0x00000100
+-#define UNI_N_CLOCK_STOPPED_VEO0 0x00000080
+-#define UNI_N_CLOCK_STOPPED_VEO1 0x00000040
+-#define UNI_N_CLOCK_STOPPED_USB0 0x00000020
+-#define UNI_N_CLOCK_STOPPED_USB1 0x00000010
+-#define UNI_N_CLOCK_STOPPED_USB2 0x00000008
+-#define UNI_N_CLOCK_STOPPED_32 0x00000004
+-#define UNI_N_CLOCK_STOPPED_45 0x00000002
+-#define UNI_N_CLOCK_STOPPED_49 0x00000001
+-
+-#define UNI_N_CLOCK_STOP_STATUS1 0x0160
+-#define UNI_N_CLOCK_STOPPED_PLL4REF 0x00080000
+-#define UNI_N_CLOCK_STOPPED_CPUDEL 0x00040000
+-#define UNI_N_CLOCK_STOPPED_CPU 0x00020000
+-#define UNI_N_CLOCK_STOPPED_BUF_REFCKO 0x00010000
+-#define UNI_N_CLOCK_STOPPED_PCI2 0x00008000
+-#define UNI_N_CLOCK_STOPPED_FW 0x00004000
+-#define UNI_N_CLOCK_STOPPED_GB 0x00002000
+-#define UNI_N_CLOCK_STOPPED_ATA66 0x00001000
+-#define UNI_N_CLOCK_STOPPED_ATA100 0x00000800
+-#define UNI_N_CLOCK_STOPPED_MAX 0x00000400
+-#define UNI_N_CLOCK_STOPPED_PCI1 0x00000200
+-#define UNI_N_CLOCK_STOPPED_KLPCI 0x00000100
+-#define UNI_N_CLOCK_STOPPED_USB0PCI 0x00000080
+-#define UNI_N_CLOCK_STOPPED_USB1PCI 0x00000040
+-#define UNI_N_CLOCK_STOPPED_USB2PCI 0x00000020
+-#define UNI_N_CLOCK_STOPPED_7PCI1 0x00000008
+-#define UNI_N_CLOCK_STOPPED_AGP 0x00000004
+-#define UNI_N_CLOCK_STOPPED_PCI0 0x00000002
+-#define UNI_N_CLOCK_STOPPED_18 0x00000001
+-
+-/* Intrepid registe to OF do-platform-clockspreading */
+-#define UNI_N_CLOCK_SPREADING 0x190
+-
+-/* Uninorth 1.5 rev. has additional perf. monitor registers at 0xf00-0xf50 */
+-
+-
+-/*
+- * U3 specific registers
+- */
+-
+-
+-/* U3 Toggle */
+-#define U3_TOGGLE_REG 0x00e0
+-#define U3_PMC_START_STOP 0x0001
+-#define U3_MPIC_RESET 0x0002
+-#define U3_MPIC_OUTPUT_ENABLE 0x0004
+-
+-/* U3 API PHY Config 1 */
+-#define U3_API_PHY_CONFIG_1 0x23030
+-
+-/* U3 HyperTransport registers */
+-#define U3_HT_CONFIG_BASE 0x70000
+-#define U3_HT_LINK_COMMAND 0x100
+-#define U3_HT_LINK_CONFIG 0x110
+-#define U3_HT_LINK_FREQ 0x120
+-
+-#endif /* __ASM_UNINORTH_H__ */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
+deleted file mode 100644
+--- a/include/asm-ppc/unistd.h
++++ /dev/null
+@@ -1,493 +0,0 @@
+-#ifndef _ASM_PPC_UNISTD_H_
+-#define _ASM_PPC_UNISTD_H_
+-
+-/*
+- * This file contains the system call numbers.
+- */
+-#define __NR_restart_syscall 0
+-#define __NR_exit 1
+-#define __NR_fork 2
+-#define __NR_read 3
+-#define __NR_write 4
+-#define __NR_open 5
+-#define __NR_close 6
+-#define __NR_waitpid 7
+-#define __NR_creat 8
+-#define __NR_link 9
+-#define __NR_unlink 10
+-#define __NR_execve 11
+-#define __NR_chdir 12
+-#define __NR_time 13
+-#define __NR_mknod 14
+-#define __NR_chmod 15
+-#define __NR_lchown 16
+-#define __NR_break 17
+-#define __NR_oldstat 18
+-#define __NR_lseek 19
+-#define __NR_getpid 20
+-#define __NR_mount 21
+-#define __NR_umount 22
+-#define __NR_setuid 23
+-#define __NR_getuid 24
+-#define __NR_stime 25
+-#define __NR_ptrace 26
+-#define __NR_alarm 27
+-#define __NR_oldfstat 28
+-#define __NR_pause 29
+-#define __NR_utime 30
+-#define __NR_stty 31
+-#define __NR_gtty 32
+-#define __NR_access 33
+-#define __NR_nice 34
+-#define __NR_ftime 35
+-#define __NR_sync 36
+-#define __NR_kill 37
+-#define __NR_rename 38
+-#define __NR_mkdir 39
+-#define __NR_rmdir 40
+-#define __NR_dup 41
+-#define __NR_pipe 42
+-#define __NR_times 43
+-#define __NR_prof 44
+-#define __NR_brk 45
+-#define __NR_setgid 46
+-#define __NR_getgid 47
+-#define __NR_signal 48
+-#define __NR_geteuid 49
+-#define __NR_getegid 50
+-#define __NR_acct 51
+-#define __NR_umount2 52
+-#define __NR_lock 53
+-#define __NR_ioctl 54
+-#define __NR_fcntl 55
+-#define __NR_mpx 56
+-#define __NR_setpgid 57
+-#define __NR_ulimit 58
+-#define __NR_oldolduname 59
+-#define __NR_umask 60
+-#define __NR_chroot 61
+-#define __NR_ustat 62
+-#define __NR_dup2 63
+-#define __NR_getppid 64
+-#define __NR_getpgrp 65
+-#define __NR_setsid 66
+-#define __NR_sigaction 67
+-#define __NR_sgetmask 68
+-#define __NR_ssetmask 69
+-#define __NR_setreuid 70
+-#define __NR_setregid 71
+-#define __NR_sigsuspend 72
+-#define __NR_sigpending 73
+-#define __NR_sethostname 74
+-#define __NR_setrlimit 75
+-#define __NR_getrlimit 76
+-#define __NR_getrusage 77
+-#define __NR_gettimeofday 78
+-#define __NR_settimeofday 79
+-#define __NR_getgroups 80
+-#define __NR_setgroups 81
+-#define __NR_select 82
+-#define __NR_symlink 83
+-#define __NR_oldlstat 84
+-#define __NR_readlink 85
+-#define __NR_uselib 86
+-#define __NR_swapon 87
+-#define __NR_reboot 88
+-#define __NR_readdir 89
+-#define __NR_mmap 90
+-#define __NR_munmap 91
+-#define __NR_truncate 92
+-#define __NR_ftruncate 93
+-#define __NR_fchmod 94
+-#define __NR_fchown 95
+-#define __NR_getpriority 96
+-#define __NR_setpriority 97
+-#define __NR_profil 98
+-#define __NR_statfs 99
+-#define __NR_fstatfs 100
+-#define __NR_ioperm 101
+-#define __NR_socketcall 102
+-#define __NR_syslog 103
+-#define __NR_setitimer 104
+-#define __NR_getitimer 105
+-#define __NR_stat 106
+-#define __NR_lstat 107
+-#define __NR_fstat 108
+-#define __NR_olduname 109
+-#define __NR_iopl 110
+-#define __NR_vhangup 111
+-#define __NR_idle 112
+-#define __NR_vm86 113
+-#define __NR_wait4 114
+-#define __NR_swapoff 115
+-#define __NR_sysinfo 116
+-#define __NR_ipc 117
+-#define __NR_fsync 118
+-#define __NR_sigreturn 119
+-#define __NR_clone 120
+-#define __NR_setdomainname 121
+-#define __NR_uname 122
+-#define __NR_modify_ldt 123
+-#define __NR_adjtimex 124
+-#define __NR_mprotect 125
+-#define __NR_sigprocmask 126
+-#define __NR_create_module 127
+-#define __NR_init_module 128
+-#define __NR_delete_module 129
+-#define __NR_get_kernel_syms 130
+-#define __NR_quotactl 131
+-#define __NR_getpgid 132
+-#define __NR_fchdir 133
+-#define __NR_bdflush 134
+-#define __NR_sysfs 135
+-#define __NR_personality 136
+-#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
+-#define __NR_setfsuid 138
+-#define __NR_setfsgid 139
+-#define __NR__llseek 140
+-#define __NR_getdents 141
+-#define __NR__newselect 142
+-#define __NR_flock 143
+-#define __NR_msync 144
+-#define __NR_readv 145
+-#define __NR_writev 146
+-#define __NR_getsid 147
+-#define __NR_fdatasync 148
+-#define __NR__sysctl 149
+-#define __NR_mlock 150
+-#define __NR_munlock 151
+-#define __NR_mlockall 152
+-#define __NR_munlockall 153
+-#define __NR_sched_setparam 154
+-#define __NR_sched_getparam 155
+-#define __NR_sched_setscheduler 156
+-#define __NR_sched_getscheduler 157
+-#define __NR_sched_yield 158
+-#define __NR_sched_get_priority_max 159
+-#define __NR_sched_get_priority_min 160
+-#define __NR_sched_rr_get_interval 161
+-#define __NR_nanosleep 162
+-#define __NR_mremap 163
+-#define __NR_setresuid 164
+-#define __NR_getresuid 165
+-#define __NR_query_module 166
+-#define __NR_poll 167
+-#define __NR_nfsservctl 168
+-#define __NR_setresgid 169
+-#define __NR_getresgid 170
+-#define __NR_prctl 171
+-#define __NR_rt_sigreturn 172
+-#define __NR_rt_sigaction 173
+-#define __NR_rt_sigprocmask 174
+-#define __NR_rt_sigpending 175
+-#define __NR_rt_sigtimedwait 176
+-#define __NR_rt_sigqueueinfo 177
+-#define __NR_rt_sigsuspend 178
+-#define __NR_pread64 179
+-#define __NR_pwrite64 180
+-#define __NR_chown 181
+-#define __NR_getcwd 182
+-#define __NR_capget 183
+-#define __NR_capset 184
+-#define __NR_sigaltstack 185
+-#define __NR_sendfile 186
+-#define __NR_getpmsg 187 /* some people actually want streams */
+-#define __NR_putpmsg 188 /* some people actually want streams */
+-#define __NR_vfork 189
+-#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
+-#define __NR_readahead 191
+-#define __NR_mmap2 192
+-#define __NR_truncate64 193
+-#define __NR_ftruncate64 194
+-#define __NR_stat64 195
+-#define __NR_lstat64 196
+-#define __NR_fstat64 197
+-#define __NR_pciconfig_read 198
+-#define __NR_pciconfig_write 199
+-#define __NR_pciconfig_iobase 200
+-#define __NR_multiplexer 201
+-#define __NR_getdents64 202
+-#define __NR_pivot_root 203
+-#define __NR_fcntl64 204
+-#define __NR_madvise 205
+-#define __NR_mincore 206
+-#define __NR_gettid 207
+-#define __NR_tkill 208
+-#define __NR_setxattr 209
+-#define __NR_lsetxattr 210
+-#define __NR_fsetxattr 211
+-#define __NR_getxattr 212
+-#define __NR_lgetxattr 213
+-#define __NR_fgetxattr 214
+-#define __NR_listxattr 215
+-#define __NR_llistxattr 216
+-#define __NR_flistxattr 217
+-#define __NR_removexattr 218
+-#define __NR_lremovexattr 219
+-#define __NR_fremovexattr 220
+-#define __NR_futex 221
+-#define __NR_sched_setaffinity 222
+-#define __NR_sched_getaffinity 223
+-/* 224 currently unused */
+-#define __NR_tuxcall 225
+-#define __NR_sendfile64 226
+-#define __NR_io_setup 227
+-#define __NR_io_destroy 228
+-#define __NR_io_getevents 229
+-#define __NR_io_submit 230
+-#define __NR_io_cancel 231
+-#define __NR_set_tid_address 232
+-#define __NR_fadvise64 233
+-#define __NR_exit_group 234
+-#define __NR_lookup_dcookie 235
+-#define __NR_epoll_create 236
+-#define __NR_epoll_ctl 237
+-#define __NR_epoll_wait 238
+-#define __NR_remap_file_pages 239
+-#define __NR_timer_create 240
+-#define __NR_timer_settime 241
+-#define __NR_timer_gettime 242
+-#define __NR_timer_getoverrun 243
+-#define __NR_timer_delete 244
+-#define __NR_clock_settime 245
+-#define __NR_clock_gettime 246
+-#define __NR_clock_getres 247
+-#define __NR_clock_nanosleep 248
+-#define __NR_swapcontext 249
+-#define __NR_tgkill 250
+-#define __NR_utimes 251
+-#define __NR_statfs64 252
+-#define __NR_fstatfs64 253
+-#define __NR_fadvise64_64 254
+-#define __NR_rtas 255
+-#define __NR_sys_debug_setcontext 256
+-/* Number 257 is reserved for vserver */
+-/* 258 currently unused */
+-/* Number 259 is reserved for new sys_mbind */
+-/* Number 260 is reserved for new sys_get_mempolicy */
+-/* Number 261 is reserved for new sys_set_mempolicy */
+-#define __NR_mq_open 262
+-#define __NR_mq_unlink 263
+-#define __NR_mq_timedsend 264
+-#define __NR_mq_timedreceive 265
+-#define __NR_mq_notify 266
+-#define __NR_mq_getsetattr 267
+-#define __NR_kexec_load 268
+-#define __NR_add_key 269
+-#define __NR_request_key 270
+-#define __NR_keyctl 271
+-#define __NR_waitid 272
+-#define __NR_ioprio_set 273
+-#define __NR_ioprio_get 274
+-#define __NR_inotify_init 275
+-#define __NR_inotify_add_watch 276
+-#define __NR_inotify_rm_watch 277
+-
+-#define __NR_syscalls 278
+-
+-#define __NR(n) #n
+-
+-/* On powerpc a system call basically clobbers the same registers like a
+- * function call, with the exception of LR (which is needed for the
+- * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
+- * an error return status).
+- */
+-
+-#define __syscall_nr(nr, type, name, args...) \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- register unsigned long __sc_7 __asm__ ("r7"); \
+- register unsigned long __sc_8 __asm__ ("r8"); \
+- \
+- __sc_loadargs_##nr(name, args); \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %0 " \
+- : "=&r" (__sc_0), \
+- "=&r" (__sc_3), "=&r" (__sc_4), \
+- "=&r" (__sc_5), "=&r" (__sc_6), \
+- "=&r" (__sc_7), "=&r" (__sc_8) \
+- : __sc_asm_input_##nr \
+- : "cr0", "ctr", "memory", \
+- "r9", "r10","r11", "r12"); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- if (__sc_err & 0x10000000) \
+- { \
+- errno = __sc_ret; \
+- __sc_ret = -1; \
+- } \
+- return (type) __sc_ret
+-
+-#define __sc_loadargs_0(name, dummy...) \
+- __sc_0 = __NR_##name
+-#define __sc_loadargs_1(name, arg1) \
+- __sc_loadargs_0(name); \
+- __sc_3 = (unsigned long) (arg1)
+-#define __sc_loadargs_2(name, arg1, arg2) \
+- __sc_loadargs_1(name, arg1); \
+- __sc_4 = (unsigned long) (arg2)
+-#define __sc_loadargs_3(name, arg1, arg2, arg3) \
+- __sc_loadargs_2(name, arg1, arg2); \
+- __sc_5 = (unsigned long) (arg3)
+-#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \
+- __sc_loadargs_3(name, arg1, arg2, arg3); \
+- __sc_6 = (unsigned long) (arg4)
+-#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \
+- __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \
+- __sc_7 = (unsigned long) (arg5)
+-#define __sc_loadargs_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
+- __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5); \
+- __sc_8 = (unsigned long) (arg6)
+-
+-#define __sc_asm_input_0 "0" (__sc_0)
+-#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
+-#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
+-#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
+-#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
+-#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
+-#define __sc_asm_input_6 __sc_asm_input_5, "6" (__sc_8)
+-
+-#define _syscall0(type,name) \
+-type name(void) \
+-{ \
+- __syscall_nr(0, type, name); \
+-}
+-
+-#define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1) \
+-{ \
+- __syscall_nr(1, type, name, arg1); \
+-}
+-
+-#define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1, type2 arg2) \
+-{ \
+- __syscall_nr(2, type, name, arg1, arg2); \
+-}
+-
+-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1, type2 arg2, type3 arg3) \
+-{ \
+- __syscall_nr(3, type, name, arg1, arg2, arg3); \
+-}
+-
+-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+-{ \
+- __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \
+-}
+-
+-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
+-{ \
+- __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \
+-}
+-
+-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
+-{ \
+- __syscall_nr(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \
+-}
+-
+-#ifdef __KERNEL__
+-
+-#define __NR__exit __NR_exit
+-#define NR_syscalls __NR_syscalls
+-
+-#define __ARCH_WANT_IPC_PARSE_VERSION
+-#define __ARCH_WANT_OLD_READDIR
+-#define __ARCH_WANT_OLD_STAT
+-#define __ARCH_WANT_STAT64
+-#define __ARCH_WANT_SYS_ALARM
+-#define __ARCH_WANT_SYS_GETHOSTNAME
+-#define __ARCH_WANT_SYS_PAUSE
+-#define __ARCH_WANT_SYS_SGETMASK
+-#define __ARCH_WANT_SYS_SIGNAL
+-#define __ARCH_WANT_SYS_TIME
+-#define __ARCH_WANT_SYS_UTIME
+-#define __ARCH_WANT_SYS_WAITPID
+-#define __ARCH_WANT_SYS_SOCKETCALL
+-#define __ARCH_WANT_SYS_FADVISE64
+-#define __ARCH_WANT_SYS_GETPGRP
+-#define __ARCH_WANT_SYS_LLSEEK
+-#define __ARCH_WANT_SYS_NICE
+-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+-#define __ARCH_WANT_SYS_OLDUMOUNT
+-#define __ARCH_WANT_SYS_SIGPENDING
+-#define __ARCH_WANT_SYS_SIGPROCMASK
+-#define __ARCH_WANT_SYS_RT_SIGACTION
+-
+-/*
+- * Forking from kernel space will result in the child getting a new,
+- * empty kernel stack area. Thus the child cannot access automatic
+- * variables set in the parent unless they are in registers, and the
+- * procedure where the fork was done cannot return to its caller in
+- * the child.
+- */
+-
+-#ifdef __KERNEL_SYSCALLS__
+-
+-#include <linux/compiler.h>
+-#include <linux/types.h>
+-
+-/*
+- * System call prototypes.
+- */
+-extern pid_t setsid(void);
+-extern int write(int fd, const char *buf, off_t count);
+-extern int read(int fd, char *buf, off_t count);
+-extern off_t lseek(int fd, off_t offset, int count);
+-extern int dup(int fd);
+-extern int execve(const char *file, char **argv, char **envp);
+-extern int open(const char *file, int flag, int mode);
+-extern int close(int fd);
+-extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
+-
+-unsigned long sys_mmap(unsigned long addr, size_t len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, off_t offset);
+-unsigned long sys_mmap2(unsigned long addr, size_t len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, unsigned long pgoff);
+-struct pt_regs;
+-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+- unsigned long a3, unsigned long a4, unsigned long a5,
+- struct pt_regs *regs);
+-int sys_clone(unsigned long clone_flags, unsigned long usp,
+- int __user *parent_tidp, void __user *child_threadptr,
+- int __user *child_tidp, int p6,
+- struct pt_regs *regs);
+-int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
+- struct pt_regs *regs);
+-int sys_vfork(int p1, int p2, int p3, int p4, int p5, int 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);
+-
+-#endif /* __KERNEL_SYSCALLS__ */
+-
+-/*
+- * "Conditional" syscalls
+- *
+- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+- * but it doesn't work on all toolchains, so we just do it by hand
+- */
+-#ifndef cond_syscall
+-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
+-#endif
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _ASM_PPC_UNISTD_H_ */
+diff --git a/include/asm-ppc/vga.h b/include/asm-ppc/vga.h
+deleted file mode 100644
+--- a/include/asm-ppc/vga.h
++++ /dev/null
+@@ -1,46 +0,0 @@
+-/*
+- * Access to VGA videoram
+- *
+- * (c) 1998 Martin Mares <mj at ucw.cz>
+- */
+-
+-#ifdef __KERNEL__
+-#ifndef _LINUX_ASM_VGA_H_
+-#define _LINUX_ASM_VGA_H_
+-
+-#include <asm/io.h>
+-
+-#include <linux/config.h>
+-
+-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
+-
+-#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.
+- */
+-
+-extern inline void scr_writew(u16 val, volatile u16 *addr)
+-{
+- st_le16(addr, val);
+-}
+-
+-extern inline u16 scr_readw(volatile const u16 *addr)
+-{
+- return ld_le16(addr);
+-}
+-
+-#define VT_BUF_HAVE_MEMCPYW
+-#define scr_memcpyw memcpy
+-
+-#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */
+-
+-extern unsigned long vgacon_remap_base;
+-#define VGA_MAP_MEM(x) (x + vgacon_remap_base)
+-#define vga_readb(x) (*(x))
+-#define vga_writeb(x,y) (*(y) = (x))
+-
+-#endif
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/xmon.h b/include/asm-ppc/xmon.h
+deleted file mode 100644
+--- a/include/asm-ppc/xmon.h
++++ /dev/null
+@@ -1,17 +0,0 @@
+-#ifndef __PPC_XMON_H
+-#define __PPC_XMON_H
+-#ifdef __KERNEL__
+-
+-struct pt_regs;
+-
+-extern void xmon(struct pt_regs *excp);
+-extern void xmon_printf(const char *fmt, ...);
+-extern void xmon_map_scc(void);
+-extern int xmon_bpt(struct pt_regs *regs);
+-extern int xmon_sstep(struct pt_regs *regs);
+-extern int xmon_iabr_match(struct pt_regs *regs);
+-extern int xmon_dabr_match(struct pt_regs *regs);
+-extern void (*xmon_fault_handler)(struct pt_regs *regs);
+-
+-#endif
+-#endif
+diff --git a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h
+deleted file mode 100644
+--- a/include/asm-ppc64/a.out.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-#ifndef __PPC64_A_OUT_H__
+-#define __PPC64_A_OUT_H__
+-
+-/*
+- * c 2001 PPC 64 Team, IBM Corp
+- *
+- * 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.
+- */
+-
+-struct exec
+-{
+- unsigned long a_info; /* Use macros N_MAGIC, etc for access */
+- unsigned a_text; /* length of text, in bytes */
+- unsigned a_data; /* length of data, in bytes */
+- unsigned a_bss; /* length of uninitialized data area for file, in bytes */
+- unsigned a_syms; /* length of symbol table data in file, in bytes */
+- unsigned a_entry; /* start address */
+- unsigned a_trsize; /* length of relocation info for text, in bytes */
+- unsigned a_drsize; /* length of relocation info for data, in bytes */
+-};
+-
+-#define N_TRSIZE(a) ((a).a_trsize)
+-#define N_DRSIZE(a) ((a).a_drsize)
+-#define N_SYMSIZE(a) ((a).a_syms)
+-
+-#ifdef __KERNEL__
+-
+-#define STACK_TOP_USER64 TASK_SIZE_USER64
+-#define STACK_TOP_USER32 TASK_SIZE_USER32
+-
+-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+- STACK_TOP_USER32 : STACK_TOP_USER64)
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* __PPC64_A_OUT_H__ */
+diff --git a/include/asm-ppc64/abs_addr.h b/include/asm-ppc64/abs_addr.h
+--- a/include/asm-ppc64/abs_addr.h
++++ b/include/asm-ppc64/abs_addr.h
+@@ -63,4 +63,11 @@ static inline unsigned long phys_to_abs(
+ #define virt_to_abs(va) phys_to_abs(__pa(va))
+ #define abs_to_virt(aa) __va(aa)
+
++/*
++ * Converts Virtual Address to Real Address for
++ * Legacy iSeries Hypervisor calls
++ */
++#define iseries_hv_addr(virtaddr) \
++ (0x8000000000000000 | virt_to_abs(virtaddr))
++
+ #endif /* _ABS_ADDR_H */
+diff --git a/include/asm-ppc64/atomic.h b/include/asm-ppc64/atomic.h
+deleted file mode 100644
+--- a/include/asm-ppc64/atomic.h
++++ /dev/null
+@@ -1,197 +0,0 @@
+-/*
+- * PowerPC64 atomic operations
+- *
+- * Copyright (C) 2001 Paul Mackerras <paulus at au.ibm.com>, IBM
+- * Copyright (C) 2001 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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_PPC64_ATOMIC_H_
+-#define _ASM_PPC64_ATOMIC_H_
+-
+-#include <asm/memory.h>
+-
+-typedef struct { volatile int counter; } atomic_t;
+-
+-#define ATOMIC_INIT(i) { (i) }
+-
+-#define atomic_read(v) ((v)->counter)
+-#define atomic_set(v,i) (((v)->counter) = (i))
+-
+-static __inline__ void atomic_add(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%3 # atomic_add\n\
+- add %0,%2,%0\n\
+- stwcx. %0,0,%3\n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (a), "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_add_return(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+- EIEIO_ON_SMP
+-"1: lwarx %0,0,%2 # atomic_add_return\n\
+- add %0,%1,%0\n\
+- stwcx. %0,0,%2\n\
+- bne- 1b"
+- ISYNC_ON_SMP
+- : "=&r" (t)
+- : "r" (a), "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
+-
+-static __inline__ void atomic_sub(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%3 # atomic_sub\n\
+- subf %0,%2,%0\n\
+- stwcx. %0,0,%3\n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (a), "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_sub_return(int a, atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+- EIEIO_ON_SMP
+-"1: lwarx %0,0,%2 # atomic_sub_return\n\
+- subf %0,%1,%0\n\
+- stwcx. %0,0,%2\n\
+- bne- 1b"
+- ISYNC_ON_SMP
+- : "=&r" (t)
+- : "r" (a), "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-static __inline__ void atomic_inc(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%2 # atomic_inc\n\
+- addic %0,%0,1\n\
+- stwcx. %0,0,%2\n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_inc_return(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+- EIEIO_ON_SMP
+-"1: lwarx %0,0,%1 # atomic_inc_return\n\
+- addic %0,%0,1\n\
+- stwcx. %0,0,%1\n\
+- bne- 1b"
+- ISYNC_ON_SMP
+- : "=&r" (t)
+- : "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-/*
+- * atomic_inc_and_test - increment and test
+- * @v: pointer of type atomic_t
+- *
+- * Atomically increments @v by 1
+- * and returns true if the result is zero, or false for all
+- * other cases.
+- */
+-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+-
+-static __inline__ void atomic_dec(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+-"1: lwarx %0,0,%2 # atomic_dec\n\
+- addic %0,%0,-1\n\
+- stwcx. %0,0,%2\n\
+- bne- 1b"
+- : "=&r" (t), "=m" (v->counter)
+- : "r" (&v->counter), "m" (v->counter)
+- : "cc");
+-}
+-
+-static __inline__ int atomic_dec_return(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+- EIEIO_ON_SMP
+-"1: lwarx %0,0,%1 # atomic_dec_return\n\
+- addic %0,%0,-1\n\
+- stwcx. %0,0,%1\n\
+- bne- 1b"
+- ISYNC_ON_SMP
+- : "=&r" (t)
+- : "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
+-#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
+-
+-/*
+- * Atomically test *v and decrement if it is greater than 0.
+- * The function returns the old value of *v minus 1.
+- */
+-static __inline__ int atomic_dec_if_positive(atomic_t *v)
+-{
+- int t;
+-
+- __asm__ __volatile__(
+- EIEIO_ON_SMP
+-"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\
+- addic. %0,%0,-1\n\
+- blt- 2f\n\
+- stwcx. %0,0,%1\n\
+- bne- 1b"
+- ISYNC_ON_SMP
+- "\n\
+-2:" : "=&r" (t)
+- : "r" (&v->counter)
+- : "cc", "memory");
+-
+- return t;
+-}
+-
+-#define smp_mb__before_atomic_dec() smp_mb()
+-#define smp_mb__after_atomic_dec() smp_mb()
+-#define smp_mb__before_atomic_inc() smp_mb()
+-#define smp_mb__after_atomic_inc() smp_mb()
+-
+-#endif /* _ASM_PPC64_ATOMIC_H_ */
+diff --git a/include/asm-ppc64/auxvec.h b/include/asm-ppc64/auxvec.h
+deleted file mode 100644
+--- a/include/asm-ppc64/auxvec.h
++++ /dev/null
+@@ -1,19 +0,0 @@
+-#ifndef __PPC64_AUXVEC_H
+-#define __PPC64_AUXVEC_H
+-
+-/*
+- * We need to put in some extra aux table entries to tell glibc what
+- * the cache block size is, so it can use the dcbz instruction safely.
+- */
+-#define AT_DCACHEBSIZE 19
+-#define AT_ICACHEBSIZE 20
+-#define AT_UCACHEBSIZE 21
+-/* A special ignored type value for PPC, for glibc compatibility. */
+-#define AT_IGNOREPPC 22
+-
+-/* The vDSO location. We have to use the same value as x86 for glibc's
+- * sake :-)
+- */
+-#define AT_SYSINFO_EHDR 33
+-
+-#endif /* __PPC64_AUXVEC_H */
+diff --git a/include/asm-ppc64/bitops.h b/include/asm-ppc64/bitops.h
+--- a/include/asm-ppc64/bitops.h
++++ b/include/asm-ppc64/bitops.h
+@@ -42,7 +42,7 @@
+
+ #ifdef __KERNEL__
+
+-#include <asm/memory.h>
++#include <asm/synch.h>
+
+ /*
+ * clear_bit doesn't imply a memory barrier
+diff --git a/include/asm-ppc64/bootinfo.h b/include/asm-ppc64/bootinfo.h
+deleted file mode 100644
+--- a/include/asm-ppc64/bootinfo.h
++++ /dev/null
+@@ -1,70 +0,0 @@
+-/*
+- * Non-machine dependent bootinfo structure. Basic idea
+- * borrowed from the m68k.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at ppc.kernel.org>
+- * Copyright (c) 2001 PPC64 Team, IBM Corp
+- *
+- * 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 _PPC64_BOOTINFO_H
+-#define _PPC64_BOOTINFO_H
+-
+-#include <asm/types.h>
+-
+-/* We use a u32 for the type of the fields since they're written by
+- * the bootloader which is a 32-bit process and read by the kernel
+- * which is a 64-bit process. This way they can both agree on the
+- * size of the type.
+- */
+-typedef u32 bi_rec_field;
+-
+-struct bi_record {
+- bi_rec_field tag; /* tag ID */
+- bi_rec_field size; /* size of record (in bytes) */
+- bi_rec_field data[0]; /* data */
+-};
+-
+-#define BI_FIRST 0x1010 /* first record - marker */
+-#define BI_LAST 0x1011 /* last record - marker */
+-#define BI_CMD_LINE 0x1012
+-#define BI_BOOTLOADER_ID 0x1013
+-#define BI_INITRD 0x1014
+-#define BI_SYSMAP 0x1015
+-#define BI_MACHTYPE 0x1016
+-
+-static __inline__ struct bi_record * bi_rec_init(unsigned long addr)
+-{
+- struct bi_record *bi_recs;
+- bi_recs = (struct bi_record *)_ALIGN(addr, PAGE_SIZE);
+- bi_recs->size = 0;
+- return bi_recs;
+-}
+-
+-static __inline__ struct bi_record * bi_rec_alloc(struct bi_record *rec,
+- unsigned long args)
+-{
+- rec = (struct bi_record *)((unsigned long)rec + rec->size);
+- rec->size = sizeof(struct bi_record) + args*sizeof(bi_rec_field);
+- return rec;
+-}
+-
+-static __inline__ struct bi_record * bi_rec_alloc_bytes(struct bi_record *rec,
+- unsigned long bytes)
+-{
+- rec = (struct bi_record *)((unsigned long)rec + rec->size);
+- rec->size = sizeof(struct bi_record) + bytes;
+- return rec;
+-}
+-
+-static __inline__ struct bi_record * bi_rec_next(struct bi_record *rec)
+-{
+- return (struct bi_record *)((unsigned long)rec + rec->size);
+-}
+-
+-#endif /* _PPC64_BOOTINFO_H */
+diff --git a/include/asm-ppc64/btext.h b/include/asm-ppc64/btext.h
+--- a/include/asm-ppc64/btext.h
++++ b/include/asm-ppc64/btext.h
+@@ -15,6 +15,7 @@ extern int boot_text_mapped;
+ extern int btext_initialize(struct device_node *np);
+
+ extern void map_boot_text(void);
++extern void init_boot_display(void);
+ extern void btext_update_display(unsigned long phys, int width, int height,
+ int depth, int pitch);
+
+diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h
+deleted file mode 100644
+--- a/include/asm-ppc64/bug.h
++++ /dev/null
+@@ -1,69 +0,0 @@
+-#ifndef _PPC64_BUG_H
+-#define _PPC64_BUG_H
+-
+-/*
+- * Define an illegal instr to trap on the bug.
+- * We don't use 0 because that marks the end of a function
+- * in the ELF ABI. That's "Boo Boo" in case you wonder...
+- */
+-#define BUG_OPCODE .long 0x00b00b00 /* For asm */
+-#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */
+-
+-#ifndef __ASSEMBLY__
+-
+-struct bug_entry {
+- unsigned long bug_addr;
+- long line;
+- const char *file;
+- const char *function;
+-};
+-
+-struct bug_entry *find_bug(unsigned long bugaddr);
+-
+-/*
+- * If this bit is set in the line number it means that the trap
+- * is for WARN_ON rather than BUG or BUG_ON.
+- */
+-#define BUG_WARNING_TRAP 0x1000000
+-
+-#ifdef CONFIG_BUG
+-
+-#define BUG() do { \
+- __asm__ __volatile__( \
+- "1: twi 31,0,0\n" \
+- ".section __bug_table,\"a\"\n\t" \
+- " .llong 1b,%0,%1,%2\n" \
+- ".previous" \
+- : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
+-} while (0)
+-
+-#define BUG_ON(x) do { \
+- __asm__ __volatile__( \
+- "1: tdnei %0,0\n" \
+- ".section __bug_table,\"a\"\n\t" \
+- " .llong 1b,%1,%2,%3\n" \
+- ".previous" \
+- : : "r" ((long long)(x)), "i" (__LINE__), \
+- "i" (__FILE__), "i" (__FUNCTION__)); \
+-} while (0)
+-
+-#define WARN_ON(x) do { \
+- __asm__ __volatile__( \
+- "1: tdnei %0,0\n" \
+- ".section __bug_table,\"a\"\n\t" \
+- " .llong 1b,%1,%2,%3\n" \
+- ".previous" \
+- : : "r" ((long long)(x)), \
+- "i" (__LINE__ + BUG_WARNING_TRAP), \
+- "i" (__FILE__), "i" (__FUNCTION__)); \
+-} while (0)
+-
+-#define HAVE_ARCH_BUG
+-#define HAVE_ARCH_BUG_ON
+-#define HAVE_ARCH_WARN_ON
+-#endif
+-#endif
+-
+-#include <asm-generic/bug.h>
+-
+-#endif
+diff --git a/include/asm-ppc64/byteorder.h b/include/asm-ppc64/byteorder.h
+deleted file mode 100644
+--- a/include/asm-ppc64/byteorder.h
++++ /dev/null
+@@ -1,86 +0,0 @@
+-#ifndef _PPC64_BYTEORDER_H
+-#define _PPC64_BYTEORDER_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.
+- */
+-
+-#include <asm/types.h>
+-#include <linux/compiler.h>
+-
+-#ifdef __GNUC__
+-#ifdef __KERNEL__
+-
+-static __inline__ __u16 ld_le16(const volatile __u16 *addr)
+-{
+- __u16 val;
+-
+- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+- return val;
+-}
+-
+-static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
+-{
+- __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+-}
+-
+-static __inline__ __u32 ld_le32(const volatile __u32 *addr)
+-{
+- __u32 val;
+-
+- __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+- return val;
+-}
+-
+-static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
+-{
+- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+-}
+-
+-static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
+-{
+- __u16 result;
+-
+- __asm__("rlwimi %0,%1,8,16,23"
+- : "=r" (result)
+- : "r" (value), "0" (value >> 8));
+- return result;
+-}
+-
+-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
+-{
+- __u32 result;
+-
+- __asm__("rlwimi %0,%1,24,16,23\n\t"
+- "rlwimi %0,%1,8,8,15\n\t"
+- "rlwimi %0,%1,24,0,7"
+- : "=r" (result)
+- : "r" (value), "0" (value >> 24));
+- return result;
+-}
+-
+-#define __arch__swab16(x) ___arch__swab16(x)
+-#define __arch__swab32(x) ___arch__swab32(x)
+-
+-/* The same, but returns converted value from the location pointer by addr. */
+-#define __arch__swab16p(addr) ld_le16(addr)
+-#define __arch__swab32p(addr) ld_le32(addr)
+-
+-/* The same, but do the conversion in situ, ie. put the value back to addr. */
+-#define __arch__swab16s(addr) st_le16(addr,*addr)
+-#define __arch__swab32s(addr) st_le32(addr,*addr)
+-
+-#endif /* __KERNEL__ */
+-
+-#ifndef __STRICT_ANSI__
+-#define __BYTEORDER_HAS_U64__
+-#endif
+-
+-#endif /* __GNUC__ */
+-
+-#include <linux/byteorder/big_endian.h>
+-
+-#endif /* _PPC64_BYTEORDER_H */
+diff --git a/include/asm-ppc64/checksum.h b/include/asm-ppc64/checksum.h
+deleted file mode 100644
+--- a/include/asm-ppc64/checksum.h
++++ /dev/null
+@@ -1,107 +0,0 @@
+-#ifndef _PPC64_CHECKSUM_H
+-#define _PPC64_CHECKSUM_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.
+- */
+-
+-/*
+- * This is a version of ip_compute_csum() optimized for IP headers,
+- * which always checksum on 4 octet boundaries. ihl is the number
+- * of 32-bit words and is always >= 5.
+- */
+-extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+-
+-/*
+- * computes the checksum of the TCP/UDP pseudo-header
+- * returns a 16-bit checksum, already complemented
+- */
+-extern unsigned short csum_tcpudp_magic(unsigned long saddr,
+- unsigned long daddr,
+- unsigned short len,
+- unsigned short proto,
+- unsigned int sum);
+-
+-/*
+- * computes the checksum of a memory block at buff, length len,
+- * and adds in "sum" (32-bit)
+- *
+- * returns a 32-bit number suitable for feeding into itself
+- * or csum_tcpudp_magic
+- *
+- * this function must be called with even lengths, except
+- * for the last fragment, which may be odd
+- *
+- * it's best to have buff aligned on a 32-bit boundary
+- */
+-extern unsigned int csum_partial(const unsigned char * buff, int len,
+- unsigned int sum);
+-
+-/*
+- * the same as csum_partial, but copies from src to dst while it
+- * checksums
+- */
+-extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
+- int len, unsigned int sum,
+- int *src_err, int *dst_err);
+-/*
+- * the same as csum_partial, but copies from src to dst while it
+- * checksums.
+- */
+-
+-unsigned int csum_partial_copy_nocheck(const char *src,
+- char *dst,
+- int len,
+- unsigned int sum);
+-
+-/*
+- * turns a 32-bit partial checksum (e.g. from csum_partial) into a
+- * 1's complement 16-bit checksum.
+- */
+-static inline unsigned int csum_fold(unsigned int sum)
+-{
+- unsigned int tmp;
+-
+- /* swap the two 16-bit halves of sum */
+- __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum));
+- /* if there is a carry from adding the two 16-bit halves,
+- it will carry from the lower half into the upper half,
+- giving us the correct sum in the upper half. */
+- sum = ~(sum + tmp) >> 16;
+- return sum;
+-}
+-
+-/*
+- * this routine is used for miscellaneous IP-like checksums, mainly
+- * in icmp.c
+- */
+-static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+-{
+- return csum_fold(csum_partial(buff, len, 0));
+-}
+-
+-#define csum_partial_copy_from_user(src, dst, len, sum, errp) \
+- csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
+-
+-#define csum_partial_copy_nocheck(src, dst, len, sum) \
+- csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
+-
+-static inline u32 csum_tcpudp_nofold(u32 saddr,
+- u32 daddr,
+- unsigned short len,
+- unsigned short proto,
+- unsigned int sum)
+-{
+- unsigned long s = sum;
+-
+- s += saddr;
+- s += daddr;
+- s += (proto << 16) + len;
+- s += (s >> 32);
+- return (u32) s;
+-}
+-
+-#endif
+diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h
+deleted file mode 100644
+--- a/include/asm-ppc64/cputable.h
++++ /dev/null
+@@ -1,167 +0,0 @@
+-/*
+- * include/asm-ppc64/cputable.h
+- *
+- * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * Modifications for ppc64:
+- * Copyright (C) 2003 Dave Engebretsen <engebret at us.ibm.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#ifndef __ASM_PPC_CPUTABLE_H
+-#define __ASM_PPC_CPUTABLE_H
+-
+-#include <linux/config.h>
+-#include <asm/page.h> /* for ASM_CONST */
+-
+-/* Exposed to userland CPU features - Must match ppc32 definitions */
+-#define PPC_FEATURE_32 0x80000000
+-#define PPC_FEATURE_64 0x40000000
+-#define PPC_FEATURE_601_INSTR 0x20000000
+-#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
+-#define PPC_FEATURE_HAS_FPU 0x08000000
+-#define PPC_FEATURE_HAS_MMU 0x04000000
+-#define PPC_FEATURE_HAS_4xxMAC 0x02000000
+-#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
+-
+-#ifdef __KERNEL__
+-
+-#ifndef __ASSEMBLY__
+-
+-/* This structure can grow, it's real size is used by head.S code
+- * via the mkdefs mechanism.
+- */
+-struct cpu_spec;
+-struct op_ppc64_model;
+-
+-typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
+-
+-struct cpu_spec {
+- /* CPU is matched via (PVR & pvr_mask) == pvr_value */
+- unsigned int pvr_mask;
+- unsigned int pvr_value;
+-
+- char *cpu_name;
+- unsigned long cpu_features; /* Kernel features */
+- unsigned int cpu_user_features; /* Userland features */
+-
+- /* cache line sizes */
+- unsigned int icache_bsize;
+- unsigned int dcache_bsize;
+-
+- /* number of performance monitor counters */
+- unsigned int num_pmcs;
+-
+- /* this is called to initialize various CPU bits like L1 cache,
+- * BHT, SPD, etc... from head.S before branching to identify_machine
+- */
+- cpu_setup_t cpu_setup;
+-
+- /* Used by oprofile userspace to select the right counters */
+- char *oprofile_cpu_type;
+-
+- /* Processor specific oprofile operations */
+- struct op_ppc64_model *oprofile_model;
+-};
+-
+-extern struct cpu_spec cpu_specs[];
+-extern struct cpu_spec *cur_cpu_spec;
+-
+-static inline unsigned long cpu_has_feature(unsigned long feature)
+-{
+- return cur_cpu_spec->cpu_features & feature;
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-/* CPU kernel features */
+-
+-/* Retain the 32b definitions for the time being - use bottom half of word */
+-#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001)
+-#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002)
+-#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004)
+-#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008)
+-#define CPU_FTR_TAU ASM_CONST(0x0000000000000010)
+-#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020)
+-#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040)
+-#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080)
+-#define CPU_FTR_601 ASM_CONST(0x0000000000000100)
+-#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200)
+-#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400)
+-#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800)
+-#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000)
+-#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000)
+-#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000)
+-
+-/* Add the 64b processor unique features in the top half of the word */
+-#define CPU_FTR_SLB ASM_CONST(0x0000000100000000)
+-#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000)
+-#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000)
+-#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000)
+-#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000)
+-#define CPU_FTR_IABR ASM_CONST(0x0000002000000000)
+-#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000)
+-/* unused ASM_CONST(0x0000008000000000) */
+-#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
+-#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
+-#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
+-#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
+-#define CPU_FTR_CTRL ASM_CONST(0x0000100000000000)
+-
+-#ifndef __ASSEMBLY__
+-
+-#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \
+- PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU)
+-
+-#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \
+- CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \
+- CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL)
+-
+-/* iSeries doesn't support large pages */
+-#ifdef CONFIG_PPC_ISERIES
+-#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE)
+-#else
+-#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE)
+-#endif /* CONFIG_PPC_ISERIES */
+-
+-#endif /* __ASSEMBLY */
+-
+-#ifdef __ASSEMBLY__
+-
+-#define BEGIN_FTR_SECTION 98:
+-
+-#define END_FTR_SECTION(msk, val) \
+-99: \
+- .section __ftr_fixup,"a"; \
+- .align 3; \
+- .llong msk; \
+- .llong val; \
+- .llong 98b; \
+- .llong 99b; \
+- .previous
+-
+-#else
+-
+-#define BEGIN_FTR_SECTION "98:\n"
+-#define END_FTR_SECTION(msk, val) \
+-"99:\n" \
+-" .section __ftr_fixup,\"a\";\n" \
+-" .align 3;\n" \
+-" .llong "#msk";\n" \
+-" .llong "#val";\n" \
+-" .llong 98b;\n" \
+-" .llong 99b;\n" \
+-" .previous\n"
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk))
+-#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0)
+-
+-#endif /* __ASM_PPC_CPUTABLE_H */
+-#endif /* __KERNEL__ */
+-
+diff --git a/include/asm-ppc64/dart.h b/include/asm-ppc64/dart.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-ppc64/dart.h
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _ASM_DART_H
++#define _ASM_DART_H
++
++
++/* physical base of DART registers */
++#define DART_BASE 0xf8033000UL
++
++/* Offset from base to control register */
++#define DARTCNTL 0
++/* Offset from base to exception register */
++#define DARTEXCP 0x10
++/* Offset from base to TLB tag registers */
++#define DARTTAG 0x1000
++
++
++/* Control Register fields */
++
++/* base address of table (pfn) */
++#define DARTCNTL_BASE_MASK 0xfffff
++#define DARTCNTL_BASE_SHIFT 12
++
++#define DARTCNTL_FLUSHTLB 0x400
++#define DARTCNTL_ENABLE 0x200
++
++/* size of table in pages */
++#define DARTCNTL_SIZE_MASK 0x1ff
++#define DARTCNTL_SIZE_SHIFT 0
++
++
++/* DART table fields */
++
++#define DARTMAP_VALID 0x80000000
++#define DARTMAP_RPNMASK 0x00ffffff
++
++
++#define DART_PAGE_SHIFT 12
++#define DART_PAGE_SIZE (1 << DART_PAGE_SHIFT)
++#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_PAGE_SHIFT)
++
++
++#endif
+diff --git a/include/asm-ppc64/dbdma.h b/include/asm-ppc64/dbdma.h
+deleted file mode 100644
+--- a/include/asm-ppc64/dbdma.h
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#include <asm-ppc/dbdma.h>
+-
+diff --git a/include/asm-ppc64/dma.h b/include/asm-ppc64/dma.h
+deleted file mode 100644
+--- a/include/asm-ppc64/dma.h
++++ /dev/null
+@@ -1,329 +0,0 @@
+-/*
+- * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+- * Written by Hennus Bergman, 1992.
+- * High DMA channel support & info by Hannu Savolainen
+- * and John Boyd, Nov. 1992.
+- * Changes for ppc sound by Christoph Nadig
+- *
+- * 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_DMA_H
+-#define _ASM_DMA_H
+-
+-#include <linux/config.h>
+-#include <asm/io.h>
+-#include <linux/spinlock.h>
+-#include <asm/system.h>
+-
+-#ifndef MAX_DMA_CHANNELS
+-#define MAX_DMA_CHANNELS 8
+-#endif
+-
+-/* The maximum address that we can perform a DMA transfer to on this platform */
+-/* Doesn't really apply... */
+-#define MAX_DMA_ADDRESS (~0UL)
+-
+-#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)
+-
+-#define dma_outb outb
+-#define dma_inb inb
+-
+-/*
+- * NOTES about DMA transfers:
+- *
+- * controller 1: channels 0-3, byte operations, ports 00-1F
+- * controller 2: channels 4-7, word operations, ports C0-DF
+- *
+- * - ALL registers are 8 bits only, regardless of transfer size
+- * - channel 4 is not used - cascades 1 into 2.
+- * - channels 0-3 are byte - addresses/counts are for physical bytes
+- * - channels 5-7 are word - addresses/counts are for physical words
+- * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
+- * - transfer count loaded to registers is 1 less than actual count
+- * - controller 2 offsets are all even (2x offsets for controller 1)
+- * - page registers for 5-7 don't use data bit 0, represent 128K pages
+- * - page registers for 0-3 use bit 0, represent 64K pages
+- *
+- * On PReP, DMA transfers are limited to the lower 16MB of _physical_ memory.
+- * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing.
+- * Note that addresses loaded into registers must be _physical_ addresses,
+- * not logical addresses (which may differ if paging is active).
+- *
+- * Address mapping for channels 0-3:
+- *
+- * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses)
+- * | ... | | ... | | ... |
+- * | ... | | ... | | ... |
+- * | ... | | ... | | ... |
+- * P7 ... P0 A7 ... A0 A7 ... A0
+- * | Page | Addr MSB | Addr LSB | (DMA registers)
+- *
+- * Address mapping for channels 5-7:
+- *
+- * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses)
+- * | ... | \ \ ... \ \ \ ... \ \
+- * | ... | \ \ ... \ \ \ ... \ (not used)
+- * | ... | \ \ ... \ \ \ ... \
+- * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0
+- * | Page | Addr MSB | Addr LSB | (DMA registers)
+- *
+- * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
+- * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
+- * the hardware level, so odd-byte transfers aren't possible).
+- *
+- * Transfer count (_not # bytes_) is limited to 64K, represented as actual
+- * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more,
+- * and up to 128K bytes may be transferred on channels 5-7 in one operation.
+- *
+- */
+-
+-/* 8237 DMA controllers */
+-#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
+-#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */
+-
+-/* DMA controller registers */
+-#define DMA1_CMD_REG 0x08 /* command register (w) */
+-#define DMA1_STAT_REG 0x08 /* status register (r) */
+-#define DMA1_REQ_REG 0x09 /* request register (w) */
+-#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+-#define DMA1_MODE_REG 0x0B /* mode register (w) */
+-#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+-#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+-#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+-#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+-#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+-
+-#define DMA2_CMD_REG 0xD0 /* command register (w) */
+-#define DMA2_STAT_REG 0xD0 /* status register (r) */
+-#define DMA2_REQ_REG 0xD2 /* request register (w) */
+-#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+-#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+-#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+-#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+-#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+-#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+-#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+-
+-#define DMA_ADDR_0 0x00 /* DMA address registers */
+-#define DMA_ADDR_1 0x02
+-#define DMA_ADDR_2 0x04
+-#define DMA_ADDR_3 0x06
+-#define DMA_ADDR_4 0xC0
+-#define DMA_ADDR_5 0xC4
+-#define DMA_ADDR_6 0xC8
+-#define DMA_ADDR_7 0xCC
+-
+-#define DMA_CNT_0 0x01 /* DMA count registers */
+-#define DMA_CNT_1 0x03
+-#define DMA_CNT_2 0x05
+-#define DMA_CNT_3 0x07
+-#define DMA_CNT_4 0xC2
+-#define DMA_CNT_5 0xC6
+-#define DMA_CNT_6 0xCA
+-#define DMA_CNT_7 0xCE
+-
+-#define DMA_LO_PAGE_0 0x87 /* DMA page registers */
+-#define DMA_LO_PAGE_1 0x83
+-#define DMA_LO_PAGE_2 0x81
+-#define DMA_LO_PAGE_3 0x82
+-#define DMA_LO_PAGE_5 0x8B
+-#define DMA_LO_PAGE_6 0x89
+-#define DMA_LO_PAGE_7 0x8A
+-
+-#define DMA_HI_PAGE_0 0x487 /* DMA page registers */
+-#define DMA_HI_PAGE_1 0x483
+-#define DMA_HI_PAGE_2 0x481
+-#define DMA_HI_PAGE_3 0x482
+-#define DMA_HI_PAGE_5 0x48B
+-#define DMA_HI_PAGE_6 0x489
+-#define DMA_HI_PAGE_7 0x48A
+-
+-#define DMA1_EXT_REG 0x40B
+-#define DMA2_EXT_REG 0x4D6
+-
+-#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
+-#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
+-#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
+-
+-#define DMA_AUTOINIT 0x10
+-
+-extern spinlock_t dma_spin_lock;
+-
+-static __inline__ unsigned long claim_dma_lock(void)
+-{
+- unsigned long flags;
+- spin_lock_irqsave(&dma_spin_lock, flags);
+- return flags;
+-}
+-
+-static __inline__ void release_dma_lock(unsigned long flags)
+-{
+- spin_unlock_irqrestore(&dma_spin_lock, flags);
+-}
+-
+-/* enable/disable a specific DMA channel */
+-static __inline__ void enable_dma(unsigned int dmanr)
+-{
+- unsigned char ucDmaCmd=0x00;
+-
+- if (dmanr != 4)
+- {
+- dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */
+- dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */
+- }
+- if (dmanr<=3)
+- {
+- dma_outb(dmanr, DMA1_MASK_REG);
+- dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */
+- } else
+- {
+- dma_outb(dmanr & 3, DMA2_MASK_REG);
+- }
+-}
+-
+-static __inline__ void disable_dma(unsigned int dmanr)
+-{
+- if (dmanr<=3)
+- dma_outb(dmanr | 4, DMA1_MASK_REG);
+- else
+- dma_outb((dmanr & 3) | 4, DMA2_MASK_REG);
+-}
+-
+-/* Clear the 'DMA Pointer Flip Flop'.
+- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+- * Use this once to initialize the FF to a known state.
+- * After that, keep track of it. :-)
+- * --- In order to do that, the DMA routines below should ---
+- * --- only be used while interrupts are disabled! ---
+- */
+-static __inline__ void clear_dma_ff(unsigned int dmanr)
+-{
+- if (dmanr<=3)
+- dma_outb(0, DMA1_CLEAR_FF_REG);
+- else
+- dma_outb(0, DMA2_CLEAR_FF_REG);
+-}
+-
+-/* set mode (above) for a specific DMA channel */
+-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+-{
+- if (dmanr<=3)
+- dma_outb(mode | dmanr, DMA1_MODE_REG);
+- else
+- dma_outb(mode | (dmanr&3), DMA2_MODE_REG);
+-}
+-
+-/* Set only the page register bits of the transfer address.
+- * This is used for successive transfers when we know the contents of
+- * the lower 16 bits of the DMA current address register, but a 64k boundary
+- * may have been crossed.
+- */
+-static __inline__ void set_dma_page(unsigned int dmanr, int pagenr)
+-{
+- switch(dmanr) {
+- case 0:
+- dma_outb(pagenr, DMA_LO_PAGE_0);
+- dma_outb(pagenr>>8, DMA_HI_PAGE_0);
+- break;
+- case 1:
+- dma_outb(pagenr, DMA_LO_PAGE_1);
+- dma_outb(pagenr>>8, DMA_HI_PAGE_1);
+- break;
+- case 2:
+- dma_outb(pagenr, DMA_LO_PAGE_2);
+- dma_outb(pagenr>>8, DMA_HI_PAGE_2);
+- break;
+- case 3:
+- dma_outb(pagenr, DMA_LO_PAGE_3);
+- dma_outb(pagenr>>8, DMA_HI_PAGE_3);
+- break;
+- case 5:
+- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
+- dma_outb(pagenr>>8, DMA_HI_PAGE_5);
+- break;
+- case 6:
+- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
+- dma_outb(pagenr>>8, DMA_HI_PAGE_6);
+- break;
+- case 7:
+- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
+- dma_outb(pagenr>>8, DMA_HI_PAGE_7);
+- break;
+- }
+-}
+-
+-
+-/* Set transfer address & page bits for specific DMA channel.
+- * Assumes dma flipflop is clear.
+- */
+-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys)
+-{
+- if (dmanr <= 3) {
+- dma_outb( phys & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+- dma_outb( (phys>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
+- } else {
+- dma_outb( (phys>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+- dma_outb( (phys>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
+- }
+- set_dma_page(dmanr, phys>>16);
+-}
+-
+-
+-/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
+- * a specific DMA channel.
+- * You must ensure the parameters are valid.
+- * NOTE: from a manual: "the number of transfers is one more
+- * than the initial word count"! This is taken into account.
+- * Assumes dma flip-flop is clear.
+- * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+- */
+-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+-{
+- count--;
+- if (dmanr <= 3) {
+- dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+- dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
+- } else {
+- dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+- dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
+- }
+-}
+-
+-
+-/* Get DMA residue count. After a DMA transfer, this
+- * should return zero. Reading this while a DMA transfer is
+- * still in progress will return unpredictable results.
+- * If called before the channel has been used, it may return 1.
+- * Otherwise, it returns the number of _bytes_ left to transfer.
+- *
+- * Assumes DMA flip-flop is clear.
+- */
+-static __inline__ int get_dma_residue(unsigned int dmanr)
+-{
+- unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
+- : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
+-
+- /* using short to get 16-bit wrap around */
+- unsigned short count;
+-
+- count = 1 + dma_inb(io_port);
+- count += dma_inb(io_port) << 8;
+-
+- return (dmanr <= 3)? count : (count<<1);
+-}
+-
+-/* These are in kernel/dma.c: */
+-extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
+-extern void free_dma(unsigned int dmanr); /* release it again */
+-
+-#ifdef CONFIG_PCI
+-extern int isa_dma_bridge_buggy;
+-#else
+-#define isa_dma_bridge_buggy (0)
+-#endif
+-#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */
+-#endif /* _ASM_DMA_H */
+diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h
+deleted file mode 100644
+--- a/include/asm-ppc64/elf.h
++++ /dev/null
+@@ -1,387 +0,0 @@
+-#ifndef __PPC64_ELF_H
+-#define __PPC64_ELF_H
+-
+-#include <asm/types.h>
+-#include <asm/ptrace.h>
+-#include <asm/cputable.h>
+-#include <asm/auxvec.h>
+-
+-/* PowerPC relocations defined by the ABIs */
+-#define R_PPC_NONE 0
+-#define R_PPC_ADDR32 1 /* 32bit absolute address */
+-#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+-#define R_PPC_ADDR16 3 /* 16bit absolute address */
+-#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+-#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+-#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+-#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+-#define R_PPC_ADDR14_BRTAKEN 8
+-#define R_PPC_ADDR14_BRNTAKEN 9
+-#define R_PPC_REL24 10 /* PC relative 26 bit */
+-#define R_PPC_REL14 11 /* PC relative 16 bit */
+-#define R_PPC_REL14_BRTAKEN 12
+-#define R_PPC_REL14_BRNTAKEN 13
+-#define R_PPC_GOT16 14
+-#define R_PPC_GOT16_LO 15
+-#define R_PPC_GOT16_HI 16
+-#define R_PPC_GOT16_HA 17
+-#define R_PPC_PLTREL24 18
+-#define R_PPC_COPY 19
+-#define R_PPC_GLOB_DAT 20
+-#define R_PPC_JMP_SLOT 21
+-#define R_PPC_RELATIVE 22
+-#define R_PPC_LOCAL24PC 23
+-#define R_PPC_UADDR32 24
+-#define R_PPC_UADDR16 25
+-#define R_PPC_REL32 26
+-#define R_PPC_PLT32 27
+-#define R_PPC_PLTREL32 28
+-#define R_PPC_PLT16_LO 29
+-#define R_PPC_PLT16_HI 30
+-#define R_PPC_PLT16_HA 31
+-#define R_PPC_SDAREL16 32
+-#define R_PPC_SECTOFF 33
+-#define R_PPC_SECTOFF_LO 34
+-#define R_PPC_SECTOFF_HI 35
+-#define R_PPC_SECTOFF_HA 36
+-
+-/* PowerPC relocations defined for the TLS access ABI. */
+-#define R_PPC_TLS 67 /* none (sym+add)@tls */
+-#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+-#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+-#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */
+-#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */
+-#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */
+-#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+-#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+-#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */
+-#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */
+-#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */
+-#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+-#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */
+-#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */
+-#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */
+-#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */
+-#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */
+-#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */
+-#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */
+-#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */
+-#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got at tprel */
+-#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got at tprel@l */
+-#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */
+-#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */
+-#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got at dtprel */
+-#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got at dtprel@l */
+-#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got at dtprel@h */
+-#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got at dtprel@ha */
+-
+-/* Keep this the last entry. */
+-#define R_PPC_NUM 95
+-
+-/*
+- * ELF register definitions..
+- *
+- * 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 <asm/ptrace.h>
+-
+-#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
+-#define ELF_NFPREG 33 /* includes fpscr */
+-#define ELF_NVRREG32 33 /* includes vscr & vrsave stuffed together */
+-#define ELF_NVRREG 34 /* includes vscr & vrsave in split vectors */
+-
+-typedef unsigned long elf_greg_t64;
+-typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
+-
+-typedef unsigned int elf_greg_t32;
+-typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
+-
+-/*
+- * These are used to set parameters in the core dumps.
+- */
+-#ifndef ELF_ARCH
+-# define ELF_ARCH EM_PPC64
+-# define ELF_CLASS ELFCLASS64
+-# define ELF_DATA ELFDATA2MSB
+- typedef elf_greg_t64 elf_greg_t;
+- typedef elf_gregset_t64 elf_gregset_t;
+-# define elf_addr_t unsigned long
+-#else
+- /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */
+- typedef elf_greg_t32 elf_greg_t;
+- typedef elf_gregset_t32 elf_gregset_t;
+-# define elf_addr_t u32
+-#endif
+-
+-typedef double elf_fpreg_t;
+-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+-
+-/* Altivec registers */
+-/*
+- * The entries with indexes 0-31 contain the corresponding vector registers.
+- * The entry with index 32 contains the vscr as the last word (offset 12)
+- * within the quadword. This allows the vscr to be stored as either a
+- * quadword (since it must be copied via a vector register to/from storage)
+- * or as a word. The entry with index 33 contains the vrsave as the first
+- * word (offset 0) within the quadword.
+- *
+- * This definition of the VMX state is compatible with the current PPC32
+- * ptrace interface. This allows signal handling and ptrace to use the same
+- * structures. This also simplifies the implementation of a bi-arch
+- * (combined (32- and 64-bit) gdb.
+- *
+- * Note that it's _not_ compatible with 32 bits ucontext which stuffs the
+- * vrsave along with vscr and so only uses 33 vectors for the register set
+- */
+-typedef __vector128 elf_vrreg_t;
+-typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG];
+-typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
+-
+-/*
+- * This is used to ensure we don't load something for the wrong architecture.
+- */
+-#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 4096
+-
+-/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+- use of this is to invoke "./ld.so someprog" to test out a new version of
+- the loader. We need to make sure that it is out of the way of the program
+- that it will "exec", and that there is sufficient room for the brk. */
+-
+-#define ELF_ET_DYN_BASE (0x08000000)
+-
+-#ifdef __KERNEL__
+-
+-/* Common routine for both 32-bit and 64-bit processes */
+-static inline void ppc64_elf_core_copy_regs(elf_gregset_t elf_regs,
+- struct pt_regs *regs)
+-{
+- int i;
+- int gprs = sizeof(struct pt_regs)/sizeof(elf_greg_t64);
+-
+- if (gprs > ELF_NGREG)
+- gprs = ELF_NGREG;
+-
+- for (i=0; i < gprs; i++)
+- elf_regs[i] = (elf_greg_t)((elf_greg_t64 *)regs)[i];
+-}
+-#define ELF_CORE_COPY_REGS(gregs, regs) ppc64_elf_core_copy_regs(gregs, regs);
+-
+-static inline int dump_task_regs(struct task_struct *tsk,
+- elf_gregset_t *elf_regs)
+-{
+- struct pt_regs *regs = tsk->thread.regs;
+- if (regs)
+- ppc64_elf_core_copy_regs(*elf_regs, regs);
+-
+- return 1;
+-}
+-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+-
+-extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
+-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+-
+-/* XXX Should we define the XFPREGS using altivec ??? */
+-
+-#endif
+-
+-/* This yields a mask that user programs can use to figure out what
+- instruction set this cpu supports. This could be done in userspace,
+- but it's not easy, and we've already done it here. */
+-
+-#define ELF_HWCAP (cur_cpu_spec->cpu_user_features)
+-
+-/* This yields a string that ld.so will use to load implementation
+- specific libraries for optimization. This is more specific in
+- intent than poking at uname or /proc/cpuinfo.
+-
+- For the moment, we have only optimizations for the Intel generations,
+- but that could change... */
+-
+-#define ELF_PLATFORM (NULL)
+-
+-#define ELF_PLAT_INIT(_r, load_addr) do { \
+- memset(_r->gpr, 0, sizeof(_r->gpr)); \
+- _r->ctr = _r->link = _r->xer = _r->ccr = 0; \
+- _r->gpr[2] = load_addr; \
+-} while (0)
+-
+-#ifdef __KERNEL__
+-#define SET_PERSONALITY(ex, ibcs2) \
+-do { \
+- unsigned long new_flags = 0; \
+- if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+- new_flags = _TIF_32BIT; \
+- if ((current_thread_info()->flags & _TIF_32BIT) \
+- != new_flags) \
+- set_thread_flag(TIF_ABI_PENDING); \
+- else \
+- clear_thread_flag(TIF_ABI_PENDING); \
+- if (personality(current->personality) != PER_LINUX32) \
+- set_personality(PER_LINUX); \
+-} while (0)
+-
+-/*
+- * An executable for which elf_read_implies_exec() returns TRUE will
+- * have the READ_IMPLIES_EXEC personality flag set automatically. This
+- * is only required to work around bugs in old 32bit toolchains. Since
+- * the 64bit ABI has never had these issues dont enable the workaround
+- * even if we have an executable stack.
+- */
+-#define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
+- (exec_stk != EXSTACK_DISABLE_X) : 0)
+-
+-#endif
+-
+-extern int dcache_bsize;
+-extern int icache_bsize;
+-extern int ucache_bsize;
+-
+-/* We do have an arch_setup_additional_pages for vDSO matters */
+-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+-struct linux_binprm;
+-extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack);
+-
+-/*
+- * The requirements here are:
+- * - keep the final alignment of sp (sp & 0xf)
+- * - make sure the 32-bit value at the first 16 byte aligned position of
+- * AUXV is greater than 16 for glibc compatibility.
+- * AT_IGNOREPPC is used for that.
+- * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+- * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+- */
+-#define ARCH_DLINFO \
+-do { \
+- /* Handle glibc compatibility. */ \
+- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+- /* Cache size items */ \
+- NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
+- NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
+- NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
+- /* vDSO base */ \
+- NEW_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base); \
+- } while (0)
+-
+-/* PowerPC64 relocations defined by the ABIs */
+-#define R_PPC64_NONE R_PPC_NONE
+-#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */
+-#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */
+-#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */
+-#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */
+-#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */
+-#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
+-#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */
+-#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+-#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+-#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */
+-#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */
+-#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+-#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+-#define R_PPC64_GOT16 R_PPC_GOT16
+-#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+-#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+-#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+-
+-#define R_PPC64_COPY R_PPC_COPY
+-#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+-#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+-#define R_PPC64_RELATIVE R_PPC_RELATIVE
+-
+-#define R_PPC64_UADDR32 R_PPC_UADDR32
+-#define R_PPC64_UADDR16 R_PPC_UADDR16
+-#define R_PPC64_REL32 R_PPC_REL32
+-#define R_PPC64_PLT32 R_PPC_PLT32
+-#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+-#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+-#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+-#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+-
+-#define R_PPC64_SECTOFF R_PPC_SECTOFF
+-#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+-#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+-#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+-#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */
+-#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */
+-#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */
+-#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */
+-#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */
+-#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */
+-#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */
+-#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */
+-#define R_PPC64_PLT64 45 /* doubleword64 L + A. */
+-#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */
+-#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */
+-#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */
+-#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */
+-#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */
+-#define R_PPC64_TOC 51 /* doubleword64 .TOC. */
+-#define R_PPC64_PLTGOT16 52 /* half16* M + A. */
+-#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */
+-#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */
+-#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */
+-
+-#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */
+-#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */
+-#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */
+-#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */
+-#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */
+-#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */
+-#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */
+-#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */
+-#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */
+-#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */
+-#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */
+-
+-/* PowerPC64 relocations defined for the TLS access ABI. */
+-#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+-#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+-#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+-#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel at l */
+-#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel at h */
+-#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel at ha */
+-#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+-#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+-#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel at l */
+-#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel at h */
+-#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel at ha */
+-#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+-#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got at tlsgd */
+-#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got at tlsgd@l */
+-#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got at tlsgd@h */
+-#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got at tlsgd@ha */
+-#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got at tlsld */
+-#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got at tlsld@l */
+-#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got at tlsld@h */
+-#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got at tlsld@ha */
+-#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got at tprel */
+-#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got at tprel@l */
+-#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got at tprel@h */
+-#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got at tprel@ha */
+-#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got at dtprel */
+-#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got at dtprel@l */
+-#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got at dtprel@h */
+-#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got at dtprel@ha */
+-#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+-#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel at l */
+-#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel at higher */
+-#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel at highera */
+-#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel at highest */
+-#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel at highesta */
+-#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+-#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel at l */
+-#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel at higher */
+-#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel at highera */
+-#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel at highest */
+-#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel at highesta */
+-
+-/* Keep this the last entry. */
+-#define R_PPC64_NUM 107
+-
+-#endif /* __PPC64_ELF_H */
+diff --git a/include/asm-ppc64/firmware.h b/include/asm-ppc64/firmware.h
+deleted file mode 100644
+--- a/include/asm-ppc64/firmware.h
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/*
+- * include/asm-ppc64/firmware.h
+- *
+- * Extracted from include/asm-ppc64/cputable.h
+- *
+- * Copyright (C) 2001 Ben. Herrenschmidt (benh at kernel.crashing.org)
+- *
+- * Modifications for ppc64:
+- * Copyright (C) 2003 Dave Engebretsen <engebret at us.ibm.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-#ifndef __ASM_PPC_FIRMWARE_H
+-#define __ASM_PPC_FIRMWARE_H
+-
+-#ifdef __KERNEL__
+-
+-#ifndef __ASSEMBLY__
+-
+-/* firmware feature bitmask values */
+-#define FIRMWARE_MAX_FEATURES 63
+-
+-#define FW_FEATURE_PFT (1UL<<0)
+-#define FW_FEATURE_TCE (1UL<<1)
+-#define FW_FEATURE_SPRG0 (1UL<<2)
+-#define FW_FEATURE_DABR (1UL<<3)
+-#define FW_FEATURE_COPY (1UL<<4)
+-#define FW_FEATURE_ASR (1UL<<5)
+-#define FW_FEATURE_DEBUG (1UL<<6)
+-#define FW_FEATURE_TERM (1UL<<7)
+-#define FW_FEATURE_PERF (1UL<<8)
+-#define FW_FEATURE_DUMP (1UL<<9)
+-#define FW_FEATURE_INTERRUPT (1UL<<10)
+-#define FW_FEATURE_MIGRATE (1UL<<11)
+-#define FW_FEATURE_PERFMON (1UL<<12)
+-#define FW_FEATURE_CRQ (1UL<<13)
+-#define FW_FEATURE_VIO (1UL<<14)
+-#define FW_FEATURE_RDMA (1UL<<15)
+-#define FW_FEATURE_LLAN (1UL<<16)
+-#define FW_FEATURE_BULK (1UL<<17)
+-#define FW_FEATURE_XDABR (1UL<<18)
+-#define FW_FEATURE_MULTITCE (1UL<<19)
+-#define FW_FEATURE_SPLPAR (1UL<<20)
+-#define FW_FEATURE_ISERIES (1UL<<21)
+-
+-enum {
+- FW_FEATURE_PSERIES_POSSIBLE = FW_FEATURE_PFT | FW_FEATURE_TCE |
+- FW_FEATURE_SPRG0 | FW_FEATURE_DABR | FW_FEATURE_COPY |
+- FW_FEATURE_ASR | FW_FEATURE_DEBUG | FW_FEATURE_TERM |
+- FW_FEATURE_PERF | FW_FEATURE_DUMP | FW_FEATURE_INTERRUPT |
+- FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
+- FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
+- FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
+- FW_FEATURE_SPLPAR,
+- FW_FEATURE_PSERIES_ALWAYS = 0,
+- FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES,
+- FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES,
+- FW_FEATURE_POSSIBLE =
+-#ifdef CONFIG_PPC_PSERIES
+- FW_FEATURE_PSERIES_POSSIBLE |
+-#endif
+-#ifdef CONFIG_PPC_ISERIES
+- FW_FEATURE_ISERIES_POSSIBLE |
+-#endif
+- 0,
+- FW_FEATURE_ALWAYS =
+-#ifdef CONFIG_PPC_PSERIES
+- FW_FEATURE_PSERIES_ALWAYS &
+-#endif
+-#ifdef CONFIG_PPC_ISERIES
+- FW_FEATURE_ISERIES_ALWAYS &
+-#endif
+- FW_FEATURE_POSSIBLE,
+-};
+-
+-/* This is used to identify firmware features which are available
+- * to the kernel.
+- */
+-extern unsigned long ppc64_firmware_features;
+-
+-static inline unsigned long firmware_has_feature(unsigned long feature)
+-{
+- return (FW_FEATURE_ALWAYS & feature) ||
+- (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
+-}
+-
+-#ifdef CONFIG_PPC_PSERIES
+-typedef struct {
+- unsigned long val;
+- char * name;
+-} firmware_feature_t;
+-
+-extern firmware_feature_t firmware_features_table[];
+-#endif
+-
+-#endif /* __ASSEMBLY__ */
+-#endif /* __KERNEL__ */
+-#endif /* __ASM_PPC_FIRMWARE_H */
+diff --git a/include/asm-ppc64/futex.h b/include/asm-ppc64/futex.h
+--- a/include/asm-ppc64/futex.h
++++ b/include/asm-ppc64/futex.h
+@@ -5,7 +5,7 @@
+
+ #include <linux/futex.h>
+ #include <asm/errno.h>
+-#include <asm/memory.h>
++#include <asm/synch.h>
+ #include <asm/uaccess.h>
+
+ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+diff --git a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h
+deleted file mode 100644
+--- a/include/asm-ppc64/hardirq.h
++++ /dev/null
+@@ -1,27 +0,0 @@
+-#ifndef __ASM_HARDIRQ_H
+-#define __ASM_HARDIRQ_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.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/cache.h>
+-#include <linux/preempt.h>
+-
+-typedef struct {
+- unsigned int __softirq_pending;
+-} ____cacheline_aligned irq_cpustat_t;
+-
+-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+-
+-static inline void ack_bad_irq(int irq)
+-{
+- printk(KERN_CRIT "illegal vector %d received!\n", irq);
+- BUG();
+-}
+-
+-#endif /* __ASM_HARDIRQ_H */
+diff --git a/include/asm-ppc64/hw_irq.h b/include/asm-ppc64/hw_irq.h
+deleted file mode 100644
+--- a/include/asm-ppc64/hw_irq.h
++++ /dev/null
+@@ -1,104 +0,0 @@
+-/*
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- *
+- * Use inline IRQs where possible - Anton Blanchard <anton at au.ibm.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-#ifdef __KERNEL__
+-#ifndef _PPC64_HW_IRQ_H
+-#define _PPC64_HW_IRQ_H
+-
+-#include <linux/config.h>
+-#include <linux/errno.h>
+-#include <asm/irq.h>
+-
+-int timer_interrupt(struct pt_regs *);
+-extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
+-
+-#ifdef CONFIG_PPC_ISERIES
+-
+-extern unsigned long local_get_flags(void);
+-extern unsigned long local_irq_disable(void);
+-extern void local_irq_restore(unsigned long);
+-
+-#define local_irq_enable() local_irq_restore(1)
+-#define local_save_flags(flags) ((flags) = local_get_flags())
+-#define local_irq_save(flags) ((flags) = local_irq_disable())
+-
+-#define irqs_disabled() (local_get_flags() == 0)
+-
+-#else
+-
+-#define local_save_flags(flags) ((flags) = mfmsr())
+-#define local_irq_restore(flags) do { \
+- __asm__ __volatile__("": : :"memory"); \
+- __mtmsrd((flags), 1); \
+-} while(0)
+-
+-static inline void local_irq_disable(void)
+-{
+- unsigned long msr;
+- msr = mfmsr();
+- __mtmsrd(msr & ~MSR_EE, 1);
+- __asm__ __volatile__("": : :"memory");
+-}
+-
+-static inline void local_irq_enable(void)
+-{
+- unsigned long msr;
+- __asm__ __volatile__("": : :"memory");
+- msr = mfmsr();
+- __mtmsrd(msr | MSR_EE, 1);
+-}
+-
+-static inline void __do_save_and_cli(unsigned long *flags)
+-{
+- unsigned long msr;
+- msr = mfmsr();
+- *flags = msr;
+- __mtmsrd(msr & ~MSR_EE, 1);
+- __asm__ __volatile__("": : :"memory");
+-}
+-
+-#define local_irq_save(flags) __do_save_and_cli(&flags)
+-
+-#define irqs_disabled() \
+-({ \
+- unsigned long flags; \
+- local_save_flags(flags); \
+- !(flags & MSR_EE); \
+-})
+-
+-#endif /* CONFIG_PPC_ISERIES */
+-
+-#define mask_irq(irq) \
+- ({ \
+- irq_desc_t *desc = get_irq_desc(irq); \
+- if (desc->handler && desc->handler->disable) \
+- desc->handler->disable(irq); \
+- })
+-#define unmask_irq(irq) \
+- ({ \
+- irq_desc_t *desc = get_irq_desc(irq); \
+- if (desc->handler && desc->handler->enable) \
+- desc->handler->enable(irq); \
+- })
+-#define ack_irq(irq) \
+- ({ \
+- irq_desc_t *desc = get_irq_desc(irq); \
+- if (desc->handler && desc->handler->ack) \
+- desc->handler->ack(irq); \
+- })
+-
+-/* Should we handle this via lost interrupts and IPIs or should we don't care like
+- * we do now ? --BenH.
+- */
+-struct hw_interrupt_type;
+-static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
+-
+-#endif /* _PPC64_HW_IRQ_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc64/iSeries/HvCallHpt.h b/include/asm-ppc64/iSeries/HvCallHpt.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/HvCallHpt.h
++++ /dev/null
+@@ -1,102 +0,0 @@
+-/*
+- * HvCallHpt.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _HVCALLHPT_H
+-#define _HVCALLHPT_H
+-
+-/*
+- * This file contains the "hypervisor call" interface which is used to
+- * drive the hypervisor from the OS.
+- */
+-
+-#include <asm/iSeries/HvCallSc.h>
+-#include <asm/iSeries/HvTypes.h>
+-#include <asm/mmu.h>
+-
+-#define HvCallHptGetHptAddress HvCallHpt + 0
+-#define HvCallHptGetHptPages HvCallHpt + 1
+-#define HvCallHptSetPp HvCallHpt + 5
+-#define HvCallHptSetSwBits HvCallHpt + 6
+-#define HvCallHptUpdate HvCallHpt + 7
+-#define HvCallHptInvalidateNoSyncICache HvCallHpt + 8
+-#define HvCallHptGet HvCallHpt + 11
+-#define HvCallHptFindNextValid HvCallHpt + 12
+-#define HvCallHptFindValid HvCallHpt + 13
+-#define HvCallHptAddValidate HvCallHpt + 16
+-#define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18
+-
+-
+-static inline u64 HvCallHpt_getHptAddress(void)
+-{
+- return HvCall0(HvCallHptGetHptAddress);
+-}
+-
+-static inline u64 HvCallHpt_getHptPages(void)
+-{
+- return HvCall0(HvCallHptGetHptPages);
+-}
+-
+-static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
+-{
+- HvCall2(HvCallHptSetPp, hpteIndex, value);
+-}
+-
+-static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff)
+-{
+- HvCall3(HvCallHptSetSwBits, hpteIndex, bitson, bitsoff);
+-}
+-
+-static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
+-{
+- HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
+-}
+-
+-static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
+- u8 bitsoff)
+-{
+- u64 compressedStatus;
+-
+- compressedStatus = HvCall4(HvCallHptInvalidateSetSwBitsGet,
+- hpteIndex, bitson, bitsoff, 1);
+- HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
+- return compressedStatus;
+-}
+-
+-static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
+-{
+- return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
+-}
+-
+-static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
+- u8 bitson, u8 bitsoff)
+-{
+- return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
+- bitson, bitsoff);
+-}
+-
+-static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
+-{
+- HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
+-}
+-
+-static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
+-{
+- HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
+-}
+-
+-#endif /* _HVCALLHPT_H */
+diff --git a/include/asm-ppc64/iSeries/HvCallPci.h b/include/asm-ppc64/iSeries/HvCallPci.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/HvCallPci.h
++++ /dev/null
+@@ -1,533 +0,0 @@
+-/*
+- * Provides the Hypervisor PCI calls for iSeries Linux Parition.
+- * Copyright (C) 2001 <Wayne G Holm> <IBM Corporation>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the:
+- * Free Software Foundation, Inc.,
+- * 59 Temple Place, Suite 330,
+- * Boston, MA 02111-1307 USA
+- *
+- * Change Activity:
+- * Created, Jan 9, 2001
+- */
+-
+-#ifndef _HVCALLPCI_H
+-#define _HVCALLPCI_H
+-
+-#include <asm/iSeries/HvCallSc.h>
+-#include <asm/iSeries/HvTypes.h>
+-
+-/*
+- * DSA == Direct Select Address
+- * this struct must be 64 bits in total
+- */
+-struct HvCallPci_DsaAddr {
+- u16 busNumber; /* PHB index? */
+- u8 subBusNumber; /* PCI bus number? */
+- u8 deviceId; /* device and function? */
+- u8 barNumber;
+- u8 reserved[3];
+-};
+-
+-union HvDsaMap {
+- u64 DsaAddr;
+- struct HvCallPci_DsaAddr Dsa;
+-};
+-
+-struct HvCallPci_LoadReturn {
+- u64 rc;
+- u64 value;
+-};
+-
+-enum HvCallPci_DeviceType {
+- HvCallPci_NodeDevice = 1,
+- HvCallPci_SpDevice = 2,
+- HvCallPci_IopDevice = 3,
+- HvCallPci_BridgeDevice = 4,
+- HvCallPci_MultiFunctionDevice = 5,
+- HvCallPci_IoaDevice = 6
+-};
+-
+-
+-struct HvCallPci_DeviceInfo {
+- u32 deviceType; /* See DeviceType enum for values */
+-};
+-
+-struct HvCallPci_BusUnitInfo {
+- u32 sizeReturned; /* length of data returned */
+- u32 deviceType; /* see DeviceType enum for values */
+-};
+-
+-struct HvCallPci_BridgeInfo {
+- struct HvCallPci_BusUnitInfo busUnitInfo; /* Generic bus unit info */
+- u8 subBusNumber; /* Bus number of secondary bus */
+- u8 maxAgents; /* Max idsels on secondary bus */
+- u8 maxSubBusNumber; /* Max Sub Bus */
+- u8 logicalSlotNumber; /* Logical Slot Number for IOA */
+-};
+-
+-
+-/*
+- * Maximum BusUnitInfo buffer size. Provided for clients so
+- * they can allocate a buffer big enough for any type of bus
+- * unit. Increase as needed.
+- */
+-enum {HvCallPci_MaxBusUnitInfoSize = 128};
+-
+-struct HvCallPci_BarParms {
+- u64 vaddr;
+- u64 raddr;
+- u64 size;
+- u64 protectStart;
+- u64 protectEnd;
+- u64 relocationOffset;
+- u64 pciAddress;
+- u64 reserved[3];
+-};
+-
+-enum HvCallPci_VpdType {
+- HvCallPci_BusVpd = 1,
+- HvCallPci_BusAdapterVpd = 2
+-};
+-
+-#define HvCallPciConfigLoad8 HvCallPci + 0
+-#define HvCallPciConfigLoad16 HvCallPci + 1
+-#define HvCallPciConfigLoad32 HvCallPci + 2
+-#define HvCallPciConfigStore8 HvCallPci + 3
+-#define HvCallPciConfigStore16 HvCallPci + 4
+-#define HvCallPciConfigStore32 HvCallPci + 5
+-#define HvCallPciEoi HvCallPci + 16
+-#define HvCallPciGetBarParms HvCallPci + 18
+-#define HvCallPciMaskFisr HvCallPci + 20
+-#define HvCallPciUnmaskFisr HvCallPci + 21
+-#define HvCallPciSetSlotReset HvCallPci + 25
+-#define HvCallPciGetDeviceInfo HvCallPci + 27
+-#define HvCallPciGetCardVpd HvCallPci + 28
+-#define HvCallPciBarLoad8 HvCallPci + 40
+-#define HvCallPciBarLoad16 HvCallPci + 41
+-#define HvCallPciBarLoad32 HvCallPci + 42
+-#define HvCallPciBarLoad64 HvCallPci + 43
+-#define HvCallPciBarStore8 HvCallPci + 44
+-#define HvCallPciBarStore16 HvCallPci + 45
+-#define HvCallPciBarStore32 HvCallPci + 46
+-#define HvCallPciBarStore64 HvCallPci + 47
+-#define HvCallPciMaskInterrupts HvCallPci + 48
+-#define HvCallPciUnmaskInterrupts HvCallPci + 49
+-#define HvCallPciGetBusUnitInfo HvCallPci + 50
+-
+-static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
+- u8 deviceId, u32 offset, u8 *value)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumber;
+- dsa.subBusNumber = subBusNumber;
+- dsa.deviceId = deviceId;
+-
+- HvCall3Ret16(HvCallPciConfigLoad8, &retVal, *(u64 *)&dsa, offset, 0);
+-
+- *value = retVal.value;
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
+- u8 deviceId, u32 offset, u16 *value)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumber;
+- dsa.subBusNumber = subBusNumber;
+- dsa.deviceId = deviceId;
+-
+- HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0);
+-
+- *value = retVal.value;
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
+- u8 deviceId, u32 offset, u32 *value)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumber;
+- dsa.subBusNumber = subBusNumber;
+- dsa.deviceId = deviceId;
+-
+- HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
+-
+- *value = retVal.value;
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
+- u8 deviceId, u32 offset, u8 value)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumber;
+- dsa.subBusNumber = subBusNumber;
+- dsa.deviceId = deviceId;
+-
+- return HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
+-}
+-
+-static inline u64 HvCallPci_configStore16(u16 busNumber, u8 subBusNumber,
+- u8 deviceId, u32 offset, u16 value)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumber;
+- dsa.subBusNumber = subBusNumber;
+- dsa.deviceId = deviceId;
+-
+- return HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0);
+-}
+-
+-static inline u64 HvCallPci_configStore32(u16 busNumber, u8 subBusNumber,
+- u8 deviceId, u32 offset, u32 value)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumber;
+- dsa.subBusNumber = subBusNumber;
+- dsa.deviceId = deviceId;
+-
+- return HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0);
+-}
+-
+-static inline u64 HvCallPci_barLoad8(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u8 *valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- HvCall3Ret16(HvCallPciBarLoad8, &retVal, *(u64 *)&dsa, offsetParm, 0);
+-
+- *valueParm = retVal.value;
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_barLoad16(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u16 *valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- HvCall3Ret16(HvCallPciBarLoad16, &retVal, *(u64 *)&dsa, offsetParm, 0);
+-
+- *valueParm = retVal.value;
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_barLoad32(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u32 *valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- HvCall3Ret16(HvCallPciBarLoad32, &retVal, *(u64 *)&dsa, offsetParm, 0);
+-
+- *valueParm = retVal.value;
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_barLoad64(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u64 *valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- HvCall3Ret16(HvCallPciBarLoad64, &retVal, *(u64 *)&dsa, offsetParm, 0);
+-
+- *valueParm = retVal.value;
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_barStore8(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u8 valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- return HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm,
+- valueParm, 0);
+-}
+-
+-static inline u64 HvCallPci_barStore16(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u16 valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- return HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm,
+- valueParm, 0);
+-}
+-
+-static inline u64 HvCallPci_barStore32(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u32 valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- return HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm,
+- valueParm, 0);
+-}
+-
+-static inline u64 HvCallPci_barStore64(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+- u64 valueParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- return HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm,
+- valueParm, 0);
+-}
+-
+-static inline u64 HvCallPci_eoi(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm)
+-{
+- struct HvCallPci_DsaAddr dsa;
+- struct HvCallPci_LoadReturn retVal;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+-
+- HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa);
+-
+- return retVal.rc;
+-}
+-
+-static inline u64 HvCallPci_getBarParms(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u8 barNumberParm, u64 parms, u32 sizeofParms)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+- dsa.barNumber = barNumberParm;
+-
+- return HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
+-}
+-
+-static inline u64 HvCallPci_maskFisr(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u64 fisrMask)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+-
+- return HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
+-}
+-
+-static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u64 fisrMask)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+-
+- return HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
+-}
+-
+-static inline u64 HvCallPci_setSlotReset(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u64 onNotOff)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+-
+- return HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff);
+-}
+-
+-static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, u8 subBusParm,
+- u8 deviceNumberParm, u64 parms, u32 sizeofParms)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceNumberParm << 4;
+-
+- return HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
+-}
+-
+-static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u64 interruptMask)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+-
+- return HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
+-}
+-
+-static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u64 interruptMask)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+-
+- return HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
+-}
+-
+-static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, u8 subBusParm,
+- u8 deviceIdParm, u64 parms, u32 sizeofParms)
+-{
+- struct HvCallPci_DsaAddr dsa;
+-
+- *((u64*)&dsa) = 0;
+-
+- dsa.busNumber = busNumberParm;
+- dsa.subBusNumber = subBusParm;
+- dsa.deviceId = deviceIdParm;
+-
+- return HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms,
+- sizeofParms);
+-}
+-
+-static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm,
+- u16 sizeParm)
+-{
+- u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+- sizeParm, HvCallPci_BusVpd);
+- if (xRc == -1)
+- return -1;
+- else
+- return xRc & 0xFFFF;
+-}
+-
+-static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm,
+- u16 sizeParm)
+-{
+- u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+- sizeParm, HvCallPci_BusAdapterVpd);
+- if (xRc == -1)
+- return -1;
+- else
+- return xRc & 0xFFFF;
+-}
+-
+-#endif /* _HVCALLPCI_H */
+diff --git a/include/asm-ppc64/iSeries/HvCallSm.h b/include/asm-ppc64/iSeries/HvCallSm.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/HvCallSm.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/*
+- * HvCallSm.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _HVCALLSM_H
+-#define _HVCALLSM_H
+-
+-/*
+- * This file contains the "hypervisor call" interface which is used to
+- * drive the hypervisor from the OS.
+- */
+-
+-#include <asm/iSeries/HvCallSc.h>
+-#include <asm/iSeries/HvTypes.h>
+-
+-#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11
+-
+-static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex,
+- u64 indexIntoBitMap)
+-{
+- return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap);
+-}
+-
+-#endif /* _HVCALLSM_H */
+diff --git a/include/asm-ppc64/iSeries/HvReleaseData.h b/include/asm-ppc64/iSeries/HvReleaseData.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/HvReleaseData.h
++++ /dev/null
+@@ -1,64 +0,0 @@
+-/*
+- * HvReleaseData.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _HVRELEASEDATA_H
+-#define _HVRELEASEDATA_H
+-
+-/*
+- * This control block contains the critical information about the
+- * release so that it can be changed in the future (ie, the virtual
+- * address of the OS's NACA).
+- */
+-#include <asm/types.h>
+-#include <asm/naca.h>
+-
+-/*
+- * When we IPL a secondary partition, we will check if if the
+- * secondary xMinPlicVrmIndex > the primary xVrmIndex.
+- * If it is then this tells PLIC that this secondary is not
+- * supported running on this "old" of a level of PLIC.
+- *
+- * Likewise, we will compare the primary xMinSlicVrmIndex to
+- * the secondary xVrmIndex.
+- * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we
+- * know that this PLIC does not support running an OS "that old".
+- */
+-
+-#define HVREL_TAGSINACTIVE 0x8000
+-#define HVREL_32BIT 0x4000
+-#define HVREL_NOSHAREDPROCS 0x2000
+-#define HVREL_NOHMT 0x1000
+-
+-struct HvReleaseData {
+- u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */
+- u16 xSize; /* Size of this control block x04-x05 */
+- u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */
+- struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */
+- u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */
+- u32 xRsvd1; /* Reserved x14-x17 */
+- u16 xFlags;
+- u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */
+- u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */
+- u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */
+- char xVrmName[12]; /* Displayable name x20-x2B */
+- char xRsvd3[20]; /* Reserved x2C-x3F */
+-};
+-
+-extern struct HvReleaseData hvReleaseData;
+-
+-#endif /* _HVRELEASEDATA_H */
+diff --git a/include/asm-ppc64/iSeries/IoHriMainStore.h b/include/asm-ppc64/iSeries/IoHriMainStore.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/IoHriMainStore.h
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/*
+- * IoHriMainStore.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#ifndef _IOHRIMAINSTORE_H
+-#define _IOHRIMAINSTORE_H
+-
+-/* Main Store Vpd for Condor,iStar,sStar */
+-struct IoHriMainStoreSegment4 {
+- u8 msArea0Exists:1;
+- u8 msArea1Exists:1;
+- u8 msArea2Exists:1;
+- u8 msArea3Exists:1;
+- u8 reserved1:4;
+- u8 reserved2;
+-
+- u8 msArea0Functional:1;
+- u8 msArea1Functional:1;
+- u8 msArea2Functional:1;
+- u8 msArea3Functional:1;
+- u8 reserved3:4;
+- u8 reserved4;
+-
+- u32 totalMainStore;
+-
+- u64 msArea0Ptr;
+- u64 msArea1Ptr;
+- u64 msArea2Ptr;
+- u64 msArea3Ptr;
+-
+- u32 cardProductionLevel;
+-
+- u32 msAdrHole;
+-
+- u8 msArea0HasRiserVpd:1;
+- u8 msArea1HasRiserVpd:1;
+- u8 msArea2HasRiserVpd:1;
+- u8 msArea3HasRiserVpd:1;
+- u8 reserved5:4;
+- u8 reserved6;
+- u16 reserved7;
+-
+- u8 reserved8[28];
+-
+- u64 nonInterleavedBlocksStartAdr;
+- u64 nonInterleavedBlocksEndAdr;
+-};
+-
+-/* Main Store VPD for Power4 */
+-struct IoHriMainStoreChipInfo1 {
+- u32 chipMfgID __attribute((packed));
+- char chipECLevel[4] __attribute((packed));
+-};
+-
+-struct IoHriMainStoreVpdIdData {
+- char typeNumber[4];
+- char modelNumber[4];
+- char partNumber[12];
+- char serialNumber[12];
+-};
+-
+-struct IoHriMainStoreVpdFruData {
+- char fruLabel[8] __attribute((packed));
+- u8 numberOfSlots __attribute((packed));
+- u8 pluggingType __attribute((packed));
+- u16 slotMapIndex __attribute((packed));
+-};
+-
+-struct IoHriMainStoreAdrRangeBlock {
+- void *blockStart __attribute((packed));
+- void *blockEnd __attribute((packed));
+- u32 blockProcChipId __attribute((packed));
+-};
+-
+-#define MaxAreaAdrRangeBlocks 4
+-
+-struct IoHriMainStoreArea4 {
+- u32 msVpdFormat __attribute((packed));
+- u8 containedVpdType __attribute((packed));
+- u8 reserved1 __attribute((packed));
+- u16 reserved2 __attribute((packed));
+-
+- u64 msExists __attribute((packed));
+- u64 msFunctional __attribute((packed));
+-
+- u32 memorySize __attribute((packed));
+- u32 procNodeId __attribute((packed));
+-
+- u32 numAdrRangeBlocks __attribute((packed));
+- struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed));
+-
+- struct IoHriMainStoreChipInfo1 chipInfo0 __attribute((packed));
+- struct IoHriMainStoreChipInfo1 chipInfo1 __attribute((packed));
+- struct IoHriMainStoreChipInfo1 chipInfo2 __attribute((packed));
+- struct IoHriMainStoreChipInfo1 chipInfo3 __attribute((packed));
+- struct IoHriMainStoreChipInfo1 chipInfo4 __attribute((packed));
+- struct IoHriMainStoreChipInfo1 chipInfo5 __attribute((packed));
+- struct IoHriMainStoreChipInfo1 chipInfo6 __attribute((packed));
+- struct IoHriMainStoreChipInfo1 chipInfo7 __attribute((packed));
+-
+- void *msRamAreaArray __attribute((packed));
+- u32 msRamAreaArrayNumEntries __attribute((packed));
+- u32 msRamAreaArrayEntrySize __attribute((packed));
+-
+- u32 numaDimmExists __attribute((packed));
+- u32 numaDimmFunctional __attribute((packed));
+- void *numaDimmArray __attribute((packed));
+- u32 numaDimmArrayNumEntries __attribute((packed));
+- u32 numaDimmArrayEntrySize __attribute((packed));
+-
+- struct IoHriMainStoreVpdIdData idData __attribute((packed));
+-
+- u64 powerData __attribute((packed));
+- u64 cardAssemblyPartNum __attribute((packed));
+- u64 chipSerialNum __attribute((packed));
+-
+- u64 reserved3 __attribute((packed));
+- char reserved4[16] __attribute((packed));
+-
+- struct IoHriMainStoreVpdFruData fruData __attribute((packed));
+-
+- u8 vpdPortNum __attribute((packed));
+- u8 reserved5 __attribute((packed));
+- u8 frameId __attribute((packed));
+- u8 rackUnit __attribute((packed));
+- char asciiKeywordVpd[256] __attribute((packed));
+- u32 reserved6 __attribute((packed));
+-};
+-
+-
+-struct IoHriMainStoreSegment5 {
+- u16 reserved1;
+- u8 reserved2;
+- u8 msVpdFormat;
+-
+- u32 totalMainStore;
+- u64 maxConfiguredMsAdr;
+-
+- struct IoHriMainStoreArea4 *msAreaArray;
+- u32 msAreaArrayNumEntries;
+- u32 msAreaArrayEntrySize;
+-
+- u32 msAreaExists;
+- u32 msAreaFunctional;
+-
+- u64 reserved3;
+-};
+-
+-extern u64 xMsVpd[];
+-
+-#endif /* _IOHRIMAINSTORE_H */
+diff --git a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
++++ /dev/null
+@@ -1,86 +0,0 @@
+-/*
+- * IoHriProcessorVpd.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _IOHRIPROCESSORVPD_H
+-#define _IOHRIPROCESSORVPD_H
+-
+-#include <asm/types.h>
+-
+-/*
+- * This struct maps Processor Vpd that is DMAd to SLIC by CSP
+- */
+-struct IoHriProcessorVpd {
+- u8 xFormat; // VPD format indicator x00-x00
+- u8 xProcStatus:8; // Processor State x01-x01
+- u8 xSecondaryThreadCount; // Secondary thread cnt x02-x02
+- u8 xSrcType:1; // Src Type x03-x03
+- u8 xSrcSoft:1; // Src stay soft ...
+- u8 xSrcParable:1; // Src parable ...
+- u8 xRsvd1:5; // Reserved ...
+- u16 xHvPhysicalProcIndex; // Hypervisor physical proc index04-x05
+- u16 xRsvd2; // Reserved x06-x07
+- u32 xHwNodeId; // Hardware node id x08-x0B
+- u32 xHwProcId; // Hardware processor id x0C-x0F
+-
+- u32 xTypeNum; // Card Type/CCIN number x10-x13
+- u32 xModelNum; // Model/Feature number x14-x17
+- u64 xSerialNum; // Serial number x18-x1F
+- char xPartNum[12]; // Book Part or FPU number x20-x2B
+- char xMfgID[4]; // Manufacturing ID x2C-x2F
+-
+- u32 xProcFreq; // Processor Frequency x30-x33
+- u32 xTimeBaseFreq; // Time Base Frequency x34-x37
+-
+- u32 xChipEcLevel; // Chip EC Levels x38-x3B
+- u32 xProcIdReg; // PIR SPR value x3C-x3F
+- u32 xPVR; // PVR value x40-x43
+- u8 xRsvd3[12]; // Reserved x44-x4F
+-
+- u32 xInstCacheSize; // Instruction cache size in KB x50-x53
+- u32 xInstBlockSize; // Instruction cache block size x54-x57
+- u32 xDataCacheOperandSize; // Data cache operand size x58-x5B
+- u32 xInstCacheOperandSize; // Inst cache operand size x5C-x5F
+-
+- u32 xDataL1CacheSizeKB; // L1 data cache size in KB x60-x63
+- u32 xDataL1CacheLineSize; // L1 data cache block size x64-x67
+- u64 xRsvd4; // Reserved x68-x6F
+-
+- u32 xDataL2CacheSizeKB; // L2 data cache size in KB x70-x73
+- u32 xDataL2CacheLineSize; // L2 data cache block size x74-x77
+- u64 xRsvd5; // Reserved x78-x7F
+-
+- u32 xDataL3CacheSizeKB; // L3 data cache size in KB x80-x83
+- u32 xDataL3CacheLineSize; // L3 data cache block size x84-x87
+- u64 xRsvd6; // Reserved x88-x8F
+-
+- u64 xFruLabel; // Card Location Label x90-x97
+- u8 xSlotsOnCard; // Slots on card (0=no slots) x98-x98
+- u8 xPartLocFlag; // Location flag (0-pluggable 1-imbedded) x99-x99
+- u16 xSlotMapIndex; // Index in slot map table x9A-x9B
+- u8 xSmartCardPortNo; // Smart card port number x9C-x9C
+- u8 xRsvd7; // Reserved x9D-x9D
+- u16 xFrameIdAndRackUnit; // Frame ID and rack unit adr x9E-x9F
+-
+- u8 xRsvd8[24]; // Reserved xA0-xB7
+-
+- char xProcSrc[72]; // CSP format SRC xB8-xFF
+-};
+-
+-extern struct IoHriProcessorVpd xIoHriProcessorVpd[];
+-
+-#endif /* _IOHRIPROCESSORVPD_H */
+diff --git a/include/asm-ppc64/iSeries/ItIplParmsReal.h b/include/asm-ppc64/iSeries/ItIplParmsReal.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/ItIplParmsReal.h
++++ /dev/null
+@@ -1,71 +0,0 @@
+-/*
+- * ItIplParmsReal.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _ITIPLPARMSREAL_H
+-#define _ITIPLPARMSREAL_H
+-
+-/*
+- * This struct maps the IPL Parameters DMA'd from the SP.
+- *
+- * Warning:
+- * This data must map in exactly 64 bytes and match the architecture for
+- * the IPL parms
+- */
+-
+-#include <asm/types.h>
+-
+-struct ItIplParmsReal {
+- u8 xFormat; // Defines format of IplParms x00-x00
+- u8 xRsvd01:6; // Reserved x01-x01
+- u8 xAlternateSearch:1; // Alternate search indicator ...
+- u8 xUaSupplied:1; // UA Supplied on programmed IPL...
+- u8 xLsUaFormat; // Format byte for UA x02-x02
+- u8 xRsvd02; // Reserved x03-x03
+- u32 xLsUa; // LS UA x04-x07
+- u32 xUnusedLsLid; // First OS LID to load x08-x0B
+- u16 xLsBusNumber; // LS Bus Number x0C-x0D
+- u8 xLsCardAdr; // LS Card Address x0E-x0E
+- u8 xLsBoardAdr; // LS Board Address x0F-x0F
+- u32 xRsvd03; // Reserved x10-x13
+- u8 xSpcnPresent:1; // SPCN present x14-x14
+- u8 xCpmPresent:1; // CPM present ...
+- u8 xRsvd04:6; // Reserved ...
+- u8 xRsvd05:4; // Reserved x15-x15
+- u8 xKeyLock:4; // Keylock setting ...
+- u8 xRsvd06:6; // Reserved x16-x16
+- u8 xIplMode:2; // Ipl mode (A|B|C|D) ...
+- u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17
+- u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19
+- u16 xPowerOnResetIpl:1; // Indicate POR condition ...
+- u16 xMainStorePreserved:1; // Main Storage is preserved ...
+- u16 xRsvd07:13; // Reserved ...
+- u16 xIplSource:16; // Ipl source x1A-x1B
+- u8 xIplReason:8; // Reason for this IPL x1C-x1C
+- u8 xRsvd08; // Reserved x1D-x1D
+- u16 xRsvd09; // Reserved x1E-x1F
+- u16 xSysBoxType; // System Box Type x20-x21
+- u16 xSysProcType; // System Processor Type x22-x23
+- u32 xRsvd10; // Reserved x24-x27
+- u64 xRsvd11; // Reserved x28-x2F
+- u64 xRsvd12; // Reserved x30-x37
+- u64 xRsvd13; // Reserved x38-x3F
+-};
+-
+-extern struct ItIplParmsReal xItIplParmsReal;
+-
+-#endif /* _ITIPLPARMSREAL_H */
+diff --git a/include/asm-ppc64/iSeries/ItSpCommArea.h b/include/asm-ppc64/iSeries/ItSpCommArea.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/ItSpCommArea.h
++++ /dev/null
+@@ -1,37 +0,0 @@
+-/*
+- * ItSpCommArea.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#ifndef _ITSPCOMMAREA_H
+-#define _ITSPCOMMAREA_H
+-
+-
+-struct SpCommArea {
+- u32 xDesc; // Descriptor (only in new formats) 000-003
+- u8 xFormat; // Format (only in new formats) 004-004
+- u8 xRsvd1[11]; // Reserved 005-00F
+- u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017
+- u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F
+- u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027
+- u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F
+- u8 xRsvd2[80]; // Reserved 030-07F
+-};
+-
+-extern struct SpCommArea xSpCommArea;
+-
+-#endif /* _ITSPCOMMAREA_H */
+diff --git a/include/asm-ppc64/iSeries/ItVpdAreas.h b/include/asm-ppc64/iSeries/ItVpdAreas.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/ItVpdAreas.h
++++ /dev/null
+@@ -1,89 +0,0 @@
+-/*
+- * ItVpdAreas.h
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _ITVPDAREAS_H
+-#define _ITVPDAREAS_H
+-
+-/*
+- * This file defines the address and length of all of the VPD area passed to
+- * the OS from PLIC (most of which start from the SP).
+- */
+-
+-#include <asm/types.h>
+-
+-/* VPD Entry index is carved in stone - cannot be changed (easily). */
+-#define ItVpdCecVpd 0
+-#define ItVpdDynamicSpace 1
+-#define ItVpdExtVpd 2
+-#define ItVpdExtVpdOnPanel 3
+-#define ItVpdFirstPaca 4
+-#define ItVpdIoVpd 5
+-#define ItVpdIplParms 6
+-#define ItVpdMsVpd 7
+-#define ItVpdPanelVpd 8
+-#define ItVpdLpNaca 9
+-#define ItVpdBackplaneAndMaybeClockCardVpd 10
+-#define ItVpdRecoveryLogBuffer 11
+-#define ItVpdSpCommArea 12
+-#define ItVpdSpLogBuffer 13
+-#define ItVpdSpLogBufferSave 14
+-#define ItVpdSpCardVpd 15
+-#define ItVpdFirstProcVpd 16
+-#define ItVpdApModelVpd 17
+-#define ItVpdClockCardVpd 18
+-#define ItVpdBusExtCardVpd 19
+-#define ItVpdProcCapacityVpd 20
+-#define ItVpdInteractiveCapacityVpd 21
+-#define ItVpdFirstSlotLabel 22
+-#define ItVpdFirstLpQueue 23
+-#define ItVpdFirstL3CacheVpd 24
+-#define ItVpdFirstProcFruVpd 25
+-
+-#define ItVpdMaxEntries 26
+-
+-#define ItDmaMaxEntries 10
+-
+-#define ItVpdAreasMaxSlotLabels 192
+-
+-
+-struct ItVpdAreas {
+- u32 xSlicDesc; // Descriptor 000-003
+- u16 xSlicSize; // Size of this control block 004-005
+- u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface006-007
+- u16 xRsvd1:15; // Reserved bits ...
+- u16 xSlicVpdEntries; // Number of VPD entries 008-009
+- u16 xSlicDmaEntries; // Number of DMA entries 00A-00B
+- u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D
+- u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F
+- u16 xSlicDmaToksOffset; // Offset into this of array 010-011
+- u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013
+- u16 xSlicDmaLensOffset; // Offset into this of array 014-015
+- u16 xSlicVpdLensOffset; // Offset into this of array 016-017
+- u16 xSlicMaxSlotLabels; // Maximum number of slot labels018-019
+- u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B
+- u8 xRsvd2[4]; // Reserved 01C-01F
+- u64 xRsvd3[12]; // Reserved 020-07F
+- u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7
+- u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF
+- u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F
+- void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
+-};
+-
+-extern struct ItVpdAreas itVpdAreas;
+-
+-#endif /* _ITVPDAREAS_H */
+diff --git a/include/asm-ppc64/iSeries/iSeries_irq.h b/include/asm-ppc64/iSeries/iSeries_irq.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/iSeries_irq.h
++++ /dev/null
+@@ -1,8 +0,0 @@
+-#ifndef __ISERIES_IRQ_H__
+-#define __ISERIES_IRQ_H__
+-
+-extern void iSeries_init_IRQ(void);
+-extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+-extern void iSeries_activate_IRQs(void);
+-
+-#endif /* __ISERIES_IRQ_H__ */
+diff --git a/include/asm-ppc64/iSeries/iSeries_pci.h b/include/asm-ppc64/iSeries/iSeries_pci.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iSeries/iSeries_pci.h
++++ /dev/null
+@@ -1,88 +0,0 @@
+-#ifndef _ISERIES_64_PCI_H
+-#define _ISERIES_64_PCI_H
+-
+-/*
+- * File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001.
+- *
+- * Define some useful macros for the iSeries pci routines.
+- * Copyright (C) 2001 Allan H Trautman, IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the:
+- * Free Software Foundation, Inc.,
+- * 59 Temple Place, Suite 330,
+- * Boston, MA 02111-1307 USA
+- *
+- * Change Activity:
+- * Created Feb 20, 2001
+- * Added device reset, March 22, 2001
+- * Ported to ppc64, May 25, 2001
+- * End Change Activity
+- */
+-
+-#include <asm/iSeries/HvCallPci.h>
+-#include <asm/abs_addr.h>
+-
+-struct pci_dev; /* For Forward Reference */
+-struct iSeries_Device_Node;
+-
+-/*
+- * Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure
+- */
+-
+-#define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.Dsa.busNumber
+-#define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.Dsa.subBusNumber
+-#define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.Dsa.deviceId
+-#define ISERIES_DSA(DevPtr) DevPtr->DsaAddr.DsaAddr
+-#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node *)PciDev->sysdata)
+-
+-#define EADsMaxAgents 7
+-
+-/*
+- * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
+- * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
+- */
+-
+-#define ISERIES_PCI_AGENTID(idsel, func) \
+- (((idsel & 0x0F) << 4) | (func & 0x07))
+-#define ISERIES_ENCODE_DEVICE(agentid) \
+- ((0x10) | ((agentid & 0x20) >> 2) | (agentid & 0x07))
+-
+-#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
+-#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
+-
+-/*
+- * Converts Virtual Address to Real Address for Hypervisor calls
+- */
+-#define ISERIES_HV_ADDR(virtaddr) \
+- (0x8000000000000000 | virt_to_abs(virtaddr))
+-
+-/*
+- * iSeries Device Information
+- */
+-struct iSeries_Device_Node {
+- struct list_head Device_List;
+- struct pci_dev *PciDev;
+- union HvDsaMap DsaAddr; /* Direct Select Address */
+- /* busNumber, subBusNumber, */
+- /* deviceId, barNumber */
+- int DevFn; /* Linux devfn */
+- int Irq; /* Assigned IRQ */
+- int Flags; /* Possible flags(disable/bist)*/
+- u8 LogicalSlot; /* Hv Slot Index for Tces */
+- struct iommu_table *iommu_table;/* Device TCE Table */
+-};
+-
+-extern void iSeries_Device_Information(struct pci_dev*, int);
+-
+-#endif /* _ISERIES_64_PCI_H */
+diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
+--- a/include/asm-ppc64/io.h
++++ b/include/asm-ppc64/io.h
+@@ -15,7 +15,7 @@
+ #ifdef CONFIG_PPC_ISERIES
+ #include <asm/iSeries/iSeries_io.h>
+ #endif
+-#include <asm/memory.h>
++#include <asm/synch.h>
+ #include <asm/delay.h>
+
+ #include <asm-generic/iomap.h>
+diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
+deleted file mode 100644
+--- a/include/asm-ppc64/iommu.h
++++ /dev/null
+@@ -1,146 +0,0 @@
+-/*
+- * iommu.h
+- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+- * Rewrite, cleanup:
+- * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#ifndef _ASM_IOMMU_H
+-#define _ASM_IOMMU_H
+-
+-#include <asm/types.h>
+-#include <linux/spinlock.h>
+-#include <linux/device.h>
+-#include <linux/dma-mapping.h>
+-
+-/*
+- * IOMAP_MAX_ORDER defines the largest contiguous block
+- * of dma (tce) space we can get. IOMAP_MAX_ORDER = 13
+- * allows up to 2**12 pages (4096 * 4096) = 16 MB
+- */
+-#define IOMAP_MAX_ORDER 13
+-
+-/*
+- * Tces come in two formats, one for the virtual bus and a different
+- * format for PCI
+- */
+-#define TCE_VB 0
+-#define TCE_PCI 1
+-
+-/* tce_entry
+- * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's
+- * abstracted so layout is irrelevant.
+- */
+-union tce_entry {
+- unsigned long te_word;
+- struct {
+- unsigned int tb_cacheBits :6; /* Cache hash bits - not used */
+- unsigned int tb_rsvd :6;
+- unsigned long tb_rpn :40; /* Real page number */
+- unsigned int tb_valid :1; /* Tce is valid (vb only) */
+- unsigned int tb_allio :1; /* Tce is valid for all lps (vb only) */
+- unsigned int tb_lpindex :8; /* LpIndex for user of TCE (vb only) */
+- unsigned int tb_pciwr :1; /* Write allowed (pci only) */
+- unsigned int tb_rdwr :1; /* Read allowed (pci), Write allowed (vb) */
+- } te_bits;
+-#define te_cacheBits te_bits.tb_cacheBits
+-#define te_rpn te_bits.tb_rpn
+-#define te_valid te_bits.tb_valid
+-#define te_allio te_bits.tb_allio
+-#define te_lpindex te_bits.tb_lpindex
+-#define te_pciwr te_bits.tb_pciwr
+-#define te_rdwr te_bits.tb_rdwr
+-};
+-
+-
+-struct iommu_table {
+- unsigned long it_busno; /* Bus number this table belongs to */
+- unsigned long it_size; /* Size of iommu table in entries */
+- unsigned long it_offset; /* Offset into global table */
+- unsigned long it_base; /* mapped address of tce table */
+- unsigned long it_index; /* which iommu table this is */
+- unsigned long it_type; /* type: PCI or Virtual Bus */
+- unsigned long it_blocksize; /* Entries in each block (cacheline) */
+- unsigned long it_hint; /* Hint for next alloc */
+- unsigned long it_largehint; /* Hint for large allocs */
+- unsigned long it_halfpoint; /* Breaking point for small/large allocs */
+- spinlock_t it_lock; /* Protects it_map */
+- unsigned long *it_map; /* A simple allocation bitmap for now */
+-};
+-
+-struct scatterlist;
+-
+-#ifdef CONFIG_PPC_MULTIPLATFORM
+-
+-/* Walks all buses and creates iommu tables */
+-extern void iommu_setup_pSeries(void);
+-extern void iommu_setup_u3(void);
+-
+-/* Frees table for an individual device node */
+-extern void iommu_free_table(struct device_node *dn);
+-
+-#endif /* CONFIG_PPC_MULTIPLATFORM */
+-
+-#ifdef CONFIG_PPC_PSERIES
+-
+-/* Creates table for an individual device node */
+-extern void iommu_devnode_init_pSeries(struct device_node *dn);
+-
+-#endif /* CONFIG_PPC_PSERIES */
+-
+-#ifdef CONFIG_PPC_ISERIES
+-
+-struct iSeries_Device_Node;
+-/* Creates table for an individual device node */
+-extern void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn);
+-
+-#endif /* CONFIG_PPC_ISERIES */
+-
+-/* Initializes an iommu_table based in values set in the passed-in
+- * structure
+- */
+-extern struct iommu_table *iommu_init_table(struct iommu_table * tbl);
+-
+-extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
+- struct scatterlist *sglist, int nelems,
+- enum dma_data_direction direction);
+-extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+- int nelems, enum dma_data_direction direction);
+-
+-extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+- dma_addr_t *dma_handle, gfp_t flag);
+-extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
+- void *vaddr, dma_addr_t dma_handle);
+-extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
+- size_t size, enum dma_data_direction direction);
+-extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
+- size_t size, enum dma_data_direction direction);
+-
+-extern void iommu_init_early_pSeries(void);
+-extern void iommu_init_early_iSeries(void);
+-extern void iommu_init_early_u3(void);
+-
+-#ifdef CONFIG_PCI
+-extern void pci_iommu_init(void);
+-extern void pci_direct_iommu_init(void);
+-#else
+-static inline void pci_iommu_init(void) { }
+-#endif
+-
+-extern void alloc_u3_dart_table(void);
+-
+-#endif /* _ASM_IOMMU_H */
+diff --git a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h
+deleted file mode 100644
+--- a/include/asm-ppc64/irq.h
++++ /dev/null
+@@ -1,120 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_IRQ_H
+-#define _ASM_IRQ_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.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/threads.h>
+-
+-/*
+- * Maximum number of interrupt sources that we can handle.
+- */
+-#define NR_IRQS 512
+-
+-/* this number is used when no interrupt has been assigned */
+-#define NO_IRQ (-1)
+-
+-/*
+- * These constants are used for passing information about interrupt
+- * signal polarity and level/edge sensing to the low-level PIC chip
+- * drivers.
+- */
+-#define IRQ_SENSE_MASK 0x1
+-#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */
+-#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */
+-
+-#define IRQ_POLARITY_MASK 0x2
+-#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */
+-#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */
+-
+-/*
+- * IRQ line status macro IRQ_PER_CPU is used
+- */
+-#define ARCH_HAS_IRQ_PER_CPU
+-
+-#define get_irq_desc(irq) (&irq_desc[(irq)])
+-
+-/* Define a way to iterate across irqs. */
+-#define for_each_irq(i) \
+- for ((i) = 0; (i) < NR_IRQS; ++(i))
+-
+-/* Interrupt numbers are virtual in case they are sparsely
+- * distributed by the hardware.
+- */
+-extern unsigned int virt_irq_to_real_map[NR_IRQS];
+-
+-/* Create a mapping for a real_irq if it doesn't already exist.
+- * Return the virtual irq as a convenience.
+- */
+-int virt_irq_create_mapping(unsigned int real_irq);
+-void virt_irq_init(void);
+-
+-static inline unsigned int virt_irq_to_real(unsigned int virt_irq)
+-{
+- return virt_irq_to_real_map[virt_irq];
+-}
+-
+-extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq);
+-
+-/*
+- * Because many systems have two overlapping names spaces for
+- * interrupts (ISA and XICS for example), and the ISA interrupts
+- * have historically not been easy to renumber, we allow ISA
+- * interrupts to take values 0 - 15, and shift up the remaining
+- * interrupts by 0x10.
+- */
+-#define NUM_ISA_INTERRUPTS 0x10
+-extern int __irq_offset_value;
+-
+-static inline int irq_offset_up(int irq)
+-{
+- return(irq + __irq_offset_value);
+-}
+-
+-static inline int irq_offset_down(int irq)
+-{
+- return(irq - __irq_offset_value);
+-}
+-
+-static inline int irq_offset_value(void)
+-{
+- return __irq_offset_value;
+-}
+-
+-static __inline__ int irq_canonicalize(int irq)
+-{
+- return irq;
+-}
+-
+-extern int distribute_irqs;
+-
+-struct irqaction;
+-struct pt_regs;
+-
+-#ifdef CONFIG_IRQSTACKS
+-/*
+- * Per-cpu stacks for handling hard and soft interrupts.
+- */
+-extern struct thread_info *hardirq_ctx[NR_CPUS];
+-extern struct thread_info *softirq_ctx[NR_CPUS];
+-
+-extern void irq_ctx_init(void);
+-extern void call_do_softirq(struct thread_info *tp);
+-extern int call_handle_IRQ_event(int irq, struct pt_regs *regs,
+- struct irqaction *action, struct thread_info *tp);
+-
+-#define __ARCH_HAS_DO_SOFTIRQ
+-
+-#else
+-#define irq_ctx_init()
+-
+-#endif /* CONFIG_IRQSTACKS */
+-
+-#endif /* _ASM_IRQ_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc64/kdebug.h b/include/asm-ppc64/kdebug.h
+deleted file mode 100644
+--- a/include/asm-ppc64/kdebug.h
++++ /dev/null
+@@ -1,43 +0,0 @@
+-#ifndef _PPC64_KDEBUG_H
+-#define _PPC64_KDEBUG_H 1
+-
+-/* nearly identical to x86_64/i386 code */
+-
+-#include <linux/notifier.h>
+-
+-struct pt_regs;
+-
+-struct die_args {
+- struct pt_regs *regs;
+- const char *str;
+- long err;
+- int trapnr;
+- int signr;
+-};
+-
+-/*
+- Note - you should never unregister because that can race with NMIs.
+- If you really want to do it first unregister - then synchronize_sched -
+- then free.
+- */
+-int register_die_notifier(struct notifier_block *nb);
+-extern struct notifier_block *ppc64_die_chain;
+-
+-/* Grossly misnamed. */
+-enum die_val {
+- DIE_OOPS = 1,
+- DIE_IABR_MATCH,
+- DIE_DABR_MATCH,
+- DIE_BPT,
+- DIE_SSTEP,
+- DIE_GPF,
+- DIE_PAGE_FAULT,
+-};
+-
+-static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
+-{
+- struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
+- return notifier_call_chain(&ppc64_die_chain, val, &args);
+-}
+-
+-#endif
+diff --git a/include/asm-ppc64/keylargo.h b/include/asm-ppc64/keylargo.h
+deleted file mode 100644
+--- a/include/asm-ppc64/keylargo.h
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#include <asm-ppc/keylargo.h>
+-
+diff --git a/include/asm-ppc64/kmap_types.h b/include/asm-ppc64/kmap_types.h
+deleted file mode 100644
+--- a/include/asm-ppc64/kmap_types.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _ASM_KMAP_TYPES_H
+-#define _ASM_KMAP_TYPES_H
+-
+-enum km_type {
+- KM_BOUNCE_READ,
+- KM_SKB_SUNRPC_DATA,
+- KM_SKB_DATA_SOFTIRQ,
+- KM_USER0,
+- KM_USER1,
+- KM_BIO_SRC_IRQ,
+- KM_BIO_DST_IRQ,
+- KM_PTE0,
+- KM_PTE1,
+- KM_IRQ0,
+- KM_IRQ1,
+- KM_SOFTIRQ0,
+- KM_SOFTIRQ1,
+- KM_TYPE_NR
+-};
+-
+-#endif
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc64/kprobes.h b/include/asm-ppc64/kprobes.h
+deleted file mode 100644
+--- a/include/asm-ppc64/kprobes.h
++++ /dev/null
+@@ -1,67 +0,0 @@
+-#ifndef _ASM_KPROBES_H
+-#define _ASM_KPROBES_H
+-/*
+- * Kernel Probes (KProbes)
+- * include/asm-ppc64/kprobes.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.
+- *
+- * 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, 2002, 2004
+- *
+- * 2002-Oct Created by Vamsi Krishna S <vamsi_krishna at in.ibm.com> Kernel
+- * Probes initial implementation ( includes suggestions from
+- * Rusty Russell).
+- * 2004-Nov Modified for PPC64 by Ananth N Mavinakayanahalli
+- * <ananth at in.ibm.com>
+- */
+-#include <linux/types.h>
+-#include <linux/ptrace.h>
+-
+-struct pt_regs;
+-
+-typedef unsigned int kprobe_opcode_t;
+-#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
+-#define MAX_INSN_SIZE 1
+-
+-#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
+-#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088)
+-#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000)
+-#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
+-
+-#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry)
+-
+-#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
+- IS_TWI(instr) || IS_TDI(instr))
+-
+-#define ARCH_SUPPORTS_KRETPROBES
+-void kretprobe_trampoline(void);
+-
+-/* Architecture specific copy of original instruction */
+-struct arch_specific_insn {
+- /* copy of original instruction */
+- kprobe_opcode_t *insn;
+-};
+-
+-#ifdef CONFIG_KPROBES
+-extern int kprobe_exceptions_notify(struct notifier_block *self,
+- unsigned long val, void *data);
+-#else /* !CONFIG_KPROBES */
+-static inline int kprobe_exceptions_notify(struct notifier_block *self,
+- unsigned long val, void *data)
+-{
+- return 0;
+-}
+-#endif
+-#endif /* _ASM_KPROBES_H */
+diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
+deleted file mode 100644
+--- a/include/asm-ppc64/lmb.h
++++ /dev/null
+@@ -1,81 +0,0 @@
+-#ifndef _PPC64_LMB_H
+-#define _PPC64_LMB_H
+-
+-/*
+- * Definitions for talking to the Open Firmware PROM on
+- * Power Macintosh computers.
+- *
+- * Copyright (C) 2001 Peter Bergner, IBM Corp.
+- *
+- * 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 <asm/prom.h>
+-
+-#define MAX_LMB_REGIONS 128
+-
+-#define LMB_ALLOC_ANYWHERE 0
+-
+-struct lmb_property {
+- unsigned long base;
+- unsigned long size;
+-};
+-
+-struct lmb_region {
+- unsigned long cnt;
+- unsigned long size;
+- struct lmb_property region[MAX_LMB_REGIONS+1];
+-};
+-
+-struct lmb {
+- unsigned long debug;
+- unsigned long rmo_size;
+- struct lmb_region memory;
+- struct lmb_region reserved;
+-};
+-
+-extern struct lmb lmb;
+-
+-extern void __init lmb_init(void);
+-extern void __init lmb_analyze(void);
+-extern long __init lmb_add(unsigned long, unsigned long);
+-extern long __init lmb_reserve(unsigned long, unsigned long);
+-extern unsigned long __init lmb_alloc(unsigned long, unsigned long);
+-extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long,
+- unsigned long);
+-extern unsigned long __init lmb_phys_mem_size(void);
+-extern unsigned long __init lmb_end_of_DRAM(void);
+-extern unsigned long __init lmb_abs_to_phys(unsigned long);
+-extern void __init lmb_enforce_memory_limit(void);
+-
+-extern void lmb_dump_all(void);
+-
+-extern unsigned long io_hole_start;
+-
+-static inline unsigned long
+-lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
+-{
+- return type->region[region_nr].size;
+-}
+-static inline unsigned long
+-lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
+-{
+- return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
+-}
+-static inline unsigned long
+-lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
+-{
+- return type->region[region_nr].base >> PAGE_SHIFT;
+-}
+-static inline unsigned long
+-lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
+-{
+- return lmb_start_pfn(type, region_nr) +
+- lmb_size_pages(type, region_nr);
+-}
+-
+-#endif /* _PPC64_LMB_H */
+diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
+deleted file mode 100644
+--- a/include/asm-ppc64/machdep.h
++++ /dev/null
+@@ -1,185 +0,0 @@
+-#ifdef __KERNEL__
+-#ifndef _PPC64_MACHDEP_H
+-#define _PPC64_MACHDEP_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.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/seq_file.h>
+-#include <linux/init.h>
+-#include <linux/dma-mapping.h>
+-
+-#include <asm/setup.h>
+-
+-struct pt_regs;
+-struct pci_bus;
+-struct device_node;
+-struct iommu_table;
+-struct rtc_time;
+-struct file;
+-
+-#ifdef CONFIG_SMP
+-struct smp_ops_t {
+- void (*message_pass)(int target, int msg);
+- int (*probe)(void);
+- void (*kick_cpu)(int nr);
+- void (*setup_cpu)(int nr);
+- void (*take_timebase)(void);
+- void (*give_timebase)(void);
+- int (*cpu_enable)(unsigned int nr);
+- int (*cpu_disable)(void);
+- void (*cpu_die)(unsigned int nr);
+- int (*cpu_bootable)(unsigned int nr);
+-};
+-#endif
+-
+-struct machdep_calls {
+- void (*hpte_invalidate)(unsigned long slot,
+- unsigned long va,
+- int large,
+- int local);
+- long (*hpte_updatepp)(unsigned long slot,
+- unsigned long newpp,
+- unsigned long va,
+- int large,
+- int local);
+- void (*hpte_updateboltedpp)(unsigned long newpp,
+- unsigned long ea);
+- long (*hpte_insert)(unsigned long hpte_group,
+- unsigned long va,
+- unsigned long prpn,
+- unsigned long vflags,
+- unsigned long rflags);
+- long (*hpte_remove)(unsigned long hpte_group);
+- void (*flush_hash_range)(unsigned long context,
+- unsigned long number,
+- int local);
+- /* special for kexec, to be called in real mode, linar mapping is
+- * destroyed as well */
+- void (*hpte_clear_all)(void);
+-
+- void (*tce_build)(struct iommu_table * tbl,
+- long index,
+- long npages,
+- unsigned long uaddr,
+- enum dma_data_direction direction);
+- void (*tce_free)(struct iommu_table *tbl,
+- long index,
+- long npages);
+- void (*tce_flush)(struct iommu_table *tbl);
+- void (*iommu_dev_setup)(struct pci_dev *dev);
+- void (*iommu_bus_setup)(struct pci_bus *bus);
+- void (*irq_bus_setup)(struct pci_bus *bus);
+-
+- int (*probe)(int platform);
+- void (*setup_arch)(void);
+- void (*init_early)(void);
+- /* Optional, may be NULL. */
+- void (*get_cpuinfo)(struct seq_file *m);
+-
+- void (*init_IRQ)(void);
+- int (*get_irq)(struct pt_regs *);
+- void (*cpu_irq_down)(int secondary);
+-
+- /* PCI stuff */
+- void (*pcibios_fixup)(void);
+- int (*pci_probe_mode)(struct pci_bus *);
+-
+- void (*restart)(char *cmd);
+- void (*power_off)(void);
+- void (*halt)(void);
+- void (*panic)(char *str);
+- void (*cpu_die)(void);
+-
+- int (*set_rtc_time)(struct rtc_time *);
+- void (*get_rtc_time)(struct rtc_time *);
+- void (*get_boot_time)(struct rtc_time *);
+-
+- void (*calibrate_decr)(void);
+-
+- void (*progress)(char *, unsigned short);
+-
+- /* Interface for platform error logging */
+- void (*log_error)(char *buf, unsigned int err_type, int fatal);
+-
+- ssize_t (*nvram_write)(char *buf, size_t count, loff_t *index);
+- ssize_t (*nvram_read)(char *buf, size_t count, loff_t *index);
+- ssize_t (*nvram_size)(void);
+- int (*nvram_sync)(void);
+-
+- /* Exception handlers */
+- void (*system_reset_exception)(struct pt_regs *regs);
+- int (*machine_check_exception)(struct pt_regs *regs);
+-
+- /* Motherboard/chipset features. This is a kind of general purpose
+- * hook used to control some machine specific features (like reset
+- * lines, chip power control, etc...).
+- */
+- long (*feature_call)(unsigned int feature, ...);
+-
+- /* Check availability of legacy devices like i8042 */
+- int (*check_legacy_ioport)(unsigned int baseport);
+-
+- /* Get legacy PCI/IDE interrupt mapping */
+- int (*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel);
+-
+- /* Get access protection for /dev/mem */
+- pgprot_t (*phys_mem_access_prot)(struct file *file,
+- unsigned long offset,
+- unsigned long size,
+- pgprot_t vma_prot);
+-
+- /* Idle loop for this platform, leave empty for default idle loop */
+- int (*idle_loop)(void);
+-
+- /* Function to enable pmcs for this platform, called once per cpu. */
+- void (*enable_pmcs)(void);
+-};
+-
+-extern int default_idle(void);
+-extern int native_idle(void);
+-
+-extern struct machdep_calls ppc_md;
+-extern char cmd_line[COMMAND_LINE_SIZE];
+-
+-#ifdef CONFIG_PPC_PMAC
+-/*
+- * Power macintoshes have either a CUDA, PMU or SMU controlling
+- * system reset, power, NVRAM, RTC.
+- */
+-typedef enum sys_ctrler_kind {
+- SYS_CTRLER_UNKNOWN = 0,
+- SYS_CTRLER_CUDA = 1,
+- SYS_CTRLER_PMU = 2,
+- SYS_CTRLER_SMU = 3,
+-} sys_ctrler_t;
+-extern sys_ctrler_t sys_ctrler;
+-
+-#endif /* CONFIG_PPC_PMAC */
+-
+-
+-
+-/* Functions to produce codes on the leds.
+- * The SRC code should be unique for the message category and should
+- * be limited to the lower 24 bits (the upper 8 are set by these funcs),
+- * and (for boot & dump) should be sorted numerically in the order
+- * the events occur.
+- */
+-/* Print a boot progress message. */
+-void ppc64_boot_msg(unsigned int src, const char *msg);
+-/* Print a termination message (print only -- does not stop the kernel) */
+-void ppc64_terminate_msg(unsigned int src, const char *msg);
+-
+-static inline void log_error(char *buf, unsigned int err_type, int fatal)
+-{
+- if (ppc_md.log_error)
+- ppc_md.log_error(buf, err_type, fatal);
+-}
+-
+-#endif /* _PPC64_MACHDEP_H */
+-#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc64/macio.h b/include/asm-ppc64/macio.h
+deleted file mode 100644
+--- a/include/asm-ppc64/macio.h
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#include <asm-ppc/macio.h>
+-
+diff --git a/include/asm-ppc64/memory.h b/include/asm-ppc64/memory.h
+deleted file mode 100644
+--- a/include/asm-ppc64/memory.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-#ifndef _ASM_PPC64_MEMORY_H_
+-#define _ASM_PPC64_MEMORY_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.
+- */
+-
+-#include <linux/config.h>
+-
+-/*
+- * Arguably the bitops and *xchg operations don't imply any memory barrier
+- * or SMP ordering, but in fact a lot of drivers expect them to imply
+- * both, since they do on x86 cpus.
+- */
+-#ifdef CONFIG_SMP
+-#define EIEIO_ON_SMP "eieio\n"
+-#define ISYNC_ON_SMP "\n\tisync"
+-#define SYNC_ON_SMP "lwsync\n\t"
+-#else
+-#define EIEIO_ON_SMP
+-#define ISYNC_ON_SMP
+-#define SYNC_ON_SMP
+-#endif
+-
+-static inline void eieio(void)
+-{
+- __asm__ __volatile__ ("eieio" : : : "memory");
+-}
+-
+-static inline void isync(void)
+-{
+- __asm__ __volatile__ ("isync" : : : "memory");
+-}
+-
+-#ifdef CONFIG_SMP
+-#define eieio_on_smp() eieio()
+-#define isync_on_smp() isync()
+-#else
+-#define eieio_on_smp() __asm__ __volatile__("": : :"memory")
+-#define isync_on_smp() __asm__ __volatile__("": : :"memory")
+-#endif
+-
+-/* Macros for adjusting thread priority (hardware multi-threading) */
+-#define HMT_very_low() asm volatile("or 31,31,31 # very low priority")
+-#define HMT_low() asm volatile("or 1,1,1 # low priority")
+-#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority")
+-#define HMT_medium() asm volatile("or 2,2,2 # medium priority")
+-#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority")
+-#define HMT_high() asm volatile("or 3,3,3 # high priority")
+-
+-#define HMT_VERY_LOW "\tor 31,31,31 # very low priority\n"
+-#define HMT_LOW "\tor 1,1,1 # low priority\n"
+-#define HMT_MEDIUM_LOW "\tor 6,6,6 # medium low priority\n"
+-#define HMT_MEDIUM "\tor 2,2,2 # medium priority\n"
+-#define HMT_MEDIUM_HIGH "\tor 5,5,5 # medium high priority\n"
+-#define HMT_HIGH "\tor 3,3,3 # high priority\n"
+-
+-#endif
+diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
+--- a/include/asm-ppc64/mmu.h
++++ b/include/asm-ppc64/mmu.h
+@@ -14,6 +14,7 @@
+ #define _PPC64_MMU_H_
+
+ #include <linux/config.h>
++#include <asm/ppc_asm.h> /* for ASM_CONST */
+ #include <asm/page.h>
+
+ /*
+@@ -29,7 +30,7 @@
+
+ /* Location of cpu0's segment table */
+ #define STAB0_PAGE 0x6
+-#define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT)
++#define STAB0_PHYS_ADDR (STAB0_PAGE<<12)
+
+ #ifndef __ASSEMBLY__
+ extern char initial_stab[];
+@@ -205,6 +206,10 @@ extern long native_hpte_insert(unsigned
+ unsigned long prpn,
+ unsigned long vflags, unsigned long rflags);
+
++extern long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
++ unsigned long va, unsigned long prpn,
++ unsigned long vflags, unsigned long rflags);
++
+ extern void stabs_alloc(void);
+
+ #endif /* __ASSEMBLY__ */
+diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
+--- a/include/asm-ppc64/mmzone.h
++++ b/include/asm-ppc64/mmzone.h
+@@ -67,9 +67,6 @@ static inline int pa_to_nid(unsigned lon
+ #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/of_device.h b/include/asm-ppc64/of_device.h
+deleted file mode 100644
+--- a/include/asm-ppc64/of_device.h
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#include <asm-ppc/of_device.h>
+-
+diff --git a/include/asm-ppc64/oprofile_impl.h b/include/asm-ppc64/oprofile_impl.h
+deleted file mode 100644
+--- a/include/asm-ppc64/oprofile_impl.h
++++ /dev/null
+@@ -1,111 +0,0 @@
+-/*
+- * Copyright (C) 2004 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * Based on alpha version.
+- *
+- * 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 OP_IMPL_H
+-#define OP_IMPL_H 1
+-
+-#define OP_MAX_COUNTER 8
+-
+-/* Per-counter configuration as set via oprofilefs. */
+-struct op_counter_config {
+- unsigned long valid;
+- unsigned long enabled;
+- unsigned long event;
+- unsigned long count;
+- unsigned long kernel;
+- /* We dont support per counter user/kernel selection */
+- unsigned long user;
+- unsigned long unit_mask;
+-};
+-
+-/* System-wide configuration as set via oprofilefs. */
+-struct op_system_config {
+- unsigned long mmcr0;
+- unsigned long mmcr1;
+- unsigned long mmcra;
+- unsigned long enable_kernel;
+- unsigned long enable_user;
+- unsigned long backtrace_spinlocks;
+-};
+-
+-/* Per-arch configuration */
+-struct op_ppc64_model {
+- void (*reg_setup) (struct op_counter_config *,
+- struct op_system_config *,
+- int num_counters);
+- void (*cpu_setup) (void *);
+- void (*start) (struct op_counter_config *);
+- void (*stop) (void);
+- void (*handle_interrupt) (struct pt_regs *,
+- struct op_counter_config *);
+- int num_counters;
+-};
+-
+-extern struct op_ppc64_model op_model_rs64;
+-extern struct op_ppc64_model op_model_power4;
+-
+-static inline unsigned int ctr_read(unsigned int i)
+-{
+- switch(i) {
+- case 0:
+- return mfspr(SPRN_PMC1);
+- case 1:
+- return mfspr(SPRN_PMC2);
+- case 2:
+- return mfspr(SPRN_PMC3);
+- case 3:
+- return mfspr(SPRN_PMC4);
+- case 4:
+- return mfspr(SPRN_PMC5);
+- case 5:
+- return mfspr(SPRN_PMC6);
+- case 6:
+- return mfspr(SPRN_PMC7);
+- case 7:
+- return mfspr(SPRN_PMC8);
+- default:
+- return 0;
+- }
+-}
+-
+-static inline void ctr_write(unsigned int i, unsigned int val)
+-{
+- switch(i) {
+- case 0:
+- mtspr(SPRN_PMC1, val);
+- break;
+- case 1:
+- mtspr(SPRN_PMC2, val);
+- break;
+- case 2:
+- mtspr(SPRN_PMC3, val);
+- break;
+- case 3:
+- mtspr(SPRN_PMC4, val);
+- break;
+- case 4:
+- mtspr(SPRN_PMC5, val);
+- break;
+- case 5:
+- mtspr(SPRN_PMC6, val);
+- break;
+- case 6:
+- mtspr(SPRN_PMC7, val);
+- break;
+- case 7:
+- mtspr(SPRN_PMC8, val);
+- break;
+- default:
+- break;
+- }
+-}
+-
+-#endif
+diff --git a/include/asm-ppc64/pSeries_reconfig.h b/include/asm-ppc64/pSeries_reconfig.h
+deleted file mode 100644
+--- a/include/asm-ppc64/pSeries_reconfig.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-#ifndef _PPC64_PSERIES_RECONFIG_H
+-#define _PPC64_PSERIES_RECONFIG_H
+-
+-#include <linux/notifier.h>
+-
+-/*
+- * Use this API if your code needs to know about OF device nodes being
+- * added or removed on pSeries systems.
+- */
+-
+-#define PSERIES_RECONFIG_ADD 0x0001
+-#define PSERIES_RECONFIG_REMOVE 0x0002
+-
+-#ifdef CONFIG_PPC_PSERIES
+-extern int pSeries_reconfig_notifier_register(struct notifier_block *);
+-extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
+-#else /* !CONFIG_PPC_PSERIES */
+-static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
+-{
+- return 0;
+-}
+-static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
+-#endif /* CONFIG_PPC_PSERIES */
+-
+-#endif /* _PPC64_PSERIES_RECONFIG_H */
+diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
+--- a/include/asm-ppc64/page.h
++++ b/include/asm-ppc64/page.h
+@@ -11,13 +11,7 @@
+ */
+
+ #include <linux/config.h>
+-
+-#ifdef __ASSEMBLY__
+- #define ASM_CONST(x) x
+-#else
+- #define __ASM_CONST(x) x##UL
+- #define ASM_CONST(x) __ASM_CONST(x)
+-#endif
++#include <asm/ppc_asm.h> /* for ASM_CONST */
+
+ /* PAGE_SHIFT determines the page size */
+ #define PAGE_SHIFT 12
+diff --git a/include/asm-ppc64/parport.h b/include/asm-ppc64/parport.h
+deleted file mode 100644
+--- a/include/asm-ppc64/parport.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/*
+- * parport.h: platform-specific PC-style parport initialisation
+- *
+- * Copyright (C) 1999, 2000 Tim Waugh <tim at cyberelk.demon.co.uk>
+- *
+- * This file should only be included by drivers/parport/parport_pc.c.
+- */
+-
+-#ifndef _ASM_PPC64_PARPORT_H
+-#define _ASM_PPC64_PARPORT_H
+-
+-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
+-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+-{
+- return parport_pc_find_isa_ports (autoirq, autodma);
+-}
+-
+-#endif /* !(_ASM_PPC_PARPORT_H) */
+diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
+--- a/include/asm-ppc64/pci-bridge.h
++++ b/include/asm-ppc64/pci-bridge.h
+@@ -2,7 +2,9 @@
+ #ifndef _ASM_PCI_BRIDGE_H
+ #define _ASM_PCI_BRIDGE_H
+
++#include <linux/config.h>
+ #include <linux/pci.h>
++#include <linux/list.h>
+
+ /*
+ * This program is free software; you can redistribute it and/or
+@@ -34,7 +36,7 @@ struct pci_controller {
+
+ struct pci_ops *ops;
+ volatile unsigned int __iomem *cfg_addr;
+- volatile unsigned char __iomem *cfg_data;
++ volatile void __iomem *cfg_data;
+
+ /* Currently, we limit ourselves to 1 IO range and 3 mem
+ * ranges since the common pci_bus structure can't handle more
+@@ -71,6 +73,12 @@ struct pci_dn {
+ struct iommu_table *iommu_table; /* for phb's or bridges */
+ struct pci_dev *pcidev; /* back-pointer to the pci device */
+ struct device_node *node; /* back-pointer to the device_node */
++#ifdef CONFIG_PPC_ISERIES
++ struct list_head Device_List;
++ int Irq; /* Assigned IRQ */
++ int Flags; /* Possible flags(disable/bist)*/
++ u8 LogicalSlot; /* Hv Slot Index for Tces */
++#endif
+ u32 config_space[16]; /* saved PCI config space */
+ };
+
+@@ -96,6 +104,16 @@ static inline struct device_node *pci_de
+ return fetch_dev_dn(dev);
+ }
+
++static inline int pci_device_from_OF_node(struct device_node *np,
++ u8 *bus, u8 *devfn)
++{
++ if (!PCI_DN(np))
++ return -ENODEV;
++ *bus = PCI_DN(np)->busno;
++ *devfn = PCI_DN(np)->devfn;
++ return 0;
++}
++
+ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+ {
+ if (bus->self)
+@@ -105,7 +123,7 @@ static inline struct device_node *pci_bu
+ }
+
+ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
+- struct device_node *dev);
++ struct device_node *dev, int primary);
+
+ extern int pcibios_remove_root_bus(struct pci_controller *phb);
+
+diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h
+--- a/include/asm-ppc64/pci.h
++++ b/include/asm-ppc64/pci.h
+@@ -168,7 +168,7 @@ extern void pcibios_add_platform_entries
+
+ struct file;
+ extern pgprot_t pci_phys_mem_access_prot(struct file *file,
+- unsigned long offset,
++ unsigned long pfn,
+ unsigned long size,
+ pgprot_t prot);
+
+diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
+--- a/include/asm-ppc64/pgtable.h
++++ b/include/asm-ppc64/pgtable.h
+@@ -471,17 +471,19 @@ static inline void __ptep_set_access_fla
+ #define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+
+ struct file;
+-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
++extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ unsigned long size, pgprot_t vma_prot);
+ #define __HAVE_PHYS_MEM_ACCESS_PROT
+
+ #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-ppc64/pmac_feature.h b/include/asm-ppc64/pmac_feature.h
+deleted file mode 100644
+--- a/include/asm-ppc64/pmac_feature.h
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#include <asm-ppc/pmac_feature.h>
+-
+diff --git a/include/asm-ppc64/pmac_low_i2c.h b/include/asm-ppc64/pmac_low_i2c.h
+deleted file mode 100644
+--- a/include/asm-ppc64/pmac_low_i2c.h
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#include <asm-ppc/pmac_low_i2c.h>
+-
+diff --git a/include/asm-ppc64/pmc.h b/include/asm-ppc64/pmc.h
+deleted file mode 100644
+--- a/include/asm-ppc64/pmc.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * pmc.h
+- * Copyright (C) 2004 David Gibson, IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _PPC64_PMC_H
+-#define _PPC64_PMC_H
+-
+-#include <asm/ptrace.h>
+-
+-typedef void (*perf_irq_t)(struct pt_regs *);
+-
+-int reserve_pmc_hardware(perf_irq_t new_perf_irq);
+-void release_pmc_hardware(void);
+-
+-void power4_enable_pmcs(void);
+-
+-#endif /* _PPC64_PMC_H */
+diff --git a/include/asm-ppc64/posix_types.h b/include/asm-ppc64/posix_types.h
+deleted file mode 100644
+--- a/include/asm-ppc64/posix_types.h
++++ /dev/null
+@@ -1,119 +0,0 @@
+-#ifndef _PPC64_POSIX_TYPES_H
+-#define _PPC64_POSIX_TYPES_H
+-
+-/*
+- * This file is generally used by user-level software, so you need to
+- * be a little careful about namespace pollution etc. Also, we cannot
+- * assume GCC is being used.
+- *
+- * 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.
+- */
+-
+-typedef unsigned long __kernel_ino_t;
+-typedef unsigned long __kernel_nlink_t;
+-typedef unsigned int __kernel_mode_t;
+-typedef long __kernel_off_t;
+-typedef long long __kernel_loff_t;
+-typedef int __kernel_pid_t;
+-typedef int __kernel_ipc_pid_t;
+-typedef unsigned int __kernel_uid_t;
+-typedef unsigned int __kernel_gid_t;
+-typedef unsigned long __kernel_size_t;
+-typedef long __kernel_ssize_t;
+-typedef long __kernel_ptrdiff_t;
+-typedef long __kernel_time_t;
+-typedef int __kernel_timer_t;
+-typedef int __kernel_clockid_t;
+-typedef long __kernel_suseconds_t;
+-typedef long __kernel_clock_t;
+-typedef int __kernel_daddr_t;
+-typedef char * __kernel_caddr_t;
+-typedef unsigned short __kernel_uid16_t;
+-typedef unsigned short __kernel_gid16_t;
+-typedef unsigned int __kernel_uid32_t;
+-typedef unsigned int __kernel_gid32_t;
+-
+-typedef unsigned int __kernel_old_uid_t;
+-typedef unsigned int __kernel_old_gid_t;
+-typedef unsigned long __kernel_old_dev_t;
+-
+-typedef struct {
+- int val[2];
+-} __kernel_fsid_t;
+-
+-#ifndef __GNUC__
+-
+-#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+-#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+-#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
+-#define __FD_ZERO(set) \
+- ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+-
+-#else /* __GNUC__ */
+-
+-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
+- || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+-/* With GNU C, use inline functions instead so args are evaluated only once: */
+-
+-#undef __FD_SET
+-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+-{
+- unsigned long _tmp = fd / __NFDBITS;
+- unsigned long _rem = fd % __NFDBITS;
+- fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+-}
+-
+-#undef __FD_CLR
+-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+-{
+- unsigned long _tmp = fd / __NFDBITS;
+- unsigned long _rem = fd % __NFDBITS;
+- fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+-}
+-
+-#undef __FD_ISSET
+-static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
+-{
+- unsigned long _tmp = fd / __NFDBITS;
+- unsigned long _rem = fd % __NFDBITS;
+- return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+-}
+-
+-/*
+- * This will unroll the loop for the normal constant case (8 ints,
+- * for a 256-bit fd_set)
+- */
+-#undef __FD_ZERO
+-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+-{
+- unsigned long *tmp = (unsigned long *)p->fds_bits;
+- int i;
+-
+- if (__builtin_constant_p(__FDSET_LONGS)) {
+- switch (__FDSET_LONGS) {
+- case 16:
+- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+-
+- case 8:
+- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+-
+- case 4:
+- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+- return;
+- }
+- }
+- i = __FDSET_LONGS;
+- while (i) {
+- i--;
+- *tmp = 0;
+- tmp++;
+- }
+-}
+-
+-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+-#endif /* __GNUC__ */
+-#endif /* _PPC64_POSIX_TYPES_H */
+diff --git a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
+--- a/include/asm-ppc64/ppc32.h
++++ b/include/asm-ppc64/ppc32.h
+@@ -70,18 +70,18 @@ typedef struct compat_siginfo {
+ #define __old_sigaction32 old_sigaction32
+
+ struct __old_sigaction32 {
+- unsigned sa_handler;
++ compat_uptr_t sa_handler;
+ compat_old_sigset_t sa_mask;
+ unsigned int sa_flags;
+- unsigned sa_restorer; /* not used by Linux/SPARC yet */
++ compat_uptr_t sa_restorer; /* not used by Linux/SPARC yet */
+ };
+
+
+
+ struct sigaction32 {
+- unsigned int sa_handler; /* Really a pointer, but need to deal with 32 bits */
++ compat_uptr_t sa_handler; /* Really a pointer, but need to deal with 32 bits */
+ unsigned int sa_flags;
+- unsigned int sa_restorer; /* Another 32 bit pointer */
++ compat_uptr_t sa_restorer; /* Another 32 bit pointer */
+ compat_sigset_t sa_mask; /* A 32 bit mask */
+ };
+
+@@ -94,9 +94,9 @@ typedef struct sigaltstack_32 {
+ struct sigcontext32 {
+ unsigned int _unused[4];
+ int signal;
+- unsigned int handler;
++ compat_uptr_t handler;
+ unsigned int oldmask;
+- u32 regs; /* 4 byte pointer to the pt_regs32 structure. */
++ compat_uptr_t regs; /* 4 byte pointer to the pt_regs32 structure. */
+ };
+
+ struct mcontext32 {
+@@ -111,7 +111,7 @@ struct ucontext32 {
+ unsigned int uc_link;
+ stack_32_t uc_stack;
+ int uc_pad[7];
+- u32 uc_regs; /* points to uc_mcontext field */
++ compat_uptr_t uc_regs; /* points to uc_mcontext field */
+ compat_sigset_t uc_sigmask; /* mask last for extensibility */
+ /* glibc has 1024-bit signal masks, ours are 64-bit */
+ int uc_maskext[30];
+diff --git a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h
+deleted file mode 100644
+--- a/include/asm-ppc64/ppc_asm.h
++++ /dev/null
+@@ -1,242 +0,0 @@
+-/*
+- * arch/ppc64/kernel/ppc_asm.h
+- *
+- * Definitions used by various bits of low-level assembly code on PowerPC.
+- *
+- * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
+- *
+- * 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 _PPC64_PPC_ASM_H
+-#define _PPC64_PPC_ASM_H
+-/*
+- * Macros for storing registers into and loading registers from
+- * exception frames.
+- */
+-#define SAVE_GPR(n, base) std n,GPR0+8*(n)(base)
+-#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+-#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+-#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+-#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+-#define REST_GPR(n, base) ld n,GPR0+8*(n)(base)
+-#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+-#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+-#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+-#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+-
+-#define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, base)
+-#define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, base)
+-
+-#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base)
+-#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
+-#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
+-#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
+-#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
+-#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
+-#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base)
+-#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
+-#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
+-#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
+-#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
+-#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
+-
+-#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base
+-#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
+-#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base)
+-#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base)
+-#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base)
+-#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base)
+-#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base
+-#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
+-#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base)
+-#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base)
+-#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
+-#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
+-
+-/* Macros to adjust thread priority for Iseries hardware multithreading */
+-#define HMT_LOW or 1,1,1
+-#define HMT_MEDIUM or 2,2,2
+-#define HMT_HIGH or 3,3,3
+-
+-/* Insert the high 32 bits of the MSR into what will be the new
+- MSR (via SRR1 and rfid) This preserves the MSR.SF and MSR.ISF
+- bits. */
+-
+-#define FIX_SRR1(ra, rb) \
+- mr rb,ra; \
+- mfmsr ra; \
+- rldimi ra,rb,0,32
+-
+-#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */
+-
+-/*
+- * LOADADDR( rn, name )
+- * loads the address of 'name' into 'rn'
+- *
+- * LOADBASE( rn, name )
+- * loads the address (less the low 16 bits) of 'name' into 'rn'
+- * suitable for base+disp addressing
+- */
+-#define LOADADDR(rn,name) \
+- lis rn,name##@highest; \
+- ori rn,rn,name##@higher; \
+- rldicr rn,rn,32,31; \
+- oris rn,rn,name##@h; \
+- ori rn,rn,name##@l
+-
+-#define LOADBASE(rn,name) \
+- lis rn,name at highest; \
+- ori rn,rn,name at higher; \
+- rldicr rn,rn,32,31; \
+- oris rn,rn,name at ha
+-
+-
+-#define SET_REG_TO_CONST(reg, value) \
+- lis reg,(((value)>>48)&0xFFFF); \
+- ori reg,reg,(((value)>>32)&0xFFFF); \
+- rldicr reg,reg,32,31; \
+- oris reg,reg,(((value)>>16)&0xFFFF); \
+- ori reg,reg,((value)&0xFFFF);
+-
+-#define SET_REG_TO_LABEL(reg, label) \
+- lis reg,(label)@highest; \
+- ori reg,reg,(label)@higher; \
+- rldicr reg,reg,32,31; \
+- oris reg,reg,(label)@h; \
+- ori reg,reg,(label)@l;
+-
+-
+-/* PPPBBB - DRENG If KERNELBASE is always 0xC0...,
+- * Then we can easily do this with one asm insn. -Peter
+- */
+-#define tophys(rd,rs) \
+- lis rd,((KERNELBASE>>48)&0xFFFF); \
+- rldicr rd,rd,32,31; \
+- sub rd,rs,rd
+-
+-#define tovirt(rd,rs) \
+- lis rd,((KERNELBASE>>48)&0xFFFF); \
+- rldicr rd,rd,32,31; \
+- add rd,rs,rd
+-
+-/* Condition Register Bit Fields */
+-
+-#define cr0 0
+-#define cr1 1
+-#define cr2 2
+-#define cr3 3
+-#define cr4 4
+-#define cr5 5
+-#define cr6 6
+-#define cr7 7
+-
+-
+-/* General Purpose Registers (GPRs) */
+-
+-#define r0 0
+-#define r1 1
+-#define r2 2
+-#define r3 3
+-#define r4 4
+-#define r5 5
+-#define r6 6
+-#define r7 7
+-#define r8 8
+-#define r9 9
+-#define r10 10
+-#define r11 11
+-#define r12 12
+-#define r13 13
+-#define r14 14
+-#define r15 15
+-#define r16 16
+-#define r17 17
+-#define r18 18
+-#define r19 19
+-#define r20 20
+-#define r21 21
+-#define r22 22
+-#define r23 23
+-#define r24 24
+-#define r25 25
+-#define r26 26
+-#define r27 27
+-#define r28 28
+-#define r29 29
+-#define r30 30
+-#define r31 31
+-
+-
+-/* Floating Point Registers (FPRs) */
+-
+-#define fr0 0
+-#define fr1 1
+-#define fr2 2
+-#define fr3 3
+-#define fr4 4
+-#define fr5 5
+-#define fr6 6
+-#define fr7 7
+-#define fr8 8
+-#define fr9 9
+-#define fr10 10
+-#define fr11 11
+-#define fr12 12
+-#define fr13 13
+-#define fr14 14
+-#define fr15 15
+-#define fr16 16
+-#define fr17 17
+-#define fr18 18
+-#define fr19 19
+-#define fr20 20
+-#define fr21 21
+-#define fr22 22
+-#define fr23 23
+-#define fr24 24
+-#define fr25 25
+-#define fr26 26
+-#define fr27 27
+-#define fr28 28
+-#define fr29 29
+-#define fr30 30
+-#define fr31 31
+-
+-#define vr0 0
+-#define vr1 1
+-#define vr2 2
+-#define vr3 3
+-#define vr4 4
+-#define vr5 5
+-#define vr6 6
+-#define vr7 7
+-#define vr8 8
+-#define vr9 9
+-#define vr10 10
+-#define vr11 11
+-#define vr12 12
+-#define vr13 13
+-#define vr14 14
+-#define vr15 15
+-#define vr16 16
+-#define vr17 17
+-#define vr18 18
+-#define vr19 19
+-#define vr20 20
+-#define vr21 21
+-#define vr22 22
+-#define vr23 23
+-#define vr24 24
+-#define vr25 25
+-#define vr26 26
+-#define vr27 27
+-#define vr28 28
+-#define vr29 29
+-#define vr30 30
+-#define vr31 31
+-
+-#endif /* _PPC64_PPC_ASM_H */
+diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
+deleted file mode 100644
+--- a/include/asm-ppc64/processor.h
++++ /dev/null
+@@ -1,558 +0,0 @@
+-#ifndef __ASM_PPC64_PROCESSOR_H
+-#define __ASM_PPC64_PROCESSOR_H
+-
+-/*
+- * Copyright (C) 2001 PPC 64 Team, IBM Corp
+- *
+- * 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/stringify.h>
+-#ifndef __ASSEMBLY__
+-#include <linux/config.h>
+-#include <asm/atomic.h>
+-#include <asm/ppcdebug.h>
+-#include <asm/a.out.h>
+-#endif
+-#include <asm/ptrace.h>
+-#include <asm/types.h>
+-#include <asm/systemcfg.h>
+-#include <asm/cputable.h>
+-
+-/* Machine State Register (MSR) Fields */
+-#define MSR_SF_LG 63 /* Enable 64 bit mode */
+-#define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */
+-#define MSR_HV_LG 60 /* Hypervisor state */
+-#define MSR_VEC_LG 25 /* Enable AltiVec */
+-#define MSR_POW_LG 18 /* Enable Power Management */
+-#define MSR_WE_LG 18 /* Wait State Enable */
+-#define MSR_TGPR_LG 17 /* TLB Update registers in use */
+-#define MSR_CE_LG 17 /* Critical Interrupt Enable */
+-#define MSR_ILE_LG 16 /* Interrupt Little Endian */
+-#define MSR_EE_LG 15 /* External Interrupt Enable */
+-#define MSR_PR_LG 14 /* Problem State / Privilege Level */
+-#define MSR_FP_LG 13 /* Floating Point enable */
+-#define MSR_ME_LG 12 /* Machine Check Enable */
+-#define MSR_FE0_LG 11 /* Floating Exception mode 0 */
+-#define MSR_SE_LG 10 /* Single Step */
+-#define MSR_BE_LG 9 /* Branch Trace */
+-#define MSR_DE_LG 9 /* Debug Exception Enable */
+-#define MSR_FE1_LG 8 /* Floating Exception mode 1 */
+-#define MSR_IP_LG 6 /* Exception prefix 0x000/0xFFF */
+-#define MSR_IR_LG 5 /* Instruction Relocate */
+-#define MSR_DR_LG 4 /* Data Relocate */
+-#define MSR_PE_LG 3 /* Protection Enable */
+-#define MSR_PX_LG 2 /* Protection Exclusive Mode */
+-#define MSR_PMM_LG 2 /* Performance monitor */
+-#define MSR_RI_LG 1 /* Recoverable Exception */
+-#define MSR_LE_LG 0 /* Little Endian */
+-
+-#ifdef __ASSEMBLY__
+-#define __MASK(X) (1<<(X))
+-#else
+-#define __MASK(X) (1UL<<(X))
+-#endif
+-
+-#define MSR_SF __MASK(MSR_SF_LG) /* Enable 64 bit mode */
+-#define MSR_ISF __MASK(MSR_ISF_LG) /* Interrupt 64b mode valid on 630 */
+-#define MSR_HV __MASK(MSR_HV_LG) /* Hypervisor state */
+-#define MSR_VEC __MASK(MSR_VEC_LG) /* Enable AltiVec */
+-#define MSR_POW __MASK(MSR_POW_LG) /* Enable Power Management */
+-#define MSR_WE __MASK(MSR_WE_LG) /* Wait State Enable */
+-#define MSR_TGPR __MASK(MSR_TGPR_LG) /* TLB Update registers in use */
+-#define MSR_CE __MASK(MSR_CE_LG) /* Critical Interrupt Enable */
+-#define MSR_ILE __MASK(MSR_ILE_LG) /* Interrupt Little Endian */
+-#define MSR_EE __MASK(MSR_EE_LG) /* External Interrupt Enable */
+-#define MSR_PR __MASK(MSR_PR_LG) /* Problem State / Privilege Level */
+-#define MSR_FP __MASK(MSR_FP_LG) /* Floating Point enable */
+-#define MSR_ME __MASK(MSR_ME_LG) /* Machine Check Enable */
+-#define MSR_FE0 __MASK(MSR_FE0_LG) /* Floating Exception mode 0 */
+-#define MSR_SE __MASK(MSR_SE_LG) /* Single Step */
+-#define MSR_BE __MASK(MSR_BE_LG) /* Branch Trace */
+-#define MSR_DE __MASK(MSR_DE_LG) /* Debug Exception Enable */
+-#define MSR_FE1 __MASK(MSR_FE1_LG) /* Floating Exception mode 1 */
+-#define MSR_IP __MASK(MSR_IP_LG) /* Exception prefix 0x000/0xFFF */
+-#define MSR_IR __MASK(MSR_IR_LG) /* Instruction Relocate */
+-#define MSR_DR __MASK(MSR_DR_LG) /* Data Relocate */
+-#define MSR_PE __MASK(MSR_PE_LG) /* Protection Enable */
+-#define MSR_PX __MASK(MSR_PX_LG) /* Protection Exclusive Mode */
+-#define MSR_PMM __MASK(MSR_PMM_LG) /* Performance monitor */
+-#define MSR_RI __MASK(MSR_RI_LG) /* Recoverable Exception */
+-#define MSR_LE __MASK(MSR_LE_LG) /* Little Endian */
+-
+-#define MSR_ MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF
+-#define MSR_KERNEL MSR_ | MSR_SF | MSR_HV
+-
+-#define MSR_USER32 MSR_ | MSR_PR | MSR_EE
+-#define MSR_USER64 MSR_USER32 | MSR_SF
+-
+-/* Floating Point Status and Control Register (FPSCR) Fields */
+-
+-#define FPSCR_FX 0x80000000 /* FPU exception summary */
+-#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */
+-#define FPSCR_VX 0x20000000 /* Invalid operation summary */
+-#define FPSCR_OX 0x10000000 /* Overflow exception summary */
+-#define FPSCR_UX 0x08000000 /* Underflow exception summary */
+-#define FPSCR_ZX 0x04000000 /* Zero-divide exception summary */
+-#define FPSCR_XX 0x02000000 /* Inexact exception summary */
+-#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */
+-#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */
+-#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */
+-#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */
+-#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */
+-#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */
+-#define FPSCR_FR 0x00040000 /* Fraction rounded */
+-#define FPSCR_FI 0x00020000 /* Fraction inexact */
+-#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */
+-#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */
+-#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */
+-#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */
+-#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */
+-#define FPSCR_VE 0x00000080 /* Invalid op exception enable */
+-#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */
+-#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */
+-#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */
+-#define FPSCR_XE 0x00000008 /* FP inexact exception enable */
+-#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */
+-#define FPSCR_RN 0x00000003 /* FPU rounding control */
+-
+-/* Special Purpose Registers (SPRNs)*/
+-
+-#define SPRN_CTR 0x009 /* Count Register */
+-#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+-#define DABR_TRANSLATION (1UL << 2)
+-#define SPRN_DAR 0x013 /* Data Address Register */
+-#define SPRN_DEC 0x016 /* Decrement Register */
+-#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+-#define DSISR_NOHPTE 0x40000000 /* no translation found */
+-#define DSISR_PROTFAULT 0x08000000 /* protection fault */
+-#define DSISR_ISSTORE 0x02000000 /* access was a store */
+-#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
+-#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */
+-#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
+-#define SPRN_MSRDORM 0x3F1 /* Hardware Implementation Register 1 */
+-#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+-#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+-#define SPRN_NIADORM 0x3F3 /* Hardware Implementation Register 2 */
+-#define SPRN_HID4 0x3F4 /* 970 HID4 */
+-#define SPRN_HID5 0x3F6 /* 970 HID5 */
+-#define SPRN_HID6 0x3F9 /* BE HID 6 */
+-#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */
+-#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */
+-#define SPRN_TSCR 0x399 /* Thread switch control on BE */
+-#define SPRN_TTR 0x39A /* Thread switch timeout on BE */
+-#define TSCR_DEC_ENABLE 0x200000 /* Decrementer Interrupt */
+-#define TSCR_EE_ENABLE 0x100000 /* External Interrupt */
+-#define TSCR_EE_BOOST 0x080000 /* External Interrupt Boost */
+-#define SPRN_TSC 0x3FD /* Thread switch control on others */
+-#define SPRN_TST 0x3FC /* Thread switch timeout on others */
+-#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
+-#define SPRN_LR 0x008 /* Link Register */
+-#define SPRN_PIR 0x3FF /* Processor Identification Register */
+-#define SPRN_PIT 0x3DB /* Programmable Interval Timer */
+-#define SPRN_PURR 0x135 /* Processor Utilization of Resources Register */
+-#define SPRN_PVR 0x11F /* Processor Version Register */
+-#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
+-#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
+-#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
+-#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
+-#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
+-#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
+-#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
+-#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
+-#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
+-#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+-#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
+-#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
+-#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, W/O) */
+-#define SPRN_TBWU 0x11D /* Time Base Write Upper Register (super, W/O) */
+-#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
+-#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
+-#define SPRN_XER 0x001 /* Fixed Point Exception Register */
+-#define SPRN_VRSAVE 0x100 /* Vector save */
+-#define SPRN_CTRLF 0x088
+-#define SPRN_CTRLT 0x098
+-#define CTRL_RUNLATCH 0x1
+-
+-/* Performance monitor SPRs */
+-#define SPRN_SIAR 780
+-#define SPRN_SDAR 781
+-#define SPRN_MMCRA 786
+-#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */
+-#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */
+-#define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
+-#define SPRN_PMC1 787
+-#define SPRN_PMC2 788
+-#define SPRN_PMC3 789
+-#define SPRN_PMC4 790
+-#define SPRN_PMC5 791
+-#define SPRN_PMC6 792
+-#define SPRN_PMC7 793
+-#define SPRN_PMC8 794
+-#define SPRN_MMCR0 795
+-#define MMCR0_FC 0x80000000UL /* freeze counters. set to 1 on a perfmon exception */
+-#define MMCR0_FCS 0x40000000UL /* freeze in supervisor state */
+-#define MMCR0_KERNEL_DISABLE MMCR0_FCS
+-#define MMCR0_FCP 0x20000000UL /* freeze in problem state */
+-#define MMCR0_PROBLEM_DISABLE MMCR0_FCP
+-#define MMCR0_FCM1 0x10000000UL /* freeze counters while MSR mark = 1 */
+-#define MMCR0_FCM0 0x08000000UL /* freeze counters while MSR mark = 0 */
+-#define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */
+-#define MMCR0_FCECE 0x02000000UL /* freeze counters on enabled condition or event */
+-/* time base exception enable */
+-#define MMCR0_TBEE 0x00400000UL /* time base exception enable */
+-#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/
+-#define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/
+-#define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */
+-#define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */
+-#define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */
+-#define MMCR0_FCTI 0x00000008UL /* freeze counters in tags inactive mode */
+-#define MMCR0_FCTA 0x00000004UL /* freeze counters in tags active mode */
+-#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
+-#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
+-#define SPRN_MMCR1 798
+-
+-/* Short-hand versions for a number of the above SPRNs */
+-
+-#define CTR SPRN_CTR /* Counter Register */
+-#define DAR SPRN_DAR /* Data Address Register */
+-#define DABR SPRN_DABR /* Data Address Breakpoint Register */
+-#define DEC SPRN_DEC /* Decrement Register */
+-#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
+-#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
+-#define MSRDORM SPRN_MSRDORM /* MSR Dormant Register */
+-#define NIADORM SPRN_NIADORM /* NIA Dormant Register */
+-#define TSC SPRN_TSC /* Thread switch control */
+-#define TST SPRN_TST /* Thread switch timeout */
+-#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
+-#define L2CR SPRN_L2CR /* PPC 750 L2 control register */
+-#define __LR SPRN_LR
+-#define PVR SPRN_PVR /* Processor Version */
+-#define PIR SPRN_PIR /* Processor ID */
+-#define PURR SPRN_PURR /* Processor Utilization of Resource Register */
+-#define SDR1 SPRN_SDR1 /* MMU hash base register */
+-#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
+-#define SPR1 SPRN_SPRG1
+-#define SPR2 SPRN_SPRG2
+-#define SPR3 SPRN_SPRG3
+-#define SPRG0 SPRN_SPRG0
+-#define SPRG1 SPRN_SPRG1
+-#define SPRG2 SPRN_SPRG2
+-#define SPRG3 SPRN_SPRG3
+-#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */
+-#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */
+-#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
+-#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
+-#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
+-#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
+-#define XER SPRN_XER
+-
+-/* Processor Version Register (PVR) field extraction */
+-
+-#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+-#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+-
+-/* Processor Version Numbers */
+-#define PV_NORTHSTAR 0x0033
+-#define PV_PULSAR 0x0034
+-#define PV_POWER4 0x0035
+-#define PV_ICESTAR 0x0036
+-#define PV_SSTAR 0x0037
+-#define PV_POWER4p 0x0038
+-#define PV_970 0x0039
+-#define PV_POWER5 0x003A
+-#define PV_POWER5p 0x003B
+-#define PV_970FX 0x003C
+-#define PV_630 0x0040
+-#define PV_630p 0x0041
+-#define PV_970MP 0x0044
+-#define PV_BE 0x0070
+-
+-/* Platforms supported by PPC64 */
+-#define PLATFORM_PSERIES 0x0100
+-#define PLATFORM_PSERIES_LPAR 0x0101
+-#define PLATFORM_ISERIES_LPAR 0x0201
+-#define PLATFORM_LPAR 0x0001
+-#define PLATFORM_POWERMAC 0x0400
+-#define PLATFORM_MAPLE 0x0500
+-#define PLATFORM_BPA 0x1000
+-
+-/* Compatibility with drivers coming from PPC32 world */
+-#define _machine (systemcfg->platform)
+-#define _MACH_Pmac PLATFORM_POWERMAC
+-
+-/*
+- * List of interrupt controllers.
+- */
+-#define IC_INVALID 0
+-#define IC_OPEN_PIC 1
+-#define IC_PPC_XIC 2
+-#define IC_BPA_IIC 3
+-
+-#define XGLUE(a,b) a##b
+-#define GLUE(a,b) XGLUE(a,b)
+-
+-#ifdef __ASSEMBLY__
+-
+-#define _GLOBAL(name) \
+- .section ".text"; \
+- .align 2 ; \
+- .globl name; \
+- .globl GLUE(.,name); \
+- .section ".opd","aw"; \
+-name: \
+- .quad GLUE(.,name); \
+- .quad .TOC. at tocbase; \
+- .quad 0; \
+- .previous; \
+- .type GLUE(.,name), at function; \
+-GLUE(.,name):
+-
+-#define _KPROBE(name) \
+- .section ".kprobes.text","a"; \
+- .align 2 ; \
+- .globl name; \
+- .globl GLUE(.,name); \
+- .section ".opd","aw"; \
+-name: \
+- .quad GLUE(.,name); \
+- .quad .TOC. at tocbase; \
+- .quad 0; \
+- .previous; \
+- .type GLUE(.,name), at function; \
+-GLUE(.,name):
+-
+-#define _STATIC(name) \
+- .section ".text"; \
+- .align 2 ; \
+- .section ".opd","aw"; \
+-name: \
+- .quad GLUE(.,name); \
+- .quad .TOC. at tocbase; \
+- .quad 0; \
+- .previous; \
+- .type GLUE(.,name), at function; \
+-GLUE(.,name):
+-
+-#else /* __ASSEMBLY__ */
+-
+-/*
+- * Default implementation of macro that returns current
+- * instruction pointer ("program counter").
+- */
+-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+-
+-/* Macros for setting and retrieving special purpose registers */
+-
+-#define mfmsr() ({unsigned long rval; \
+- asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+-
+-#define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \
+- : : "r" (v))
+-#define mtmsrd(v) __mtmsrd((v), 0)
+-
+-#define mfspr(rn) ({unsigned long rval; \
+- asm volatile("mfspr %0," __stringify(rn) \
+- : "=r" (rval)); rval;})
+-#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
+-
+-#define mftb() ({unsigned long rval; \
+- asm volatile("mftb %0" : "=r" (rval)); rval;})
+-
+-#define mttbl(v) asm volatile("mttbl %0":: "r"(v))
+-#define mttbu(v) asm volatile("mttbu %0":: "r"(v))
+-
+-#define mfasr() ({unsigned long rval; \
+- asm volatile("mfasr %0" : "=r" (rval)); rval;})
+-
+-static inline void set_tb(unsigned int upper, unsigned int lower)
+-{
+- mttbl(0);
+- mttbu(upper);
+- mttbl(lower);
+-}
+-
+-#define __get_SP() ({unsigned long sp; \
+- asm volatile("mr %0,1": "=r" (sp)); sp;})
+-
+-#ifdef __KERNEL__
+-
+-extern int have_of;
+-extern u64 ppc64_interrupt_controller;
+-
+-struct task_struct;
+-void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
+-void release_thread(struct task_struct *);
+-
+-/* Prepare to copy thread state - unlazy all lazy status */
+-extern void prepare_to_copy(struct task_struct *tsk);
+-
+-/* Create a new kernel thread. */
+-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+-
+-/* Lazy FPU handling on uni-processor */
+-extern struct task_struct *last_task_used_math;
+-extern struct task_struct *last_task_used_altivec;
+-
+-/* 64-bit user address space is 44-bits (16TB user VM) */
+-#define TASK_SIZE_USER64 (0x0000100000000000UL)
+-
+-/*
+- * 32-bit user address space is 4GB - 1 page
+- * (this 1 page is needed so referencing of 0xFFFFFFFF generates EFAULT
+- */
+-#define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE))
+-
+-#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
+- TASK_SIZE_USER32 : TASK_SIZE_USER64)
+-
+-/* This decides where the kernel will search for a free chunk of vm
+- * space during mmap's.
+- */
+-#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
+-#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))
+-
+-#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)||(ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \
+- TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
+-
+-typedef struct {
+- unsigned long seg;
+-} mm_segment_t;
+-
+-struct thread_struct {
+- unsigned long ksp; /* Kernel stack pointer */
+- unsigned long ksp_vsid;
+- struct pt_regs *regs; /* Pointer to saved register state */
+- mm_segment_t fs; /* for get_fs() validation */
+- double fpr[32]; /* Complete floating point set */
+- unsigned long fpscr; /* Floating point status (plus pad) */
+- unsigned long fpexc_mode; /* Floating-point exception mode */
+- unsigned long start_tb; /* Start purr when proc switched in */
+- unsigned long accum_tb; /* Total accumilated purr for process */
+- unsigned long vdso_base; /* base of the vDSO library */
+- unsigned long dabr; /* Data address breakpoint register */
+-#ifdef CONFIG_ALTIVEC
+- /* Complete AltiVec register set */
+- vector128 vr[32] __attribute((aligned(16)));
+- /* AltiVec status */
+- vector128 vscr __attribute((aligned(16)));
+- unsigned long vrsave;
+- int used_vr; /* set if process has used altivec */
+-#endif /* CONFIG_ALTIVEC */
+-};
+-
+-#define ARCH_MIN_TASKALIGN 16
+-
+-#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
+-
+-#define INIT_THREAD { \
+- .ksp = INIT_SP, \
+- .regs = (struct pt_regs *)INIT_SP - 1, \
+- .fs = KERNEL_DS, \
+- .fpr = {0}, \
+- .fpscr = 0, \
+- .fpexc_mode = MSR_FE0|MSR_FE1, \
+-}
+-
+-/*
+- * Return saved PC of a blocked thread. For now, this is the "user" PC
+- */
+-#define thread_saved_pc(tsk) \
+- ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
+-
+-unsigned long get_wchan(struct task_struct *p);
+-
+-#define KSTK_EIP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
+-#define KSTK_ESP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0)
+-
+-/* Get/set floating-point exception mode */
+-#define GET_FPEXC_CTL(tsk, adr) get_fpexc_mode((tsk), (adr))
+-#define SET_FPEXC_CTL(tsk, val) set_fpexc_mode((tsk), (val))
+-
+-extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr);
+-extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val);
+-
+-static inline unsigned int __unpack_fe01(unsigned long msr_bits)
+-{
+- return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
+-}
+-
+-static inline unsigned long __pack_fe01(unsigned int fpmode)
+-{
+- return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1);
+-}
+-
+-#define cpu_relax() do { HMT_low(); HMT_medium(); barrier(); } while (0)
+-
+-/*
+- * Prefetch macros.
+- */
+-#define ARCH_HAS_PREFETCH
+-#define ARCH_HAS_PREFETCHW
+-#define ARCH_HAS_SPINLOCK_PREFETCH
+-
+-static inline void prefetch(const void *x)
+-{
+- if (unlikely(!x))
+- return;
+-
+- __asm__ __volatile__ ("dcbt 0,%0" : : "r" (x));
+-}
+-
+-static inline void prefetchw(const void *x)
+-{
+- if (unlikely(!x))
+- return;
+-
+- __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x));
+-}
+-
+-#define spin_lock_prefetch(x) prefetchw(x)
+-
+-#define HAVE_ARCH_PICK_MMAP_LAYOUT
+-
+-static inline void ppc64_runlatch_on(void)
+-{
+- unsigned long ctrl;
+-
+- if (cpu_has_feature(CPU_FTR_CTRL)) {
+- ctrl = mfspr(SPRN_CTRLF);
+- ctrl |= CTRL_RUNLATCH;
+- mtspr(SPRN_CTRLT, ctrl);
+- }
+-}
+-
+-static inline void ppc64_runlatch_off(void)
+-{
+- unsigned long ctrl;
+-
+- if (cpu_has_feature(CPU_FTR_CTRL)) {
+- ctrl = mfspr(SPRN_CTRLF);
+- ctrl &= ~CTRL_RUNLATCH;
+- mtspr(SPRN_CTRLT, ctrl);
+- }
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#ifdef __KERNEL__
+-#define RUNLATCH_ON(REG) \
+-BEGIN_FTR_SECTION \
+- mfspr (REG),SPRN_CTRLF; \
+- ori (REG),(REG),CTRL_RUNLATCH; \
+- mtspr SPRN_CTRLT,(REG); \
+-END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
+-#endif
+-
+-/*
+- * Number of entries in the SLB. If this ever changes we should handle
+- * it with a use a cpu feature fixup.
+- */
+-#define SLB_NUM_ENTRIES 64
+-
+-#endif /* __ASM_PPC64_PROCESSOR_H */
+diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
+--- a/include/asm-ppc64/prom.h
++++ b/include/asm-ppc64/prom.h
+@@ -14,6 +14,7 @@
+ * 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/proc_fs.h>
+ #include <asm/atomic.h>
+
+@@ -137,6 +138,9 @@ struct device_node {
+ struct kref kref;
+ unsigned long _flags;
+ void *data;
++#ifdef CONFIG_PPC_ISERIES
++ struct list_head Device_List;
++#endif
+ };
+
+ extern struct device_node *of_chosen;
+diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
+deleted file mode 100644
+--- a/include/asm-ppc64/rtas.h
++++ /dev/null
+@@ -1,249 +0,0 @@
+-#ifndef _PPC64_RTAS_H
+-#define _PPC64_RTAS_H
+-
+-#include <linux/spinlock.h>
+-#include <asm/page.h>
+-
+-/*
+- * Definitions for talking to the RTAS on CHRP machines.
+- *
+- * Copyright (C) 2001 Peter Bergner
+- * Copyright (C) 2001 PPC 64 Team, IBM Corp
+- *
+- * 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.
+- */
+-
+-#define RTAS_UNKNOWN_SERVICE (-1)
+-#define RTAS_INSTANTIATE_MAX (1UL<<30) /* Don't instantiate rtas at/above this value */
+-
+-/* Buffer size for ppc_rtas system call. */
+-#define RTAS_RMOBUF_MAX (64 * 1024)
+-
+-/* RTAS return status codes */
+-#define RTAS_BUSY -2 /* RTAS Busy */
+-#define RTAS_EXTENDED_DELAY_MIN 9900
+-#define RTAS_EXTENDED_DELAY_MAX 9905
+-
+-/*
+- * In general to call RTAS use rtas_token("string") to lookup
+- * an RTAS token for the given string (e.g. "event-scan").
+- * To actually perform the call use
+- * ret = rtas_call(token, n_in, n_out, ...)
+- * Where n_in is the number of input parameters and
+- * n_out is the number of output parameters
+- *
+- * If the "string" is invalid on this system, RTAS_UNKNOWN_SERVICE
+- * will be returned as a token. rtas_call() does look for this
+- * token and error out gracefully so rtas_call(rtas_token("str"), ...)
+- * may be safely used for one-shot calls to RTAS.
+- *
+- */
+-
+-typedef u32 rtas_arg_t;
+-
+-struct rtas_args {
+- u32 token;
+- u32 nargs;
+- u32 nret;
+- rtas_arg_t args[16];
+- rtas_arg_t *rets; /* Pointer to return values in args[]. */
+-};
+-
+-extern struct rtas_args rtas_stop_self_args;
+-
+-struct rtas_t {
+- unsigned long entry; /* physical address pointer */
+- unsigned long base; /* physical address pointer */
+- unsigned long size;
+- spinlock_t lock;
+- struct rtas_args args;
+- struct device_node *dev; /* virtual address pointer */
+-};
+-
+-/* RTAS event classes */
+-#define RTAS_INTERNAL_ERROR 0x80000000 /* set bit 0 */
+-#define RTAS_EPOW_WARNING 0x40000000 /* set bit 1 */
+-#define RTAS_POWERMGM_EVENTS 0x20000000 /* set bit 2 */
+-#define RTAS_HOTPLUG_EVENTS 0x10000000 /* set bit 3 */
+-#define RTAS_EVENT_SCAN_ALL_EVENTS 0xf0000000
+-
+-/* RTAS event severity */
+-#define RTAS_SEVERITY_FATAL 0x5
+-#define RTAS_SEVERITY_ERROR 0x4
+-#define RTAS_SEVERITY_ERROR_SYNC 0x3
+-#define RTAS_SEVERITY_WARNING 0x2
+-#define RTAS_SEVERITY_EVENT 0x1
+-#define RTAS_SEVERITY_NO_ERROR 0x0
+-
+-/* RTAS event disposition */
+-#define RTAS_DISP_FULLY_RECOVERED 0x0
+-#define RTAS_DISP_LIMITED_RECOVERY 0x1
+-#define RTAS_DISP_NOT_RECOVERED 0x2
+-
+-/* RTAS event initiator */
+-#define RTAS_INITIATOR_UNKNOWN 0x0
+-#define RTAS_INITIATOR_CPU 0x1
+-#define RTAS_INITIATOR_PCI 0x2
+-#define RTAS_INITIATOR_ISA 0x3
+-#define RTAS_INITIATOR_MEMORY 0x4
+-#define RTAS_INITIATOR_POWERMGM 0x5
+-
+-/* RTAS event target */
+-#define RTAS_TARGET_UNKNOWN 0x0
+-#define RTAS_TARGET_CPU 0x1
+-#define RTAS_TARGET_PCI 0x2
+-#define RTAS_TARGET_ISA 0x3
+-#define RTAS_TARGET_MEMORY 0x4
+-#define RTAS_TARGET_POWERMGM 0x5
+-
+-/* RTAS event type */
+-#define RTAS_TYPE_RETRY 0x01
+-#define RTAS_TYPE_TCE_ERR 0x02
+-#define RTAS_TYPE_INTERN_DEV_FAIL 0x03
+-#define RTAS_TYPE_TIMEOUT 0x04
+-#define RTAS_TYPE_DATA_PARITY 0x05
+-#define RTAS_TYPE_ADDR_PARITY 0x06
+-#define RTAS_TYPE_CACHE_PARITY 0x07
+-#define RTAS_TYPE_ADDR_INVALID 0x08
+-#define RTAS_TYPE_ECC_UNCORR 0x09
+-#define RTAS_TYPE_ECC_CORR 0x0a
+-#define RTAS_TYPE_EPOW 0x40
+-#define RTAS_TYPE_PLATFORM 0xE0
+-#define RTAS_TYPE_IO 0xE1
+-#define RTAS_TYPE_INFO 0xE2
+-#define RTAS_TYPE_DEALLOC 0xE3
+-#define RTAS_TYPE_DUMP 0xE4
+-/* I don't add PowerMGM events right now, this is a different topic */
+-#define RTAS_TYPE_PMGM_POWER_SW_ON 0x60
+-#define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61
+-#define RTAS_TYPE_PMGM_LID_OPEN 0x62
+-#define RTAS_TYPE_PMGM_LID_CLOSE 0x63
+-#define RTAS_TYPE_PMGM_SLEEP_BTN 0x64
+-#define RTAS_TYPE_PMGM_WAKE_BTN 0x65
+-#define RTAS_TYPE_PMGM_BATTERY_WARN 0x66
+-#define RTAS_TYPE_PMGM_BATTERY_CRIT 0x67
+-#define RTAS_TYPE_PMGM_SWITCH_TO_BAT 0x68
+-#define RTAS_TYPE_PMGM_SWITCH_TO_AC 0x69
+-#define RTAS_TYPE_PMGM_KBD_OR_MOUSE 0x6a
+-#define RTAS_TYPE_PMGM_ENCLOS_OPEN 0x6b
+-#define RTAS_TYPE_PMGM_ENCLOS_CLOSED 0x6c
+-#define RTAS_TYPE_PMGM_RING_INDICATE 0x6d
+-#define RTAS_TYPE_PMGM_LAN_ATTENTION 0x6e
+-#define RTAS_TYPE_PMGM_TIME_ALARM 0x6f
+-#define RTAS_TYPE_PMGM_CONFIG_CHANGE 0x70
+-#define RTAS_TYPE_PMGM_SERVICE_PROC 0x71
+-
+-struct rtas_error_log {
+- unsigned long version:8; /* Architectural version */
+- unsigned long severity:3; /* Severity level of error */
+- unsigned long disposition:2; /* Degree of recovery */
+- unsigned long extended:1; /* extended log present? */
+- unsigned long /* reserved */ :2; /* Reserved for future use */
+- unsigned long initiator:4; /* Initiator of event */
+- unsigned long target:4; /* Target of failed operation */
+- unsigned long type:8; /* General event or error*/
+- unsigned long extended_log_length:32; /* length in bytes */
+- unsigned char buffer[1];
+-};
+-
+-struct flash_block {
+- char *data;
+- unsigned long length;
+-};
+-
+-/* This struct is very similar but not identical to
+- * that needed by the rtas flash update.
+- * All we need to do for rtas is rewrite num_blocks
+- * into a version/length and translate the pointers
+- * to absolute.
+- */
+-#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block))
+-struct flash_block_list {
+- unsigned long num_blocks;
+- struct flash_block_list *next;
+- struct flash_block blocks[FLASH_BLOCKS_PER_NODE];
+-};
+-struct flash_block_list_header { /* just the header of flash_block_list */
+- unsigned long num_blocks;
+- struct flash_block_list *next;
+-};
+-extern struct flash_block_list_header rtas_firmware_flash_list;
+-
+-extern struct rtas_t rtas;
+-
+-extern void enter_rtas(unsigned long);
+-extern int rtas_token(const char *service);
+-extern int rtas_call(int token, int, int, int *, ...);
+-extern void call_rtas_display_status(unsigned char);
+-extern void rtas_restart(char *cmd);
+-extern void rtas_power_off(void);
+-extern void rtas_halt(void);
+-extern void rtas_os_term(char *str);
+-extern int rtas_get_sensor(int sensor, int index, int *state);
+-extern int rtas_get_power_level(int powerdomain, int *level);
+-extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
+-extern int rtas_set_indicator(int indicator, int index, int new_value);
+-extern void rtas_progress(char *s, unsigned short hex);
+-extern void rtas_initialize(void);
+-
+-struct rtc_time;
+-extern void rtas_get_boot_time(struct rtc_time *rtc_time);
+-extern void rtas_get_rtc_time(struct rtc_time *rtc_time);
+-extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
+-
+-/* Given an RTAS status code of 9900..9905 compute the hinted delay */
+-unsigned int rtas_extended_busy_delay_time(int status);
+-static inline int rtas_is_extended_busy(int status)
+-{
+- return status >= 9900 && status <= 9909;
+-}
+-
+-extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
+-
+-/* Error types logged. */
+-#define ERR_FLAG_ALREADY_LOGGED 0x0
+-#define ERR_FLAG_BOOT 0x1 /* log was pulled from NVRAM on boot */
+-#define ERR_TYPE_RTAS_LOG 0x2 /* from rtas event-scan */
+-#define ERR_TYPE_KERNEL_PANIC 0x4 /* from panic() */
+-
+-/* All the types and not flags */
+-#define ERR_TYPE_MASK (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+-
+-#define RTAS_DEBUG KERN_DEBUG "RTAS: "
+-
+-#define RTAS_ERROR_LOG_MAX 2048
+-
+-/*
+- * Return the firmware-specified size of the error log buffer
+- * for all rtas calls that require an error buffer argument.
+- * This includes 'check-exception' and 'rtas-last-error'.
+- */
+-extern int rtas_get_error_log_max(void);
+-
+-/* Event Scan Parameters */
+-#define EVENT_SCAN_ALL_EVENTS 0xf0000000
+-#define SURVEILLANCE_TOKEN 9000
+-#define LOG_NUMBER 64 /* must be a power of two */
+-#define LOG_NUMBER_MASK (LOG_NUMBER-1)
+-
+-/* Some RTAS ops require a data buffer and that buffer must be < 4G.
+- * Rather than having a memory allocator, just use this buffer
+- * (get the lock first), make the RTAS call. Copy the data instead
+- * of holding the buffer for long.
+- */
+-
+-#define RTAS_DATA_BUF_SIZE 4096
+-extern spinlock_t rtas_data_buf_lock;
+-extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
+-
+-extern void rtas_stop_self(void);
+-
+-/* RMO buffer reserved for user-space RTAS use */
+-extern unsigned long rtas_rmo_buf;
+-
+-#define GLOBAL_INTERRUPT_QUEUE 9005
+-
+-#endif /* _PPC64_RTAS_H */
+diff --git a/include/asm-ppc64/rwsem.h b/include/asm-ppc64/rwsem.h
+deleted file mode 100644
+--- a/include/asm-ppc64/rwsem.h
++++ /dev/null
+@@ -1,167 +0,0 @@
+-/*
+- * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff
+- * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h
+- * by Paul Mackerras <paulus at samba.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.
+- */
+-
+-#ifndef _PPC64_RWSEM_H
+-#define _PPC64_RWSEM_H
+-
+-#ifdef __KERNEL__
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-
+-/*
+- * the semaphore definition
+- */
+-struct rw_semaphore {
+- /* XXX this should be able to be an atomic_t -- paulus */
+- signed int count;
+-#define RWSEM_UNLOCKED_VALUE 0x00000000
+-#define RWSEM_ACTIVE_BIAS 0x00000001
+-#define RWSEM_ACTIVE_MASK 0x0000ffff
+-#define RWSEM_WAITING_BIAS (-0x00010000)
+-#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
+-#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+- spinlock_t wait_lock;
+- struct list_head wait_list;
+-#if RWSEM_DEBUG
+- int debug;
+-#endif
+-};
+-
+-/*
+- * initialisation
+- */
+-#if RWSEM_DEBUG
+-#define __RWSEM_DEBUG_INIT , 0
+-#else
+-#define __RWSEM_DEBUG_INIT /* */
+-#endif
+-
+-#define __RWSEM_INITIALIZER(name) \
+- { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+- LIST_HEAD_INIT((name).wait_list) \
+- __RWSEM_DEBUG_INIT }
+-
+-#define DECLARE_RWSEM(name) \
+- struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+-
+-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+-
+-static inline void init_rwsem(struct rw_semaphore *sem)
+-{
+- sem->count = RWSEM_UNLOCKED_VALUE;
+- spin_lock_init(&sem->wait_lock);
+- INIT_LIST_HEAD(&sem->wait_list);
+-#if RWSEM_DEBUG
+- sem->debug = 0;
+-#endif
+-}
+-
+-/*
+- * lock for reading
+- */
+-static inline void __down_read(struct rw_semaphore *sem)
+-{
+- if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0))
+- rwsem_down_read_failed(sem);
+-}
+-
+-static inline int __down_read_trylock(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- while ((tmp = sem->count) >= 0) {
+- if (tmp == cmpxchg(&sem->count, tmp,
+- tmp + RWSEM_ACTIVE_READ_BIAS)) {
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+-/*
+- * lock for writing
+- */
+-static inline void __down_write(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+- (atomic_t *)(&sem->count));
+- if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
+- rwsem_down_write_failed(sem);
+-}
+-
+-static inline int __down_write_trylock(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+- RWSEM_ACTIVE_WRITE_BIAS);
+- return tmp == RWSEM_UNLOCKED_VALUE;
+-}
+-
+-/*
+- * unlock after reading
+- */
+-static inline void __up_read(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- tmp = atomic_dec_return((atomic_t *)(&sem->count));
+- if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
+- rwsem_wake(sem);
+-}
+-
+-/*
+- * unlock after writing
+- */
+-static inline void __up_write(struct rw_semaphore *sem)
+-{
+- if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+- (atomic_t *)(&sem->count)) < 0))
+- rwsem_wake(sem);
+-}
+-
+-/*
+- * implement atomic add functionality
+- */
+-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+-{
+- atomic_add(delta, (atomic_t *)(&sem->count));
+-}
+-
+-/*
+- * downgrade write lock to read lock
+- */
+-static inline void __downgrade_write(struct rw_semaphore *sem)
+-{
+- int tmp;
+-
+- tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+- if (tmp < 0)
+- rwsem_downgrade_wake(sem);
+-}
+-
+-/*
+- * implement exchange and add functionality
+- */
+-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+-{
+- return atomic_add_return(delta, (atomic_t *)(&sem->count));
+-}
+-
+-#endif /* __KERNEL__ */
+-#endif /* _PPC_RWSEM_XADD_H */
+diff --git a/include/asm-ppc64/scatterlist.h b/include/asm-ppc64/scatterlist.h
+deleted file mode 100644
+--- a/include/asm-ppc64/scatterlist.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-#ifndef _PPC64_SCATTERLIST_H
+-#define _PPC64_SCATTERLIST_H
+-
+-/*
+- * Copyright (C) 2001 PPC64 Team, IBM Corp
+- *
+- * 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 <asm/dma.h>
+-
+-struct scatterlist {
+- struct page *page;
+- unsigned int offset;
+- unsigned int length;
+-
+- /* For TCE support */
+- u32 dma_address;
+- u32 dma_length;
+-};
+-
+-#define sg_dma_address(sg) ((sg)->dma_address)
+-#define sg_dma_len(sg) ((sg)->dma_length)
+-
+-#define ISA_DMA_THRESHOLD (~0UL)
+-
+-#endif /* !(_PPC64_SCATTERLIST_H) */
+diff --git a/include/asm-ppc64/seccomp.h b/include/asm-ppc64/seccomp.h
+deleted file mode 100644
+--- a/include/asm-ppc64/seccomp.h
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#ifndef _ASM_SECCOMP_H
+-
+-#include <linux/thread_info.h> /* already defines TIF_32BIT */
+-
+-#ifndef TIF_32BIT
+-#error "unexpected TIF_32BIT on ppc64"
+-#endif
+-
+-#include <linux/unistd.h>
+-
+-#define __NR_seccomp_read __NR_read
+-#define __NR_seccomp_write __NR_write
+-#define __NR_seccomp_exit __NR_exit
+-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+-
+-#define __NR_seccomp_read_32 __NR_read
+-#define __NR_seccomp_write_32 __NR_write
+-#define __NR_seccomp_exit_32 __NR_exit
+-#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+-
+-#endif /* _ASM_SECCOMP_H */
+diff --git a/include/asm-ppc64/sections.h b/include/asm-ppc64/sections.h
+deleted file mode 100644
+--- a/include/asm-ppc64/sections.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-#ifndef _PPC64_SECTIONS_H
+-#define _PPC64_SECTIONS_H
+-
+-extern char _end[];
+-
+-#include <asm-generic/sections.h>
+-
+-#define __pmac
+-#define __pmacdata
+-
+-#define __prep
+-#define __prepdata
+-
+-#define __chrp
+-#define __chrpdata
+-
+-#define __openfirmware
+-#define __openfirmwaredata
+-
+-
+-static inline int in_kernel_text(unsigned long addr)
+-{
+- if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end)
+- return 1;
+-
+- return 0;
+-}
+-
+-#endif
+diff --git a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h
+deleted file mode 100644
+--- a/include/asm-ppc64/semaphore.h
++++ /dev/null
+@@ -1,98 +0,0 @@
+-#ifndef _PPC64_SEMAPHORE_H
+-#define _PPC64_SEMAPHORE_H
+-
+-/*
+- * Remove spinlock-based RW semaphores; RW semaphore definitions are
+- * now in rwsem.h and we use the generic lib/rwsem.c implementation.
+- * Rework semaphores to use atomic_dec_if_positive.
+- * -- Paul Mackerras (paulus at samba.org)
+- */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- /*
+- * Note that any negative value of count is equivalent to 0,
+- * but additionally indicates that some process(es) might be
+- * sleeping on `wait'.
+- */
+- atomic_t count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .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)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+-
+- /*
+- * Try to get the semaphore, take the slow path if we fail.
+- */
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- __down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+-
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- ret = __down_interruptible(sem);
+- return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- return atomic_dec_if_positive(&sem->count) < 0;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+- if (unlikely(atomic_inc_return(&sem->count) <= 0))
+- __up(sem);
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* !(_PPC64_SEMAPHORE_H) */
+diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
+--- a/include/asm-ppc64/smp.h
++++ b/include/asm-ppc64/smp.h
+@@ -77,7 +77,6 @@ extern int smt_enabled_at_boot;
+
+ extern int smp_mpic_probe(void);
+ extern void smp_mpic_setup_cpu(int cpu);
+-extern void smp_mpic_message_pass(int target, int msg);
+ extern void smp_generic_kick_cpu(int nr);
+
+ extern void smp_generic_give_timebase(void);
+diff --git a/include/asm-ppc64/smu.h b/include/asm-ppc64/smu.h
+deleted file mode 100644
+--- a/include/asm-ppc64/smu.h
++++ /dev/null
+@@ -1,379 +0,0 @@
+-#ifndef _SMU_H
+-#define _SMU_H
+-
+-/*
+- * Definitions for talking to the SMU chip in newer G5 PowerMacs
+- */
+-
+-#include <linux/config.h>
+-#include <linux/list.h>
+-
+-/*
+- * Known SMU commands
+- *
+- * Most of what is below comes from looking at the Open Firmware driver,
+- * though this is still incomplete and could use better documentation here
+- * or there...
+- */
+-
+-
+-/*
+- * Partition info commands
+- *
+- * I do not know what those are for at this point
+- */
+-#define SMU_CMD_PARTITION_COMMAND 0x3e
+-
+-
+-/*
+- * Fan control
+- *
+- * This is a "mux" for fan control commands, first byte is the
+- * "sub" command.
+- */
+-#define SMU_CMD_FAN_COMMAND 0x4a
+-
+-
+-/*
+- * Battery access
+- *
+- * Same command number as the PMU, could it be same syntax ?
+- */
+-#define SMU_CMD_BATTERY_COMMAND 0x6f
+-#define SMU_CMD_GET_BATTERY_INFO 0x00
+-
+-/*
+- * Real time clock control
+- *
+- * This is a "mux", first data byte contains the "sub" command.
+- * The "RTC" part of the SMU controls the date, time, powerup
+- * timer, but also a PRAM
+- *
+- * Dates are in BCD format on 7 bytes:
+- * [sec] [min] [hour] [weekday] [month day] [month] [year]
+- * with month being 1 based and year minus 100
+- */
+-#define SMU_CMD_RTC_COMMAND 0x8e
+-#define SMU_CMD_RTC_SET_PWRUP_TIMER 0x00 /* i: 7 bytes date */
+-#define SMU_CMD_RTC_GET_PWRUP_TIMER 0x01 /* o: 7 bytes date */
+-#define SMU_CMD_RTC_STOP_PWRUP_TIMER 0x02
+-#define SMU_CMD_RTC_SET_PRAM_BYTE_ACC 0x20 /* i: 1 byte (address?) */
+-#define SMU_CMD_RTC_SET_PRAM_AUTOINC 0x21 /* i: 1 byte (data?) */
+-#define SMU_CMD_RTC_SET_PRAM_LO_BYTES 0x22 /* i: 10 bytes */
+-#define SMU_CMD_RTC_SET_PRAM_HI_BYTES 0x23 /* i: 10 bytes */
+-#define SMU_CMD_RTC_GET_PRAM_BYTE 0x28 /* i: 1 bytes (address?) */
+-#define SMU_CMD_RTC_GET_PRAM_LO_BYTES 0x29 /* o: 10 bytes */
+-#define SMU_CMD_RTC_GET_PRAM_HI_BYTES 0x2a /* o: 10 bytes */
+-#define SMU_CMD_RTC_SET_DATETIME 0x80 /* i: 7 bytes date */
+-#define SMU_CMD_RTC_GET_DATETIME 0x81 /* o: 7 bytes date */
+-
+- /*
+- * i2c commands
+- *
+- * To issue an i2c command, first is to send a parameter block to the
+- * the SMU. This is a command of type 0x9a with 9 bytes of header
+- * eventually followed by data for a write:
+- *
+- * 0: bus number (from device-tree usually, SMU has lots of busses !)
+- * 1: transfer type/format (see below)
+- * 2: device address. For combined and combined4 type transfers, this
+- * is the "write" version of the address (bit 0x01 cleared)
+- * 3: subaddress length (0..3)
+- * 4: subaddress byte 0 (or only byte for subaddress length 1)
+- * 5: subaddress byte 1
+- * 6: subaddress byte 2
+- * 7: combined address (device address for combined mode data phase)
+- * 8: data length
+- *
+- * The transfer types are the same good old Apple ones it seems,
+- * that is:
+- * - 0x00: Simple transfer
+- * - 0x01: Subaddress transfer (addr write + data tx, no restart)
+- * - 0x02: Combined transfer (addr write + restart + data tx)
+- *
+- * This is then followed by actual data for a write.
+- *
+- * At this point, the OF driver seems to have a limitation on transfer
+- * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know
+- * wether this is just an OF limit due to some temporary buffer size
+- * or if this is an SMU imposed limit. This driver has the same limitation
+- * for now as I use a 0x10 bytes temporary buffer as well
+- *
+- * Once that is completed, a response is expected from the SMU. This is
+- * obtained via a command of type 0x9a with a length of 1 byte containing
+- * 0 as the data byte. OF also fills the rest of the data buffer with 0xff's
+- * though I can't tell yet if this is actually necessary. Once this command
+- * is complete, at this point, all I can tell is what OF does. OF tests
+- * byte 0 of the reply:
+- * - on read, 0xfe or 0xfc : bus is busy, wait (see below) or nak ?
+- * - on read, 0x00 or 0x01 : reply is in buffer (after the byte 0)
+- * - on write, < 0 -> failure (immediate exit)
+- * - else, OF just exists (without error, weird)
+- *
+- * So on read, there is this wait-for-busy thing when getting a 0xfc or
+- * 0xfe result. OF does a loop of up to 64 retries, waiting 20ms and
+- * doing the above again until either the retries expire or the result
+- * is no longer 0xfe or 0xfc
+- *
+- * The Darwin I2C driver is less subtle though. On any non-success status
+- * from the response command, it waits 5ms and tries again up to 20 times,
+- * it doesn't differenciate between fatal errors or "busy" status.
+- *
+- * This driver provides an asynchronous paramblock based i2c command
+- * interface to be used either directly by low level code or by a higher
+- * level driver interfacing to the linux i2c layer. The current
+- * implementation of this relies on working timers & timer interrupts
+- * though, so be careful of calling context for now. This may be "fixed"
+- * in the future by adding a polling facility.
+- */
+-#define SMU_CMD_I2C_COMMAND 0x9a
+- /* transfer types */
+-#define SMU_I2C_TRANSFER_SIMPLE 0x00
+-#define SMU_I2C_TRANSFER_STDSUB 0x01
+-#define SMU_I2C_TRANSFER_COMBINED 0x02
+-
+-/*
+- * Power supply control
+- *
+- * The "sub" command is an ASCII string in the data, the
+- * data lenght is that of the string.
+- *
+- * The VSLEW command can be used to get or set the voltage slewing.
+- * - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
+- * reply at data offset 6, 7 and 8.
+- * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is
+- * used to set the voltage slewing point. The SMU replies with "DONE"
+- * I yet have to figure out their exact meaning of those 3 bytes in
+- * both cases.
+- *
+- */
+-#define SMU_CMD_POWER_COMMAND 0xaa
+-#define SMU_CMD_POWER_RESTART "RESTART"
+-#define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN"
+-#define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW"
+-
+-/* Misc commands
+- *
+- * This command seem to be a grab bag of various things
+- */
+-#define SMU_CMD_MISC_df_COMMAND 0xdf
+-#define SMU_CMD_MISC_df_SET_DISPLAY_LIT 0x02 /* i: 1 byte */
+-#define SMU_CMD_MISC_df_NMI_OPTION 0x04
+-
+-/*
+- * Version info commands
+- *
+- * I haven't quite tried to figure out how these work
+- */
+-#define SMU_CMD_VERSION_COMMAND 0xea
+-
+-
+-/*
+- * Misc commands
+- *
+- * This command seem to be a grab bag of various things
+- */
+-#define SMU_CMD_MISC_ee_COMMAND 0xee
+-#define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02
+-#define SMU_CMD_MISC_ee_LEDS_CTRL 0x04 /* i: 00 (00,01) [00] */
+-#define SMU_CMD_MISC_ee_GET_DATA 0x05 /* i: 00 , o: ?? */
+-
+-
+-
+-/*
+- * - Kernel side interface -
+- */
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * Asynchronous SMU commands
+- *
+- * Fill up this structure and submit it via smu_queue_command(),
+- * and get notified by the optional done() callback, or because
+- * status becomes != 1
+- */
+-
+-struct smu_cmd;
+-
+-struct smu_cmd
+-{
+- /* public */
+- u8 cmd; /* command */
+- int data_len; /* data len */
+- int reply_len; /* reply len */
+- void *data_buf; /* data buffer */
+- void *reply_buf; /* reply buffer */
+- int status; /* command status */
+- void (*done)(struct smu_cmd *cmd, void *misc);
+- void *misc;
+-
+- /* private */
+- struct list_head link;
+-};
+-
+-/*
+- * Queues an SMU command, all fields have to be initialized
+- */
+-extern int smu_queue_cmd(struct smu_cmd *cmd);
+-
+-/*
+- * Simple command wrapper. This structure embeds a small buffer
+- * to ease sending simple SMU commands from the stack
+- */
+-struct smu_simple_cmd
+-{
+- struct smu_cmd cmd;
+- u8 buffer[16];
+-};
+-
+-/*
+- * Queues a simple command. All fields will be initialized by that
+- * function
+- */
+-extern int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
+- unsigned int data_len,
+- void (*done)(struct smu_cmd *cmd, void *misc),
+- void *misc,
+- ...);
+-
+-/*
+- * Completion helper. Pass it to smu_queue_simple or as 'done'
+- * member to smu_queue_cmd, it will call complete() on the struct
+- * completion passed in the "misc" argument
+- */
+-extern void smu_done_complete(struct smu_cmd *cmd, void *misc);
+-
+-/*
+- * Synchronous helpers. Will spin-wait for completion of a command
+- */
+-extern void smu_spinwait_cmd(struct smu_cmd *cmd);
+-
+-static inline void smu_spinwait_simple(struct smu_simple_cmd *scmd)
+-{
+- smu_spinwait_cmd(&scmd->cmd);
+-}
+-
+-/*
+- * Poll routine to call if blocked with irqs off
+- */
+-extern void smu_poll(void);
+-
+-
+-/*
+- * Init routine, presence check....
+- */
+-extern int smu_init(void);
+-extern int smu_present(void);
+-struct of_device;
+-extern struct of_device *smu_get_ofdev(void);
+-
+-
+-/*
+- * Common command wrappers
+- */
+-extern void smu_shutdown(void);
+-extern void smu_restart(void);
+-struct rtc_time;
+-extern int smu_get_rtc_time(struct rtc_time *time, int spinwait);
+-extern int smu_set_rtc_time(struct rtc_time *time, int spinwait);
+-
+-/*
+- * SMU command buffer absolute address, exported by pmac_setup,
+- * this is allocated very early during boot.
+- */
+-extern unsigned long smu_cmdbuf_abs;
+-
+-
+-/*
+- * Kenrel asynchronous i2c interface
+- */
+-
+-/* SMU i2c header, exactly matches i2c header on wire */
+-struct smu_i2c_param
+-{
+- u8 bus; /* SMU bus ID (from device tree) */
+- u8 type; /* i2c transfer type */
+- u8 devaddr; /* device address (includes direction) */
+- u8 sublen; /* subaddress length */
+- u8 subaddr[3]; /* subaddress */
+- u8 caddr; /* combined address, filled by SMU driver */
+- u8 datalen; /* length of transfer */
+- u8 data[7]; /* data */
+-};
+-
+-#define SMU_I2C_READ_MAX 0x0d
+-#define SMU_I2C_WRITE_MAX 0x05
+-
+-struct smu_i2c_cmd
+-{
+- /* public */
+- struct smu_i2c_param info;
+- void (*done)(struct smu_i2c_cmd *cmd, void *misc);
+- void *misc;
+- int status; /* 1 = pending, 0 = ok, <0 = fail */
+-
+- /* private */
+- struct smu_cmd scmd;
+- int read;
+- int stage;
+- int retries;
+- u8 pdata[0x10];
+- struct list_head link;
+-};
+-
+-/*
+- * Call this to queue an i2c command to the SMU. You must fill info,
+- * including info.data for a write, done and misc.
+- * For now, no polling interface is provided so you have to use completion
+- * callback.
+- */
+-extern int smu_queue_i2c(struct smu_i2c_cmd *cmd);
+-
+-
+-#endif /* __KERNEL__ */
+-
+-/*
+- * - Userland interface -
+- */
+-
+-/*
+- * A given instance of the device can be configured for 2 different
+- * things at the moment:
+- *
+- * - sending SMU commands (default at open() time)
+- * - receiving SMU events (not yet implemented)
+- *
+- * Commands are written with write() of a command block. They can be
+- * "driver" commands (for example to switch to event reception mode)
+- * or real SMU commands. They are made of a header followed by command
+- * data if any.
+- *
+- * For SMU commands (not for driver commands), you can then read() back
+- * a reply. The reader will be blocked or not depending on how the device
+- * file is opened. poll() isn't implemented yet. The reply will consist
+- * of a header as well, followed by the reply data if any. You should
+- * always provide a buffer large enough for the maximum reply data, I
+- * recommand one page.
+- *
+- * It is illegal to send SMU commands through a file descriptor configured
+- * for events reception
+- *
+- */
+-struct smu_user_cmd_hdr
+-{
+- __u32 cmdtype;
+-#define SMU_CMDTYPE_SMU 0 /* SMU command */
+-#define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */
+-
+- __u8 cmd; /* SMU command byte */
+- __u32 data_len; /* Lenght of data following */
+-};
+-
+-struct smu_user_reply_hdr
+-{
+- __u32 status; /* Command status */
+- __u32 reply_len; /* Lenght of data follwing */
+-};
+-
+-#endif /* _SMU_H */
+diff --git a/include/asm-ppc64/spinlock_types.h b/include/asm-ppc64/spinlock_types.h
+deleted file mode 100644
+--- a/include/asm-ppc64/spinlock_types.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#ifndef __ASM_SPINLOCK_TYPES_H
+-#define __ASM_SPINLOCK_TYPES_H
+-
+-#ifndef __LINUX_SPINLOCK_TYPES_H
+-# error "please don't include this file directly"
+-#endif
+-
+-typedef struct {
+- volatile unsigned int slock;
+-} raw_spinlock_t;
+-
+-#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+-
+-typedef struct {
+- volatile signed int lock;
+-} raw_rwlock_t;
+-
+-#define __RAW_RW_LOCK_UNLOCKED { 0 }
+-
+-#endif
+diff --git a/include/asm-ppc64/sstep.h b/include/asm-ppc64/sstep.h
+deleted file mode 100644
+--- a/include/asm-ppc64/sstep.h
++++ /dev/null
+@@ -1,24 +0,0 @@
+-/*
+- * Copyright (C) 2004 Paul Mackerras <paulus at au.ibm.com>, IBM
+- *
+- * 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.
+- */
+-
+-struct pt_regs;
+-
+-/*
+- * We don't allow single-stepping an mtmsrd that would clear
+- * MSR_RI, since that would make the exception unrecoverable.
+- * Since we need to single-step to proceed from a breakpoint,
+- * we don't allow putting a breakpoint on an mtmsrd instruction.
+- * Similarly we don't allow breakpoints on rfid instructions.
+- * These macros tell us if an instruction is a mtmsrd or rfid.
+- */
+-#define IS_MTMSRD(instr) (((instr) & 0xfc0007fe) == 0x7c000164)
+-#define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024)
+-
+-/* Emulate instructions that cause a transfer of control. */
+-extern int emulate_step(struct pt_regs *regs, unsigned int instr);
+diff --git a/include/asm-ppc64/statfs.h b/include/asm-ppc64/statfs.h
+deleted file mode 100644
+--- a/include/asm-ppc64/statfs.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-#ifndef _PPC64_STATFS_H
+-#define _PPC64_STATFS_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 __KERNEL_STRICT_NAMES
+-#include <linux/types.h>
+-typedef __kernel_fsid_t fsid_t;
+-#endif
+-
+-/*
+- * We're already 64-bit, so duplicate the definition
+- */
+-struct statfs {
+- long f_type;
+- long f_bsize;
+- long f_blocks;
+- long f_bfree;
+- long f_bavail;
+- long f_files;
+- long f_ffree;
+- __kernel_fsid_t f_fsid;
+- long f_namelen;
+- long f_frsize;
+- long f_spare[5];
+-};
+-
+-struct statfs64 {
+- long f_type;
+- long f_bsize;
+- long f_blocks;
+- long f_bfree;
+- long f_bavail;
+- long f_files;
+- long f_ffree;
+- __kernel_fsid_t f_fsid;
+- long f_namelen;
+- long f_frsize;
+- long f_spare[5];
+-};
+-
+-struct compat_statfs64 {
+- __u32 f_type;
+- __u32 f_bsize;
+- __u64 f_blocks;
+- __u64 f_bfree;
+- __u64 f_bavail;
+- __u64 f_files;
+- __u64 f_ffree;
+- __kernel_fsid_t f_fsid;
+- __u32 f_namelen;
+- __u32 f_frsize;
+- __u32 f_spare[5];
+-};
+-
+-#endif /* _PPC64_STATFS_H */
+diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
+--- a/include/asm-ppc64/system.h
++++ b/include/asm-ppc64/system.h
+@@ -13,7 +13,7 @@
+ #include <asm/page.h>
+ #include <asm/processor.h>
+ #include <asm/hw_irq.h>
+-#include <asm/memory.h>
++#include <asm/synch.h>
+
+ /*
+ * Memory barrier.
+@@ -48,7 +48,7 @@
+ #ifdef CONFIG_SMP
+ #define smp_mb() mb()
+ #define smp_rmb() rmb()
+-#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory")
++#define smp_wmb() eieio()
+ #define smp_read_barrier_depends() read_barrier_depends()
+ #else
+ #define smp_mb() __asm__ __volatile__("": : :"memory")
+@@ -120,8 +120,8 @@ extern void giveup_altivec(struct task_s
+ extern void disable_kernel_altivec(void);
+ extern void enable_kernel_altivec(void);
+ extern int emulate_altivec(struct pt_regs *);
+-extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
+-extern void cvt_df(double *from, float *to, unsigned long *fpscr);
++extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
++extern void cvt_df(double *from, float *to, struct thread_struct *thread);
+
+ #ifdef CONFIG_ALTIVEC
+ extern void flush_altivec_to_thread(struct task_struct *);
+@@ -131,7 +131,12 @@ static inline void flush_altivec_to_thre
+ }
+ #endif
+
++static inline void flush_spe_to_thread(struct task_struct *t)
++{
++}
++
+ extern int mem_init_done; /* set on boot once kmalloc can be called */
++extern unsigned long memory_limit;
+
+ /* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */
+ extern unsigned char e2a(unsigned char);
+@@ -144,12 +149,7 @@ struct thread_struct;
+ extern struct task_struct * _switch(struct thread_struct *prev,
+ struct thread_struct *next);
+
+-static inline int __is_processor(unsigned long pv)
+-{
+- unsigned long pvr;
+- asm("mfspr %0, 0x11F" : "=r" (pvr));
+- return(PVR_VER(pvr) == pv);
+-}
++extern int powersave_nap; /* set if nap mode can be used in idle loop */
+
+ /*
+ * Atomic exchange
+diff --git a/include/asm-ppc64/tce.h b/include/asm-ppc64/tce.h
+new file mode 100644
+--- /dev/null
++++ b/include/asm-ppc64/tce.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
++ * Rewrite, cleanup:
++ * Copyright (C) 2004 Olof Johansson <olof at austin.ibm.com>, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _ASM_TCE_H
++#define _ASM_TCE_H
++
++/*
++ * Tces come in two formats, one for the virtual bus and a different
++ * format for PCI
++ */
++#define TCE_VB 0
++#define TCE_PCI 1
++
++/* TCE page size is 4096 bytes (1 << 12) */
++
++#define TCE_SHIFT 12
++#define TCE_PAGE_SIZE (1 << TCE_SHIFT)
++#define TCE_PAGE_FACTOR (PAGE_SHIFT - TCE_SHIFT)
++
++
++/* tce_entry
++ * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's
++ * abstracted so layout is irrelevant.
++ */
++union tce_entry {
++ unsigned long te_word;
++ struct {
++ unsigned int tb_cacheBits :6; /* Cache hash bits - not used */
++ unsigned int tb_rsvd :6;
++ unsigned long tb_rpn :40; /* Real page number */
++ unsigned int tb_valid :1; /* Tce is valid (vb only) */
++ unsigned int tb_allio :1; /* Tce is valid for all lps (vb only) */
++ unsigned int tb_lpindex :8; /* LpIndex for user of TCE (vb only) */
++ unsigned int tb_pciwr :1; /* Write allowed (pci only) */
++ unsigned int tb_rdwr :1; /* Read allowed (pci), Write allowed (vb) */
++ } te_bits;
++#define te_cacheBits te_bits.tb_cacheBits
++#define te_rpn te_bits.tb_rpn
++#define te_valid te_bits.tb_valid
++#define te_allio te_bits.tb_allio
++#define te_lpindex te_bits.tb_lpindex
++#define te_pciwr te_bits.tb_pciwr
++#define te_rdwr te_bits.tb_rdwr
++};
++
++
++#endif
+diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
+deleted file mode 100644
+--- a/include/asm-ppc64/thread_info.h
++++ /dev/null
+@@ -1,125 +0,0 @@
+-/* thread_info.h: PPC low-level thread information
+- * adapted from the i386 version by Paul Mackerras
+- *
+- * Copyright (C) 2002 David Howells (dhowells at redhat.com)
+- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+- */
+-
+-#ifndef _ASM_THREAD_INFO_H
+-#define _ASM_THREAD_INFO_H
+-
+-#ifdef __KERNEL__
+-
+-#ifndef __ASSEMBLY__
+-#include <linux/config.h>
+-#include <linux/cache.h>
+-#include <asm/processor.h>
+-#include <asm/page.h>
+-#include <linux/stringify.h>
+-
+-/*
+- * low level task data.
+- */
+-struct thread_info {
+- struct task_struct *task; /* main task structure */
+- struct exec_domain *exec_domain; /* execution domain */
+- int cpu; /* cpu we're on */
+- int preempt_count; /* 0 => preemptable, <0 => BUG */
+- struct restart_block restart_block;
+- /* set by force_successful_syscall_return */
+- unsigned char syscall_noerror;
+- /* low level flags - has atomic operations done on it */
+- unsigned long flags ____cacheline_aligned_in_smp;
+-};
+-
+-/*
+- * macros/functions for gaining access to the thread information structure
+- *
+- * preempt_count needs to be 1 initially, until the scheduler is functional.
+- */
+-#define INIT_THREAD_INFO(tsk) \
+-{ \
+- .task = &tsk, \
+- .exec_domain = &default_exec_domain, \
+- .cpu = 0, \
+- .preempt_count = 1, \
+- .restart_block = { \
+- .fn = do_no_restart_syscall, \
+- }, \
+- .flags = 0, \
+-}
+-
+-#define init_thread_info (init_thread_union.thread_info)
+-#define init_stack (init_thread_union.stack)
+-
+-/* thread information allocation */
+-
+-#define THREAD_ORDER 2
+-#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+-#define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER)
+-#ifdef CONFIG_DEBUG_STACK_USAGE
+-#define alloc_thread_info(tsk) \
+- ({ \
+- struct thread_info *ret; \
+- \
+- ret = kmalloc(THREAD_SIZE, GFP_KERNEL); \
+- if (ret) \
+- memset(ret, 0, THREAD_SIZE); \
+- ret; \
+- })
+-#else
+-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+-#endif
+-#define free_thread_info(ti) kfree(ti)
+-#define get_thread_info(ti) get_task_struct((ti)->task)
+-#define put_thread_info(ti) put_task_struct((ti)->task)
+-
+-/* how to get the thread information struct from C */
+-static inline struct thread_info *current_thread_info(void)
+-{
+- struct thread_info *ti;
+- __asm__("clrrdi %0,1,%1" : "=r"(ti) : "i" (THREAD_SHIFT));
+- return ti;
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#define PREEMPT_ACTIVE 0x10000000
+-
+-/*
+- * thread information flag bit numbers
+- */
+-#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+-#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+-#define TIF_SIGPENDING 2 /* signal pending */
+-#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+-#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
+- TIF_NEED_RESCHED */
+-#define TIF_32BIT 5 /* 32 bit binary */
+-/* #define SPARE 6 */
+-#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */
+-#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
+-#define TIF_SINGLESTEP 9 /* singlestepping active */
+-#define TIF_MEMDIE 10
+-#define TIF_SECCOMP 11 /* secure computing */
+-
+-/* as above, but as bit values */
+-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+-#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+-#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+-#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+-#define _TIF_32BIT (1<<TIF_32BIT)
+-/* #define _SPARE (1<<SPARE) */
+-#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
+-#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
+-#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+-#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
+-
+-#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
+- _TIF_NEED_RESCHED)
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _ASM_THREAD_INFO_H */
+diff --git a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h
+deleted file mode 100644
+--- a/include/asm-ppc64/time.h
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/*
+- * Common time prototypes and such for all ppc machines.
+- *
+- * Written by Cort Dougan (cort at cs.nmt.edu) to merge
+- * Paul Mackerras' version and mine for PReP and Pmac.
+- *
+- * 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 __PPC64_TIME_H
+-#define __PPC64_TIME_H
+-
+-#ifdef __KERNEL__
+-#include <linux/config.h>
+-#include <linux/types.h>
+-#include <linux/mc146818rtc.h>
+-
+-#include <asm/processor.h>
+-#include <asm/paca.h>
+-#include <asm/iSeries/HvCall.h>
+-
+-/* time.c */
+-extern unsigned long tb_ticks_per_jiffy;
+-extern unsigned long tb_ticks_per_usec;
+-extern unsigned long tb_ticks_per_sec;
+-extern unsigned long tb_to_xs;
+-extern unsigned tb_to_us;
+-extern unsigned long tb_last_stamp;
+-
+-struct rtc_time;
+-extern void to_tm(int tim, struct rtc_time * tm);
+-extern time_t last_rtc_update;
+-
+-void generic_calibrate_decr(void);
+-void setup_default_decr(void);
+-
+-/* Some sane defaults: 125 MHz timebase, 1GHz processor */
+-extern unsigned long ppc_proc_freq;
+-#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
+-extern unsigned long ppc_tb_freq;
+-#define DEFAULT_TB_FREQ 125000000UL
+-
+-/*
+- * By putting all of this stuff into a single struct we
+- * reduce the number of cache lines touched by do_gettimeofday.
+- * Both by collecting all of the data in one cache line and
+- * by touching only one TOC entry
+- */
+-struct gettimeofday_vars {
+- unsigned long tb_to_xs;
+- unsigned long stamp_xsec;
+- unsigned long tb_orig_stamp;
+-};
+-
+-struct gettimeofday_struct {
+- unsigned long tb_ticks_per_sec;
+- struct gettimeofday_vars vars[2];
+- struct gettimeofday_vars * volatile varp;
+- unsigned var_idx;
+- unsigned tb_to_us;
+-};
+-
+-struct div_result {
+- unsigned long result_high;
+- unsigned long result_low;
+-};
+-
+-int via_calibrate_decr(void);
+-
+-static __inline__ unsigned long get_tb(void)
+-{
+- return mftb();
+-}
+-
+-/* Accessor functions for the decrementer register. */
+-static __inline__ unsigned int get_dec(void)
+-{
+- return (mfspr(SPRN_DEC));
+-}
+-
+-static __inline__ void set_dec(int val)
+-{
+-#ifdef CONFIG_PPC_ISERIES
+- struct paca_struct *lpaca = get_paca();
+- int cur_dec;
+-
+- if (lpaca->lppaca.shared_proc) {
+- lpaca->lppaca.virtual_decr = val;
+- cur_dec = get_dec();
+- if (cur_dec > val)
+- HvCall_setVirtualDecr();
+- } else
+-#endif
+- mtspr(SPRN_DEC, val);
+-}
+-
+-static inline unsigned long tb_ticks_since(unsigned long tstamp)
+-{
+- return get_tb() - tstamp;
+-}
+-
+-#define mulhwu(x,y) \
+-({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
+-#define mulhdu(x,y) \
+-({unsigned long z; asm ("mulhdu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
+-
+-
+-unsigned mulhwu_scale_factor(unsigned, unsigned);
+-void div128_by_32( unsigned long dividend_high, unsigned long dividend_low,
+- unsigned divisor, struct div_result *dr );
+-
+-/* Used to store Processor Utilization register (purr) values */
+-
+-struct cpu_usage {
+- u64 current_tb; /* Holds the current purr register values */
+-};
+-
+-DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
+-
+-#endif /* __KERNEL__ */
+-#endif /* __PPC64_TIME_H */
+diff --git a/include/asm-ppc64/tlbflush.h b/include/asm-ppc64/tlbflush.h
+--- a/include/asm-ppc64/tlbflush.h
++++ b/include/asm-ppc64/tlbflush.h
+@@ -20,10 +20,8 @@
+ struct mm_struct;
+ struct ppc64_tlb_batch {
+ unsigned long index;
+- unsigned long context;
+ struct mm_struct *mm;
+ pte_t pte[PPC64_TLB_BATCH_NR];
+- unsigned long addr[PPC64_TLB_BATCH_NR];
+ unsigned long vaddr[PPC64_TLB_BATCH_NR];
+ unsigned int large;
+ };
+@@ -48,8 +46,7 @@ static inline void flush_tlb_pending(voi
+ #define flush_tlb_kernel_range(start, end) flush_tlb_pending()
+ #define flush_tlb_pgtables(mm, start, end) do { } while (0)
+
+-extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
+- int local);
+-void flush_hash_range(unsigned long context, unsigned long number, int local);
++extern void flush_hash_page(unsigned long va, pte_t pte, int local);
++void flush_hash_range(unsigned long number, int local);
+
+ #endif /* _PPC64_TLBFLUSH_H */
+diff --git a/include/asm-ppc64/types.h b/include/asm-ppc64/types.h
+deleted file mode 100644
+--- a/include/asm-ppc64/types.h
++++ /dev/null
+@@ -1,79 +0,0 @@
+-#ifndef _PPC64_TYPES_H
+-#define _PPC64_TYPES_H
+-
+-#ifndef __ASSEMBLY__
+-
+-/*
+- * This file is never included by application software unless
+- * explicitly requested (e.g., via linux/types.h) in which case the
+- * application is Linux specific so (user-) name space pollution is
+- * not a major issue. However, for interoperability, libraries still
+- * need to be careful to avoid a name clashes.
+- *
+- * 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.
+- */
+-
+-typedef unsigned int umode_t;
+-
+-/*
+- * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+- * header files exported to user space
+- */
+-
+-typedef __signed__ char __s8;
+-typedef unsigned char __u8;
+-
+-typedef __signed__ short __s16;
+-typedef unsigned short __u16;
+-
+-typedef __signed__ int __s32;
+-typedef unsigned int __u32;
+-
+-typedef __signed__ long __s64;
+-typedef unsigned long __u64;
+-
+-typedef struct {
+- __u32 u[4];
+-} __attribute((aligned(16))) __vector128;
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#ifdef __KERNEL__
+-/*
+- * These aren't exported outside the kernel to avoid name space clashes
+- */
+-#define BITS_PER_LONG 64
+-
+-#ifndef __ASSEMBLY__
+-
+-typedef signed char s8;
+-typedef unsigned char u8;
+-
+-typedef signed short s16;
+-typedef unsigned short u16;
+-
+-typedef signed int s32;
+-typedef unsigned int u32;
+-
+-typedef signed long s64;
+-typedef unsigned long u64;
+-
+-typedef __vector128 vector128;
+-
+-typedef u32 dma_addr_t;
+-typedef u64 dma64_addr_t;
+-
+-typedef struct {
+- unsigned long entry;
+- unsigned long toc;
+- unsigned long env;
+-} func_descr_t;
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _PPC64_TYPES_H */
+diff --git a/include/asm-ppc64/udbg.h b/include/asm-ppc64/udbg.h
+--- a/include/asm-ppc64/udbg.h
++++ b/include/asm-ppc64/udbg.h
+@@ -28,4 +28,7 @@ extern unsigned long udbg_ifdebug(unsign
+ extern void __init ppcdbg_initialize(void);
+
+ extern void udbg_init_uart(void __iomem *comport, unsigned int speed);
++
++struct device_node;
++extern void udbg_init_scc(struct device_node *np);
+ #endif
+diff --git a/include/asm-ppc64/uninorth.h b/include/asm-ppc64/uninorth.h
+deleted file mode 100644
+--- a/include/asm-ppc64/uninorth.h
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#include <asm-ppc/uninorth.h>
+-
+diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
+deleted file mode 100644
+--- a/include/asm-ppc64/unistd.h
++++ /dev/null
+@@ -1,487 +0,0 @@
+-#ifndef _ASM_PPC_UNISTD_H_
+-#define _ASM_PPC_UNISTD_H_
+-
+-/*
+- * This file contains the system call numbers.
+- *
+- * 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.
+- */
+-
+-#define __NR_restart_syscall 0
+-#define __NR_exit 1
+-#define __NR_fork 2
+-#define __NR_read 3
+-#define __NR_write 4
+-#define __NR_open 5
+-#define __NR_close 6
+-#define __NR_waitpid 7
+-#define __NR_creat 8
+-#define __NR_link 9
+-#define __NR_unlink 10
+-#define __NR_execve 11
+-#define __NR_chdir 12
+-#define __NR_time 13
+-#define __NR_mknod 14
+-#define __NR_chmod 15
+-#define __NR_lchown 16
+-#define __NR_break 17
+-#define __NR_oldstat 18
+-#define __NR_lseek 19
+-#define __NR_getpid 20
+-#define __NR_mount 21
+-#define __NR_umount 22
+-#define __NR_setuid 23
+-#define __NR_getuid 24
+-#define __NR_stime 25
+-#define __NR_ptrace 26
+-#define __NR_alarm 27
+-#define __NR_oldfstat 28
+-#define __NR_pause 29
+-#define __NR_utime 30
+-#define __NR_stty 31
+-#define __NR_gtty 32
+-#define __NR_access 33
+-#define __NR_nice 34
+-#define __NR_ftime 35
+-#define __NR_sync 36
+-#define __NR_kill 37
+-#define __NR_rename 38
+-#define __NR_mkdir 39
+-#define __NR_rmdir 40
+-#define __NR_dup 41
+-#define __NR_pipe 42
+-#define __NR_times 43
+-#define __NR_prof 44
+-#define __NR_brk 45
+-#define __NR_setgid 46
+-#define __NR_getgid 47
+-#define __NR_signal 48
+-#define __NR_geteuid 49
+-#define __NR_getegid 50
+-#define __NR_acct 51
+-#define __NR_umount2 52
+-#define __NR_lock 53
+-#define __NR_ioctl 54
+-#define __NR_fcntl 55
+-#define __NR_mpx 56
+-#define __NR_setpgid 57
+-#define __NR_ulimit 58
+-#define __NR_oldolduname 59
+-#define __NR_umask 60
+-#define __NR_chroot 61
+-#define __NR_ustat 62
+-#define __NR_dup2 63
+-#define __NR_getppid 64
+-#define __NR_getpgrp 65
+-#define __NR_setsid 66
+-#define __NR_sigaction 67
+-#define __NR_sgetmask 68
+-#define __NR_ssetmask 69
+-#define __NR_setreuid 70
+-#define __NR_setregid 71
+-#define __NR_sigsuspend 72
+-#define __NR_sigpending 73
+-#define __NR_sethostname 74
+-#define __NR_setrlimit 75
+-#define __NR_getrlimit 76
+-#define __NR_getrusage 77
+-#define __NR_gettimeofday 78
+-#define __NR_settimeofday 79
+-#define __NR_getgroups 80
+-#define __NR_setgroups 81
+-#define __NR_select 82
+-#define __NR_symlink 83
+-#define __NR_oldlstat 84
+-#define __NR_readlink 85
+-#define __NR_uselib 86
+-#define __NR_swapon 87
+-#define __NR_reboot 88
+-#define __NR_readdir 89
+-#define __NR_mmap 90
+-#define __NR_munmap 91
+-#define __NR_truncate 92
+-#define __NR_ftruncate 93
+-#define __NR_fchmod 94
+-#define __NR_fchown 95
+-#define __NR_getpriority 96
+-#define __NR_setpriority 97
+-#define __NR_profil 98
+-#define __NR_statfs 99
+-#define __NR_fstatfs 100
+-#define __NR_ioperm 101
+-#define __NR_socketcall 102
+-#define __NR_syslog 103
+-#define __NR_setitimer 104
+-#define __NR_getitimer 105
+-#define __NR_stat 106
+-#define __NR_lstat 107
+-#define __NR_fstat 108
+-#define __NR_olduname 109
+-#define __NR_iopl 110
+-#define __NR_vhangup 111
+-#define __NR_idle 112
+-#define __NR_vm86 113
+-#define __NR_wait4 114
+-#define __NR_swapoff 115
+-#define __NR_sysinfo 116
+-#define __NR_ipc 117
+-#define __NR_fsync 118
+-#define __NR_sigreturn 119
+-#define __NR_clone 120
+-#define __NR_setdomainname 121
+-#define __NR_uname 122
+-#define __NR_modify_ldt 123
+-#define __NR_adjtimex 124
+-#define __NR_mprotect 125
+-#define __NR_sigprocmask 126
+-#define __NR_create_module 127
+-#define __NR_init_module 128
+-#define __NR_delete_module 129
+-#define __NR_get_kernel_syms 130
+-#define __NR_quotactl 131
+-#define __NR_getpgid 132
+-#define __NR_fchdir 133
+-#define __NR_bdflush 134
+-#define __NR_sysfs 135
+-#define __NR_personality 136
+-#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
+-#define __NR_setfsuid 138
+-#define __NR_setfsgid 139
+-#define __NR__llseek 140
+-#define __NR_getdents 141
+-#define __NR__newselect 142
+-#define __NR_flock 143
+-#define __NR_msync 144
+-#define __NR_readv 145
+-#define __NR_writev 146
+-#define __NR_getsid 147
+-#define __NR_fdatasync 148
+-#define __NR__sysctl 149
+-#define __NR_mlock 150
+-#define __NR_munlock 151
+-#define __NR_mlockall 152
+-#define __NR_munlockall 153
+-#define __NR_sched_setparam 154
+-#define __NR_sched_getparam 155
+-#define __NR_sched_setscheduler 156
+-#define __NR_sched_getscheduler 157
+-#define __NR_sched_yield 158
+-#define __NR_sched_get_priority_max 159
+-#define __NR_sched_get_priority_min 160
+-#define __NR_sched_rr_get_interval 161
+-#define __NR_nanosleep 162
+-#define __NR_mremap 163
+-#define __NR_setresuid 164
+-#define __NR_getresuid 165
+-#define __NR_query_module 166
+-#define __NR_poll 167
+-#define __NR_nfsservctl 168
+-#define __NR_setresgid 169
+-#define __NR_getresgid 170
+-#define __NR_prctl 171
+-#define __NR_rt_sigreturn 172
+-#define __NR_rt_sigaction 173
+-#define __NR_rt_sigprocmask 174
+-#define __NR_rt_sigpending 175
+-#define __NR_rt_sigtimedwait 176
+-#define __NR_rt_sigqueueinfo 177
+-#define __NR_rt_sigsuspend 178
+-#define __NR_pread64 179
+-#define __NR_pwrite64 180
+-#define __NR_chown 181
+-#define __NR_getcwd 182
+-#define __NR_capget 183
+-#define __NR_capset 184
+-#define __NR_sigaltstack 185
+-#define __NR_sendfile 186
+-#define __NR_getpmsg 187 /* some people actually want streams */
+-#define __NR_putpmsg 188 /* some people actually want streams */
+-#define __NR_vfork 189
+-#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */
+-#define __NR_readahead 191
+-/* #define __NR_mmap2 192 32bit only */
+-/* #define __NR_truncate64 193 32bit only */
+-/* #define __NR_ftruncate64 194 32bit only */
+-/* #define __NR_stat64 195 32bit only */
+-/* #define __NR_lstat64 196 32bit only */
+-/* #define __NR_fstat64 197 32bit only */
+-#define __NR_pciconfig_read 198
+-#define __NR_pciconfig_write 199
+-#define __NR_pciconfig_iobase 200
+-#define __NR_multiplexer 201
+-#define __NR_getdents64 202
+-#define __NR_pivot_root 203
+-/* #define __NR_fcntl64 204 32bit only */
+-#define __NR_madvise 205
+-#define __NR_mincore 206
+-#define __NR_gettid 207
+-#define __NR_tkill 208
+-#define __NR_setxattr 209
+-#define __NR_lsetxattr 210
+-#define __NR_fsetxattr 211
+-#define __NR_getxattr 212
+-#define __NR_lgetxattr 213
+-#define __NR_fgetxattr 214
+-#define __NR_listxattr 215
+-#define __NR_llistxattr 216
+-#define __NR_flistxattr 217
+-#define __NR_removexattr 218
+-#define __NR_lremovexattr 219
+-#define __NR_fremovexattr 220
+-#define __NR_futex 221
+-#define __NR_sched_setaffinity 222
+-#define __NR_sched_getaffinity 223
+-/* 224 currently unused */
+-#define __NR_tuxcall 225
+-/* #define __NR_sendfile64 226 32bit only */
+-#define __NR_io_setup 227
+-#define __NR_io_destroy 228
+-#define __NR_io_getevents 229
+-#define __NR_io_submit 230
+-#define __NR_io_cancel 231
+-#define __NR_set_tid_address 232
+-#define __NR_fadvise64 233
+-#define __NR_exit_group 234
+-#define __NR_lookup_dcookie 235
+-#define __NR_epoll_create 236
+-#define __NR_epoll_ctl 237
+-#define __NR_epoll_wait 238
+-#define __NR_remap_file_pages 239
+-#define __NR_timer_create 240
+-#define __NR_timer_settime 241
+-#define __NR_timer_gettime 242
+-#define __NR_timer_getoverrun 243
+-#define __NR_timer_delete 244
+-#define __NR_clock_settime 245
+-#define __NR_clock_gettime 246
+-#define __NR_clock_getres 247
+-#define __NR_clock_nanosleep 248
+-#define __NR_swapcontext 249
+-#define __NR_tgkill 250
+-#define __NR_utimes 251
+-#define __NR_statfs64 252
+-#define __NR_fstatfs64 253
+-/* #define __NR_fadvise64_64 254 32bit only */
+-#define __NR_rtas 255
+-/* Number 256 is reserved for sys_debug_setcontext */
+-/* Number 257 is reserved for vserver */
+-/* 258 currently unused */
+-#define __NR_mbind 259
+-#define __NR_get_mempolicy 260
+-#define __NR_set_mempolicy 261
+-#define __NR_mq_open 262
+-#define __NR_mq_unlink 263
+-#define __NR_mq_timedsend 264
+-#define __NR_mq_timedreceive 265
+-#define __NR_mq_notify 266
+-#define __NR_mq_getsetattr 267
+-#define __NR_kexec_load 268
+-#define __NR_add_key 269
+-#define __NR_request_key 270
+-#define __NR_keyctl 271
+-#define __NR_waitid 272
+-#define __NR_ioprio_set 273
+-#define __NR_ioprio_get 274
+-#define __NR_inotify_init 275
+-#define __NR_inotify_add_watch 276
+-#define __NR_inotify_rm_watch 277
+-
+-#define __NR_syscalls 278
+-#ifdef __KERNEL__
+-#define NR_syscalls __NR_syscalls
+-#endif
+-
+-#ifndef __ASSEMBLY__
+-
+-/* On powerpc a system call basically clobbers the same registers like a
+- * function call, with the exception of LR (which is needed for the
+- * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
+- * an error return status).
+- */
+-
+-#define __syscall_nr(nr, type, name, args...) \
+- unsigned long __sc_ret, __sc_err; \
+- { \
+- register unsigned long __sc_0 __asm__ ("r0"); \
+- register unsigned long __sc_3 __asm__ ("r3"); \
+- register unsigned long __sc_4 __asm__ ("r4"); \
+- register unsigned long __sc_5 __asm__ ("r5"); \
+- register unsigned long __sc_6 __asm__ ("r6"); \
+- register unsigned long __sc_7 __asm__ ("r7"); \
+- register unsigned long __sc_8 __asm__ ("r8"); \
+- \
+- __sc_loadargs_##nr(name, args); \
+- __asm__ __volatile__ \
+- ("sc \n\t" \
+- "mfcr %0 " \
+- : "=&r" (__sc_0), \
+- "=&r" (__sc_3), "=&r" (__sc_4), \
+- "=&r" (__sc_5), "=&r" (__sc_6), \
+- "=&r" (__sc_7), "=&r" (__sc_8) \
+- : __sc_asm_input_##nr \
+- : "cr0", "ctr", "memory", \
+- "r9", "r10","r11", "r12"); \
+- __sc_ret = __sc_3; \
+- __sc_err = __sc_0; \
+- } \
+- if (__sc_err & 0x10000000) \
+- { \
+- errno = __sc_ret; \
+- __sc_ret = -1; \
+- } \
+- return (type) __sc_ret
+-
+-#define __sc_loadargs_0(name, dummy...) \
+- __sc_0 = __NR_##name
+-#define __sc_loadargs_1(name, arg1) \
+- __sc_loadargs_0(name); \
+- __sc_3 = (unsigned long) (arg1)
+-#define __sc_loadargs_2(name, arg1, arg2) \
+- __sc_loadargs_1(name, arg1); \
+- __sc_4 = (unsigned long) (arg2)
+-#define __sc_loadargs_3(name, arg1, arg2, arg3) \
+- __sc_loadargs_2(name, arg1, arg2); \
+- __sc_5 = (unsigned long) (arg3)
+-#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \
+- __sc_loadargs_3(name, arg1, arg2, arg3); \
+- __sc_6 = (unsigned long) (arg4)
+-#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \
+- __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \
+- __sc_7 = (unsigned long) (arg5)
+-#define __sc_loadargs_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
+- __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5); \
+- __sc_8 = (unsigned long) (arg6)
+-
+-#define __sc_asm_input_0 "0" (__sc_0)
+-#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
+-#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
+-#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
+-#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
+-#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
+-#define __sc_asm_input_6 __sc_asm_input_5, "6" (__sc_8)
+-
+-#define _syscall0(type,name) \
+-type name(void) \
+-{ \
+- __syscall_nr(0, type, name); \
+-}
+-
+-#define _syscall1(type,name,type1,arg1) \
+-type name(type1 arg1) \
+-{ \
+- __syscall_nr(1, type, name, arg1); \
+-}
+-
+-#define _syscall2(type,name,type1,arg1,type2,arg2) \
+-type name(type1 arg1, type2 arg2) \
+-{ \
+- __syscall_nr(2, type, name, arg1, arg2); \
+-}
+-
+-#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+-type name(type1 arg1, type2 arg2, type3 arg3) \
+-{ \
+- __syscall_nr(3, type, name, arg1, arg2, arg3); \
+-}
+-
+-#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+-{ \
+- __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \
+-}
+-
+-#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
+-{ \
+- __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \
+-}
+-#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
+-type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
+-{ \
+- __syscall_nr(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \
+-}
+-
+-#ifdef __KERNEL_SYSCALLS__
+-
+-/*
+- * Forking from kernel space will result in the child getting a new,
+- * empty kernel stack area. Thus the child cannot access automatic
+- * variables set in the parent unless they are in registers, and the
+- * procedure where the fork was done cannot return to its caller in
+- * the child.
+- */
+-
+-/*
+- * System call prototypes.
+- */
+-static inline _syscall3(int, execve, __const__ char *, file, char **, argv,
+- char **,envp)
+-
+-#endif /* __KERNEL_SYSCALLS__ */
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/types.h>
+-#include <linux/compiler.h>
+-#include <linux/linkage.h>
+-
+-#define __ARCH_WANT_IPC_PARSE_VERSION
+-#define __ARCH_WANT_OLD_READDIR
+-#define __ARCH_WANT_STAT64
+-#define __ARCH_WANT_SYS_ALARM
+-#define __ARCH_WANT_SYS_GETHOSTNAME
+-#define __ARCH_WANT_SYS_PAUSE
+-#define __ARCH_WANT_SYS_SGETMASK
+-#define __ARCH_WANT_SYS_SIGNAL
+-#define __ARCH_WANT_SYS_TIME
+-#define __ARCH_WANT_COMPAT_SYS_TIME
+-#define __ARCH_WANT_SYS_UTIME
+-#define __ARCH_WANT_SYS_WAITPID
+-#define __ARCH_WANT_SYS_SOCKETCALL
+-#define __ARCH_WANT_SYS_FADVISE64
+-#define __ARCH_WANT_SYS_GETPGRP
+-#define __ARCH_WANT_SYS_LLSEEK
+-#define __ARCH_WANT_SYS_NICE
+-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+-#define __ARCH_WANT_SYS_OLDUMOUNT
+-#define __ARCH_WANT_SYS_SIGPENDING
+-#define __ARCH_WANT_SYS_SIGPROCMASK
+-#define __ARCH_WANT_SYS_RT_SIGACTION
+-
+-unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot,
+- unsigned long flags, unsigned long fd, off_t offset);
+-struct pt_regs;
+-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+- unsigned long a3, unsigned long a4, unsigned long a5,
+- struct pt_regs *regs);
+-int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3,
+- unsigned long p4, unsigned long p5, unsigned long p6,
+- struct pt_regs *regs);
+-int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
+- unsigned long p4, unsigned long p5, unsigned long p6,
+- struct pt_regs *regs);
+-int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
+- 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);
+-
+-/*
+- * "Conditional" syscalls
+- *
+- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+- * but it doesn't work on all toolchains, so we just do it by hand
+- */
+-#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall")
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif /* _ASM_PPC_UNISTD_H_ */
+diff --git a/include/asm-ppc64/vga.h b/include/asm-ppc64/vga.h
+deleted file mode 100644
+--- a/include/asm-ppc64/vga.h
++++ /dev/null
+@@ -1,50 +0,0 @@
+-/*
+- * Access to VGA videoram
+- *
+- * (c) 1998 Martin Mares <mj at ucw.cz>
+- *
+- * 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_ASM_VGA_H_
+-#define _LINUX_ASM_VGA_H_
+-
+-#include <asm/io.h>
+-
+-#include <linux/config.h>
+-
+-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
+-
+-#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)
+-{
+- st_le16(addr, val);
+-}
+-
+-static inline u16 scr_readw(volatile const u16 *addr)
+-{
+- return ld_le16(addr);
+-}
+-
+-#define VT_BUF_HAVE_MEMCPYW
+-#define scr_memcpyw memcpy
+-
+-#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */
+-
+-extern unsigned long vgacon_remap_base;
+-#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0))
+-
+-#define vga_readb(x) (*(x))
+-#define vga_writeb(x,y) (*(y) = (x))
+-
+-#endif
+diff --git a/include/asm-ppc64/vio.h b/include/asm-ppc64/vio.h
+deleted file mode 100644
+--- a/include/asm-ppc64/vio.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-/*
+- * IBM PowerPC Virtual I/O Infrastructure Support.
+- *
+- * Copyright (c) 2003 IBM Corp.
+- * Dave Engebretsen engebret at us.ibm.com
+- * Santiago Leon santil at us.ibm.com
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#ifndef _ASM_VIO_H
+-#define _ASM_VIO_H
+-
+-#include <linux/config.h>
+-#include <linux/init.h>
+-#include <linux/errno.h>
+-#include <linux/device.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/mod_devicetable.h>
+-
+-#include <asm/hvcall.h>
+-#include <asm/scatterlist.h>
+-
+-/*
+- * Architecture-specific constants for drivers to
+- * extract attributes of the device using vio_get_attribute()
+- */
+-#define VETH_MAC_ADDR "local-mac-address"
+-#define VETH_MCAST_FILTER_SIZE "ibm,mac-address-filters"
+-
+-/* End architecture-specific constants */
+-
+-#define h_vio_signal(ua, mode) \
+- plpar_hcall_norets(H_VIO_SIGNAL, ua, mode)
+-
+-#define VIO_IRQ_DISABLE 0UL
+-#define VIO_IRQ_ENABLE 1UL
+-
+-struct iommu_table;
+-
+-/*
+- * The vio_dev structure is used to describe virtual I/O devices.
+- */
+-struct vio_dev {
+- struct iommu_table *iommu_table; /* vio_map_* uses this */
+- char *name;
+- char *type;
+- uint32_t unit_address;
+- unsigned int irq;
+- struct device dev;
+-};
+-
+-struct vio_driver {
+- struct list_head node;
+- char *name;
+- const struct vio_device_id *id_table;
+- int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
+- int (*remove)(struct vio_dev *dev);
+- unsigned long driver_data;
+- struct device_driver driver;
+-};
+-
+-struct vio_bus_ops {
+- int (*match)(const struct vio_device_id *id, const struct vio_dev *dev);
+- void (*unregister_device)(struct vio_dev *);
+- void (*release_device)(struct device *);
+-};
+-
+-extern struct dma_mapping_ops vio_dma_ops;
+-extern struct bus_type vio_bus_type;
+-extern struct vio_dev vio_bus_device;
+-
+-extern int vio_register_driver(struct vio_driver *drv);
+-extern void vio_unregister_driver(struct vio_driver *drv);
+-
+-extern struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev);
+-extern void __devinit vio_unregister_device(struct vio_dev *dev);
+-
+-extern int vio_bus_init(struct vio_bus_ops *);
+-
+-#ifdef CONFIG_PPC_PSERIES
+-struct device_node;
+-
+-extern struct vio_dev * __devinit vio_register_device_node(
+- struct device_node *node_vdev);
+-extern struct vio_dev *vio_find_node(struct device_node *vnode);
+-extern const void *vio_get_attribute(struct vio_dev *vdev, void *which,
+- int *length);
+-extern int vio_enable_interrupts(struct vio_dev *dev);
+-extern int vio_disable_interrupts(struct vio_dev *dev);
+-#endif
+-
+-static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
+-{
+- return container_of(drv, struct vio_driver, driver);
+-}
+-
+-static inline struct vio_dev *to_vio_dev(struct device *dev)
+-{
+- return container_of(dev, struct vio_dev, dev);
+-}
+-
+-#endif /* _ASM_VIO_H */
+diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h
+deleted file mode 100644
+--- a/include/asm-ppc64/xics.h
++++ /dev/null
+@@ -1,34 +0,0 @@
+-/*
+- * arch/ppc64/kernel/xics.h
+- *
+- * Copyright 2000 IBM Corporation.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#ifndef _PPC64_KERNEL_XICS_H
+-#define _PPC64_KERNEL_XICS_H
+-
+-#include <linux/cache.h>
+-
+-void xics_init_IRQ(void);
+-int xics_get_irq(struct pt_regs *);
+-void xics_setup_cpu(void);
+-void xics_teardown_cpu(int secondary);
+-void xics_cause_IPI(int cpu);
+-void xics_request_IPIs(void);
+-void xics_migrate_irqs_away(void);
+-
+-/* first argument is ignored for now*/
+-void pSeriesLP_cppr_info(int n_cpu, u8 value);
+-
+-struct xics_ipi_struct {
+- volatile unsigned long value;
+-} ____cacheline_aligned;
+-
+-extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+-
+-#endif /* _PPC64_KERNEL_XICS_H */
+diff --git a/include/asm-s390/rwsem.h b/include/asm-s390/rwsem.h
+--- a/include/asm-s390/rwsem.h
++++ b/include/asm-s390/rwsem.h
+@@ -351,5 +351,10 @@ static inline long rwsem_atomic_update(l
+ 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
+--- a/include/asm-s390/semaphore.h
++++ b/include/asm-s390/semaphore.h
+@@ -29,9 +29,6 @@ struct semaphore {
+ #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
+--- 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 @@ extern unsigned int console_irq;
+ #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
+--- a/include/asm-s390/unistd.h
++++ b/include/asm-s390/unistd.h
+@@ -590,7 +590,6 @@ asmlinkage long sys_clone(struct pt_regs
+ 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
+--- 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 int dma_set_mask(struct de
+ }
+
+ 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
+--- a/include/asm-sh/machvec.h
++++ b/include/asm-sh/machvec.h
+@@ -64,7 +64,7 @@ struct sh_machine_vector
+
+ 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
+--- a/include/asm-sh/pgtable.h
++++ b/include/asm-sh/pgtable.h
+@@ -224,8 +224,6 @@ static inline pgprot_t pgprot_noncached(
+ 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
+--- a/include/asm-sh/rwsem.h
++++ b/include/asm-sh/rwsem.h
+@@ -166,5 +166,10 @@ static inline int rwsem_atomic_update(in
+ 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
+--- a/include/asm-sh/semaphore.h
++++ b/include/asm-sh/semaphore.h
+@@ -33,9 +33,6 @@ struct semaphore {
+ .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
+--- a/include/asm-sh/unistd.h
++++ b/include/asm-sh/unistd.h
+@@ -503,7 +503,6 @@ asmlinkage int sys_vfork(unsigned long r
+ 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
+--- a/include/asm-sh64/dma-mapping.h
++++ b/include/asm-sh64/dma-mapping.h
+@@ -25,7 +25,7 @@ static inline int dma_set_mask(struct de
+ }
+
+ 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
+--- a/include/asm-sh64/pgtable.h
++++ b/include/asm-sh64/pgtable.h
+@@ -457,9 +457,6 @@ extern inline pte_t pte_mkhuge(pte_t pte
+ 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
+--- a/include/asm-sh64/semaphore.h
++++ b/include/asm-sh64/semaphore.h
+@@ -40,9 +40,6 @@ struct semaphore {
+ .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
+--- 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
+--- 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
+--- a/include/asm-sparc/pgtable.h
++++ b/include/asm-sparc/pgtable.h
+@@ -255,8 +255,6 @@ BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung
+ #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
+--- a/include/asm-sparc/semaphore.h
++++ b/include/asm-sparc/semaphore.h
+@@ -22,9 +22,6 @@ struct semaphore {
+ .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
+--- 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
+--- a/include/asm-sparc64/pgtable.h
++++ b/include/asm-sparc64/pgtable.h
+@@ -231,9 +231,6 @@ extern struct page *mem_map_zero;
+ #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
+--- a/include/asm-sparc64/rwsem.h
++++ b/include/asm-sparc64/rwsem.h
+@@ -56,6 +56,11 @@ static inline void rwsem_atomic_add(int
+ 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
+--- a/include/asm-sparc64/semaphore.h
++++ b/include/asm-sparc64/semaphore.h
+@@ -22,9 +22,6 @@ struct semaphore {
+ { 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
+--- a/include/asm-sparc64/tlb.h
++++ b/include/asm-sparc64/tlb.h
+@@ -25,9 +25,8 @@ struct mmu_gather {
+ 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 @@ extern void flush_tlb_pending(void);
+
+ 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 @@ extern void smp_flush_tlb_mm(struct mm_s
+
+ 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
+--- 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
+--- a/include/asm-um/dma-mapping.h
++++ b/include/asm-um/dma-mapping.h
+@@ -19,7 +19,7 @@ dma_set_mask(struct device *dev, u64 dma
+
+ 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
+--- 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
+--- a/include/asm-um/page.h
++++ b/include/asm-um/page.h
+@@ -115,7 +115,7 @@ extern unsigned long uml_physmem;
+ #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
+--- a/include/asm-um/pgtable.h
++++ b/include/asm-um/pgtable.h
+@@ -138,7 +138,7 @@ extern unsigned long pg0[1024];
+
+ #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
+--- a/include/asm-v850/semaphore.h
++++ b/include/asm-v850/semaphore.h
+@@ -18,9 +18,6 @@ struct semaphore {
+ { 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
+--- a/include/asm-v850/unistd.h
++++ b/include/asm-v850/unistd.h
+@@ -452,7 +452,6 @@ unsigned long sys_mmap2(unsigned long ad
+ 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
+--- a/include/asm-x86_64/dma-mapping.h
++++ b/include/asm-x86_64/dma-mapping.h
+@@ -17,7 +17,7 @@ extern dma_addr_t bad_dma_address;
+ (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
+--- 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 @@ static __inline__ int mtrr_del_page (int
+
+ #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
+--- a/include/asm-x86_64/pgtable.h
++++ b/include/asm-x86_64/pgtable.h
+@@ -318,8 +318,6 @@ static inline int pmd_large(pmd_t pte) {
+ * 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
+--- a/include/asm-x86_64/rwsem.h
++++ b/include/asm-x86_64/rwsem.h
+@@ -274,5 +274,10 @@ LOCK_PREFIX "xaddl %0,(%2)"
+ 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
+--- a/include/asm-x86_64/semaphore.h
++++ b/include/asm-x86_64/semaphore.h
+@@ -56,9 +56,6 @@ struct semaphore {
+ .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
+--- a/include/asm-x86_64/swiotlb.h
++++ b/include/asm-x86_64/swiotlb.h
+@@ -27,7 +27,7 @@ extern void swiotlb_unmap_sg(struct devi
+ 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
+--- a/include/asm-x86_64/unistd.h
++++ b/include/asm-x86_64/unistd.h
+@@ -780,8 +780,6 @@ asmlinkage long sys_pipe(int *fildes);
+ #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
+--- a/include/asm-xtensa/dma-mapping.h
++++ b/include/asm-xtensa/dma-mapping.h
+@@ -28,7 +28,7 @@ extern void consistent_sync(void*, size_
+ #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
+--- a/include/asm-xtensa/semaphore.h
++++ b/include/asm-xtensa/semaphore.h
+@@ -29,9 +29,6 @@ struct semaphore {
+ .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
+--- /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 at 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
+--- a/include/linux/ata.h
++++ b/include/linux/ata.h
+@@ -42,13 +42,18 @@ enum {
+ 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 @@ enum {
+ 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 @@ enum {
+ 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 @@ enum {
+ 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 @@ struct ata_taskfile {
+ ((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 atapi_cdb_len(u16 *dev
+ }
+ }
+
+-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
+--- a/include/linux/audit.h
++++ b/include/linux/audit.h
+@@ -260,11 +260,11 @@ extern int audit_filter_user(struct netl
+ #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
+--- a/include/linux/bio.h
++++ b/include/linux/bio.h
+@@ -301,7 +301,7 @@ extern struct bio *bio_map_user_iov(stru
+ 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
+--- 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 @@ extern int bitmap_scnlistprintf(char *bu
+ 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
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -96,8 +96,8 @@ struct io_context {
+
+ 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 @@ typedef void (rq_end_io_fn)(struct reque
+ 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 @@ struct request {
+ 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 @@ enum rq_flag_bits {
+ __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 @@ enum rq_flag_bits {
+
+ #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 @@ enum rq_flag_bits {
+ #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 @@ struct request_queue
+ 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 @@ struct request_queue
+ * 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 @@ struct request_queue
+ unsigned int sg_reserved_size;
+ int node;
+
+- struct list_head drain_list;
+-
+ /*
+ * reserved for flush operations
+ */
+@@ -434,7 +442,7 @@ enum {
+ #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 @@ enum {
+ #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 generic_make_request(struct
+ 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_run_queue(request_queue_
+ 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 @@ extern void end_request(struct request *
+
+ 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 blk_dump_rq_flags(struct req
+ 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
+--- a/include/linux/buffer_head.h
++++ b/include/linux/buffer_head.h
+@@ -126,8 +126,8 @@ BUFFER_FNS(Eopnotsupp, eopnotsupp)
+ /* 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 @@ extern int buffer_heads_over_limit;
+ * 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 @@ static inline void attach_page_buffers(s
+ {
+ 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
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -32,6 +32,7 @@ struct cpu {
+ };
+
+ 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
+--- 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
+--- 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 @@ static inline int __cpulist_parse(const
+ 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
+--- 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
+--- a/include/linux/cycx_drv.h
++++ b/include/linux/cycx_drv.h
+@@ -60,6 +60,5 @@ extern int cycx_peek(struct cycx_hw *hw,
+ 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
+--- 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 @@ struct device_driver {
+ 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 @@ struct class_attribute class_attr_##_nam
+ 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_device {
+ 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 int class_device_rename(struct cl
+ 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 class_interface {
+ 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 void class_interface_unregister(s
+
+ 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 device {
+
+ 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 int device_attach(struct device
+ 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
+@@ -379,32 +396,6 @@ extern struct device * get_device(struct
+ extern void put_device(struct device * dev);
+
+
+-/* drivers/base/platform.c */
+-
+-struct platform_device {
+- const char * name;
+- u32 id;
+- struct device dev;
+- u32 num_resources;
+- struct resource * resource;
+-};
+-
+-#define to_platform_device(x) container_of((x), struct platform_device, dev)
+-
+-extern int platform_device_register(struct platform_device *);
+-extern void platform_device_unregister(struct platform_device *);
+-
+-extern struct bus_type platform_bus_type;
+-extern struct device platform_bus;
+-
+-extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);
+-extern int platform_get_irq(struct platform_device *, unsigned int);
+-extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, char *);
+-extern int platform_get_irq_byname(struct platform_device *, char *);
+-extern int platform_add_devices(struct platform_device **, int);
+-
+-extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int);
+-
+ /* drivers/base/power.c */
+ extern void device_shutdown(void);
+
+diff --git a/include/linux/dmi.h b/include/linux/dmi.h
+--- a/include/linux/dmi.h
++++ b/include/linux/dmi.h
+@@ -60,7 +60,7 @@ struct dmi_device {
+ 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
+--- a/include/linux/elevator.h
++++ b/include/linux/elevator.h
+@@ -8,18 +8,17 @@ typedef void (elevator_merge_req_fn) (re
+
+ 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 @@ struct elevator_ops
+ 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 @@ struct elevator_queue
+ /*
+ * 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 int elv_register_queue(request_qu
+ 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 @@ enum {
+ 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
+--- a/include/linux/etherdevice.h
++++ b/include/linux/etherdevice.h
+@@ -104,6 +104,22 @@ static inline void random_ether_addr(u8
+ 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
+--- a/include/linux/ethtool.h
++++ b/include/linux/ethtool.h
+@@ -269,6 +269,8 @@ u32 ethtool_op_get_tso(struct net_device
+ 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);
+
+ /**
+ * ðtool_ops - Alter and report network device settings
+@@ -298,6 +300,8 @@ int ethtool_op_get_perm_addr(struct net_
+ * 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 @@ struct ethtool_ops {
+ 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 @@ struct ethtool_ops {
+ #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
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -320,7 +320,7 @@ struct address_space_operations {
+ /* 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 @@ struct file_ra_state {
+ #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 @@ struct file {
+ 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
+--- /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 at intracom.gr>
++ *
++ * 2005 (c) MontaVista Software, Inc.
++ * Vitaly Bordug <vbordug at 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/fsl_devices.h b/include/linux/fsl_devices.h
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -47,16 +47,21 @@
+ struct gianfar_platform_data {
+ /* device specific information */
+ u32 device_flags;
+- u32 phy_reg_addr;
+
+ /* board specific information */
+ u32 board_flags;
+- u32 phy_flags;
+- u32 phyid;
+- u32 interruptPHY;
++ const char *bus_id;
+ u8 mac_addr[6];
+ };
+
++struct gianfar_mdio_data {
++ /* device specific information */
++ u32 paddr;
++
++ /* board specific information */
++ int irq[32];
++};
++
+ /* Flags related to gianfar device features */
+ #define FSL_GIANFAR_DEV_HAS_GIGABIT 0x00000001
+ #define FSL_GIANFAR_DEV_HAS_COALESCE 0x00000002
+diff --git a/include/linux/fuse.h b/include/linux/fuse.h
+--- a/include/linux/fuse.h
++++ b/include/linux/fuse.h
+@@ -61,7 +61,6 @@ struct fuse_kstatfs {
+ #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
+--- 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
+--- a/include/linux/genhd.h
++++ b/include/linux/genhd.h
+@@ -119,7 +119,7 @@ struct gendisk {
+ 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 gendisk {
+ 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
+--- a/include/linux/gfp.h
++++ b/include/linux/gfp.h
+@@ -12,8 +12,8 @@ struct vm_area_struct;
+ * 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 @@ struct vm_area_struct;
+ *
+ * __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 @@ struct vm_area_struct;
+
+ #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 @@ static inline struct page *alloc_pages_n
+ 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
+--- /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
+--- /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
+--- /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
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -16,7 +16,6 @@ static inline int is_vm_hugetlb_page(str
+ 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 @@ static inline unsigned long hugetlb_tota
+ #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
+--- 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 at cc.hut.fi> and even
+ Frodo Looijaard <frodol at 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 @@ struct i2c_algo_bit_data {
+ 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
+--- a/include/linux/i2c-algo-pca.h
++++ b/include/linux/i2c-algo-pca.h
+@@ -9,8 +9,6 @@ struct i2c_algo_pca_data {
+ 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
+--- 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 at cc.hut.fi> and even
+ Frodo Looijaard <frodol at 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 @@ struct i2c_algo_pcf_data {
+ 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
+--- 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
+--- 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
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -23,15 +23,15 @@
+ /* With some changes from Kyösti Mälkki <kmalkki at cc.hut.fi> and
+ Frodo Looijaard <frodol at 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_write_byte_data(str
+ 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 @@ struct i2c_msg {
+ #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 @@ struct i2c_msg {
+ #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 @@ struct i2c_msg {
+ 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 @@ struct i2c_msg {
+ 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 @@ union i2c_smbus_data {
+ #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 @@ union i2c_smbus_data {
+
+ #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
+--- 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 i2o_device {
+ struct device device;
+
+ struct semaphore lock; /* device lock */
+-
+- struct class_device classdev; /* i2o device class */
+ };
+
+ /*
+@@ -194,7 +196,7 @@ struct i2o_controller {
+ 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 @@ static inline int i2o_dma_map_sg(struct
+ * 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 @@ static inline void i2o_dma_free(struct d
+ * 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
+--- 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
+--- a/include/linux/ide.h
++++ b/include/linux/ide.h
+@@ -218,7 +218,7 @@ typedef enum { ide_unknown, ide_generic,
+ 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
+--- a/include/linux/idr.h
++++ b/include/linux/idr.h
+@@ -71,7 +71,7 @@ struct idr {
+ */
+
+ 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
+--- 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
+--- 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 @@ struct input_absinfo {
+ #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 input_dev {
+ 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 @@ static inline void init_input_dev(struct
+ 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 @@ static inline void input_set_abs_params(
+ 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
+--- a/include/linux/jbd.h
++++ b/include/linux/jbd.h
+@@ -69,7 +69,7 @@ extern int journal_enable_debug;
+ #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 int journal_forget (handle_t *,
+ 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
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -307,7 +307,7 @@ struct sysinfo {
+ 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
+--- a/include/linux/key-ui.h
++++ b/include/linux/key-ui.h
+@@ -24,7 +24,8 @@ extern spinlock_t key_serial_lock;
+ #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
+--- a/include/linux/key.h
++++ b/include/linux/key.h
+@@ -40,28 +40,32 @@ struct key;
+ #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 {
+ 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
+--- 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
+--- a/include/linux/kobject.h
++++ b/include/linux/kobject.h
+@@ -65,7 +65,7 @@ extern void kobject_unregister(struct ko
+ 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
+--- a/include/linux/kthread.h
++++ b/include/linux/kthread.h
+@@ -70,6 +70,18 @@ void kthread_bind(struct task_struct *k,
+ 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
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -91,12 +91,13 @@ enum {
+ 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 @@ enum {
+ ATA_SHIFT_UDMA = 0,
+ ATA_SHIFT_MWDMA = 8,
+ ATA_SHIFT_PIO = 11,
+-};
+-
+-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,
++
++ /* Masks for port functions */
++ ATA_PORT_PRIMARY = (1 << 0),
++ ATA_PORT_SECONDARY = (1 << 1),
++};
++
++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_port;
+ 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_ioports {
+ 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 @@ struct ata_host_set {
+ 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 @@ struct ata_device {
+ 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 ata_port {
+ 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 @@ struct ata_port_operations {
+ 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 @@ struct ata_port_info {
+ 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 @@ extern int ata_pci_init_one (struct pci_
+ 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_queuecmd(struct scsi
+ 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 @@ extern void ata_sg_init_one(struct ata_q
+ 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_start (struct ata_
+ 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 @@ extern int ata_std_bios_param(struct scs
+ 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 @@ struct pci_bits {
+
+ 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 @@ static inline unsigned int ata_tag_valid
+ 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 @@ static inline unsigned int sata_dev_pres
+ 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
+--- a/include/linux/loop.h
++++ b/include/linux/loop.h
+@@ -52,7 +52,7 @@ struct loop_device {
+ 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
+--- a/include/linux/mbcache.h
++++ b/include/linux/mbcache.h
+@@ -22,7 +22,7 @@ struct mb_cache_entry {
+ };
+
+ 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
+--- /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
+--- /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
+--- 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 @@ struct vm_area_struct;
+ * 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 @@ struct mempolicy {
+ 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 @@ struct mempolicy *get_vma_policy(struct
+
+ 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_default_policy(v
+ {
+ }
+
++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
+--- a/include/linux/mii.h
++++ b/include/linux/mii.h
+@@ -158,6 +158,7 @@ extern int mii_link_ok (struct mii_if_in
+ 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
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -157,7 +157,7 @@ extern unsigned int kobjsize(const void
+
+ #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 @@ struct page {
+ * 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 @@ struct page {
+ #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 @@ extern void FASTCALL(__page_cache_releas
+
+ #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 get_page(struct page
+
+ 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 int PageAnon(struct page *
+ 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 @@ struct zap_details {
+
+ 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 @@ static inline void unmap_shared_mapping_
+ }
+
+ 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 @@ void install_arg_page(struct vm_area_str
+
+ 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 @@ extern unsigned long do_mremap(unsigned
+ * 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 @@ struct shrinker;
+ 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 split_vma(struct mm_struct *,
+ 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 @@ void handle_ra_miss(struct address_space
+ 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 @@ static inline unsigned long vma_pages(st
+ return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ }
+
+-extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr);
+-
+-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 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);
++
++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
+--- a/include/linux/mmc/mmc.h
++++ b/include/linux/mmc/mmc.h
+@@ -50,7 +50,7 @@ struct mmc_command {
+ #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 @@ struct mmc_data {
+ 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
+--- 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 @@ struct zone {
+ * 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 @@ struct zone {
+ /* 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 @@ typedef struct pglist_data {
+ 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 @@ typedef struct pglist_data {
+ #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 get_zone_counts(unsigned long *acti
+ 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 @@ static inline struct mem_section *__nr_t
+ 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
+--- a/include/linux/mod_devicetable.h
++++ b/include/linux/mod_devicetable.h
+@@ -244,4 +244,9 @@ struct pcmcia_device_id {
+ #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
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -554,7 +554,9 @@ static inline void MODULE_PARM_(void) {
+ #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
+--- a/include/linux/msdos_fs.h
++++ b/include/linux/msdos_fs.h
+@@ -282,6 +282,17 @@ static inline u8 fat_attr(struct inode *
+ 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
+--- 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
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -8,6 +8,7 @@ struct vfsmount;
+ struct open_intent {
+ int flags;
+ int create_mode;
++ struct file *file;
+ };
+
+ enum { MAX_NESTED_LINKS = 5 };
+@@ -65,6 +66,13 @@ extern int FASTCALL(link_path_walk(const
+ 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
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -308,6 +308,7 @@ struct net_device
+ #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_rx_complete(str
+
+ 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/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
+--- a/include/linux/netfilter_arp/arp_tables.h
++++ b/include/linux/netfilter_arp/arp_tables.h
+@@ -68,7 +68,8 @@ struct arpt_entry_target
+ u_int16_t target_size;
+
+ /* Used by userspace */
+- char name[ARPT_FUNCTION_MAXNAMELEN];
++ char name[ARPT_FUNCTION_MAXNAMELEN-1];
++ u_int8_t revision;
+ } user;
+ struct {
+ u_int16_t target_size;
+@@ -148,7 +149,9 @@ struct arpt_entry
+
+ #define ARPT_SO_GET_INFO (ARPT_BASE_CTL)
+ #define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1)
+-#define ARPT_SO_GET_MAX ARPT_SO_GET_ENTRIES
++/* #define ARPT_SO_GET_REVISION_MATCH (ARPT_BASE_CTL + 2)*/
++#define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3)
++#define ARPT_SO_GET_MAX ARPT_SO_GET_REVISION_TARGET
+
+ /* CONTINUE verdict for targets */
+ #define ARPT_CONTINUE 0xFFFFFFFF
+@@ -236,6 +239,15 @@ struct arpt_get_entries
+ struct arpt_entry entrytable[0];
+ };
+
++/* The argument to ARPT_SO_GET_REVISION_*. Returns highest revision
++ * kernel supports, if >= revision. */
++struct arpt_get_revision
++{
++ char name[ARPT_FUNCTION_MAXNAMELEN-1];
++
++ u_int8_t revision;
++};
++
+ /* Standard return verdict, or do jump. */
+ #define ARPT_STANDARD_TARGET ""
+ /* Error verdict. */
+@@ -274,7 +286,9 @@ struct arpt_target
+ {
+ struct list_head list;
+
+- const char name[ARPT_FUNCTION_MAXNAMELEN];
++ const char name[ARPT_FUNCTION_MAXNAMELEN-1];
++
++ u_int8_t revision;
+
+ /* Returns verdict. */
+ unsigned int (*target)(struct sk_buff **pskb,
+diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
+--- a/include/linux/netfilter_ipv6/ip6_tables.h
++++ b/include/linux/netfilter_ipv6/ip6_tables.h
+@@ -57,7 +57,8 @@ struct ip6t_entry_match
+ u_int16_t match_size;
+
+ /* Used by userspace */
+- char name[IP6T_FUNCTION_MAXNAMELEN];
++ char name[IP6T_FUNCTION_MAXNAMELEN-1];
++ u_int8_t revision;
+ } user;
+ struct {
+ u_int16_t match_size;
+@@ -80,7 +81,8 @@ struct ip6t_entry_target
+ u_int16_t target_size;
+
+ /* Used by userspace */
+- char name[IP6T_FUNCTION_MAXNAMELEN];
++ char name[IP6T_FUNCTION_MAXNAMELEN-1];
++ u_int8_t revision;
+ } user;
+ struct {
+ u_int16_t target_size;
+@@ -161,7 +163,9 @@ struct ip6t_entry
+
+ #define IP6T_SO_GET_INFO (IP6T_BASE_CTL)
+ #define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1)
+-#define IP6T_SO_GET_MAX IP6T_SO_GET_ENTRIES
++#define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 2)
++#define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 3)
++#define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET
+
+ /* CONTINUE verdict for targets */
+ #define IP6T_CONTINUE 0xFFFFFFFF
+@@ -291,6 +295,15 @@ struct ip6t_get_entries
+ struct ip6t_entry entrytable[0];
+ };
+
++/* The argument to IP6T_SO_GET_REVISION_*. Returns highest revision
++ * kernel supports, if >= revision. */
++struct ip6t_get_revision
++{
++ char name[IP6T_FUNCTION_MAXNAMELEN-1];
++
++ u_int8_t revision;
++};
++
+ /* Standard return verdict, or do jump. */
+ #define IP6T_STANDARD_TARGET ""
+ /* Error verdict. */
+@@ -352,7 +365,9 @@ struct ip6t_match
+ {
+ struct list_head list;
+
+- const char name[IP6T_FUNCTION_MAXNAMELEN];
++ const char name[IP6T_FUNCTION_MAXNAMELEN-1];
++
++ u_int8_t revision;
+
+ /* Return true or false: return FALSE and set *hotdrop = 1 to
+ force immediate packet drop. */
+@@ -387,7 +402,9 @@ struct ip6t_target
+ {
+ struct list_head list;
+
+- const char name[IP6T_FUNCTION_MAXNAMELEN];
++ const char name[IP6T_FUNCTION_MAXNAMELEN-1];
++
++ u_int8_t revision;
+
+ /* Returns verdict. Argument order changed since 2.6.9, as this
+ must now handle non-linear skbs, using skb_copy_bits and
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+--- 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 @@ struct nfs_inode {
+ 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 @@ static inline int nfs_caches_unstable(st
+ 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 long nfs_save_change_attri
+ 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 void nfs_zap_caches(struct inode
+ 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 @@ extern void nfs_file_clear_open_context(
+ /* 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
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -41,7 +41,7 @@ struct nfs_fattr {
+ __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 @@ struct nfs4_change_info {
+ 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 nfs_openres {
+ 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_openres {
+ 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_open_confirmres {
+ */
+ 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 @@ struct nfs_lowner {
+ 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 @@ struct nfs_writeargs {
+ enum nfs3_stable_how stable;
+ unsigned int pgbase;
+ struct page ** pages;
++ const u32 * bitmask;
+ };
+
+ struct nfs_writeverf {
+@@ -273,6 +268,7 @@ struct nfs_writeres {
+ struct nfs_fattr * fattr;
+ struct nfs_writeverf * verf;
+ __u32 count;
++ const struct nfs_server *server;
+ };
+
+ /*
+@@ -550,6 +546,7 @@ struct nfs4_create_res {
+ 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 @@ struct nfs4_link_arg {
+ 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_readlink {
+ 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 @@ struct nfs4_rename_arg {
+ 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 @@ struct nfs_rpc_ops {
+ 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
+--- 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 @@ static inline int __nodelist_parse(const
+ 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
+--- 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_lock_page(stru
+ 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 @@ extern int read_cache_pages(struct addre
+ 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
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -132,6 +132,7 @@ struct pci_dev {
+ 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 pci_disable_msix(struct pci_
+ 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 @@ static inline int pci_enable_wake(struct
+
+ #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
+--- 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/platform_device.h b/include/linux/platform_device.h
+new file mode 100644
+--- /dev/null
++++ b/include/linux/platform_device.h
+@@ -0,0 +1,40 @@
++/*
++ * platform_device.h - generic, centralized driver model
++ *
++ * Copyright (c) 2001-2003 Patrick Mochel <mochel at osdl.org>
++ *
++ * This file is released under the GPLv2
++ *
++ * See Documentation/driver-model/ for more information.
++ */
++
++#ifndef _PLATFORM_DEVICE_H_
++#define _PLATFORM_DEVICE_H_
++
++#include <linux/device.h>
++
++struct platform_device {
++ const char * name;
++ u32 id;
++ struct device dev;
++ u32 num_resources;
++ struct resource * resource;
++};
++
++#define to_platform_device(x) container_of((x), struct platform_device, dev)
++
++extern int platform_device_register(struct platform_device *);
++extern void platform_device_unregister(struct platform_device *);
++
++extern struct bus_type platform_bus_type;
++extern struct device platform_bus;
++
++extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);
++extern int platform_get_irq(struct platform_device *, unsigned int);
++extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, char *);
++extern int platform_get_irq_byname(struct platform_device *, char *);
++extern int platform_add_devices(struct platform_device **, int);
++
++extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int);
++
++#endif /* _PLATFORM_DEVICE_H_ */
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -170,6 +170,7 @@ typedef int __bitwise suspend_disk_metho
+
+ 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 @@ typedef struct pm_message {
+
+ 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 @@ extern void device_resume(void);
+
+ #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
+--- 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
+--- a/include/linux/rcupdate.h
++++ b/include/linux/rcupdate.h
+@@ -275,6 +275,7 @@ static inline int rcu_pending(int cpu)
+ 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
+--- a/include/linux/reiserfs_fs.h
++++ b/include/linux/reiserfs_fs.h
+@@ -1972,7 +1972,7 @@ extern struct address_space_operations r
+
+ /* 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
+--- a/include/linux/rmap.h
++++ b/include/linux/rmap.h
+@@ -95,8 +95,8 @@ int try_to_unmap(struct page *);
+ /*
+ * 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
+--- a/include/linux/rwsem-spinlock.h
++++ b/include/linux/rwsem-spinlock.h
+@@ -61,5 +61,10 @@ extern void FASTCALL(__up_read(struct rw
+ 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
+--- 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
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -249,6 +249,36 @@ arch_get_unmapped_area_topdown(struct fi
+ 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 @@ extern void arch_unmap_area_topdown(stru
+ #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 @@ struct mm_struct {
+ * 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 @@ struct mm_struct {
+ /* 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 @@ extern int set_cpus_allowed(task_t *p, c
+ #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 @@ extern int do_sigaltstack(const stack_t
+ #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 @@ extern void unhash_process(struct task_s
+ /*
+ * 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
+--- a/include/linux/sdladrv.h
++++ b/include/linux/sdladrv.h
+@@ -52,12 +52,8 @@ typedef struct sdlahw
+
+ 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
+--- 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 @@ struct swap_info_struct;
+ * 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 @@ struct swap_info_struct;
+ * @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 @@ struct security_operations {
+ 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 @@ struct security_operations {
+ 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 @@ static inline int security_inode_removex
+ 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 @@ static inline int security_inode_removex
+ 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 @@ static inline void security_sk_free(stru
+ }
+ #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
+--- 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_8250.h b/include/linux/serial_8250.h
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -12,7 +12,7 @@
+ #define _LINUX_SERIAL_8250_H
+
+ #include <linux/serial_core.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+
+ /*
+ * This is the platform device platform_data structure
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -117,7 +117,9 @@
+ #define PORT_M32R_SIO 68
+
+ /*Digi jsm */
+-#define PORT_JSM 65
++#define PORT_JSM 69
++
++#define PORT_IP3106 70
+
+ #ifdef __KERNEL__
+
+diff --git a/include/linux/serial_ip3106.h b/include/linux/serial_ip3106.h
+new file mode 100644
+--- /dev/null
++++ b/include/linux/serial_ip3106.h
+@@ -0,0 +1,81 @@
++/*
++ * Embedded Alley Solutions, source at 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
+--- 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
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -137,6 +137,8 @@ struct skb_shared_info {
+ 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 @@ enum {
+ * 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 @@ enum {
+ * @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 @@ enum {
+ * @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_over_panic(struct
+ 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
+--- a/include/linux/slab.h
++++ b/include/linux/slab.h
+@@ -121,7 +121,7 @@ extern unsigned int ksize(const void *);
+ 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
+--- a/include/linux/spinlock.h
++++ b/include/linux/spinlock.h
+@@ -171,23 +171,42 @@ extern int __lockfunc generic__raw_read_
+ #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
+--- a/include/linux/sunrpc/auth.h
++++ b/include/linux/sunrpc/auth.h
+@@ -66,7 +66,12 @@ struct rpc_cred_cache {
+
+ 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
+--- 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 @@ enum {
+ 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
+--- a/include/linux/sunrpc/gss_api.h
++++ b/include/linux/sunrpc/gss_api.h
+@@ -40,14 +40,21 @@ int gss_import_sec_context(
+ 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 @@ char *gss_service_to_auth_domain_name(st
+
+ struct pf_desc {
+ u32 pseudoflavor;
+- u32 qop;
+ u32 service;
+ char *name;
+ char *auth_domain_name;
+@@ -85,14 +91,21 @@ struct gss_api_ops {
+ 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
+--- a/include/linux/sunrpc/gss_err.h
++++ b/include/linux/sunrpc/gss_err.h
+@@ -66,16 +66,6 @@ typedef unsigned int OM_uint32;
+
+
+ /*
+- * 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
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -116,18 +116,22 @@ enum seal_alg {
+
+ 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 @@ u32
+ 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
+--- a/include/linux/sunrpc/gss_spkm3.h
++++ b/include/linux/sunrpc/gss_spkm3.h
+@@ -41,9 +41,9 @@ struct spkm3_ctx {
+ #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
+--- a/include/linux/sunrpc/msg_prot.h
++++ b/include/linux/sunrpc/msg_prot.h
+@@ -76,5 +76,30 @@ enum rpc_auth_stat {
+
+ #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
+--- a/include/linux/sunrpc/xdr.h
++++ b/include/linux/sunrpc/xdr.h
+@@ -161,14 +161,10 @@ typedef struct {
+
+ 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
+--- 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,34 +22,23 @@ extern unsigned int xprt_tcp_slot_table_
+ #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.
++ * RPC call and reply header size as number of 32bit words (verifier
++ * size computed separately)
+ */
+-#define RPC_CONNECT_TIMEOUT (60*HZ)
++#define RPC_CALLHDRSIZE 6
++#define RPC_REPHDRSIZE 4
+
+ /*
+- * Delay an arbitrary number of seconds before attempting to reconnect
+- * after an error.
++ * Parameters for choosing a free port
+ */
+-#define RPC_REESTABLISH_TIMEOUT (15*HZ)
++extern unsigned int xprt_min_resvport;
++extern unsigned int xprt_max_resvport;
+
+-/* RPC call and reply header size as number of 32bit words (verifier
+- * size computed separately)
+- */
+-#define RPC_CALLHDRSIZE 6
+-#define RPC_REPHDRSIZE 4
++#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
+@@ -76,6 +51,9 @@ struct rpc_timeout {
+ unsigned char to_exponential;
+ };
+
++struct rpc_task;
++struct rpc_xprt;
++
+ /*
+ * This describes a complete RPC request
+ */
+@@ -95,7 +73,10 @@ struct rpc_rqst {
+ 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 @@ struct rpc_rqst {
+ #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 @@ struct rpc_xprt {
+ 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 rpc_xprt {
+ 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 @@ struct rpc_xprt {
+ 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 @@ struct rpc_xprt {
+ 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);
+-
+-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 *);
++/*
++ * 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);
++
++/*
++ * 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 *);
+-
+-#define XPRT_LOCKED 0
+-#define XPRT_CONNECT 1
+-#define XPRT_CONNECTING 2
+-
+-#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))
++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);
++
++static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
++{
++ return p + xprt->tsh_size;
++}
++
++/*
++ * 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
+--- a/include/linux/suspend.h
++++ b/include/linux/suspend.h
+@@ -71,7 +71,12 @@ void restore_processor_state(void);
+ 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
+--- a/include/linux/swap.h
++++ b/include/linux/swap.h
+@@ -171,8 +171,8 @@ extern int rotate_reclaimable_page(struc
+ 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
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -491,6 +491,7 @@ asmlinkage long sys_nfsservctl(int cmd,
+ 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
+--- 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_state
+ 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 @@ static inline unsigned int textsearch_ge
+ 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
+--- a/include/linux/timer.h
++++ b/include/linux/timer.h
+@@ -12,16 +12,12 @@ struct timer_list {
+ 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 @@ extern struct timer_base_s __init_timer_
+ .expires = (_expires), \
+ .data = (_data), \
+ .base = &__init_timer_base, \
+- .magic = TIMER_MAGIC, \
+ }
+
+ #define DEFINE_TIMER(_name, _function, _expires, _data) \
+@@ -38,6 +33,15 @@ extern struct timer_base_s __init_timer_
+
+ 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 @@ extern unsigned long next_timer_interrup
+ * 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
+--- a/include/linux/timex.h
++++ b/include/linux/timex.h
+@@ -282,6 +282,13 @@ static inline int ntp_synced(void)
+ 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
+--- a/include/linux/types.h
++++ b/include/linux/types.h
+@@ -151,7 +151,12 @@ typedef unsigned long sector_t;
+ */
+
+ #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 @@ typedef __u64 __bitwise __be64;
+ #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
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -57,6 +57,7 @@ struct usb_host_endpoint {
+ 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 @@ struct usb_interface {
+ * 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_interface_cache {
+ 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 @@ int __usb_get_extra_descriptor(char *buf
+ __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
+ type,(void**)ptr)
+
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+
+ struct usb_operations;
+
+@@ -268,7 +270,8 @@ struct usb_bus {
+ 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 usb_bus {
+ 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 usb_device {
+
+ 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 @@ struct usb_device {
+
+ 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 @@ extern struct usb_host_interface *usb_al
+ * 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 @@ static inline int usb_make_path (struct
+ * 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 @@ static inline int usb_make_path (struct
+ * 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 @@ static inline int usb_make_path (struct
+ * 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 @@ static inline int usb_make_path (struct
+ * 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 @@ struct usb_driver {
+
+ 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 @@ extern struct bus_type usb_bus_type;
+
+ /**
+ * 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 @@ extern struct bus_type usb_bus_type;
+ struct usb_class_driver {
+ char *name;
+ struct file_operations *fops;
+- mode_t mode;
+- int minor_base;
++ int minor_base;
+ };
+
+ /*
+@@ -603,7 +623,7 @@ extern void usb_deregister_dev(struct us
+
+ extern int usb_disabled(void);
+
+-/* -------------------------------------------------------------------------- */
++/* ----------------------------------------------------------------------- */
+
+ /*
+ * URB support, for asynchronous request completions
+@@ -613,12 +633,14 @@ extern int usb_disabled(void);
+ * 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 @@ struct urb
+ 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 @@ struct urb
+ 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 @@ static inline void usb_fill_int_urb (str
+ }
+
+ 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 @@ extern int usb_bulk_msg(struct usb_devic
+ 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 @@ int usb_sg_init (
+ 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 @@ void usb_sg_wait (struct usb_sg_request
+ /* 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 @@ usb_maxpacket(struct usb_device *udev, i
+ 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
+--- a/include/linux/usb_gadget.h
++++ b/include/linux/usb_gadget.h
+@@ -107,18 +107,18 @@ struct usb_ep_ops {
+ 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 @@ usb_ep_disable (struct usb_ep *ep)
+ * 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 @@ usb_ep_free_request (struct usb_ep *ep,
+ */
+ 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 @@ usb_ep_free_buffer (struct usb_ep *ep, v
+ * 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
+--- a/include/linux/usb_otg.h
++++ b/include/linux/usb_otg.h
+@@ -63,6 +63,10 @@ struct otg_transceiver {
+ 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 @@ otg_set_power(struct otg_transceiver *ot
+ }
+
+ 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
+--- a/include/linux/usbdevice_fs.h
++++ b/include/linux/usbdevice_fs.h
+@@ -140,6 +140,12 @@ struct usbdevfs_urb32 {
+ 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 @@ struct usbdevfs_urb32 {
+ #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
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -32,10 +32,14 @@ struct vm_struct {
+ * 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 void vunmap(void *addr);
+ 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
+--- a/include/linux/wanpipe.h
++++ b/include/linux/wanpipe.h
+@@ -265,15 +265,6 @@ typedef struct {
+ #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
+--- /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/linux/zutil.h b/include/linux/zutil.h
+--- a/include/linux/zutil.h
++++ b/include/linux/zutil.h
+@@ -15,7 +15,6 @@
+
+ #include <linux/zlib.h>
+ #include <linux/string.h>
+-#include <linux/errno.h>
+ #include <linux/kernel.h>
+
+ typedef unsigned char uch;
+diff --git a/include/media/ovcamchip.h b/include/media/ovcamchip.h
+--- 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
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -237,8 +237,7 @@ typedef struct ax25_cb {
+ 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
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -171,4 +171,10 @@ static inline int skb_frags_no(struct sk
+
+ 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
+--- a/include/net/bluetooth/rfcomm.h
++++ b/include/net/bluetooth/rfcomm.h
+@@ -275,9 +275,6 @@ static inline void rfcomm_session_hold(s
+ 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
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -94,7 +94,6 @@ struct dst_ops
+ 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
+--- 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 at 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 @@ struct ieee80211_hdr_3addr {
+ #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 @@ do { if (ieee80211_debug_level & (level)
+ 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 @@ do { if (ieee80211_debug_level & (level)
+ * 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 @@ const char *escape_essid(const char *ess
+
+ #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 @@ const char *escape_essid(const char *ess
+ #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 @@ const char *escape_essid(const char *ess
+ #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 @@ const char *escape_essid(const char *ess
+
+ 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 @@ struct ieee80211_snap_hdr {
+ #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 @@ enum ieee80211_reasoncode {
+ 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 @@ enum ieee80211_reasoncode {
+ #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 @@ struct ieee80211_rx_stats {
+ 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 @@ struct ieee80211_device;
+
+ #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_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_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_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 @@ enum ieee80211_mfie {
+ 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 @@ enum ieee80211_mfie {
+ 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 @@ struct ieee80211_info_element {
+ 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 @@ struct ieee80211_txb {
+
+ #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 @@ struct ieee80211_network {
+ 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 @@ struct ieee80211_network {
+ 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 @@ enum ieee80211_state {
+ #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 @@ struct ieee80211_device {
+ 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 @@ struct ieee80211_device {
+ #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 @@ extern inline int ieee80211_is_empty_ess
+ 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 @@ extern inline int ieee80211_is_valid_mod
+ 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 @@ extern inline int ieee80211_get_hdrlen(u
+ 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 struct net_device *alloc_ieee8021
+ 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_set_encode(struc
+ 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
+--- 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 @@ struct ieee80211_crypto_ops {
+ * 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 @@ struct ieee80211_crypt_data {
+
+ 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
+--- /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 at 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
+--- a/include/net/netrom.h
++++ b/include/net/netrom.h
+@@ -136,8 +136,7 @@ static __inline__ void nr_node_put(struc
+ 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
+--- a/include/net/sctp/user.h
++++ b/include/net/sctp/user.h
+@@ -171,10 +171,10 @@ struct sctp_sndrcvinfo {
+ */
+
+ 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
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -207,7 +207,7 @@ struct sock {
+ 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
+--- a/include/net/syncppp.h
++++ b/include/net/syncppp.h
+@@ -86,7 +86,6 @@ static inline struct sppp *sppp_of(struc
+
+ 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
+--- 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
+--- 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_id;
+
+ 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_apr_event_param {
+
+ 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 @@ typedef int (*ib_cm_handler)(struct ib_c
+ 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 @@ struct ib_cm_id {
+
+ /**
+ * 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 @@ struct ib_cm_id {
+ * 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
+--- 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 @@ struct ib_class_port_info
+
+ /**
+ * 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 @@ typedef void (*ib_mad_send_handler)(stru
+ * 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 @@ struct ib_mad_agent {
+
+ /**
+ * 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 @@ struct ib_mad_recv_buf {
+ * @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 @@ int ib_unregister_mad_agent(struct ib_ma
+ /**
+ * 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 @@ int ib_unregister_mad_agent(struct ib_ma
+ * 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 @@ void ib_free_recv_mad(struct ib_mad_recv
+ /**
+ * 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 @@ int ib_process_mad_wc(struct ib_mad_agen
+ * @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 @@ int ib_process_mad_wc(struct ib_mad_agen
+ * 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 @@ int ib_process_mad_wc(struct ib_mad_agen
+ */
+ 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
+--- 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_event_get {
+ };
+
+ 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 @@ struct ib_ucm_req_event_resp {
+ __u8 retry_count;
+ __u8 rnr_retry_count;
+ __u8 srq;
++ __u8 port;
+ };
+
+ struct ib_ucm_rep_event_resp {
+@@ -353,10 +352,9 @@ struct ib_ucm_apr_event_resp {
+ };
+
+ 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
+--- 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 @@ enum {
+ 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 @@ enum {
+ * 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 @@ struct ib_uverbs_cmd_hdr {
+ __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 @@ struct ib_uverbs_query_port_resp {
+ __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 @@ struct ib_uverbs_dereg_mr {
+ __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 @@ struct ib_uverbs_create_cq_resp {
+ __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 @@ struct ib_uverbs_destroy_qp_resp {
+ __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
+--- a/include/rdma/ib_verbs.h
++++ b/include/rdma/ib_verbs.h
+@@ -595,11 +595,8 @@ struct ib_send_wr {
+ } 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 @@ struct ib_device {
+ 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
+--- a/include/scsi/scsi.h
++++ b/include/scsi/scsi.h
+@@ -116,6 +116,9 @@ extern const char *const scsi_device_typ
+ /* 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
+--- 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 @@ struct scsi_cmnd {
+ #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
+--- a/include/scsi/scsi_request.h
++++ b/include/scsi/scsi_request.h
+@@ -45,7 +45,7 @@ struct scsi_request {
+ 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
+--- 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/emu10k1.h b/include/sound/emu10k1.h
+--- a/include/sound/emu10k1.h
++++ b/include/sound/emu10k1.h
+@@ -1055,6 +1055,7 @@ typedef struct {
+ unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */
+ unsigned char ca0102_chip; /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */
+ unsigned char ca0108_chip; /* Audigy 2 Value */
++ unsigned char ca_cardbus_chip; /* Audigy 2 ZS Notebook */
+ unsigned char ca0151_chip; /* P16V */
+ unsigned char spk71; /* Has 7.1 speakers */
+ unsigned char sblive51; /* SBLive! 5.1 - extout 0x11 -> center, 0x12 -> lfe */
+diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
+--- a/include/sound/memalloc.h
++++ b/include/sound/memalloc.h
+@@ -111,7 +111,7 @@ size_t snd_dma_get_reserved_buf(struct s
+ 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
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -60,8 +60,8 @@ config INIT_ENV_ARG_LIMIT
+ 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/ipc/shm.c b/ipc/shm.c
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -233,10 +233,11 @@ static int newseg (key_t key, int shmflg
+ 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
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -22,7 +22,6 @@ obj-$(CONFIG_KEXEC) += kexec.o
+ 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_DETECT_SOFTLOCKUP) += softl
+ 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 at linuxcare.com.au>, the -fno-omit-frame-pointer is
+diff --git a/kernel/acct.c b/kernel/acct.c
+--- a/kernel/acct.c
++++ b/kernel/acct.c
+@@ -553,7 +553,7 @@ void acct_update_integrals(struct task_s
+ 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
+--- a/kernel/audit.c
++++ b/kernel/audit.c
+@@ -133,7 +133,7 @@ struct audit_buffer {
+ 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 @@ static inline void audit_get_stamp(struc
+ * 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 @@ void audit_log_end(struct audit_buffer *
+ /* 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
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -803,7 +803,7 @@ static void audit_log_task_info(struct a
+ 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
+--- 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
+--- 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 @@ struct cpuset {
+ 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 vfsmount *cpuset_mount;
+ 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.
+- *
+- * 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.
+- *
+- * 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.
+- *
+- * 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
++ * 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.
++ *
++ * 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.
++ *
++ * 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().
++ *
++ * 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.
+- */
+-
+-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.
++ * 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 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 @@ static inline struct cftype *__d_cft(str
+ }
+
+ /*
+- * 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 @@ static int cpuset_path(const struct cpus
+ * 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 @@ static void cpuset_release_agent(const c
+ * 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 @@ static void check_for_release(struct cpu
+ * 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 @@ static void guarantee_online_cpus(const
+ * 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 @@ static void guarantee_online_mems(const
+ }
+
+ /*
+- * 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, ¤t->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, ¤t->mems_allowed);
+ }
+ }
+
+@@ -579,7 +620,7 @@ static void refresh_mems(void)
+ *
+ * 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 @@ static int is_cpuset_subset(const struct
+ * 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 @@ static int validate_change(const struct
+ * 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 @@ static void update_cpu_domains(struct cp
+ 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 @@ static int update_cpumask(struct cpuset
+ 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 @@ static int update_nodemask(struct cpuset
+ 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 @@ static int update_nodemask(struct cpuset
+ * 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 @@ static int update_flag(cpuset_flagbits_t
+ 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 @@ static int attach_task(struct cpuset *cs
+ 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 @@ static int attach_task(struct cpuset *cs
+ 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 @@ static int attach_task(struct cpuset *cs
+ 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 @@ static ssize_t cpuset_common_file_write(
+ }
+ buffer[nbytes] = 0; /* nul-terminate */
+
+- cpuset_down(&cpuset_sem);
++ down(&manage_sem);
+
+ if (is_removed(cs)) {
+ retval = -ENODEV;
+@@ -901,7 +971,7 @@ static ssize_t cpuset_common_file_write(
+ if (retval == 0)
+ retval = nbytes;
+ out2:
+- cpuset_up(&cpuset_sem);
++ up(&manage_sem);
+ cpuset_release_agent(pathbuf);
+ out1:
+ kfree(buffer);
+@@ -941,9 +1011,9 @@ static int cpuset_sprintf_cpulist(char *
+ {
+ 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 @@ static int cpuset_sprintf_memlist(char *
+ {
+ 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 @@ static ssize_t cpuset_common_file_read(s
+ goto out;
+ }
+ *s++ = '\n';
+- *s = '\0';
+
+ retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
+ out:
+@@ -1048,6 +1117,21 @@ static int cpuset_file_release(struct in
+ 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 @@ static struct inode_operations cpuset_di
+ .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 @@ struct ctr_struct {
+
+ /*
+ * 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 @@ static int pid_array_to_buf(char *buf, i
+ 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 @@ static long cpuset_create(struct cpuset
+ 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 @@ static long cpuset_create(struct cpuset
+
+ 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 @@ static int cpuset_rmdir(struct inode *un
+
+ /* 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 @@ void __init cpuset_init_smp(void)
+ * 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 @@ void cpuset_fork(struct task_struct *tsk
+ *
+ * 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.
+- *
+- * 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.
++ * 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 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 cpuset_cpus_allowed(const stru
+ {
+ 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 @@ void cpuset_init_current_mems_allowed(vo
+ * 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 @@ int cpuset_zonelist_valid_mems_allowed(s
+
+ /*
+ * 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 @@ static const struct cpuset *nearest_excl
+ * 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 @@ int cpuset_zone_allowed(struct zone *z,
+ 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 @@ done:
+ * 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 @@ int cpuset_excl_nodes_overlap(const stru
+ 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 @@ done:
+ * 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 @@ static int proc_cpuset_show(struct seq_f
+ 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 @@ static int proc_cpuset_show(struct seq_f
+ 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
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -547,7 +547,7 @@ static inline void reparent_thread(task_
+
+ 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 @@ static inline void reparent_thread(task_
+ 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 @@ static void exit_notify(struct task_stru
+ (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 @@ static void exit_notify(struct task_stru
+ /* 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 @@ fastcall NORET_TYPE void do_exit(long co
+ 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 @@ fastcall NORET_TYPE void do_exit(long co
+ 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 @@ repeat:
+
+ 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
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -182,37 +182,37 @@ static struct task_struct *dup_task_stru
+ }
+
+ #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 @@ static inline int dup_mmap(struct mm_str
+ }
+
+ /*
+- * 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 @@ static inline int dup_mmap(struct mm_str
+ 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 @@ static inline int dup_mmap(struct mm_str
+ 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 @@ static struct mm_struct * mm_init(struct
+ 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 @@ static int copy_mm(unsigned long clone_f
+ 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
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -205,15 +205,13 @@ static int get_futex_key(unsigned long u
+ /*
+ * Do a quick atomic lookup first - this is the fastpath.
+ */
+- spin_lock(¤t->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(¤t->mm->page_table_lock);
++ put_page(page);
+ return 0;
+ }
+- spin_unlock(¤t->mm->page_table_lock);
+
+ /*
+ * Do it the general way.
+diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
+--- a/kernel/irq/handle.c
++++ b/kernel/irq/handle.c
+@@ -117,14 +117,16 @@ fastcall unsigned int __do_IRQ(unsigned
+ /*
+ * No locking required for CPU-local interrupts:
+ */
+- desc->handler->ack(irq);
++ if (desc->handler->ack)
++ desc->handler->ack(irq);
+ action_ret = handle_IRQ_event(irq, regs, desc->action);
+ desc->handler->end(irq);
+ return 1;
+ }
+
+ spin_lock(&desc->lock);
+- desc->handler->ack(irq);
++ if (desc->handler->ack)
++ desc->handler->ack(irq);
+ /*
+ * REPLAY is when Linux resends an IRQ that was dropped earlier
+ * WAITING is used by probe to mark irqs that are being tested
+diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
+--- 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
+--- a/kernel/kexec.c
++++ b/kernel/kexec.c
+@@ -90,7 +90,7 @@ int kexec_should_crash(struct task_struc
+ 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 @@ static int kimage_is_destination_range(s
+ 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 @@ static struct page *kimage_alloc_pages(u
+ 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 @@ static void kimage_free_pages(struct pag
+ {
+ 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 kimage_entry_t *kimage_dst_used(s
+ }
+
+ 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
+--- a/kernel/kmod.c
++++ b/kernel/kmod.c
+@@ -131,14 +131,14 @@ struct subprocess_info {
+ 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(¤t->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(¤t->blocked);
+ recalc_sigpending();
+diff --git a/kernel/kprobes.c b/kernel/kprobes.c
+--- 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
+--- a/kernel/kthread.c
++++ b/kernel/kthread.c
+@@ -165,6 +165,12 @@ EXPORT_SYMBOL(kthread_bind);
+
+ 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 @@ int kthread_stop(struct task_struct *k)
+
+ /* 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 @@ int kthread_stop(struct task_struct *k)
+
+ 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
+--- 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
+--- a/kernel/posix-cpu-timers.c
++++ b/kernel/posix-cpu-timers.c
+@@ -1225,7 +1225,7 @@ void posix_cpu_timer_schedule(struct k_i
+ /*
+ * 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 @@ void posix_cpu_timer_schedule(struct k_i
+ 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 @@ void posix_cpu_timer_schedule(struct k_i
+ 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 @@ void posix_cpu_timer_schedule(struct k_i
+ * 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 @@ void posix_cpu_timer_schedule(struct k_i
+ */
+ 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
+--- a/kernel/posix-timers.c
++++ b/kernel/posix-timers.c
+@@ -1295,13 +1295,6 @@ sys_clock_getres(clockid_t which_clock,
+ 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 @@ static int common_nsleep(clockid_t which
+ 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 @@ static int common_nsleep(clockid_t which
+ ¤t_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 @@ static int common_nsleep(clockid_t which
+ if (left < (s64)0)
+ break;
+
+- new_timer.expires = jiffies + left;
+- __set_current_state(TASK_INTERRUPTIBLE);
+- add_timer(&new_timer);
+-
+- schedule();
++ schedule_timeout_interruptible(left);
+
+- 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
+--- a/kernel/power/Makefile
++++ b/kernel/power/Makefile
+@@ -4,7 +4,7 @@ EXTRA_CFLAGS += -DDEBUG
+ 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
+--- a/kernel/power/disk.c
++++ b/kernel/power/disk.c
+@@ -30,7 +30,6 @@ extern int swsusp_check(void);
+ 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 @@ static void free_some_memory(void)
+ 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 @@ int pm_suspend_disk(void)
+ 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 @@ static int software_resume(void)
+
+ 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 @@ static int software_resume(void)
+ 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
+--- a/kernel/power/main.c
++++ b/kernel/power/main.c
+@@ -167,6 +167,8 @@ static int enter_state(suspend_state_t s
+ {
+ int error;
+
++ if (pm_ops->valid && !pm_ops->valid(state))
++ return -ENODEV;
+ if (down_trylock(&pm_sem))
+ return -EBUSY;
+
+@@ -236,7 +238,8 @@ static ssize_t state_show(struct subsyst
+ 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
+--- a/kernel/power/power.h
++++ b/kernel/power/power.h
+@@ -53,3 +53,20 @@ extern void thaw_processes(void);
+
+ 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
+--- /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 at 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
+--- 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 at fornax.hu>
+- * Copyright (C) 1998,2001-2004 Pavel Machek <pavel at suse.cz>
++ * Copyright (C) 1998,2001-2005 Pavel Machek <pavel at 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 @@ static unsigned int nr_copy_pages __nosa
+ 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_header {
+ 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 @@ static int write_suspend_image(void)
+ 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 @@ static int enough_free_mem(void)
+ * 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 @@ static int suspend_prepare_image(void)
+ 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 @@ int swsusp_write(void)
+ }
+
+
+-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 @@ int swsusp_suspend(void)
+ 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 @@ int swsusp_resume(void)
+ * 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 @@ int swsusp_resume(void)
+ *
+ * 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 @@ static int check_pagedir(struct pbe *pbl
+ 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 @@ static struct pbe * swsusp_pagedir_reloc
+ 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 @@ static struct pbe * swsusp_pagedir_reloc
+ 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 @@ static struct pbe * swsusp_pagedir_reloc
+ 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 @@ static int read_pagedir(struct pbe *pbli
+ break;
+ }
+
+- if (error)
+- free_pagedir(pblist);
+- else
++ if (!error)
+ BUG_ON(i != swsusp_info.pagedir_pages);
+
+ return error;
+@@ -1485,15 +1015,6 @@ static int read_suspend_image(void)
+ 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
+--- 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 at colorfullife.com
+ * Rewrote bits to get rid of console_lock
+ * 01Mar01 Andrew Morton <andrewm at uow.edu.au>
+@@ -148,7 +148,7 @@ static int __init console_setup(char *st
+ 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 @@ static int __init log_buf_len_setup(char
+ 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 @@ static int __init log_buf_len_setup(char
+ 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 @@ __setup("log_buf_len=", log_buf_len_setu
+ * 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 @@ int do_syslog(int type, char __user * bu
+ 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 @@ int do_syslog(int type, char __user * bu
+ 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 @@ int do_syslog(int type, char __user * bu
+ 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 @@ int do_syslog(int type, char __user * bu
+ 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 @@ out:
+ 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 @@ static void call_console_drivers(unsigne
+ 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 void zap_locks(void)
+ 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 @@ __attribute__((weak)) unsigned long long
+
+ /*
+ * 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 @@ EXPORT_SYMBOL(vprintk);
+
+ #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 @@ EXPORT_SYMBOL(console_start);
+ * 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 @@ void register_console(struct console * c
+ * 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 @@ void register_console(struct console * c
+ }
+ 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 @@ int unregister_console(struct console *
+ 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 @@ void tty_write_message(struct tty_struct
+ 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 @@ int __printk_ratelimit(int ratelimit_jif
+ 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 @@ int __printk_ratelimit(int ratelimit_jif
+ 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
+--- a/kernel/ptrace.c
++++ b/kernel/ptrace.c
+@@ -56,6 +56,10 @@ void ptrace_untrace(task_t *child)
+ 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 @@ void __ptrace_unlink(task_t *child)
+ SET_LINKS(child);
+ }
+
+- if (child->state == TASK_TRACED)
+- ptrace_untrace(child);
++ ptrace_untrace(child);
+ }
+
+ /*
+diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
+--- a/kernel/rcupdate.c
++++ b/kernel/rcupdate.c
+@@ -154,6 +154,15 @@ void fastcall call_rcu_bh(struct rcu_hea
+ }
+
+ /*
++ * 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 @@ void synchronize_kernel(void)
+ }
+
+ 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
+--- /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 at 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
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -2511,8 +2511,6 @@ void account_system_time(struct task_str
+ 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 @@ EXPORT_SYMBOL(cpu_present_map);
+
+ #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
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -277,7 +277,6 @@ static struct sigqueue *__sigqueue_alloc
+ } 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 *t
+
+ 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 @@ static int check_kill_permission(int sig
+ 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 @@ static int send_signal(int sig, struct s
+ * 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 @@ static int send_signal(int sig, struct s
+ 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 @@ static int send_signal(int sig, struct s
+ 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 @@ specific_send_sig_info(int sig, struct s
+ 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 @@ force_sig_info(int sig, struct siginfo *
+ 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;
++ }
++ if (sigismember(&t->blocked, sig)) {
+ sigdelset(&t->blocked, sig);
+- recalc_sigpending_tsk(t);
+ }
++ recalc_sigpending_tsk(t);
+ ret = specific_send_sig_info(sig, info, t);
+ spin_unlock_irqrestore(&t->sighand->siglock, flags);
+
+@@ -906,15 +895,7 @@ force_sig_info(int sig, struct siginfo *
+ 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 @@ __group_send_sig_info(int sig, struct si
+ 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 @@ void zap_other_threads(struct task_struc
+ 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 @@ send_sig_info(int sig, struct siginfo *i
+ 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 @@ send_group_sig_info(int sig, struct sigi
+ 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 @@ force_sigsegv(int sig, struct task_struc
+ 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 @@ void sigqueue_free(struct sigqueue *q)
+ * pending queue.
+ */
+ if (unlikely(!list_empty(&q->list))) {
+- read_lock(&tasklist_lock);
+- spin_lock_irqsave(q->lock, flags);
++ spinlock_t *lock = ¤t->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 @@ send_sigqueue(int sig, struct sigqueue *
+ 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 @@ send_group_sigqueue(int sig, struct sigq
+ * 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 @@ relock:
+ /* 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,26 +2260,13 @@ sys_kill(int pid, int sig)
+ return kill_something_info(sig, &info, pid);
+ }
+
+-/**
+- * sys_tgkill - send signal to one specific thread
+- * @tgid: the thread group ID of the thread
+- * @pid: the PID of the thread
+- * @sig: signal to be sent
+- *
+- * This syscall also checks the tgid and returns -ESRCH even if the PID
+- * exists but it's not belonging to the target process anymore. This
+- * method solves the problem of threads exiting and PIDs getting reused.
+- */
+-asmlinkage long sys_tgkill(int tgid, int pid, int sig)
++static int do_tkill(int tgid, int pid, int sig)
+ {
+- struct siginfo info;
+ int error;
++ struct siginfo info;
+ struct task_struct *p;
+
+- /* This is only valid for single tasks */
+- if (pid <= 0 || tgid <= 0)
+- return -EINVAL;
+-
++ error = -ESRCH;
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = SI_TKILL;
+@@ -2311,8 +2275,7 @@ asmlinkage long sys_tgkill(int tgid, int
+
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+- error = -ESRCH;
+- if (p && (p->tgid == tgid)) {
++ if (p && (tgid <= 0 || p->tgid == tgid)) {
+ error = check_kill_permission(sig, &info, p);
+ /*
+ * The null signal is a permissions and process existence
+@@ -2326,47 +2289,40 @@ asmlinkage long sys_tgkill(int tgid, int
+ }
+ }
+ read_unlock(&tasklist_lock);
++
+ return error;
+ }
+
++/**
++ * sys_tgkill - send signal to one specific thread
++ * @tgid: the thread group ID of the thread
++ * @pid: the PID of the thread
++ * @sig: signal to be sent
++ *
++ * This syscall also checks the tgid and returns -ESRCH even if the PID
++ * exists but it's not belonging to the target process anymore. This
++ * method solves the problem of threads exiting and PIDs getting reused.
++ */
++asmlinkage long sys_tgkill(int tgid, int pid, int sig)
++{
++ /* This is only valid for single tasks */
++ if (pid <= 0 || tgid <= 0)
++ return -EINVAL;
++
++ return do_tkill(tgid, pid, sig);
++}
++
+ /*
+ * Send a signal to only one task, even if it's a CLONE_THREAD task.
+ */
+ 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
+--- a/kernel/time.c
++++ b/kernel/time.c
+@@ -338,30 +338,20 @@ int do_adjtimex(struct timex *txc)
+ 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 @@ leave: if ((time_status & (STA_UNSYNC|ST
+ 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 @@ int do_settimeofday (struct timespec *tv
+ 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
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -46,6 +46,10 @@ static void time_interpolator_update(lon
+ #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 @@ static inline void set_running_timer(tve
+ #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 @@ void fastcall init_timer(struct timer_li
+ {
+ 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 __mod_timer(struct timer_list *timer
+ int ret = 0;
+
+ BUG_ON(!timer->function);
+- check_timer(timer);
+
+ base = lock_timer_base(timer, &flags);
+
+@@ -283,9 +261,6 @@ void add_timer_on(struct timer_list *tim
+ 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 @@ int mod_timer(struct timer_list *timer,
+ {
+ 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 @@ int del_timer(struct timer_list *timer)
+ 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 @@ out:
+ */
+ 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 @@ long time_next_adjust;
+ */
+ 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");
+- }
+- 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;
+- }
+-
+- /*
+- * 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 {
++ /* 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");
++ }
++ 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;
++ }
++
++ /*
++ * 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 @@ static void update_wall_time_one_tick(vo
+ {
+ 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 @@ static void update_wall_time_one_tick(vo
+ * 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 @@ fastcall signed long __sched schedule_ti
+ 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 @@ fastcall signed long __sched schedule_ti
+
+ 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 @@ EXPORT_SYMBOL(schedule_timeout);
+ */
+ 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 @@ static void time_interpolator_update(lon
+ 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
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -12,6 +12,8 @@
+ * Andrew Morton <andrewm at uow.edu.au>
+ * Kai Petzke <wpp at marie.physik.tu-berlin.de>
+ * Theodore Ts'o <tytso at mit.edu>
++ *
++ * Made to use alloc_percpu by Christoph Lameter <clameter at sgi.com>.
+ */
+
+ #include <linux/module.h>
+@@ -57,7 +59,7 @@ struct cpu_workqueue_struct {
+ * 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 @@ int fastcall queue_work(struct workqueue
+ 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 @@ static void delayed_work_timer_fn(unsign
+ 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 @@ void fastcall flush_workqueue(struct wor
+
+ 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 @@ void fastcall flush_workqueue(struct wor
+ 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 @@ struct workqueue_struct *__create_workqu
+ 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 @@ static void cleanup_workqueue_thread(str
+ 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 @@ void destroy_workqueue(struct workqueue_
+ spin_unlock(&workqueue_lock);
+ }
+ unlock_cpu_hotplug();
++ free_percpu(wq->cpu_wq);
+ kfree(wq);
+ }
+
+@@ -458,7 +462,7 @@ int current_is_keventd(void)
+
+ 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 @@ int current_is_keventd(void)
+ /* 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 @@ static void take_over_work(struct workqu
+ 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 @@ static int __devinit workqueue_cpu_callb
+ 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
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -128,7 +128,7 @@ config DEBUG_HIGHMEM
+ 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 @@ config DEBUG_FS
+
+ 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
+--- a/lib/bitmap.c
++++ b/lib/bitmap.c
+@@ -511,6 +511,172 @@ int bitmap_parselist(const char *bp, uns
+ }
+ 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 at 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
+--- 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
+--- 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 @@ static void free_layer(struct idr *idp,
+ * 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 @@ static int sub_alloc(struct idr *idp, vo
+ 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 @@ static int idr_get_new_above_int(struct
+ {
+ struct idr_layer *p, *new;
+ int layers, v, id;
+-
++
+ id = starting_id;
+ build_up:
+ p = idp->top;
+@@ -225,6 +225,7 @@ build_up:
+ 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 @@ EXPORT_SYMBOL(idr_get_new_above);
+ 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 @@ static void sub_remove(struct idr *idp,
+ free_layer(idp, **paa);
+ **paa-- = NULL;
+ }
+- if ( ! *paa )
++ if (!*paa)
+ idp->layers = 0;
+- } else {
++ } else
+ idr_remove_warning(id);
+- }
+ }
+
+ /**
+@@ -326,9 +327,8 @@ void idr_remove(struct idr *idp, int id)
+ 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 @@ void idr_remove(struct idr *idp, int id)
+ --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 @@ void *idr_find(struct idr *idp, int id)
+ }
+ 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 void idr_cache_ctor(void * idr_la
+ 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
+--- 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 @@ static void fill_kobj_path(struct kobjec
+ * @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
+--- a/lib/kobject_uevent.c
++++ b/lib/kobject_uevent.c
+@@ -54,7 +54,7 @@ static char *action_to_string(enum kobje
+ 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 @@ static struct sock *uevent_sock;
+ * @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 send_uevent(const char *signa
+ }
+
+ 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
+--- 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
+--- 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
+--- a/lib/string.c
++++ b/lib/string.c
+@@ -36,11 +36,13 @@ int strnicmp(const char *s1, const char
+ /* 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 @@ int strnicmp(const char *s1, const char
+ }
+ return (int)c1 - (int)c2;
+ }
+-
+ EXPORT_SYMBOL(strnicmp);
+ #endif
+
+@@ -66,7 +67,7 @@ EXPORT_SYMBOL(strnicmp);
+ * @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 @@ EXPORT_SYMBOL(strcpy);
+ * 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 strlcpy(char *dest, const char *s
+ 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 @@ EXPORT_SYMBOL(strlcpy);
+ * @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 @@ char * strcat(char * dest, const char *
+ dest++;
+ while ((*dest++ = *src++) != '\0')
+ ;
+-
+ return tmp;
+ }
+ EXPORT_SYMBOL(strcat);
+@@ -162,7 +163,7 @@ EXPORT_SYMBOL(strcat);
+ * 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 @@ char * strncat(char *dest, const char *s
+ }
+ }
+ }
+-
+ return tmp;
+ }
+ EXPORT_SYMBOL(strncat);
+@@ -216,15 +216,14 @@ EXPORT_SYMBOL(strlcat);
+ * @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 @@ EXPORT_SYMBOL(strcmp);
+ * @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 @@ EXPORT_SYMBOL(strncmp);
+ * @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 @@ EXPORT_SYMBOL(strchr);
+ * @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 @@ EXPORT_SYMBOL(strrchr);
+ 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 @@ EXPORT_SYMBOL(strnchr);
+ * 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 @@ EXPORT_SYMBOL(strlen);
+ * @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 @@ size_t strspn(const char *s, const char
+ return count;
+ ++count;
+ }
+-
+ return count;
+ }
+
+@@ -384,9 +381,8 @@ size_t strcspn(const char *s, const char
+ }
+ ++count;
+ }
+-
+ return count;
+-}
++}
+ EXPORT_SYMBOL(strcspn);
+
+ #ifndef __HAVE_ARCH_STRPBRK
+@@ -395,14 +391,14 @@ EXPORT_SYMBOL(strcspn);
+ * @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 @@ EXPORT_SYMBOL(strpbrk);
+ * 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 @@ char * strsep(char **s, const char *ct)
+ if (end)
+ *end++ = '\0';
+ *s = end;
+-
+ return sbegin;
+ }
+-
+ EXPORT_SYMBOL(strsep);
+ #endif
+
+@@ -449,13 +444,12 @@ EXPORT_SYMBOL(strsep);
+ *
+ * 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 @@ EXPORT_SYMBOL(memset);
+ * 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 @@ EXPORT_SYMBOL(memcpy);
+ *
+ * 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 @@ EXPORT_SYMBOL(memmove);
+ * @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 @@ EXPORT_SYMBOL(memcmp);
+ * 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 @@ EXPORT_SYMBOL(memscan);
+ * @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 @@ void *memchr(const void *s, int c, size_
+ 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
+--- a/lib/textsearch.c
++++ b/lib/textsearch.c
+@@ -254,7 +254,7 @@ unsigned int textsearch_find_continuous(
+ * 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
+--- 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/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
+--- a/lib/zlib_inflate/inflate.c
++++ b/lib/zlib_inflate/inflate.c
+@@ -3,7 +3,6 @@
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+-#include <linux/module.h>
+ #include <linux/zutil.h>
+ #include "infblock.h"
+ #include "infutil.h"
+diff --git a/mm/Kconfig b/mm/Kconfig
+--- a/mm/Kconfig
++++ b/mm/Kconfig
+@@ -111,3 +111,24 @@ config SPARSEMEM_STATIC
+ 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
+--- a/mm/Makefile
++++ b/mm/Makefile
+@@ -18,5 +18,5 @@ obj-$(CONFIG_NUMA) += mempolicy.o
+ 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
+--- a/mm/bootmem.c
++++ b/mm/bootmem.c
+@@ -305,6 +305,7 @@ static unsigned long __init free_all_boo
+ 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
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -66,7 +66,7 @@ generic_file_direct_IO(int rw, struct ki
+ *
+ * ->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 @@ generic_file_direct_IO(int rw, struct ki
+ * ->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 @@ static int sync_page(void *word)
+ * 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 @@ int filemap_write_and_wait_range(struct
+ * 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 @@ int add_to_page_cache(struct page *page,
+ 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 @@ EXPORT_SYMBOL(find_lock_page);
+ * 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 @@ struct page *
+ 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 @@ __generic_file_aio_read(struct kiocb *io
+ 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 @@ repeat:
+ 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 @@ repeat:
+
+ return 0;
+ }
++EXPORT_SYMBOL(filemap_populate);
+
+ struct vm_operations_struct generic_file_vm_ops = {
+ .nopage = filemap_nopage,
+@@ -1555,7 +1556,6 @@ int generic_file_mmap(struct file * file
+ 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
+--- a/mm/filemap_xip.c
++++ b/mm/filemap_xip.c
+@@ -174,6 +174,8 @@ __xip_unmap (struct address_space * mapp
+ 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 @@ __xip_unmap (struct address_space * mapp
+ 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 @@ xip_file_nopage(struct vm_area_struct *
+
+ 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 @@ xip_file_nopage(struct vm_area_struct *
+ page = ZERO_PAGE(address);
+ }
+
++out:
++ page_cache_get(page);
+ return page;
+ }
+
+diff --git a/mm/fremap.c b/mm/fremap.c
+--- 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 @@ int install_page(struct mm_struct *mm, s
+ 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 @@ int install_page(struct mm_struct *mm, s
+ 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 @@ int install_file_pte(struct mm_struct *m
+ 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
+--- 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 @@ static void page_pool_free(void *page, v
+ * 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 @@ int init_emergency_isa_pool(void)
+ 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
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -277,19 +277,23 @@ int copy_hugetlb_page_range(struct mm_st
+ 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 @@ void unmap_hugepage_range(struct vm_area
+ 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 @@ void unmap_hugepage_range(struct vm_area
+
+ 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));
+ }
+- flush_tlb_range(vma, start, end);
+-}
+-
+-void zap_hugepage_range(struct vm_area_struct *vma,
+- unsigned long start, unsigned long length)
+-{
+- struct mm_struct *mm = vma->vm_mm;
+
+- spin_lock(&mm->page_table_lock);
+- unmap_hugepage_range(vma, start, start + length);
+ spin_unlock(&mm->page_table_lock);
++ flush_tlb_range(vma, start, end);
+ }
+
+-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
++static struct page *find_lock_huge_page(struct address_space *mapping,
++ unsigned long idx)
+ {
+- struct mm_struct *mm = current->mm;
+- unsigned long addr;
+- int ret = 0;
+-
+- WARN_ON(!is_vm_hugetlb_page(vma));
+- BUG_ON(vma->vm_start & ~HPAGE_MASK);
+- BUG_ON(vma->vm_end & ~HPAGE_MASK);
+-
+- 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;
+- }
++ struct page *page;
++ int err;
++ struct inode *inode = mapping->host;
++ unsigned long size;
++
++retry:
++ page = find_lock_page(mapping, idx);
++ if (page)
++ goto out;
++
++ /* Check to make sure the mapping hasn't been truncated */
++ size = i_size_read(inode) >> HPAGE_SHIFT;
++ if (idx >= size)
++ goto out;
++
++ if (hugetlb_get_quota(mapping))
++ goto out;
++ page = alloc_huge_page();
++ if (!page) {
++ hugetlb_put_quota(mapping);
++ 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 @@ int follow_hugetlb_page(struct mm_struct
+ 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;
+
+- 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;
+- }
++ /*
++ * 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) {
+ 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
+--- a/mm/madvise.c
++++ b/mm/madvise.c
+@@ -126,7 +126,7 @@ static long madvise_dontneed(struct vm_a
+ 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
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -114,6 +114,7 @@ static void free_pte_range(struct mmu_ga
+ {
+ 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 @@ void free_pgd_range(struct mmu_gather **
+ 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 @@ void free_pgtables(struct mmu_gather **t
+ 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 @@ void free_pgtables(struct mmu_gather **t
+ 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 @@ void free_pgtables(struct mmu_gather **t
+ }
+ }
+
+-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 @@ copy_one_pte(struct mm_struct *dst_mm, s
+ /* 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;
+ }
+
+- 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 region is VM_RESERVED, the mapping is not
++ * mapped via rmap - duplicate the pte as is.
+ */
+- page = NULL;
+- if (pfn_valid(pfn))
+- page = pfn_to_page(pfn);
++ if (vm_flags & VM_RESERVED)
++ goto out_set_pte;
+
+- if (!page || PageReserved(page)) {
+- set_pte_at(dst_mm, addr, dst_pte, pte);
+- return;
++ pfn = pte_pfn(pte);
++ /* If the pte points outside of valid memory but
++ * the region is not VM_RESERVED, we have a problem.
++ */
++ 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 @@ copy_one_pte(struct mm_struct *dst_mm, s
+ 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 @@ static int copy_pte_range(struct mm_stru
+ 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 @@ int copy_page_range(struct mm_struct *ds
+ 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 @@ static void zap_pte_range(struct mmu_gat
+ 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 @@ static void zap_pte_range(struct mmu_gat
+ 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 @@ static void zap_pte_range(struct mmu_gat
+ 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 @@ static inline void zap_pmd_range(struct
+ 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 @@ static inline void zap_pud_range(struct
+ 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 @@ static void unmap_page_range(struct mmu_
+ 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 @@ static void unmap_page_range(struct mmu_
+ /**
+ * 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 @@ static void unmap_page_range(struct mmu_
+ *
+ * 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 @@ static void unmap_page_range(struct mmu_
+ * 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 @@ unsigned long unmap_vmas(struct mmu_gath
+ 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 @@ unsigned long unmap_vmas(struct mmu_gath
+ 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 zap_page_range(struct vm_a
+ 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 no_page_table;
++
++ if (pmd_huge(*pmd)) {
++ BUG_ON(flags & FOLL_GET);
++ page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
+ goto out;
+- if (pmd_huge(*pmd))
+- return follow_huge_pmd(mm, address, pmd, write);
++ }
+
+- ptep = pte_offset_map(pmd, address);
++ 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;
+-}
+-
+-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;
++ return page;
+
+- /* 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 @@ int get_user_pages(struct task_struct *t
+ 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 @@ int get_user_pages(struct task_struct *t
+ 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 @@ int get_user_pages(struct task_struct *t
+ &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))) {
+- 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);
++ if (write)
++ foll_flags |= FOLL_WRITE;
+
++ cond_resched();
++ while (!(page = follow_page(mm, start, foll_flags))) {
++ int ret;
++ 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 @@ int get_user_pages(struct task_struct *t
+ * 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 @@ int get_user_pages(struct task_struct *t
+ 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 @@ int get_user_pages(struct task_struct *t
+ start += PAGE_SIZE;
+ len--;
+ } while (len && start < vma->vm_end);
+- spin_unlock(&mm->page_table_lock);
+ } while (len);
+ return i;
+ }
+@@ -1024,16 +1018,21 @@ static int zeromap_pte_range(struct mm_s
+ 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 @@ int zeromap_page_range(struct vm_area_st
+ 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 @@ static int remap_pte_range(struct mm_str
+ 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 @@ int remap_pfn_range(struct vm_area_struc
+ * 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 @@ int remap_pfn_range(struct vm_area_struc
+ 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 @@ int remap_pfn_range(struct vm_area_struc
+ 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 @@ static inline pte_t maybe_mkwrite(pte_t
+ }
+
+ /*
+- * 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 @@ static inline void break_cow(struct vm_a
+ * 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.
+- */
+-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)
++ * 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,
++ 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 @@ static int do_wp_page(struct mm_struct *
+ 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 @@ static int do_wp_page(struct mm_struct *
+ 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 @@ again:
+
+ 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 @@ void swapin_readahead(swp_entry_t entry,
+ }
+
+ /*
+- * We hold the mm semaphore and the page_table_lock on entry and
+- * should release the pagetable lock on exit..
+- */
+-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)
++ * 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,
++ 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 @@ static int do_swap_page(struct mm_struct
+ 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 @@ static int do_swap_page(struct mm_struct
+
+ /* 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 @@ static int do_swap_page(struct mm_struct
+
+ 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 @@ static int do_swap_page(struct mm_struct
+ /* 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.
+- */
+-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)
++ * 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,
++ 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 @@ no_mem:
+ * 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.
+- */
+-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)
++ * 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, 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 @@ do_no_page(struct mm_struct *mm, struct
+ 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 @@ retry:
+ 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 @@ retry:
+ */
+ /* 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.
+- */
+-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)
++ *
++ * 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, 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);
+- }
+-
+- pgoff = pte_to_pgoff(*pte);
++ if (!pte_unmap_same(mm, pmd, page_table, orig_pte))
++ return VM_FAULT_MINOR;
+
+- pte_unmap(pte);
+- spin_unlock(&mm->page_table_lock);
++ 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 */
+
+- 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 @@ static int do_file_page(struct mm_struct
+ * 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 @@ int __handle_mm_fault(struct mm_struct *
+ 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 @@ unsigned long vmalloc_to_pfn(void * vmal
+
+ 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 @@ static int __init gate_vma_init(void)
+ 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
+--- /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
+--- 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 @@ struct mempolicy default_policy = {
+ .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 @@ static int mpol_check_policy(int mode, u
+ 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 @@ static struct zonelist *bind_zonelist(un
+ 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 @@ static struct mempolicy *mpol_new(int mo
+ 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 @@ static struct mempolicy *mpol_new(int mo
+ }
+
+ /* 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 @@ static int check_pte_range(struct mm_str
+ 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 @@ static inline int check_pmd_range(struct
+ 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 @@ static inline int check_pud_range(struct
+ 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 @@ static inline int check_pgd_range(struct
+ /* 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 @@ check_range(struct mm_struct *mm, unsign
+ 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 @@ check_range(struct mm_struct *mm, unsign
+ 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 @@ static int mbind_range(struct vm_area_st
+ 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 @@ asmlinkage long sys_mbind(unsigned long
+ 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 @@ asmlinkage long sys_mbind(unsigned long
+ }
+
+ /* 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 @@ static int lookup_node(struct mm_struct
+ 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 @@ asmlinkage long sys_get_mempolicy(int __
+ 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(¤t->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 @@ asmlinkage long sys_get_mempolicy(int __
+ 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 @@ asmlinkage long compat_sys_mbind(compat_
+ 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 @@ get_vma_policy(struct task_struct *task,
+
+ 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 @@ static struct zonelist *zonelist_policy(
+ 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 @@ static struct zonelist *zonelist_policy(
+ 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 @@ static unsigned interleave_nodes(struct
+ 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 interleave_nodes(struct
+ 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 @@ alloc_page_vma(gfp_t gfp, struct vm_area
+ 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 @@ int __mpol_equal(struct mempolicy *a, st
+ 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 @@ int mpol_set_shared_policy(struct shared
+ 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 @@ void __init numa_policy_init(void)
+ /* 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
+--- a/mm/mempool.c
++++ b/mm/mempool.c
+@@ -205,7 +205,7 @@ void * mempool_alloc(mempool_t *pool, gf
+ 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
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -181,26 +181,36 @@ static void __remove_shared_vm_struct(st
+ }
+
+ /*
+- * 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 @@ none:
+ }
+
+ #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 @@ munmap_back:
+ 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 at 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 @@ munmap_back:
+ }
+ 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 @@ static int acct_stack_growth(struct vm_a
+ 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 @@ int expand_stack(struct vm_area_struct *
+ 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 @@ find_extend_vma(struct mm_struct * mm, u
+ }
+ #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 @@ static void unmap_region(struct mm_struc
+ 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 @@ int do_munmap(struct mm_struct *mm, unsi
+ 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 @@ asmlinkage long sys_munmap(unsigned long
+
+ 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 @@ void exit_mmap(struct mm_struct *mm)
+ 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.
+- */
+- while (vma) {
+- struct vm_area_struct *next = vma->vm_next;
+- remove_vm_struct(vma);
+- vma = next;
+- }
++ /*
++ * Walk the list again, actually closing and freeing it,
++ * with preemption enabled, without holding any MM locks.
++ */
++ 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
+--- a/mm/mprotect.c
++++ b/mm/mprotect.c
+@@ -29,8 +29,9 @@ static void change_pte_range(struct mm_s
+ 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 @@ static void change_pte_range(struct mm_s
+ 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 @@ static void change_protection(struct vm_
+ 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 @@ static void change_protection(struct vm_
+ 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 @@ mprotect_fixup(struct vm_area_struct *vm
+ * 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 at 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 @@ success:
+ 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
+--- 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 @@ static pte_t *get_one_pte_map(struct mm_
+ 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 @@ move_one_page(struct vm_area_struct *vma
+ 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);
+-
+- /* 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);
+- }
+- spin_unlock(&mm->page_table_lock);
++ /*
++ * 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);
++
++ 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);
++ }
++
++ 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 @@ static unsigned long move_vma(struct vm_
+ unsigned long new_pgoff;
+ unsigned long moved_len;
+ unsigned long excess = 0;
++ unsigned long hiwater_vm;
+ int split = 0;
+
+ /*
+@@ -229,17 +201,24 @@ static unsigned long move_vma(struct vm_
+ }
+
+ /*
+- * 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 do_mremap(unsigned long ad
+ 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 @@ unsigned long do_mremap(unsigned long ad
+ 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 @@ unsigned long do_mremap(unsigned long ad
+ * 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 @@ unsigned long do_mremap(unsigned long ad
+ * 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 @@ unsigned long do_mremap(unsigned long ad
+ }
+ 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 @@ unsigned long do_mremap(unsigned long ad
+ 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
+--- 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 @@ static inline void sync_pmd_range(struct
+ 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,58 +84,34 @@ static inline void sync_pud_range(struct
+ 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 @@ static int msync_interval(struct vm_area
+ 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
+--- a/mm/nommu.c
++++ b/mm/nommu.c
+@@ -931,6 +931,8 @@ int do_munmap(struct mm_struct *mm, unsi
+ realalloc -= kobjsize(vml);
+ askedalloc -= sizeof(*vml);
+ kfree(vml);
++
++ update_hiwater_vm(mm);
+ mm->total_vm -= len >> PAGE_SHIFT;
+
+ #ifdef DEBUG
+@@ -1047,7 +1049,8 @@ struct vm_area_struct *find_vma(struct m
+
+ 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 arch_unmap_area(struct mm_struct *m
+ {
+ }
+
+-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
+--- 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 @@ int min_free_kbytes = 1024;
+ 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)
+- return 1;
+-#ifdef CONFIG_HOLES_IN_ZONE
+- if (!pfn_valid(page_to_pfn(page)))
+- return 1;
+-#endif
+- if (zone != page_zone(page))
++ if (!page_is_consistent(zone, page))
+ return 1;
++
+ return 0;
+ }
+
+@@ -114,7 +138,8 @@ static void bad_page(const char *functio
+ 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 @@ static void prep_compound_page(struct pa
+ struct page *p = page + i;
+
+ SetPageCompound(p);
+- p->private = (unsigned long)page;
++ set_page_private(p, (unsigned long)page);
+ }
+ }
+
+@@ -173,7 +198,7 @@ static void destroy_compound_page(struct
+
+ 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 @@ static void destroy_compound_page(struct
+ * 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 @@ __find_combined_index(unsigned long page
+ * (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 @@ static inline int page_is_buddy(struct p
+ * 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 @@ static inline void free_pages_check(cons
+ 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 @@ static void prep_new_page(struct page *p
+ 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 @@ buffered_rmqueue(struct zone *zone, int
+ * 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 @@ struct page * fastcall
+ __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 @@ fastcall unsigned long get_zeroed_page(g
+ * 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 @@ void __pagevec_free(struct pagevec *pvec
+
+ 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 @@ static unsigned int nr_free_zone_pages(i
+ */
+ 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_buffer_pages(void)
+ */
+ 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 @@ void show_free_areas(void)
+ } 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 @@ static int __init build_zonelists_node(p
+ 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 @@ static void __init build_zonelists(pg_da
+ 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 @@ static void __init build_zonelists(pg_da
+ 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 @@ static void __init calculate_zone_totalp
+ * 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 @@ void __init memmap_init_zone(unsigned lo
+ 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 @@ static int __devinit zone_batchsize(stru
+
+ /*
+ * 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 @@ inline void setup_pageset(struct per_cpu
+
+ 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 @@ inline void setup_pageset(struct per_cpu
+ 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 @@ void __init setup_per_cpu_pageset()
+
+ #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 @@ void __init setup_per_cpu_pageset()
+ 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 @@ static void __init free_area_init_core(s
+ 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 @@ static void __init free_area_init_core(s
+ 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 @@ static void __init free_area_init_core(s
+ 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 @@ static void setup_per_zone_lowmem_reserv
+ * 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
+--- a/mm/page_io.c
++++ b/mm/page_io.c
+@@ -91,7 +91,8 @@ int swap_writepage(struct page *page, st
+ 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 @@ int swap_readpage(struct file *file, str
+
+ 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
+--- 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(struct pdflush_work
+ 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
+--- 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 @@ unsigned long page_address_in_vma(struct
+ /*
+ * 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;
++ }
++
++ ptl = pte_lockptr(mm, pmd);
++ spin_lock(ptl);
++ if (pte_present(*pte) && page_to_pfn(page) == pte_pfn(*pte)) {
++ *ptlp = ptl;
++ return pte;
+ }
+- spin_unlock(&mm->page_table_lock);
+- return ERR_PTR(-ENOENT);
++ pte_unmap_unlock(pte, ptl);
++ return NULL;
+ }
+
+ /*
+@@ -287,24 +294,28 @@ static int page_referenced_one(struct pa
+ 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 @@ int page_referenced(struct page *page, i
+ * @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 @@ void page_add_anon_rmap(struct page *pag
+ * 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 @@ void page_add_file_rmap(struct page *pag
+ * 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 @@ static int try_to_unmap_one(struct page
+ 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 @@ static int try_to_unmap_one(struct page
+ 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 @@ static int try_to_unmap_one(struct page
+ 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 @@ static void try_to_unmap_cluster(unsigne
+ 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 @@ static void try_to_unmap_cluster(unsigne
+
+ 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;
++
++ pte = pte_offset_map_lock(mm, pmd, address, &ptl);
+
+- for (original_pte = pte = pte_offset_map(pmd, address);
+- address < end; pte++, address += PAGE_SIZE) {
++ /* 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 @@ static void try_to_unmap_cluster(unsigne
+
+ 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 try_to_unmap(struct page *page)
+ {
+ int ret;
+
+- BUG_ON(PageReserved(page));
+ BUG_ON(!PageLocked(page));
+
+ if (PageAnon(page))
+diff --git a/mm/shmem.c b/mm/shmem.c
+--- 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 @@ enum sgp_type {
+ 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 @@ static void shmem_swp_set(struct shmem_i
+
+ 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 @@ static swp_entry_t *shmem_swp_alloc(stru
+
+ 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 @@ static void shmem_truncate(struct inode
+ 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 @@ static void shmem_truncate(struct inode
+ 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 @@ static int shmem_unuse_inode(struct shme
+ 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 @@ struct page *shmem_swapin(struct shmem_i
+ }
+
+ 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 @@ static int shmem_populate(struct vm_area
+ 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 @@ static void do_shmem_file_read(struct fi
+ */
+ 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
+--- a/mm/slab.c
++++ b/mm/slab.c
+@@ -386,7 +386,7 @@ struct kmem_cache_s {
+ 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 @@ static void cache_init_objs(kmem_cache_t
+ 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 @@ static int cache_grow(kmem_cache_t *cach
+ 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 @@ retry:
+ 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 @@ static inline void *__cache_alloc(kmem_c
+ /*
+ * 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 @@ static void free_block(kmem_cache_t *cac
+ 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
+--- 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 @@ static inline int sparse_index_init(unsi
+ }
+ #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 @@ static struct page *sparse_early_mem_map
+ 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 @@ void sparse_init(void)
+ * 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
+--- a/mm/swap.c
++++ b/mm/swap.c
+@@ -39,7 +39,7 @@ int page_cluster;
+ 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 @@ void put_page(struct page *page)
+ }
+ 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 @@ void release_pages(struct page **pages,
+ 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);
+@@ -259,6 +259,8 @@ void __pagevec_release(struct pagevec *p
+ pagevec_reinit(pvec);
+ }
+
++EXPORT_SYMBOL(__pagevec_release);
++
+ /*
+ * pagevec_release() for pages which are known to not be on the LRU
+ *
+@@ -270,7 +272,6 @@ void __pagevec_release_nonlru(struct pag
+ 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];
+
+@@ -388,6 +389,7 @@ unsigned pagevec_lookup_tag(struct pagev
+ return pagevec_count(pvec);
+ }
+
++EXPORT_SYMBOL(pagevec_lookup_tag);
+
+ #ifdef CONFIG_SMP
+ /*
+diff --git a/mm/swap_state.c b/mm/swap_state.c
+--- a/mm/swap_state.c
++++ b/mm/swap_state.c
+@@ -83,7 +83,7 @@ static int __add_to_swap_cache(struct pa
+ 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 @@ void __delete_from_swap_cache(struct pag
+ 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 @@ void delete_from_swap_cache(struct page
+ {
+ 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 @@ static inline void free_swap_cache(struc
+
+ /*
+ * 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
+--- a/mm/swapfile.c
++++ b/mm/swapfile.c
+@@ -61,7 +61,7 @@ void swap_unplug_io_fn(struct backing_de
+ 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 @@ void swap_unplug_io_fn(struct backing_de
+ /*
+ * 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 @@ static inline int page_swapcount(struct
+ 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 @@ int remove_exclusive_swap_page(struct pa
+ 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 @@ void free_swap_and_cache(swp_entry_t ent
+ }
+
+ /*
+- * 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 @@ static int unuse_pte_range(struct vm_are
+ 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 @@ static int unuse_mm(struct mm_struct *mm
+ 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 @@ int page_queue_congested(struct page *pa
+ 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
+--- a/mm/thrash.c
++++ b/mm/thrash.c
+@@ -19,7 +19,7 @@ static unsigned long swap_token_check;
+ 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
+--- a/mm/tiny-shmem.c
++++ b/mm/tiny-shmem.c
+@@ -31,11 +31,14 @@ static struct vfsmount *shm_mnt;
+
+ 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
+--- 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
+--- 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 at 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 @@ static int vmap_pte_range(pmd_t *pmd, un
+ {
+ 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 @@ int map_vm_area(struct vm_struct *area,
+
+ 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 @@ struct vm_struct *__get_vm_area(unsigned
+ 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 @@ out:
+ 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 @@ struct vm_struct *get_vm_area(unsigned l
+ 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 @@ void vfree(void *addr)
+ BUG_ON(in_interrupt());
+ __vunmap(addr, 1);
+ }
+-
+ EXPORT_SYMBOL(vfree);
+
+ /**
+@@ -360,7 +369,6 @@ void vunmap(void *addr)
+ BUG_ON(in_interrupt());
+ __vunmap(addr, 0);
+ }
+-
+ EXPORT_SYMBOL(vunmap);
+
+ /**
+@@ -392,10 +400,10 @@ void *vmap(struct page **pages, unsigned
+
+ 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 @@ void *__vmalloc_area(struct vm_struct *a
+ 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 @@ void *__vmalloc_area(struct vm_struct *a
+ 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 @@ fail:
+ 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 @@ void *__vmalloc(unsigned long size, gfp_
+ 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 @@ void *vmalloc(unsigned long size)
+ {
+ 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 @@ void *vmalloc_32(unsigned long size)
+ {
+ 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
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -70,7 +70,7 @@ struct scan_control {
+ unsigned int priority;
+
+ /* This context's GFP mask */
+- unsigned int gfp_mask;
++ gfp_t gfp_mask;
+
+ int may_writepage;
+
+@@ -186,7 +186,7 @@ EXPORT_SYMBOL(remove_shrinker);
+ *
+ * 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 @@ static int shrink_list(struct list_head
+ * 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 @@ static int shrink_list(struct list_head
+
+ #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 @@ shrink_caches(struct zone **zones, struc
+ * 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 @@ module_init(kswapd_init)
+ /*
+ * 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
+--- a/net/bluetooth/af_bluetooth.c
++++ b/net/bluetooth/af_bluetooth.c
+@@ -308,12 +308,6 @@ static struct net_proto_family bt_sock_f
+ .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
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -87,7 +87,7 @@ int hci_unregister_notifier(struct notif
+ 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 @@ static inline void hci_scodata_packet(st
+ 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
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -66,20 +66,20 @@ static struct hci_sec_filter hci_sec_fil
+ /* 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
+--- 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
+--- a/net/bluetooth/hidp/core.c
++++ b/net/bluetooth/hidp/core.c
+@@ -520,7 +520,7 @@ static int hidp_session(void *arg)
+
+ if (session->input) {
+ input_unregister_device(session->input);
+- kfree(session->input);
++ session->input = NULL;
+ }
+
+ up_write(&hidp_session_sem);
+@@ -536,6 +536,8 @@ static inline void hidp_setup_input(stru
+
+ 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 @@ int hidp_add_connection(struct hidp_conn
+ 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 @@ unlink:
+
+ __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
+--- 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
+--- a/net/bluetooth/rfcomm/core.c
++++ b/net/bluetooth/rfcomm/core.c
+@@ -133,6 +133,49 @@ static inline void rfcomm_session_put(st
+
+ /* ---- 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
+--- 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 at qualcomm.com>
+- Copyright (C) 2002 Marcel Holtmann <marcel at 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/bridge/br_fdb.c b/net/bridge/br_fdb.c
+--- a/net/bridge/br_fdb.c
++++ b/net/bridge/br_fdb.c
+@@ -86,8 +86,8 @@ void br_fdb_changeaddr(struct net_bridge
+ struct net_bridge_port *op;
+ list_for_each_entry(op, &br->port_list, list) {
+ if (op != p &&
+- !memcmp(op->dev->dev_addr,
+- f->addr.addr, ETH_ALEN)) {
++ !compare_ether_addr(op->dev->dev_addr,
++ f->addr.addr)) {
+ f->dst = op;
+ goto insert;
+ }
+@@ -151,8 +151,8 @@ void br_fdb_delete_by_port(struct net_br
+ struct net_bridge_port *op;
+ list_for_each_entry(op, &br->port_list, list) {
+ if (op != p &&
+- !memcmp(op->dev->dev_addr,
+- f->addr.addr, ETH_ALEN)) {
++ !compare_ether_addr(op->dev->dev_addr,
++ f->addr.addr)) {
+ f->dst = op;
+ goto skip_delete;
+ }
+@@ -174,7 +174,7 @@ struct net_bridge_fdb_entry *__br_fdb_ge
+ struct net_bridge_fdb_entry *fdb;
+
+ hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) {
+- if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
++ if (!compare_ether_addr(fdb->addr.addr, addr)) {
+ if (unlikely(has_expired(br, fdb)))
+ break;
+ return fdb;
+@@ -264,7 +264,7 @@ static inline struct net_bridge_fdb_entr
+ struct net_bridge_fdb_entry *fdb;
+
+ hlist_for_each_entry_rcu(fdb, h, head, hlist) {
+- if (!memcmp(fdb->addr.addr, addr, ETH_ALEN))
++ if (!compare_ether_addr(fdb->addr.addr, addr))
+ return fdb;
+ }
+ return NULL;
+diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
+--- a/net/bridge/br_input.c
++++ b/net/bridge/br_input.c
+@@ -128,7 +128,7 @@ int br_handle_frame(struct net_bridge_po
+ dest = eth_hdr(skb)->h_dest;
+ }
+
+- if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
++ if (!compare_ether_addr(p->br->dev->dev_addr, dest))
+ skb->pkt_type = PACKET_HOST;
+
+ NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
+--- a/net/bridge/br_stp_if.c
++++ b/net/bridge/br_stp_if.c
+@@ -15,6 +15,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/smp_lock.h>
++#include <linux/etherdevice.h>
+
+ #include "br_private.h"
+ #include "br_private_stp.h"
+@@ -133,10 +134,10 @@ static void br_stp_change_bridge_id(stru
+ memcpy(br->dev->dev_addr, addr, ETH_ALEN);
+
+ list_for_each_entry(p, &br->port_list, list) {
+- if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
++ if (!compare_ether_addr(p->designated_bridge.addr, oldaddr))
+ memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
+
+- if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
++ if (!compare_ether_addr(p->designated_root.addr, oldaddr))
+ memcpy(p->designated_root.addr, addr, ETH_ALEN);
+
+ }
+@@ -157,12 +158,12 @@ void br_stp_recalculate_bridge_id(struct
+
+ list_for_each_entry(p, &br->port_list, list) {
+ if (addr == br_mac_zero ||
+- memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
++ compare_ether_addr(p->dev->dev_addr, addr) < 0)
+ addr = p->dev->dev_addr;
+
+ }
+
+- if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
++ if (compare_ether_addr(br->bridge_id.addr, addr))
+ br_stp_change_bridge_id(br, addr);
+ }
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2717,6 +2717,20 @@ int register_netdevice(struct net_device
+ 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
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -93,6 +93,20 @@ int ethtool_op_get_perm_addr(struct net_
+ }
+
+
++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 @@ static int __ethtool_set_sg(struct net_d
+ 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 @@ static int ethtool_set_tso(struct net_de
+ 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 @@ int dev_ethtool(struct ifreq *ifr)
+ 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_sg);
+ 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
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -1625,12 +1625,9 @@ static int neightbl_fill_info(struct nei
+
+ 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
+--- 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 at 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 at wantstofly.org>
+ * New time handling. Lennert Buytenhek <buytenh at 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 @@ struct pktgen_dev {
+ * 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 @@ struct pktgen_dev {
+ __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_thread {
+ 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 @@ static inline s64 divremdi3(s64 x, s64 y
+
+ /* 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 @@ static inline __u64 pg_div64(__u64 n, __
+ {
+ __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 inline __u64 tv_diff(const struct
+
+ 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_delay_d = 0;
+ 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 @@ static ssize_t proc_pgctrl_write(struct
+
+ 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)
++{
++ 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)
+ {
+- char *p;
+ 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 @@ static int proc_if_read(char *buf , char
+ 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 @@ static int proc_if_read(char *buf , char
+ (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);
+-
+- 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, "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, " 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 @@ done_str:
+ 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 @@ static int proc_if_write(struct file *fi
+ 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 @@ static int proc_if_write(struct file *fi
+ 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);
+- struct pktgen_dev *pkt_dev = NULL;
++ 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,
++};
+
+- if (!t) {
+- printk("pktgen: ERROR: could not find thread in proc_thread_read\n");
+- return -EINVAL;
+- }
++static int pktgen_thread_show(struct seq_file *seq, void *v)
++{
++ struct pktgen_thread *t = seq->private;
++ struct pktgen_dev *pkt_dev = NULL;
+
+- p = buf;
+- p += sprintf(p, "Name: %s max_before_softirq: %d\n",
++ BUG_ON(!t);
++
++ 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 @@ static int proc_thread_write(struct file
+ 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 @@ static void spin(struct pktgen_dev *pkt_
+ 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 @@ static void pktgen_stop_all_threads_ifs(
+ pktgen_stop(t);
+ t = t->next;
+ }
+- thread_unlock();
++ thread_unlock();
+ }
+
+ static int thread_is_running(struct pktgen_thread *t )
+@@ -2552,10 +2513,9 @@ static void pktgen_rem_thread(struct pkt
+
+ 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 @@ static struct pktgen_dev *pktgen_find_de
+ 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 add_dev_to_thread(struct pktg
+ 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 struct pktgen_thread *pktgen_find
+ 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 @@ static int pktgen_create_thread(const ch
+ 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 @@ static int pktgen_remove_device(struct p
+
+ /* 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 pktgen_remove_device(struct p
+ static int __init pg_init(void)
+ {
+ int cpu;
+- printk(version);
++ struct proc_dir_entry *pe;
+
+- module_fname[0] = 0;
+-
+- create_proc_dir();
++ printk(version);
+
+- 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);
++ pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
++ if (!pg_proc_dir)
++ return -ENODEV;
++ pg_proc_dir->owner = THIS_MODULE;
++
++ 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 @@ static void __exit pg_cleanup(void)
+ 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
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -122,6 +122,8 @@ void skb_under_panic(struct sk_buff *skb
+ * __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 @@ struct sk_buff *__alloc_skb(unsigned int
+ 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 @@ unsigned int skb_find_text(struct sk_buf
+ 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_prepare_seq_read);
+ 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
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -940,7 +940,7 @@ static struct sk_buff *sock_alloc_send_p
+ 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/dccp.h b/net/dccp/dccp.h
+--- a/net/dccp/dccp.h
++++ b/net/dccp/dccp.h
+@@ -118,7 +118,6 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_
+ #define DCCP_ADD_STATS_USER(field, val) \
+ SNMP_ADD_STATS_USER(dccp_statistics, field, val)
+
+-extern int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb);
+ extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
+
+ extern int dccp_send_response(struct sock *sk);
+diff --git a/net/dccp/output.c b/net/dccp/output.c
+--- a/net/dccp/output.c
++++ b/net/dccp/output.c
+@@ -12,6 +12,7 @@
+
+ #include <linux/config.h>
+ #include <linux/dccp.h>
++#include <linux/kernel.h>
+ #include <linux/skbuff.h>
+
+ #include <net/sock.h>
+@@ -25,13 +26,20 @@ static inline void dccp_event_ack_sent(s
+ inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
+ }
+
++static inline void dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
++{
++ skb_set_owner_w(skb, sk);
++ WARN_ON(sk->sk_send_head);
++ sk->sk_send_head = skb;
++}
++
+ /*
+ * All SKB's seen here are completely headerless. It is our
+ * job to build the DCCP header, and pass the packet down to
+ * IP so it can do the same plus pass the packet off to the
+ * device.
+ */
+-int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
++static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
+ {
+ if (likely(skb != NULL)) {
+ const struct inet_sock *inet = inet_sk(sk);
+@@ -50,10 +58,21 @@ int dccp_transmit_skb(struct sock *sk, s
+ switch (dcb->dccpd_type) {
+ case DCCP_PKT_DATA:
+ set_ack = 0;
++ /* fall through */
++ case DCCP_PKT_DATAACK:
+ break;
++
+ case DCCP_PKT_SYNC:
+ case DCCP_PKT_SYNCACK:
+ ackno = dcb->dccpd_seq;
++ /* fall through */
++ default:
++ /*
++ * Only data packets should come through with skb->sk
++ * set.
++ */
++ WARN_ON(skb->sk);
++ skb_set_owner_w(skb, sk);
+ break;
+ }
+
+@@ -63,9 +82,6 @@ int dccp_transmit_skb(struct sock *sk, s
+ skb->h.raw = skb_push(skb, dccp_header_size);
+ dh = dccp_hdr(skb);
+
+- if (!skb->sk)
+- skb_set_owner_w(skb, sk);
+-
+ /* Build DCCP header and checksum it. */
+ memset(dh, 0, dccp_header_size);
+ dh->dccph_type = dcb->dccpd_type;
+@@ -393,10 +409,8 @@ int dccp_connect(struct sock *sk)
+
+ DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
+ skb->csum = 0;
+- skb_set_owner_w(skb, sk);
+
+- BUG_TRAP(sk->sk_send_head == NULL);
+- sk->sk_send_head = skb;
++ dccp_skb_entail(sk, skb);
+ dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
+ DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
+
+@@ -425,7 +439,6 @@ void dccp_send_ack(struct sock *sk)
+ skb_reserve(skb, MAX_DCCP_HEADER);
+ skb->csum = 0;
+ DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
+- skb_set_owner_w(skb, sk);
+ dccp_transmit_skb(sk, skb);
+ }
+ }
+@@ -482,7 +495,6 @@ void dccp_send_sync(struct sock *sk, con
+ DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
+ DCCP_SKB_CB(skb)->dccpd_seq = seq;
+
+- skb_set_owner_w(skb, sk);
+ dccp_transmit_skb(sk, skb);
+ }
+
+@@ -495,7 +507,7 @@ void dccp_send_close(struct sock *sk, co
+ {
+ 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)
+@@ -507,10 +519,8 @@ void dccp_send_close(struct sock *sk, co
+ DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
+
+- skb_set_owner_w(skb, sk);
+ if (active) {
+- BUG_TRAP(sk->sk_send_head == NULL);
+- sk->sk_send_head = skb;
++ dccp_skb_entail(sk, skb);
+ dccp_transmit_skb(sk, skb_clone(skb, prio));
+ } else
+ dccp_transmit_skb(sk, skb);
+diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
+--- a/net/decnet/af_decnet.c
++++ b/net/decnet/af_decnet.c
+@@ -719,22 +719,9 @@ static int dn_bind(struct socket *sock,
+ 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
+--- a/net/ethernet/eth.c
++++ b/net/ethernet/eth.c
+@@ -146,19 +146,6 @@ int eth_rebuild_header(struct sk_buff *s
+ 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 @@ __be16 eth_type_trans(struct sk_buff *sk
+ 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 @@ __be16 eth_type_trans(struct sk_buff *sk
+ */
+
+ 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
+--- a/net/ieee80211/Makefile
++++ b/net/ieee80211/Makefile
+@@ -7,5 +7,6 @@ ieee80211-objs := \
+ 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
+--- a/net/ieee80211/ieee80211_crypt.c
++++ b/net/ieee80211/ieee80211_crypt.c
+@@ -41,6 +41,12 @@ void ieee80211_crypt_deinit_entries(stru
+ {
+ 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 @@ void ieee80211_crypt_deinit_entries(stru
+ }
+ 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 @@ void ieee80211_crypt_deinit_handler(unsi
+ 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 @@ void ieee80211_crypt_delayed_deinit(stru
+ * 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 void ieee80211_crypt_null_deinit(
+ }
+
+ 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 @@ static void __exit ieee80211_crypto_dein
+ 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
+--- a/net/ieee80211/ieee80211_crypt_ccmp.c
++++ b/net/ieee80211/ieee80211_crypt_ccmp.c
+@@ -119,7 +119,7 @@ static inline void xor_block(u8 * b, u8
+ }
+
+ 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 @@ static void ccmp_init_blocks(struct cryp
+ 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 @@ static int ieee80211_ccmp_encrypt(struct
+ *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 @@ static int ieee80211_ccmp_decrypt(struct
+ {
+ 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 @@ static int ieee80211_ccmp_decrypt(struct
+ 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 char *ieee80211_ccmp_print_stats(
+ }
+
+ 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
+--- a/net/ieee80211/ieee80211_crypt_tkip.c
++++ b/net/ieee80211/ieee80211_crypt_tkip.c
+@@ -59,8 +59,24 @@ struct ieee80211_tkip_data {
+
+ /* 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 @@ static void *ieee80211_tkip_init(int key
+ 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 @@ static void tkip_mixing_phase2(u8 * WEPS
+ #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;
++
++ if (skb_headroom(skb) < 8 || skb->len < hdr_len)
++ return NULL;
+
+- hdr = (struct ieee80211_hdr *)skb->data;
+ 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 @@ static int ieee80211_tkip_encrypt(struct
+ 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 @@ static int ieee80211_tkip_encrypt(struct
+ 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 @@ static int ieee80211_tkip_decrypt(struct
+ 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 int michael_mic(struct ieee80211_
+
+ 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 @@ static int ieee80211_michael_mic_add(str
+ 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 @@ static void ieee80211_michael_mic_failur
+ 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 @@ static int ieee80211_michael_mic_verify(
+ 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 char *ieee80211_tkip_print_stats(
+ }
+
+ 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
+--- a/net/ieee80211/ieee80211_crypt_wep.c
++++ b/net/ieee80211/ieee80211_crypt_wep.c
+@@ -229,19 +229,19 @@ static char *prism2_wep_print_stats(char
+ }
+
+ 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
+--- /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 at 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
+--- 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,13 +53,16 @@
+
+ #include <net/ieee80211.h>
+
+-MODULE_DESCRIPTION("802.11 data/management/control stack");
+-MODULE_AUTHOR
+- ("Copyright (C) 2004 Intel Corporation <jketreno at linux.intel.com>");
++#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 at linux.intel.com>"
++
++MODULE_VERSION(DRV_VERSION);
++MODULE_DESCRIPTION(DRV_DESCRIPTION);
++MODULE_AUTHOR(DRV_COPYRIGHT);
+ MODULE_LICENSE("GPL");
+
+-#define DRV_NAME "ieee80211"
+-
+ static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
+ {
+ if (ieee->networks)
+@@ -126,26 +129,34 @@ struct net_device *alloc_ieee80211(int s
+
+ /* 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 @@ void free_ieee80211(struct net_device *d
+
+ 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 show_debug_level(char *page,
+ 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 @@ static int __init ieee80211_init(void)
+ 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
+--- 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 at cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline at 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 @@ static struct ieee80211_frag_entry *ieee
+
+ /* 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 @@ static struct sk_buff *ieee80211_frag_ca
+ 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 @@ static struct sk_buff *ieee80211_frag_ca
+
+ /* 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 @@ ieee80211_rx_frame_mgmt(struct ieee80211
+ 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 @@ static int ieee80211_is_eapol_frame(stru
+ {
+ 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 @@ static inline int
+ 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 @@ ieee80211_rx_frame_decrypt_msdu(struct i
+ 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 @@ int ieee80211_rx(struct ieee80211_device
+ 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 @@ int ieee80211_rx(struct ieee80211_device
+ 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 @@ int ieee80211_rx(struct ieee80211_device
+ 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 @@ int ieee80211_rx(struct ieee80211_device
+
+ /* 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 @@ int ieee80211_rx(struct ieee80211_device
+ (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 @@ int ieee80211_rx(struct ieee80211_device
+ /* 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 @@ int ieee80211_rx(struct ieee80211_device
+ 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 @@ int ieee80211_rx(struct ieee80211_device
+
+ #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)
+ {
+-#ifdef CONFIG_IEEE80211_DEBUG
+- char rates_str[64];
+- char *p;
+-#endif
+- struct ieee80211_info_element *info_element;
+- u16 left;
+- u8 i;
++ int ret = 0;
++ u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
+
+- /* 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 ((info_element == NULL) || (element_param == NULL))
++ return -1;
+
+- if (stats->freq == IEEE80211_52GHZ_BAND) {
+- /* for A band (No DS info) */
+- network->channel = stats->received_channel;
++ 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
+- network->flags |= NETWORK_HAS_CCK;
++ ret = -1;
++ if (ret == 0)
++ ret = ieee80211_verify_qos_info(&element_param->info_element,
++ QOS_OUI_PARAM_SUB_TYPE);
++ return ret;
++}
+
+- network->wpa_ie_len = 0;
+- network->rsn_ie_len = 0;
++/*
++ * 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;
+
+- 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);
++ 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(¶m_element,
++ info_element);
++ if (rc == 0) {
++ qos_param = &(network->qos_data.parameters);
++ ieee80211_qos_convert_ac_to_parameters(¶m_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
++
++ 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 @@ static inline int ieee80211_network_init
+ 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 @@ static inline int ieee80211_network_init
+ #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 @@ static inline int ieee80211_network_init
+ }
+ }
+
+- 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 @@ static inline int ieee80211_network_init
+ #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 @@ static inline int ieee80211_network_init
+ }
+ }
+
+- 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 @@ static inline int ieee80211_network_init
+ 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 @@ static inline int ieee80211_network_init
+ 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 int is_same_network(struct
+ 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 @@ static inline void update_network(struct
+ 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 @@ static inline void update_network(struct
+ 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 @@ static inline void ieee80211_process_pro
+ 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 @@ static inline void ieee80211_process_pro
+ 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 @@ static inline void ieee80211_process_pro
+ 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 @@ void ieee80211_rx_mgt(struct ieee80211_d
+
+ 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
+--- 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 @@ payload of each frame is reduced to 492
+ 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 @@ static inline int ieee80211_encrypt_frag
+ 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 @@ void ieee80211_txb_free(struct ieee80211
+ }
+
+ 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 @@ static struct ieee80211_txb *ieee80211_a
+ 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 @@ static struct ieee80211_txb *ieee80211_a
+ 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+ 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+ }
+
+ /* 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+ /* 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+
+ 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;
+-
+- /* 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;
++ /* 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);
++
++ if (unlikely(!skb_new))
++ goto failed;
++
++ 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);
++ }
++
++ 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 (encrypt)
+- bytes_per_frag -= crypt->ops->extra_prefix_len +
+- crypt->ops->extra_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)
++ /* 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+ 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+
+ /* 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+ 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 @@ int ieee80211_xmit(struct sk_buff *skb,
+ 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
+--- 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 @@ static inline char *ipw2100_translate_sc
+ 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 @@ static inline char *ipw2100_translate_sc
+ 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 @@ static inline char *ipw2100_translate_sc
+ 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 @@ static inline char *ipw2100_translate_sc
+ 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 @@ int ieee80211_wx_get_scan(struct ieee802
+ 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 ieee80211_wx_set_encode(struct ieee8
+ };
+ 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 @@ int ieee80211_wx_set_encode(struct ieee8
+
+ 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 @@ int ieee80211_wx_set_encode(struct ieee8
+ 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 @@ int ieee80211_wx_set_encode(struct ieee8
+ 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);
++ 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 @@ int ieee80211_wx_get_encode(struct ieee8
+ 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 @@ int ieee80211_wx_get_encode(struct ieee8
+ 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 @@ int ieee80211_wx_get_encode(struct ieee8
+ 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
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -715,6 +715,7 @@ int devinet_ioctl(unsigned int cmd, void
+ 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 @@ int devinet_ioctl(unsigned int cmd, void
+ 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
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -591,7 +591,7 @@ static int fib_inetaddr_event(struct not
+ 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
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -2404,7 +2404,7 @@ static int fib_route_seq_show(struct seq
+ 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
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -1108,12 +1108,9 @@ void __init icmp_init(struct net_proto_f
+ 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
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -275,7 +275,8 @@ int ip_output(struct sk_buff *skb)
+ {
+ 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 @@ csum_page(struct page *page, int offset,
+ 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 @@ int ip_append_data(struct sock *sk,
+ 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 @@ ssize_t ip_append_page(struct sock *sk,
+ 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 @@ ssize_t ip_append_page(struct sock *sk,
+ 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/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
+--- a/net/ipv4/netfilter/arp_tables.c
++++ b/net/ipv4/netfilter/arp_tables.c
+@@ -347,58 +347,106 @@ unsigned int arpt_do_table(struct sk_buf
+ return verdict;
+ }
+
+-static inline void *find_inlist_lock_noload(struct list_head *head,
+- const char *name,
+- int *error,
+- struct semaphore *mutex)
++/*
++ * These are weird, but module loading must not be done with mutex
++ * held (since they will register), and we have to have a single
++ * function to use try_then_request_module().
++ */
++
++/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
++static inline struct arpt_table *find_table_lock(const char *name)
+ {
+- void *ret;
++ struct arpt_table *t;
+
+- *error = down_interruptible(mutex);
+- if (*error != 0)
+- return NULL;
++ if (down_interruptible(&arpt_mutex) != 0)
++ return ERR_PTR(-EINTR);
+
+- ret = list_named_find(head, name);
+- if (!ret) {
+- *error = -ENOENT;
+- up(mutex);
+- }
+- return ret;
++ list_for_each_entry(t, &arpt_tables, list)
++ if (strcmp(t->name, name) == 0 && try_module_get(t->me))
++ return t;
++ up(&arpt_mutex);
++ return NULL;
+ }
+
+-#ifndef CONFIG_KMOD
+-#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
+-#else
+-static void *
+-find_inlist_lock(struct list_head *head,
+- const char *name,
+- const char *prefix,
+- int *error,
+- struct semaphore *mutex)
+-{
+- void *ret;
+-
+- ret = find_inlist_lock_noload(head, name, error, mutex);
+- if (!ret) {
+- duprintf("find_inlist: loading `%s%s'.\n", prefix, name);
+- request_module("%s%s", prefix, name);
+- ret = find_inlist_lock_noload(head, name, error, mutex);
++
++/* Find target, grabs ref. Returns ERR_PTR() on error. */
++static inline struct arpt_target *find_target(const char *name, u8 revision)
++{
++ struct arpt_target *t;
++ int err = 0;
++
++ if (down_interruptible(&arpt_mutex) != 0)
++ return ERR_PTR(-EINTR);
++
++ list_for_each_entry(t, &arpt_target, list) {
++ if (strcmp(t->name, name) == 0) {
++ if (t->revision == revision) {
++ if (try_module_get(t->me)) {
++ up(&arpt_mutex);
++ return t;
++ }
++ } else
++ err = -EPROTOTYPE; /* Found something. */
++ }
+ }
++ up(&arpt_mutex);
++ return ERR_PTR(err);
++}
+
+- return ret;
++struct arpt_target *arpt_find_target(const char *name, u8 revision)
++{
++ struct arpt_target *target;
++
++ target = try_then_request_module(find_target(name, revision),
++ "arpt_%s", name);
++ if (IS_ERR(target) || !target)
++ return NULL;
++ return target;
+ }
+-#endif
+
+-static inline struct arpt_table *arpt_find_table_lock(const char *name, int *error, struct semaphore *mutex)
++static int target_revfn(const char *name, u8 revision, int *bestp)
+ {
+- return find_inlist_lock(&arpt_tables, name, "arptable_", error, mutex);
++ struct arpt_target *t;
++ int have_rev = 0;
++
++ list_for_each_entry(t, &arpt_target, list) {
++ if (strcmp(t->name, name) == 0) {
++ if (t->revision > *bestp)
++ *bestp = t->revision;
++ if (t->revision == revision)
++ have_rev =1;
++ }
++ }
++ return have_rev;
+ }
+
+-static struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
++/* Returns true or false (if no such extension at all) */
++static inline int find_revision(const char *name, u8 revision,
++ int (*revfn)(const char *, u8, int *),
++ int *err)
+ {
+- return find_inlist_lock(&arpt_target, name, "arpt_", error, mutex);
++ int have_rev, best = -1;
++
++ if (down_interruptible(&arpt_mutex) != 0) {
++ *err = -EINTR;
++ return 1;
++ }
++ have_rev = revfn(name, revision, &best);
++ up(&arpt_mutex);
++
++ /* Nothing at all? Return 0 to try loading module. */
++ if (best == -1) {
++ *err = -ENOENT;
++ return 0;
++ }
++
++ *err = best;
++ if (!have_rev)
++ *err = -EPROTONOSUPPORT;
++ return 1;
+ }
+
++
+ /* All zeroes == unconditional rule. */
+ static inline int unconditional(const struct arpt_arp *arp)
+ {
+@@ -544,17 +592,15 @@ static inline int check_entry(struct arp
+ }
+
+ t = arpt_get_target(e);
+- target = arpt_find_target_lock(t->u.user.name, &ret, &arpt_mutex);
+- if (!target) {
++ target = try_then_request_module(find_target(t->u.user.name,
++ t->u.user.revision),
++ "arpt_%s", t->u.user.name);
++ if (IS_ERR(target) || !target) {
+ duprintf("check_entry: `%s' not found\n", t->u.user.name);
++ ret = target ? PTR_ERR(target) : -ENOENT;
+ goto out;
+ }
+- if (!try_module_get((target->me))) {
+- ret = -ENOENT;
+- goto out_unlock;
+- }
+ t->u.kernel.target = target;
+- up(&arpt_mutex);
+
+ if (t->u.kernel.target == &arpt_standard_target) {
+ if (!standard_check(t, size)) {
+@@ -576,8 +622,6 @@ static inline int check_entry(struct arp
+ (*i)++;
+ return 0;
+
+-out_unlock:
+- up(&arpt_mutex);
+ out:
+ return ret;
+ }
+@@ -846,8 +890,8 @@ static int get_entries(const struct arpt
+ int ret;
+ struct arpt_table *t;
+
+- t = arpt_find_table_lock(entries->name, &ret, &arpt_mutex);
+- if (t) {
++ t = find_table_lock(entries->name);
++ if (t || !IS_ERR(t)) {
+ duprintf("t->private->number = %u\n",
+ t->private->number);
+ if (entries->size == t->private->size)
+@@ -859,10 +903,10 @@ static int get_entries(const struct arpt
+ entries->size);
+ ret = -EINVAL;
+ }
++ module_put(t->me);
+ up(&arpt_mutex);
+ } else
+- duprintf("get_entries: Can't find %s!\n",
+- entries->name);
++ ret = t ? PTR_ERR(t) : -ENOENT;
+
+ return ret;
+ }
+@@ -913,22 +957,19 @@ static int do_replace(void __user *user,
+
+ duprintf("arp_tables: Translated table\n");
+
+- t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex);
+- if (!t)
++ t = try_then_request_module(find_table_lock(tmp.name),
++ "arptable_%s", tmp.name);
++ if (!t || IS_ERR(t)) {
++ ret = t ? PTR_ERR(t) : -ENOENT;
+ goto free_newinfo_counters_untrans;
++ }
+
+ /* You lied! */
+ if (tmp.valid_hooks != t->valid_hooks) {
+ duprintf("Valid hook crap: %08X vs %08X\n",
+ tmp.valid_hooks, t->valid_hooks);
+ ret = -EINVAL;
+- goto free_newinfo_counters_untrans_unlock;
+- }
+-
+- /* Get a reference in advance, we're not allowed fail later */
+- if (!try_module_get(t->me)) {
+- ret = -EBUSY;
+- goto free_newinfo_counters_untrans_unlock;
++ goto put_module;
+ }
+
+ oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
+@@ -959,7 +1000,6 @@ static int do_replace(void __user *user,
+
+ put_module:
+ module_put(t->me);
+- free_newinfo_counters_untrans_unlock:
+ up(&arpt_mutex);
+ free_newinfo_counters_untrans:
+ ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry, NULL);
+@@ -989,7 +1029,7 @@ static int do_add_counters(void __user *
+ unsigned int i;
+ struct arpt_counters_info tmp, *paddc;
+ struct arpt_table *t;
+- int ret;
++ int ret = 0;
+
+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ return -EFAULT;
+@@ -1006,9 +1046,11 @@ static int do_add_counters(void __user *
+ goto free;
+ }
+
+- t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex);
+- if (!t)
++ t = find_table_lock(tmp.name);
++ if (!t || IS_ERR(t)) {
++ ret = t ? PTR_ERR(t) : -ENOENT;
+ goto free;
++ }
+
+ write_lock_bh(&t->lock);
+ if (t->private->number != paddc->num_counters) {
+@@ -1025,6 +1067,7 @@ static int do_add_counters(void __user *
+ unlock_up_free:
+ write_unlock_bh(&t->lock);
+ up(&arpt_mutex);
++ module_put(t->me);
+ free:
+ vfree(paddc);
+
+@@ -1079,8 +1122,10 @@ static int do_arpt_get_ctl(struct sock *
+ break;
+ }
+ name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
+- t = arpt_find_table_lock(name, &ret, &arpt_mutex);
+- if (t) {
++
++ t = try_then_request_module(find_table_lock(name),
++ "arptable_%s", name);
++ if (t && !IS_ERR(t)) {
+ struct arpt_getinfo info;
+
+ info.valid_hooks = t->valid_hooks;
+@@ -1096,9 +1141,10 @@ static int do_arpt_get_ctl(struct sock *
+ ret = -EFAULT;
+ else
+ ret = 0;
+-
+ up(&arpt_mutex);
+- }
++ module_put(t->me);
++ } else
++ ret = t ? PTR_ERR(t) : -ENOENT;
+ }
+ break;
+
+@@ -1119,6 +1165,24 @@ static int do_arpt_get_ctl(struct sock *
+ break;
+ }
+
++ case ARPT_SO_GET_REVISION_TARGET: {
++ struct arpt_get_revision rev;
++
++ if (*len != sizeof(rev)) {
++ ret = -EINVAL;
++ break;
++ }
++ if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
++ ret = -EFAULT;
++ break;
++ }
++
++ try_then_request_module(find_revision(rev.name, rev.revision,
++ target_revfn, &ret),
++ "arpt_%s", rev.name);
++ break;
++ }
++
+ default:
+ duprintf("do_arpt_get_ctl: unknown request %i\n", cmd);
+ ret = -EINVAL;
+@@ -1136,12 +1200,9 @@ int arpt_register_target(struct arpt_tar
+ if (ret != 0)
+ return ret;
+
+- if (!list_named_insert(&arpt_target, target)) {
+- duprintf("arpt_register_target: `%s' already in list!\n",
+- target->name);
+- ret = -EINVAL;
+- }
++ list_add(&target->list, &arpt_target);
+ up(&arpt_mutex);
++
+ return ret;
+ }
+
+diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
+--- 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 @@ DEFINE_PER_CPU(struct ip_conntrack_stat,
+ 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 @@ static int kill_all(struct ip_conntrack
+ 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 @@ void ip_conntrack_cleanup(void)
+ 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 @@ int __init ip_conntrack_init(void)
+
+ /* 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 @@ int __init ip_conntrack_init(void)
+ 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 @@ int __init ip_conntrack_init(void)
+ 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 @@ int __init ip_conntrack_init(void)
+ 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
+--- a/net/ipv4/netfilter/ipt_addrtype.c
++++ b/net/ipv4/netfilter/ipt_addrtype.c
+@@ -48,7 +48,7 @@ static int checkentry(const char *tablen
+ 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
+--- a/net/ipv4/proc.c
++++ b/net/ipv4/proc.c
+@@ -90,9 +90,7 @@ fold_field(void *mib[], int offt)
+ 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
+--- 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 @@ static int __ipv6_regen_rndid(struct ine
+ 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
+--- a/net/ipv6/icmp.c
++++ b/net/ipv6/icmp.c
+@@ -700,10 +700,7 @@ int __init icmpv6_init(struct net_proto_
+ 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 @@ void icmpv6_cleanup(void)
+ {
+ 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
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -147,7 +147,8 @@ static int ip6_output2(struct sk_buff *s
+
+ 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 @@ out_err_release:
+ *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 @@ int ip6_append_data(struct sock *sk, int
+ */
+
+ 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
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -164,7 +164,7 @@ static int ip6_mc_leave_src(struct sock
+ #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)
+@@ -1087,7 +1087,7 @@ static void mld_marksources(struct ifmca
+
+ int igmp6_event_query(struct sk_buff *skb)
+ {
+- struct mld2_query *mlh2 = (struct mld2_query *) skb->h.raw;
++ struct mld2_query *mlh2 = NULL;
+ struct ifmcaddr6 *ma;
+ struct in6_addr *group;
+ unsigned long max_delay;
+@@ -1140,6 +1140,13 @@ int igmp6_event_query(struct sk_buff *sk
+ /* clear deleted report items */
+ mld_clear_delrec(idev);
+ } else if (len >= 28) {
++ int srcs_offset = sizeof(struct mld2_query) -
++ sizeof(struct icmp6hdr);
++ if (!pskb_may_pull(skb, srcs_offset)) {
++ in6_dev_put(idev);
++ return -EINVAL;
++ }
++ mlh2 = (struct mld2_query *) skb->h.raw;
+ max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000;
+ if (!max_delay)
+ max_delay = 1;
+@@ -1156,7 +1163,15 @@ int igmp6_event_query(struct sk_buff *sk
+ return 0;
+ }
+ /* mark sources to include, if group & source-specific */
+- mark = mlh2->nsrcs != 0;
++ if (mlh2->nsrcs != 0) {
++ if (!pskb_may_pull(skb, srcs_offset +
++ mlh2->nsrcs * sizeof(struct in6_addr))) {
++ in6_dev_put(idev);
++ return -EINVAL;
++ }
++ mlh2 = (struct mld2_query *) skb->h.raw;
++ mark = 1;
++ }
+ } else {
+ in6_dev_put(idev);
+ return -EINVAL;
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -2,7 +2,7 @@
+ * Packet matching code.
+ *
+ * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
+- * Copyright (C) 2000-2002 Netfilter core team <coreteam at netfilter.org>
++ * Copyright (C) 2000-2005 Netfilter Core Team <coreteam at netfilter.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
+@@ -23,7 +23,6 @@
+ #include <linux/tcp.h>
+ #include <linux/udp.h>
+ #include <linux/icmpv6.h>
+-#include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <asm/uaccess.h>
+ #include <asm/semaphore.h>
+@@ -80,13 +79,12 @@ static DECLARE_MUTEX(ip6t_mutex);
+ #define inline
+ #endif
+
+-/* Locking is simple: we assume at worst case there will be one packet
+- in user context and one from bottom halves (or soft irq if Alexey's
+- softnet patch was applied).
+-
++/*
+ We keep a set of rules for each CPU, so we can avoid write-locking
+- them; doing a readlock_bh() stops packets coming through if we're
+- in user context.
++ them in the softirq when updating the counters and therefore
++ only need to read-lock in the softirq; doing a write_lock_bh() in user
++ context stops packets coming through and allows user context to read
++ the counters or update the rules.
+
+ To be cache friendly on SMP, we arrange them like so:
+ [ n-entries ]
+@@ -356,7 +354,7 @@ ip6t_do_table(struct sk_buff **pskb,
+ struct ip6t_table *table,
+ void *userdata)
+ {
+- static const char nulldevname[IFNAMSIZ];
++ static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
+ int offset = 0;
+ unsigned int protoff = 0;
+ int hotdrop = 0;
+@@ -369,7 +367,6 @@ ip6t_do_table(struct sk_buff **pskb,
+ /* Initialization */
+ indev = in ? in->name : nulldevname;
+ outdev = out ? out->name : nulldevname;
+-
+ /* We handle fragments by dealing with the first fragment as
+ * if it was a normal packet. All other fragments are treated
+ * normally, except that they will NEVER match rules that ask
+@@ -497,75 +494,145 @@ ip6t_do_table(struct sk_buff **pskb,
+ #endif
+ }
+
+-/* If it succeeds, returns element and locks mutex */
+-static inline void *
+-find_inlist_lock_noload(struct list_head *head,
+- const char *name,
+- int *error,
+- struct semaphore *mutex)
+-{
+- void *ret;
+-
+-#if 1
+- duprintf("find_inlist: searching for `%s' in %s.\n",
+- name, head == &ip6t_target ? "ip6t_target"
+- : head == &ip6t_match ? "ip6t_match"
+- : head == &ip6t_tables ? "ip6t_tables" : "UNKNOWN");
+-#endif
++/*
++ * These are weird, but module loading must not be done with mutex
++ * held (since they will register), and we have to have a single
++ * function to use try_then_request_module().
++ */
+
+- *error = down_interruptible(mutex);
+- if (*error != 0)
+- return NULL;
++/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
++static inline struct ip6t_table *find_table_lock(const char *name)
++{
++ struct ip6t_table *t;
++
++ if (down_interruptible(&ip6t_mutex) != 0)
++ return ERR_PTR(-EINTR);
++
++ list_for_each_entry(t, &ip6t_tables, list)
++ if (strcmp(t->name, name) == 0 && try_module_get(t->me))
++ return t;
++ up(&ip6t_mutex);
++ return NULL;
++}
++
++/* Find match, grabs ref. Returns ERR_PTR() on error. */
++static inline struct ip6t_match *find_match(const char *name, u8 revision)
++{
++ struct ip6t_match *m;
++ int err = 0;
++
++ if (down_interruptible(&ip6t_mutex) != 0)
++ return ERR_PTR(-EINTR);
+
+- ret = list_named_find(head, name);
+- if (!ret) {
+- *error = -ENOENT;
+- up(mutex);
++ list_for_each_entry(m, &ip6t_match, list) {
++ if (strcmp(m->name, name) == 0) {
++ if (m->revision == revision) {
++ if (try_module_get(m->me)) {
++ up(&ip6t_mutex);
++ return m;
++ }
++ } else
++ err = -EPROTOTYPE; /* Found something. */
++ }
+ }
+- return ret;
++ up(&ip6t_mutex);
++ return ERR_PTR(err);
+ }
+
+-#ifndef CONFIG_KMOD
+-#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
+-#else
+-static void *
+-find_inlist_lock(struct list_head *head,
+- const char *name,
+- const char *prefix,
+- int *error,
+- struct semaphore *mutex)
+-{
+- void *ret;
+-
+- ret = find_inlist_lock_noload(head, name, error, mutex);
+- if (!ret) {
+- duprintf("find_inlist: loading `%s%s'.\n", prefix, name);
+- request_module("%s%s", prefix, name);
+- ret = find_inlist_lock_noload(head, name, error, mutex);
++/* Find target, grabs ref. Returns ERR_PTR() on error. */
++static inline struct ip6t_target *find_target(const char *name, u8 revision)
++{
++ struct ip6t_target *t;
++ int err = 0;
++
++ if (down_interruptible(&ip6t_mutex) != 0)
++ return ERR_PTR(-EINTR);
++
++ list_for_each_entry(t, &ip6t_target, list) {
++ if (strcmp(t->name, name) == 0) {
++ if (t->revision == revision) {
++ if (try_module_get(t->me)) {
++ up(&ip6t_mutex);
++ return t;
++ }
++ } else
++ err = -EPROTOTYPE; /* Found something. */
++ }
+ }
++ up(&ip6t_mutex);
++ return ERR_PTR(err);
++}
+
+- return ret;
++struct ip6t_target *ip6t_find_target(const char *name, u8 revision)
++{
++ struct ip6t_target *target;
++
++ target = try_then_request_module(find_target(name, revision),
++ "ip6t_%s", name);
++ if (IS_ERR(target) || !target)
++ return NULL;
++ return target;
+ }
+-#endif
+
+-static inline struct ip6t_table *
+-ip6t_find_table_lock(const char *name, int *error, struct semaphore *mutex)
++static int match_revfn(const char *name, u8 revision, int *bestp)
+ {
+- return find_inlist_lock(&ip6t_tables, name, "ip6table_", error, mutex);
++ struct ip6t_match *m;
++ int have_rev = 0;
++
++ list_for_each_entry(m, &ip6t_match, list) {
++ if (strcmp(m->name, name) == 0) {
++ if (m->revision > *bestp)
++ *bestp = m->revision;
++ if (m->revision == revision)
++ have_rev = 1;
++ }
++ }
++ return have_rev;
+ }
+
+-static inline struct ip6t_match *
+-find_match_lock(const char *name, int *error, struct semaphore *mutex)
++static int target_revfn(const char *name, u8 revision, int *bestp)
+ {
+- return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex);
++ struct ip6t_target *t;
++ int have_rev = 0;
++
++ list_for_each_entry(t, &ip6t_target, list) {
++ if (strcmp(t->name, name) == 0) {
++ if (t->revision > *bestp)
++ *bestp = t->revision;
++ if (t->revision == revision)
++ have_rev = 1;
++ }
++ }
++ return have_rev;
+ }
+
+-static struct ip6t_target *
+-ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex)
++/* Returns true or fals (if no such extension at all) */
++static inline int find_revision(const char *name, u8 revision,
++ int (*revfn)(const char *, u8, int *),
++ int *err)
+ {
+- return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
++ int have_rev, best = -1;
++
++ if (down_interruptible(&ip6t_mutex) != 0) {
++ *err = -EINTR;
++ return 1;
++ }
++ have_rev = revfn(name, revision, &best);
++ up(&ip6t_mutex);
++
++ /* Nothing at all? Return 0 to try loading module. */
++ if (best == -1) {
++ *err = -ENOENT;
++ return 0;
++ }
++
++ *err = best;
++ if (!have_rev)
++ *err = -EPROTONOSUPPORT;
++ return 1;
+ }
+
++
+ /* All zeroes == unconditional rule. */
+ static inline int
+ unconditional(const struct ip6t_ip6 *ipv6)
+@@ -725,20 +792,16 @@ check_match(struct ip6t_entry_match *m,
+ unsigned int hookmask,
+ unsigned int *i)
+ {
+- int ret;
+ struct ip6t_match *match;
+
+- match = find_match_lock(m->u.user.name, &ret, &ip6t_mutex);
+- if (!match) {
+- // duprintf("check_match: `%s' not found\n", m->u.name);
+- return ret;
+- }
+- if (!try_module_get(match->me)) {
+- up(&ip6t_mutex);
+- return -ENOENT;
++ match = try_then_request_module(find_match(m->u.user.name,
++ m->u.user.revision),
++ "ip6t_%s", m->u.user.name);
++ if (IS_ERR(match) || !match) {
++ duprintf("check_match: `%s' not found\n", m->u.user.name);
++ return match ? PTR_ERR(match) : -ENOENT;
+ }
+ m->u.kernel.match = match;
+- up(&ip6t_mutex);
+
+ if (m->u.kernel.match->checkentry
+ && !m->u.kernel.match->checkentry(name, ipv6, m->data,
+@@ -776,22 +839,16 @@ check_entry(struct ip6t_entry *e, const
+ goto cleanup_matches;
+
+ t = ip6t_get_target(e);
+- target = ip6t_find_target_lock(t->u.user.name, &ret, &ip6t_mutex);
+- if (!target) {
++ target = try_then_request_module(find_target(t->u.user.name,
++ t->u.user.revision),
++ "ip6t_%s", t->u.user.name);
++ if (IS_ERR(target) || !target) {
+ duprintf("check_entry: `%s' not found\n", t->u.user.name);
+- goto cleanup_matches;
+- }
+- if (!try_module_get(target->me)) {
+- up(&ip6t_mutex);
+- ret = -ENOENT;
++ ret = target ? PTR_ERR(target) : -ENOENT;
+ goto cleanup_matches;
+ }
+ t->u.kernel.target = target;
+- up(&ip6t_mutex);
+- if (!t->u.kernel.target) {
+- ret = -EBUSY;
+- goto cleanup_matches;
+- }
++
+ if (t->u.kernel.target == &ip6t_standard_target) {
+ if (!standard_check(t, size)) {
+ ret = -EINVAL;
+@@ -1118,8 +1175,8 @@ get_entries(const struct ip6t_get_entrie
+ int ret;
+ struct ip6t_table *t;
+
+- t = ip6t_find_table_lock(entries->name, &ret, &ip6t_mutex);
+- if (t) {
++ t = find_table_lock(entries->name);
++ if (t && !IS_ERR(t)) {
+ duprintf("t->private->number = %u\n",
+ t->private->number);
+ if (entries->size == t->private->size)
+@@ -1131,10 +1188,10 @@ get_entries(const struct ip6t_get_entrie
+ entries->size);
+ ret = -EINVAL;
+ }
++ module_put(t->me);
+ up(&ip6t_mutex);
+ } else
+- duprintf("get_entries: Can't find %s!\n",
+- entries->name);
++ ret = t ? PTR_ERR(t) : -ENOENT;
+
+ return ret;
+ }
+@@ -1182,22 +1239,19 @@ do_replace(void __user *user, unsigned i
+
+ duprintf("ip_tables: Translated table\n");
+
+- t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex);
+- if (!t)
++ t = try_then_request_module(find_table_lock(tmp.name),
++ "ip6table_%s", tmp.name);
++ if (!t || IS_ERR(t)) {
++ ret = t ? PTR_ERR(t) : -ENOENT;
+ goto free_newinfo_counters_untrans;
++ }
+
+ /* You lied! */
+ if (tmp.valid_hooks != t->valid_hooks) {
+ duprintf("Valid hook crap: %08X vs %08X\n",
+ tmp.valid_hooks, t->valid_hooks);
+ ret = -EINVAL;
+- goto free_newinfo_counters_untrans_unlock;
+- }
+-
+- /* Get a reference in advance, we're not allowed fail later */
+- if (!try_module_get(t->me)) {
+- ret = -EBUSY;
+- goto free_newinfo_counters_untrans_unlock;
++ goto put_module;
+ }
+
+ oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
+@@ -1219,7 +1273,6 @@ do_replace(void __user *user, unsigned i
+ /* Decrease module usage counts and free resource */
+ IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
+ vfree(oldinfo);
+- /* Silent error: too late now. */
+ if (copy_to_user(tmp.counters, counters,
+ sizeof(struct ip6t_counters) * tmp.num_counters) != 0)
+ ret = -EFAULT;
+@@ -1229,7 +1282,6 @@ do_replace(void __user *user, unsigned i
+
+ put_module:
+ module_put(t->me);
+- free_newinfo_counters_untrans_unlock:
+ up(&ip6t_mutex);
+ free_newinfo_counters_untrans:
+ IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
+@@ -1268,7 +1320,7 @@ do_add_counters(void __user *user, unsig
+ unsigned int i;
+ struct ip6t_counters_info tmp, *paddc;
+ struct ip6t_table *t;
+- int ret;
++ int ret = 0;
+
+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ return -EFAULT;
+@@ -1285,9 +1337,11 @@ do_add_counters(void __user *user, unsig
+ goto free;
+ }
+
+- t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex);
+- if (!t)
++ t = find_table_lock(tmp.name);
++ if (!t || IS_ERR(t)) {
++ ret = t ? PTR_ERR(t) : -ENOENT;
+ goto free;
++ }
+
+ write_lock_bh(&t->lock);
+ if (t->private->number != paddc->num_counters) {
+@@ -1304,6 +1358,7 @@ do_add_counters(void __user *user, unsig
+ unlock_up_free:
+ write_unlock_bh(&t->lock);
+ up(&ip6t_mutex);
++ module_put(t->me);
+ free:
+ vfree(paddc);
+
+@@ -1360,8 +1415,10 @@ do_ip6t_get_ctl(struct sock *sk, int cmd
+ break;
+ }
+ name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
+- t = ip6t_find_table_lock(name, &ret, &ip6t_mutex);
+- if (t) {
++
++ t = try_then_request_module(find_table_lock(name),
++ "ip6table_%s", name);
++ if (t && !IS_ERR(t)) {
+ struct ip6t_getinfo info;
+
+ info.valid_hooks = t->valid_hooks;
+@@ -1377,9 +1434,10 @@ do_ip6t_get_ctl(struct sock *sk, int cmd
+ ret = -EFAULT;
+ else
+ ret = 0;
+-
+ up(&ip6t_mutex);
+- }
++ module_put(t->me);
++ } else
++ ret = t ? PTR_ERR(t) : -ENOENT;
+ }
+ break;
+
+@@ -1400,6 +1458,31 @@ do_ip6t_get_ctl(struct sock *sk, int cmd
+ break;
+ }
+
++ case IP6T_SO_GET_REVISION_MATCH:
++ case IP6T_SO_GET_REVISION_TARGET: {
++ struct ip6t_get_revision rev;
++ int (*revfn)(const char *, u8, int *);
++
++ if (*len != sizeof(rev)) {
++ ret = -EINVAL;
++ break;
++ }
++ if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
++ ret = -EFAULT;
++ break;
++ }
++
++ if (cmd == IP6T_SO_GET_REVISION_TARGET)
++ revfn = target_revfn;
++ else
++ revfn = match_revfn;
++
++ try_then_request_module(find_revision(rev.name, rev.revision,
++ revfn, &ret),
++ "ip6t_%s", rev.name);
++ break;
++ }
++
+ default:
+ duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
+ ret = -EINVAL;
+@@ -1417,12 +1500,7 @@ ip6t_register_target(struct ip6t_target
+ ret = down_interruptible(&ip6t_mutex);
+ if (ret != 0)
+ return ret;
+-
+- if (!list_named_insert(&ip6t_target, target)) {
+- duprintf("ip6t_register_target: `%s' already in list!\n",
+- target->name);
+- ret = -EINVAL;
+- }
++ list_add(&target->list, &ip6t_target);
+ up(&ip6t_mutex);
+ return ret;
+ }
+@@ -1444,11 +1522,7 @@ ip6t_register_match(struct ip6t_match *m
+ if (ret != 0)
+ return ret;
+
+- if (!list_named_insert(&ip6t_match, match)) {
+- duprintf("ip6t_register_match: `%s' already in list!\n",
+- match->name);
+- ret = -EINVAL;
+- }
++ list_add(&match->list, &ip6t_match);
+ up(&ip6t_mutex);
+
+ return ret;
+diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
+--- a/net/ipv6/netfilter/ip6t_MARK.c
++++ b/net/ipv6/netfilter/ip6t_MARK.c
+@@ -56,8 +56,12 @@ checkentry(const char *tablename,
+ return 1;
+ }
+
+-static struct ip6t_target ip6t_mark_reg
+-= { { NULL, NULL }, "MARK", target, checkentry, NULL, THIS_MODULE };
++static struct ip6t_target ip6t_mark_reg = {
++ .name = "MARK",
++ .target = target,
++ .checkentry = checkentry,
++ .me = THIS_MODULE
++};
+
+ static int __init init(void)
+ {
+diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
+--- a/net/ipv6/proc.c
++++ b/net/ipv6/proc.c
+@@ -140,9 +140,7 @@ fold_field(void *mib[], int offt)
+ 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/route.c b/net/ipv6/route.c
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -483,7 +483,7 @@ restart:
+ goto out;
+ }
+
+- rt = rt6_device_match(rt, skb->dev->ifindex, 0);
++ rt = rt6_device_match(rt, skb->dev->ifindex, strict);
+ BACKTRACK();
+
+ if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -740,11 +740,8 @@ int netlink_attachskb(struct sock *sk, s
+
+ 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 @@ struct netlink_broadcast_data {
+ 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
+--- a/net/rose/rose_route.c
++++ b/net/rose/rose_route.c
+@@ -727,7 +727,7 @@ int rose_rt_ioctl(unsigned int cmd, void
+ }
+ 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/rose/rose_timer.c b/net/rose/rose_timer.c
+--- a/net/rose/rose_timer.c
++++ b/net/rose/rose_timer.c
+@@ -138,6 +138,7 @@ static void rose_heartbeat_expiry(unsign
+ is accepted() it isn't 'dead' so doesn't get removed. */
+ if (sock_flag(sk, SOCK_DESTROY) ||
+ (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
++ bh_unlock_sock(sk);
+ rose_destroy_socket(sk);
+ return;
+ }
+diff --git a/net/sctp/proc.c b/net/sctp/proc.c
+--- a/net/sctp/proc.c
++++ b/net/sctp/proc.c
+@@ -69,9 +69,7 @@ fold_field(void *mib[], int nr)
+ 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
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -554,7 +554,7 @@ struct sctp_chunk *sctp_make_datafrag_em
+ 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
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -1010,6 +1010,19 @@ static int __sctp_connect(struct sock* s
+ 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_STATIC int sctp_sendmsg(struct kioc
+ 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 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
+ 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 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
+ 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 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
+ 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 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
+
+ /* 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 @@ static int sctp_setsockopt_maxseg(struct
+ 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_peer_primary_
+ 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_primary_addr(
+ 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))
+- return -EFAULT;
+- if (copy_to_user(optval, &val, len))
++ adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind;
++ if (copy_to_user(optval, &adaption, len))
+ return -EFAULT;
++
+ return 0;
+ }
+
+@@ -4640,8 +4662,8 @@ SCTP_STATIC int sctp_msghdr_parse(const
+
+ /* 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
+--- a/net/sctp/ulpevent.c
++++ b/net/sctp/ulpevent.c
+@@ -698,7 +698,7 @@ struct sctp_ulpevent *sctp_ulpevent_make
+ 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 @@ void sctp_ulpevent_read_sndrcvinfo(const
+ *
+ * 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 @@ void sctp_ulpevent_read_sndrcvinfo(const
+ * 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
+--- 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
+--- 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
+--- a/net/sunrpc/auth_gss/Makefile
++++ b/net/sunrpc/auth_gss/Makefile
+@@ -10,7 +10,7 @@ auth_rpcgss-objs := auth_gss.o gss_gener
+ 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
+--- 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 @@ gss_marshal(struct rpc_task *task, u32 *
+
+ /* 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 @@ gss_marshal(struct rpc_task *task, u32 *
+ *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 @@ static u32 *
+ 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 @@ gss_validate(struct rpc_task *task, u32
+ 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 @@ gss_wrap_req_integ(struct rpc_cred *cred
+ 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 @@ gss_wrap_req_integ(struct rpc_cred *cred
+ 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 @@ gss_wrap_req(struct rpc_task *task,
+ rqstp, p, obj);
+ break;
+ case RPC_GSS_SVC_PRIVACY:
++ status = gss_wrap_req_priv(cred, ctx, encode,
++ rqstp, p, obj);
+ break;
+ }
+ out:
+@@ -1054,15 +1146,43 @@ gss_unwrap_resp_integ(struct rpc_cred *c
+ 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)
++ return status;
++ 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 @@ gss_unwrap_resp(struct rpc_task *task,
+ 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 @@ gss_unwrap_resp(struct rpc_task *task,
+ 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
+--- 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 @@ krb5_encrypt(
+ 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 @@ krb5_decrypt(
+ 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 @@ out:
+
+ 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 @@ make_checksum(s32 cksumtype, char *heade
+ 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 @@ out:
+ }
+
+ 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
+--- 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 @@ gss_delete_sec_context_kerberos(void *in
+ 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 @@ static struct pf_desc gss_kerberos_pfs[]
+ .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
+--- 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 @@ krb5_make_token(struct krb5_ctx *ctx, in
+
+ 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 @@ krb5_make_token(struct krb5_ctx *ctx, in
+ 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 @@ krb5_make_token(struct krb5_ctx *ctx, in
+
+ *(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
+--- 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 @@ krb5_read_token(struct krb5_ctx *ctx,
+ 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 @@ krb5_read_token(struct krb5_ctx *ctx,
+ 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 @@ krb5_read_token(struct krb5_ctx *ctx,
+ 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 @@ krb5_read_token(struct krb5_ctx *ctx,
+
+ /* 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
+--- /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
+--- 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 @@ gss_import_sec_context(const void *input
+
+ 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 @@ gss_get_mic(struct gss_ctx *context_hand
+ 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
+--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
+@@ -224,18 +224,13 @@ gss_delete_sec_context_spkm3(void *inter
+ 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 @@ gss_verify_mic_spkm3(struct gss_ctx *ct
+
+ 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 gss_api_ops gss_spkm3_ops
+ };
+
+ 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
+--- 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 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ 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
+--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+@@ -52,7 +52,7 @@ u32
+ 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
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -566,8 +566,7 @@ gss_verify_header(struct svc_rqst *rqstp
+
+ 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 @@ gss_write_verf(struct svc_rqst *rqstp, s
+ 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 @@ unwrap_integ_data(struct xdr_buf *buf, u
+ 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 @@ svcauth_gss_release(struct svc_rqst *rqs
+ 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
+--- 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
+--- 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
+--- 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_allocate(struct rpc_tas
+ 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 @@ void
+ 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 @@ call_allocate(struct rpc_task *task)
+ 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 @@ call_encode(struct rpc_task *task)
+ 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 @@ static void
+ 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"));
+-
+- task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_connect;
++ dprintk("RPC: %4d call_bind (status %d)\n",
++ task->tk_pid, task->tk_status);
+
++ 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_connect(struct rpc_task *task)
++call_bind_status(struct rpc_task *task)
+ {
+- struct rpc_clnt *clnt = task->tk_client;
+-
+- dprintk("RPC: %4d call_connect status %d\n",
+- task->tk_pid, task->tk_status);
++ int status = -EACCES;
+
+- if (xprt_connected(clnt->cl_xprt)) {
+- task->tk_action = call_transmit;
++ 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;
+ }
+- task->tk_action = call_connect_status;
+- if (task->tk_status < 0)
+- return;
+- xprt_connect(task);
++
++ 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_xprt *xprt = task->tk_xprt;
++
++ dprintk("RPC: %4d call_connect xprt %p %s connected\n",
++ task->tk_pid, xprt,
++ (xprt_connected(xprt) ? "is" : "is not"));
++
++ task->tk_action = call_transmit;
++ if (!xprt_connected(xprt)) {
++ 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 @@ call_connect_status(struct rpc_task *tas
+ 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 @@ call_connect_status(struct rpc_task *tas
+ 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 @@ call_transmit(struct rpc_task *task)
+ 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 @@ call_transmit(struct rpc_task *task)
+ 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 @@ static u32 *
+ 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
+--- 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 @@ rpc_getport(struct rpc_task *task, struc
+ 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 @@ rpc_getport_external(struct sockaddr_in
+ 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 @@ rpc_register(u32 prog, u32 vers, int pro
+
+ 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 @@ rpc_register(u32 prog, u32 vers, int pro
+ }
+
+ 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 @@ pmap_create(char *hostname, struct socka
+ 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
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -76,25 +76,35 @@ int
+ 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 @@ rpc_close_pipes(struct inode *inode)
+ 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 @@ repeat:
+ 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 @@ __rpc_rmdir(struct inode *dir, struct de
+ 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 @@ rpc_unlink(char *path)
+ 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
+--- /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 at 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
+--- 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
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -548,9 +548,6 @@ svc_write_space(struct sock *sk)
+ /*
+ * 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
+--- a/net/sunrpc/sysctl.c
++++ b/net/sunrpc/sysctl.c
+@@ -119,8 +119,18 @@ done:
+ 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 @@ static ctl_table debug_table[] = {
+ .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
+--- a/net/sunrpc/xdr.c
++++ b/net/sunrpc/xdr.c
+@@ -6,15 +6,12 @@
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir at 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_inline_pages(struct xdr_buf *xdr, un
+ 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
+--- 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 at monad.swb.de>
+ *
+- * TCP callback races fixes (C) 1998 Red Hat Software <alan at redhat.com>
+- * TCP send fixes (C) 1998 Red Hat Software <alan at redhat.com>
+- * TCP NFS related read + write fixes
+- * (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied at 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 at fys.uio.no>
++ * Transport switch API copyright (C) 2005, Chuck Lever <cel at 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,81 +54,90 @@
+ # 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.
++ */
++#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)
++
++/**
++ * 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 void
+-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
++int xprt_reserve_xprt(struct rpc_task *task)
+ {
+- u8 *buf = (u8 *) packet;
+- int j;
++ struct rpc_xprt *xprt = task->tk_xprt;
++ struct rpc_rqst *req = task->tk_rqstp;
+
+- 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]);
++ if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
++ if (task == xprt->snd_task)
++ return 1;
++ if (task == NULL)
++ return 0;
++ goto out_sleep;
+ }
+- dprintk("\n");
+-}
+-#else
+-static inline void
+-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
+-{
+- /* NOP */
+-}
+-#endif
++ xprt->snd_task = task;
++ if (req) {
++ req->rq_bytes_sent = 0;
++ req->rq_ntrans++;
++ }
++ return 1;
+
+-/*
+- * Look up RPC transport given an INET socket
+- */
+-static inline struct rpc_xprt *
+-xprt_from_sock(struct sock *sk)
+-{
+- return (struct rpc_xprt *) sk->sk_user_data;
++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;
+ }
+
+ /*
+- * 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.
++ * 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.
+ */
+-static int
+-__xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
++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->sockstate)) {
++ if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
+ if (task == xprt->snd_task)
+ return 1;
+ goto out_sleep;
+ }
+- if (xprt->nocong || __xprt_get_cong(xprt, task)) {
++ if (__xprt_get_cong(xprt, task)) {
+ xprt->snd_task = task;
+ if (req) {
+ req->rq_bytes_sent = 0;
+@@ -156,10 +146,10 @@ __xprt_lock_write(struct rpc_xprt *xprt,
+ return 1;
+ }
+ smp_mb__before_clear_bit();
+- clear_bit(XPRT_LOCKED, &xprt->sockstate);
++ clear_bit(XPRT_LOCKED, &xprt->state);
+ smp_mb__after_clear_bit();
+ 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 +159,52 @@ out_sleep:
+ return 0;
+ }
+
+-static inline int
+-xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
++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 @@ __xprt_lock_write_next(struct rpc_xprt *
+ 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 @@ __xprt_lock_write_next(struct rpc_xprt *
+ }
+ 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)
+-{
+- spin_lock_bh(&xprt->sock_lock);
+- __xprt_release_write(xprt, task);
+- spin_unlock_bh(&xprt->sock_lock);
+-}
+-
+-/*
+- * Write data to socket.
++/**
++ * 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.
+ */
+-static inline int
+-xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
++void xprt_release_xprt_cong(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);
++ 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);
+ }
+- /* 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;
++static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
++{
++ spin_lock_bh(&xprt->transport_lock);
++ xprt->ops->release_xprt(xprt, task);
++ spin_unlock_bh(&xprt->transport_lock);
+ }
+
+ /*
+@@ -321,26 +302,40 @@ __xprt_put_cong(struct rpc_xprt *xprt, s
+ 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 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt,
+ 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 @@ static void xprt_reset_majortimeo(struct
+ 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 @@ int xprt_adjust_timeout(struct rpc_rqst
+ 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 @@ int xprt_adjust_timeout(struct rpc_rqst
+ 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 @@ void xprt_connect(struct rpc_task *task)
+ if (!xprt_lock_write(xprt, task))
+ return;
+ if (xprt_connected(xprt))
+- goto out_write;
+-
+- 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();
+- }
++ xprt_release_write(xprt, task);
++ else {
++ if (task->tk_rqstp)
++ task->tk_rqstp->rq_bytes_sent = 0;
++
++ 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 @@ xprt_connect_status(struct rpc_task *tas
+ 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;
++ }
++
++ /* if soft mounted, just cause this RPC to fail */
++ if (RPC_IS_SOFT(task)) {
++ xprt_release_write(xprt, task);
++ task->tk_status = -EIO;
+ }
+- xprt_release_write(xprt, task);
+ }
+
+-/*
+- * 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 @@ xprt_lookup_rqst(struct rpc_xprt *xprt,
+ return req;
+ }
+
+-/*
+- * Complete reply received.
+- * The TCP code relies on us to remove the request from xprt->pending.
+- */
+-static void
+-xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
+-{
+- struct rpc_task *task = req->rq_task;
+- struct rpc_clnt *clnt = task->tk_client;
+-
+- /* 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);
+- }
+- }
+-
+-#ifdef RPC_PROFILE
+- /* Profile only reads for now */
+- if (copied > 1024) {
+- static unsigned long nextstat;
+- static unsigned long pkt_rtt, pkt_len, pkt_cnt;
+-
+- 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: %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)
+-{
+- 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.
++/**
++ * xprt_update_rtt - update an RPC client's RTT state after receiving a reply
++ * @task: RPC request that recently completed
++ *
+ */
+-static int
+-tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
+- unsigned int offset, size_t len)
++void xprt_update_rtt(struct rpc_task *task)
+ {
+- 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;
++ 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;
+
+- 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;
++ 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);
+ }
+- 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.
++/**
++ * 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.
+ */
+-static void
+-xprt_write_space(struct sock *sk)
++void xprt_complete_rqst(struct rpc_task *task, int copied)
+ {
+- 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;
+- }
++ struct rpc_rqst *req = task->tk_rqstp;
+
+- if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
+- goto out;
++ dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
++ task->tk_pid, ntohl(req->rq_xid), copied);
+
+- 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);
++ list_del_init(&req->rq_list);
++ req->rq_received = req->rq_private_buf.len = copied;
++ rpc_wake_up_task(task);
+ }
+
+-/*
+- * RPC receive timeout handler.
+- */
+-static void
+-xprt_timer(struct rpc_task *task)
++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 @@ xprt_prepare_transmit(struct rpc_task *t
+ 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 @@ xprt_prepare_transmit(struct rpc_task *t
+ 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_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_clnt *clnt = task->tk_client;
+ 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 @@ xprt_transmit(struct rpc_task *task)
+ } 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 @@ xprt_transmit(struct rpc_task *task)
+ 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 @@ do_xprt_reserve(struct rpc_task *task)
+ 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 @@ static inline void xprt_init_xid(struct
+ 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 @@ xprt_request_init(struct rpc_task *task,
+ 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);
+-}
+-
+-/*
+- * Set default timeout parameters
+- */
+-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);
++ rpc_wake_up_next(&xprt->backlog);
++ spin_unlock(&xprt->reserve_lock);
+ }
+
+-/*
+- * Set constant timeout
++/**
++ * 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
++ *
+ */
+-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 @@ xprt_setup(int proto, struct sockaddr_in
+ 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
+- */
+-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.
++/**
++ * xprt_create_proto - create an RPC client transport
++ * @proto: requested transport protocol
++ * @sap: remote peer's address
++ * @to: timeout parameters for new transport
++ *
+ */
+-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 @@ xprt_create_proto(int proto, struct sock
+ 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
+- */
+-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.
++/**
++ * xprt_destroy - destroy an RPC transport, killing off all requests.
++ * @xprt: transport to destroy
++ *
+ */
+-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
+--- /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 at redhat.com>
++ * TCP send fixes (C) 1998 Red Hat Software <alan at redhat.com>
++ * TCP NFS related read + write fixes
++ * (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied at 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 at fys.uio.no>
++ *
++ * IP socket transport implementation, (C) 2005 Chuck Lever <cel at 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
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -1192,46 +1192,6 @@ int xfrm_bundle_ok(struct xfrm_dst *firs
+
+ 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 @@ int xfrm_policy_register_afinfo(struct x
+ 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 @@ int xfrm_policy_unregister_afinfo(struct
+ 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
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -1026,6 +1026,12 @@ void xfrm_state_delete_tunnel(struct xfr
+ }
+ 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
+--- a/scripts/kconfig/Makefile
++++ b/scripts/kconfig/Makefile
+@@ -116,6 +116,15 @@ endif
+ 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
+--- 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
+--- a/scripts/kconfig/mconf.c
++++ b/scripts/kconfig/mconf.c
+@@ -219,6 +219,7 @@ save_config_help[] = N_(
+ 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 @@ again:
+ 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
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -359,6 +359,13 @@ static int do_vio_entry(const char *file
+ 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 @@ void handle_moddevtable(struct module *m
+ 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
+--- a/security/dummy.c
++++ b/security/dummy.c
+@@ -377,7 +377,7 @@ static int dummy_inode_removexattr (stru
+ 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 @@ static int dummy_socket_getpeersec(struc
+ 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 @@ static int dummy_setprocattr(struct task
+ 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 @@ void security_fixup_ops (struct security
+ 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
+--- 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 at 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 *key_alloc(struct key_type *t
+ 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 @@ struct key *key_alloc(struct key_type *t
+ 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,34 @@ struct key *key_alloc(struct key_type *t
+ 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);
++ if (!not_in_quota) {
++ spin_lock(&user->lock);
++ user->qnkeys--;
++ user->qnbytes -= quotalen;
++ spin_unlock(&user->lock);
++ }
++ key_user_put(user);
++ key = ERR_PTR(ret);
++ goto error;
++
++no_memory_3:
+ kmem_cache_free(key_jar, key);
+- no_memory_2:
++no_memory_2:
+ if (!not_in_quota) {
+ spin_lock(&user->lock);
+ user->qnkeys--;
+@@ -332,11 +353,11 @@ struct key *key_alloc(struct key_type *t
+ spin_unlock(&user->lock);
+ }
+ key_user_put(user);
+- no_memory_1:
++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 @@ static void key_cleanup(void *data)
+
+ 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 @@ static inline key_ref_t __key_update(key
+ 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 @@ static inline key_ref_t __key_update(key
+ 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 @@ key_ref_t key_create_or_update(key_ref_t
+
+ /* 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 @@ key_ref_t key_create_or_update(key_ref_t
+ 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 @@ int key_update(key_ref_t key_ref, const
+ 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
+--- a/security/keys/keyctl.c
++++ b/security/keys/keyctl.c
+@@ -624,8 +624,8 @@ long keyctl_keyring_search(key_serial_t
+
+ /* 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 @@ long keyctl_read_key(key_serial_t keyid,
+ 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 @@ long keyctl_chown_key(key_serial_t id, u
+ 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 @@ long keyctl_setperm_key(key_serial_t id,
+ 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
+--- 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 @@ struct key *keyring_alloc(const char *de
+ 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_ref_t keyring_search_aux(key_ref_t k
+ 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 @@ descend:
+ 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 @@ ascend:
+ 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_ref_t __keyring_search_one(key_ref_t
+ (!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 @@ struct key *find_keyring_by_name(const c
+ 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
+--- 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 @@ use_these_perms:
+
+ 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
+--- a/security/keys/process_keys.c
++++ b/security/keys/process_keys.c
+@@ -39,7 +39,7 @@ struct key root_user_keyring = {
+ .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 @@ struct key root_session_keyring = {
+ .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 @@ key_ref_t lookup_user_key(struct task_st
+ 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
+--- 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 @@ struct key_type key_type_user = {
+ .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 @@ static int user_instantiate(struct key *
+ 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 @@ static int user_duplicate(struct key *ke
+
+ } /* end user_duplicate() */
+
++EXPORT_SYMBOL_GPL(user_duplicate);
++
+ /*****************************************************************************/
+ /*
+ * dispose of the old data from an updated user defined key
+@@ -131,7 +121,7 @@ static void user_update_rcu_disposal(str
+ * 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 @@ static int user_update(struct key *key,
+
+ 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 @@ static void user_destroy(struct key *key
+
+ } /* 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 @@ static void user_describe(const struct k
+
+ } /* 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 @@ static long user_read(const struct key *
+ return ret;
+
+ } /* end user_read() */
++
++EXPORT_SYMBOL_GPL(user_read);
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -122,11 +122,10 @@ static int task_alloc_security(struct ta
+ {
+ 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 @@ static int inode_alloc_security(struct i
+ 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 @@ static int file_alloc_security(struct fi
+ 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 @@ static int superblock_alloc_security(str
+ {
+ 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 @@ static void superblock_free_security(str
+ }
+
+ #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 @@ static int selinux_bprm_alloc_security(s
+ {
+ 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 @@ static inline void flush_unauthorized_fi
+
+ 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 void selinux_inode_post_setxattr(
+
+ 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 @@ static int selinux_inode_removexattr (st
+ 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 @@ static int selinux_task_kill(struct task
+ 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 @@ out:
+ 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 @@ static int ipc_alloc_security(struct tas
+ 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 @@ static int msg_msg_alloc_security(struct
+ {
+ 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
+--- a/security/selinux/netif.c
++++ b/security/selinux/netif.c
+@@ -114,13 +114,12 @@ static struct sel_netif *sel_netif_looku
+ 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
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -105,7 +105,7 @@ static ssize_t sel_write_enforce(struct
+ 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 @@ static ssize_t sel_write_disable(struct
+ 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 @@ static ssize_t sel_write_load(struct fil
+ 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 @@ static ssize_t sel_write_context(struct
+ 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 @@ static ssize_t sel_write_checkreqprot(st
+ 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 @@ static ssize_t sel_write_access(struct f
+ 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 @@ static ssize_t sel_write_create(struct f
+ 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 @@ static ssize_t sel_write_relabel(struct
+ 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 @@ static ssize_t sel_write_user(struct fil
+ 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 @@ static ssize_t sel_write_member(struct f
+ 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 @@ static ssize_t sel_read_bool(struct file
+ if (!filep->f_op)
+ goto out;
+
+- if (count < 0 || count > PAGE_SIZE) {
++ if (count > PAGE_SIZE) {
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -800,7 +790,7 @@ static ssize_t sel_write_bool(struct fil
+ if (!filep->f_op)
+ goto out;
+
+- if (count < 0 || count >= PAGE_SIZE) {
++ if (count >= PAGE_SIZE) {
+ length = -ENOMEM;
+ goto out;
+ }
+@@ -858,7 +848,7 @@ static ssize_t sel_commit_bools_write(st
+ if (!filep->f_op)
+ goto out;
+
+- if (count < 0 || count >= PAGE_SIZE) {
++ if (count >= PAGE_SIZE) {
+ length = -ENOMEM;
+ goto out;
+ }
+@@ -924,7 +914,7 @@ static void sel_remove_bools(struct dent
+
+ 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 @@ static ssize_t sel_write_avc_cache_thres
+ 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
+--- a/security/selinux/ss/conditional.c
++++ b/security/selinux/ss/conditional.c
+@@ -220,10 +220,9 @@ int cond_read_bool(struct policydb *p, s
+ 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 @@ static int cond_insertf(struct avtab *a,
+ 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 @@ static int cond_read_node(struct policyd
+ 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 @@ int cond_read_list(struct policydb *p, v
+ 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
+--- a/security/selinux/ss/ebitmap.c
++++ b/security/selinux/ss/ebitmap.c
+@@ -39,12 +39,11 @@ int ebitmap_cpy(struct ebitmap *dst, str
+ 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 @@ int ebitmap_set_bit(struct ebitmap *e, u
+ 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 @@ int ebitmap_read(struct ebitmap *e, void
+ 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
+--- a/security/selinux/ss/hashtab.c
++++ b/security/selinux/ss/hashtab.c
+@@ -15,11 +15,10 @@ struct hashtab *hashtab_create(u32 (*has
+ 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 @@ int hashtab_insert(struct hashtab *h, vo
+ 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
+--- a/security/selinux/ss/policydb.c
++++ b/security/selinux/ss/policydb.c
+@@ -121,12 +121,11 @@ static int roles_init(struct policydb *p
+ 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 @@ static int perm_read(struct policydb *p,
+ __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 @@ static int common_read(struct policydb *
+ 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 @@ static int read_cons_helper(struct const
+
+ 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 @@ static int read_cons_helper(struct const
+ 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 @@ static int class_read(struct policydb *p
+ 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 @@ static int role_read(struct policydb *p,
+ __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 @@ static int type_read(struct policydb *p,
+ __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 @@ static int user_read(struct policydb *p,
+ __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 @@ static int sens_read(struct policydb *p,
+ __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 @@ static int cat_read(struct policydb *p,
+ __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 @@ int policydb_read(struct policydb *p, vo
+ 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 @@ int policydb_read(struct policydb *p, vo
+ 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 @@ int policydb_read(struct policydb *p, vo
+ 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 @@ int policydb_read(struct policydb *p, vo
+ 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 @@ int policydb_read(struct policydb *p, vo
+ 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 @@ int policydb_read(struct policydb *p, vo
+ 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
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -1531,12 +1531,11 @@ int security_get_user_sids(u32 fromsid,
+ }
+ 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 @@ int security_get_user_sids(u32 fromsid,
+ 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 @@ int security_get_bools(int *len, char **
+ 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
+--- 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
+--- a/sound/arm/pxa2xx-ac97.c
++++ b/sound/arm/pxa2xx-ac97.c
+@@ -13,7 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/device.h>
++#include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
+ #include <linux/delay.h>
+@@ -275,23 +275,23 @@ static int pxa2xx_ac97_do_resume(snd_car
+ 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
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -28,6 +28,8 @@
+ #include <linux/ctype.h>
+ #include <linux/pci.h>
+ #include <linux/pm.h>
++#include <linux/platform_device.h>
++
+ #include <sound/core.h>
+ #include <sound/control.h>
+ #include <sound/info.h>
+@@ -676,8 +678,8 @@ struct snd_generic_device {
+ #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 +820,10 @@ int snd_card_set_pm_callback(snd_card_t
+
+ #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 +833,10 @@ static int snd_generic_suspend(struct de
+ 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
+--- a/sound/core/memalloc.c
++++ b/sound/core/memalloc.c
+@@ -190,7 +190,7 @@ static void unmark_pages(struct page *pa
+ *
+ * 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 @@ static void *snd_malloc_dev_pages(struct
+ {
+ 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
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2949,8 +2949,7 @@ static struct page * snd_pcm_mmap_status
+ 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 @@ static struct page * snd_pcm_mmap_contro
+ 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 @@ static struct page *snd_pcm_mmap_data_no
+ 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
+--- a/sound/core/seq/instr/ainstr_gf1.c
++++ b/sound/core/seq/instr/ainstr_gf1.c
+@@ -51,7 +51,7 @@ static int snd_seq_gf1_copy_wave_from_st
+ 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 @@ static int snd_seq_gf1_put(void *private
+ 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
+--- a/sound/core/seq/instr/ainstr_iw.c
++++ b/sound/core/seq/instr/ainstr_iw.c
+@@ -129,7 +129,7 @@ static int snd_seq_iwffff_copy_wave_from
+ 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 @@ static int snd_seq_iwffff_put(void *priv
+ 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
+--- a/sound/core/seq/instr/ainstr_simple.c
++++ b/sound/core/seq/instr/ainstr_simple.c
+@@ -57,7 +57,8 @@ static int snd_seq_simple_put(void *priv
+ 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
+--- a/sound/core/sound.c
++++ b/sound/core/sound.c
+@@ -231,7 +231,7 @@ int snd_register_device(int type, snd_ca
+ 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
+--- 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
+--- 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
+--- a/sound/oss/awe_wave.c
++++ b/sound/oss/awe_wave.c
+@@ -6062,7 +6062,7 @@ static int awe_pnp_probe(struct pnp_dev
+ 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
+--- a/sound/oss/cs4232.c
++++ b/sound/oss/cs4232.c
+@@ -195,10 +195,12 @@ static int __init probe_cs4232(struct ad
+ 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
+--- a/sound/oss/dmasound/dmasound.h
++++ b/sound/oss/dmasound/dmasound.h
+@@ -116,7 +116,7 @@ typedef struct {
+ 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
+--- a/sound/oss/dmasound/dmasound_atari.c
++++ b/sound/oss/dmasound/dmasound_atari.c
+@@ -114,7 +114,7 @@ static ssize_t ata_ctx_u16le(const u_cha
+ /*** 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 @@ static TRANS transFalconExpanding = {
+ * 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
+--- a/sound/oss/dmasound/dmasound_awacs.c
++++ b/sound/oss/dmasound/dmasound_awacs.c
+@@ -271,7 +271,7 @@ int expand_read_bal; /* Balance factor f
+
+ /*** 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 @@ tas_init_frame_rates(unsigned int *prop,
+ /*
+ * 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
+--- a/sound/oss/dmasound/dmasound_paula.c
++++ b/sound/oss/dmasound/dmasound_paula.c
+@@ -69,7 +69,7 @@ static int write_sq_block_size_half, wri
+ /*** 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 @@ static inline void StopDMA(void)
+ 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
+--- a/sound/oss/dmasound/dmasound_q40.c
++++ b/sound/oss/dmasound/dmasound_q40.c
+@@ -36,7 +36,7 @@ static int expand_data; /* Data for expa
+ /*** 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 @@ static TRANS transQ40Compressing = {
+
+ /*** 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
+--- a/sound/oss/soundcard.c
++++ b/sound/oss/soundcard.c
+@@ -567,7 +567,7 @@ static int __init oss_init(void)
+ 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 @@ static int __init oss_init(void)
+ 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
+--- a/sound/oss/wavfront.c
++++ b/sound/oss/wavfront.c
+@@ -2434,7 +2434,7 @@ static int __init detect_wavefront (int
+ 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 @@ static int __init detect_wavefront (int
+ } 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 @@ static int __init detect_wavefront (int
+
+ if (wavefront_hw_reset ()) {
+ printk (KERN_WARNING LOGNAME "hardware reset failed\n");
++ release_region (io_base, 16);
+ return 0;
+ }
+
+@@ -2496,6 +2500,8 @@ static int __init detect_wavefront (int
+
+ 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 wavefront_init (int at
+ }
+
+ 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 @@ static int __init install_wavefront (voi
+ 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
+--- a/sound/oss/ymfpci.c
++++ b/sound/oss/ymfpci.c
+@@ -107,14 +107,15 @@ static LIST_HEAD(ymf_devs);
+ */
+
+ 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
+--- a/sound/parisc/harmony.c
++++ b/sound/parisc/harmony.c
+@@ -197,7 +197,7 @@ snd_harmony_interrupt(int irq, void *dev
+ 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 @@ snd_harmony_interrupt(int irq, void *dev
+ }
+
+ 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 @@ snd_harmony_playback_trigger(snd_pcm_sub
+ 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 @@ snd_harmony_capture_trigger(snd_pcm_subs
+ 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 @@ snd_harmony_playback_prepare(snd_pcm_sub
+
+ 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 @@ snd_harmony_capture_prepare(snd_pcm_subs
+
+ 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 @@ snd_harmony_volume_get(snd_kcontrol_t *k
+
+ 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 @@ snd_harmony_volume_put(snd_kcontrol_t *k
+ int old_gain = h->st.gain;
+ unsigned long flags;
+
++ spin_lock_irqsave(&h->mixer_lock, flags);
++
+ left = ucontrol->value.integer.value[0] & mask;
+- right = ucontrol->value.integer.value[1] & mask;
+- if (invert) {
++ if (invert)
+ left = mask - left;
+- right = mask - right;
++ 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 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);
+
+- h->st.gain &= ~( (mask << shift_right) | (mask << shift_left) );
+- h->st.gain |= ( (left << shift_left) | (right << shift_right) );
++ 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 (old_gain - h->st.gain);
++ return h->st.gain != old_gain;
+ }
+
+ #define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/ \
+@@ -767,10 +832,25 @@ snd_harmony_volume_put(snd_kcontrol_t *k
+ ((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 @@ snd_harmony_create(snd_card_t *card,
+ 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
+--- a/sound/parisc/harmony.h
++++ b/sound/parisc/harmony.h
+@@ -61,7 +61,7 @@ typedef struct snd_card_harmony {
+ #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 @@ typedef struct snd_card_harmony {
+ #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
+--- a/sound/pci/ac97/ac97_bus.c
++++ b/sound/pci/ac97/ac97_bus.c
+@@ -31,7 +31,8 @@ static int ac97_bus_suspend(struct devic
+ 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 @@ static int ac97_bus_resume(struct device
+ 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
+--- a/sound/pci/bt87x.c
++++ b/sound/pci/bt87x.c
+@@ -761,15 +761,18 @@ static int __devinit snd_bt87x_create(sn
+
+ #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/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
+--- a/sound/pci/emu10k1/emu10k1_main.c
++++ b/sound/pci/emu10k1/emu10k1_main.c
+@@ -579,6 +579,30 @@ static int __devinit snd_emu10k1_ecard_i
+ return 0;
+ }
+
++static int __devinit snd_emu10k1_cardbus_init(emu10k1_t * emu)
++{
++ unsigned long special_port;
++ unsigned int value;
++
++ /* Special initialisation routine
++ * before the rest of the IO-Ports become active.
++ */
++ special_port = emu->port + 0x38;
++ value = inl(special_port);
++ outl(0x00d00000, special_port);
++ value = inl(special_port);
++ outl(0x00d00001, special_port);
++ value = inl(special_port);
++ outl(0x00d0005f, special_port);
++ value = inl(special_port);
++ outl(0x00d0007f, special_port);
++ value = inl(special_port);
++ outl(0x0090007f, special_port);
++ value = inl(special_port);
++
++ return 0;
++}
++
+ /*
+ * Create the EMU10K1 instance
+ */
+@@ -624,6 +648,16 @@ static emu_chip_details_t emu_chip_detai
+ .ca0108_chip = 1,
+ .spk71 = 1,
+ .ac97_chip = 1} ,
++ /* Audigy 2 ZS Notebook Cardbus card.*/
++ /* Tested by James at superbug.co.uk 30th October 2005 */
++ /* Not working yet, but progressing. */
++ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
++ .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
++ .id = "Audigy2",
++ .emu10k2_chip = 1,
++ .ca0108_chip = 1,
++ .ca_cardbus_chip = 1,
++ .spk71 = 1} ,
+ {.vendor = 0x1102, .device = 0x0008,
+ .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
+ .id = "Audigy2",
+@@ -1011,6 +1045,11 @@ int __devinit snd_emu10k1_create(snd_car
+ snd_emu10k1_free(emu);
+ return err;
+ }
++ } else if (emu->card_capabilities->ca_cardbus_chip) {
++ if ((err = snd_emu10k1_cardbus_init(emu)) < 0) {
++ snd_emu10k1_free(emu);
++ return err;
++ }
+ } else {
+ /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
+ does not support this, it shouldn't do any harm */
+diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
+--- 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 @@ static snd_kcontrol_new_t snd_pmac_beep_
+ int __init snd_pmac_attach_beep(pmac_t *chip)
+ {
+ pmac_beep_t *beep;
+- int err;
+-
+- 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;
++ struct input_dev *input_dev;
++ void *dmabuf;
++ int err = -ENOMEM;
++
++ 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
+--- a/sound/sound_core.c
++++ b/sound/sound_core.c
+@@ -174,7 +174,7 @@ static int sound_insert_unit(struct soun
+
+ 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
+--- a/sound/usb/usbmidi.c
++++ b/sound/usb/usbmidi.c
+@@ -163,7 +163,7 @@ static const uint8_t snd_usbmidi_cin_len
+ /*
+ * 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)
Deleted: dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-1
===================================================================
--- dists/trunk/linux-2.6/debian/patches-debian/series/2.6.14-1 2005-11-03 11:39:35 UTC (rev 4717)
+++ dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-1 2005-11-03 17:51:59 UTC (rev 4720)
@@ -1,27 +0,0 @@
-+ amd64-int3-fix.patch
-#+ drivers-scsi-megaraid_splitup.patch
-+ fbdev-radeon-noaccel.patch
-+ fs-asfs-2.patch
-+ ia64-irq-affinity-upfix.patch
-#- m68k-42_dma.patch
-#- m68k-sonic.patch
-#+ m68k-arch.patch
-#+ m68k-drivers.patch
-#+ m68k-kernel.patch
-#+ m68k-include-m68k.patch
-+ modular-ide.patch
-+ modular-ide-pnp.patch
-+ powerpc-calibrate-tau.patch
-+ powerpc-g3-750cxe.patch
-#+ powerpc-g4-l2-flush-errata.patch
-+ powerpc-mkvmlinuz-support.patch
-+ powerpc-serial.patch
-+ qla2xxx-removed.patch
-#+ remove-references-to-removed-drivers.patch
-+ sparc64-hme-lockup.patch
-+ tty-locking-fixes9.patch
-+ version.patch
-+ powerpc-mv643xx-hotplug-support.patch
-+ powerpc-apus.patch
-+ s390-uaccess-const.patch
-+ powerpc-build-links.patch
Deleted: dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-2
===================================================================
--- dists/trunk/linux-2.6/debian/patches-debian/series/2.6.14-2 2005-11-03 11:39:35 UTC (rev 4717)
+++ dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-2 2005-11-03 17:51:59 UTC (rev 4720)
@@ -1,2 +0,0 @@
-+ alpha-compile-fix.patch
-+ powerpc64-audit_sysctl-build.patch
Added: dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-git-20051103
===================================================================
--- dists/trunk/linux-2.6/debian/patches-debian/series/2.6.14-git-20051103 2005-11-03 11:39:35 UTC (rev 4717)
+++ dists/trunk/linux-2.6-git/debian/patches-debian/series/2.6.14-git-20051103 2005-11-03 17:51:59 UTC (rev 4720)
@@ -0,0 +1,21 @@
++ patch-2.6.14-git5
++ amd64-int3-fix.patch
++ fbdev-radeon-noaccel.patch
++ fs-asfs-2.patch
++ ia64-irq-affinity-upfix.patch
++ modular-ide.patch
++ modular-ide-pnp.patch
+#+ powerpc-calibrate-tau.patch
+#+ powerpc-g3-750cxe.patch
++ powerpc-mkvmlinuz-support.patch
++ powerpc-serial.patch
++ qla2xxx-removed.patch
++ sparc64-hme-lockup.patch
++ tty-locking-fixes9.patch
++ version.patch
+#+ powerpc-mv643xx-hotplug-support.patch
+#+ powerpc-apus.patch
++ s390-uaccess-const.patch
++ powerpc-build-links.patch
+#+ alpha-compile-fix.patch
+#+ powerpc64-audit_sysctl-build.patch
More information about the Kernel-svn-changes
mailing list